Compare commits

...

223 Commits
0.6 ... 1.2

Author SHA1 Message Date
140be1b4b3 prepared 1.2 2006-08-30 12:39:27 +02:00
79259acc12 now using Salmi's menu command 2006-08-30 11:21:56 +02:00
5a3bea2d69 removed a warning reported by Jukka 2006-08-30 11:15:58 +02:00
30d928591d simplified configurerequest 2006-08-29 19:24:28 +02:00
70a3e62257 now dwm enforces max screen size also in tiled mode on non-floating clients which are maximized 2006-08-29 18:05:02 +02:00
6828fba7a0 fixed 2006-08-29 17:33:27 +02:00
aa1bda8164 configurenotify remembers max geom now, and restores this if necessary, however it accepts to touch the max size on configurerequest, this shouldn't break fillscreen apps (tested with mplayer) 2006-08-29 17:31:55 +02:00
157ea539a2 applied patch similiar proposed by dave tweed 2006-08-29 17:11:37 +02:00
c3c94c0e0a improved selection policy 2006-08-29 15:28:29 +02:00
9d73909075 still something wrong with reorder() 2006-08-29 13:40:09 +02:00
016c54196e this algorithm seems to keep order for any scenario 2006-08-29 09:57:57 +02:00
5056bb952d fix client position in list also on tag and toggletag 2006-08-29 09:25:14 +02:00
8a6679b3b4 added attach/detach functions which don't attach at the begin of list, but at the slot of a first match of the tags of a client 2006-08-29 09:23:44 +02:00
7b6d5ff298 removed crappy variables 2006-08-28 14:32:51 +02:00
846850914d changed config.arg.h - I really need the 4th tag 2006-08-28 12:27:00 +02:00
4e6c513ac2 updated html page 2006-08-28 10:21:40 +02:00
db9cda6a7d Added tag 1.1 for changeset 44a55e6e46bf6c231780b09d919977d6f01083de 2006-08-28 10:19:55 +02:00
a50b15a9e9 added a comment to spawn 2006-08-28 08:17:27 +02:00
0a25fe9188 applied sanders focus_ patches 2006-08-28 08:06:50 +02:00
2dd5212a79 applied sanders somepatches.patch 2006-08-28 08:02:29 +02:00
00e95e1f38 oh frking dear big font... 2006-08-25 18:14:55 +02:00
0a0759132c term enlightened 2006-08-25 18:05:18 +02:00
5cf362c7d0 switching to darker colorscheme with larger font 2006-08-25 18:03:56 +02:00
413be1112a patched arg.h 2006-08-25 17:42:58 +02:00
8233dc8568 new stuff 2006-08-25 17:34:03 +02:00
afa8b3bcd9 switching to dark colors again 2006-08-25 17:31:57 +02:00
c518345f40 updated man page of dwm 2006-08-25 16:21:45 +02:00
afe6ac9923 changed order of options 2006-08-25 16:15:13 +02:00
e995c1b532 trying a different configuration 2006-08-25 15:48:44 +02:00
e36929292e removed small 1px gap, somehow without it things feel better 2006-08-25 15:37:00 +02:00
03128f78df oops 2006-08-25 15:24:18 +02:00
7d4a5e654c fixed typo 2006-08-25 15:21:49 +02:00
41ba7a7984 s/TILED/TILE/g 2006-08-25 15:16:20 +02:00
aa471f2d65 removed a bunch of lines, made mode symbols configurable 2006-08-25 15:12:32 +02:00
d37dfa1bed changed symbols for float/tiled mode, added mouse-driven mode toggle to buttonpress() 2006-08-25 15:06:38 +02:00
9f35cc52fe small fix to separate client title from right-most tag 2006-08-25 14:46:01 +02:00
f1fe19bc2b restored config.arg.h 2006-08-25 13:02:07 +02:00
b55bd709ee new color stuff/new rendering stuff 2006-08-25 12:59:45 +02:00
9833610356 back to 3 colors 2006-08-25 07:54:49 +02:00
de7fc0011e fixed 2006-08-24 12:07:10 +02:00
2e0c767d74 3->4 colors 2006-08-24 12:04:56 +02:00
a5379e901c Added tag 1.0 for changeset bbc98e77ae89a7c9232a5be0835f60ea00d8036e 2006-08-24 10:28:50 +02:00
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
18 changed files with 1071 additions and 784 deletions

