Compare commits

..

209 Commits
0.5 ... 1.0

Author SHA1 Message Date
a039d51d5f prepared dwm-1.0 2006-08-24 10:25:05 +02:00
60b3dceccf yet another fix 2006-08-24 10:20:00 +02:00
c2ac851b90 small man page fix 2006-08-24 10:18:42 +02:00
c976bc6c2c found less intrusive way 2006-08-24 09:41:41 +02:00
2e834e941f changing tag indicator through underline 2006-08-24 09:25:10 +02:00
77e5f3167c black on light is really better, I notice this after all 2006-08-23 19:05:03 +02:00
7e597ae204 updated man page 2006-08-23 18:50:46 +02:00
c39df91ab9 applied tag drawing change to man page 2006-08-23 14:40:44 +02:00
af1158d105 implemented right tag drawing in the status bar and titlebars 2006-08-23 14:38:25 +02:00
b739721d9e removed a blank line 2006-08-23 13:04:43 +02:00
7711ab6707 eliminated sentinel warning 2006-08-23 12:28:39 +02:00
d370c32f69 small fix of man page 2006-08-23 12:10:55 +02:00
d6a6eca71d implemented class:inst:title matching 2006-08-23 12:08:37 +02:00
39ffc18635 applied zero_to_five patch 2006-08-23 12:03:25 +02:00
3e972ec84d tags appear in the left again 2006-08-23 11:33:50 +02:00
b5159dfd2f separated setup stuff into main.c:setup() - this makes main() more readable 2006-08-23 10:21:57 +02:00
07c2659806 updated man page 2006-08-22 19:56:29 +02:00
dc83b9e988 titlebars contain tags in the right now 2006-08-22 19:55:20 +02:00
8b4bc8270a fixed default key bindings (indexes of tags were screwed up) 2006-08-22 18:08:25 +02:00
0ff80653d3 rearranged getproto 2006-08-22 17:40:21 +02:00
352e1b4c81 removed winprop (merged into getproto) 2006-08-22 17:38:59 +02:00
aa13727067 separated several functions into view.c 2006-08-22 16:50:21 +02:00
595028614b removed DEFTAG 2006-08-22 16:42:29 +02:00
6a3ae5e26a removed badmalloc (thx for the pointer to Uriel) 2006-08-22 16:06:11 +02:00
8c334ee078 rxvt is quite slow under OpenBSD 2006-08-22 10:06:11 +02:00
f60fe2a4f9 font fix 2006-08-22 10:01:32 +02:00
b112257bf2 slight change of my config.h 2006-08-22 09:57:32 +02:00
eb88adcd8a fixed 2006-08-22 09:49:48 +02:00
950a1ab5af windows which have set transient_for hint inherit the transient_for window tags now 2006-08-21 17:35:37 +02:00
1b9fe55025 after switching to OpenBSD again, I switched back to a saner color scheme 2006-08-21 17:41:09 +02:00
2272df9d31 applied Sanders focus_* patches, removed the unnecessary clean-prefix from the new function names 2006-08-21 09:03:14 +02:00
08d85d6d66 small renamings of two static functions 2006-08-21 07:33:18 +02:00
b43989207a small changes to dwm.1, rearranged order within main event loop 2006-08-21 07:31:15 +02:00
2eebebf262 applied Sanders patch 2006-08-18 13:40:34 +02:00
8c1fffe106 made a new client position strategy similiar to that one proposed by Sander, but which takes top bar into account 2006-08-18 08:39:33 +02:00
5e9acbc952 fixed a bug reported by sander 2006-08-17 10:06:36 +02:00
a420ceab50 applied the shorter xprop command 2006-08-17 09:44:17 +02:00
0e1c649dca centering apps only if transient_for is not(!) set 2006-08-17 09:37:43 +02:00
67c2124fa9 fixed issue Sander reported 2006-08-17 09:35:44 +02:00
a635743c6d corrected order of cleanup code 2006-08-16 19:25:29 +02:00
b5c2412d84 condition was insufficient 2006-08-16 17:58:18 +02:00
ad2e77d635 fixed issue reported by sander 2006-08-16 17:56:04 +02:00
a20b10d01f added general centralization rule for new clients (works around various borken apps) 2006-08-16 15:57:36 +02:00
4cc0551948 removed leading ; 2006-08-16 15:31:24 +02:00
56130c3689 added sample command to config.default.h to highlight how to query class:instance info with a one-liner of shell commands 2006-08-16 15:00:14 +02:00
14f7380308 applied another config.mk patch made by sander 2006-08-16 12:36:32 +02:00
727449d1e7 we close stdin as well 2006-08-16 09:31:41 +02:00
80bf2aa559 simplified sort | uniq into sort -u (on my boxes all sort support -u) 2006-08-16 09:05:58 +02:00
b9cd0c4331 fixing small bug in config.mk 2006-08-15 16:54:54 +02:00
f77a87137c adding forgetten whitespace 2006-08-15 10:45:14 +02:00
65dfe8fdce added gmane archive to dwm.html 2006-08-15 10:44:15 +02:00
e3bb595d77 Added tag 0.9 for changeset fae61afa861755636c4a1070694209ace8efbb6c 2006-08-15 10:25:30 +02:00
a1682b8927 prepared dwm-0.9 2006-08-15 10:11:29 +02:00
24d91e3b8a extended cleanup 2006-08-15 09:37:12 +02:00
ce04a66528 applied Sanders changes to config.arg.h 2006-08-15 08:38:19 +02:00
df74b26e5d applied jk_to_tab patch 2006-08-15 08:25:11 +02:00
b6ad663f87 changed main event loop 2006-08-15 07:31:42 +02:00
ee31e38dc7 removed NUMLOCKMASK, added dynamically calculated numlockmask instead 2006-08-14 19:18:02 +02:00
442334641e added Sander to LICENSE (since he has contributed/revised big portions) 2006-08-14 18:47:13 +02:00
dfa5ea6360 applied viewsel.patch 2006-08-14 18:46:07 +02:00
3e06edeb5d applied sanders man page patch, removed button2 from bar click 2006-08-14 18:14:08 +02:00
78b050c13c applied sanders tag()/toggletag() fixes 2006-08-14 17:50:48 +02:00
4ad20ffc2c fixed 2006-08-14 17:48:54 +02:00
57e6e3bb80 added missing arrange 2006-08-14 17:14:22 +02:00
19da197f58 changed replacetag into toggletag 2006-08-14 16:59:18 +02:00
666fae97e6 added some flicker prevention 2006-08-14 16:37:55 +02:00
823fb1118a remove unnecessary XSync 2006-08-14 16:26:06 +02:00
db1d62e184 changed order of selecting input at root window 2006-08-14 16:21:16 +02:00
d26ffc7fa3 removed finished message 2006-08-14 16:11:54 +02:00
0f3acce042 added mappingnotify event for kb refreshes 2006-08-14 16:08:52 +02:00
9eef9f7b02 removed unneecessary crap 2006-08-14 15:43:04 +02:00
aff4c787f4 applied the saner patch (removed the pathetic one) 2006-08-14 15:33:23 +02:00
fe3dfbbe90 pplied Sanders appendtag patch 2006-08-14 15:31:58 +02:00
2ffdc1936c some other small fixes 2006-08-14 15:11:02 +02:00
0fe52c63ea removed ungrabkeys again (because of sander's mail) 2006-08-14 11:38:43 +02:00
28a52197c4 fixed string cutting 2006-08-14 10:58:03 +02:00
2c0d1cc87b fixed a core dump 2006-08-14 10:49:22 +02:00
375a251d16 implemented ungrabkeys() which is called in cleanup() 2006-08-14 10:24:38 +02:00
d4b7a9a373 implemented restack behavior (floats are on top in tiled mode) 2006-08-14 10:18:24 +02:00
4d67199a4b fixed string cutting in draw.c 2006-08-14 08:52:15 +02:00
95766d6241 applied Sanders LD and resize patches 2006-08-14 08:43:19 +02:00
4cb78a170c removed viewnext/viewprev 2006-08-14 08:38:26 +02:00
2c66b422e7 supplying NULL args in select 2006-08-14 07:40:20 +02:00
e571de83e9 reducing ConnectionNumber calls to a bare minimum 2006-08-14 07:23:46 +02:00
4bb89e2cb1 updated man page, added CAVEATS section 2006-08-13 18:04:42 +02:00
349cadacf6 made shortcuts like proposed by Sander, renamed viewextend to toggleview (more clear) 2006-08-13 17:58:06 +02:00
292ccc4c43 implemented viewextend and added M-S-C-n shortcuts for extending the current view... updated man page (works great!) nice feature 2006-08-11 19:26:12 +02:00
d7413ffd2d implement multi-tag selection through button3 click on the specific tag 2006-08-11 18:37:41 +02:00
50729a2e73 after some days of experimenting with grey background, I finally give up and switch to white on black ;) 2006-08-11 18:11:39 +02:00
a3e3f0b9ed applied Sanders fixes to dwm.1 2006-08-11 17:12:48 +02:00
45aea23355 fixed dwm.1, added Mod1-Shift-c (was missing for an odd reason) 2006-08-11 12:32:34 +02:00
975b459c17 simplified drawtext 2006-08-11 11:52:55 +02:00
2b35faee06 updated dwm(1) 2006-08-11 10:54:29 +02:00
84818bdbb5 upgraded version info 2006-08-11 10:28:51 +02:00
895902b57a applied Sander's patch as well 2006-08-11 10:05:53 +02:00
7d4184dc5c realized that client focussing through the bar is pretty useless, better is sloppy view focussing for B1/B3 as well instead 2006-08-11 10:00:47 +02:00
8278f0a6be implemented focusprev on button1 press in the bar, and focusnext on button3 press in the bar 2006-08-11 09:16:40 +02:00
d3969634ac simplified unmanage 2006-08-11 08:47:55 +02:00
735ca9ccd6 removed the if(clients) check from popping code 2006-08-11 08:34:42 +02:00
4ee661d908 added dwm favicon 2006-08-10 18:44:19 +02:00
9fce8215b7 applied Sanders zoom_update patch 2006-08-10 17:48:50 +02:00
6521c2dd41 respecting inc hints in floating mode on togglemax 2006-08-10 17:33:11 +02:00
9ee9ce7e14 reverting last patch, that sucks, I don't care about retarded apps like gvim 2006-08-10 16:37:13 +02:00
9d39da6452 togglemax repects inc-hints (this way gvim can be toggle'maxed as well) 2006-08-10 16:35:36 +02:00
0228dcd58f applied grammar correction by ILF 2006-08-10 15:35:02 +02:00
3d35ea99bb Added tag 0.8 for changeset cd15de32e173f8ce97bfe1c9b6607937b59056b4 2006-08-10 15:19:31 +02:00
0680c76a6f prepared 0.8 2006-08-10 15:19:25 +02:00
c3e5f5cc9a updated html 2006-08-10 13:30:39 +02:00
1c620d27d8 fixed the issue reported by sander (gaps at left columns button due to round-offs) 2006-08-10 12:33:44 +02:00
fde45ebed8 applied sumik's multihead patch 2006-08-10 11:26:32 +02:00
4bd0d33f57 applied sander's patch 2006-08-10 11:19:25 +02:00
00255728aa readded border color, this sucks least 2006-08-10 11:12:15 +02:00
4b0328f209 drawing border with fg color 2006-08-10 11:07:27 +02:00
30561a0161 removed unnecessary border color 2006-08-10 10:27:08 +02:00
a4c4998c8b swapping my default colors (bg with fg) 2006-08-10 10:22:15 +02:00
8e053b6476 made terminals darker, that is better indeed 2006-08-10 10:20:26 +02:00
b79b5facb1 disallow zoom on maximized clients 2006-08-10 10:16:12 +02:00
c53f0fca91 added zoom on Mod1-Button1 on managed clients only (there is no moving possible) 2006-08-09 18:37:33 +02:00
c225e1afc2 removed NET_ACTIVE_WINDOW handling 2006-08-08 18:12:18 +02:00
92e55c7c53 implemented NET_ACTIVE_WINDOW support 2006-08-08 17:08:45 +02:00
c86f131681 fixed typo 2006-08-08 12:58:05 +02:00
e943234d09 it always takes a while until one sticks to a colorscheme, but this one feels well 2006-08-08 12:50:11 +02:00
9fc24e371b default colors are best 2006-08-08 12:47:45 +02:00
cac467d52c without borders it looks cleaner 2006-08-08 11:47:29 +02:00
04f17d2669 red is easier to my eyes with ffffaa bg 2006-08-08 11:18:05 +02:00
dff15a02f7 using a better colorscheme (ffffaa is the best background for black) 2006-08-08 11:06:56 +02:00
42277b1110 applied Sanders tiny patches 2006-08-08 09:30:45 +02:00
095f9e143e removed some " 2006-08-07 17:38:14 +02:00
9fbb2ebb90 I really only need 3 tags 2006-08-07 14:12:28 +02:00
dbcf87ce76 added a trailing '.' to shortcut descriptions in dwm(1) 2006-08-07 14:10:22 +02:00
4250c26e9b changed signature of drawtext 2006-08-07 13:54:59 +02:00
e48de30516 applied grabbing-- and shell_minimal 2006-08-07 13:40:31 +02:00
1f0060caa3 updated screenshot section 2006-08-07 12:26:28 +02:00
c732cc90ab changed font size, I'm not blind... 2006-08-07 12:21:17 +02:00
4e2c5b5f25 small fix of a comment 2006-08-07 12:12:56 +02:00
d9386a0c07 typo fix 2006-08-07 11:58:46 +02:00
66e16c92d3 applied Sanders man page/Makefile patch 2006-08-07 11:57:05 +02:00
6a8e176df1 settle with grey 2006-08-07 11:10:19 +02:00
632c7f3410 next version is 0.8 2006-08-07 10:32:36 +02:00
045f1840e0 made my colors tasting better with the background 2006-08-07 10:28:21 +02:00
45d16d090b status box should have a border in my eyes 2006-08-07 09:47:13 +02:00
525c5ff4d8 next attempt for w on black switch 2006-08-07 09:41:43 +02:00
5952157c3b Added tag 0.7 for changeset 3fb41412e2492f66476d92ce8f007a8b48fb1d2a 2006-08-07 08:55:39 +02:00
f777d21899 prepared dwm.html 2006-08-07 08:51:43 +02:00
82064af2d7 added stripping to dwm target in Makefile 2006-08-07 08:46:11 +02:00
d54444cfd7 changed getproto, maybe that might fix the killclient issue reported on the list 2006-08-07 08:19:58 +02:00
525ef3c178 applied endless loop prevention on zoom() 2006-08-07 08:05:04 +02:00
5ef6ef1bac updated man page 2006-08-07 07:36:36 +02:00
f4208e7cac small fix of the last commit 2006-08-05 14:57:26 +02:00
ecc95c903b using -Os again, zoom is ignored in floating mode or on floating clients 2006-08-05 14:56:32 +02:00
a207949b65 mouse grab needs also to grab for combinations of numlock/lockmask 2006-08-05 14:02:25 +02:00
86d12249dd slight fix 2006-08-05 13:10:09 +02:00
b098c94ed4 small performance tweak ;) 2006-08-04 18:34:40 +02:00
6a39a496d0 fixed xterm font change (all other related apps should work fine with this fix as well) 2006-08-04 18:25:40 +02:00
3d73084b5e fixed view-change bug reported on the list 2006-08-04 18:17:02 +02:00
12b1d439e4 no need for -g anymore, regexp matching works now 2006-08-04 17:04:50 +02:00
1076161bf3 fixed dmenu link (thx to deifl) 2006-08-04 15:47:50 +02:00
e21d93b7bd switched to regexp matching for Rules 2006-08-04 14:40:32 +02:00
f504aea132 fixed a bug in dmenu call 2006-08-04 13:42:40 +02:00
9955ddc978 using execl now, argv changed, using cmd and const char defs directly in the KEYS struct 2006-08-04 12:00:55 +02:00
0dfe729f90 added dmenu to dwm.html 2006-08-04 10:36:22 +02:00
8f698bd4cc small stylistic fix 2006-08-04 10:27:16 +02:00
99b126d0af removed CONFIG 2006-08-03 17:08:43 +02:00
a2d56f6dce make config.h not a time dependence 2006-08-03 15:36:13 +02:00
db876f9fb0 removed rm config.h from clean 2006-08-03 15:29:28 +02:00
05a618b06e added gmake compliance 2006-08-03 15:21:08 +02:00
72608f0d5a s/tag2/two/g 2006-08-03 15:09:52 +02:00
bba044de4f applied Jukka's diff 2006-08-03 15:05:34 +02:00
4d55eee754 applied Sanders Makefile patch 2006-08-03 13:50:37 +02:00
d41b232b52 stylistic chnage 2006-08-03 12:21:00 +02:00
b35575574b removed TLast tag enum, now tags is simple defined as char *[] array, the rest is calculated correctly, rules take an int array for the tags 2006-08-03 12:12:26 +02:00
666b4563a0 hotfix of settags 2006-08-03 11:38:26 +02:00
7315bb08ad using SRC instead of *.c 2006-08-03 11:27:29 +02:00
f80688f1c7 changed the files included in make dist 2006-08-03 10:59:20 +02:00
dc5c070c44 applied Sanders doc changes, added a PHONY line and changed the output of config.h creation somewhat 2006-08-03 10:58:29 +02:00
8cc7f3bace changed Client->tags and Rule->tags to be Bool (I'll also try to remove the TLast enum) 2006-08-03 10:55:07 +02:00
5d3fd3707b implemented the idea presented by Sander for dwm target 2006-08-02 17:49:21 +02:00
1bf0c4a8e7 changing MASTERW value from 52 to 60 (in both, default and arg), I feel this is better now 2006-08-02 17:19:22 +02:00
863656d2bc fixed a type in README, and patched config.mk 2006-08-02 17:12:00 +02:00
f1a34ae1e4 updated dwm.html 2006-08-02 16:54:58 +02:00
3000cad507 Added tag 0.6 for changeset c11f86db4550cac5d0a648a3fe4d6d3b9a4fcf7e 2006-08-02 16:52:21 +02:00
0f8249f262 removed config.h (stupid hg) 2006-08-02 16:52:02 +02:00
b515765216 removed the CONFIG variable from config.mk, renamed config.h into config.default.h, after first clone/extract one needs to copy config.default.h to config.h, that is easier than always heavy typing make CONFIG=blafasel 2006-08-02 16:46:59 +02:00
85e6d59956 added Acroread.* and MPlayer.* to config.arg.h rules 2006-08-02 16:38:21 +02:00
95e8d12b71 made fullscreen apps working fine in floating mode (there is no sane way to make them work in tiled mode, thus I switch to floating mode if I run such kind of app), also fixed the xterm issue reported by Sander 2006-08-02 16:32:05 +02:00
a55f0e12fe new stuff 2006-08-02 13:05:04 +02:00
0cf3ba0eab dwm is now exit, if stdin is closed due broken pipe 2006-08-02 12:33:24 +02:00
1d85225952 implemented focus on enterwindow on titlebars 2006-08-02 11:28:27 +02:00
3af6434085 applied Sanders patches (numlock2) 2006-08-02 11:13:32 +02:00
57871415c1 reverting to old resize policy 2006-08-02 10:48:58 +02:00
52021851d1 new resize stuff (using XConfigureWindow instead of XSendEvent) 2006-08-02 10:43:21 +02:00
080a38d62d renamed WM_PROTOCOL_DELWIN into PROTODELWIN 2006-08-01 16:44:23 +02:00
ab7a11c0c7 renamed ARRANGE into DEFMODE 2006-08-01 16:39:20 +02:00
d8675f6f30 small fixes to dwm.html 2006-08-01 16:35:54 +02:00
eff4478c2d simplified README 2006-08-01 16:29:25 +02:00
81683351f0 removed 1 missing LOC 2006-08-01 16:20:29 +02:00
b38905b004 removed 5LOC 2006-08-01 16:20:03 +02:00
d9a6a3b5d2 removed artefacts of single-linked list (thanx to Jukka, I must have been mad) 2006-08-01 16:14:17 +02:00
7c2e3bb67d cleaned config.*h to prevent some confusion 2006-08-01 15:29:37 +02:00
b01a51a844 saved 2LOC 2006-08-01 15:16:29 +02:00
77f8c075c4 uppercasing all define'd values (uppercase-prefixed should only be enum field qualifiers) 2006-08-01 14:46:01 +02:00
33b4821cd6 fixed config.h files 2006-08-01 14:03:29 +02:00
a73a882806 centralized/externalized configuration to config.h 2006-08-01 13:59:13 +02:00
57416beefe applied Cedric's NumLock patch 2006-08-01 12:41:38 +02:00
1b63f832c5 applied Jukkas prev/next patch with XK_{h,l} 2006-08-01 12:39:14 +02:00
7b5638f61d applied Sanders patches 2006-08-01 12:32:33 +02:00
937cabfa0a committed a patch which fixes the hints of Jukka 2006-08-01 11:49:19 +02:00
deba5069e5 updated html 2006-07-21 21:15:39 +02:00
956113b295 Added tag 0.5 for changeset 22213b9a2114167ee8ba019a012e27da0422a61a 2006-07-21 21:15:11 +02:00
18 changed files with 1073 additions and 811 deletions

View File

@ -2,3 +2,8 @@ d31b5ad96b0ba7b5b0a30928fcf000428339a577 0.1
0a6472e2203994bc5738d40a340d26f7ec9d6062 0.2
7e66082e5092fb0bccd18a3695a0bec52c80fdb2 0.3
eb3165734f00fe7f7da8aeebaed00e60a57caac9 0.4
22213b9a2114167ee8ba019a012e27da0422a61a 0.5
c11f86db4550cac5d0a648a3fe4d6d3b9a4fcf7e 0.6
3fb41412e2492f66476d92ce8f007a8b48fb1d2a 0.7
cd15de32e173f8ce97bfe1c9b6607937b59056b4 0.8
fae61afa861755636c4a1070694209ace8efbb6c 0.9

View File

@ -1,6 +1,7 @@
MIT/X Consortium License
(C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
(C)opyright MMVI Sander van Dijk <a dot h dot vandijk at gmail dot com>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View File

@ -3,59 +3,60 @@
include config.mk
SRC = client.c draw.c event.c main.c tag.c util.c
SRC = client.c draw.c event.c main.c tag.c util.c view.c
OBJ = ${SRC:.c=.o}
MAN1 = dwm.1
BIN = dwm
all: options dwm
@echo finished
options:
@echo dwm build options:
@echo "LIBS = ${LIBS}"
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
@echo "LD = ${LD}"
.c.o:
@echo CC $<
@${CC} -c ${CFLAGS} $<
${OBJ}: dwm.h
${OBJ}: dwm.h config.h config.mk
config.h:
@echo creating $@ from config.default.h
@cp config.default.h $@
dwm: ${OBJ}
@echo LD $@
@${CC} -o $@ ${OBJ} ${LDFLAGS}
@${LD} -o $@ ${OBJ} ${LDFLAGS}
@strip $@
clean:
rm -f dwm *.o core dwm-${VERSION}.tar.gz
@echo cleaning
@rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
dist: clean
mkdir -p dwm-${VERSION}
cp -R Makefile README LICENSE config.mk *.h *.c ${MAN1} dwm-${VERSION}
tar -cf dwm-${VERSION}.tar dwm-${VERSION}
gzip dwm-${VERSION}.tar
rm -rf dwm-${VERSION}
@echo creating dist tarball
@mkdir -p dwm-${VERSION}
@cp -R LICENSE Makefile README config.*.h config.mk \
dwm.1 dwm.h ${SRC} dwm-${VERSION}
@tar -cf dwm-${VERSION}.tar dwm-${VERSION}
@gzip dwm-${VERSION}.tar
@rm -rf dwm-${VERSION}
install: all
@echo installing executable file to ${DESTDIR}${PREFIX}/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin
@cp -f ${BIN} ${DESTDIR}${PREFIX}/bin
@for i in ${BIN}; do \
chmod 755 ${DESTDIR}${PREFIX}/bin/`basename $$i`; \
done
@echo installed executable files to ${DESTDIR}${PREFIX}/bin
@cp -f dwm ${DESTDIR}${PREFIX}/bin
@chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
@echo installing manual page to ${DESTDIR}${MANPREFIX}/man1
@mkdir -p ${DESTDIR}${MANPREFIX}/man1
@cp -f ${MAN1} ${DESTDIR}${MANPREFIX}/man1
@for i in ${MAN1}; do \
chmod 444 ${DESTDIR}${MANPREFIX}/man1/`basename $$i`; \
done
@echo installed manual pages to ${DESTDIR}${MANPREFIX}/man1
@sed 's/VERSION/${VERSION}/g' < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1
uninstall:
for i in ${BIN}; do \
rm -f ${DESTDIR}${PREFIX}/bin/`basename $$i`; \
done
for i in ${MAN1}; do \
rm -f ${DESTDIR}${MANPREFIX}/man1/`basename $$i`; \
done
@echo removing executable file from ${DESTDIR}${PREFIX}/bin
@rm -f ${DESTDIR}${PREFIX}/bin/dwm
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
@rm -f ${DESTDIR}${MANPREFIX}/man1/dwm.1
.PHONY: all options clean dist install uninstall

22
README
View File

@ -1,6 +1,6 @@
dwm - dynamic window manager
----------------------------
dwm is an extremly fast, small, and dynamic X11 window manager.
dwm is an extremely fast, small, and dynamic window manager for X.
Requirements
@ -10,8 +10,8 @@ In order to build dwm you need the Xlib header files.
Installation
------------
Edit config.mk to match your local setup. dwm is installed into
the /usr/local namespace by default.
Edit config.mk to match your local setup (dwm is installed into
the /usr/local namespace by default).
Afterwards enter the following command to build and install dwm (if
necessary as root):
@ -30,21 +30,19 @@ the DISPLAY environment variable is set correctly, e.g.:
DISPLAY=foo.bar:1 exec dwm
This will start dwm on display :1 of the host foo.bar.
(This will start dwm on display :1 of the host foo.bar.)
Displaying status info
----------------------
In order to display status info in the bar, you can do following
in .xinitrc:
In order to display status info in the bar, you can do something
like this in your .xinitrc:
while true
do
echo `date` `uptime | sed 's/.*://; s/,//g'`
sleep 2
sleep 1
done | dwm
Configuration
-------------
The configuration of dwm is done by customizing source code,
grep for CUSTOMIZE keyword.
The configuration of dwm is done by creating a custom config.h
and (re)compiling the source code.

282
client.c
View File

@ -3,7 +3,6 @@
* See LICENSE file for license details.
*/
#include "dwm.h"
#include <stdlib.h>
#include <string.h>
#include <X11/Xatom.h>
@ -11,27 +10,45 @@
/* static functions */
static void
grabbutton(Client *c, unsigned int button, unsigned int modifier)
{
XGrabButton(dpy, button, modifier, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, button, modifier | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, button, modifier | numlockmask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, button, modifier | numlockmask | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
}
static void
resizetitle(Client *c)
{
int i;
c->tw = 0;
for(i = 0; i < TLast; i++)
if(c->tags[i])
c->tw += textw(c->tags[i]);
c->tw += textw(c->name);
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(c->tags[tsel])
XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th);
if(isvisible(c))
XMoveResizeWindow(dpy, c->twin, c->tx, c->ty, c->tw, c->th);
else
XMoveResizeWindow(dpy, c->title, c->tx + 2 * sw, c->ty, c->tw, c->th);
XMoveResizeWindow(dpy, c->twin, c->tx + 2 * sw, c->ty, c->tw, c->th);
}
static void
ungrabbutton(Client *c, unsigned int button, unsigned int modifier)
{
XUngrabButton(dpy, button, modifier, c->win);
XUngrabButton(dpy, button, modifier | LockMask, c->win);
XUngrabButton(dpy, button, modifier | numlockmask, c->win);
XUngrabButton(dpy, button, modifier | numlockmask | LockMask, c->win);
}
static int
xerrordummy(Display *dsply, XErrorEvent *ee)
{
@ -44,62 +61,28 @@ void
ban(Client *c)
{
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty);
XMoveWindow(dpy, c->twin, c->tx + 2 * sw, c->ty);
}
void
focus(Client *c)
{
Client *old = sel;
XEvent ev;
sel = c;
if(old && old != c)
if(!issel)
return;
if(!sel)
sel = c;
else if(sel != c) {
if(sel->ismax)
togglemax(NULL);
sel = c;
grabbutton(old, AnyButton, 0);
drawtitle(old);
}
ungrabbutton(c, AnyButton, 0);
drawtitle(c);
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
XSync(dpy, False);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}
void
focusnext(Arg *arg)
{
Client *c;
if(!sel)
return;
if(sel->ismax)
togglemax(NULL);
if(!(c = getnext(sel->next, tsel)))
c = getnext(clients, tsel);
if(c) {
higher(c);
focus(c);
}
}
void
focusprev(Arg *arg)
{
Client *c;
if(!sel)
return;
if(sel->ismax)
togglemax(NULL);
if(!(c = getprev(sel->prev))) {
for(c = clients; c && c->next; c = c->next);
c = getprev(c);
}
if(c) {
higher(c);
focus(c);
}
}
Client *
@ -119,7 +102,7 @@ getctitle(Window w)
Client *c;
for(c = clients; c; c = c->next)
if(c->title == w)
if(c->twin == w)
return c;
return NULL;
}
@ -179,39 +162,27 @@ gravitate(Client *c, Bool invert)
c->y += dy;
}
void
higher(Client *c)
{
XRaiseWindow(dpy, c->win);
XRaiseWindow(dpy, c->title);
}
void
killclient(Arg *arg)
{
if(!sel)
return;
if(sel->proto & WM_PROTOCOL_DELWIN)
if(sel->proto & PROTODELWIN)
sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]);
else
XKillClient(dpy, sel->win);
}
void
lower(Client *c)
{
XLowerWindow(dpy, c->title);
XLowerWindow(dpy, c->win);
}
void
manage(Window w, XWindowAttributes *wa)
{
Client *c;
unsigned int i;
Client *c, *tc;
Window trans;
XSetWindowAttributes twa;
c = emallocz(sizeof(Client));
c->tags = emallocz(ntags * sizeof(Bool));
c->win = w;
c->x = c->tx = wa->x;
c->y = c->ty = wa->y;
@ -219,77 +190,57 @@ manage(Window w, XWindowAttributes *wa)
c->h = wa->height;
c->th = bh;
if(c->y < bh)
c->y = c->ty = bh;
c->border = 1;
c->proto = getproto(c->win);
c->border = 0;
setsize(c);
if(c->x + c->w + 2 > sw)
c->x = sw - c->w - 2;
if(c->x < 0)
c->x = 0;
if(c->y + c->h + 2 > sh)
c->y = sh - c->h - 2;
if(c->h != sh && c->y < bh)
c->y = bh;
c->proto = getproto(c->win);
XSelectInput(dpy, c->win,
StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
XGetTransientForHint(dpy, c->win, &trans);
twa.override_redirect = 1;
twa.background_pixmap = ParentRelative;
twa.event_mask = ExposureMask;
twa.event_mask = ExposureMask | EnterWindowMask;
c->title = 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,
DefaultVisual(dpy, screen),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
settags(c);
if(clients)
clients->prev = c;
c->next = clients;
clients = c;
XGrabButton(dpy, Button1, MODKEY, c->win, False, ButtonPressMask,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY, c->win, False, ButtonPressMask,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY, c->win, False, ButtonPressMask,
GrabModeAsync, GrabModeSync, None, None);
grabbutton(c, Button1, MODKEY);
grabbutton(c, Button2, MODKEY);
grabbutton(c, Button3, MODKEY);
if((tc = getclient(trans))) /* inherit tags */
for(i = 0; i < ntags; i++)
c->tags[i] = tc->tags[i];
else
settags(c);
if(!c->isfloat)
c->isfloat = trans || (c->maxw && c->minw &&
(c->maxw == c->minw) && (c->maxh == c->minh));
c->isfloat = trans
|| (c->maxw && c->minw &&
c->maxw == c->minw && c->maxh == c->minh);
settitle(c);
if(isvisible(c))
sel = c;
arrange(NULL);
/* mapping the window now prevents flicker */
if(c->tags[tsel]) {
XMapRaised(dpy, c->win);
XMapRaised(dpy, c->title);
XMapWindow(dpy, c->win);
XMapWindow(dpy, c->twin);
if(isvisible(c))
focus(c);
}
else {
XMapRaised(dpy, c->win);
XMapRaised(dpy, c->title);
}
}
void
pop(Client *c)
{
Client **l;
for(l = &clients; *l && *l != c; l = &(*l)->next);
if(c->prev)
c->prev->next = c->next;
if(c->next)
c->next->prev = c->prev;
*l = c->next;
c->prev = NULL;
if(clients)
clients->prev = c;
c->next = clients;
clients = c;
arrange(NULL);
}
void
@ -297,7 +248,7 @@ resize(Client *c, Bool sizehints, Corner sticky)
{
int bottom = c->y + c->h;
int right = c->x + c->w;
XConfigureEvent e;
XWindowChanges wc;
if(sizehints) {
if(c->incw)
@ -313,30 +264,21 @@ resize(Client *c, Bool sizehints, Corner sticky)
if(c->maxh && c->h > c->maxh)
c->h = c->maxh;
}
if(c->x > sw) /* might happen on restart */
c->x = sw - c->w;
if(c->y > sh)
c->y = sh - c->h;
if(sticky == TopRight || sticky == BotRight)
c->x = right - c->w;
if(sticky == BotLeft || sticky == BotRight)
c->y = bottom - c->h;
resizetitle(c);
XSetWindowBorderWidth(dpy, c->win, 1);
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
e.type = ConfigureNotify;
e.event = c->win;
e.window = c->win;
e.x = c->x;
e.y = c->y;
e.width = c->w;
e.height = c->h;
e.border_width = c->border;
e.above = None;
e.override_redirect = False;
XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e);
wc.x = c->x;
wc.y = c->y;
wc.width = c->w;
wc.height = c->h;
if(c->w == sw && c->h == sh)
wc.border_width = 0;
else
wc.border_width = 1;
XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
XSync(dpy, False);
}
@ -383,7 +325,7 @@ void
settitle(Client *c)
{
char **list = NULL;
int n;
int i, n;
XTextProperty name;
name.nitems = 0;
@ -423,11 +365,11 @@ togglemax(Arg *arg)
oh = sel->h;
sel->x = sx;
sel->y = sy + bh;
sel->w = sw - 2 * sel->border;
sel->h = sh - 2 * sel->border - bh;
sel->w = sw - 2;
sel->h = sh - 2 - bh;
higher(sel);
resize(sel, False, TopLeft);
restack();
resize(sel, arrange == dofloat, TopLeft);
sel->x = ox;
sel->y = oy;
@ -442,63 +384,27 @@ togglemax(Arg *arg)
void
unmanage(Client *c)
{
Client **l;
XGrabServer(dpy);
XSetErrorHandler(xerrordummy);
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
XDestroyWindow(dpy, c->title);
XDestroyWindow(dpy, c->twin);
for(l = &clients; *l && *l != c; l = &(*l)->next);
if(c->prev)
c->prev->next = c->next;
if(c->next)
c->next->prev = c->prev;
*l = c->next;
if(sel == c) {
sel = getnext(c->next, tsel);
if(!sel)
sel = getprev(c->prev);
if(!sel)
sel = clients;
}
if(c == clients)
clients = c->next;
if(sel == c)
sel = getnext(clients);
free(c->tags);
free(c);
XSync(dpy, False);
XSetErrorHandler(xerror);
XUngrabServer(dpy);
arrange(NULL);
if(sel)
focus(sel);
}
void
zoom(Arg *arg)
{
Client *c, **l;
if(!sel)
return;
if(sel == getnext(clients, tsel) && sel->next) {
if((c = getnext(sel->next, tsel)))
sel = c;
}
/* pop */
for(l = &clients; *l && *l != sel; l = &(*l)->next);
if(sel->prev)
sel->prev->next = sel->next;
if(sel->next)
sel->next->prev = sel->prev;
*l = sel->next;
sel->prev = NULL;
if(clients)
clients->prev = sel;
sel->next = clients;
clients = sel;
arrange(NULL);
focus(sel);
}

53
config.arg.h Normal file
View File

@ -0,0 +1,53 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#define TAGS \
const char *tags[] = { "work", "net", "fnord", NULL };
#define DEFMODE dotile /* dofloat */
#define FONT "-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*"
#define BGCOLOR "#666699"
#define FGCOLOR "#eeeeee"
#define BORDERCOLOR "#9999CC"
#define MODKEY Mod1Mask
#define MASTERW 60 /* percent */
#define KEYS \
static Key key[] = { \
/* modifier key function arguments */ \
{ MODKEY|ShiftMask, XK_Return, spawn, \
{ .cmd = "exec uxterm -bg '#e0e0e0' -fg '#000000' -cr '#000000' +sb -fn '"FONT"'" } }, \
{ MODKEY, XK_p, spawn, \
{ .cmd = "exec `ls -lL /usr/bin /usr/X11R6/bin /usr/local/bin 2>/dev/null | " \
"awk 'NF>2 && $1 ~ /^[^d].*x/ {print $NF}' | sort -u | dmenu`" } }, \
{ MODKEY, XK_j, focusnext, { 0 } }, \
{ MODKEY, XK_k, focusprev, { 0 } }, \
{ MODKEY, XK_Return, zoom, { 0 } }, \
{ MODKEY, XK_m, togglemax, { 0 } }, \
{ MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \
{ MODKEY|ShiftMask, XK_2, tag, { .i = 1 } }, \
{ MODKEY|ShiftMask, XK_3, tag, { .i = 2 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_1, toggletag, { .i = 0 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_2, toggletag, { .i = 1 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_3, toggletag, { .i = 2 } }, \
{ MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \
{ MODKEY, XK_space, togglemode, { 0 } }, \
{ MODKEY, XK_1, view, { .i = 0 } }, \
{ MODKEY, XK_2, view, { .i = 1 } }, \
{ MODKEY, XK_3, view, { .i = 2 } }, \
{ MODKEY|ControlMask, XK_1, toggleview, { .i = 0 } }, \
{ MODKEY|ControlMask, XK_2, toggleview, { .i = 1 } }, \
{ MODKEY|ControlMask, XK_3, toggleview, { .i = 2 } }, \
{ MODKEY|ShiftMask, XK_q, quit, { 0 } }, \
};
#define RULES \
static Rule rule[] = { \
/* class:instance:title regex tags regex isfloat */ \
{ "Firefox.*", "net", False }, \
{ "Gimp.*", NULL, True}, \
{ "MPlayer.*", NULL, True}, \
{ "Acroread.*", NULL, True}, \
};

57
config.default.h Normal file
View File

@ -0,0 +1,57 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#define TAGS \
const char *tags[] = { "1", "2", "3", "4", "5", NULL };
#define DEFMODE dotile /* dofloat */
#define FONT "fixed"
#define BGCOLOR "#666699"
#define FGCOLOR "#eeeeee"
#define BORDERCOLOR "#9999CC"
#define MODKEY Mod1Mask
#define MASTERW 60 /* percent */
#define KEYS \
static Key key[] = { \
/* modifier key function arguments */ \
{ MODKEY|ShiftMask, XK_Return, spawn, { .cmd = "exec xterm" } }, \
{ MODKEY, XK_Tab, focusnext, { 0 } }, \
{ MODKEY|ShiftMask, XK_Tab, focusprev, { 0 } }, \
{ MODKEY, XK_Return, zoom, { 0 } }, \
{ MODKEY, XK_m, togglemax, { 0 } }, \
{ MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \
{ MODKEY|ShiftMask, XK_2, tag, { .i = 1 } }, \
{ MODKEY|ShiftMask, XK_3, tag, { .i = 2 } }, \
{ MODKEY|ShiftMask, XK_4, tag, { .i = 3 } }, \
{ MODKEY|ShiftMask, XK_5, tag, { .i = 4 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_1, toggletag, { .i = 0 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_2, toggletag, { .i = 1 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_3, toggletag, { .i = 2 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_4, toggletag, { .i = 3 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_5, toggletag, { .i = 4 } }, \
{ MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \
{ MODKEY, XK_space, togglemode, { 0 } }, \
{ MODKEY, XK_1, view, { .i = 0 } }, \
{ MODKEY, XK_2, view, { .i = 1 } }, \
{ MODKEY, XK_3, view, { .i = 2 } }, \
{ MODKEY, XK_4, view, { .i = 3 } }, \
{ MODKEY, XK_5, view, { .i = 4 } }, \
{ MODKEY|ControlMask, XK_1, toggleview, { .i = 0 } }, \
{ MODKEY|ControlMask, XK_2, toggleview, { .i = 1 } }, \
{ MODKEY|ControlMask, XK_3, toggleview, { .i = 2 } }, \
{ MODKEY|ControlMask, XK_4, toggleview, { .i = 3 } }, \
{ MODKEY|ControlMask, XK_5, toggleview, { .i = 4 } }, \
{ MODKEY|ShiftMask, XK_q, quit, { 0 } }, \
};
/* Query class:instance:title for regex matching info with following command:
* xprop | awk -F '"' '/^WM_CLASS/ { printf("%s:%s:",$4,$2) }; /^WM_NAME/{ printf("%s\n",$2) }' */
#define RULES \
static Rule rule[] = { \
/* class:instance:title regex tags regex isfloat */ \
{ "Firefox.*", "2", False }, \
{ "Gimp.*", NULL, True}, \
};

View File

@ -1,4 +1,7 @@
# Customize to fit your system
# dwm version
VERSION = 1.0
# Customize below to fit your system
# paths
PREFIX = /usr/local
@ -7,24 +10,16 @@ MANPREFIX = ${PREFIX}/share/man
X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib
VERSION = 0.5
# includes and libs
LIBS = -L${PREFIX}/lib -L/usr/lib -lc -L${X11LIB} -lX11
INCS = -I. -I/usr/include -I${X11INC}
LIBS = -L/usr/lib -lc -L${X11LIB} -lX11
# Linux/BSD
CFLAGS = -O3 -I. -I${PREFIX}/include -I/usr/include -I${X11INC} \
-DVERSION=\"${VERSION}\"
# flags
CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\"
LDFLAGS = ${LIBS}
#CFLAGS = -g -Wall -O2 -I. -I${PREFIX}/include -I/usr/include -I${X11INC} \
# -DVERSION=\"${VERSION}\"
#CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = -g ${LIBS}
# Solaris
#CFLAGS = -fast -xtarget=ultra ${INCLUDES} -DVERSION=\"${VERSION}\"
#LIBS += -lnsl -lsocket
AR = ar cr
# compiler and linker
CC = cc
RANLIB = ranlib
LD = ${CC}

118
draw.c
View File

@ -3,35 +3,14 @@
* See LICENSE file for license details.
*/
#include "dwm.h"
#include <stdio.h>
#include <string.h>
#include <X11/Xlocale.h>
/* static */
static void
drawborder(void)
{
XPoint points[5];
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
XSetForeground(dpy, dc.gc, dc.border);
points[0].x = dc.x;
points[0].y = dc.y;
points[1].x = dc.w - 1;
points[1].y = 0;
points[2].x = 0;
points[2].y = dc.h - 1;
points[3].x = -(dc.w - 1);
points[3].y = 0;
points[4].x = 0;
points[4].y = -(dc.h - 1);
XDrawLines(dpy, dc.drawable, dc.gc, points, 5, CoordModePrevious);
}
static unsigned int
textnw(char *text, unsigned int len)
textnw(const char *text, unsigned int len)
{
XRectangle r;
@ -43,25 +22,35 @@ textnw(char *text, unsigned int len)
}
static void
drawtext(const char *text, Bool invert, Bool border)
drawtext(const char *text, Bool invert, Bool highlight)
{
int x, y, w, h;
static char buf[256];
unsigned int len;
unsigned int len, olen;
XGCValues gcv;
XPoint points[5];
XRectangle r = { dc.x, dc.y, dc.w, dc.h };
XSetForeground(dpy, dc.gc, invert ? dc.fg : dc.bg);
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
w = 0;
if(border)
drawborder();
points[0].x = dc.x;
points[0].y = dc.y;
points[1].x = dc.w - 1;
points[1].y = 0;
points[2].x = 0;
points[2].y = dc.h - 1;
points[3].x = -(dc.w - 1);
points[3].y = 0;
points[4].x = 0;
points[4].y = -(dc.h - 1);
XSetForeground(dpy, dc.gc, dc.border);
XDrawLines(dpy, dc.drawable, dc.gc, points, 5, CoordModePrevious);
if(!text)
return;
len = strlen(text);
w = 0;
olen = len = strlen(text);
if(len >= sizeof(buf))
len = sizeof(buf) - 1;
memcpy(buf, text, len);
@ -74,21 +63,40 @@ drawtext(const char *text, Bool invert, Bool border)
/* shorten text if necessary */
while(len && (w = textnw(buf, len)) > dc.w - h)
buf[--len] = 0;
if(len < olen) {
if(len > 1)
buf[len - 1] = '.';
if(len > 2)
buf[len - 2] = '.';
if(len > 3)
buf[len - 3] = '.';
}
if(w > dc.w)
return; /* too long */
gcv.foreground = invert ? dc.bg : dc.fg;
gcv.background = invert ? dc.fg : dc.bg;
if(dc.font.set) {
XChangeGC(dpy, dc.gc, GCForeground | GCBackground, &gcv);
XmbDrawImageString(dpy, dc.drawable, dc.font.set, dc.gc,
x, y, buf, len);
XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
}
else {
gcv.font = dc.font.xfont->fid;
XChangeGC(dpy, dc.gc, GCForeground | GCBackground | GCFont, &gcv);
XDrawImageString(dpy, dc.drawable, dc.gc, x, y, buf, len);
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
}
if(highlight) {
points[0].x = dc.x + 1;
points[0].y = dc.y + 1;
points[1].x = dc.w - 3;
points[1].y = 0;
points[2].x = 0;
points[2].y = dc.h - 3;
points[3].x = -(dc.w - 3);
points[3].y = 0;
points[4].x = 0;
points[4].y = -(dc.h - 3);
XDrawLines(dpy, dc.drawable, dc.gc, points, 5, CoordModePrevious);
}
}
@ -99,7 +107,7 @@ drawall()
{
Client *c;
for(c = clients; c; c = getnext(c->next, tsel))
for(c = clients; c; c = getnext(c->next))
drawtitle(c);
drawstatus();
}
@ -115,21 +123,26 @@ drawstatus()
drawtext(NULL, !istile, False);
dc.w = 0;
for(i = 0; i < TLast; i++) {
for(i = 0; i < ntags; i++) {
dc.x += dc.w;
dc.w = textw(tags[i]);
if(istile)
drawtext(tags[i], (i == tsel), True);
drawtext(tags[i], seltag[i], sel && sel->tags[i]);
else
drawtext(tags[i], (i != tsel), True);
drawtext(tags[i], !seltag[i], sel && sel->tags[i]);
}
x = dc.x + dc.w;
dc.w = textw(stext);
dc.x = bx + bw - dc.w;
drawtext(stext, !istile, False);
if(sel && ((dc.w = dc.x - x) >= bh)) {
if(dc.x < x) {
dc.x = x;
drawtext(sel->name, istile, True);
dc.w = bw - x;
}
drawtext(stext, !istile, False);
if(sel && ((dc.w = dc.x - x) > bh)) {
dc.x = x;
drawtext(sel->name, istile, False);
}
XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0);
XSync(dpy, False);
@ -141,30 +154,19 @@ drawtitle(Client *c)
int i;
Bool istile = arrange == dotile;
if(c == sel) {
if(c == sel && issel) {
drawstatus();
XUnmapWindow(dpy, c->title);
XUnmapWindow(dpy, c->twin);
XSetWindowBorder(dpy, c->win, dc.fg);
return;
}
XSetWindowBorder(dpy, c->win, dc.bg);
XMapWindow(dpy, c->title);
XMapWindow(dpy, c->twin);
dc.x = dc.y = 0;
dc.w = 0;
for(i = 0; i < TLast; i++) {
if(c->tags[i]) {
dc.x += dc.w;
dc.w = textw(c->tags[i]);
drawtext(c->tags[i], !istile, True);
}
}
dc.x += dc.w;
dc.w = textw(c->name);
drawtext(c->name, !istile, True);
XCopyArea(dpy, dc.drawable, c->title, dc.gc, 0, 0, c->tw, c->th, 0, 0);
dc.w = c->tw;
drawtext(c->name, !istile, False);
XCopyArea(dpy, dc.drawable, c->twin, dc.gc, 0, 0, c->tw, c->th, 0, 0);
XSync(dpy, False);
}
@ -230,7 +232,7 @@ setfont(const char *fontstr)
}
unsigned int
textw(char *text)
textw(const char *text)
{
return textnw(text, strlen(text)) + dc.font.height;
}

174
dwm.1
View File

@ -1,4 +1,4 @@
.TH DWM 1 dwm-0.5
.TH DWM 1 dwm-VERSION
.SH NAME
dwm \- dynamic window manager
.SH SYNOPSIS
@ -6,109 +6,145 @@ dwm \- dynamic window manager
.RB [ \-v ]
.SH DESCRIPTION
.B dwm
is a dynamic window manager for X11. It manages windows in tiling and floating
modes. Either mode can be applied dynamically, depending on the application in
use and the task performed.
is a dynamic window manager for X. It manages windows in tiling and floating
modes. Either mode can be applied dynamically, optimizing the environment for
the application in use and the task performed.
.P
In tiling mode windows are managed in a master and stacking column. The master
column contains the window which needs most attention at a time, whereas the
stacking column contains all other windows in a stack. Dialog windows are
managed floating, however. In floating mode windows can be resized and moved
freely.
column contains the window which currently needs most attention, whereas the
stacking column contains all other windows. In floating mode windows can be
resized and moved freely. Dialog windows are always managed floating,
regardless of the mode selected.
.P
Windows are grouped by tags. All windows with a specific tag can be viewed at a
time. But each window may contain more than one tag, which makes it visible in
several views.
Windows are grouped by tags. Each window can be tagged with one or multiple
tags. Selecting a certain tag for viewing will display all windows with that
tag.
.P
.B dwm
consists of a small status bar which reads the text displayed from standard
input, if written. It draws 1-pixel borders around windows to indicate the
focus state. Unfocused windows contain a small bar in front of the window
displaying the tags and the window title.
contains a small status bar which displays all available tags, the title
of the focused window, and the text read from standard input. The tags of the
focused window are highlighted.
.P
.B 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.
.SH OPTIONS
.TP
.B \-v
prints version information to standard output, then exits.
.SH USAGE
.SS Status bar
.TP
.B Standard input
is read and displayed in the status text area.
.TP
.B Button1
click on a tag label views all windows with that
.BR tag .
.TP
.B Button3
click on a tag label adds/removes all windows with that
.B tag
to/from the view.
.SS Keyboard commands
.TP
.B Mod1-Shift-Return
Start
.BR xterm (1).
.TP
.B Mod1-Tab
Focus next
.BR window .
.TP
.B Mod1-Shift-Tab
Focus previous
.BR window .
.TP
.B Mod1-Return
Zoom
Zoom current
.B window
to the
.B master
column
.TP
.B Mod1-k
Focus previous
.B window
.TP
.B Mod1-j
Focus next
.B window
.RB ( tiling
mode only).
.TP
.B Mod1-m
Maximize current
.B window
.TP
.B Mod1-[0..n]
Focus
.B nth
tag
.TP
.B Mod1-space
(Re-)arrange
.B all
windows tiled
.TP
.B Mod1-Shift-space
(Re-)arrange
.B all
windows floating
.BR window .
.TP
.B Mod1-Shift-[0..n]
Apply
.B nth
tag to current
.B window
.B nth tag
to current
.BR window .
.TP
.B Mod1-Control-Shift-[0..n]
Add/remove
.B nth tag
to/from current
.BR window .
.TP
.B Mod1-Shift-c
Close focused
.B window.
.TP
.B Mod1-space
Toggle between
.B tiled
and
.B floating
mode (affects
.BR "all windows" ).
.TP
.B Mod1-[0..n]
View all windows with
.BR "tag n" .
.TP
.B Mod1-Control-[0..n]
Add/remove all windows with
.B tag n
to/from the view.
.TP
.B Mod1-Shift-q
Quit
.B dwm
.TP
.B Mod1-Shift-Return
Start
.B terminal
.TP
.B Mod1-Shift-w
Start
.B web browser
.TP
.B Mod1-Shift-l
Lock
.B screen
.TP
.B Mod1-Control-[0..n]
Append
.B nth
tag to current
.B window
.B dwm.
.SS Mouse commands
.TP
.B Mod1-Button1
Moves current
Move current
.B window
while dragging
.RB ( floating
mode only).
.TP
.B Mod1-Button2
Lowers current
Zoom current
.B window
to the
.B master
column
.RB ( tiling
mode only).
.TP
.B Mod1-Button3
Resizes current
Resize current
.B window
while dragging
.RB ( floating
mode only).
.SH CUSTOMIZATION
.B dwm
is customized through editing its source code. This keeps it fast, secure and
simple. The source code contains the
.I CUSTOMIZE
keyword to highlight relevant portions for customization.
is customized by creating a custom config.h and (re)compiling the source
code. This keeps it fast, secure and simple.
.SH CAVEATS
The status bar may display
.B broken pipe
when
.B dwm
has been started by
.BR xdm (1),
because it closes standard output before executing
.BR dwm .
.SH SEE ALSO
.BR dmenu (1)

94
dwm.h
View File

@ -3,38 +3,18 @@
* See LICENSE file for license details.
*/
#include "config.h"
#include <X11/Xlib.h>
/* CUSTOMIZE */
/* mask shorthands, used in event.c and client.c */
#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask)
#define MOUSEMASK (BUTTONMASK | PointerMotionMask)
#define PROTODELWIN 1
#define FONT "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*"
#define BGCOLOR "#0a2c2d"
#define FGCOLOR "#ddeeee"
#define BORDERCOLOR "#176164"
#define MODKEY Mod1Mask /* Mod4Mask */
/*
#define BGCOLOR "#666699"
#define FGCOLOR "#eeeeee"
#define BORDERCOLOR "#9999CC"
*/
#define MASTERW 52 /* percent */
#define WM_PROTOCOL_DELWIN 1
/* tags */
enum { Tfnord, Tdev, Tnet, Twork, Tmisc, TLast };
/* END CUSTOMIZE */
typedef union Arg Arg;
typedef struct Client Client;
typedef enum Corner Corner;
typedef struct DC DC;
typedef struct Fnt Fnt;
union Arg {
const char **argv;
typedef union {
const char *cmd;
int i;
};
} Arg;
/* atoms */
enum { NetSupported, NetWMName, NetLast };
@ -43,17 +23,18 @@ enum { WMProtocols, WMDelete, WMLast };
/* cursor */
enum { CurNormal, CurResize, CurMove, CurLast };
enum Corner { TopLeft, TopRight, BotLeft, BotRight };
/* window corners */
typedef enum { TopLeft, TopRight, BotLeft, BotRight } Corner;
struct Fnt {
typedef struct {
int ascent;
int descent;
int height;
XFontSet set;
XFontStruct *xfont;
};
} Fnt;
struct DC { /* draw context */
typedef struct { /* draw context */
int x, y, w, h;
unsigned long bg;
unsigned long fg;
@ -61,32 +42,35 @@ struct DC { /* draw context */
Drawable drawable;
Fnt font;
GC gc;
};
} DC;
typedef struct Client Client;
struct Client {
char name[256];
char *tags[TLast];
int proto;
int x, y, w, h;
int tx, ty, tw, th; /* title */
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int grav;
unsigned int border;
long flags;
unsigned int border;
Bool isfloat;
Bool ismax;
Bool *tags;
Client *next;
Client *prev;
Window win;
Window title;
Window twin;
};
extern char *tags[TLast], stext[1024];
extern int tsel, screen, sx, sy, sw, sh, bx, by, bw, bh, mw;
extern const char *tags[];
extern char stext[1024];
extern int screen, sx, sy, sw, sh, bx, by, bw, bh, mw;
extern unsigned int ntags, numlockmask;
extern void (*handler[LASTEvent])(XEvent *);
extern void (*arrange)(Arg *);
extern Atom wmatom[WMLast], netatom[NetLast];
extern Bool running, issel;
extern Bool running, issel, *seltag;
extern Client *clients, *sel;
extern Cursor cursor[CurLast];
extern DC dc;
@ -96,21 +80,16 @@ extern Window root, barwin;
/* client.c */
extern void ban(Client *c);
extern void focus(Client *c);
extern void focusnext(Arg *arg);
extern void focusprev(Arg *arg);
extern Client *getclient(Window w);
extern Client *getctitle(Window w);
extern void gravitate(Client *c, Bool invert);
extern void higher(Client *c);
extern void killclient(Arg *arg);
extern void lower(Client *c);
extern void manage(Window w, XWindowAttributes *wa);
extern void resize(Client *c, Bool sizehints, Corner sticky);
extern void setsize(Client *c);
extern void settitle(Client *c);
extern void togglemax(Arg *arg);
extern void unmanage(Client *c);
extern void zoom(Arg *arg);
/* draw.c */
extern void drawall();
@ -118,10 +97,11 @@ extern void drawstatus();
extern void drawtitle(Client *c);
extern unsigned long getcolor(const char *colstr);
extern void setfont(const char *fontstr);
extern unsigned int textw(char *text);
extern unsigned int textw(const char *text);
/* event.c */
extern void grabkeys();
extern void procevent();
/* main.c */
extern int getproto(Window w);
@ -130,17 +110,27 @@ extern void sendevent(Window w, Atom a, long value);
extern int xerror(Display *dsply, XErrorEvent *ee);
/* tag.c */
extern void appendtag(Arg *arg);
extern void dofloat(Arg *arg);
extern void dotile(Arg *arg);
extern Client *getnext(Client *c, unsigned int t);
extern void initrregs();
extern Client *getnext(Client *c);
extern Client *getprev(Client *c);
extern void replacetag(Arg *arg);
extern void settags(Client *c);
extern void togglemode(Arg *arg);
extern void view(Arg *arg);
extern void tag(Arg *arg);
extern void toggletag(Arg *arg);
/* util.c */
extern void *emallocz(unsigned int size);
extern void eprint(const char *errstr, ...);
extern void *erealloc(void *ptr, unsigned int size);
extern void spawn(Arg *arg);
/* view.c */
extern void dofloat(Arg *arg);
extern void dotile(Arg *arg);
extern void focusnext(Arg *arg);
extern void focusprev(Arg *arg);
extern Bool isvisible(Client *c);
extern void restack();
extern void togglemode(Arg *arg);
extern void toggleview(Arg *arg);
extern void view(Arg *arg);
extern void zoom(Arg *arg);

View File

@ -4,6 +4,7 @@
<meta name="author" content="Anselm R. Garbe">
<meta name="generator" content="ed">
<meta name="copyright" content="(C)opyright 2006 by Anselm R. Garbe">
<link rel="dwm icon" href="favicon.ico" type="image/x-icon" />
<style type="text/css">
body {
color: #000000;
@ -21,7 +22,7 @@
<p>
dwm is a dynamic window manager for X11.
</p>
<h4>Philosophy</h4>
<h4>Background</h4>
<p>
As founder and main developer of wmii I came to the conclusion that
wmii is too clunky for my needs. I don't need so many funky features
@ -39,7 +40,7 @@
</p>
<ul>
<li>
dwm has no Lua integration, no 9P support, no menu, no editable
dwm has no Lua integration, no 9P support, no editable
tagbars, no shell-based configuration, no remote control, and comes
without any additional tools like printing the selection or warping
the mouse.
@ -55,7 +56,7 @@
depending on the application in use and the task performed.
</li>
<li>
dwm don't distinguishes between layers, there is no floating or
dwm doesn't distinguishes between layers, there is no floating or
tiled layer. Wether the clients of currently selected tag are in
tiled mode or not, you can re-arrange all clients on the fly.
Popup- and fixed-size windows are treated floating, however.
@ -67,7 +68,7 @@
and status text read from standard input. You don't have to learn
Lua/sh/ruby or some weird configuration file format (like X
resource files), beside C to customize it for your needs,
you <b>only</b> have to learn C.
you <b>only</b> have to learn C (at least editing header files).
</li>
<li>
Because dwm is customized through editing its source code, it's
@ -88,15 +89,24 @@
It can be downloaded and distributed under the conditions
of the <a href="http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm?f=f10eb1139362;file=LICENSE;style=raw">MIT/X Consortium license</a>.
</li>
<li>
Optionally you can install <b>dmenu</b> to extend dwm with a wmii-alike menu.
</li>
</ul>
<h4>Links</h4>
<ul>
<li><a href="http://10kloc.org/cgi-bin/man/man2html?query=dwm">Man page</a></li>
<li><a href="http://10kloc.org/shots/dwm-20060714.png">Screenshot</a> (20060714)</li>
<li><a href="http://10kloc.org/shots/dwm-20060810a.png">Screenshot of tiled mode</a> (20060810)</li>
<li><a href="http://10kloc.org/shots/dwm-20060810b.png">Screenshotof floating mode</a> (20060810)</li>
<li><a href="http://10kloc.org/download/poster.ps">A4 poster (PostScript)</a></li>
<li>Mailing List: <a href="http://10kloc.org/cgi-bin/mailman/listinfo/dwm">dwm at wmii dot de</a> <a href="http://10kloc.org/pipermail/dwm/">(Archives)</a></li>
<li>Mailing List: <a href="http://10kloc.org/cgi-bin/mailman/listinfo/dwm">dwm at wmii dot de</a> <a href="http://10kloc.org/pipermail/dwm/">(Archives)</a>&nbsp;<a href="http://dir.gmane.org/gmane.comp.window-managers.dwm">(GMANE Archive)</a></li>
<li>IRC channel: <code>#dwm</code> at <code>irc.oftc.net</code></li>
</ul>
<h3>Download</h3>
<ul>
<li><a href="http://10kloc.org/download/dwm-1.0.tar.gz">dwm 1.0</a> (15kb) (20060824)</li>
<li><a href="http://10kloc.org/download/dmenu-0.5.tar.gz">dmenu 0.5</a> (7kb) (20060824)</li>
</ul>
<h3>Development</h3>
<p>
dwm is actively developed in parallel to wmii. You can <a href="http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm">browse</a> its source code repository or get a copy using <a href="http://www.selenic.com/mercurial/">Mercurial</a> with following command:
@ -104,15 +114,14 @@
<p>
<code>hg clone http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm</code>
</p>
<h3>Download</h3>
<ul>
<li><a href="http://10kloc.org/download/dwm-0.4.tar.gz">dwm 0.4</a> (13kb) (20060720)</li>
</ul>
<p>
<code>hg clone http://10kloc.org/cgi-bin/hgwebdir.cgi/dmenu</code>
</p>
<h3>Miscellaneous</h3>
<p>
You can purchase this <a href="https://www.spreadshirt.net/shop.php?op=article&article_id=3298632&view=403">tricot</a>
if you like dwm and the dwm logo, which has been designed by Anselm.
</p>
<p><small>--Anselm (20060719)</small></p>
<p><small>--Anselm</small></p>
</body>
</html>

210
event.c
View File

@ -3,15 +3,11 @@
* See LICENSE file for license details.
*/
#include "dwm.h"
#include <stdlib.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#define ButtonMask (ButtonPressMask | ButtonReleaseMask)
#define MouseMask (ButtonMask | PointerMotionMask)
/* CUSTOMIZE */
/* static */
typedef struct {
unsigned long mod;
@ -20,53 +16,9 @@ typedef struct {
Arg arg;
} Key;
/*
const char *browse[] = { "firefox", NULL };
const char *gimp[] = { "gimp", NULL };
*/
const char *term[] = { "xterm", NULL };
/*
"urxvt", "-tr", "+sb", "-bg", "black", "-fg", "white", "-cr", "white",
"-fn", "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*", NULL
};
const char *xlock[] = { "xlock", NULL };
*/
KEYS
static Key key[] = {
/* modifier key function arguments */
{ MODKEY, XK_0, view, { .i = Tfnord } },
{ MODKEY, XK_1, view, { .i = Tdev } },
{ MODKEY, XK_2, view, { .i = Tnet } },
{ MODKEY, XK_3, view, { .i = Twork } },
{ MODKEY, XK_4, view, { .i = Tmisc} },
{ MODKEY, XK_j, focusnext, { 0 } },
{ MODKEY, XK_k, focusprev, { 0 } },
{ MODKEY, XK_m, togglemax, { 0 } },
{ MODKEY, XK_space, togglemode, { 0 } },
{ MODKEY, XK_Return, zoom, { 0 } },
{ MODKEY|ControlMask, XK_0, appendtag, { .i = Tfnord } },
{ MODKEY|ControlMask, XK_1, appendtag, { .i = Tdev } },
{ MODKEY|ControlMask, XK_2, appendtag, { .i = Tnet } },
{ MODKEY|ControlMask, XK_3, appendtag, { .i = Twork } },
{ MODKEY|ControlMask, XK_4, appendtag, { .i = Tmisc } },
{ MODKEY|ShiftMask, XK_0, replacetag, { .i = Tfnord } },
{ MODKEY|ShiftMask, XK_1, replacetag, { .i = Tdev } },
{ MODKEY|ShiftMask, XK_2, replacetag, { .i = Tnet } },
{ MODKEY|ShiftMask, XK_3, replacetag, { .i = Twork } },
{ MODKEY|ShiftMask, XK_4, replacetag, { .i = Tmisc } },
{ MODKEY|ShiftMask, XK_c, killclient, { 0 } },
{ MODKEY|ShiftMask, XK_q, quit, { 0 } },
{ MODKEY|ShiftMask, XK_Return, spawn, { .argv = term } },
/*
{ MODKEY|ShiftMask, XK_g, spawn, { .argv = gimp } },
{ MODKEY|ShiftMask, XK_l, spawn, { .argv = xlock } },
{ MODKEY|ShiftMask, XK_w, spawn, { .argv = browse } },
*/
};
/* END CUSTOMIZE */
/* static */
#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
static void
movemouse(Client *c)
@ -78,12 +30,12 @@ movemouse(Client *c)
ocx = c->x;
ocy = c->y;
if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurMove], CurrentTime) != GrabSuccess)
return;
XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
for(;;) {
XMaskEvent(dpy, MouseMask | ExposureMask, &ev);
XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
switch (ev.type) {
default: break;
case Expose:
@ -106,17 +58,18 @@ static void
resizemouse(Client *c)
{
int ocx, ocy;
int nw, nh;
Corner sticky;
XEvent ev;
ocx = c->x;
ocy = c->y;
if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurResize], CurrentTime) != GrabSuccess)
return;
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
for(;;) {
XMaskEvent(dpy, MouseMask | ExposureMask, &ev);
XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
switch(ev.type) {
default: break;
case Expose:
@ -124,8 +77,10 @@ resizemouse(Client *c)
break;
case MotionNotify:
XSync(dpy, False);
c->w = abs(ocx - ev.xmotion.x);
c->h = abs(ocy - ev.xmotion.y);
if((nw = abs(ocx - ev.xmotion.x)))
c->w = abs(ocx - ev.xmotion.x);
if((nh = abs(ocy - ev.xmotion.y)))
c->h = abs(ocy - ev.xmotion.y);
c->x = (ocx <= ev.xmotion.x) ? ocx : ocx - c->w;
c->y = (ocy <= ev.xmotion.y) ? ocy : ocy - c->h;
if(ocx <= ev.xmotion.x)
@ -150,43 +105,37 @@ buttonpress(XEvent *e)
XButtonPressedEvent *ev = &e->xbutton;
if(barwin == ev->window) {
switch(ev->button) {
default:
x = 0;
for(a.i = 0; a.i < TLast; a.i++) {
x += textw(tags[a.i]);
if(ev->x < x) {
x = 0;
for(a.i = 0; a.i < ntags; a.i++) {
x += textw(tags[a.i]);
if(ev->x < x) {
if(ev->button == Button1)
view(&a);
break;
}
else if(ev->button == Button3)
toggleview(&a);
return;
}
break;
case Button4:
a.i = (tsel + 1 < TLast) ? tsel + 1 : 0;
view(&a);
break;
case Button5:
a.i = (tsel - 1 >= 0) ? tsel - 1 : TLast - 1;
view(&a);
break;
}
}
else if((c = getclient(ev->window))) {
focus(c);
if(CLEANMASK(ev->state) == 0)
return;
switch(ev->button) {
default:
break;
case Button1:
if(!c->ismax && (arrange == dofloat || c->isfloat)) {
higher(c);
restack(c);
movemouse(c);
}
break;
case Button2:
lower(c);
zoom(NULL);
break;
case Button3:
if(!c->ismax && (arrange == dofloat || c->isfloat)) {
higher(c);
restack(c);
resizemouse(c);
}
break;
@ -197,11 +146,12 @@ buttonpress(XEvent *e)
static void
configurerequest(XEvent *e)
{
unsigned long newmask;
Client *c;
XConfigureRequestEvent *ev = &e->xconfigurerequest;
XEvent synev;
XWindowChanges wc;
ev->value_mask &= ~CWSibling;
if((c = getclient(ev->window))) {
gravitate(c, True);
if(ev->value_mask & CWX)
@ -213,22 +163,46 @@ configurerequest(XEvent *e)
if(ev->value_mask & CWHeight)
c->h = ev->height;
if(ev->value_mask & CWBorderWidth)
c->border = 1;
c->border = ev->border_width;
gravitate(c, False);
resize(c, True, TopLeft);
wc.x = c->x;
wc.y = c->y;
wc.width = c->w;
wc.height = c->h;
newmask = ev->value_mask & (~(CWSibling | CWStackMode | CWBorderWidth));
if(newmask)
XConfigureWindow(dpy, c->win, newmask, &wc);
else {
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;
/* Send synthetic ConfigureNotify */
XSendEvent(dpy, c->win, True, NoEventMask, &synev);
}
XSync(dpy, False);
if(c->isfloat)
resize(c, False, TopLeft);
else
arrange(NULL);
}
else {
wc.x = ev->x;
wc.y = ev->y;
wc.width = ev->width;
wc.height = ev->height;
wc.border_width = ev->border_width;
wc.sibling = ev->above;
wc.stack_mode = ev->detail;
XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
XSync(dpy, False);
}
wc.x = ev->x;
wc.y = ev->y;
wc.width = ev->width;
wc.height = ev->height;
wc.border_width = 1;
wc.sibling = None;
wc.stack_mode = Above;
ev->value_mask &= ~CWStackMode;
ev->value_mask |= CWBorderWidth;
XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
XSync(dpy, False);
}
static void
@ -250,10 +224,13 @@ enternotify(XEvent *e)
if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
return;
if((c = getclient(ev->window)))
if((c = getclient(ev->window)) || (c = getctitle(ev->window)))
focus(c);
else if(ev->window == root)
else if(ev->window == root) {
issel = True;
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
drawall();
}
}
static void
@ -279,12 +256,15 @@ keypress(XEvent *e)
XKeyEvent *ev = &e->xkey;
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
for(i = 0; i < len; i++)
if((keysym == key[i].keysym) && (key[i].mod == ev->state)) {
for(i = 0; i < len; i++) {
if(keysym == key[i].keysym &&
CLEANMASK(key[i].mod) == CLEANMASK(ev->state))
{
if(key[i].func)
key[i].func(&key[i].arg);
return;
}
}
}
static void
@ -292,8 +272,20 @@ leavenotify(XEvent *e)
{
XCrossingEvent *ev = &e->xcrossing;
if((ev->window == root) && !ev->same_screen)
issel = True;
if((ev->window == root) && !ev->same_screen) {
issel = False;
drawall();
}
}
static void
mappingnotify(XEvent *e)
{
XMappingEvent *ev = &e->xmapping;
XRefreshKeyboardMapping(ev);
if(ev->request == MappingKeyboard)
grabkeys();
}
static void
@ -368,6 +360,7 @@ void (*handler[LASTEvent]) (XEvent *) = {
[LeaveNotify] = leavenotify,
[Expose] = expose,
[KeyPress] = keypress,
[MappingNotify] = mappingnotify,
[MapRequest] = maprequest,
[PropertyNotify] = propertynotify,
[UnmapNotify] = unmapnotify
@ -380,10 +373,29 @@ grabkeys()
unsigned int i;
KeyCode code;
XUngrabKey(dpy, AnyKey, AnyModifier, root);
for(i = 0; i < len; i++) {
code = XKeysymToKeycode(dpy, key[i].keysym);
XUngrabKey(dpy, code, key[i].mod, root);
XGrabKey(dpy, code, key[i].mod, root, True,
GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, key[i].mod | LockMask, root, True,
GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, key[i].mod | numlockmask, root, True,
GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, key[i].mod | numlockmask | LockMask, root, True,
GrabModeAsync, GrabModeAsync);
}
}
void
procevent()
{
XEvent ev;
while(XPending(dpy)) {
XNextEvent(dpy, &ev);
if(handler[ev.type])
(handler[ev.type])(&ev); /* call handler */
}
}

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

240
main.c
View File

@ -4,7 +4,6 @@
*/
#include "dwm.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@ -12,23 +11,49 @@
#include <unistd.h>
#include <sys/select.h>
#include <X11/cursorfont.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <X11/Xproto.h>
/* extern */
char stext[1024];
Bool *seltag;
int screen, sx, sy, sw, sh, bx, by, bw, bh, mw;
unsigned int ntags, numlockmask;
Atom wmatom[WMLast], netatom[NetLast];
Bool running = True;
Bool issel = True;
Client *clients = NULL;
Client *sel = NULL;
Cursor cursor[CurLast];
Display *dpy;
DC dc = {0};
Window root, barwin;
/* static */
static int (*xerrorxlib)(Display *, XErrorEvent *);
static Bool otherwm;
static Bool otherwm, readin;
static void
cleanup()
{
close(STDIN_FILENO);
while(sel) {
resize(sel, True, TopLeft);
unmanage(sel);
}
if(dc.font.set)
XFreeFontSet(dpy, dc.font.set);
else
XFreeFont(dpy, dc.font.xfont);
XUngrabKey(dpy, AnyKey, AnyModifier, root);
XFreePixmap(dpy, dc.drawable);
XFreeGC(dpy, dc.gc);
XDestroyWindow(dpy, barwin);
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
XSync(dpy, False);
}
static void
@ -38,6 +63,7 @@ scan()
Window *wins, d1, d2;
XWindowAttributes wa;
wins = NULL;
if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
for(i = 0; i < num; i++) {
if(!XGetWindowAttributes(dpy, wins[i], &wa))
@ -52,23 +78,77 @@ scan()
XFree(wins);
}
static int
win_property(Window w, Atom a, Atom t, long l, unsigned char **prop)
static void
setup()
{
int status, format;
unsigned long res, extra;
Atom real;
int i, j;
unsigned int mask;
Window w;
XModifierKeymap *modmap;
XSetWindowAttributes wa;
status = XGetWindowProperty(dpy, w, a, 0L, l, False, t, &real, &format,
&res, &extra, prop);
/* init atoms */
wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
PropModeReplace, (unsigned char *) netatom, NetLast);
if(status != Success || *prop == 0) {
return 0;
/* init cursors */
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
modmap = XGetModifierMapping(dpy);
for (i = 0; i < 8; i++) {
for (j = 0; j < modmap->max_keypermod; j++) {
if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock))
numlockmask = (1 << i);
}
}
if(res == 0) {
free((void *) *prop);
}
return res;
XFree(modmap);
wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask | EnterWindowMask | LeaveWindowMask;
wa.cursor = cursor[CurNormal];
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
grabkeys();
initrregs();
for(ntags = 0; tags[ntags]; ntags++);
seltag = emallocz(sizeof(Bool) * ntags);
seltag[0] = True;
/* style */
dc.bg = getcolor(BGCOLOR);
dc.fg = getcolor(FGCOLOR);
dc.border = getcolor(BORDERCOLOR);
setfont(FONT);
sx = sy = 0;
sw = DisplayWidth(dpy, screen);
sh = DisplayHeight(dpy, screen);
mw = (sw * MASTERW) / 100;
bx = by = 0;
bw = sw;
dc.h = bh = dc.font.height + 4;
wa.override_redirect = 1;
wa.background_pixmap = ParentRelative;
wa.event_mask = ButtonPressMask | ExposureMask;
barwin = XCreateWindow(dpy, root, bx, by, bw, bh, 0, DefaultDepth(dpy, screen),
CopyFromParent, DefaultVisual(dpy, screen),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
XDefineCursor(dpy, barwin, cursor[CurNormal]);
XMapRaised(dpy, barwin);
dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, 0);
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
strcpy(stext, "dwm-"VERSION);
}
/*
@ -84,38 +164,22 @@ xerrorstart(Display *dsply, XErrorEvent *ee)
/* extern */
char stext[1024];
/* CUSTOMIZE */
int tsel = Tdev; /* default tag */
/* END CUSTOMIZE */
int screen, sx, sy, sw, sh, bx, by, bw, bh, mw;
Atom wmatom[WMLast], netatom[NetLast];
Bool running = True;
Bool issel = True;
Client *clients = NULL;
Client *sel = NULL;
Cursor cursor[CurLast];
Display *dpy;
DC dc = {0};
Window root, barwin;
int
getproto(Window w)
{
int protos = 0;
int i;
long res;
unsigned char *protocols;
int i, format, protos, status;
unsigned long extra, res;
Atom *protocols, real;
res = win_property(w, wmatom[WMProtocols], XA_ATOM, 20L, &protocols);
if(res <= 0) {
protos = 0;
status = XGetWindowProperty(dpy, w, wmatom[WMProtocols], 0L, 20L, False,
XA_ATOM, &real, &format, &res, &extra, (unsigned char **)&protocols);
if(status != Success || protocols == 0)
return protos;
}
for(i = 0; i < res; i++) {
for(i = 0; i < res; i++)
if(protocols[i] == wmatom[WMDelete])
protos |= WM_PROTOCOL_DELWIN;
}
free((char *) protocols);
protos |= PROTODELWIN;
free(protocols);
return protos;
}
@ -137,7 +201,7 @@ sendevent(Window w, Atom a, long value)
void
quit(Arg *arg)
{
running = False;
readin = running = False;
}
/*
@ -164,13 +228,8 @@ xerror(Display *dpy, XErrorEvent *ee)
int
main(int argc, char *argv[])
{
int i;
unsigned int mask;
int r, xfd;
fd_set rd;
Bool readin = True;
Window w;
XEvent ev;
XSetWindowAttributes wa;
if(argc == 2 && !strncmp("-v", argv[1], 3)) {
fputs("dwm-"VERSION", (C)opyright MMVI Anselm R. Garbe\n", stdout);
@ -181,96 +240,43 @@ main(int argc, char *argv[])
dpy = XOpenDisplay(0);
if(!dpy)
eprint("dwm: cannot connect X server\n");
eprint("dwm: cannot open display\n");
xfd = ConnectionNumber(dpy);
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
/* check if another WM is already running */
otherwm = False;
XSetErrorHandler(xerrorstart);
/* this causes an error if some other WM is running */
/* this causes an error if some other window manager is running */
XSelectInput(dpy, root, SubstructureRedirectMask);
XSync(dpy, False);
if(otherwm)
eprint("dwm: another window manager is already running\n");
XSync(dpy, False);
XSetErrorHandler(NULL);
xerrorxlib = XSetErrorHandler(xerror);
XSync(dpy, False);
/* init atoms */
wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
PropModeReplace, (unsigned char *) netatom, NetLast);
/* init cursors */
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
grabkeys();
/* style */
dc.bg = getcolor(BGCOLOR);
dc.fg = getcolor(FGCOLOR);
dc.border = getcolor(BORDERCOLOR);
setfont(FONT);
sx = sy = 0;
sw = DisplayWidth(dpy, screen);
sh = DisplayHeight(dpy, screen);
mw = (sw * MASTERW) / 100;
wa.override_redirect = 1;
wa.background_pixmap = ParentRelative;
wa.event_mask = ButtonPressMask | ExposureMask;
bx = by = 0;
bw = sw;
dc.h = bh = dc.font.height + 4;
barwin = XCreateWindow(dpy, root, bx, by, bw, bh, 0, DefaultDepth(dpy, screen),
CopyFromParent, DefaultVisual(dpy, screen),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
XDefineCursor(dpy, barwin, cursor[CurNormal]);
XMapRaised(dpy, barwin);
dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, 0);
setup();
drawstatus();
issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
wa.event_mask = SubstructureRedirectMask | EnterWindowMask | LeaveWindowMask;
wa.cursor = cursor[CurNormal];
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
strcpy(stext, "dwm-"VERSION);
scan();
/* main event loop, reads status text from stdin as well */
/* main event loop, also reads status text from stdin */
XSync(dpy, False);
procevent();
readin = True;
while(running) {
FD_ZERO(&rd);
if(readin)
FD_SET(STDIN_FILENO, &rd);
FD_SET(ConnectionNumber(dpy), &rd);
i = select(ConnectionNumber(dpy) + 1, &rd, 0, 0, 0);
if(i == -1 && errno == EINTR)
FD_SET(xfd, &rd);
r = select(xfd + 1, &rd, NULL, NULL, NULL);
if((r == -1) && (errno == EINTR))
continue;
if(i < 0)
eprint("select failed\n");
else if(i > 0) {
if(FD_ISSET(ConnectionNumber(dpy), &rd)) {
while(XPending(dpy)) {
XNextEvent(dpy, &ev);
if(handler[ev.type])
(handler[ev.type])(&ev); /* call handler */
}
}
if(r > 0) {
if(readin && FD_ISSET(STDIN_FILENO, &rd)) {
readin = NULL != fgets(stext, sizeof(stext), stdin);
if(readin)
@ -280,8 +286,10 @@ main(int argc, char *argv[])
drawstatus();
}
}
else if(r < 0)
eprint("select failed\n");
procevent();
}
cleanup();
XCloseDisplay(dpy);

224
tag.c
View File

@ -3,212 +3,144 @@
* See LICENSE file for license details.
*/
#include "dwm.h"
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <X11/Xutil.h>
/* static */
typedef struct {
const char *pattern;
char *tags[TLast];
const char *clpattern;
const char *tpattern;
Bool isfloat;
} Rule;
/* CUSTOMIZE */
static Rule rule[] = {
/* class:instance tags isfloat */
{ "Firefox.*", { [Tnet] = "net" }, False },
{ "Gimp.*", { 0 }, True},
};
typedef struct {
regex_t *clregex;
regex_t *tregex;
} RReg;
char *tags[TLast] = {
[Tfnord] = "fnord",
[Tdev] = "dev",
[Tnet] = "net",
[Twork] = "work",
[Tmisc] = "misc",
};
/* static */
void (*arrange)(Arg *) = dotile;
TAGS
RULES
/* END CUSTOMIZE */
static RReg *rreg = NULL;
static unsigned int len = 0;
/* extern */
void
appendtag(Arg *arg)
{
if(!sel)
return;
sel->tags[arg->i] = tags[arg->i];
arrange(NULL);
}
void
dofloat(Arg *arg)
{
Client *c;
for(c = clients; c; c = c->next) {
c->ismax = False;
if(c->tags[tsel]) {
resize(c, True, TopLeft);
}
else
ban(c);
}
if(sel && !sel->tags[tsel]) {
if((sel = getnext(clients, tsel))) {
higher(sel);
focus(sel);
}
}
drawall();
}
void
dotile(Arg *arg)
{
int n, i, w, h;
Client *c;
w = sw - mw;
for(n = 0, c = clients; c; c = c->next)
if(c->tags[tsel] && !c->isfloat)
n++;
if(n > 1)
h = (sh - bh) / (n - 1);
else
h = sh - bh;
for(i = 0, c = clients; c; c = c->next) {
c->ismax = False;
if(c->tags[tsel]) {
if(c->isfloat) {
higher(c);
resize(c, True, TopLeft);
continue;
}
if(n == 1) {
c->x = sx;
c->y = sy + bh;
c->w = sw - 2 * c->border;
c->h = sh - 2 * c->border - bh;
}
else if(i == 0) {
c->x = sx;
c->y = sy + bh;
c->w = mw - 2 * c->border;
c->h = sh - 2 * c->border - bh;
}
else if(h > bh) {
c->x = sx + mw;
c->y = sy + (i - 1) * h + bh;
c->w = w - 2 * c->border;
c->h = h - 2 * c->border;
}
else { /* fallback if h < bh */
c->x = sx + mw;
c->y = sy + bh;
c->w = w - 2 * c->border;
c->h = sh - 2 * c->border - bh;
}
resize(c, False, TopLeft);
i++;
}
else
ban(c);
}
if(!sel || (sel && !sel->tags[tsel])) {
if((sel = getnext(clients, tsel))) {
higher(sel);
focus(sel);
}
}
drawall();
}
Client *
getnext(Client *c, unsigned int t)
getnext(Client *c)
{
for(; c && !c->tags[t]; c = c->next);
for(; c && !isvisible(c); c = c->next);
return c;
}
Client *
getprev(Client *c)
{
for(; c && !c->tags[tsel]; c = c->prev);
for(; c && !isvisible(c); c = c->prev);
return c;
}
void
replacetag(Arg *arg)
initrregs()
{
int i;
unsigned int i;
regex_t *reg;
if(!sel)
if(rreg)
return;
len = sizeof(rule) / sizeof(rule[0]);
rreg = emallocz(len * sizeof(RReg));
for(i = 0; i < TLast; i++)
sel->tags[i] = NULL;
appendtag(arg);
for(i = 0; i < len; i++) {
if(rule[i].clpattern) {
reg = emallocz(sizeof(regex_t));
if(regcomp(reg, rule[i].clpattern, 0))
free(reg);
else
rreg[i].clregex = reg;
}
if(rule[i].tpattern) {
reg = emallocz(sizeof(regex_t));
if(regcomp(reg, rule[i].tpattern, 0))
free(reg);
else
rreg[i].tregex = reg;
}
}
}
void
settags(Client *c)
{
char classinst[256];
static unsigned int len = sizeof(rule) / sizeof(rule[0]);
char prop[512];
unsigned int i, j;
regex_t regex;
regmatch_t tmp;
Bool matched = False;
XClassHint ch;
if(XGetClassHint(dpy, c->win, &ch)) {
snprintf(classinst, sizeof(classinst), "%s:%s",
snprintf(prop, sizeof(prop), "%s:%s:%s",
ch.res_class ? ch.res_class : "",
ch.res_name ? ch.res_name : "");
for(i = 0; !matched && i < len; i++) {
if(!regcomp(&regex, rule[i].pattern, 0)) {
if(!regexec(&regex, classinst, 1, &tmp, 0)) {
for(j = 0; j < TLast; j++) {
if(rule[i].tags[j])
matched = True;
c->tags[j] = rule[i].tags[j];
ch.res_name ? ch.res_name : "", c->name);
for(i = 0; !matched && i < len; i++)
if(rreg[i].clregex && !regexec(rreg[i].clregex, prop, 1, &tmp, 0)) {
c->isfloat = rule[i].isfloat;
for(j = 0; rreg[i].tregex && j < ntags; j++) {
if(!regexec(rreg[i].tregex, tags[j], 1, &tmp, 0)) {
matched = True;
c->tags[j] = True;
}
c->isfloat = rule[i].isfloat;
}
regfree(&regex);
}
}
if(ch.res_class)
XFree(ch.res_class);
if(ch.res_name)
XFree(ch.res_name);
}
if(!matched)
c->tags[tsel] = tags[tsel];
for(i = 0; i < ntags; i++)
c->tags[i] = seltag[i];
}
void
togglemode(Arg *arg)
tag(Arg *arg)
{
arrange = arrange == dofloat ? dotile : dofloat;
arrange(NULL);
unsigned int i;
if(!sel)
return;
for(i = 0; i < ntags; i++)
sel->tags[i] = False;
sel->tags[arg->i] = True;
settitle(sel);
if(!isvisible(sel))
arrange(NULL);
else
drawstatus();
}
void
view(Arg *arg)
toggletag(Arg *arg)
{
tsel = arg->i;
arrange(NULL);
drawall();
unsigned int i;
if(!sel)
return;
sel->tags[arg->i] = !sel->tags[arg->i];
for(i = 0; i < ntags && !sel->tags[i]; i++);
if(i == ntags)
sel->tags[arg->i] = True;
settitle(sel);
if(!isvisible(sel))
arrange(NULL);
else
drawstatus();
}

34
util.c
View File

@ -3,21 +3,12 @@
* See LICENSE file for license details.
*/
#include "dwm.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
/* static */
static void
bad_malloc(unsigned int size)
{
eprint("fatal: could not malloc() %u bytes\n", size);
}
/* extern */
void *
@ -26,12 +17,13 @@ emallocz(unsigned int size)
void *res = calloc(1, size);
if(!res)
bad_malloc(size);
eprint("fatal: could not malloc() %u bytes\n", size);
return res;
}
void
eprint(const char *errstr, ...) {
eprint(const char *errstr, ...)
{
va_list ap;
va_start(ap, errstr);
@ -40,20 +32,32 @@ eprint(const char *errstr, ...) {
exit(EXIT_FAILURE);
}
void *
erealloc(void *ptr, unsigned int size)
{
void *res = realloc(ptr, size);
if(!res)
eprint("fatal: could not malloc() %u bytes\n", size);
return res;
}
void
spawn(Arg *arg)
{
char **argv = (char **)arg->argv;
static char *shell = NULL;
if(!argv || !argv[0])
if(!shell && !(shell = getenv("SHELL")))
shell = "/bin/sh";
if(!arg->cmd)
return;
if(fork() == 0) {
if(fork() == 0) {
if(dpy)
close(ConnectionNumber(dpy));
setsid();
execvp(argv[0], argv);
fprintf(stderr, "dwm: execvp %s", argv[0]);
execl(shell, shell, "-c", arg->cmd, (char *)NULL);
fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg->cmd);
perror(" failed");
}
exit(0);

253
view.c Normal file
View File

@ -0,0 +1,253 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include "dwm.h"
/* extern */
void (*arrange)(Arg *) = DEFMODE;
void
dofloat(Arg *arg)
{
Client *c;
for(c = clients; c; c = c->next) {
c->ismax = False;
if(isvisible(c)) {
resize(c, True, TopLeft);
}
else
ban(c);
}
if(!sel || !isvisible(sel))
sel = getnext(clients);
if(sel)
focus(sel);
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
restack();
}
void
dotile(Arg *arg)
{
int h, i, n, w;
Client *c;
w = sw - mw;
for(n = 0, c = clients; c; c = c->next)
if(isvisible(c) && !c->isfloat)
n++;
if(n > 1)
h = (sh - bh) / (n - 1);
else
h = sh - bh;
for(i = 0, c = clients; c; c = c->next) {
c->ismax = False;
if(isvisible(c)) {
if(c->isfloat) {
resize(c, True, TopLeft);
continue;
}
if(n == 1) {
c->x = sx;
c->y = sy + bh;
c->w = sw - 2;
c->h = sh - 2 - bh;
}
else if(i == 0) {
c->x = sx;
c->y = sy + bh;
c->w = mw - 2;
c->h = sh - 2 - bh;
}
else if(h > bh) {
c->x = sx + mw;
c->y = sy + (i - 1) * h + bh;
c->w = w - 2;
if(i + 1 == n)
c->h = sh - c->y - 2;
else
c->h = h - 2;
}
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);
i++;
}
else
ban(c);
}
if(!sel || !isvisible(sel))
sel = getnext(clients);
if(sel)
focus(sel);
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
restack();
}
void
focusnext(Arg *arg)
{
Client *c;
if(!sel)
return;
if(!(c = getnext(sel->next)))
c = getnext(clients);
if(c) {
focus(c);
restack();
}
}
void
focusprev(Arg *arg)
{
Client *c;
if(!sel)
return;
if(!(c = getprev(sel->prev))) {
for(c = clients; c && c->next; c = c->next);
c = getprev(c);
}
if(c) {
focus(c);
restack();
}
}
Bool
isvisible(Client *c)
{
unsigned int i;
for(i = 0; i < ntags; i++)
if(c->tags[i] && seltag[i])
return True;
return False;
}
void
restack()
{
static unsigned int nwins = 0;
static Window *wins = NULL;
unsigned int f, fi, m, mi, n;
Client *c;
XEvent ev;
for(f = 0, m = 0, c = clients; c; c = c->next)
if(isvisible(c)) {
if(c->isfloat || arrange == dofloat)
f++;
else
m++;
}
if(!(n = 2 * (f + m))) {
drawstatus();
return;
}
if(nwins < n) {
nwins = n;
wins = erealloc(wins, nwins * sizeof(Window));
}
fi = 0;
mi = 2 * f;
if(sel->isfloat || arrange == dofloat) {
wins[fi++] = sel->twin;
wins[fi++] = sel->win;
}
else {
wins[mi++] = sel->twin;
wins[mi++] = sel->win;
}
for(c = clients; c; c = c->next)
if(isvisible(c) && c != sel) {
if(c->isfloat || arrange == dofloat) {
wins[fi++] = c->twin;
wins[fi++] = c->win;
}
else {
wins[mi++] = c->twin;
wins[mi++] = c->win;
}
}
XRestackWindows(dpy, wins, n);
drawall();
XSync(dpy, False);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}
void
togglemode(Arg *arg)
{
arrange = (arrange == dofloat) ? dotile : dofloat;
if(sel)
arrange(NULL);
else
drawstatus();
}
void
toggleview(Arg *arg)
{
unsigned int i;
seltag[arg->i] = !seltag[arg->i];
for(i = 0; i < ntags && !seltag[i]; i++);
if(i == ntags)
seltag[arg->i] = True; /* cannot toggle last view */
arrange(NULL);
}
void
view(Arg *arg)
{
unsigned int i;
for(i = 0; i < ntags; i++)
seltag[i] = False;
seltag[arg->i] = True;
arrange(NULL);
}
void
zoom(Arg *arg)
{
Client *c;
if(!sel || (arrange != dotile) || sel->isfloat || sel->ismax)
return;
if(sel == getnext(clients)) {
if((c = getnext(sel->next)))
sel = c;
else
return;
}
/* pop */
sel->prev->next = sel->next;
if(sel->next)
sel->next->prev = sel->prev;
sel->prev = NULL;
clients->prev = sel;
sel->next = clients;
clients = sel;
focus(sel);
arrange(NULL);
}