Compare commits

...

258 Commits
3.2 ... 4.4

Author SHA1 Message Date
67a1141f44 removed unnecessary include, prepared dwm-4.4 2007-08-23 18:11:24 +02:00
8be3f3ec9e setlayout should perform strcmp's if arg != NULL, because Layout is local to screen.o 2007-08-22 19:06:35 +02:00
5762e92994 reverted release CFLAGs 2007-08-22 19:02:17 +02:00
36672d0401 removed the _DWM_PROPERTIES handling, reverted ban/unban to XMoveWindow(), and changed argument of setlayout to layout[N].symbol check 2007-08-22 19:01:05 +02:00
b18e684015 renamed char prop[] into buf[] 2007-08-19 18:50:47 +02:00
fc109ea8f7 fixed misappearance of iconified windows on SIGKILL 2007-08-19 18:39:54 +02:00
b975c47280 moved updatebarpos to screen 2007-08-19 11:00:47 +02:00
47765f7286 added screen.c, removed layout.c and tag.c 2007-08-19 10:57:02 +02:00
96d7fe16ea prepared merging layout.c and tag.c into screen.c 2007-08-19 10:40:07 +02:00
78d1a22d4e small fix 2007-08-19 10:13:24 +02:00
0c60620410 hmm I doubt the usefulness of storing this information... 2007-08-18 14:20:56 +02:00
50be6c8b67 cleaned up settags-handling 2007-08-18 13:48:05 +02:00
7d156dee1e applied Gottox mwfact patch 2007-08-18 11:40:25 +02:00
55d8dda9f4 replaced static Layout *lt with static unsigned int sellayout... (will be adapted later when _DWM_CONFIG is serialized as root window property) 2007-08-17 21:19:07 +02:00
86953bd682 renamed seltag into seltags 2007-08-17 21:12:55 +02:00
a923298d35 applied Jukka Salmi's setmwfact patch 2007-08-17 21:10:50 +02:00
04dec4c943 made plural arrays 2007-08-16 18:41:22 +02:00
e40448fd63 fixed the issue observed by various people, that clients appeared on empty tags 2007-08-16 18:30:25 +02:00
10bc0ce912 made tag/view/toggle{tag,view} work on pointer to tags-array, there was the need to define Key key[] not static to do this. split focusclient into focusnext/prev, fixed config.*.h's 2007-08-16 17:55:55 +02:00
e8792d95a1 applied Jukka's patch 2007-08-16 08:05:30 +02:00
feec92df84 fixed _DWM_CONFIG persistation, fixed the client disapperance bug during restarts 2007-08-15 19:31:41 +02:00
10d13f01ff fififi 2007-08-15 19:27:32 +02:00
8fcc4ff0ae fix of resize (thanks Sander for the hint!) 2007-08-14 19:38:10 +02:00
f2512243f4 fixed a typo 2007-08-14 07:54:51 +02:00
b32cd4454b small bugfix 2007-08-13 20:10:44 +02:00
9e56e1ded6 tags should be persistent now during X server run 2007-08-13 20:06:00 +02:00
e4ad320599 small bugfix 2007-08-13 19:22:51 +02:00
a200c39635 made tile simplier 2007-08-13 19:19:38 +02:00
77044e8765 made Layout a static struct in layout.c, added some convenience getters in layout.c, now lt->arrange accesses are not possible anymore, arrange() is the super-arrange function which sets up all layouts 2007-08-13 19:13:54 +02:00
2feb3afe78 made resize more precise 2007-08-13 18:24:15 +02:00
0937cc78bf moved floating to layout.c, kept tile.c outside 2007-08-12 13:10:21 +02:00
f6e41b0bc3 renamed MASTER into MWFACT, master into mwfact, and incmaster into addtomwfact 2007-08-12 12:46:08 +02:00
2c6087e3d2 fixed a comment 2007-08-11 14:44:11 +02:00
2d81b78b85 separated layout-specific stuff into separate .h and .c files which are included in config.h resp. config.mk - this allows writing layouts for dwm without any need to patch existing code 2007-08-11 12:11:50 +02:00
b5eea45a31 let not overlap the borders 2007-08-10 18:27:25 +02:00
aa53e39ec0 removed VRATIO, NMASTER, inc*(), renamed HRATIO into MASTER, see mailinglist for details 2007-08-10 18:16:05 +02:00
4216bf801f slight change of my color scheme 2007-08-05 17:37:40 +02:00
2cd1609770 removed spow(x, 0); calls, I did them for consistency's sake, but it should be rather obvious how the scaling works anyways 2007-08-05 16:00:08 +02:00
85c9ebf2fc applied Jukka's dwm.1 patch 2007-08-05 15:58:07 +02:00
796925089c changed shortcuts as described on the mailinglist, added sanity checks for ratios during tile (fallback to wah if clients would get too small), documented that new stuff/shortcuts in dwm(1) 2007-08-05 12:47:52 +02:00
da91dfc948 small fix of static function order 2007-08-04 10:57:56 +02:00
4135e34dfa I introduced {H,V}RATIO and inc{h,v,}ratio() functions - the default behaves like in dwm-4.3, config.arg.h shows how I prefer the ratio being handled (for the future I plan to change const char *arg into ..., and renaming Client into Win.) 2007-08-04 10:51:39 +02:00
846128a498 removed a C++ style comment 2007-08-03 19:29:58 +02:00
e461e60997 implemented ratio tile as described on the mailinglist 2007-08-03 19:23:30 +02:00
28c10330bd changed the fix of yesterday, the resize should only be necessary at manage() time, not on any unban() 2007-07-31 18:22:13 +02:00
0d40590c2c foo 2007-07-30 21:03:08 +02:00
8fda28be35 set client state to iconic on maprequest 2007-07-28 17:25:44 +02:00
a54cf2ecef changed ban/unban implementation to not move the windows anymore, but map/unmap them instead - PLEASE TEST THIS 2007-07-28 17:18:45 +02:00
4b9337a01e removed shiftview(), if you scroll the views in the tag area, you can also use Button1 instead
removed focusclient([-]1) bound to scroll wheel - if you slightly move the mouse you will focus the first client anways which is in the way
2007-07-28 12:58:56 +02:00
154497541d applied Jeroen's {clean,spell}.diff patches, thanks Jeroen! 2007-07-26 20:15:02 +02:00
e0cfe07648 applied Jeroen Schot's shiftview patch 2007-07-24 18:29:29 +02:00
82be289985 applied dwm-windowscrolling patch 2007-07-24 18:25:01 +02:00
f2190c8fc2 Added tag 4.3 for changeset e0ec0d5d8b1e 2007-07-14 21:14:15 +02:00
c31648d15d restoring tip to be a working dwm again (switching FONT to terminus in config.arg.h) 2007-07-12 19:45:28 +02:00
52250e7c1e please recheck this patch with Mathematica from Wolfram Research - lemme know if it fixes the geyish blob window bug 2007-06-19 09:08:15 +02:00
51a94a2f14 removed crappy createnotify handler 2007-06-19 09:04:21 +02:00
c95bf3db9d applied restack patch of anydot, with slight changes 2007-06-06 11:43:14 +02:00
4bf3b01953 I change the style of init somewhat, init as early as possible. 2007-06-06 11:17:56 +02:00
ff957d1eac uncommented creatnotify 2007-06-04 14:38:24 +02:00
83aa110c6f added an creatnotify event handler 2007-06-04 11:50:48 +02:00
5a1a2edf0e applied anudots [un]ban repair patch 2007-06-04 11:37:33 +02:00
b3419f49a3 making variable declarations in dwm.h extern, this seems to be more ansi compliant 2007-06-01 12:11:25 +02:00
141beb2704 replaced BORDERPX with sel->border in togglemax(), in other places this is not possible. 2007-05-30 20:49:38 +02:00
4e49d5a0ad Added tag 4.2 for changeset c13cb8c6b7a5 2007-05-30 12:22:29 +02:00
2c6be7239f referred to LICENSE file 2007-05-30 12:19:28 +02:00
d934296476 Jukka also belongs to Copyright holders after all he has contributed and done for dwm, updated -v as well 2007-05-30 12:10:01 +02:00
39ae286861 applied Jukkas patch 2007-05-30 08:57:44 +02:00
59e65d1709 changed -v output (now also anydot and nsz are contained in this output) 2007-05-29 13:53:08 +02:00
9fdd2cd1a9 added nsz to copyright holders as well, because he did a lot recently 2007-05-29 11:57:08 +02:00
e1deda9e04 added anydot to Copyright holders, because he contributed a lot recently 2007-05-29 11:47:55 +02:00
199a601611 applied anydot's 3 minor patches, thank you anydot 2007-05-29 11:35:20 +02:00
492c6f10fc applied Sanders patch 2007-05-28 15:05:47 +02:00
caa7ab5362 applied anydots proposal to let togglefloating restore fixed windows 2007-05-25 15:28:10 +02:00
f3e672efd8 fix if n < nmaster of remainer calculation for master windows 2007-05-24 16:25:09 +02:00
02d5dddc00 rev 900, cool 2007-05-24 15:55:28 +02:00
c789941bba fo 2007-05-24 15:53:48 +02:00
e45b3ced67 calculating the remainder for master and stack area correctly 2007-05-24 15:40:07 +02:00
5a9af492ae fixed issue reported by Christian Garbs 2007-05-24 11:35:32 +02:00
32563abe86 removed the only one and superfloues strncmp 2007-05-23 22:33:46 +02:00
70c7b432ea foo 2007-05-23 14:51:51 +02:00
69dfcaa317 reverted last change after Sander pointed out the original decision 2007-05-23 07:49:05 +02:00
6ee8e3e93b applied anydots remark of togglefloating() 2007-05-23 07:47:20 +02:00
8439369db9 applied Szabolcs proposal for zoom() as well 2007-05-22 11:29:59 +02:00
81658eaab3 applied Szabolcs proposal to simplify setlayout() 2007-05-22 11:29:04 +02:00
81aebf8cae Added tag 4.1 for changeset 00f4180df72b 2007-05-21 14:37:26 +02:00
fa32f02a43 no that change breaks fullscreen apps 2007-05-16 22:05:02 +02:00
598e22907e raise barwin in restack, that's the most elegant solution I think 2007-05-16 21:59:53 +02:00
1e826ddd3e simplification 2007-05-15 14:06:18 +02:00
a967d7f664 raising the barwin has no effect becasue of restack 2007-05-15 13:58:29 +02:00
ce450c5bf1 fix 2007-05-15 13:56:47 +02:00
8f5f7a5b5a barwindow raising 2007-05-15 13:56:06 +02:00
5ad2828c57 using BarTop as fallback if BARPOS is set to BarOff as default for toggling 2007-05-15 13:49:43 +02:00
b896b58d6d removed strip, added -s to LDFLAGS 2007-05-15 13:44:04 +02:00
fef6c5c66b added new Mod1-b functionality to dwm(1) 2007-05-15 13:42:07 +02:00
37e062b0ed another fix, call lt->arrange() in togglebar only 2007-05-15 13:36:04 +02:00
cf58091736 fixed bpos init 2007-05-15 13:23:51 +02:00
2aef8b9b4c made bar togglalble 2007-05-15 12:09:18 +02:00
d96307cbe4 thanks to Jukka 2007-05-14 16:24:01 +02:00
124866e269 added the GTK Save-As bug report to BUGS section of dwm(1) 2007-05-14 13:42:00 +02:00
ab3d6a7dfe applied dfenze cleanups, fixed some comments in dwm.h 2007-05-14 11:54:30 +02:00
c67dbb28e4 small fix of fix 2007-05-10 13:49:17 +02:00
b8bccb4ac5 fixed a potential security flaw 2007-05-10 13:47:44 +02:00
b6b2f584ec applied Maarten Maathuis recenter-patch for floating clients only requesting new width and height exceeding the screen space 2007-05-09 11:31:14 +02:00
f7bdb39d9e s/remain/remainder/ 2007-05-09 10:12:55 +02:00
ecd9c3e222 fixing remaining space calculation 2007-05-09 10:11:34 +02:00
216099d072 thanks to Juka to check -Wall ;) 2007-05-08 08:52:34 +02:00
fc2e3eae20 next version is 4.1 2007-05-07 13:14:55 +02:00
f9e7a33019 applied patch of Paul Liu to allow onthefly resizing due to xrandr changes 2007-05-07 13:12:41 +02:00
7c9fa2566f Added tag 4.0 for changeset 018c38468422 2007-04-19 09:26:44 +02:00
22399a3bc0 fixed the border issue for mplayer, ff is definately broken when using F11 (fullscreen mode) 2007-04-19 09:24:25 +02:00
ad2508f957 touch border 2007-04-19 08:53:40 +02:00
b078599833 set border at manage time 2007-04-18 21:11:46 +02:00
1e80207876 using pixelcarnage-monospace (proggyclean), because this is better to the eyes 2007-04-18 17:29:38 +02:00
464fc2cd18 changed border handling 2007-04-17 14:56:46 +02:00
be8d6d40f6 changing order of c->border restorage 2007-04-13 12:22:00 +02:00
f0c2353393 I used 2006 in other places as well 2007-04-13 11:41:39 +02:00
a730213c3b yet another fix of copyright compactisition 2007-04-13 11:40:09 +02:00
399993c6b5 making Copyright notices more compact 2007-04-13 11:32:38 +02:00
4d318060a2 next version will be 4.0, so don't expect it within the next days 2007-04-11 15:18:16 +02:00
540d5eed46 make also transients floating when we do not know the main window 2007-04-11 15:17:29 +02:00
7d071ce2bd Added tag 3.9 for changeset 55478328b242 2007-04-02 11:11:47 +02:00
93aeaa53c9 next version will be 3.9, but don't expect it this week 2007-03-29 15:18:30 +02:00
06f9f346e6 add an additional check in resize() to prevent a crash of dwm 2007-03-29 15:17:57 +02:00
5c48012ad2 Added tag 3.8 for changeset 2ea201354cf0 2007-03-05 11:54:59 +01:00
a686c9ccd2 we don't need to set the font all the time 2007-03-02 15:14:40 +01:00
9ca5c3b108 some changes to updatesizehints, I don't change the aspect ratio algorithm now - I can't think, it is a mess 2007-03-01 12:33:45 +01:00
bab5b1178d removed sendevent 2007-02-26 16:24:51 +01:00
ee8fb0c6e4 Escape -s in dwm.1 2007-02-26 10:47:11 +01:00
0d9d3e79e9 Added tag 3.7 for changeset baee494346e5 2007-02-24 15:41:05 +01:00
12280f0253 prepared 3.7, ready to rambo 2007-02-24 15:40:50 +01:00
a58731e835 removed an unnecessary newline 2007-02-24 14:08:27 +01:00
1df45593ed removed superfluous externs (except for tags, because tags is defined in the source) 2007-02-24 14:06:35 +01:00
2122e39ce1 replacing Mod1-i with Mod1-Shift-j, Mod1-d with Mod1-Shift-k 2007-02-23 13:37:55 +01:00
e70139428a oops, small bugfix in my config 2007-02-23 11:17:07 +01:00
3d1d75a224 default masterwidth should also be at 600 2007-02-23 11:13:57 +01:00
35f08f4231 changed order if h/l 2007-02-23 11:09:18 +01:00
0ea0343a63 well I agree to several people claiming h/j/k/l is the better default than Tab/S-Tab/g/s for focus and master resizing 2007-02-23 10:40:32 +01:00
338c083858 renamed untiled into floating, keeping tiled instead of tiling (afaik tiled sounds more correct) - English speakers convinced me 2007-02-22 22:10:16 +01:00
671442e89d hahaha, untiled and non-untiled sounded really cumbersome 2007-02-22 18:22:51 +01:00
8d111632f5 made Fnt an anonymous inner struct 2007-02-22 18:17:07 +01:00
fe5acb939a made Fnt an anonymous inner struct 2007-02-22 18:08:31 +01:00
cac492b0e9 nah, I don't want 640 as MASTERWIDTH 2007-02-22 17:58:45 +01:00
ef9b3e173c using MASTERWIDTH=640 and 32px steps by default (incmasterw()) 2007-02-22 17:52:45 +01:00
5a13632afb simplified focusclient() 2007-02-22 17:51:34 +01:00
587100873a renamed versatile into untiled 2007-02-22 17:43:41 +01:00
27b0595af7 merged focus{prev.next} into focusclient(1/-1) 2007-02-22 15:25:19 +01:00
12d5a26fd2 made dwm.h more tidy (thx Jukka for the zoom() hint) 2007-02-22 15:06:56 +01:00
89b7f1503e oops 2007-02-22 12:16:58 +01:00
5711609203 small bugfix 2007-02-22 12:15:48 +01:00
825b7c3eb1 fixed some issues due to the Arg->const char * transition 2007-02-22 12:00:02 +01:00
ba96131af0 restoring default keybindings as Sander complained 2007-02-22 11:45:03 +01:00
2c477cf661 replaced Arg union with const char *arg, seems cleaner to me, even if we need atoi() in some places 2007-02-22 11:42:08 +01:00
986ca73074 re-added xterm to config.default.h 2007-02-22 11:15:31 +01:00
288098893c removed button4/5-bindings for incnmaster on mode label - that is misleading 2007-02-22 11:09:44 +01:00
cb9607c284 fixed order of key bindings described in dwm.1 2007-02-22 11:06:37 +01:00
4bd4f421d3 status needs update even in togglemax() - since we got an indicator for this 2007-02-22 10:59:42 +01:00
84432e6b36 reusing drawsquare for client title, empty square before title means versatile window, filled square before title means versatile maximized window. 2007-02-22 10:57:19 +01:00
1a25414ace dwm draws a small caret before the client title if it's a versatile client 2007-02-22 10:52:57 +01:00
3171371498 nah grouped keybindings by context 2007-02-22 09:29:38 +01:00
92105e7862 fixed exit condition in togglemax() 2007-02-22 08:08:36 +01:00
6ee9f13457 fixing missing extern declars in dwm.h for {de,at}tach() 2007-02-22 08:02:04 +01:00
352cae4380 several changes, made togglemax extern and separated it from zoom() - moved zoom() and togglemax() into layout.c, changed void (*func)(Arg *) into void (*func)(Arg), changed default keybindings of focusnext/focusprev and incmasterw to h/j/k/l accordingly, made keys in config*h appear alphabetically (special keys first), renamed resizemaster into incmasterw, renamed MASTER into MASTERWIDTH 2007-02-22 07:59:13 +01:00
b3b58c08e4 just ignore the FD_ISSET check in main.c of xfd, just call XPending (which does the same afair) 2007-02-21 21:36:54 +01:00
204f0a340d optimizing background color of terminals 2007-02-21 17:00:06 +01:00
78666b99b8 using 333 as background, hey proggyclean is really good 2007-02-21 16:57:21 +01:00
0bdcf75e25 switching to 13pt proggyclean (this fits better my 1920x1200 resolution than 12pt terminus which is too small or 14pt terminus which is too fat) 2007-02-21 16:53:25 +01:00
f1009285d8 using smaller font 2007-02-21 16:47:53 +01:00
f76b3a4685 using a green selborder 2007-02-21 15:47:52 +01:00
84ae6e12eb reverting to bg 555 2007-02-21 13:31:04 +01:00
784659565a s/555/357/ for SELCOLOR 2007-02-21 13:29:02 +01:00
7ae0c198b3 switching to urxvtcd for the moment (the uxterm flicker makes me headaches, st is really highest prio now) 2007-02-21 13:24:37 +01:00
dc6623728d Added tag 3.6.1 for changeset 20ec6976cee1 2007-02-21 12:09:10 +01:00
7541f1ad49 creating 3.6.1 2007-02-21 12:08:18 +01:00
74cbbe5f35 reverted accidental removal of sx, sy 2007-02-21 11:49:06 +01:00
52f0b9e2e3 removed some global vars which should be static instead 2007-02-21 11:45:51 +01:00
29c26b88e7 moved focus{next,prev} and nexttiled from client.c to layout.c (because those are not client-specific), moved toggleversatile() from layout.c to client.c (because those are client-specific) 2007-02-21 11:39:57 +01:00
f196b71e4d cleaned up and commented the config.*.h 2007-02-21 11:30:52 +01:00
ab83872134 Added tag 3.6 for changeset 75b1b25fe0d7e29400baf30568153f668324928b 2007-02-21 11:05:27 +01:00
ad4962c7eb fixed quoting and a comment 2007-02-21 11:04:33 +01:00
d180ba418c renamed setfont to initfont, getcolor to initcolor 2007-02-20 13:56:21 +01:00
138b7fbd05 fixed order 2007-02-20 13:48:02 +01:00
e7508783e8 added draw.c again (except getcolor and setfont which are helpers in main.c) 2007-02-20 13:46:21 +01:00
f4d15b1fec separating drawsquare from drawtext, made drawtext extern 2007-02-20 13:40:31 +01:00
355beb53f0 rechecked with OpenBSD 2007-02-20 11:26:16 +01:00
8012fcf333 split screen.c into layout.c and tag.c (because the view is an implicit mixture of both) 2007-02-20 10:49:53 +01:00
6bc4556ebd using eprint instead of fputs 2007-02-19 21:17:54 +01:00
879241c05c replaced togglelayout with setlayout 2007-02-19 18:33:15 +01:00
3794c62945 changed some odering in config*.h 2007-02-19 18:19:43 +01:00
5a03daf47f renamed Client->versatile and Rule->versatile into Client->isversatile resp. Rule->isversatile 2007-02-19 17:18:24 +01:00
6d5f67a092 renames swim[ming] into versatile 2007-02-19 17:12:26 +01:00
cee56d3863 renamed floating into swimming (this does not clash with C naming conventions and fits better the fish symbol) - also in man page 2007-02-19 17:00:32 +01:00
7c4da24465 removed debug compile flags 2007-02-19 16:41:47 +01:00
cdbc84b9a8 introduced Layout struct 2007-02-19 16:40:36 +01:00
b2f895166a some more code polishing 2007-02-19 16:07:22 +01:00
ebe68f650a forgot an extern declaration 2007-02-19 16:04:38 +01:00
df9fd28f9a bugfix of transient handling 2007-02-19 15:57:08 +01:00
e9c49ddd7a removed procevent, more refactoring 2007-02-19 15:23:35 +01:00
f8415019d4 draw.c is useless (belongs to main.c now) 2007-02-19 15:17:31 +01:00
238dd5d2b1 renamed view.c into screen.c 2007-02-19 15:05:29 +01:00
64871a7045 renamed manage.c to view.c 2007-02-19 14:57:32 +01:00
2e95bc0413 renamed Rule members, renamed RReg into Regexps 2007-02-19 14:52:19 +01:00
4cdbd523e5 merged tag.c, view.c and tile.c to manage.c 2007-02-19 14:44:05 +01:00
b3d7e07f18 some more refactoring 2007-02-19 13:53:40 +01:00
30af19d442 added some new convenience functions 2007-02-19 13:42:39 +01:00
5d9146ff37 some more refactoring 2007-02-19 13:17:49 +01:00
5cc27f1b3c introduced tile.c, some refactoring of functions 2007-02-19 13:00:29 +01:00
39ed54a468 simplified configurerequest to a bare minimum, removed wrong ban() calls 2007-02-19 11:34:12 +01:00
b61f91361c fixed configurerequest according to Jukkas complains 2007-02-19 11:22:47 +01:00
3167373512 fixed configurerequest according to the problem Jukka reported 2007-02-19 11:03:27 +01:00
4cff744438 don't resize master if not in tiled mode 2007-02-19 10:51:11 +01:00
c3527bea57 removed useless space 2007-02-16 16:51:27 +01:00
de6695792a well, resize should be called in dofloat anyways ;) 2007-02-16 16:41:22 +01:00
6e22ccf7b1 removed ugly ban(), extended resize() that it only resets the size if necessary, added border_width commit to manage() 2007-02-16 16:38:40 +01:00
8a5f002c41 removed getnext/getprev, redundant 2007-02-16 10:20:34 +01:00
3ce8c9f338 added ban() which takes care than a banned window is not banned again... (this reduces the overall ConfigureNotify's to clients) 2007-02-14 14:01:12 +01:00
0d095ae2ff Added tag 3.5 for changeset 63ad05e7f9e1 2007-02-14 09:35:48 +01:00
2d7f59424c simplifying regexps in config samples 2007-02-14 09:31:23 +01:00
e256afe31e made for/if/else constructs more consistent, some code polishing 2007-02-14 09:09:18 +01:00
64cfebc5e7 made configurerequest more tidy 2007-02-14 08:14:41 +01:00
7a095d0ce2 I didn't knew of c->isfixed, that should fix Jukkas issue with gkrellm ;) 2007-02-13 22:53:58 +01:00
5052c538d9 making it more sure that transient checks will work in any case 2007-02-13 22:24:27 +01:00
22d8c6fd18 stupid me, one needs to set c->{x,y,w,h} in configurerequest obviously ;) 2007-02-13 14:59:58 +01:00
71857b87ee simplified configurerequest 2007-02-13 13:39:33 +01:00
6ba400ee0f yet another consistency fix of dwm 2007-02-12 17:20:51 +01:00
35e65ea640 I don't see any reason why we should select for input on override-redirect windows? 2007-02-12 16:41:46 +01:00
d0d986dd0e bugfix of bugfix (thx to Sander) 2007-02-12 14:20:47 +01:00
9685e7dbc2 fixed a bug 2007-02-12 13:04:29 +01:00
37f39afb8e during writing 2wm.1 I noticed some bugs in dwm.1 2007-02-12 11:42:32 +01:00
dc9f62f393 removing all EnterNotifys after resize 2007-02-12 10:21:26 +01:00
7055315725 added pointer warp on drop in resize 2007-02-12 10:19:52 +01:00
fd995dac78 pneubeck pointed out an obvious thing, that a second p = stext + strlen(stext) - 1 is unnecessary 2007-02-09 14:56:19 +01:00
e5765cdd84 treating acroread and mplayer floating by default 2007-02-09 11:58:37 +01:00
8d0e58f80b adapting John Grahor's patch to dwm-3.5 2007-02-09 09:54:08 +01:00
8fcd1bfda8 fixed copyright notice in Makefile 2007-02-08 14:09:52 +01:00
e39e697998 fixed order of Bool declarations 2007-02-08 13:39:33 +01:00
d2dd58eabd added TOPBAR option for making the bar appear what the user likes 2007-02-08 11:48:01 +01:00
c6fc6b173d next version is 3.5 2007-02-08 11:11:15 +01:00
4590d7877c making the bar appear at bottom 2007-02-08 11:08:40 +01:00
f577fe4e27 Added tag 3.4 for changeset 9ede7b2d2450 2007-02-07 12:42:35 +01:00
9ed5de00b6 removed debug flags 2007-02-07 12:37:21 +01:00
28ffff801b replaced getproto with a saner function, now old-school artifacts of WM times in the early 90s completely disappeared, no punned pointer warning anymore ;) 2007-02-07 12:37:06 +01:00
44ef3f5a07 yet another fix 2007-02-06 15:29:19 +01:00
dafbd0dcb0 simplification 2007-02-06 15:28:25 +01:00
2ddc78720a implemented aspect ratio support of windows 2007-02-06 15:22:13 +01:00
7ece30ebc0 made some changes more concistent 2007-02-05 11:19:46 +01:00
3d48f33025 got rid of LD (inspired by JGs patch to wmii) 2007-02-05 11:09:53 +01:00
19fd903d40 applied apm's patch proposal, getting rid of XDrawLines 2007-02-05 11:05:16 +01:00
5732e471ae Added tag 3.3 for changeset 0f91934037b0 2007-02-01 08:23:00 +01:00
042297b27b applied Sander's drop_bh patch 2007-01-31 20:08:55 +01:00
a5cb80b86c handling WM_STATE seems to make DnD in gtk/qt apps working, well let's handle this in dwm as well 2007-01-28 20:29:41 +01:00
7e98db251e regarding to http://plan9.bell-labs.com/sources/contrib/rsc/man.ps the BUGS section should appear after SEE ALSO section. 2007-01-26 12:41:15 +01:00
bced9077f9 renamed CAVEATS into BUGS 2007-01-26 12:31:57 +01:00
82fed986f9 Added tag 3.2.2 for changeset d3876aa79292 2007-01-25 10:05:02 +01:00
2c1db7ed35 prepared yet another hotfix release 2007-01-25 09:59:48 +01:00
ea4827a578 Added tag 3.2.1 for changeset f2cabc83a18f 2007-01-24 17:25:37 +01:00
55be4d6137 hotfix release 3.2.1 2007-01-24 17:25:30 +01:00
1f18466409 applied offscreen appearance hotfix 2007-01-24 17:24:55 +01:00
b65a1e3379 Added tag 3.2 for changeset 4ce65f61f01b 2007-01-24 12:12:29 +01:00
18 changed files with 1348 additions and 1174 deletions