View File

@ -3,3 +3,9 @@ d31b5ad96b0ba7b5b0a30928fcf000428339a577 0.1
7e66082e5092fb0bccd18a3695a0bec52c80fdb2 0.3
eb3165734f00fe7f7da8aeebaed00e60a57caac9 0.4
22213b9a2114167ee8ba019a012e27da0422a61a 0.5
c11f86db4550cac5d0a648a3fe4d6d3b9a4fcf7e 0.6
3fb41412e2492f66476d92ce8f007a8b48fb1d2a 0.7
cd15de32e173f8ce97bfe1c9b6607937b59056b4 0.8
fae61afa861755636c4a1070694209ace8efbb6c 0.9
bbc98e77ae89a7c9232a5be0835f60ea00d8036e 1.0
44a55e6e46bf6c231780b09d919977d6f01083de 1.1

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,58 +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 "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 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

6
README
View File

@ -1,6 +1,6 @@
dwm - dynamic window manager
----------------------------
dwm is an extremely fast, small, and dynamic X11 window manager.
dwm is an extremely fast, small, and dynamic window manager for X.
Requirements
@ -16,7 +16,6 @@ the /usr/local namespace by default).
Afterwards enter the following command to build and install dwm (if
necessary as root):
cp config.default.h config.h
make clean install
@ -45,4 +44,5 @@ like this in your .xinitrc:
Configuration
-------------
The configuration of dwm is done by editing config.h.
The configuration of dwm is done by creating a custom config.h
and (re)compiling the source code.

235
client.c
View File

@ -10,24 +10,57 @@
/* static functions */
static void
grabbuttons(Client *c, Bool focus)
{
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
if(focus) {
XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button1, MODKEY | numlockmask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button1, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY | numlockmask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY | numlockmask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
}
else
XGrabButton(dpy, AnyButton, AnyModifier, 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);
}
@ -43,62 +76,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;
grabbuttons(old, False);
drawtitle(old);
}
grabbuttons(c, True);
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)))
c = getnext(clients);
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 *
@ -118,7 +117,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;
}
@ -178,13 +177,6 @@ gravitate(Client *c, Bool invert)
c->y += dy;
}
void
higher(Client *c)
{
XRaiseWindow(dpy, c->win);
XRaiseWindow(dpy, c->title);
}
void
killclient(Arg *arg)
{
@ -196,21 +188,16 @@ killclient(Arg *arg)
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;
@ -221,8 +208,14 @@ manage(Window w, XWindowAttributes *wa)
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 = c->ty = bh;
c->y = bh;
c->proto = getproto(c->win);
XSelectInput(dpy, c->win,
@ -232,35 +225,34 @@ manage(Window w, XWindowAttributes *wa)
twa.background_pixmap = ParentRelative;
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);
grabbuttons(c, False);
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);
if(clients)
clients->prev = c;
c->next = clients;
clients = c;
XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
settags(c);
if(!c->isfloat)
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 */
XMapRaised(dpy, c->win);
XMapRaised(dpy, c->title);
if(c->tags[tsel])
XMapWindow(dpy, c->win);
XMapWindow(dpy, c->twin);
if(isvisible(c))
focus(c);
}
@ -269,7 +261,6 @@ 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) {
@ -286,10 +277,6 @@ resize(Client *c, Bool sizehints, Corner sticky)
if(c->maxh && c->h > c->maxh)
c->h = c->maxh;
}
if(c->x > right) /* might happen on restart */
c->x = right - c->w;
if(c->y > bottom)
c->y = bottom - c->h;
if(sticky == TopRight || sticky == BotRight)
c->x = right - c->w;
if(sticky == BotLeft || sticky == BotRight)
@ -394,8 +381,8 @@ togglemax(Arg *arg)
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;
@ -410,58 +397,30 @@ togglemax(Arg *arg)
void
unmanage(Client *c)
{
Client *tc;
Window trans;
XGrabServer(dpy);
XSetErrorHandler(xerrordummy);
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
XDestroyWindow(dpy, c->title);
XGetTransientForHint(dpy, c->win, &trans);
if(c->prev)
c->prev->next = c->next;
if(c->next)
c->next->prev = c->prev;
if(c == clients)
clients = c->next;
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
XDestroyWindow(dpy, c->twin);
detach(c);
if(sel == c) {
sel = getnext(c->next);
if(!sel)
sel = getprev(c->prev);
if(!sel)
sel = clients;
if(trans && (tc = getclient(trans)) && isvisible(tc))
sel = tc;
else
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;
if(!sel)
return;
if(sel == getnext(clients) && sel->next) {
if((c = getnext(sel->next)))
sel = c;
}
/* pop */
if(sel->prev)
sel->prev->next = sel->next;
if(sel->next)
sel->next->prev = sel->prev;
sel->prev = NULL;
if(clients)
clients->prev = sel;
sel->next = clients;
clients = sel;
arrange(NULL);
focus(sel);
}

View File

@ -3,71 +3,63 @@
* See LICENSE file for license details.
*/
enum { Tfnord, Tdev, Tnet, Twork, Tmisc, TLast };
#define TAGS \
char *tags[TLast] = { \
[Tfnord] = "fnord", \
[Tdev] = "dev", \
[Tnet] = "net", \
[Twork] = "work", \
[Tmisc] = "misc", \
};
const char *tags[] = { "dev", "work", "net", "fnord", NULL };
#define DEFMODE dotile /* dofloat */
#define DEFTAG Tdev
#define FONT "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*"
#define BGCOLOR "#0a2c2d"
#define FGCOLOR "#ddeeee"
#define BORDERCOLOR "#176164"
#define FLOATSYMBOL "><>"
#define TILESYMBOL "[]="
#define FONT "-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*"
#define SELBGCOLOR "#333366"
#define SELFGCOLOR "#eeeeee"
#define NORMBGCOLOR "#333333"
#define NORMFGCOLOR "#dddddd"
#define STATUSBGCOLOR "#222222"
#define STATUSFGCOLOR "#9999cc"
#define MODKEY Mod1Mask
#define NUMLOCKMASK Mod2Mask
#define MASTERW 52 /* percent */
#define MASTERW 60 /* percent */
#define KEYS \
const char *browse[] = { "firefox", NULL }; \
const char *gimp[] = { "gimp", NULL }; \
const char *term[] = { \
"urxvt", "-tr", "+sb", "-bg", "black", "-fg", "white", "-cr", "white", \
"-fn", "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*", NULL \
}; \
const char *xlock[] = { "xlock", NULL }; \
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_h, viewprev, { 0 } }, \
{ MODKEY, XK_j, focusnext, { 0 } }, \
{ MODKEY, XK_k, focusprev, { 0 } }, \
{ MODKEY, XK_l, viewnext, { 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 } }, \
/* modifier key function arguments */ \
{ MODKEY|ShiftMask, XK_Return, spawn, \
{ .cmd = "exec uxterm -bg '#111111' -fg '#eeeeee' -cr '#eeeeee' +sb -fn '"FONT"'" } }, \
{ MODKEY, XK_p, spawn, \
{ .cmd = "exec \"$(IFS=:; for dir in $PATH; do " \
"for file in \"$dir\"/*; do [ -x \"$file\" ] && echo \"${file##*/}\"; done; " \
"done | 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|ShiftMask, XK_4, tag, { .i = 3 } }, \
{ 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|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|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|ShiftMask, XK_q, quit, { 0 } }, \
};
#define RULES \
static Rule rule[] = { \
/* class:instance tags isfloat */ \
{ "Firefox.*", { [Tnet] = "net" }, False }, \
{ "Gimp.*", { 0 }, True}, \
{ "MPlayer.*", { 0 }, True}, \
{ "Acroread.*", { 0 }, True}, \
/* class:instance:title regex tags regex isfloat */ \
{ "Firefox.*", "net", False }, \
{ "Gimp.*", NULL, True}, \
{ "MPlayer.*", NULL, True}, \
{ "Acroread.*", NULL, True}, \
};

View File

@ -3,60 +3,62 @@
* See LICENSE file for license details.
*/
enum { Tfnord, Tdev, Tnet, Twork, Tmisc, TLast };
#define TAGS \
char *tags[TLast] = { \
[Tfnord] = "fnord", \
[Tdev] = "dev", \
[Tnet] = "net", \
[Twork] = "work", \
[Tmisc] = "misc", \
};
const char *tags[] = { "1", "2", "3", "4", "5", NULL };
#define DEFMODE dotile /* dofloat */
#define DEFTAG Tdev
#define FLOATSYMBOL "~"
#define TILESYMBOL "#"
#define FONT "fixed"
#define BGCOLOR "#666699"
#define FGCOLOR "#eeeeee"
#define BORDERCOLOR "#9999CC"
#define SELBGCOLOR "#666699"
#define SELFGCOLOR "#eeeeee"
#define NORMBGCOLOR "#333366"
#define NORMFGCOLOR "#cccccc"
#define STATUSBGCOLOR "#dddddd"
#define STATUSFGCOLOR "#222222"
#define MODKEY Mod1Mask
#define NUMLOCKMASK Mod2Mask
#define MASTERW 52 /* percent */
#define MASTERW 60 /* percent */
#define KEYS \
const char *term[] = { "xterm", NULL }; \
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_h, viewprev, { 0 } }, \
{ MODKEY, XK_j, focusnext, { 0 } }, \
{ MODKEY, XK_k, focusprev, { 0 } }, \
{ MODKEY, XK_l, viewnext, { 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 } }, \
/* 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 tags isfloat */ \
{ "Firefox.*", { [Tnet] = "net" }, False }, \
{ "Gimp.*", { 0 }, True}, \
/* class:instance:title regex tags regex isfloat */ \
{ "Firefox.*", "2", False }, \
{ "Gimp.*", NULL, True}, \
};