15
.hgtags
View File

@ -31,3 +31,18 @@ c7f84f23ec5aef29988dcdc4ec22a7352ee8f58e 2.5.1
3a5910fac3ccb522a98aeeba7af7008530b25092 2.9
76b58d21ea98257c05565a3b9c850b9b26a32968 3.0
e1c8bef05e6e48df4f26471ea0712aa43ab9d949 3.1
4ce65f61f01b055fa6c2901c6d2527ef741aa4bf 3.2
f2cabc83a18f9b5b548159329ddd4dee904fa31f 3.2.1
d3876aa792923f9a95f7ad0c7f0134533404df35 3.2.2
0f91934037b04221ff5d1ba3a6c39c1ff26e3661 3.3
9ede7b2d2450537e750d5505789fbe63960e97e6 3.4
63ad05e7f9e1f4f1881fb02f529cb6c6ae81e693 3.5
75b1b25fe0d7e29400baf30568153f668324928b 3.6
20ec6976cee1fcfee0c2f354ae382ee3f9f68efa 3.6.1
baee494346e520f8dee2cee9491b8350064770d2 3.7
2ea201354cf016407ea93e1e390d1422940d29b0 3.8
55478328b2422c700c5404a774c85e77322f41a3 3.9
018c3846842291cb6c009dc087e7fe2f0ef53bea 4.0
00f4180df72b49aadb2933804fde4bfb33e5666d 4.1
c13cb8c6b7a56af74cc88346e71d2490470b546f 4.2
e0ec0d5d8b1ef3ee04a83c7c0fee5853aa2ac6a6 4.3

View File

@ -1,7 +1,10 @@
MIT/X Consortium License
(C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
(C)opyright MMVI-MMVII Sander van Dijk <a dot h dot vandijk at gmail dot com>
© 2006-2007 Anselm R. Garbe <garbeam at gmail dot com>
© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
© 2006-2007 Jukka Salmi <jukka at salmi dot ch>
© 2007 Premysl Hruby <dfenze at gmail dot com>
© 2007 Szabolcs Nagy <nszabolcs 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

@ -1,9 +1,9 @@
# dwm - dynamic window manager
# (C)opyright MMVII Anselm R. Garbe
# © 2006-2007 Anselm R. Garbe, Sander van Dijk
include config.mk
SRC = client.c draw.c event.c main.c tag.c util.c view.c
SRC += client.c draw.c event.c main.c screen.c util.c
OBJ = ${SRC:.c=.o}
all: options dwm
@ -13,7 +13,6 @@ options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
@echo "LD = ${LD}"
.c.o:
@echo CC $<
@ -26,9 +25,8 @@ config.h:
@cp config.default.h $@
dwm: ${OBJ}
@echo LD $@
@${LD} -o $@ ${OBJ} ${LDFLAGS}
@strip $@
@echo CC -o $@
@${CC} -o $@ ${OBJ} ${LDFLAGS}
clean:
@echo cleaning
@ -38,7 +36,7 @@ dist: clean
@echo creating dist tarball
@mkdir -p dwm-${VERSION}
@cp -R LICENSE Makefile README config.*.h config.mk \
dwm.1 dwm.h ${SRC} dwm-${VERSION}
dwm.1 dwm.h tile.h ${SRC} dwm-${VERSION}
@tar -cf dwm-${VERSION}.tar dwm-${VERSION}
@gzip dwm-${VERSION}.tar
@rm -rf dwm-${VERSION}
@ -50,7 +48,7 @@ install: all
@chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
@echo installing manual page to ${DESTDIR}${MANPREFIX}/man1
@mkdir -p ${DESTDIR}${MANPREFIX}/man1
@sed 's/VERSION/${VERSION}/g' < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
@sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1
uninstall:

355
client.c
View File

@ -1,17 +1,20 @@
/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
/* See LICENSE file for copyright and license details. */
#include "dwm.h"
#include <stdlib.h>
#include <string.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
/* static functions */
/* static */
static void
attachstack(Client *c) {
c->snext = stack;
stack = c;
}
static void
detachstack(Client *c) {
Client **tc;
for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext);
*tc = c->snext;
}
@ -53,42 +56,92 @@ grabbuttons(Client *c, Bool focused) {
GrabModeAsync, GrabModeSync, None, None);
}
static Bool
isprotodel(Client *c) {
int i, n;
Atom *protocols;
Bool ret = False;
if(XGetWMProtocols(dpy, c->win, &protocols, &n)) {
for(i = 0; !ret && i < n; i++)
if(protocols[i] == wmatom[WMDelete])
ret = True;
XFree(protocols);
}
return ret;
}
static void
setclientstate(Client *c, long state) {
long data[] = {state, None};
XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
PropModeReplace, (unsigned char *)data, 2);
}
static int
xerrordummy(Display *dsply, XErrorEvent *ee) {
return 0;
}
/* extern functions */
/* extern */
void
attach(Client *c) {
if(clients)
clients->prev = c;
c->next = clients;
clients = c;
}
void
ban(Client *c) {
if(c->isbanned)
return;
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
c->isbanned = True;
}
void
configure(Client *c) {
XEvent synev;
XConfigureEvent ce;
synev.type = ConfigureNotify;
synev.xconfigure.display = dpy;
synev.xconfigure.event = c->win;
synev.xconfigure.window = c->win;
synev.xconfigure.x = c->x;
synev.xconfigure.y = c->y;
synev.xconfigure.width = c->w;
synev.xconfigure.height = c->h;
synev.xconfigure.border_width = c->border;
synev.xconfigure.above = None;
XSendEvent(dpy, c->win, True, NoEventMask, &synev);
ce.type = ConfigureNotify;
ce.display = dpy;
ce.event = c->win;
ce.window = c->win;
ce.x = c->x;
ce.y = c->y;
ce.width = c->w;
ce.height = c->h;
ce.border_width = c->border;
ce.above = None;
ce.override_redirect = False;
XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce);
}
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
focus(Client *c) {
if(c && !isvisible(c))
return;
if((!c && selscreen) || (c && !isvisible(c)))
for(c = stack; c && !isvisible(c); c = c->snext);
if(sel && sel != c) {
grabbuttons(sel, False);
XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
}
if(c) {
detachstack(c);
c->snext = stack;
stack = c;
attachstack(c);
grabbuttons(c, True);
}
sel = c;
@ -103,30 +156,32 @@ focus(Client *c) {
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
}
Client *
getclient(Window w) {
Client *c;
for(c = clients; c; c = c->next)
if(c->win == w)
return c;
return NULL;
}
void
killclient(Arg *arg) {
killclient(const char *arg) {
XEvent ev;
if(!sel)
return;
if(sel->proto & PROTODELWIN)
sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]);
if(isprotodel(sel)) {
ev.type = ClientMessage;
ev.xclient.window = sel->win;
ev.xclient.message_type = wmatom[WMProtocols];
ev.xclient.format = 32;
ev.xclient.data.l[0] = wmatom[WMDelete];
ev.xclient.data.l[1] = CurrentTime;
XSendEvent(dpy, sel->win, False, NoEventMask, &ev);
}
else
XKillClient(dpy, sel->win);
}
void
manage(Window w, XWindowAttributes *wa) {
Client *c;
unsigned int i;
Client *c, *t = NULL;
Window trans;
Status rettrans;
XWindowChanges wc;
c = emallocz(sizeof(Client));
c->tags = emallocz(ntags * sizeof(Bool));
@ -135,84 +190,140 @@ manage(Window w, XWindowAttributes *wa) {
c->y = wa->y;
c->w = wa->width;
c->h = wa->height;
c->oldborder = wa->border_width;
if(c->w == sw && c->h == sh) {
c->border = 0;
c->x = sx;
c->y = sy;
c->border = wa->border_width;
}
else {
c->border = BORDERPX;
if(c->x < wax)
c->x = wax;
if(c->y < way)
c->y = way;
if(c->x + c->w + 2 * c->border > wax + waw)
c->x = wax + waw - c->w - 2 * c->border;
if(c->y + c->h + 2 * c->border > way + wah)
c->y = way + wah - c->h - 2 * c->border;
if(c->x < wax)
c->x = wax;
if(c->y < way)
c->y = way;
c->border = BORDERPX;
}
wc.border_width = c->border;
XConfigureWindow(dpy, w, CWBorderWidth, &wc);
XSetWindowBorder(dpy, w, dc.norm[ColBorder]);
configure(c); /* propagates border_width, if size doesn't change */
updatesizehints(c);
c->proto = getproto(c->win);
XSelectInput(dpy, c->win,
XSelectInput(dpy, w,
StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
XGetTransientForHint(dpy, c->win, &trans);
grabbuttons(c, False);
XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]);
updatetitle(c);
settags(c, getclient(trans));
if(!c->isfloat)
c->isfloat = trans || c->isfixed;
if(clients)
clients->prev = c;
c->next = clients;
c->snext = stack;
stack = clients = c;
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success))
for(t = clients; t && t->win != trans; t = t->next);
if(t)
for(i = 0; i < ntags; i++)
c->tags[i] = t->tags[i];
applyrules(c);
if(!c->isfloating)
c->isfloating = (rettrans == Success) || c->isfixed;
attach(c);
attachstack(c);
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); /* some windows require this */
ban(c);
XMapWindow(dpy, c->win);
if(isvisible(c))
focus(c);
arrange();
}
void
resize(Client *c, Bool sizehints) {
XWindowChanges wc;
resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
double dx, dy, max, min, ratio;
XWindowChanges wc;
if(sizehints) {
if(c->minay > 0 && c->maxay > 0 && (h - c->baseh) > 0 && (w - c->basew) > 0) {
dx = (double)(w - c->basew);
dy = (double)(h - c->baseh);
min = (double)(c->minax) / (double)(c->minay);
max = (double)(c->maxax) / (double)(c->maxay);
ratio = dx / dy;
if(max > 0 && min > 0 && ratio > 0) {
if(ratio < min) {
dy = (dx * min + dy) / (min * min + 1);
dx = dy * min;
w = (int)dx + c->basew;
h = (int)dy + c->baseh;
}
else if(ratio > max) {
dy = (dx * min + dy) / (max * max + 1);
dx = dy * min;
w = (int)dx + c->basew;
h = (int)dy + c->baseh;
}
}
}
if(c->minw && w < c->minw)
w = c->minw;
if(c->minh && h < c->minh)
h = c->minh;
if(c->maxw && w > c->maxw)
w = c->maxw;
if(c->maxh && h > c->maxh)
h = c->maxh;
if(c->incw)
c->w -= (c->w - c->basew) % c->incw;
w -= (w - c->basew) % c->incw;
if(c->inch)
c->h -= (c->h - c->baseh) % c->inch;
if(c->minw && c->w < c->minw)
c->w = c->minw;
if(c->minh && c->h < c->minh)
c->h = c->minh;
if(c->maxw && c->w > c->maxw)
c->w = c->maxw;
if(c->maxh && c->h > c->maxh)
c->h = c->maxh;
h -= (h - c->baseh) % c->inch;
}
if(c->w == sw && c->h == sh)
c->border = 0;
else
c->border = BORDERPX;
if(w <= 0 || h <= 0)
return;
/* offscreen appearance fixes */
if(c->x + c->w + 2 * c->border < sx)
c->x = sx;
if(c->y + c->h + 2 * c->border < sy)
c->y = sy;
if(c->x > sw)
c->x = sw - c->w - 2 * c->border;
if(c->y > sh)
c->y = sh - c->h - 2 * c->border;
wc.x = c->x;
wc.y = c->y;
wc.width = c->w;
wc.height = c->h;
wc.border_width = c->border;
XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc);
configure(c);
if(x > sw)
x = sw - w - 2 * c->border;
if(y > sh)
y = sh - h - 2 * c->border;
if(x + w + 2 * c->border < sx)
x = sx;
if(y + h + 2 * c->border < sy)
y = sy;
if(c->x != x || c->y != y || c->w != w || c->h != h) {
c->x = wc.x = x;
c->y = wc.y = y;
c->w = wc.width = w;
c->h = wc.height = h;
wc.border_width = c->border;
XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc);
configure(c);
XSync(dpy, False);
}
}
void
unban(Client *c) {
if(!c->isbanned)
return;
XMoveWindow(dpy, c->win, c->x, c->y);
c->isbanned = False;
}
void
unmanage(Client *c) {
XWindowChanges wc;
wc.border_width = c->oldborder;
/* The server grab construct avoids race conditions. */
XGrabServer(dpy);
XSetErrorHandler(xerrordummy);
XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
detach(c);
detachstack(c);
if(sel == c)
focus(NULL);
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
setclientstate(c, WithdrawnState);
free(c->tags);
free(c);
XSync(dpy, False);
XSetErrorHandler(xerror);
XUngrabServer(dpy);
arrange();
}
void
@ -227,6 +338,10 @@ updatesizehints(Client *c) {
c->basew = size.base_width;
c->baseh = size.base_height;
}
else if(c->flags & PMinSize) {
c->basew = size.min_width;
c->baseh = size.min_height;
}
else
c->basew = c->baseh = 0;
if(c->flags & PResizeInc) {
@ -245,56 +360,26 @@ updatesizehints(Client *c) {
c->minw = size.min_width;
c->minh = size.min_height;
}
else if(c->flags & PBaseSize) {
c->minw = size.base_width;
c->minh = size.base_height;
}
else
c->minw = c->minh = 0;
c->isfixed = (c->maxw && c->minw && c->maxh && c->minh &&
c->maxw == c->minw && c->maxh == c->minh);
if(c->flags & PAspect) {
c->minax = size.min_aspect.x;
c->maxax = size.max_aspect.x;
c->minay = size.min_aspect.y;
c->maxay = size.max_aspect.y;
}
else
c->minax = c->maxax = c->minay = c->maxay = 0;
c->isfixed = (c->maxw && c->minw && c->maxh && c->minh
&& c->maxw == c->minw && c->maxh == c->minh);
}
void
updatetitle(Client *c) {
char **list = NULL;
int n;
XTextProperty name;
name.nitems = 0;
c->name[0] = 0;
XGetTextProperty(dpy, c->win, &name, netatom[NetWMName]);
if(!name.nitems)
XGetWMName(dpy, c->win, &name);
if(!name.nitems)
return;
if(name.encoding == XA_STRING)
strncpy(c->name, (char *)name.value, sizeof c->name);
else {
if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
&& n > 0 && *list)
{
strncpy(c->name, *list, sizeof c->name);
XFreeStringList(list);
}
}
XFree(name.value);
}
void
unmanage(Client *c) {
Client *nc;
/* The server grab construct avoids race conditions. */
XGrabServer(dpy);
XSetErrorHandler(xerrordummy);
detach(c);
detachstack(c);
if(sel == c) {
for(nc = stack; nc && !isvisible(nc); nc = nc->snext);
focus(nc);
}
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
free(c->tags);
free(c);
XSync(dpy, False);
XSetErrorHandler(xerror);
XUngrabServer(dpy);
arrange();
if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
gettextprop(c->win, wmatom[WMName], c->name, sizeof c->name);
}

View File