View File

@ -1,5 +1,5 @@
# dwm version
VERSION = 0.6
VERSION = 1.2
# Customize below to fit your system
@ -11,14 +11,15 @@ X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib
# includes and libs
INCS = -I/usr/lib -I${X11INC}
INCS = -I. -I/usr/include -I${X11INC}
LIBS = -L/usr/lib -lc -L${X11LIB} -lX11
# flags
CFLAGS = -O3 ${INCS} -DVERSION=\"${VERSION}\"
CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\"
LDFLAGS = ${LIBS}
#CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = -g ${LIBS}
# compiler
# compiler and linker
CC = cc
LD = ${CC}

126
draw.c
View File

@ -9,28 +9,8 @@
/* 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;
@ -42,25 +22,22 @@ textnw(char *text, unsigned int len)
}
static void
drawtext(const char *text, Bool invert, Bool border)
drawtext(const char *text, unsigned long col[ColLast], Bool highlight)
{
int x, y, w, h;
static char buf[256];
unsigned int len;
unsigned int len, olen;
XGCValues gcv;
XRectangle r = { dc.x, dc.y, dc.w, dc.h };
XSetForeground(dpy, dc.gc, invert ? dc.fg : dc.bg);
XSetForeground(dpy, dc.gc, col[ColBG]);
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
w = 0;
if(border)
drawborder();
if(!text)
return;
len = strlen(text);
w = 0;
olen = len = strlen(text);
if(len >= sizeof(buf))
len = sizeof(buf) - 1;
memcpy(buf, text, len);
@ -73,21 +50,32 @@ 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;
gcv.foreground = col[ColFG];
if(dc.font.set) {
XChangeGC(dpy, dc.gc, GCForeground | GCBackground, &gcv);
XmbDrawImageString(dpy, dc.drawable, dc.font.set, dc.gc,
x, y, buf, len);
XChangeGC(dpy, dc.gc, GCForeground, &gcv);
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);
XChangeGC(dpy, dc.gc, GCForeground | GCFont, &gcv);
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
}
if(highlight) {
r.x = dc.x + 2;
r.y = dc.y + 2;
r.width = r.height = 3;
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
}
}
@ -107,28 +95,36 @@ void
drawstatus()
{
int i, x;
Bool istile = arrange == dotile;
dc.x = dc.y = 0;
dc.w = bw;
drawtext(NULL, !istile, False);
dc.w = 0;
for(i = 0; i < TLast; i++) {
dc.x += dc.w;
for(i = 0; i < ntags; i++) {
dc.w = textw(tags[i]);
if(istile)
drawtext(tags[i], (i == tsel), True);
if(seltag[i])
drawtext(tags[i], dc.sel, sel && sel->tags[i]);
else
drawtext(tags[i], (i != tsel), True);
drawtext(tags[i], dc.norm, sel && sel->tags[i]);
dc.x += dc.w;
}
dc.w = bmw;
drawtext(arrange == dotile ? TILESYMBOL : FLOATSYMBOL, dc.status, False);
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, dc.status, False);
if((dc.w = dc.x - x) > bh) {
dc.x = x;
if(sel)
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);
XSync(dpy, False);
@ -137,33 +133,19 @@ drawstatus()
void
drawtitle(Client *c)
{
int i;
Bool istile = arrange == dotile;
if(c == sel) {
if(c == sel && issel) {
drawstatus();
XUnmapWindow(dpy, c->title);
XSetWindowBorder(dpy, c->win, dc.fg);
XUnmapWindow(dpy, c->twin);
XSetWindowBorder(dpy, c->win, dc.sel[ColBG]);
return;
}
XSetWindowBorder(dpy, c->win, dc.bg);
XMapWindow(dpy, c->title);
XSetWindowBorder(dpy, c->win, dc.norm[ColBG]);
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, dc.norm, False);
XCopyArea(dpy, dc.drawable, c->twin, dc.gc, 0, 0, c->tw, c->th, 0, 0);
XSync(dpy, False);
}
@ -229,7 +211,7 @@ setfont(const char *fontstr)
}
unsigned int
textw(char *text)
textw(const char *text)
{
return textnw(text, strlen(text)) + dc.font.height;
}

160
dwm.1
View File

@ -1,4 +1,4 @@
.TH DWM 1 dwm-0.6
.TH DWM 1 dwm-VERSION
.SH NAME
dwm \- dynamic window manager
.SH SYNOPSIS
@ -6,61 +6,93 @@ 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
has 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 mode, the
title of the focused window, and the text read from standard input. The tags of
the focused window are highlighted with a small point.
.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 ,
click on the mode label toggles between
.B tiled
and
.B floating
mode.
.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-h
Focus previous
.B tag
.TP
.B Mod1-j
Focus next
.B window
.TP
.B Mod1-k
Focus previous
.B window
.TP
.B Mod1-l
Focus next
.B tag
.RB ( tiling
mode only).
.TP
.B Mod1-m
Maximize current
.B window
.BR window .
.TP
.B Mod1-[0..n]
Focus
.B Mod1-Shift-[0..n]
Apply
.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
@ -68,42 +100,56 @@ Toggle between
and
.B floating
mode (affects
.BR "all windows" )
.BR "all windows" ).
.TP
.B Mod1-Shift-[0..n]
Apply
.B nth tag
to current
.B window
.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-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 by editing the file config.h of the source code.
This keeps it fast, secure and simple.
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)

78
dwm.h
View File

@ -11,15 +11,10 @@
#define MOUSEMASK (BUTTONMASK | PointerMotionMask)
#define PROTODELWIN 1
typedef union Arg Arg;
typedef struct Client Client;
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 };
@ -28,51 +23,57 @@ enum { WMProtocols, WMDelete, WMLast };
/* cursor */
enum { CurNormal, CurResize, CurMove, CurLast };
/* windowcorners */
/* color */
enum { ColFG, ColBG, ColLast };
/* 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;
unsigned long border;
unsigned long norm[ColLast];
unsigned long sel[ColLast];
unsigned long status[ColLast];
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;
long flags;
unsigned int border;
unsigned int border, weight;
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 bx, by, bw, bh, bmw, mw, screen, sx, sy, sw, sh;
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;
@ -82,21 +83,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();
@ -104,10 +100,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);
@ -116,19 +113,28 @@ 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 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 viewnext(Arg *arg);
extern void viewprev(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 detach(Client *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.
@ -88,18 +89,23 @@
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-0.5.tar.gz">dwm 0.5</a> (13kb) (20060721)</li>
<li><a href="http://10kloc.org/download/dwm-1.2.tar.gz">dwm 1.2</a> (15kb) (20060830)</li>
<li><a href="http://10kloc.org/download/dmenu-0.6.tar.gz">dmenu 0.6</a> (7kb) (20060828)</li>
</ul>
<h3>Development</h3>
<p>
@ -108,11 +114,14 @@
<p>
<code>hg clone http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm</code>
</p>
<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 (20060801)</small></p>
<p><small>--Anselm</small></p>
</body>
</html>

170
event.c
View File

@ -18,7 +18,7 @@ typedef struct {
KEYS
#define CLEANMASK(mask) (mask & ~(NUMLOCKMASK | LockMask))
#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
static void
movemouse(Client *c)
@ -58,6 +58,7 @@ static void
resizemouse(Client *c)
{
int ocx, ocy;
int nw, nh;
Corner sticky;
XEvent ev;
@ -76,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)
@ -102,42 +105,41 @@ 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:
viewnext(&a);
break;
case Button5:
viewprev(&a);
break;
}
if(ev->x < x + bmw) {
if(ev->button == Button1)
togglemode(NULL);
}
}
else if((c = getclient(ev->window))) {
focus(c);
if(CLEANMASK(ev->state) != MODKEY)
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;
@ -145,33 +147,50 @@ buttonpress(XEvent *e)
}
}
static void
synconfig(Client *c, int x, int y, int w, int h, unsigned int border)
{
XEvent synev;
synev.type = ConfigureNotify;
synev.xconfigure.display = dpy;
synev.xconfigure.event = c->win;
synev.xconfigure.window = c->win;
synev.xconfigure.x = x;
synev.xconfigure.y = y;
synev.xconfigure.width = w;
synev.xconfigure.height = h;
synev.xconfigure.border_width = border;
synev.xconfigure.above = None;
XSendEvent(dpy, c->win, True, NoEventMask, &synev);
}
static void
configurerequest(XEvent *e)
{
unsigned long newmask;
Client *c;
XConfigureRequestEvent *ev = &e->xconfigurerequest;
XEvent synev;
XWindowChanges wc;
unsigned long newmask;
if((c = getclient(ev->window))) {
gravitate(c, True);
if(c->isfloat) {
if(ev->value_mask & CWX)
c->x = ev->x;
if(ev->value_mask & CWY)
c->y = ev->y;
if(ev->value_mask & CWWidth)
c->w = ev->width;
if(ev->value_mask & CWHeight)
c->h = ev->height;
if(!c->isfloat && (arrange != dofloat) && c->ismax) {
synconfig(c, sx, sy + bh, sw - 2, sh - 2 - bh, ev->border_width);
XSync(dpy, False);
return;
}
gravitate(c, True);
if(ev->value_mask & CWX)
c->x = ev->x;
if(ev->value_mask & CWY)
c->y = ev->y;
if(ev->value_mask & CWWidth)
c->w = ev->width;
if(ev->value_mask & CWHeight)
c->h = ev->height;
if(ev->value_mask & CWBorderWidth)
c->border = ev->border_width;
gravitate(c, False);
resize(c, True, TopLeft);
wc.x = c->x;
wc.y = c->y;
wc.width = c->w;
@ -179,20 +198,13 @@ configurerequest(XEvent *e)
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);
}
else
synconfig(c, c->x, c->y, c->w, c->h, c->border);
XSync(dpy, False);
if(c->isfloat)
resize(c, False, TopLeft);
else
arrange(NULL);
}
else {
wc.x = ev->x;
@ -203,8 +215,8 @@ configurerequest(XEvent *e)
wc.sibling = ev->above;
wc.stack_mode = ev->detail;
XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
XSync(dpy, False);
}
XSync(dpy, False);
}
static void
@ -223,13 +235,16 @@ enternotify(XEvent *e)
Client *c;
XCrossingEvent *ev = &e->xcrossing;
if(ev->detail == NotifyInferior)
if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
return;
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
@ -255,13 +270,15 @@ keypress(XEvent *e)
XKeyEvent *ev = &e->xkey;
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
for(i = 0; i < len; i++)
for(i = 0; i < len; i++) {
if(keysym == key[i].keysym &&
CLEANMASK(key[i].mod) == CLEANMASK(ev->state)) {
CLEANMASK(key[i].mod) == CLEANMASK(ev->state))
{
if(key[i].func)
key[i].func(&key[i].arg);
return;
}
}
}
static void
@ -269,8 +286,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
@ -345,6 +374,7 @@ void (*handler[LASTEvent]) (XEvent *) = {
[LeaveNotify] = leavenotify,
[Expose] = expose,
[KeyPress] = keypress,
[MappingNotify] = mappingnotify,
[MapRequest] = maprequest,
[PropertyNotify] = propertynotify,
[UnmapNotify] = unmapnotify
@ -357,23 +387,29 @@ grabkeys()
unsigned int i;
KeyCode code;
XUngrabKey(dpy, AnyKey, AnyModifier, root);
for(i = 0; i < len; i++) {
code = XKeysymToKeycode(dpy, key[i].keysym);
/* normal */
XUngrabKey(dpy, code, key[i].mod, root);
XGrabKey(dpy, code, key[i].mod, root, True,
GrabModeAsync, GrabModeAsync);
/* capslock */
XUngrabKey(dpy, code, key[i].mod | LockMask, root);
XGrabKey(dpy, code, key[i].mod | LockMask, root, True,
GrabModeAsync, GrabModeAsync);
/* numlock */
XUngrabKey(dpy, code, key[i].mod | NUMLOCKMASK, root);
XGrabKey(dpy, code, key[i].mod | NUMLOCKMASK, root, True,
XGrabKey(dpy, code, key[i].mod | numlockmask, root, True,
GrabModeAsync, GrabModeAsync);
/* capslock & numlock */
XUngrabKey(dpy, code, key[i].mod | NUMLOCKMASK | LockMask, root);
XGrabKey(dpy, code, key[i].mod | NUMLOCKMASK | LockMask, root, True,
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

@ -11,22 +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 bx, by, bw, bh, bmw, mw, screen, sx, sy, sw, sh;
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
@ -36,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))
@ -50,23 +78,81 @@ 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.norm[ColBG] = getcolor(NORMBGCOLOR);
dc.norm[ColFG] = getcolor(NORMFGCOLOR);
dc.sel[ColBG] = getcolor(SELBGCOLOR);
dc.sel[ColFG] = getcolor(SELFGCOLOR);
dc.status[ColBG] = getcolor(STATUSBGCOLOR);
dc.status[ColFG] = getcolor(STATUSFGCOLOR);
setfont(FONT);
bmw = textw(FLOATSYMBOL) > textw(TILESYMBOL) ? textw(FLOATSYMBOL) : textw(TILESYMBOL);
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 + 2;
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);
}
/*
@ -82,36 +168,22 @@ xerrorstart(Display *dsply, XErrorEvent *ee)
/* extern */
char stext[1024];
int tsel = DEFTAG;
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 |= PROTODELWIN;
}
free((char *) protocols);
free(protocols);
return protos;
}
@ -133,7 +205,7 @@ sendevent(Window w, Atom a, long value)
void
quit(Arg *arg)
{
running = False;
readin = running = False;
}
/*
@ -160,13 +232,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);
@ -177,96 +244,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)
@ -276,8 +290,10 @@ main(int argc, char *argv[])
drawstatus();
}
}
else if(r < 0)
eprint("select failed\n");
procevent();
}
cleanup();
XCloseDisplay(dpy);

226
tag.c
View File

@ -5,213 +5,147 @@
#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;
typedef struct {
regex_t *clregex;
regex_t *tregex;
} RReg;
/* static */
TAGS
RULES
void (*arrange)(Arg *) = DEFMODE;
static RReg *rreg = NULL;
static unsigned int len = 0;
static void
commit()
{
/* asserts sel != NULL */
settitle(sel);
if(!isvisible(sel))
arrange(NULL);
else
drawstatus();
}
/* 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))) {
higher(sel);
focus(sel);
}
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
}
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->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;
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 || (sel && !sel->tags[tsel])) {
if((sel = getnext(clients))) {
higher(sel);
focus(sel);
}
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
}
drawall();
}
Client *
getnext(Client *c)
{
for(; c && !c->tags[tsel]; 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];
for(i = 0; i < ntags && !c->tags[i]; i++);
c->weight = 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;
commit();
}
void
view(Arg *arg)
toggletag(Arg *arg)
{
tsel = arg->i;
arrange(NULL);
drawall();
}
unsigned int i;
void
viewnext(Arg *arg)
{
arg->i = (tsel < TLast-1) ? tsel+1 : 0;
view(arg);
}
if(!sel)
return;
void
viewprev(Arg *arg)
{
arg->i = (tsel > 0) ? tsel-1 : TLast-1;
view(arg);
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;
commit();
}

34
util.c
View File

@ -9,14 +9,6 @@
#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 *
@ -25,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);
@ -39,20 +32,33 @@ 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;
/* the double-fork construct avoids zombie processes */
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);

289
view.c Normal file
View File

@ -0,0 +1,289 @@
/*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include "dwm.h"
#include <stdio.h>
/* static */
static Client *
minclient()
{
Client *c, *min;
for(min = c = clients; c; c = c->next)
if(c->weight < min->weight)
min = c;
return min;
}
static void
reorder()
{
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;
}
/* extern */
void (*arrange)(Arg *) = DEFMODE;
void
detach(Client *c)
{
if(c->prev)
c->prev->next = c->next;
if(c->next)
c->next->prev = c->prev;
if(c == clients)
clients = c->next;
c->next = c->prev = NULL;
}
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 = getnext(clients)))
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 = getnext(clients)))
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 */
reorder();
arrange(NULL);
}
void
view(Arg *arg)
{
unsigned int i;
for(i = 0; i < ntags; i++)
seltag[i] = False;
seltag[arg->i] = True;
reorder();
arrange(NULL);
}
void
zoom(Arg *arg)
{
Client *c = sel;
if(!c || (arrange != dotile) || c->isfloat || c->ismax)
return;
if(c == getnext(clients))
if(!(c = getnext(c->next)))
return;
detach(c);
c->next = clients;
clients->prev = c;
clients = c;
focus(c);
arrange(NULL);
}