@ -1,93 +1,96 @@
/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#define TAGS \
const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
/* See LICENSE file for copyright and license details. */
/* appearance */
#define BARPOS BarTop /* BarBot, BarOff */
#define BORDERPX 1
#define DEFMODE dotile /* dofloat */
#define FLOATSYMBOL "><>"
#define TILESYMBOL "[]="
#define FONT "-*-terminus-medium-r-*-*-14-*-*-*-*-*-*-*"
#define FONT "-*-terminus-medium-r-*-*-14-*-*-*-*-*-iso10646-*"
#define NORMBORDERCOLOR "#333"
#define NORMBGCOLOR "#222"
#define NORMFGCOLOR "#ccc"
#define SELBORDERCOLOR "#69c"
#define SELBORDERCOLOR "#59a"
#define SELBGCOLOR "#555"
#define SELFGCOLOR "#fff"
#define MASTER 600 /* per thousand */
#define MODKEY Mod1Mask
#define NMASTER 1 /* clients in master area */
#define SNAP 40 /* pixel */
#define KEYS \
static Key key[] = { \
/* modifier key function argument */ \
{ MODKEY|ShiftMask, XK_Return, spawn, \
{ .cmd = "exec uxterm -bg '#222' -fg '#eee' -cr '#eee' +sb -fn '"FONT"'" } }, \
{ MODKEY, XK_p, spawn, \
{ .cmd = "exe=\"$(lsx `echo $PATH | sed 's/:/ /g'` | sort -u " \
" | dmenu -fn '"FONT"' -nb '"NORMBGCOLOR"' -nf '"NORMFGCOLOR"' " \
"-sb '"SELBGCOLOR"' -sf '"SELFGCOLOR"')\" && exec $exe" } }, \
{ MODKEY, XK_j, focusnext, { 0 } }, \
{ MODKEY, XK_k, focusprev, { 0 } }, \
{ MODKEY, XK_Return, zoom, { 0 } }, \
{ MODKEY, XK_g, resizemaster, { .i = 15 } }, \
{ MODKEY, XK_s, resizemaster, { .i = -15 } }, \
{ MODKEY, XK_i, incnmaster, { .i = 1 } }, \
{ MODKEY, XK_d, incnmaster, { .i = -1 } }, \
{ MODKEY|ShiftMask, XK_0, tag, { .i = -1 } }, \
{ 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|ShiftMask, XK_6, tag, { .i = 5 } }, \
{ MODKEY|ShiftMask, XK_7, tag, { .i = 6 } }, \
{ MODKEY|ShiftMask, XK_8, tag, { .i = 7 } }, \
{ MODKEY|ShiftMask, XK_9, tag, { .i = 8 } }, \
{ 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|ControlMask|ShiftMask, XK_6, toggletag, { .i = 5 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_7, toggletag, { .i = 6 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_8, toggletag, { .i = 7 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_9, toggletag, { .i = 8 } }, \
{ MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \
{ MODKEY, XK_space, togglemode, { 0 } }, \
{ MODKEY|ShiftMask, XK_space, togglefloat, { 0 } }, \
{ MODKEY, XK_0, view, { .i = -1 } }, \
{ 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, XK_6, view, { .i = 5 } }, \
{ MODKEY, XK_7, view, { .i = 6 } }, \
{ MODKEY, XK_8, view, { .i = 7 } }, \
{ MODKEY, XK_9, view, { .i = 8 } }, \
{ 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|ControlMask, XK_6, toggleview, { .i = 5 } }, \
{ MODKEY|ControlMask, XK_7, toggleview, { .i = 6 } }, \
{ MODKEY|ControlMask, XK_8, toggleview, { .i = 7 } }, \
{ MODKEY|ControlMask, XK_9, toggleview, { .i = 8 } }, \
{ MODKEY|ShiftMask, XK_q, quit, { 0 } }, \
};
/* tagging */
#define TAGS \
const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
#define RULES \
static Rule rule[] = { \
/* class:instance:title regex tags regex isfloat */ \
{ "Firefox.*", "3", False }, \
{ "Gimp.*", NULL, True }, \
{ "MPlayer.*", NULL, True }, \
{ "Acroread.*", NULL, True }, \
static Rule rules[] = { \
/* class:instance:title regex tags regex isfloating */ \
{ "Firefox", "3", False }, \
{ "Gimp", NULL, True }, \
{ "MPlayer", NULL, True }, \
{ "Acroread", NULL, True }, \
};
/* layout(s) */
#include "tile.h"
#define LAYOUTS \
static Layout layouts[] = { \
/* symbol function */ \
{ "[]=", tile }, /* first entry is default */ \
{ "><>", floating }, \
};
#define MWFACT 0.6 /* master width factor [0.1 .. 0.9] */
#define SNAP 32 /* snap pixel */
/* key definitions */
#define MODKEY Mod1Mask
#define KEYS \
Key keys[] = { \
/* modifier key function argument */ \
{ MODKEY, XK_p, spawn, \
"exe=`dmenu_path | dmenu -fn '"FONT"' -nb '"NORMBGCOLOR"' -nf '"NORMFGCOLOR"'" \
" -sb '"SELBGCOLOR"' -sf '"SELFGCOLOR"'` && exec $exe" }, \
{ MODKEY|ShiftMask, XK_Return, spawn, \
"exec urxvtcd -tr -bg '#111' -fg '#eee' -cr '#eee' +sb -fn '"FONT"'" }, \
{ MODKEY, XK_space, setlayout, NULL }, \
{ MODKEY, XK_b, togglebar, NULL }, \
{ MODKEY, XK_j, focusnext, NULL }, \
{ MODKEY, XK_k, focusprev, NULL }, \
{ MODKEY, XK_h, setmwfact, "-0.05" }, \
{ MODKEY, XK_l, setmwfact, "+0.05" }, \
{ MODKEY, XK_m, togglemax, NULL }, \
{ MODKEY, XK_Return, zoom, NULL }, \
{ MODKEY|ShiftMask, XK_space, togglefloating, NULL }, \
{ MODKEY|ShiftMask, XK_c, killclient, NULL }, \
{ MODKEY, XK_0, view, NULL }, \
{ MODKEY, XK_1, view, tags[0] }, \
{ MODKEY, XK_2, view, tags[1] }, \
{ MODKEY, XK_3, view, tags[2] }, \
{ MODKEY, XK_4, view, tags[3] }, \
{ MODKEY, XK_5, view, tags[4] }, \
{ MODKEY, XK_6, view, tags[5] }, \
{ MODKEY, XK_7, view, tags[6] }, \
{ MODKEY, XK_8, view, tags[7] }, \
{ MODKEY, XK_9, view, tags[8] }, \
{ MODKEY|ControlMask, XK_1, toggleview, tags[0] }, \
{ MODKEY|ControlMask, XK_2, toggleview, tags[1] }, \
{ MODKEY|ControlMask, XK_3, toggleview, tags[2] }, \
{ MODKEY|ControlMask, XK_4, toggleview, tags[3] }, \
{ MODKEY|ControlMask, XK_5, toggleview, tags[4] }, \
{ MODKEY|ControlMask, XK_6, toggleview, tags[5] }, \
{ MODKEY|ControlMask, XK_7, toggleview, tags[6] }, \
{ MODKEY|ControlMask, XK_8, toggleview, tags[7] }, \
{ MODKEY|ControlMask, XK_9, toggleview, tags[8] }, \
{ MODKEY|ShiftMask, XK_0, tag, NULL }, \
{ MODKEY|ShiftMask, XK_1, tag, tags[0] }, \
{ MODKEY|ShiftMask, XK_2, tag, tags[1] }, \
{ MODKEY|ShiftMask, XK_3, tag, tags[2] }, \
{ MODKEY|ShiftMask, XK_4, tag, tags[3] }, \
{ MODKEY|ShiftMask, XK_5, tag, tags[4] }, \
{ MODKEY|ShiftMask, XK_6, tag, tags[5] }, \
{ MODKEY|ShiftMask, XK_7, tag, tags[6] }, \
{ MODKEY|ShiftMask, XK_8, tag, tags[7] }, \
{ MODKEY|ShiftMask, XK_9, tag, tags[8] }, \
{ MODKEY|ControlMask|ShiftMask, XK_1, toggletag, tags[0] }, \
{ MODKEY|ControlMask|ShiftMask, XK_2, toggletag, tags[1] }, \
{ MODKEY|ControlMask|ShiftMask, XK_3, toggletag, tags[2] }, \
{ MODKEY|ControlMask|ShiftMask, XK_4, toggletag, tags[3] }, \
{ MODKEY|ControlMask|ShiftMask, XK_5, toggletag, tags[4] }, \
{ MODKEY|ControlMask|ShiftMask, XK_6, toggletag, tags[5] }, \
{ MODKEY|ControlMask|ShiftMask, XK_7, toggletag, tags[6] }, \
{ MODKEY|ControlMask|ShiftMask, XK_8, toggletag, tags[7] }, \
{ MODKEY|ControlMask|ShiftMask, XK_9, toggletag, tags[8] }, \
{ MODKEY|ShiftMask, XK_q, quit, NULL }, \
};

View File

@ -1,15 +1,8 @@
/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#define TAGS \
const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
/* See LICENSE file for copyright and license details. */
/* appearance */
#define BARPOS BarTop /* BarBot, BarOff */
#define BORDERPX 1
#define DEFMODE dotile /* dofloat */
#define FLOATSYMBOL "><>"
#define TILESYMBOL "[]="
#define FONT "-*-fixed-medium-r-normal-*-13-*-*-*-*-*-*-*"
#define NORMBORDERCOLOR "#dddddd"
#define NORMBGCOLOR "#eeeeee"
@ -18,70 +11,84 @@ const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
#define SELBGCOLOR "#006699"
#define SELFGCOLOR "#ffffff"
#define MASTER 600 /* per thousand */
#define MODKEY Mod1Mask
#define NMASTER 1 /* clients in master area */
#define SNAP 20 /* pixel */
#define KEYS \
static Key key[] = { \
/* modifier key function argument */ \
{ 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_g, resizemaster, { .i = 15 } }, \
{ MODKEY, XK_s, resizemaster, { .i = -15 } }, \
{ MODKEY, XK_i, incnmaster, { .i = 1 } }, \
{ MODKEY, XK_d, incnmaster, { .i = -1 } }, \
{ MODKEY|ShiftMask, XK_0, tag, { .i = -1 } }, \
{ 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|ShiftMask, XK_6, tag, { .i = 5 } }, \
{ MODKEY|ShiftMask, XK_7, tag, { .i = 6 } }, \
{ MODKEY|ShiftMask, XK_8, tag, { .i = 7 } }, \
{ MODKEY|ShiftMask, XK_9, tag, { .i = 8 } }, \
{ 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|ControlMask|ShiftMask, XK_6, toggletag, { .i = 5 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_7, toggletag, { .i = 6 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_8, toggletag, { .i = 7 } }, \
{ MODKEY|ControlMask|ShiftMask, XK_9, toggletag, { .i = 8 } }, \
{ MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \
{ MODKEY, XK_space, togglemode, { 0 } }, \
{ MODKEY|ShiftMask, XK_space, togglefloat, { 0 } }, \
{ MODKEY, XK_0, view, { .i = -1 } }, \
{ 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, XK_6, view, { .i = 5 } }, \
{ MODKEY, XK_7, view, { .i = 6 } }, \
{ MODKEY, XK_8, view, { .i = 7 } }, \
{ MODKEY, XK_9, view, { .i = 8 } }, \
{ 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|ControlMask, XK_6, toggleview, { .i = 5 } }, \
{ MODKEY|ControlMask, XK_7, toggleview, { .i = 6 } }, \
{ MODKEY|ControlMask, XK_8, toggleview, { .i = 7 } }, \
{ MODKEY|ControlMask, XK_9, toggleview, { .i = 8 } }, \
{ MODKEY|ShiftMask, XK_q, quit, { 0 } }, \
};
/* tagging */
#define TAGS \
const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
/* 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 */ \
{ "Gimp.*", NULL, True }, \
static Rule rules[] = { \
/* class:instance:title regex tags regex isfloating */ \
{ "Gimp", NULL, True }, \
{ "MPlayer", NULL, True }, \
{ "Acroread", NULL, True }, \
};
/* layout(s) */
#include "tile.h"
#define LAYOUTS \
static Layout layouts[] = { \
/* symbol function */ \
{ "[]=", tile }, /* first entry is default */ \
{ "><>", floating }, \
};
#define MWFACT 0.6 /* master width factor [0.1 .. 0.9] */
#define SNAP 32 /* snap pixel */
/* key definitions */
#define MODKEY Mod1Mask
#define KEYS \
Key keys[] = { \
/* modifier key function argument */ \
{ MODKEY|ShiftMask, XK_Return, spawn, "exec xterm" }, \
{ MODKEY, XK_p, spawn, "exe=`dmenu_path | dmenu` && exec $exe" }, \
{ MODKEY, XK_space, setlayout, NULL }, \
{ MODKEY, XK_b, togglebar, NULL }, \
{ MODKEY, XK_j, focusnext, NULL }, \
{ MODKEY, XK_k, focusprev, NULL }, \
{ MODKEY, XK_h, setmwfact, "-0.05" }, \
{ MODKEY, XK_l, setmwfact, "+0.05" }, \
{ MODKEY, XK_m, togglemax, NULL }, \
{ MODKEY, XK_Return, zoom, NULL }, \
{ MODKEY|ShiftMask, XK_space, togglefloating, NULL }, \
{ MODKEY|ShiftMask, XK_c, killclient, NULL }, \
{ MODKEY, XK_0, view, NULL }, \
{ MODKEY, XK_1, view, tags[0] }, \
{ MODKEY, XK_2, view, tags[1] }, \
{ MODKEY, XK_3, view, tags[2] }, \
{ MODKEY, XK_4, view, tags[3] }, \
{ MODKEY, XK_5, view, tags[4] }, \
{ MODKEY, XK_6, view, tags[5] }, \
{ MODKEY, XK_7, view, tags[6] }, \
{ MODKEY, XK_8, view, tags[7] }, \
{ MODKEY, XK_9, view, tags[8] }, \
{ MODKEY|ControlMask, XK_1, toggleview, tags[0] }, \
{ MODKEY|ControlMask, XK_2, toggleview, tags[1] }, \
{ MODKEY|ControlMask, XK_3, toggleview, tags[2] }, \
{ MODKEY|ControlMask, XK_4, toggleview, tags[3] }, \
{ MODKEY|ControlMask, XK_5, toggleview, tags[4] }, \
{ MODKEY|ControlMask, XK_6, toggleview, tags[5] }, \
{ MODKEY|ControlMask, XK_7, toggleview, tags[6] }, \
{ MODKEY|ControlMask, XK_8, toggleview, tags[7] }, \
{ MODKEY|ControlMask, XK_9, toggleview, tags[8] }, \
{ MODKEY|ShiftMask, XK_0, tag, NULL }, \
{ MODKEY|ShiftMask, XK_1, tag, tags[0] }, \
{ MODKEY|ShiftMask, XK_2, tag, tags[1] }, \
{ MODKEY|ShiftMask, XK_3, tag, tags[2] }, \
{ MODKEY|ShiftMask, XK_4, tag, tags[3] }, \
{ MODKEY|ShiftMask, XK_5, tag, tags[4] }, \
{ MODKEY|ShiftMask, XK_6, tag, tags[5] }, \
{ MODKEY|ShiftMask, XK_7, tag, tags[6] }, \
{ MODKEY|ShiftMask, XK_8, tag, tags[7] }, \
{ MODKEY|ShiftMask, XK_9, tag, tags[8] }, \
{ MODKEY|ControlMask|ShiftMask, XK_1, toggletag, tags[0] }, \
{ MODKEY|ControlMask|ShiftMask, XK_2, toggletag, tags[1] }, \
{ MODKEY|ControlMask|ShiftMask, XK_3, toggletag, tags[2] }, \
{ MODKEY|ControlMask|ShiftMask, XK_4, toggletag, tags[3] }, \
{ MODKEY|ControlMask|ShiftMask, XK_5, toggletag, tags[4] }, \
{ MODKEY|ControlMask|ShiftMask, XK_6, toggletag, tags[5] }, \
{ MODKEY|ControlMask|ShiftMask, XK_7, toggletag, tags[6] }, \
{ MODKEY|ControlMask|ShiftMask, XK_8, toggletag, tags[7] }, \
{ MODKEY|ControlMask|ShiftMask, XK_9, toggletag, tags[8] }, \
{ MODKEY|ShiftMask, XK_q, quit, NULL }, \
};

View File

@ -1,8 +1,11 @@
# dwm version
VERSION = 3.2
VERSION = 4.4
# Customize below to fit your system
# additional layouts beside floating
SRC = tile.c
# paths
PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man
@ -16,7 +19,7 @@ LIBS = -L/usr/lib -lc -L${X11LIB} -lX11
# flags
CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\"
LDFLAGS = ${LIBS}
LDFLAGS = -s ${LIBS}
#CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = -g ${LIBS}
@ -27,4 +30,3 @@ LDFLAGS = ${LIBS}
# compiler and linker
CC = cc
LD = ${CC}

195
draw.c
View File

@ -1,16 +1,34 @@
/* (C)opyright MMIV-MMVII Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
/* See LICENSE file for copyright and license details. */
#include "dwm.h"
#include <stdio.h>
#include <string.h>
/* static */
static void
drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) {
int x;
XGCValues gcv;
XRectangle r = { dc.x, dc.y, dc.w, dc.h };
gcv.foreground = col[ColFG];
XChangeGC(dpy, dc.gc, GCForeground, &gcv);
x = (dc.font.ascent + dc.font.descent + 2) / 4;
r.x = dc.x + 1;
r.y = dc.y + 1;
if(filled) {
r.width = r.height = x + 1;
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
}
else if(empty) {
r.width = r.height = x;
XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
}
}
static Bool
isoccupied(unsigned int t)
{
isoccupied(unsigned int t) {
Client *c;
for(c = clients; c; c = c->next)
if(c->tags[t])
return True;
@ -28,14 +46,54 @@ textnw(const char *text, unsigned int len) {
return XTextWidth(dc.font.xfont, text, len);
}
static void
drawtext(const char *text, unsigned long col[ColLast], Bool filledsquare, Bool emptysquare) {
/* extern */
void
drawstatus(void) {
int i, x;
dc.x = dc.y = 0;
for(i = 0; i < ntags; i++) {
dc.w = textw(tags[i]);
if(seltags[i]) {
drawtext(tags[i], dc.sel);
drawsquare(sel && sel->tags[i], isoccupied(i), dc.sel);
}
else {
drawtext(tags[i], dc.norm);
drawsquare(sel && sel->tags[i], isoccupied(i), dc.norm);
}
dc.x += dc.w;
}
dc.w = blw;
drawtext(getsymbol(), dc.norm);
x = dc.x + dc.w;
dc.w = textw(stext);
dc.x = sw - dc.w;
if(dc.x < x) {
dc.x = x;
dc.w = sw - x;
}
drawtext(stext, dc.norm);
if((dc.w = dc.x - x) > bh) {
dc.x = x;
if(sel) {
drawtext(sel->name, dc.sel);
drawsquare(sel->ismax, sel->isfloating, dc.sel);
}
else
drawtext(NULL, dc.norm);
}
XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0);
XSync(dpy, False);
}
void
drawtext(const char *text, unsigned long col[ColLast]) {
int x, y, w, h;
static char buf[256];
unsigned int len, olen;
XGCValues gcv;
XRectangle r = { dc.x, dc.y, dc.w, dc.h };
XPoint pt[5];
XSetForeground(dpy, dc.gc, col[ColBG]);
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
@ -63,120 +121,11 @@ drawtext(const char *text, unsigned long col[ColLast], Bool filledsquare, Bool e
}
if(w > dc.w)
return; /* too long */
gcv.foreground = col[ColFG];
if(dc.font.set) {
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 | GCFont, &gcv);
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
}
x = (h + 2) / 4;
if(filledsquare) {
r.x = dc.x + 1;
r.y = dc.y + 1;
r.width = r.height = x + 1;
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
}
else if(emptysquare) {
pt[0].x = dc.x + 1;
pt[0].y = dc.y + 1;
pt[1].x = x;
pt[1].y = 0;
pt[2].x = 0;
pt[2].y = x;
pt[3].x = -x;
pt[3].y = 0;
pt[4].x = 0;
pt[4].y = -x;
XDrawLines(dpy, dc.drawable, dc.gc, pt, 5, CoordModePrevious);
}
}
/* extern */
void
drawstatus(void) {
int i, x;
dc.x = dc.y = 0;
for(i = 0; i < ntags; i++) {
dc.w = textw(tags[i]);
if(seltag[i])
drawtext(tags[i], dc.sel, sel && sel->tags[i], isoccupied(i));
else
drawtext(tags[i], dc.norm, sel && sel->tags[i], isoccupied(i));
dc.x += dc.w;
}
dc.w = bmw;
drawtext(arrange == dofloat ? FLOATSYMBOL : TILESYMBOL, dc.norm, False, False);
x = dc.x + dc.w;
dc.w = textw(stext);
dc.x = sw - dc.w;
if(dc.x < x) {
dc.x = x;
dc.w = sw - x;
}
drawtext(stext, dc.norm, False, False);
if((dc.w = dc.x - x) > bh) {
dc.x = x;
drawtext(sel ? sel->name : NULL, sel ? dc.sel : dc.norm, False, False);
}
XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0);
XSync(dpy, False);
}
unsigned long
getcolor(const char *colstr) {
Colormap cmap = DefaultColormap(dpy, screen);
XColor color;
if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
eprint("error, cannot allocate color '%s'\n", colstr);
return color.pixel;
}
void
setfont(const char *fontstr) {
char *def, **missing;
int i, n;
missing = NULL;
XSetForeground(dpy, dc.gc, col[ColFG]);
if(dc.font.set)
XFreeFontSet(dpy, dc.font.set);
dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
if(missing) {
while(n--)
fprintf(stderr, "missing fontset: %s\n", missing[n]);
XFreeStringList(missing);
}
if(dc.font.set) {
XFontSetExtents *font_extents;
XFontStruct **xfonts;
char **font_names;
dc.font.ascent = dc.font.descent = 0;
font_extents = XExtentsOfFontSet(dc.font.set);
n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
if(dc.font.ascent < (*xfonts)->ascent)
dc.font.ascent = (*xfonts)->ascent;
if(dc.font.descent < (*xfonts)->descent)
dc.font.descent = (*xfonts)->descent;
xfonts++;
}
}
else {
if(dc.font.xfont)
XFreeFont(dpy, dc.font.xfont);
dc.font.xfont = NULL;
if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)))
eprint("error, cannot load font: '%s'\n", fontstr);
dc.font.ascent = dc.font.xfont->ascent;
dc.font.descent = dc.font.xfont->descent;
}
dc.font.height = dc.font.ascent + dc.font.descent;
XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
else
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
}
unsigned int

126
dwm.1
View File

@ -1,29 +1,31 @@
.TH DWM 1 dwm-VERSION
.TH DWM 1 dwm\-VERSION
.SH NAME
dwm \- dynamic window manager
.SH SYNOPSIS
.B dwm
.RB [ \-v ]
.SH DESCRIPTION
dwm is a dynamic window manager for X. It manages windows in tiling and
floating modes. Either mode can be applied dynamically, optimizing the
dwm is a dynamic window manager for X. It manages windows in tiled and
floating layouts. Either layout 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 area. The master
area contains the windows which currently need most attention, whereas the
stacking area contains all other windows. In floating mode windows can be
In tiled layout windows are managed in a master and stacking area. The master
area contains the window which currently needs most attention, whereas the
stacking area contains all other windows. In floating layout windows can be
resized and moved freely. Dialog windows are always managed floating,
regardless of the mode applied.
regardless of the layout applied.
.P
Windows are grouped by tags. Each window can be tagged with one or multiple
tags. Selecting certain tags displays all windows with these tags.
.P
dwm contains a small status bar which displays all available tags, the mode,
the title of the focused window, and the text read from standard input. The
selected tags are indicated with a different color. The tags of the focused
window are indicated with a filled square in the top left corner. The tags
which are applied to one or more windows are indicated with an empty square in
the top left corner.
dwm contains a small status bar which displays all available tags, the layout,
the title of the focused window, and the text read from standard input. A
floating window is indicated with an empty square and a maximized
floating window is indicated with a filled square before the windows
title. The selected tags are indicated with a different color. The tags of
the focused window are indicated with a filled square in the top left
corner. The tags which are applied to one or more windows are indicated
with an empty square in the top left corner.
.P
dwm draws a small border around windows to indicate the focus state.
.SH OPTIONS
@ -37,101 +39,97 @@ prints version information to standard output, then exits.
is read and displayed in the status text area.
.TP
.B Button1
click on a tag label to display all windows with that tag, click on the mode
label toggles between tiling and floating mode.
click on a tag label to display all windows with that tag, click on the layout
label toggles between tiled and floating layout.
.TP
.B Button3
click on a tag label adds/removes all windows with that tag to/from the view.
.TP
.B Button4
click on the mode label increases the number of windows in the master area (tiling mode only).
.TP
.B Button5
click on the mode label decreases the number of windows in the master area (tiling mode only).
.TP
.B Mod1-Button1
.B Mod1\-Button1
click on a tag label applies that tag to the focused window.
.TP
.B Mod1-Button3
.B Mod1\-Button3
click on a tag label adds/removes that tag to/from the focused window.
.SS Keyboard commands
.TP
.B Mod1-Shift-Return
.B Mod1\-Shift\-Return
Start
.BR xterm (1).
.BR xterm.
.TP
.B Mod1-Tab
.B Mod1\-Return
Zooms/cycles current window to/from master area (tiled layout only).
.TP
.B Mod1\-b
Shows/hides the status bar.
.TP
.B Mod1\-h
Decreases the master area width about 5% (tiled layout only).
.TP
.B Mod1\-j
Focus next window.
.TP
.B Mod1-Shift-Tab
.B Mod1\-k
Focus previous window.
.TP
.B Mod1-Return
Zooms/cycles current window to/from master area (tiling mode), toggles maximization current window (floating mode).
.B Mod1\-l
Increases the master area width about 5% (tiled layout only).
.TP
.B Mod1-g
Grow master area (tiling mode only).
.B Mod1\-m
Toggles maximization of current window (floating layout only).
.TP
.B Mod1-s
Shrink master area (tiling mode only).
.TP
.B Mod1-i
Increase the number of windows in the master area (tiling mode only).
.TP
.B Mod1-d
Decrease the number of windows in the master area (tiling mode only).
.TP
.B Mod1-Shift-[1..n]
.B Mod1\-Shift\-[1..n]
Apply
.RB nth
tag to current window.
.TP
.B Mod1-Shift-0
.B Mod1\-Shift\-0
Apply all tags to current window.
.TP
.B Mod1-Control-Shift-[1..n]
.B Mod1\-Control\-Shift\-[1..n]
Add/remove
.B nth
tag to/from current window.
.TP
.B Mod1-Shift-c
.B Mod1\-Shift\-c
Close focused window.
.TP
.B Mod1-space
Toggle between tiling and floating mode (affects all windows).
.B Mod1\-space
Toggle between tiled and floating layout (affects all windows).
.TP
.B Mod1-Shift-space
Toggle focused window between floating and non-floating state (tiling mode only).
.B Mod1\-Shift\-space
Toggle focused window between tiled and floating state (tiled layout only).
.TP
.B Mod1-[1..n]
.B Mod1\-[1..n]
View all windows with
.BR nth
tag.
.TP
.B Mod1-0
.B Mod1\-0
View all windows with any tag.
.TP
.B Mod1-Control-[1..n]
.B Mod1\-Control\-[1..n]
Add/remove all windows with
.BR nth
tag to/from the view.
.TP
.B Mod1-Shift-q
.B Mod1\-Shift\-q
Quit dwm.
.SS Mouse commands
.TP
.B Mod1-Button1
Move current window while dragging (floating mode only).
.B Mod1\-Button1
Move current window while dragging (floating layout only).
.TP
.B Mod1-Button2
Zoom current window to the master area (tiling mode only).
.B Mod1\-Button2
Zooms/cycles current window to/from master area (tiled layout only).
.TP
.B Mod1-Button3
Resize current window while dragging (floating mode only).
.B Mod1\-Button3
Resize current window while dragging (floating layout only).
.SH CUSTOMIZATION
dwm is customized by creating a custom config.h and (re)compiling the source
code. This keeps it fast, secure and simple.
.SH CAVEATS
.SH SEE ALSO
.BR dmenu (1)
.SH BUGS
The status bar may display
.BR "EOF"
when dwm has been started by an X session manager like
@ -145,5 +143,11 @@ you can use JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or you
can set the following environment variable (to use the older Motif
backend instead):
.BR AWT_TOOLKIT=MToolkit .
.SH SEE ALSO
.BR dmenu (1)
.P
Recent GTK 2.10.9+ versions contain a broken
.BR Save\-As
file dialog implementation,
which requests to reconfigure its window size in an endless loop. However, its
window is still respondable during this state, so you can simply ignore the flicker
until a new GTK version appears, which will fix this bug, approximately
GTK 2.10.12+ versions.

157
dwm.h
View File

@ -1,5 +1,4 @@
/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
/* See LICENSE file for copyright and license details.
*
* dynamic window manager is designed like any other X client as well. It is
* driven through handling X events. In contrast to other X clients, a window
@ -24,9 +23,8 @@
*
* Keys and tagging rules are organized as arrays and defined in the config.h
* file. These arrays are kept static in event.o and tag.o respectively,
* because no other part of dwm needs access to them. The current mode is
* represented by the arrange() function pointer, which wether points to
* dofloat() or dotile().
* because no other part of dwm needs access to them. The current layout is
* represented by the lt pointer.
*
* To understand everything else, start reading main.c:main().
*/
@ -36,46 +34,23 @@
/* mask shorthands, used in event.c and client.c */
#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask)
/* other stuff used in different places */
#define PROTODELWIN 1
enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */
enum { WMProtocols, WMDelete, WMLast }; /* default atoms */
enum { BarTop, BarBot, BarOff }; /* bar position */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { ColBorder, ColFG, ColBG, ColLast }; /* color */
typedef union {
const char *cmd;
int i;
} Arg; /* argument type */
typedef struct {
int ascent;
int descent;
int height;
XFontSet set;
XFontStruct *xfont;
} Fnt;
typedef struct {
int x, y, w, h;
unsigned long norm[ColLast];
unsigned long sel[ColLast];
Drawable drawable;
Fnt font;
GC gc;
} DC; /* draw context */
enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */
enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */
typedef struct Client Client;
struct Client {
char name[256];
int proto;
int x, y, w, h;
int rx, ry, rw, rh; /* revert geometry */
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int minax, maxax, minay, maxay;
long flags;
unsigned int border;
Bool isfloat, isfixed, ismax;
unsigned int border, oldborder;
Bool isbanned, isfixed, ismax, isfloating;
Bool *tags;
Client *next;
Client *prev;
@ -83,17 +58,30 @@ struct Client {
Window win;
};
typedef struct {
int x, y, w, h;
unsigned long norm[ColLast];
unsigned long sel[ColLast];
Drawable drawable;
GC gc;
struct {
int ascent;
int descent;
int height;
XFontSet set;
XFontStruct *xfont;
} font;
} DC; /* draw context */
extern const char *tags[]; /* all tags */
extern char stext[256]; /* status text */
extern int bh, bmw; /* bar height, bar mode label width */
extern int screen, sx, sy, sw, sh; /* screen geometry */
extern int wax, way, wah, waw; /* windowarea geometry */
extern unsigned int master, nmaster; /* master percent, number of master clients */
extern unsigned int ntags, numlockmask; /* number of tags, dynamic lock mask */
extern unsigned int bh, blw, bpos; /* bar height, bar layout label width, bar position */
extern unsigned int ntags, numlockmask; /* number of tags, numlock mask */
extern void (*handler[LASTEvent])(XEvent *); /* event handler */
extern void (*arrange)(void); /* arrange function, indicates mode */
extern Atom wmatom[WMLast], netatom[NetLast];
extern Bool running, selscreen, *seltag; /* seltag is array of Bool */
extern Bool selscreen, *seltags; /* seltags is array of Bool */
extern Client *clients, *sel, *stack; /* global client list and stack */
extern Cursor cursor[CurLast];
extern DC dc; /* global draw context */
@ -101,57 +89,58 @@ extern Display *dpy;
extern Window root, barwin;
/* client.c */
extern void configure(Client *c); /* send synthetic configure event */
extern void focus(Client *c); /* focus c, c may be NULL */
extern Client *getclient(Window w); /* return client of w */
extern void killclient(Arg *arg); /* kill c nicely */
extern void manage(Window w, XWindowAttributes *wa); /* manage new client */
extern void resize(Client *c, Bool sizehints); /* resize c*/
extern void updatesizehints(Client *c); /* update the size hint variables of c */
extern void updatetitle(Client *c); /* update the name of c */
extern void unmanage(Client *c); /* destroy c */
void attach(Client *c); /* attaches c to global client list */
void ban(Client *c); /* bans c */
void configure(Client *c); /* send synthetic configure event */
void detach(Client *c); /* detaches c from global client list */
void focus(Client *c); /* focus c if visible && !NULL, or focus top visible */
void killclient(const char *arg); /* kill sel nicely */
void manage(Window w, XWindowAttributes *wa); /* manage new client */
void resize(Client *c, int x, int y,
int w, int h, Bool sizehints); /* resize with given coordinates c*/
void unban(Client *c); /* unbans c */
void unmanage(Client *c); /* unmanage c */
void updatesizehints(Client *c); /* update the size hint variables of c */
void updatetitle(Client *c); /* update the name of c */
/* draw.c */
extern void drawstatus(void); /* draw the bar */
extern unsigned long getcolor(const char *colstr); /* return color of colstr */
extern void setfont(const char *fontstr); /* set the font for DC */
extern unsigned int textw(const char *text); /* return the width of text in px*/
void drawstatus(void); /* draw the bar */
void drawtext(const char *text, unsigned long col[ColLast]); /* draw text */
unsigned int textw(const char *text); /* return the width of text in px*/
/* event.c */
extern void grabkeys(void); /* grab all keys defined in config.h */
extern void procevent(void); /* process pending X events */
void grabkeys(void); /* grab all keys defined in config.h */
/* main.c */
extern int getproto(Window w); /* return protocol mask of WMProtocols property of w */
extern void quit(Arg *arg); /* quit dwm nicely */
extern void sendevent(Window w, Atom a, long value); /* send synthetic event to w */
extern int xerror(Display *dsply, XErrorEvent *ee); /* dwm's X error handler */
Bool gettextprop(Window w, Atom atom,
char *text, unsigned int size); /* return text property, UTF-8 compliant */
void quit(const char *arg); /* quit dwm nicely */
int xerror(Display *dsply, XErrorEvent *ee); /* dwm's X error handler */
/* tag.c */
extern void initrregs(void); /* initialize regexps of rules defined in config.h */
extern Client *getnext(Client *c); /* returns next visible client */
extern Client *getprev(Client *c); /* returns previous visible client */
extern void settags(Client *c, Client *trans); /* sets tags of c */
extern void tag(Arg *arg); /* tags c with arg's index */
extern void toggletag(Arg *arg); /* toggles c tags with arg's index */
/* screen.c */
void applyrules(Client *c); /* applies rules to c */
void arrange(void); /* arranges all windows depending on the layout in use */
void compileregs(void); /* initialize regexps of rules defined in config.h */
void focusnext(const char *arg); /* focuses next visible client */
void focusprev(const char *arg); /* focuses prev visible client */
const char *getsymbol(void); /* returns symbol of enabled layout */
void initlayouts(void); /* initialize layout array */
Bool isarrange(void (*func)()); /* returns True if func is the layout function in use */
Bool isfloating(void); /* returns True if floating layout is enabled */
Bool isvisible(Client *c); /* returns True if client is visible */
Client *nexttiled(Client *c); /* returns tiled successor of c */
void restack(void); /* restores z layers of all clients */
void setlayout(const char *arg); /* sets layout, NULL means next layout */
void tag(const char *arg); /* tags sel with arg's index */
void togglebar(const char *arg); /* shows/hides the bar */
void togglefloating(const char *arg); /* toggles sel between floating/tiled state */
void togglemax(const char *arg); /* toggles maximization of floating client */
void toggletag(const char *arg); /* toggles sel tags with arg's index */
void toggleview(const char *arg); /* toggles the tag with arg's index (in)visible */
void updatebarpos(void); /* updates the bar position */
void view(const char *arg); /* views the tag with arg's index */
/* util.c */
extern void *emallocz(unsigned int size); /* allocates zero-initialized memory, exits on error */
extern void eprint(const char *errstr, ...); /* prints errstr and exits with 1 */
extern void spawn(Arg *arg); /* forks a new subprocess with to arg's cmd */
/* view.c */
extern void detach(Client *c); /* detaches c from global client list */
extern void dofloat(void); /* arranges all windows floating */
extern void dotile(void); /* arranges all windows tiled */
extern void focusnext(Arg *arg); /* focuses next visible client, arg is ignored */
extern void focusprev(Arg *arg); /* focuses previous visible client, arg is ignored */
extern void incnmaster(Arg *arg); /* increments nmaster with arg's index value */
extern Bool isvisible(Client *c); /* returns True if client is visible */
extern void resizemaster(Arg *arg); /* resizes the master percent with arg's index value */
extern void restack(void); /* restores z layers of all clients */
extern void togglefloat(Arg *arg); /* toggles focusesd client between floating/non-floating state */
extern void togglemode(Arg *arg); /* toggles global arrange function (dotile/dofloat) */
extern void toggleview(Arg *arg); /* toggles the tag with arg's index (in)visible */
extern void view(Arg *arg); /* views the tag with arg's index */
extern void zoom(Arg *arg); /* zooms the focused client to master area, arg is ignored */
void *emallocz(unsigned int size); /* allocates zero-initialized memory, exits on error */
void eprint(const char *errstr, ...); /* prints errstr and exits with 1 */
void spawn(const char *arg); /* forks a new subprocess with arg's cmd */

217
event.c
View File

@ -1,34 +1,39 @@
/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
/* See LICENSE file for copyright and license details. */
#include "dwm.h"
#include <stdlib.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
/* static */
typedef struct {
unsigned long mod;
KeySym keysym;
void (*func)(Arg *arg);
Arg arg;
void (*func)(const char *arg);
const char *arg;
} Key;
KEYS
#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
#define MOUSEMASK (BUTTONMASK | PointerMotionMask)
static Client *
getclient(Window w) {
Client *c;
for(c = clients; c && c->win != w; c = c->next);
return c;
}
static void
movemouse(Client *c) {
int x1, y1, ocx, ocy, di;
int x1, y1, ocx, ocy, di, nx, ny;
unsigned int dui;
Window dummy;
XEvent ev;
ocx = c->x;
ocy = c->y;
ocx = nx = c->x;
ocy = ny = c->y;
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurMove], CurrentTime) != GrabSuccess)
return;
@ -38,7 +43,6 @@ movemouse(Client *c) {
XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev);
switch (ev.type) {
case ButtonRelease:
resize(c, True);
XUngrabPointer(dpy, CurrentTime);
return;
case ConfigureRequest:
@ -48,17 +52,17 @@ movemouse(Client *c) {
break;
case MotionNotify:
XSync(dpy, False);
c->x = ocx + (ev.xmotion.x - x1);
c->y = ocy + (ev.xmotion.y - y1);
if(abs(wax + c->x) < SNAP)
c->x = wax;
else if(abs((wax + waw) - (c->x + c->w + 2 * c->border)) < SNAP)
c->x = wax + waw - c->w - 2 * c->border;
if(abs(way - c->y) < SNAP)
c->y = way;
else if(abs((way + wah) - (c->y + c->h + 2 * c->border)) < SNAP)
c->y = way + wah - c->h - 2 * c->border;
resize(c, False);
nx = ocx + (ev.xmotion.x - x1);
ny = ocy + (ev.xmotion.y - y1);
if(abs(wax + nx) < SNAP)
nx = wax;
else if(abs((wax + waw) - (nx + c->w + 2 * c->border)) < SNAP)
nx = wax + waw - c->w - 2 * c->border;
if(abs(way - ny) < SNAP)
ny = way;
else if(abs((way + wah) - (ny + c->h + 2 * c->border)) < SNAP)
ny = way + wah - c->h - 2 * c->border;
resize(c, nx, ny, c->w, c->h, False);
break;
}
}
@ -81,8 +85,10 @@ resizemouse(Client *c) {
XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev);
switch(ev.type) {
case ButtonRelease:
resize(c, True);
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
c->w + c->border - 1, c->h + c->border - 1);
XUngrabPointer(dpy, CurrentTime);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
return;
case ConfigureRequest:
case Expose:
@ -91,11 +97,11 @@ resizemouse(Client *c) {
break;
case MotionNotify:
XSync(dpy, False);
nw = ev.xmotion.x - ocx - 2 * c->border + 1;
c->w = nw > 0 ? nw : 1;
nh = ev.xmotion.y - ocy - 2 * c->border + 1;
c->h = nh > 0 ? nh : 1;
resize(c, True);
if((nw = ev.xmotion.x - ocx - 2 * c->border + 1) <= 0)
nw = 1;
if((nh = ev.xmotion.y - ocy - 2 * c->border + 1) <= 0)
nh = 1;
resize(c, c->x, c->y, nw, nh, True);
break;
}
}
@ -103,58 +109,46 @@ resizemouse(Client *c) {
static void
buttonpress(XEvent *e) {
int x;
Arg a;
unsigned int i, x;
Client *c;
XButtonPressedEvent *ev = &e->xbutton;
if(barwin == ev->window) {
x = 0;
for(a.i = 0; a.i < ntags; a.i++) {
x += textw(tags[a.i]);
for(i = 0; i < ntags; i++) {
x += textw(tags[i]);
if(ev->x < x) {
if(ev->button == Button1) {
if(ev->state & MODKEY)
tag(&a);
tag(tags[i]);
else
view(&a);
view(tags[i]);
}
else if(ev->button == Button3) {
if(ev->state & MODKEY)
toggletag(&a);
toggletag(tags[i]);
else
toggleview(&a);
toggleview(tags[i]);
}
return;
}
}
if(ev->x < x + bmw)
switch(ev->button) {
case Button1:
togglemode(NULL);
break;
case Button4:
a.i = 1;
incnmaster(&a);
break;
case Button5:
a.i = -1;
incnmaster(&a);
break;
}
if((ev->x < x + blw) && ev->button == Button1)
setlayout(NULL);
}
else if((c = getclient(ev->window))) {
focus(c);
if(CLEANMASK(ev->state) != MODKEY)
return;
if(ev->button == Button1 && (arrange == dofloat || c->isfloat)) {
if(ev->button == Button1 && (isfloating() || c->isfloating)) {
restack();
movemouse(c);
}
else if(ev->button == Button2)
zoom(NULL);
else if(ev->button == Button3 && (arrange == dofloat || c->isfloat) &&
!c->isfixed) {
else if(ev->button == Button3
&& (isfloating() || c->isfloating) && !c->isfixed)
{
restack();
resizemouse(c);
}
@ -163,40 +157,35 @@ buttonpress(XEvent *e) {
static void
configurerequest(XEvent *e) {
unsigned long newmask;
Client *c;
XConfigureRequestEvent *ev = &e->xconfigurerequest;
XWindowChanges wc;
if((c = getclient(ev->window))) {
c->ismax = False;
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;
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
configure(c);
XSync(dpy, False);
if(c->isfloat) {
resize(c, False);
if(!isvisible(c))
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
if(c->isfixed || c->isfloating || isfloating()) {
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->x + c->w) > sw && c->isfloating)
c->x = sw / 2 - c->w / 2; /* center in x direction */
if((c->y + c->h) > sh && c->isfloating)
c->y = sh / 2 - c->h / 2; /* center in y direction */
if((ev->value_mask & (CWX | CWY))
&& !(ev->value_mask & (CWWidth | CWHeight)))
configure(c);
if(isvisible(c))
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
}
else
arrange();
configure(c);
}
else {
wc.x = ev->x;
@ -207,7 +196,22 @@ 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
configurenotify(XEvent *e) {
XConfigureEvent *ev = &e->xconfigure;
if (ev->window == root && (ev->width != sw || ev->height != sh)) {
sw = ev->width;
sh = ev->height;
XFreePixmap(dpy, dc.drawable);
dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
XResizeWindow(dpy, barwin, sw, bh);
updatebarpos();
arrange();
}
}
@ -227,12 +231,11 @@ enternotify(XEvent *e) {
if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
return;
if((c = getclient(ev->window)) && isvisible(c))
if((c = getclient(ev->window)))
focus(c);
else if(ev->window == root) {
selscreen = True;
for(c = stack; c && !isvisible(c); c = c->snext);
focus(c);
focus(NULL);
}
}
@ -248,20 +251,20 @@ expose(XEvent *e) {
static void
keypress(XEvent *e) {
static unsigned int len = sizeof key / sizeof key[0];
KEYS
unsigned int len = sizeof keys / sizeof keys[0];
unsigned int i;
KeySym keysym;
XKeyEvent *ev = &e->xkey;
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
for(i = 0; i < len; i++) {
if(keysym == key[i].keysym
&& CLEANMASK(key[i].mod) == CLEANMASK(ev->state))
for(i = 0; i < len; i++)
if(keysym == keys[i].keysym
&& CLEANMASK(keys[i].mod) == CLEANMASK(ev->state))
{
if(key[i].func)
key[i].func(&key[i].arg);
if(keys[i].func)
keys[i].func(keys[i].arg);
}
}
}
static void
@ -290,11 +293,8 @@ maprequest(XEvent *e) {
if(!XGetWindowAttributes(dpy, ev->window, &wa))
return;
if(wa.override_redirect) {
XSelectInput(dpy, ev->window,
(StructureNotifyMask | PropertyChangeMask));
if(wa.override_redirect)
return;
}
if(!getclient(ev->window))
manage(ev->window, &wa);
}
@ -308,15 +308,11 @@ propertynotify(XEvent *e) {
if(ev->state == PropertyDelete)
return; /* ignore */
if((c = getclient(ev->window))) {
if(ev->atom == wmatom[WMProtocols]) {
c->proto = getproto(c->win);
return;
}
switch (ev->atom) {
default: break;
case XA_WM_TRANSIENT_FOR:
XGetTransientForHint(dpy, c->win, &trans);
if(!c->isfloat && (c->isfloat = (trans != 0)))
if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL)))
arrange();
break;
case XA_WM_NORMAL_HINTS:
@ -345,6 +341,7 @@ unmapnotify(XEvent *e) {
void (*handler[LASTEvent]) (XEvent *) = {
[ButtonPress] = buttonpress,
[ConfigureRequest] = configurerequest,
[ConfigureNotify] = configurenotify,
[DestroyNotify] = destroynotify,
[EnterNotify] = enternotify,
[LeaveNotify] = leavenotify,
@ -358,31 +355,21 @@ void (*handler[LASTEvent]) (XEvent *) = {
void
grabkeys(void) {
static unsigned int len = sizeof key / sizeof key[0];
KEYS
unsigned int len = sizeof keys / sizeof keys[0];
unsigned int i;
KeyCode code;
XUngrabKey(dpy, AnyKey, AnyModifier, root);
for(i = 0; i < len; i++) {
code = XKeysymToKeycode(dpy, key[i].keysym);
XGrabKey(dpy, code, key[i].mod, root, True,
code = XKeysymToKeycode(dpy, keys[i].keysym);
XGrabKey(dpy, code, keys[i].mod, root, True,
GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, key[i].mod | LockMask, root, True,
XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, key[i].mod | numlockmask, root, True,
XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True,
GrabModeAsync, GrabModeAsync);
XGrabKey(dpy, code, key[i].mod | numlockmask | LockMask, root, True,
XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True,
GrabModeAsync, GrabModeAsync);
}
}
void
procevent(void) {
XEvent ev;
while(XPending(dpy)) {
XNextEvent(dpy, &ev);
if(handler[ev.type])
(handler[ev.type])(&ev); /* call handler */
}
}

224
main.c
View File

@ -1,7 +1,4 @@
/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
/* See LICENSE file for copyright and license details. */
#include "dwm.h"
#include <errno.h>
#include <locale.h>
@ -14,15 +11,17 @@
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <X11/Xproto.h>
#include <X11/Xutil.h>
/* extern */
char stext[256];
Bool *seltag;
int bh, bmw, screen, sx, sy, sw, sh, wax, way, waw, wah;
unsigned int master, nmaster, ntags, numlockmask;
int screen, sx, sy, sw, sh, wax, way, waw, wah;
unsigned int bh, ntags;
unsigned int bpos = BARPOS;
unsigned int numlockmask = 0;
Atom wmatom[WMLast], netatom[NetLast];
Bool running = True;
Bool *seltags;
Bool selscreen = True;
Client *clients = NULL;
Client *sel = NULL;
@ -36,12 +35,13 @@ Window root, barwin;
static int (*xerrorxlib)(Display *, XErrorEvent *);
static Bool otherwm, readin;
static Bool running = True;
static void
cleanup(void) {
close(STDIN_FILENO);
while(stack) {
resize(stack, True);
unban(stack);
unmanage(stack);
}
if(dc.font.set)
@ -57,7 +57,76 @@ cleanup(void) {
XFreeCursor(dpy, cursor[CurMove]);
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
XSync(dpy, False);
free(seltag);
free(seltags);
}
static unsigned long
initcolor(const char *colstr) {
Colormap cmap = DefaultColormap(dpy, screen);
XColor color;
if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
eprint("error, cannot allocate color '%s'\n", colstr);
return color.pixel;
}
static void
initfont(const char *fontstr) {
char *def, **missing;
int i, n;
missing = NULL;
if(dc.font.set)
XFreeFontSet(dpy, dc.font.set);
dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
if(missing) {
while(n--)
fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]);
XFreeStringList(missing);
}
if(dc.font.set) {
XFontSetExtents *font_extents;
XFontStruct **xfonts;
char **font_names;
dc.font.ascent = dc.font.descent = 0;
font_extents = XExtentsOfFontSet(dc.font.set);
n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
if(dc.font.ascent < (*xfonts)->ascent)
dc.font.ascent = (*xfonts)->ascent;
if(dc.font.descent < (*xfonts)->descent)
dc.font.descent = (*xfonts)->descent;
xfonts++;
}
}
else {
if(dc.font.xfont)
XFreeFont(dpy, dc.font.xfont);
dc.font.xfont = NULL;
if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)))
eprint("error, cannot load font: '%s'\n", fontstr);
dc.font.ascent = dc.font.xfont->ascent;
dc.font.descent = dc.font.xfont->descent;
}
dc.font.height = dc.font.ascent + dc.font.descent;
}
static long
getstate(Window w) {
int format, status;
long result = -1;
unsigned char *p = NULL;
unsigned long n, extra;
Atom real;
status = XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
&real, &format, &n, &extra, (unsigned char **)&p);
if(status != Success)
return -1;
if(n != 0)
result = *p;
XFree(p);
return result;
}
static void
@ -69,11 +138,17 @@ scan(void) {
wins = NULL;
if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
for(i = 0; i < num; i++) {
if(!XGetWindowAttributes(dpy, wins[i], &wa)
|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
continue;
if(wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
manage(wins[i], &wa);
}
for(i = 0; i < num; i++) { /* now the transients */
if(!XGetWindowAttributes(dpy, wins[i], &wa))
continue;
if(wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
continue;
if(wa.map_state == IsViewable)
if(XGetTransientForHint(dpy, wins[i], &d1)
&& (wa.map_state == IsViewable || getstate(wins[i]) == IconicState))
manage(wins[i], &wa);
}
}
@ -92,6 +167,8 @@ setup(void) {
/* init atoms */
wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
wmatom[WMName] = XInternAtom(dpy, "WM_NAME", False);
wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
@ -101,60 +178,56 @@ setup(void) {
cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
/* init modifier map */
numlockmask = 0;
modmap = XGetModifierMapping(dpy);
for (i = 0; i < 8; i++) {
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))
if(modmap->modifiermap[i * modmap->max_keypermod + j]
== XKeysymToKeycode(dpy, XK_Num_Lock))
numlockmask = (1 << i);
}
}
XFreeModifiermap(modmap);
/* select for events */
wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
| EnterWindowMask | LeaveWindowMask;
| EnterWindowMask | LeaveWindowMask | StructureNotifyMask;
wa.cursor = cursor[CurNormal];
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
XSelectInput(dpy, root, wa.event_mask);
grabkeys();
initrregs();
compileregs();
for(ntags = 0; tags[ntags]; ntags++);
seltag = emallocz(sizeof(Bool) * ntags);
seltag[0] = True;
seltags = emallocz(sizeof(Bool) * ntags);
seltags[0] = True;
/* style */
dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR);
dc.norm[ColBG] = getcolor(NORMBGCOLOR);
dc.norm[ColFG] = getcolor(NORMFGCOLOR);
dc.sel[ColBorder] = getcolor(SELBORDERCOLOR);
dc.sel[ColBG] = getcolor(SELBGCOLOR);
dc.sel[ColFG] = getcolor(SELFGCOLOR);
setfont(FONT);
dc.norm[ColBorder] = initcolor(NORMBORDERCOLOR);
dc.norm[ColBG] = initcolor(NORMBGCOLOR);
dc.norm[ColFG] = initcolor(NORMFGCOLOR);
dc.sel[ColBorder] = initcolor(SELBORDERCOLOR);
dc.sel[ColBG] = initcolor(SELBGCOLOR);
dc.sel[ColFG] = initcolor(SELFGCOLOR);
initfont(FONT);
/* geometry */
sx = sy = 0;
sw = DisplayWidth(dpy, screen);
sh = DisplayHeight(dpy, screen);
master = MASTER;
nmaster = NMASTER;
bmw = textw(TILESYMBOL) > textw(FLOATSYMBOL) ? textw(TILESYMBOL) : textw(FLOATSYMBOL);
initlayouts();
/* bar */
dc.h = bh = dc.font.height + 2;
wa.override_redirect = 1;
wa.background_pixmap = ParentRelative;
wa.event_mask = ButtonPressMask | ExposureMask;
barwin = XCreateWindow(dpy, root, sx, sy, sw, bh, 0, DefaultDepth(dpy, screen),
CopyFromParent, DefaultVisual(dpy, screen),
barwin = XCreateWindow(dpy, root, sx, sy, sw, bh, 0,
DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
XDefineCursor(dpy, barwin, cursor[CurNormal]);
updatebarpos();
XMapRaised(dpy, barwin);
strcpy(stext, "dwm-"VERSION);
/* windowarea */
wax = sx;
way = sy + bh;
wah = sh - bh;
waw = sw;
/* pixmap for everything */
dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, 0);
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
if(!dc.font.set)
XSetFont(dpy, dc.gc, dc.font.xfont->fid);
/* multihead support */
selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
}
@ -171,40 +244,35 @@ xerrorstart(Display *dsply, XErrorEvent *ee) {
/* extern */
int
getproto(Window w) {
int i, format, protos, status;
unsigned long extra, res;
Atom *protocols, real;
Bool
gettextprop(Window w, Atom atom, char *text, unsigned int size) {
char **list = NULL;
int n;
XTextProperty name;
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++)
if(protocols[i] == wmatom[WMDelete])
protos |= PROTODELWIN;
free(protocols);
return protos;
if(!text || size == 0)
return False;
text[0] = '\0';
XGetTextProperty(dpy, w, &name, atom);
if(!name.nitems)
return False;
if(name.encoding == XA_STRING)
strncpy(text, (char *)name.value, size - 1);
else {
if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
&& n > 0 && *list)
{
strncpy(text, *list, size - 1);
XFreeStringList(list);
}
}
text[size - 1] = '\0';
XFree(name.value);
return True;
}
void
sendevent(Window w, Atom a, long value) {
XEvent e;
e.type = ClientMessage;
e.xclient.window = w;
e.xclient.message_type = a;
e.xclient.format = 32;
e.xclient.data.l[0] = value;
e.xclient.data.l[1] = CurrentTime;
XSendEvent(dpy, w, False, NoEventMask, &e);
XSync(dpy, False);
}
void
quit(Arg *arg) {
quit(const char *arg) {
readin = running = False;
}
@ -233,16 +301,14 @@ main(int argc, char *argv[]) {
char *p;
int r, xfd;
fd_set rd;
XEvent ev;
if(argc == 2 && !strncmp("-v", argv[1], 3)) {
fputs("dwm-"VERSION", (C)opyright MMVI-MMVII Anselm R. Garbe\n", stdout);
exit(EXIT_SUCCESS);
}
if(argc == 2 && !strcmp("-v", argv[1]))
eprint("dwm-"VERSION", © 2006-2007 A. R. Garbe, S. van Dijk, J. Salmi, P. Hruby, S. Nagy\n");
else if(argc != 1)
eprint("usage: dwm [-v]\n");
setlocale(LC_CTYPE, "");
dpy = XOpenDisplay(0);
if(!dpy)
if(!(dpy = XOpenDisplay(0)))
eprint("dwm: cannot open display\n");
xfd = ConnectionNumber(dpy);
screen = DefaultScreen(dpy);
@ -265,7 +331,6 @@ main(int argc, char *argv[]) {
/* main event loop, also reads status text from stdin */
XSync(dpy, False);
procevent();
readin = True;
while(running) {
FD_ZERO(&rd);
@ -290,14 +355,17 @@ main(int argc, char *argv[]) {
break;
default:
for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0');
for(p = stext + strlen(stext) - 1; p >= stext && *p != '\n'; --p);
for(; p >= stext && *p != '\n'; --p);
if(p > stext)
strncpy(stext, p + 1, sizeof stext);
}
drawstatus();
}
if(FD_ISSET(xfd, &rd))
procevent();
while(XPending(dpy)) {
XNextEvent(dpy, &ev);
if(handler[ev.type])
(handler[ev.type])(&ev); /* call handler */
}
}
cleanup();
XCloseDisplay(dpy);

376
screen.c Normal file
View File

@ -0,0 +1,376 @@
/* See LICENSE file for copyright and license details. */
#include "dwm.h"
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xutil.h>
/* static */
typedef struct {
const char *symbol;
void (*arrange)(void);
} Layout;
typedef struct {
const char *prop;
const char *tags;
Bool isfloating;
} Rule;
typedef struct {
regex_t *propregex;
regex_t *tagregex;
} Regs;
TAGS
RULES
static unsigned int nrules = 0;
static unsigned int nlayouts = 0;
static unsigned int ltidx = 0; /* default */
static Regs *regs = NULL;
static unsigned int
idxoftag(const char *tag) {
unsigned int i;
for(i = 0; i < ntags; i++)
if(tags[i] == tag)
return i;
return 0;
}
static void
floating(void) { /* default floating layout */
Client *c;
for(c = clients; c; c = c->next)
if(isvisible(c))
resize(c, c->x, c->y, c->w, c->h, True);
}
LAYOUTS
/* extern */
unsigned int blw = 0;
void
applyrules(Client *c) {
static char buf[512];
unsigned int i, j;
regmatch_t tmp;
Bool matched = False;
XClassHint ch = { 0 };
/* rule matching */
XGetClassHint(dpy, c->win, &ch);
snprintf(buf, sizeof buf, "%s:%s:%s",
ch.res_class ? ch.res_class : "",
ch.res_name ? ch.res_name : "", c->name);
for(i = 0; i < nrules; i++)
if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) {
c->isfloating = rules[i].isfloating;
for(j = 0; regs[i].tagregex && j < ntags; j++) {
if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
matched = True;
c->tags[j] = True;
}
}
}
if(ch.res_class)
XFree(ch.res_class);
if(ch.res_name)
XFree(ch.res_name);
if(!matched)
for(i = 0; i < ntags; i++)
c->tags[i] = seltags[i];
}
void
arrange(void) {
Client *c;
for(c = clients; c; c = c->next)
if(isvisible(c))
unban(c);
else
ban(c);
layouts[ltidx].arrange();
focus(NULL);
restack();
}
void
compileregs(void) {
unsigned int i;
regex_t *reg;
if(regs)
return;
nrules = sizeof rules / sizeof rules[0];
regs = emallocz(nrules * sizeof(Regs));
for(i = 0; i < nrules; i++) {
if(rules[i].prop) {
reg = emallocz(sizeof(regex_t));
if(regcomp(reg, rules[i].prop, REG_EXTENDED))
free(reg);
else
regs[i].propregex = reg;
}
if(rules[i].tags) {
reg = emallocz(sizeof(regex_t));
if(regcomp(reg, rules[i].tags, REG_EXTENDED))
free(reg);
else
regs[i].tagregex = reg;
}
}
}
void
focusnext(const char *arg) {
Client *c;
if(!sel)
return;
for(c = sel->next; c && !isvisible(c); c = c->next);
if(!c)
for(c = clients; c && !isvisible(c); c = c->next);
if(c) {
focus(c);
restack();
}
}
void
focusprev(const char *arg) {
Client *c;
if(!sel)
return;
for(c = sel->prev; c && !isvisible(c); c = c->prev);
if(!c) {
for(c = clients; c && c->next; c = c->next);
for(; c && !isvisible(c); c = c->prev);
}
if(c) {
focus(c);
restack();
}
}
const char *
getsymbol(void)
{
return layouts[ltidx].symbol;
}
void
initlayouts(void) {
unsigned int i, w;
nlayouts = sizeof layouts / sizeof layouts[0];
for(blw = i = 0; i < nlayouts; i++) {
w = textw(layouts[i].symbol);
if(w > blw)
blw = w;
}
}
Bool
isfloating(void) {
return layouts[ltidx].arrange == floating;
}
Bool
isarrange(void (*func)())
{
return func == layouts[ltidx].arrange;
}
Bool
isvisible(Client *c) {
unsigned int i;
for(i = 0; i < ntags; i++)
if(c->tags[i] && seltags[i])
return True;
return False;
}
Client *
nexttiled(Client *c) {
for(; c && (c->isfloating || !isvisible(c)); c = c->next);
return c;
}
void
restack(void) {
Client *c;
XEvent ev;
XWindowChanges wc;
drawstatus();
if(!sel)
return;
if(sel->isfloating || isfloating())
XRaiseWindow(dpy, sel->win);
if(!isfloating()) {
wc.stack_mode = Below;
wc.sibling = barwin;
if(!sel->isfloating) {
XConfigureWindow(dpy, sel->win, CWSibling | CWStackMode, &wc);
wc.sibling = sel->win;
}
for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
if(c == sel)
continue;
XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc);
wc.sibling = c->win;
}
}
XSync(dpy, False);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}
void
setlayout(const char *arg) {
unsigned int i;
if(!arg) {
if(++ltidx == nlayouts)
ltidx = 0;;
}
else {
for(i = 0; i < nlayouts; i++)
if(!strcmp(arg, layouts[i].symbol))
break;
if(i == nlayouts)
return;
ltidx = i;
}
if(sel)
arrange();
else
drawstatus();
}
void
tag(const char *arg) {
unsigned int i;
if(!sel)
return;
for(i = 0; i < ntags; i++)
sel->tags[i] = arg == NULL;
i = idxoftag(arg);
if(i >= 0 && i < ntags)
sel->tags[i] = True;
arrange();
}
void
togglebar(const char *arg) {
if(bpos == BarOff)
bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
else
bpos = BarOff;
updatebarpos();
arrange();
}
void
togglefloating(const char *arg) {
if(!sel || isfloating())
return;
sel->isfloating = !sel->isfloating;
if(sel->isfloating)
resize(sel, sel->x, sel->y, sel->w, sel->h, True);
arrange();
}
void
togglemax(const char *arg) {
XEvent ev;
if(!sel || (!isfloating() && !sel->isfloating) || sel->isfixed)
return;
if((sel->ismax = !sel->ismax)) {
sel->rx = sel->x;
sel->ry = sel->y;
sel->rw = sel->w;
sel->rh = sel->h;
resize(sel, wax, way, waw - 2 * sel->border, wah - 2 * sel->border, True);
}
else
resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
drawstatus();
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}
void
toggletag(const char *arg) {
unsigned int i, j;
if(!sel)
return;
i = idxoftag(arg);
sel->tags[i] = !sel->tags[i];
for(j = 0; j < ntags && !sel->tags[j]; j++);
if(j == ntags)
sel->tags[i] = True;
arrange();
}
void
toggleview(const char *arg) {
unsigned int i, j;
i = idxoftag(arg);
seltags[i] = !seltags[i];
for(j = 0; j < ntags && !seltags[j]; j++);
if(j == ntags)
seltags[i] = True; /* cannot toggle last view */
arrange();
}
void
updatebarpos(void) {
XEvent ev;
wax = sx;
way = sy;
wah = sh;
waw = sw;
switch(bpos) {
default:
wah -= bh;
way += bh;
XMoveWindow(dpy, barwin, sx, sy);
break;
case BarBot:
wah -= bh;
XMoveWindow(dpy, barwin, sx, sy + wah);
break;
case BarOff:
XMoveWindow(dpy, barwin, sx, sy - bh);
break;
}
XSync(dpy, False);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}
void
view(const char *arg) {
unsigned int i;
for(i = 0; i < ntags; i++)
seltags[i] = arg == NULL;
i = idxoftag(arg);
if(i >= 0 && i < ntags)
seltags[i] = True;
arrange();
}

133
tag.c
View File

@ -1,133 +0,0 @@
/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
* 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>
typedef struct {
const char *clpattern;
const char *tpattern;
Bool isfloat;
} Rule;
typedef struct {
regex_t *clregex;
regex_t *tregex;
} RReg;
/* static */
TAGS
RULES
static RReg *rreg = NULL;
static unsigned int len = 0;
/* extern */
Client *
getnext(Client *c) {
for(; c && !isvisible(c); c = c->next);
return c;
}
Client *
getprev(Client *c) {
for(; c && !isvisible(c); c = c->prev);
return c;
}
void
initrregs(void) {
unsigned int i;
regex_t *reg;
if(rreg)
return;
len = sizeof rule / sizeof rule[0];
rreg = emallocz(len * sizeof(RReg));
for(i = 0; i < len; i++) {
if(rule[i].clpattern) {
reg = emallocz(sizeof(regex_t));
if(regcomp(reg, rule[i].clpattern, REG_EXTENDED))
free(reg);
else
rreg[i].clregex = reg;
}
if(rule[i].tpattern) {
reg = emallocz(sizeof(regex_t));
if(regcomp(reg, rule[i].tpattern, REG_EXTENDED))
free(reg);
else
rreg[i].tregex = reg;
}
}
}
void
settags(Client *c, Client *trans) {
char prop[512];
unsigned int i, j;
regmatch_t tmp;
Bool matched = trans != NULL;
XClassHint ch;
if(matched) {
for(i = 0; i < ntags; i++)
c->tags[i] = trans->tags[i];
}
else if(XGetClassHint(dpy, c->win, &ch)) {
snprintf(prop, sizeof prop, "%s:%s:%s",
ch.res_class ? ch.res_class : "",
ch.res_name ? ch.res_name : "", c->name);
for(i = 0; 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;
}
}
}
if(ch.res_class)
XFree(ch.res_class);
if(ch.res_name)
XFree(ch.res_name);
}
if(!matched)
for(i = 0; i < ntags; i++)
c->tags[i] = seltag[i];
}
void
tag(Arg *arg) {
unsigned int i;
if(!sel)
return;
for(i = 0; i < ntags; i++)
sel->tags[i] = (arg->i == -1) ? True : False;
if(arg->i >= 0 && arg->i < ntags)
sel->tags[arg->i] = True;
arrange();
}
void
toggletag(Arg *arg) {
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;
arrange();
}

86
tile.c Normal file
View File

@ -0,0 +1,86 @@
/* See LICENSE file for copyright and license details. */
#include "dwm.h"
#include <stdio.h>
/* static */
static double mwfact = MWFACT;
/* extern */
void
setmwfact(const char *arg) {
double delta;
if(!isarrange(tile))
return;
/* arg handling, manipulate mwfact */
if(arg == NULL)
mwfact = MWFACT;
else if(1 == sscanf(arg, "%lf", &delta)) {
if(arg[0] != '+' && arg[0] != '-')
mwfact = delta;
else
mwfact += delta;
if(mwfact < 0.1)
mwfact = 0.1;
else if(mwfact > 0.9)
mwfact = 0.9;
}
arrange();
}
void
tile(void) {
unsigned int i, n, nx, ny, nw, nh, mw, th;
Client *c;
for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
n++;
/* window geoms */
mw = (n == 1) ? waw : mwfact * waw;
th = (n > 1) ? wah / (n - 1) : 0;
if(n > 1 && th < bh)
th = wah;
nx = wax;
ny = way;
for(i = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) {
c->ismax = False;
if(i == 0) { /* master */
nw = mw - 2 * c->border;
nh = wah - 2 * c->border;
}
else { /* tile window */
if(i == 1) {
ny = way;
nx += mw;
}
nw = waw - mw - 2 * c->border;
if(i + 1 == n) /* remainder */
nh = (way + wah) - ny - 2 * c->border;
else
nh = th - 2 * c->border;
}
resize(c, nx, ny, nw, nh, False);
if(n > 1 && th != wah)
ny += nh + 2 * c->border;
i++;
}
}
void
zoom(const char *arg) {
Client *c;
if(!sel || !isarrange(tile) || sel->isfloating)
return;
if((c = sel) == nexttiled(clients))
if(!(c = nexttiled(c->next)))
return;
detach(c);
attach(c);
focus(c);
arrange();
}

6
tile.h Normal file
View File

@ -0,0 +1,6 @@
/* See LICENSE file for copyright and license details. */
/* tile.c */
void setmwfact(const char *arg); /* sets master width factor */
void tile(void); /* arranges all windows tiled */
void zoom(const char *arg); /* zooms the focused client to master area, arg is ignored */

12
util.c
View File

@ -1,6 +1,4 @@
/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
/* See LICENSE file for copyright and license details. */
#include "dwm.h"
#include <stdarg.h>
#include <stdio.h>
@ -30,12 +28,12 @@ eprint(const char *errstr, ...) {
}
void
spawn(Arg *arg) {
spawn(const char *arg) {
static char *shell = NULL;
if(!shell && !(shell = getenv("SHELL")))
shell = "/bin/sh";
if(!arg->cmd)
if(!arg)
return;
/* The double-fork construct avoids zombie processes and keeps the code
* clean from stupid signal handlers. */
@ -44,8 +42,8 @@ spawn(Arg *arg) {
if(dpy)
close(ConnectionNumber(dpy));
setsid();
execl(shell, shell, "-c", arg->cmd, (char *)NULL);
fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg->cmd);
execl(shell, shell, "-c", arg, (char *)NULL);
fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg);
perror(" failed");
}
exit(0);

269
view.c
View File

@ -1,269 +0,0 @@
/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
#include "dwm.h"
#include <stdio.h>
/* static */
static Client *
nexttiled(Client *c) {
for(c = getnext(c); c && c->isfloat; c = getnext(c->next));
return c;
}
static void
togglemax(Client *c) {
XEvent ev;
if(c->isfixed)
return;
if((c->ismax = !c->ismax)) {
c->rx = c->x; c->x = wax;
c->ry = c->y; c->y = way;
c->rw = c->w; c->w = waw - 2 * BORDERPX;
c->rh = c->h; c->h = wah - 2 * BORDERPX;
}
else {
c->x = c->rx;
c->y = c->ry;
c->w = c->rw;
c->h = c->rh;
}
resize(c, True);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}
/* extern */
void (*arrange)(void) = 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(void) {
Client *c;
for(c = clients; c; c = c->next) {
if(isvisible(c)) {
resize(c, True);
}
else
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
}
if(!sel || !isvisible(sel)) {
for(c = stack; c && !isvisible(c); c = c->snext);
focus(c);
}
restack();
}
void
dotile(void) {
unsigned int i, n, mw, mh, tw, th;
Client *c;
for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
n++;
/* window geoms */
mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
mw = (n > nmaster) ? (waw * master) / 1000 : waw;
th = (n > nmaster) ? wah / (n - nmaster) : 0;
tw = waw - mw;
for(i = 0, c = clients; c; c = c->next)
if(isvisible(c)) {
if(c->isfloat) {
resize(c, True);
continue;
}
c->ismax = False;
c->x = wax;
c->y = way;
if(i < nmaster) {
c->y += i * mh;
c->w = mw - 2 * BORDERPX;
c->h = mh - 2 * BORDERPX;
}
else { /* tile window */
c->x += mw;
c->w = tw - 2 * BORDERPX;
if(th > bh) {
c->y += (i - nmaster) * th;
c->h = th - 2 * BORDERPX;
}
else /* fallback if th < bh */
c->h = wah - 2 * BORDERPX;
}
resize(c, False);
i++;
}
else
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
if(!sel || !isvisible(sel)) {
for(c = stack; c && !isvisible(c); c = c->snext);
focus(c);
}
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();
}
}
void
incnmaster(Arg *arg) {
if((arrange == dofloat) || (nmaster + arg->i < 1) || (wah / (nmaster + arg->i) < bh))
return;
nmaster += arg->i;
if(sel)
arrange();
else
drawstatus();
}
Bool
isvisible(Client *c) {
unsigned int i;
for(i = 0; i < ntags; i++)
if(c->tags[i] && seltag[i])
return True;
return False;
}
void
resizemaster(Arg *arg) {
if(arg->i == 0)
master = MASTER;
else {
if(master + arg->i > 950 || master + arg->i < 50)
return;
master += arg->i;
}
arrange();
}
void
restack(void) {
Client *c;
XEvent ev;
drawstatus();
if(!sel)
return;
if(sel->isfloat || arrange == dofloat)
XRaiseWindow(dpy, sel->win);
if(arrange != dofloat) {
if(!sel->isfloat)
XLowerWindow(dpy, sel->win);
for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
if(c == sel)
continue;
XLowerWindow(dpy, c->win);
}
}
XSync(dpy, False);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}
void
togglefloat(Arg *arg) {
if (!sel || arrange == dofloat)
return;
sel->isfloat = !sel->isfloat;
arrange();
}
void
togglemode(Arg *arg) {
arrange = (arrange == dofloat) ? dotile : dofloat;
if(sel)
arrange();
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();
}
void
view(Arg *arg) {
unsigned int i;
for(i = 0; i < ntags; i++)
seltag[i] = (arg->i == -1) ? True : False;
if(arg->i >= 0 && arg->i < ntags)
seltag[arg->i] = True;
arrange();
}
void
zoom(Arg *arg) {
unsigned int n;
Client *c;
if(!sel)
return;
if(sel->isfloat || (arrange == dofloat)) {
togglemax(sel);
return;
}
for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
n++;
if((c = sel) == nexttiled(clients))
if(!(c = nexttiled(c->next)))
return;
detach(c);
if(clients)
clients->prev = c;
c->next = clients;
clients = c;
focus(c);
arrange();
}