Compare commits
748 Commits
Author | SHA1 | Date | |
---|---|---|---|
8e4f659772 | |||
99b45ee0d4 | |||
3f3811e80d | |||
fd9e12e7c5 | |||
4e8381c135 | |||
fa54da1744 | |||
6024c104c1 | |||
f0dd75e8c5 | |||
95131de64f | |||
e81decd079 | |||
ef6b5ee95a | |||
edb4762434 | |||
14dc678a7f | |||
9b7ba80925 | |||
833edb4d88 | |||
ba9a2ef74b | |||
215f92fabb | |||
0339db5604 | |||
ffcb42df85 | |||
84b5615062 | |||
3935b19814 | |||
9f219c6a08 | |||
904554033c | |||
0b87eae829 | |||
be9497bd75 | |||
9253bcdb53 | |||
1bdfed1d0d | |||
3eb84701d7 | |||
edc446997e | |||
873287e2ec | |||
5dee96918f | |||
45277ea35b | |||
cebe408f75 | |||
1950543da6 | |||
1dc6430ff6 | |||
586865823b | |||
7d0f7c5f99 | |||
92b735ffef | |||
a40a0f0bd6 | |||
c8f5653ecd | |||
61bb8b2241 | |||
bb2e7222ba | |||
f04cac6d6e | |||
f09418bbb6 | |||
ed3ab6b4fc | |||
f087d20e6e | |||
a8e9513783 | |||
c82db690cc | |||
cb3f58ad06 | |||
b69c870a30 | |||
e78b4a9207 | |||
3cd4023fb3 | |||
f40f86fa87 | |||
c3a2e016bb | |||
c8e9479186 | |||
10dfa65860 | |||
3bd8466e93 | |||
76c8c16d79 | |||
3cb34830eb | |||
db2236001c | |||
3756f7f6b8 | |||
99f78fa553 | |||
a9b6a312a7 | |||
6aa8e37efe | |||
ceac8c91ff | |||
5b238c8dab | |||
022d076054 | |||
2952b68db8 | |||
bb3bd6fec3 | |||
e63bf22948 | |||
5376947571 | |||
975c898376 | |||
a137a86a23 | |||
839c7f6939 | |||
7a59cd1457 | |||
24849acada | |||
ab9571bbc5 | |||
56a31dc4a7 | |||
7af4d439bd | |||
cd2d7549b3 | |||
3465bed290 | |||
4ec3a673ff | |||
5ed9c48196 | |||
3c91283ede | |||
e941181f46 | |||
43e82adf0d | |||
42cf1c7d8f | |||
dce4fb3737 | |||
646b351cc7 | |||
e3b7e1d620 | |||
04db03a4e6 | |||
4a4817b3aa | |||
7e1182ce55 | |||
40529e1469 | |||
14343e69cc | |||
35db6d8afc | |||
3d1090ba89 | |||
18248ebf4b | |||
b468873b2b | |||
cdec9782a1 | |||
6af273771c | |||
4fb31e0896 | |||
b800a1d136 | |||
33a74489f0 | |||
5364697914 | |||
7edc596311 | |||
68b400e95d | |||
656882d76f | |||
1479e76f01 | |||
f2544a3318 | |||
aafeaf7317 | |||
f21d46ea7d | |||
c0ba635c50 | |||
0a673ad7a3 | |||
3aabc08ede | |||
d456617f0e | |||
61fe833a06 | |||
917e281634 | |||
31451c3ad3 | |||
344f35f9f5 | |||
87adcd263b | |||
fd3c19bd55 | |||
1bdb393f81 | |||
940feed314 | |||
606b44179d | |||
20f6917910 | |||
820cbb3545 | |||
90f3238301 | |||
3bfc43c3d0 | |||
c1128417a9 | |||
1b62f8fa58 | |||
54c3044dec | |||
51336aa4a3 | |||
c4b6ac812e | |||
873bcb97a9 | |||
907db0a851 | |||
4e7c469862 | |||
26445a0dc9 | |||
b5068e32e9 | |||
f099d2d5b5 | |||
80a9da555e | |||
d21026f0a1 | |||
e5a1e77351 | |||
8262d9e663 | |||
90af1ced3c | |||
5ccd42f807 | |||
1586b7a02d | |||
2420071f4c | |||
04c26574b8 | |||
b1a28ae1da | |||
f68a01cd76 | |||
2b625eb73e | |||
0f1f30daca | |||
dec4850d05 | |||
0de4197cc5 | |||
a372248b80 | |||
69e7d7dfd3 | |||
c99fe7dd7d | |||
d6670a800d | |||
6288c44697 | |||
d5c5c52b30 | |||
d0b4575bf4 | |||
03518ce49e | |||
cd8bb06af5 | |||
3150a8a1be | |||
b3c5f5435a | |||
a692bdcf2b | |||
d83454f6b7 | |||
27b0142203 | |||
867ba36030 | |||
e83f36db10 | |||
212f417e44 | |||
3a392b8558 | |||
92fe06b501 | |||
6cf29bff33 | |||
60c06a7cb4 | |||
1147546122 | |||
d384cee751 | |||
5c710cf89c | |||
8a111c181e | |||
2255bf46a0 | |||
04797343db | |||
e7d41cc188 | |||
22d8818850 | |||
6784429c3c | |||
37fea84de8 | |||
c14d293e51 | |||
79b1657a19 | |||
d24837f1ad | |||
3c2d303c0e | |||
1e20a0f78a | |||
96f9855248 | |||
3c48858ffa | |||
dd46d5b588 | |||
0bc4e41ebd | |||
703c4dd253 | |||
b68528d85d | |||
a644baf674 | |||
c1f8688bfa | |||
bea4dd2490 | |||
83d10be1c1 | |||
1529058f27 | |||
36311d88af | |||
f1a2a3c850 | |||
ee734fae6b | |||
62d3caa999 | |||
4c9b397ff9 | |||
5c6545adf5 | |||
a704b1ee34 | |||
f83d61dfe8 | |||
c6180949a7 | |||
1973ab0643 | |||
427053f8d1 | |||
a88e0373ef | |||
aa9f2be24e | |||
c53b29e60b | |||
d6bdd03d91 | |||
1144e98394 | |||
7671d03a90 | |||
bc554d45d8 | |||
ac4caea921 | |||
161f2d921b | |||
210378f198 | |||
7879616a75 | |||
9e8dd3479d | |||
0b72be924d | |||
91e902f7fe | |||
30fed9a211 | |||
c45d46ad9a | |||
6f55de8310 | |||
07ad298133 | |||
f0a4845e7d | |||
82ec7a7ed4 | |||
e7300e0f6f | |||
c3feffa1e2 | |||
956a430054 | |||
01056b6636 | |||
eb260b1a41 | |||
7fe81359d4 | |||
a3a859b4e9 | |||
9c066c24b3 | |||
0a668922a4 | |||
5762964232 | |||
cba6b211c2 | |||
42750a621b | |||
8ef465d592 | |||
33fe200b52 | |||
91fffb3f7d | |||
1fa31efebf | |||
244addb3f4 | |||
c13be8d620 | |||
dc39ae8568 | |||
966d76a428 | |||
7151bf8329 | |||
dfecd46190 | |||
5bc4db0f76 | |||
999d6e795f | |||
636075297c | |||
6877a00033 | |||
0927d635bc | |||
450b08dde2 | |||
da80487c07 | |||
d9779c06fc | |||
20996c6c5a | |||
8dc9fcf1b9 | |||
fc21dd4b7e | |||
758b100d12 | |||
8420fb1ced | |||
f6128a16f9 | |||
87526be6f0 | |||
565050ac51 | |||
5e408d8ff6 | |||
1724f7fa43 | |||
3e6fe6b541 | |||
6620615ab9 | |||
61c3095f2f | |||
a72dc2fec2 | |||
8b17f5517b | |||
cd96232f7e | |||
a9e145fe6d | |||
5dd92c7655 | |||
52bd69c2a4 | |||
ca376970db | |||
8352f2b3a8 | |||
d4bfde79f3 | |||
7ac8c1d4e1 | |||
16e1ef5d40 | |||
1d729384d1 | |||
25c1eb28f9 | |||
d719cc9a0e | |||
9cde6570cc | |||
e408ca97d8 | |||
183dc670a3 | |||
25947bcfdb | |||
1ddfc571ae | |||
21cd59a630 | |||
6cbe47d481 | |||
029655bb22 | |||
27db9d4448 | |||
176408afa8 | |||
64674c395b | |||
b9dee2c6f1 | |||
a73ff905b0 | |||
e3f0445df1 | |||
ab06f7444b | |||
a2a3590979 | |||
e8aafb8e91 | |||
18b1312449 | |||
80ee95473b | |||
454a04acdf | |||
891831fe62 | |||
cdb8e27453 | |||
5c4913e983 | |||
fa5ae54bbb | |||
7de534192c | |||
54dc0d542c | |||
913333f518 | |||
d702f39274 | |||
0d8671a5ad | |||
38e9b67026 | |||
a3bbdb1b7b | |||
d53ceee682 | |||
78f56672b5 | |||
c2fff604a7 | |||
6644a6aa2e | |||
3da2453997 | |||
2ce37bc69e | |||
f27ccc5c60 | |||
2dbfda72f0 | |||
7df39f3fc7 | |||
0b45199cec | |||
3632d7132f | |||
565697087b | |||
ea0008cba2 | |||
af508c2e82 | |||
f0d1d5206f | |||
1c80c05587 | |||
1e350be229 | |||
1a26389e2b | |||
bf9da23f07 | |||
2373940215 | |||
90687482ad | |||
5ab627c06c | |||
76d7e80fc4 | |||
af8049bce8 | |||
2bb51b3246 | |||
b16d8282be | |||
fef4614772 | |||
be39dddcc5 | |||
6d209b9b29 | |||
57a0788bd8 | |||
3ad906eede | |||
0be9fb8797 | |||
62a491e36d | |||
0b5dcf229f | |||
fda92f46aa | |||
a62ea4062f | |||
7dc28d130f | |||
fbce733532 | |||
e7572804fa | |||
ed1bef1241 | |||
2b047e460b | |||
5f74dc5e78 | |||
ea8a4ca46a | |||
4883a06221 | |||
4dea5324c0 | |||
53cac17692 | |||
83abfc05eb | |||
862b0d541d | |||
c1c6fdc5d8 | |||
9a4d07d9de | |||
30410108eb | |||
753e0e048e | |||
d15d4ba45a | |||
815f9c054d | |||
addc52c948 | |||
26f41c9055 | |||
73ec124ae9 | |||
ec11a3470c | |||
4b3b597da3 | |||
288cf78b18 | |||
6411aa921b | |||
db5db8806f | |||
258c338030 | |||
85da537856 | |||
2b4157eccd | |||
0f26de991f | |||
840f937a98 | |||
6975a7e31a | |||
47f63dce55 | |||
02a8ca95cf | |||
2ce50a9cad | |||
bfa5869da1 | |||
087a55f8d3 | |||
6d7285fd6e | |||
69c7b4b0ba | |||
97699e5b1b | |||
2dc7f42fd7 | |||
9f3a5cb754 | |||
b48fa3f101 | |||
051a404b66 | |||
d8d733c34f | |||
bb01e5a16f | |||
06f7eed103 | |||
0ffa6d1393 | |||
15ce143620 | |||
63d7190231 | |||
b279cef670 | |||
6254ef9dc7 | |||
4a2902efe4 | |||
6fad4c49f1 | |||
78f0f8595f | |||
7ecadcee39 | |||
c86ed46a1b | |||
9086f98068 | |||
9aa4a9043d | |||
d5893f55be | |||
f529d41ca1 | |||
45768ee04b | |||
a6d23fb61c | |||
bf76cefe47 | |||
9bb0f20515 | |||
2431ae7df7 | |||
829b6b57e7 | |||
7b4c512e62 | |||
7f7c3140a9 | |||
277155cf77 | |||
0c38ec7cd6 | |||
deef4c9bfd | |||
b86c818599 | |||
c2a916bf30 | |||
2bd46d1ce6 | |||
6e0ce46365 | |||
c853d5e9bb | |||
31da0b7525 | |||
12ea925076 | |||
79ecbeca7e | |||
cf98ea2a9c | |||
d8fad9bf7a | |||
f25cc5678f | |||
5a92420fce | |||
ae1d865ac0 | |||
1ce173402f | |||
a06b9193c7 | |||
43bb77a569 | |||
e3da222c1e | |||
66608a60fe | |||
b6aa84e51b | |||
9ff5143acb | |||
1edf6a7866 | |||
4db2f44277 | |||
1f1a132784 | |||
512541bfbd | |||
709da0b858 | |||
5cd65f8cd8 | |||
e3838e8585 | |||
016dca4f69 | |||
8f052596b2 | |||
9463d5354b | |||
d662f98d89 | |||
e5a965a274 | |||
5d422bb1ce | |||
38a43c2dcc | |||
c56533615f | |||
a8e0772c4d | |||
98e7950be8 | |||
88e6eb4a3a | |||
0840c1367c | |||
077d3e435b | |||
d26b60b43e | |||
32f36ab2d5 | |||
08bcf721b4 | |||
fc578c57e4 | |||
c8eaab21b6 | |||
c26e22ccee | |||
c2784e4a38 | |||
6e9387793b | |||
92f3c181c3 | |||
d589f7679a | |||
75690c808d | |||
fde58d5e63 | |||
e1002745fa | |||
940a4cc6c6 | |||
64243ab05b | |||
32c5046635 | |||
6c8618f502 | |||
9189f7a12d | |||
2d4faae522 | |||
5d2385b636 | |||
0fe2e783e9 | |||
cd3d83f571 | |||
0a9ef560c0 | |||
0528a37c79 | |||
56b2fece9e | |||
9f569fac74 | |||
48d0c56eac | |||
825d6cb93a | |||
f852504014 | |||
c3fa9e879f | |||
8e05f6c592 | |||
39d1ecd5b0 | |||
103fb58a44 | |||
5f55af40ae | |||
f806a17692 | |||
822101dd5b | |||
6bdef73a4f | |||
234b12eb73 | |||
bd4deaebfc | |||
499315c22c | |||
f22d047d41 | |||
4a5c8d84db | |||
71365a524f | |||
3afca3e6a1 | |||
bdc80bdad6 | |||
64707da963 | |||
549726869b | |||
42cb2bd3be | |||
585294ce0f | |||
a864a82b34 | |||
bd67a82fb5 | |||
14d8d828ab | |||
4246affc15 | |||
42c4b31003 | |||
a785a0d712 | |||
489ac07e83 | |||
349d768b57 | |||
6dfa7cac56 | |||
71681c21a5 | |||
704781875c | |||
d7cc0f6416 | |||
6b79f3f326 | |||
446fa8c671 | |||
fa244aa7fb | |||
7ac4f8a4af | |||
7eb26288fc | |||
93a4fe1052 | |||
5602f44b29 | |||
b848f4bda8 | |||
86c4797f2c | |||
c094ed2473 | |||
bfd6079a15 | |||
7f70d90219 | |||
858251de46 | |||
d26c28c1e7 | |||
b6335776e4 | |||
c059625128 | |||
874837f653 | |||
5fa559dbfc | |||
146ff227fe | |||
bb0a328978 | |||
721b208478 | |||
6229ed20c2 | |||
940240e5e6 | |||
08c596ed10 | |||
9ce6abb95c | |||
0e21794e02 | |||
d477fb6927 | |||
3d6630b7d2 | |||
c982bb1389 | |||
6cf73e706a | |||
a520ba3c0b | |||
0c71b16b92 | |||
00c28a7ef2 | |||
5a3a2d6b63 | |||
a355782a77 | |||
20cd336087 | |||
a6a216f28c | |||
2c2063bc75 | |||
e6ede461a9 | |||
6877205e9d | |||
fb5f99d935 | |||
7ebab7533a | |||
9fa5ca3538 | |||
fe6b0c0fc1 | |||
aa2395b6a8 | |||
dba22848c7 | |||
33b1960220 | |||
e237b2a76f | |||
dd9ee6d248 | |||
1380569133 | |||
831428b00c | |||
69439715c0 | |||
f2e98f48fb | |||
c19d4b2930 | |||
f77a3d0a62 | |||
8aa1533879 | |||
2fc9cffdeb | |||
3c5b6f03ba | |||
02673538bc | |||
95eae7b9d2 | |||
59107755c8 | |||
d05d09b205 | |||
47b1974446 | |||
247ba66c08 | |||
d7b074fcce | |||
c9170189bf | |||
f7a45ff28b | |||
add7df6e9b | |||
3a79b82721 | |||
b31b430592 | |||
88c8ead3e8 | |||
2e95837220 | |||
5d9ae3f3b7 | |||
2e38296edd | |||
59aa02a075 | |||
e3c2d327f6 | |||
295ad21092 | |||
39af3c2607 | |||
96ee9d888c | |||
a82cba2759 | |||
f7c097e802 | |||
da1b3fa437 | |||
ad0a2fa042 | |||
9804726c82 | |||
7bc272a4e4 | |||
f1719ac2de | |||
d99ec61482 | |||
2f70a14ee1 | |||
00ca643bd7 | |||
0271ac0ed7 | |||
d5178292ed | |||
2bfd3fffbf | |||
a3d8c05a95 | |||
fd01413fae | |||
d6e24f7116 | |||
c43d7b7587 | |||
de5b294edc | |||
8e0f8ffcc6 | |||
dd21823536 | |||
9cb9c32ee7 | |||
4076e2ff60 | |||
55edd2d6ec | |||
2e8e5509d9 | |||
4426032450 | |||
e0f0397896 | |||
ca3e847e45 | |||
c2737b7b93 | |||
191cb9ce28 | |||
6ab163c695 | |||
e8244395e4 | |||
954db46bac | |||
508922b90d | |||
4adfdc9d95 | |||
c619363d15 | |||
012710a3ce | |||
c2c54cc0fa | |||
a62630ae92 | |||
62b18fb9d4 | |||
e0d6451086 | |||
7a496e9777 | |||
308f95ae5a | |||
40a734bca9 | |||
985e330524 | |||
5f19423c7b | |||
d66ad1457e | |||
8497f9f781 | |||
91bb749e97 | |||
68ff133857 | |||
4380db468a | |||
123a565bb9 | |||
d0e0505301 | |||
762b66ae7c | |||
cb4951dd54 | |||
667da18b31 | |||
e9a0733506 | |||
198502f41d | |||
35efafe8ac | |||
951d022dfc | |||
54bde0f9d7 | |||
260a55ef62 | |||
0e98090d65 | |||
af4667a85a | |||
a98b5e5935 | |||
b8985dc7bb | |||
6f60b2e1cd | |||
3033d45d1c | |||
34e7872c89 | |||
c36f7c3c5e | |||
3fd39feb41 | |||
93eee247ca | |||
d5e8edcbcb | |||
13577b15e5 | |||
5473e763f6 | |||
cdd6c3e820 | |||
29f2b15ddc | |||
7b65b763bc | |||
e94774dd69 | |||
af0034f3a5 | |||
cd7ebaad25 | |||
8dc03d6e6b | |||
1dcb18c124 | |||
206eb344e2 | |||
04de5720e6 | |||
5a04edecb1 | |||
24c125cc8a | |||
0453c1d180 | |||
0b5c14cf59 | |||
a73de0cff4 | |||
eeea4ef583 | |||
883e09b2eb | |||
7e25897f11 | |||
95091dcad4 | |||
57676994ea | |||
60adbab726 | |||
c3eca4d14f | |||
d1f4fbb469 | |||
635b64384d | |||
bedbe59aaa | |||
3f3086f8b8 | |||
f92a4e45c4 | |||
2fc8a13588 | |||
63725004f5 | |||
e9348dcaca | |||
fa857b2896 | |||
c77663fcb4 | |||
17d39ee014 | |||
8d1810c85b | |||
60444daa70 | |||
b0477c3017 | |||
24dae7d7e3 | |||
fa1ce22bc4 | |||
1fafcb1820 | |||
08c2d92480 | |||
fe2775a15b | |||
01022b95d6 | |||
b2f276b0f9 | |||
d1ce3eac33 | |||
9449ea3e00 | |||
49197fe4bf | |||
11cfff2dae | |||
a026617c65 | |||
a6df995b5d | |||
e041ff70b0 | |||
2d7bb8d7c9 | |||
0235a84ef2 | |||
2091200c95 | |||
7e476fb86b | |||
9800518ae3 | |||
5d831eaa94 | |||
e0a6dee30d | |||
73e2aba341 | |||
9f88fd093c | |||
0e515a06c8 | |||
c4b3c0d979 | |||
f3a5116248 | |||
ae760f3f38 | |||
169d96ae8f | |||
f651435061 |
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# DWM Files
|
||||
*.o
|
||||
*.orig
|
||||
dwm
|
||||
dwm-msg
|
||||
config.h
|
49
.hgtags
49
.hgtags
@ -1,49 +0,0 @@
|
||||
d31b5ad96b0ba7b5b0a30928fcf000428339a577 0.1
|
||||
0a6472e2203994bc5738d40a340d26f7ec9d6062 0.2
|
||||
7e66082e5092fb0bccd18a3695a0bec52c80fdb2 0.3
|
||||
eb3165734f00fe7f7da8aeebaed00e60a57caac9 0.4
|
||||
22213b9a2114167ee8ba019a012e27da0422a61a 0.5
|
||||
c11f86db4550cac5d0a648a3fe4d6d3b9a4fcf7e 0.6
|
||||
3fb41412e2492f66476d92ce8f007a8b48fb1d2a 0.7
|
||||
cd15de32e173f8ce97bfe1c9b6607937b59056b4 0.8
|
||||
fae61afa861755636c4a1070694209ace8efbb6c 0.9
|
||||
bbc98e77ae89a7c9232a5be0835f60ea00d8036e 1.0
|
||||
44a55e6e46bf6c231780b09d919977d6f01083de 1.1
|
||||
e3179ce2b90451d2807cd53b589d768412b8666b 1.2
|
||||
f5f5cbf016a94b48a8fe9c47f0736e96d166d5d4 1.3
|
||||
3cff9403766bf83a9fc2a0aef230115d68de2a8e 1.4
|
||||
728c9089b079721b43c3347124639a29baa22a97 1.5
|
||||
ad3fa2d185426c51fd5deceae809770363f8d33c 1.6
|
||||
4dbdb61c8b8ce21dee5c7050a6b103855964ed20 1.7
|
||||
d5ad819f2a66a40fa75dd2e44429f3bfc884d07b 1.7.1
|
||||
c71952fa3c7ca848ec38a6923b5c6d0e18fff431 1.8
|
||||
a5567a0d30112822db2627a04a2e7aa3b6c38148 1.9
|
||||
12deea36603da407e3f32640048846a3bd74a9ec 2.0
|
||||
a2c465098a3b972bbed00feda9804b6aae1e9531 2.1
|
||||
7e92f58754ae6edb3225f26d754bd89c1ff458cf 2.2
|
||||
719b37b37b0df829d7cf017ac70e353088fe5849 2.3
|
||||
32b246925086910d63147483160281a91a47479f 2.4
|
||||
dcbbfabc8ecc5f33a6cc950584de87da1a368045 2.5
|
||||
c7f84f23ec5aef29988dcdc4ec22a7352ee8f58e 2.5.1
|
||||
5308dd22b6ee8e3218c81d9e7e4125f235bb5778 2.6
|
||||
21951c0dfbae5af68ed77821a4d87253ee91803f 2.7
|
||||
107719a9ce3bd0c79f9f1f626596eb338a276561 2.8
|
||||
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
|
||||
408014d2126153d2b0fce26a13ba707db222b7b9 4.4
|
66
IPCClient.c
Normal file
66
IPCClient.c
Normal file
@ -0,0 +1,66 @@
|
||||
#include "IPCClient.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
IPCClient *
|
||||
ipc_client_new(int fd)
|
||||
{
|
||||
IPCClient *c = (IPCClient *)malloc(sizeof(IPCClient));
|
||||
|
||||
if (c == NULL) return NULL;
|
||||
|
||||
// Initialize struct
|
||||
memset(&c->event, 0, sizeof(struct epoll_event));
|
||||
|
||||
c->buffer_size = 0;
|
||||
c->buffer = NULL;
|
||||
c->fd = fd;
|
||||
c->event.data.fd = fd;
|
||||
c->next = NULL;
|
||||
c->prev = NULL;
|
||||
c->subscriptions = 0;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
ipc_list_add_client(IPCClientList *list, IPCClient *nc)
|
||||
{
|
||||
DEBUG("Adding client with fd %d to list\n", nc->fd);
|
||||
|
||||
if (*list == NULL) {
|
||||
// List is empty, point list at first client
|
||||
*list = nc;
|
||||
} else {
|
||||
IPCClient *c;
|
||||
// Go to last client in list
|
||||
for (c = *list; c && c->next; c = c->next)
|
||||
;
|
||||
c->next = nc;
|
||||
nc->prev = c;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ipc_list_remove_client(IPCClientList *list, IPCClient *c)
|
||||
{
|
||||
IPCClient *cprev = c->prev;
|
||||
IPCClient *cnext = c->next;
|
||||
|
||||
if (cprev != NULL) cprev->next = c->next;
|
||||
if (cnext != NULL) cnext->prev = c->prev;
|
||||
if (c == *list) *list = c->next;
|
||||
}
|
||||
|
||||
IPCClient *
|
||||
ipc_list_get_client(IPCClientList list, int fd)
|
||||
{
|
||||
for (IPCClient *c = list; c; c = c->next) {
|
||||
if (c->fd == fd) return c;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
61
IPCClient.h
Normal file
61
IPCClient.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef IPC_CLIENT_H_
|
||||
#define IPC_CLIENT_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
typedef struct IPCClient IPCClient;
|
||||
/**
|
||||
* This structure contains the details of an IPC Client and pointers for a
|
||||
* linked list
|
||||
*/
|
||||
struct IPCClient {
|
||||
int fd;
|
||||
int subscriptions;
|
||||
|
||||
char *buffer;
|
||||
uint32_t buffer_size;
|
||||
|
||||
struct epoll_event event;
|
||||
IPCClient *next;
|
||||
IPCClient *prev;
|
||||
};
|
||||
|
||||
typedef IPCClient *IPCClientList;
|
||||
|
||||
/**
|
||||
* Allocate memory for new IPCClient with the specified file descriptor and
|
||||
* initialize struct.
|
||||
*
|
||||
* @param fd File descriptor of IPC client
|
||||
*
|
||||
* @return Address to allocated IPCClient struct
|
||||
*/
|
||||
IPCClient *ipc_client_new(int fd);
|
||||
|
||||
/**
|
||||
* Add an IPC Client to the specified list
|
||||
*
|
||||
* @param list Address of the list to add the client to
|
||||
* @param nc Address of the IPCClient
|
||||
*/
|
||||
void ipc_list_add_client(IPCClientList *list, IPCClient *nc);
|
||||
|
||||
/**
|
||||
* Remove an IPCClient from the specified list
|
||||
*
|
||||
* @param list Address of the list to remove the client from
|
||||
* @param c Address of the IPCClient
|
||||
*/
|
||||
void ipc_list_remove_client(IPCClientList *list, IPCClient *c);
|
||||
|
||||
/**
|
||||
* Get an IPCClient from the specified IPCClient list
|
||||
*
|
||||
* @param list List to remove the client from
|
||||
* @param fd File descriptor of the IPCClient
|
||||
*/
|
||||
IPCClient *ipc_list_get_client(IPCClientList list, int fd);
|
||||
|
||||
#endif // IPC_CLIENT_H_
|
20
LICENSE
20
LICENSE
@ -1,10 +1,22 @@
|
||||
MIT/X Consortium License
|
||||
|
||||
© 2006-2007 Anselm R. Garbe <garbeam at gmail dot com>
|
||||
© 2006-2019 Anselm R Garbe <anselm@garbe.ca>
|
||||
© 2006-2009 Jukka Salmi <jukka at salmi dot ch>
|
||||
© 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>
|
||||
© 2007-2011 Peter Hartlich <sgkkr at hartlich dot com>
|
||||
© 2007-2009 Szabolcs Nagy <nszabolcs at gmail dot com>
|
||||
© 2007-2009 Christof Musik <christof at sendfax dot de>
|
||||
© 2007-2009 Premysl Hruby <dfenze at gmail dot com>
|
||||
© 2007-2008 Enno Gottox Boland <gottox at s01 dot de>
|
||||
© 2008 Martin Hurton <martin dot hurton at gmail dot com>
|
||||
© 2008 Neale Pickett <neale dot woozle dot org>
|
||||
© 2009 Mate Nagy <mnagy at port70 dot net>
|
||||
© 2010-2016 Hiltjo Posthuma <hiltjo@codemadness.org>
|
||||
© 2010-2012 Connor Lane Smith <cls@lubutu.com>
|
||||
© 2011 Christoph Lohmann <20h@r-36.net>
|
||||
© 2015-2016 Quentin Rameau <quinq@fifth.space>
|
||||
© 2015-2016 Eric Pruitt <eric.pruitt@gmail.com>
|
||||
© 2016-2017 Markus Teich <markus.teich@stusta.mhn.de>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
58
Makefile
58
Makefile
@ -1,12 +1,12 @@
|
||||
# dwm - dynamic window manager
|
||||
# © 2006-2007 Anselm R. Garbe, Sander van Dijk
|
||||
# See LICENSE file for copyright and license details.
|
||||
|
||||
include config.mk
|
||||
|
||||
SRC += client.c draw.c event.c main.c screen.c util.c
|
||||
SRC = drw.c dwm.c util.c
|
||||
OBJ = ${SRC:.c=.o}
|
||||
|
||||
all: options dwm
|
||||
all: options dwm dwm-msg
|
||||
|
||||
options:
|
||||
@echo dwm build options:
|
||||
@ -15,46 +15,42 @@ options:
|
||||
@echo "CC = ${CC}"
|
||||
|
||||
.c.o:
|
||||
@echo CC $<
|
||||
@${CC} -c ${CFLAGS} $<
|
||||
${CC} -c ${CFLAGS} $<
|
||||
|
||||
${OBJ}: dwm.h config.h config.mk
|
||||
${OBJ}: config.h config.mk
|
||||
|
||||
config.h:
|
||||
@echo creating $@ from config.default.h
|
||||
@cp config.default.h $@
|
||||
cp config.def.h $@
|
||||
|
||||
dwm: ${OBJ}
|
||||
@echo CC -o $@
|
||||
@${CC} -o $@ ${OBJ} ${LDFLAGS}
|
||||
${CC} -o $@ ${OBJ} ${LDFLAGS}
|
||||
|
||||
dwm-msg: dwm-msg.o
|
||||
${CC} -o $@ $< ${LDFLAGS}
|
||||
|
||||
clean:
|
||||
@echo cleaning
|
||||
@rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
|
||||
rm -f dwm dwm-msg ${OBJ} dwm-${VERSION}.tar.gz config.h
|
||||
|
||||
dist: clean
|
||||
@echo creating dist tarball
|
||||
@mkdir -p dwm-${VERSION}
|
||||
@cp -R LICENSE Makefile README config.*.h config.mk \
|
||||
dwm.1 dwm.h tile.h ${SRC} dwm-${VERSION}
|
||||
@tar -cf dwm-${VERSION}.tar dwm-${VERSION}
|
||||
@gzip dwm-${VERSION}.tar
|
||||
@rm -rf dwm-${VERSION}
|
||||
mkdir -p dwm-${VERSION}
|
||||
cp -R LICENSE Makefile README config.def.h config.mk\
|
||||
dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION}
|
||||
tar -cf dwm-${VERSION}.tar dwm-${VERSION}
|
||||
gzip dwm-${VERSION}.tar
|
||||
rm -rf dwm-${VERSION}
|
||||
|
||||
install: all
|
||||
@echo installing executable file to ${DESTDIR}${PREFIX}/bin
|
||||
@mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||
@cp -f dwm ${DESTDIR}${PREFIX}/bin
|
||||
@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
|
||||
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1
|
||||
mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||
cp -f dwm dwmc dwm-msg ${DESTDIR}${PREFIX}/bin
|
||||
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
|
||||
chmod 755 ${DESTDIR}${PREFIX}/bin/dwmc
|
||||
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm-msg
|
||||
mkdir -p ${DESTDIR}${MANPREFIX}/man1
|
||||
sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
|
||||
chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1
|
||||
|
||||
uninstall:
|
||||
@echo removing executable file from ${DESTDIR}${PREFIX}/bin
|
||||
@rm -f ${DESTDIR}${PREFIX}/bin/dwm
|
||||
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
|
||||
@rm -f ${DESTDIR}${MANPREFIX}/man1/dwm.1
|
||||
rm -f ${DESTDIR}${PREFIX}/bin/dwm*\
|
||||
${DESTDIR}${MANPREFIX}/man1/dwm.1
|
||||
|
||||
.PHONY: all options clean dist install uninstall
|
||||
|
48
README
48
README
@ -1,48 +0,0 @@
|
||||
dwm - dynamic window manager
|
||||
============================
|
||||
dwm is an extremely fast, small, and dynamic window manager for X.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
In order to build dwm you need the Xlib header files.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
Edit config.mk to match your local setup (dwm is installed into
|
||||
the /usr/local namespace by default).
|
||||
|
||||
Afterwards enter the following command to build and install dwm (if
|
||||
necessary as root):
|
||||
|
||||
make clean install
|
||||
|
||||
|
||||
Running dwm
|
||||
-----------
|
||||
Add the following line to your .xinitrc to start dwm using startx:
|
||||
|
||||
exec dwm
|
||||
|
||||
In order to connect dwm to a specific display, make sure that
|
||||
the DISPLAY environment variable is set correctly, e.g.:
|
||||
|
||||
DISPLAY=foo.bar:1 exec dwm
|
||||
|
||||
(This will start dwm on display :1 of the host foo.bar.)
|
||||
|
||||
In order to display status info in the bar, you can do something
|
||||
like this in your .xinitrc:
|
||||
|
||||
while true
|
||||
do
|
||||
echo `date` `uptime | sed 's/.*,//'`
|
||||
sleep 1
|
||||
done | dwm
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
The configuration of dwm is done by creating a custom config.h
|
||||
and (re)compiling the source code.
|
86
README.md
Normal file
86
README.md
Normal file
@ -0,0 +1,86 @@
|
||||
# dwm - dynamic window manager
|
||||
|
||||
Sravan's custom build of dwm. Original dwm build by suckless team found here: [https://dwm.suckless.org/](https://dwm.suckless.org/)
|
||||
Choice of patches heavily inspired by [Palmdrop's custom build of dwm](https://github.com/palmdrop/dwm).
|
||||
|
||||
## Requirements
|
||||
|
||||
In order to build dwm you need the Xlib header files.
|
||||
|
||||
## Installation
|
||||
|
||||
Edit [config.mk](config.mk) to match your local setup (dwm is installed into
|
||||
the /usr/local namespace by default).
|
||||
|
||||
Afterwards enter the following command to build and install dwm (if
|
||||
necessary as root):
|
||||
|
||||
```
|
||||
make clean install
|
||||
```
|
||||
|
||||
## Running dwm
|
||||
|
||||
Add the following line to your .xinitrc to start dwm using startx:
|
||||
|
||||
```
|
||||
exec dwm
|
||||
```
|
||||
|
||||
In order to connect dwm to a specific display, make sure that
|
||||
the DISPLAY environment variable is set correctly, e.g.:
|
||||
|
||||
```
|
||||
DISPLAY=foo.bar:1 exec dwm
|
||||
```
|
||||
|
||||
(This will start dwm on display :1 of the host foo.bar.)
|
||||
|
||||
In order to display status info in the bar, you can do something
|
||||
like this in your .xinitrc:
|
||||
|
||||
```
|
||||
while xsetroot -name "`date` `uptime | sed 's/.*,//'`"
|
||||
do
|
||||
sleep 1
|
||||
done &
|
||||
exec dwm
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The configuration of dwm is done by creating a custom config.h
|
||||
and (re)compiling the source code.
|
||||
|
||||
## Patches
|
||||
|
||||
Most patches can be found on the suckless website: [https://dwm.suckless.org/patches/](https://dwm.suckless.org/patches/)
|
||||
|
||||
* [actualfullscreen](https://dwm.suckless.org/patches/actualfullscreen/) - Actually toggle fullscreen for a window, instead of toggling the status bar and the monocle layout
|
||||
* [alwaysfullscreen](https://dwm.suckless.org/patches/alwaysfullscreen/) - Do not allow the focus to drift from the active fullscreen client when using focusstack()
|
||||
* [anybar](https://github.com/mihirlad55/dwm-anybar) (Polybar Tray Fix Version) - Enables dwm to manage external status bars such as lemonbar and polybar
|
||||
* [aspectresize](https://dwm.suckless.org/patches/aspectresize/) - Allows you to resize a window while maintaining aspect ratio
|
||||
* [attachbelow](https://dwm.suckless.org/patches/attachbelow/) (Toggleable) - Make new clients attach below the selected client, instead of always becoming the new master
|
||||
* [autoresize](https://dwm.suckless.org/patches/autoresize/) - Windows that are not visible when requesting a resize/move will get resized/moved
|
||||
* [center](https://dwm.suckless.org/patches/center/) - Add an `iscentered` rule to automatically center clients on the current monitor
|
||||
* [cfacts](https://dwm.suckless.org/patches/cfacts/) - Assign different weights to clients in their respective stack in tiled layout
|
||||
* [cfacts-vanitygaps](https://github.com/bakkeby/patches/blob/master/dwm/dwm-cfacts-vanitygaps-6.2.diff) - Vanity gaps patch compatible with cfacts patch
|
||||
* [combo](https://dwm.suckless.org/patches/combo/) - Select multiple tags for tag or view by pressing all the right keys as a combo
|
||||
* [cool autostart](https://dwm.suckless.org/patches/cool_autostart/) - Execute commands from `autostart` array in `config.h` on startup and kill processes upon dwm exit
|
||||
* [cyclelayouts](https://dwm.suckless.org/patches/cyclelayouts/) - Cycle through all available layouts
|
||||
* [dwmc](https://dwm.suckless.org/patches/dwmc/) - Simple dwmc client using a fork of [fsignal](https://dwm.suckless.org/patches/fsignal/) to communicate with dwm
|
||||
* [fixborders](https://dwm.suckless.org/patches/alpha/) - Make borders opaque
|
||||
* [ipc](https://github.com/mihirlad55/dwm-ipc) - Allows third party programs (e.g. polybar) to query window manager for information
|
||||
* [movestack](https://dwm.suckless.org/patches/movestack/) - Move clients around in the stack and swap them with the master
|
||||
* [noborder](https://dwm.suckless.org/patches/noborder/) (Floating Fix) - Remove the border when there is only one window visible
|
||||
* [swallow](https://dwm.suckless.org/patches/swallow/) - Programs opened from terminal will "swallow" the terminal
|
||||
* [unfloatvisible](https://dwm.suckless.org/patches/unfloatvisible/) - Resets `isfloating` on any visible windows that have it set
|
||||
* [xresources](https://dwm.suckless.org/patches/xresources/) - Allows dwm settings (e.g. colors) to be set in Xresources
|
||||
|
||||
## Polybar
|
||||
|
||||
The anybar and ipc patches above allow dwm to use an external status bar.
|
||||
I am using polybar. My config can be found [here](https://github.com/balajsra/polybar).
|
||||
|
||||
* [Polybar DWM Module](https://github.com/mihirlad55/polybar-dwm-module)
|
||||
* [Polybar](https://github.com/polybar/polybar)
|
386
client.c
386
client.c
@ -1,386 +0,0 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
#include "dwm.h"
|
||||
#include <stdlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
static void
|
||||
grabbuttons(Client *c, Bool focused) {
|
||||
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
|
||||
|
||||
if(focused) {
|
||||
XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK,
|
||||
GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK,
|
||||
GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button1, MODKEY | numlockmask, c->win, False, BUTTONMASK,
|
||||
GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button1, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
|
||||
GrabModeAsync, GrabModeSync, None, None);
|
||||
|
||||
XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK,
|
||||
GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button2, MODKEY | LockMask, c->win, False, BUTTONMASK,
|
||||
GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button2, MODKEY | numlockmask, c->win, False, BUTTONMASK,
|
||||
GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button2, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
|
||||
GrabModeAsync, GrabModeSync, None, None);
|
||||
|
||||
XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK,
|
||||
GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button3, MODKEY | LockMask, c->win, False, BUTTONMASK,
|
||||
GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button3, MODKEY | numlockmask, c->win, False, BUTTONMASK,
|
||||
GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button3, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
|
||||
GrabModeAsync, GrabModeSync, None, None);
|
||||
}
|
||||
else
|
||||
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK,
|
||||
GrabModeAsync, GrabModeSync, None, None);
|
||||
}
|
||||
|
||||
static 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 */
|
||||
|
||||
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) {
|
||||
XConfigureEvent ce;
|
||||
|
||||
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 && 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);
|
||||
attachstack(c);
|
||||
grabbuttons(c, True);
|
||||
}
|
||||
sel = c;
|
||||
drawstatus();
|
||||
if(!selscreen)
|
||||
return;
|
||||
if(c) {
|
||||
XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
|
||||
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
|
||||
}
|
||||
else
|
||||
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
|
||||
}
|
||||
|
||||
void
|
||||
killclient(const char *arg) {
|
||||
XEvent ev;
|
||||
|
||||
if(!sel)
|
||||
return;
|
||||
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) {
|
||||
unsigned int i;
|
||||
Client *c, *t = NULL;
|
||||
Window trans;
|
||||
Status rettrans;
|
||||
XWindowChanges wc;
|
||||
|
||||
c = emallocz(sizeof(Client));
|
||||
c->tags = emallocz(ntags * sizeof(Bool));
|
||||
c->win = w;
|
||||
c->x = wa->x;
|
||||
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->x = sx;
|
||||
c->y = sy;
|
||||
c->border = wa->border_width;
|
||||
}
|
||||
else {
|
||||
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);
|
||||
XSelectInput(dpy, w,
|
||||
StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
|
||||
grabbuttons(c, False);
|
||||
updatetitle(c);
|
||||
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);
|
||||
setclientstate(c, NormalState);
|
||||
arrange();
|
||||
}
|
||||
|
||||
void
|
||||
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)
|
||||
w -= (w - c->basew) % c->incw;
|
||||
if(c->inch)
|
||||
h -= (h - c->baseh) % c->inch;
|
||||
}
|
||||
if(w <= 0 || h <= 0)
|
||||
return;
|
||||
/* offscreen appearance fixes */
|
||||
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
|
||||
updatesizehints(Client *c) {
|
||||
long msize;
|
||||
XSizeHints size;
|
||||
|
||||
if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
|
||||
size.flags = PSize;
|
||||
c->flags = size.flags;
|
||||
if(c->flags & PBaseSize) {
|
||||
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) {
|
||||
c->incw = size.width_inc;
|
||||
c->inch = size.height_inc;
|
||||
}
|
||||
else
|
||||
c->incw = c->inch = 0;
|
||||
if(c->flags & PMaxSize) {
|
||||
c->maxw = size.max_width;
|
||||
c->maxh = size.max_height;
|
||||
}
|
||||
else
|
||||
c->maxw = c->maxh = 0;
|
||||
if(c->flags & PMinSize) {
|
||||
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;
|
||||
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) {
|
||||
if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
|
||||
gettextprop(c->win, wmatom[WMName], c->name, sizeof c->name);
|
||||
}
|
96
config.arg.h
96
config.arg.h
@ -1,96 +0,0 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
/* appearance */
|
||||
#define BARPOS BarTop /* BarBot, BarOff */
|
||||
#define BORDERPX 1
|
||||
#define FONT "-*-terminus-medium-r-*-*-14-*-*-*-*-*-iso10646-*"
|
||||
#define NORMBORDERCOLOR "#333"
|
||||
#define NORMBGCOLOR "#222"
|
||||
#define NORMFGCOLOR "#ccc"
|
||||
#define SELBORDERCOLOR "#59a"
|
||||
#define SELBGCOLOR "#555"
|
||||
#define SELFGCOLOR "#fff"
|
||||
|
||||
/* tagging */
|
||||
#define TAGS \
|
||||
const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
|
||||
#define RULES \
|
||||
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 }, \
|
||||
};
|
350
config.def.h
Normal file
350
config.def.h
Normal file
@ -0,0 +1,350 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
/* appearance */
|
||||
static unsigned int borderpx = 2; /* border pixel of windows */
|
||||
static const unsigned int snap = 32; /* snap pixel */
|
||||
static unsigned int gappih = 20; /* horiz inner gap between windows */
|
||||
static unsigned int gappiv = 20; /* vert inner gap between windows */
|
||||
static unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */
|
||||
static unsigned int gappov = 10; /* vert outer gap between windows and screen edge */
|
||||
static const int noborder = 0; /* 1 means no border when there is only one window */
|
||||
static const int swallowfloating = 0; /* 1 means swallow floating windows by default */
|
||||
static int smartgaps = 0; /* 1 means no outer gap when there is only one window */
|
||||
static const int showbar = 1; /* 0 means no bar */
|
||||
static const int topbar = 1; /* 0 means bottom bar */
|
||||
static const int usealtbar = 1; /* 1 means use non-dwm status bar */
|
||||
static const char *altbarclass = "Polybar"; /* Alternate bar class name */
|
||||
static const char *alttrayname = "tray"; /* Polybar tray instance name */
|
||||
static const char *altbarcmd = "$HOME/.config/polybar/launch.sh"; /* Alternate bar launch command */
|
||||
static const char *fonts[] = { "NotoSans Nerd Font:size=10" };
|
||||
static char normbgcolor[] = "#222222"; /* background color */
|
||||
static char normbordercolor[] = "#444444"; /* inactive window border color */
|
||||
static char normfgcolor[] = "#bbbbbb"; /* font color */
|
||||
static char selfgcolor[] = "#eeeeee"; /* current tag and current window font color */
|
||||
static char selbordercolor[] = "#005577"; /* Top bar second color and active window border color */
|
||||
static char selbgcolor[] = "#005577"; /* Top bar second color and active window border color */
|
||||
static char *colors[][3] = {
|
||||
/* fg bg border */
|
||||
[SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor },
|
||||
[SchemeSel] = { selfgcolor, selbgcolor, selbordercolor },
|
||||
};
|
||||
|
||||
static const char *const autostart[] = {
|
||||
// System Restore Processes
|
||||
"bash", "/home/sravan/.screenlayout/default-screen-layout.sh", NULL, // Restore default screen layout
|
||||
"nitrogen", "--restore", NULL, // Restore wallpaper
|
||||
"numlockx", "on", NULL, // NumLock on by default
|
||||
// System Tray Applications
|
||||
"volctl", NULL, // PulseAudio Volume Control
|
||||
"nyrna", NULL, // Nyrna Application Suspend
|
||||
"blueman-applet", NULL, // Blueman Bluetooth Manager
|
||||
"nm-applet", NULL, // Network Manager Applet
|
||||
"kdeconnect-indicator", NULL, // KDE Connect
|
||||
"flameshot", NULL, // Flameshot Screenshot Tool
|
||||
"xfce4-power-manager", NULL, // XFCE4 Power Manager
|
||||
// Background Processes
|
||||
"bash", "/home/sravan/.config/picom/toggle_picom.sh", NULL, // Picom Compositor
|
||||
"bash", "/home/sravan/.config/dunst/launch_dunst.sh", NULL, // Dunst Notification Daemon
|
||||
"greenclip", "daemon", NULL, // Greenclip Clipboard Manager
|
||||
"redshift", "-x", NULL, // Reset redshift display gamma
|
||||
"redshift-gtk", NULL, // Redshift Blue Light Filter
|
||||
"/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1", NULL, // GNOME Polkit Authentication Agent
|
||||
"xss-lock", "-l", "--", "multilockscreen", "--lock", NULL, // Session lock handler
|
||||
// Hardware Driver Applications
|
||||
"solaar", "--window=hide", NULL, // Logitech Mouse Driver
|
||||
"openrgb", "--startminimized", NULL, // OpenRGB
|
||||
"optimus-manager-qt", NULL, // Optimus Manager Qt
|
||||
NULL /* terminate */
|
||||
};
|
||||
|
||||
/* tagging */
|
||||
static const char *tags[] = { " ₁", "龎 ₂", " ₃", " ₄", "爵 ₅", " ₆", " ₇", " ₈", " ₉" };
|
||||
|
||||
static const Rule rules[] = {
|
||||
/* xprop(1):
|
||||
* WM_CLASS(STRING) = instance, class
|
||||
* WM_NAME(STRING) = title
|
||||
*/
|
||||
/* class instance title tags mask isfloating isterminal noswallow monitor */
|
||||
{ NULL, NULL, "Origin", 0, 1, 0, 0, -1 },
|
||||
{ "kitty", NULL, NULL, 0, 0, 0, 1, -1 },
|
||||
{ NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */
|
||||
};
|
||||
|
||||
/* layout(s) */
|
||||
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
||||
static const int nmaster = 1; /* number of clients in master area */
|
||||
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
||||
static int attachbelow = 1; /* 1 means attach after the currently active window */
|
||||
|
||||
#define FORCE_VSPLIT 1 /* nrowgrid layout: force two clients to always split vertically */
|
||||
#include "vanitygaps.c"
|
||||
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
{ "[]=", tile }, /* first entry is default */
|
||||
{ "[M]", monocle },
|
||||
{ "[@]", spiral },
|
||||
{ "[\\]", dwindle },
|
||||
{ "H[]", deck },
|
||||
{ "TTT", bstack },
|
||||
{ "===", bstackhoriz },
|
||||
{ "HHH", grid },
|
||||
{ "###", nrowgrid },
|
||||
{ "---", horizgrid },
|
||||
{ ":::", gaplessgrid },
|
||||
{ "|M|", centeredmaster },
|
||||
{ ">M>", centeredfloatingmaster },
|
||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||
};
|
||||
|
||||
/* key definitions */
|
||||
#define MODKEY Mod4Mask /* Mod1Mask = Alt, Mod4Mask = Super */
|
||||
#define TAGKEYS(KEY,TAG) \
|
||||
{ MODKEY, KEY, comboview, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|ShiftMask, KEY, combotag, {.ui = 1 << TAG} }, \
|
||||
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
|
||||
|
||||
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
||||
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||
|
||||
/* commands */
|
||||
static const char *rofiruncmd[] = { "rofi", "-show", "drun", NULL };
|
||||
static const char *roficlipcmd[] = { "rofi", "-show", "clipboard", NULL };
|
||||
static const char *lockcmd[] = { "loginctl", "lock-session", NULL };
|
||||
static const char *sleepcmd[] = { "systemctl", "suspend", NULL };
|
||||
static const char *termcmd[] = { "kitty", NULL };
|
||||
static const char *upvolcmd[] = { "/usr/bin/pactl", "set-sink-volume", "@DEFAULT_SINK@", "+1%", NULL };
|
||||
static const char *downvolcmd[] = { "/usr/bin/pactl", "set-sink-volume", "@DEFAULT_SINK@", "-1%", NULL };
|
||||
static const char *mutevolcmd[] = { "/usr/bin/pactl", "set-sink-mute", "@DEFAULT_SINK@", "toggle", NULL };
|
||||
static const char *playerplaypausecmd[] = { "playerctl", "--player=playerctld", "play-pause", NULL };
|
||||
static const char *playernextcmd[] = { "playerctl", "--player=playerctld", "next", NULL };
|
||||
static const char *playerprevcmd[] = { "playerctl", "--player=playerctld", "previous", NULL };
|
||||
static const char *playershiftcmd[] = { "playerctld", "shift", NULL};
|
||||
static const char *flameshotcmd[] = { "flameshot", "gui", NULL };
|
||||
static const char *notifycontextcmd[] = { "dunstctl", "context", NULL };
|
||||
static const char *notifyhistorycmd[] = { "dunstctl", "history-pop", NULL };
|
||||
static const char *notifyclosecmd[] = { "dunstctl", "close", NULL };
|
||||
static const char *notifytogglecmd[] = { "dunstctl", "set-paused", "toggle", NULL };
|
||||
static const char *compositortogglecmd[] = { "/bin/bash", "/home/sravan/.config/picom/toggle_picom.sh", NULL, };
|
||||
|
||||
/*
|
||||
* Xresources preferences to load at startup
|
||||
*/
|
||||
ResourcePref resources[] = {
|
||||
{ "normbgcolor", STRING, &normbgcolor },
|
||||
{ "normbordercolor", STRING, &normbordercolor },
|
||||
{ "normfgcolor", STRING, &normfgcolor },
|
||||
{ "selbgcolor", STRING, &selbgcolor },
|
||||
{ "selbordercolor", STRING, &selbordercolor },
|
||||
{ "selfgcolor", STRING, &selfgcolor },
|
||||
{ "borderpx", INTEGER, &borderpx },
|
||||
{ "gappih", INTEGER, &gappih },
|
||||
{ "gappiv", INTEGER, &gappiv },
|
||||
{ "gappoh", INTEGER, &gappoh },
|
||||
{ "gappov", INTEGER, &gappov },
|
||||
// { "snap", INTEGER, &snap },
|
||||
// { "showbar", INTEGER, &showbar },
|
||||
// { "topbar", INTEGER, &topbar },
|
||||
// { "nmaster", INTEGER, &nmaster },
|
||||
// { "resizehints", INTEGER, &resizehints },
|
||||
// { "mfact", FLOAT, &mfact },
|
||||
};
|
||||
|
||||
#include "movestack.c"
|
||||
#include "unfloat.c"
|
||||
#include <X11/XF86keysym.h>
|
||||
static Key keys[] = {
|
||||
/* modifier key function argument */
|
||||
{ MODKEY, XK_p, spawn, {.v = rofiruncmd} },
|
||||
{ MODKEY, XK_c, spawn, {.v = roficlipcmd} },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_l, spawn, {.v = lockcmd} },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_s, spawn, {.v = sleepcmd} },
|
||||
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd} },
|
||||
{ MODKEY, XK_n, spawn, {.v = notifycontextcmd} },
|
||||
{ MODKEY|ShiftMask, XK_n, spawn, {.v = notifyhistorycmd} },
|
||||
{ MODKEY|ControlMask, XK_n, spawn, {.v = notifyclosecmd} },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_n, spawn, {.v = notifytogglecmd} },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_Escape, spawn, {.v = compositortogglecmd} },
|
||||
{ MODKEY, XK_b, togglebar, {0} },
|
||||
{ MODKEY, XK_j, focusstack, {.i = +1 } },
|
||||
{ MODKEY, XK_k, focusstack, {.i = -1 } },
|
||||
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
||||
{ MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
|
||||
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
|
||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
||||
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||
{ MODKEY|ShiftMask, XK_h, setcfact, {.f = +0.25} },
|
||||
{ MODKEY|ShiftMask, XK_l, setcfact, {.f = -0.25} },
|
||||
{ MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} },
|
||||
{ MODKEY, XK_Return, zoom, {0} },
|
||||
{ MODKEY|ControlMask, XK_u, incrgaps, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_u, incrgaps, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_i, incrigaps, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_i, incrigaps, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_o, incrogaps, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_o, incrogaps, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_6, incrihgaps, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_6, incrihgaps, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_7, incrivgaps, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_7, incrivgaps, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_8, incrohgaps, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_8, incrohgaps, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_9, incrovgaps, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_9, incrovgaps, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_0, togglegaps, {0} },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_0, defaultgaps, {0} },
|
||||
{ MODKEY, XK_Tab, comboview, {0} },
|
||||
{ MODKEY|ControlMask, XK_j, aspectresize, {.i = +24} },
|
||||
{ MODKEY|ControlMask, XK_k, aspectresize, {.i = -24} },
|
||||
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_c, spawn, SHCMD("kill -SEGV ""\"$(xprop | grep PID| awk '{print $3}')""\"") },
|
||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
||||
{ MODKEY|ShiftMask, XK_t, unfloatvisible, {.v = &layouts[0]} },
|
||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY|ShiftMask, XK_m, unfloatvisible, {.v = &layouts[1]} },
|
||||
{ MODKEY, XK_g, setlayout, {.v = &layouts[7]} },
|
||||
{ MODKEY|ShiftMask, XK_g, unfloatvisible, {.v = &layouts[7]} },
|
||||
{ MODKEY, XK_u, setlayout, {.v = &layouts[11]} },
|
||||
{ MODKEY|ShiftMask, XK_u, unfloatvisible, {.v = &layouts[11]} },
|
||||
{ MODKEY, XK_f, setlayout, {.v = &layouts[13]} },
|
||||
{ MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } },
|
||||
{ MODKEY, XK_space, setlayout, {0} },
|
||||
{ MODKEY|ShiftMask, XK_space, unfloatvisible, {0} },
|
||||
{ MODKEY|ControlMask, XK_space, togglefloating, {0} },
|
||||
{ MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
|
||||
{ MODKEY|ShiftMask, XK_Tab, toggleAttachBelow, {0} },
|
||||
{ MODKEY, XK_0, comboview, {.ui = ~0 } },
|
||||
{ MODKEY|ShiftMask, XK_0, combotag, {.ui = ~0 } },
|
||||
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
|
||||
{ MODKEY, XK_period, focusmon, {.i = +1 } },
|
||||
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
|
||||
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_Tab, spawn, {.v = playershiftcmd} },
|
||||
{ 0, XF86XK_AudioLowerVolume, spawn, {.v = downvolcmd} },
|
||||
{ 0, XF86XK_AudioMute, spawn, {.v = mutevolcmd} },
|
||||
{ 0, XF86XK_AudioRaiseVolume, spawn, {.v = upvolcmd} },
|
||||
{ 0, XF86XK_AudioPlay, spawn, {.v = playerplaypausecmd} },
|
||||
{ 0, XF86XK_AudioNext, spawn, {.v = playernextcmd} },
|
||||
{ 0, XF86XK_AudioPrev, spawn, {.v = playerprevcmd} },
|
||||
{ 0, XK_Print, spawn, {.v = flameshotcmd} },
|
||||
TAGKEYS( XK_1, 0)
|
||||
TAGKEYS( XK_2, 1)
|
||||
TAGKEYS( XK_3, 2)
|
||||
TAGKEYS( XK_4, 3)
|
||||
TAGKEYS( XK_5, 4)
|
||||
TAGKEYS( XK_6, 5)
|
||||
TAGKEYS( XK_7, 6)
|
||||
TAGKEYS( XK_8, 7)
|
||||
TAGKEYS( XK_9, 8)
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_q, quit, {0} },
|
||||
};
|
||||
|
||||
/* button definitions */
|
||||
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
|
||||
static Button buttons[] = {
|
||||
/* click event mask button function argument */
|
||||
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
||||
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
||||
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
||||
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
|
||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
||||
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
||||
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
||||
{ ClkTagBar, 0, Button1, comboview, {0} },
|
||||
{ ClkTagBar, 0, Button3, toggleview, {0} },
|
||||
{ ClkTagBar, MODKEY, Button1, combotag, {0} },
|
||||
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
||||
};
|
||||
|
||||
static const char *ipcsockpath = "/tmp/dwm.sock";
|
||||
static IPCCommand ipccommands[] = {
|
||||
IPCCOMMAND( view, 1, {ARG_TYPE_UINT} ),
|
||||
IPCCOMMAND( toggleview, 1, {ARG_TYPE_UINT} ),
|
||||
IPCCOMMAND( tag, 1, {ARG_TYPE_UINT} ),
|
||||
IPCCOMMAND( toggletag, 1, {ARG_TYPE_UINT} ),
|
||||
IPCCOMMAND( tagmon, 1, {ARG_TYPE_UINT} ),
|
||||
IPCCOMMAND( focusmon, 1, {ARG_TYPE_SINT} ),
|
||||
IPCCOMMAND( focusstack, 1, {ARG_TYPE_SINT} ),
|
||||
IPCCOMMAND( zoom, 1, {ARG_TYPE_NONE} ),
|
||||
IPCCOMMAND( incnmaster, 1, {ARG_TYPE_SINT} ),
|
||||
IPCCOMMAND( killclient, 1, {ARG_TYPE_SINT} ),
|
||||
IPCCOMMAND( togglefloating, 1, {ARG_TYPE_NONE} ),
|
||||
IPCCOMMAND( setmfact, 1, {ARG_TYPE_FLOAT} ),
|
||||
IPCCOMMAND( setlayoutsafe, 1, {ARG_TYPE_PTR} ),
|
||||
IPCCOMMAND( quit, 1, {ARG_TYPE_NONE} )
|
||||
};
|
||||
|
||||
void
|
||||
setlayoutex(const Arg *arg)
|
||||
{
|
||||
setlayout(&((Arg) { .v = &layouts[arg->i] }));
|
||||
}
|
||||
|
||||
void
|
||||
viewex(const Arg *arg)
|
||||
{
|
||||
view(&((Arg) { .ui = 1 << arg->ui }));
|
||||
}
|
||||
|
||||
void
|
||||
viewall(const Arg *arg)
|
||||
{
|
||||
view(&((Arg){.ui = ~0}));
|
||||
}
|
||||
|
||||
void
|
||||
toggleviewex(const Arg *arg)
|
||||
{
|
||||
toggleview(&((Arg) { .ui = 1 << arg->ui }));
|
||||
}
|
||||
|
||||
void
|
||||
tagex(const Arg *arg)
|
||||
{
|
||||
tag(&((Arg) { .ui = 1 << arg->ui }));
|
||||
}
|
||||
|
||||
void
|
||||
toggletagex(const Arg *arg)
|
||||
{
|
||||
toggletag(&((Arg) { .ui = 1 << arg->ui }));
|
||||
}
|
||||
|
||||
void
|
||||
tagall(const Arg *arg)
|
||||
{
|
||||
tag(&((Arg){.ui = ~0}));
|
||||
}
|
||||
|
||||
/* signal definitions */
|
||||
/* signum must be greater than 0 */
|
||||
/* trigger signals using `xsetroot -name "fsignal:<signame> [<type> <value>]"` */
|
||||
static Signal signals[] = {
|
||||
/* signum function */
|
||||
{ "focusstack", focusstack },
|
||||
{ "setmfact", setmfact },
|
||||
{ "togglebar", togglebar },
|
||||
{ "incnmaster", incnmaster },
|
||||
{ "togglefloating", togglefloating },
|
||||
{ "focusmon", focusmon },
|
||||
{ "tagmon", tagmon },
|
||||
{ "zoom", zoom },
|
||||
{ "view", view },
|
||||
{ "viewall", viewall },
|
||||
{ "viewex", viewex },
|
||||
{ "toggleview", view },
|
||||
{ "toggleviewex", toggleviewex },
|
||||
{ "tag", tag },
|
||||
{ "tagall", tagall },
|
||||
{ "tagex", tagex },
|
||||
{ "toggletag", tag },
|
||||
{ "toggletagex", toggletagex },
|
||||
{ "killclient", killclient },
|
||||
{ "quit", quit },
|
||||
{ "setlayout", setlayout },
|
||||
{ "setlayoutex", setlayoutex },
|
||||
};
|
@ -1,94 +0,0 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
/* appearance */
|
||||
#define BARPOS BarTop /* BarBot, BarOff */
|
||||
#define BORDERPX 1
|
||||
#define FONT "-*-fixed-medium-r-normal-*-13-*-*-*-*-*-*-*"
|
||||
#define NORMBORDERCOLOR "#dddddd"
|
||||
#define NORMBGCOLOR "#eeeeee"
|
||||
#define NORMFGCOLOR "#222222"
|
||||
#define SELBORDERCOLOR "#ff0000"
|
||||
#define SELBGCOLOR "#006699"
|
||||
#define SELFGCOLOR "#ffffff"
|
||||
|
||||
/* 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 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 }, \
|
||||
};
|
33
config.mk
33
config.mk
@ -1,11 +1,8 @@
|
||||
# dwm version
|
||||
VERSION = 4.4.1
|
||||
VERSION = 6.2
|
||||
|
||||
# Customize below to fit your system
|
||||
|
||||
# additional layouts beside floating
|
||||
SRC = tile.c
|
||||
|
||||
# paths
|
||||
PREFIX = /usr/local
|
||||
MANPREFIX = ${PREFIX}/share/man
|
||||
@ -13,20 +10,34 @@ MANPREFIX = ${PREFIX}/share/man
|
||||
X11INC = /usr/X11R6/include
|
||||
X11LIB = /usr/X11R6/lib
|
||||
|
||||
# Xinerama, comment if you don't want it
|
||||
XINERAMALIBS = -lXinerama
|
||||
XINERAMAFLAGS = -DXINERAMA
|
||||
|
||||
# freetype
|
||||
FREETYPELIBS = -lfontconfig -lXft
|
||||
FREETYPEINC = /usr/include/freetype2
|
||||
# OpenBSD (uncomment)
|
||||
#FREETYPEINC = ${X11INC}/freetype2
|
||||
#KVMLIB = -lkvm
|
||||
|
||||
# yajl
|
||||
YAJLLIBS = -lyajl
|
||||
YAJLINC = /usr/include/yajl
|
||||
|
||||
# includes and libs
|
||||
INCS = -I. -I/usr/include -I${X11INC}
|
||||
LIBS = -L/usr/lib -lc -L${X11LIB} -lX11
|
||||
INCS = -I${X11INC} -I${FREETYPEINC} -I${YAJLINC}
|
||||
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${YAJLLIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB}
|
||||
|
||||
# flags
|
||||
CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\"
|
||||
LDFLAGS = -s ${LIBS}
|
||||
#CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
|
||||
#LDFLAGS = -g ${LIBS}
|
||||
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
|
||||
#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
|
||||
CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS}
|
||||
LDFLAGS = ${LIBS}
|
||||
|
||||
# Solaris
|
||||
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
|
||||
#LDFLAGS = ${LIBS}
|
||||
#CFLAGS += -xtarget=ultra
|
||||
|
||||
# compiler and linker
|
||||
CC = cc
|
||||
|
134
draw.c
134
draw.c
@ -1,134 +0,0 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
#include "dwm.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) {
|
||||
Client *c;
|
||||
|
||||
for(c = clients; c; c = c->next)
|
||||
if(c->tags[t])
|
||||
return True;
|
||||
return False;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
textnw(const char *text, unsigned int len) {
|
||||
XRectangle r;
|
||||
|
||||
if(dc.font.set) {
|
||||
XmbTextExtents(dc.font.set, text, len, NULL, &r);
|
||||
return r.width;
|
||||
}
|
||||
return XTextWidth(dc.font.xfont, text, len);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
XRectangle r = { dc.x, dc.y, dc.w, dc.h };
|
||||
|
||||
XSetForeground(dpy, dc.gc, col[ColBG]);
|
||||
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
|
||||
if(!text)
|
||||
return;
|
||||
w = 0;
|
||||
olen = len = strlen(text);
|
||||
if(len >= sizeof buf)
|
||||
len = sizeof buf - 1;
|
||||
memcpy(buf, text, len);
|
||||
buf[len] = 0;
|
||||
h = dc.font.ascent + dc.font.descent;
|
||||
y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
|
||||
x = dc.x + (h / 2);
|
||||
/* shorten text if necessary */
|
||||
while(len && (w = textnw(buf, len)) > dc.w - h)
|
||||
buf[--len] = 0;
|
||||
if(len < olen) {
|
||||
if(len > 1)
|
||||
buf[len - 1] = '.';
|
||||
if(len > 2)
|
||||
buf[len - 2] = '.';
|
||||
if(len > 3)
|
||||
buf[len - 3] = '.';
|
||||
}
|
||||
if(w > dc.w)
|
||||
return; /* too long */
|
||||
XSetForeground(dpy, dc.gc, col[ColFG]);
|
||||
if(dc.font.set)
|
||||
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
|
||||
textw(const char *text) {
|
||||
return textnw(text, strlen(text)) + dc.font.height;
|
||||
}
|
438
drw.c
Normal file
438
drw.c
Normal file
@ -0,0 +1,438 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xft/Xft.h>
|
||||
|
||||
#include "drw.h"
|
||||
#include "util.h"
|
||||
|
||||
#define UTF_INVALID 0xFFFD
|
||||
#define UTF_SIZ 4
|
||||
|
||||
static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
|
||||
static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
|
||||
static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
|
||||
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
|
||||
|
||||
static long
|
||||
utf8decodebyte(const char c, size_t *i)
|
||||
{
|
||||
for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
|
||||
if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
|
||||
return (unsigned char)c & ~utfmask[*i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t
|
||||
utf8validate(long *u, size_t i)
|
||||
{
|
||||
if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
|
||||
*u = UTF_INVALID;
|
||||
for (i = 1; *u > utfmax[i]; ++i)
|
||||
;
|
||||
return i;
|
||||
}
|
||||
|
||||
static size_t
|
||||
utf8decode(const char *c, long *u, size_t clen)
|
||||
{
|
||||
size_t i, j, len, type;
|
||||
long udecoded;
|
||||
|
||||
*u = UTF_INVALID;
|
||||
if (!clen)
|
||||
return 0;
|
||||
udecoded = utf8decodebyte(c[0], &len);
|
||||
if (!BETWEEN(len, 1, UTF_SIZ))
|
||||
return 1;
|
||||
for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
|
||||
udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
|
||||
if (type)
|
||||
return j;
|
||||
}
|
||||
if (j < len)
|
||||
return 0;
|
||||
*u = udecoded;
|
||||
utf8validate(u, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
Drw *
|
||||
drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
|
||||
{
|
||||
Drw *drw = ecalloc(1, sizeof(Drw));
|
||||
|
||||
drw->dpy = dpy;
|
||||
drw->screen = screen;
|
||||
drw->root = root;
|
||||
drw->w = w;
|
||||
drw->h = h;
|
||||
drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
|
||||
drw->gc = XCreateGC(dpy, root, 0, NULL);
|
||||
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
|
||||
|
||||
return drw;
|
||||
}
|
||||
|
||||
void
|
||||
drw_resize(Drw *drw, unsigned int w, unsigned int h)
|
||||
{
|
||||
if (!drw)
|
||||
return;
|
||||
|
||||
drw->w = w;
|
||||
drw->h = h;
|
||||
if (drw->drawable)
|
||||
XFreePixmap(drw->dpy, drw->drawable);
|
||||
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
|
||||
}
|
||||
|
||||
void
|
||||
drw_free(Drw *drw)
|
||||
{
|
||||
XFreePixmap(drw->dpy, drw->drawable);
|
||||
XFreeGC(drw->dpy, drw->gc);
|
||||
drw_fontset_free(drw->fonts);
|
||||
free(drw);
|
||||
}
|
||||
|
||||
/* This function is an implementation detail. Library users should use
|
||||
* drw_fontset_create instead.
|
||||
*/
|
||||
static Fnt *
|
||||
xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
|
||||
{
|
||||
Fnt *font;
|
||||
XftFont *xfont = NULL;
|
||||
FcPattern *pattern = NULL;
|
||||
|
||||
if (fontname) {
|
||||
/* Using the pattern found at font->xfont->pattern does not yield the
|
||||
* same substitution results as using the pattern returned by
|
||||
* FcNameParse; using the latter results in the desired fallback
|
||||
* behaviour whereas the former just results in missing-character
|
||||
* rectangles being drawn, at least with some fonts. */
|
||||
if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
|
||||
fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
|
||||
return NULL;
|
||||
}
|
||||
if (!(pattern = FcNameParse((FcChar8 *) fontname))) {
|
||||
fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
|
||||
XftFontClose(drw->dpy, xfont);
|
||||
return NULL;
|
||||
}
|
||||
} else if (fontpattern) {
|
||||
if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
|
||||
fprintf(stderr, "error, cannot load font from pattern.\n");
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
die("no font specified.");
|
||||
}
|
||||
|
||||
/* Do not allow using color fonts. This is a workaround for a BadLength
|
||||
* error from Xft with color glyphs. Modelled on the Xterm workaround. See
|
||||
* https://bugzilla.redhat.com/show_bug.cgi?id=1498269
|
||||
* https://lists.suckless.org/dev/1701/30932.html
|
||||
* https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349
|
||||
* and lots more all over the internet.
|
||||
*/
|
||||
FcBool iscol;
|
||||
if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
|
||||
XftFontClose(drw->dpy, xfont);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
font = ecalloc(1, sizeof(Fnt));
|
||||
font->xfont = xfont;
|
||||
font->pattern = pattern;
|
||||
font->h = xfont->ascent + xfont->descent;
|
||||
font->dpy = drw->dpy;
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
static void
|
||||
xfont_free(Fnt *font)
|
||||
{
|
||||
if (!font)
|
||||
return;
|
||||
if (font->pattern)
|
||||
FcPatternDestroy(font->pattern);
|
||||
XftFontClose(font->dpy, font->xfont);
|
||||
free(font);
|
||||
}
|
||||
|
||||
Fnt*
|
||||
drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
|
||||
{
|
||||
Fnt *cur, *ret = NULL;
|
||||
size_t i;
|
||||
|
||||
if (!drw || !fonts)
|
||||
return NULL;
|
||||
|
||||
for (i = 1; i <= fontcount; i++) {
|
||||
if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) {
|
||||
cur->next = ret;
|
||||
ret = cur;
|
||||
}
|
||||
}
|
||||
return (drw->fonts = ret);
|
||||
}
|
||||
|
||||
void
|
||||
drw_fontset_free(Fnt *font)
|
||||
{
|
||||
if (font) {
|
||||
drw_fontset_free(font->next);
|
||||
xfont_free(font);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
|
||||
{
|
||||
if (!drw || !dest || !clrname)
|
||||
return;
|
||||
|
||||
if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
|
||||
DefaultColormap(drw->dpy, drw->screen),
|
||||
clrname, dest))
|
||||
die("error, cannot allocate color '%s'", clrname);
|
||||
|
||||
dest->pixel |= 0xff << 24;
|
||||
}
|
||||
|
||||
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
||||
* returned color scheme when done using it. */
|
||||
Clr *
|
||||
drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount)
|
||||
{
|
||||
size_t i;
|
||||
Clr *ret;
|
||||
|
||||
/* need at least two colors for a scheme */
|
||||
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < clrcount; i++)
|
||||
drw_clr_create(drw, &ret[i], clrnames[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
drw_setfontset(Drw *drw, Fnt *set)
|
||||
{
|
||||
if (drw)
|
||||
drw->fonts = set;
|
||||
}
|
||||
|
||||
void
|
||||
drw_setscheme(Drw *drw, Clr *scm)
|
||||
{
|
||||
if (drw)
|
||||
drw->scheme = scm;
|
||||
}
|
||||
|
||||
void
|
||||
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
|
||||
{
|
||||
if (!drw || !drw->scheme)
|
||||
return;
|
||||
XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
|
||||
if (filled)
|
||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||
else
|
||||
XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
|
||||
}
|
||||
|
||||
int
|
||||
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
|
||||
{
|
||||
char buf[1024];
|
||||
int ty;
|
||||
unsigned int ew;
|
||||
XftDraw *d = NULL;
|
||||
Fnt *usedfont, *curfont, *nextfont;
|
||||
size_t i, len;
|
||||
int utf8strlen, utf8charlen, render = x || y || w || h;
|
||||
long utf8codepoint = 0;
|
||||
const char *utf8str;
|
||||
FcCharSet *fccharset;
|
||||
FcPattern *fcpattern;
|
||||
FcPattern *match;
|
||||
XftResult result;
|
||||
int charexists = 0;
|
||||
|
||||
if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
|
||||
return 0;
|
||||
|
||||
if (!render) {
|
||||
w = ~w;
|
||||
} else {
|
||||
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||
d = XftDrawCreate(drw->dpy, drw->drawable,
|
||||
DefaultVisual(drw->dpy, drw->screen),
|
||||
DefaultColormap(drw->dpy, drw->screen));
|
||||
x += lpad;
|
||||
w -= lpad;
|
||||
}
|
||||
|
||||
usedfont = drw->fonts;
|
||||
while (1) {
|
||||
utf8strlen = 0;
|
||||
utf8str = text;
|
||||
nextfont = NULL;
|
||||
while (*text) {
|
||||
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
|
||||
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
||||
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
||||
if (charexists) {
|
||||
if (curfont == usedfont) {
|
||||
utf8strlen += utf8charlen;
|
||||
text += utf8charlen;
|
||||
} else {
|
||||
nextfont = curfont;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!charexists || nextfont)
|
||||
break;
|
||||
else
|
||||
charexists = 0;
|
||||
}
|
||||
|
||||
if (utf8strlen) {
|
||||
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
|
||||
/* shorten text if necessary */
|
||||
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--)
|
||||
drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
|
||||
|
||||
if (len) {
|
||||
memcpy(buf, utf8str, len);
|
||||
buf[len] = '\0';
|
||||
if (len < utf8strlen)
|
||||
for (i = len; i && i > len - 3; buf[--i] = '.')
|
||||
; /* NOP */
|
||||
|
||||
if (render) {
|
||||
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
|
||||
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
|
||||
usedfont->xfont, x, ty, (XftChar8 *)buf, len);
|
||||
}
|
||||
x += ew;
|
||||
w -= ew;
|
||||
}
|
||||
}
|
||||
|
||||
if (!*text) {
|
||||
break;
|
||||
} else if (nextfont) {
|
||||
charexists = 0;
|
||||
usedfont = nextfont;
|
||||
} else {
|
||||
/* Regardless of whether or not a fallback font is found, the
|
||||
* character must be drawn. */
|
||||
charexists = 1;
|
||||
|
||||
fccharset = FcCharSetCreate();
|
||||
FcCharSetAddChar(fccharset, utf8codepoint);
|
||||
|
||||
if (!drw->fonts->pattern) {
|
||||
/* Refer to the comment in xfont_create for more information. */
|
||||
die("the first font in the cache must be loaded from a font string.");
|
||||
}
|
||||
|
||||
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
|
||||
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
|
||||
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
|
||||
FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);
|
||||
|
||||
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
|
||||
FcDefaultSubstitute(fcpattern);
|
||||
match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
|
||||
|
||||
FcCharSetDestroy(fccharset);
|
||||
FcPatternDestroy(fcpattern);
|
||||
|
||||
if (match) {
|
||||
usedfont = xfont_create(drw, NULL, match);
|
||||
if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
|
||||
for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
|
||||
; /* NOP */
|
||||
curfont->next = usedfont;
|
||||
} else {
|
||||
xfont_free(usedfont);
|
||||
usedfont = drw->fonts;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (d)
|
||||
XftDrawDestroy(d);
|
||||
|
||||
return x + (render ? w : 0);
|
||||
}
|
||||
|
||||
void
|
||||
drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
|
||||
{
|
||||
if (!drw)
|
||||
return;
|
||||
|
||||
XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
|
||||
XSync(drw->dpy, False);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
drw_fontset_getwidth(Drw *drw, const char *text)
|
||||
{
|
||||
if (!drw || !drw->fonts || !text)
|
||||
return 0;
|
||||
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
|
||||
}
|
||||
|
||||
void
|
||||
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
|
||||
{
|
||||
XGlyphInfo ext;
|
||||
|
||||
if (!font || !text)
|
||||
return;
|
||||
|
||||
XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
|
||||
if (w)
|
||||
*w = ext.xOff;
|
||||
if (h)
|
||||
*h = font->h;
|
||||
}
|
||||
|
||||
Cur *
|
||||
drw_cur_create(Drw *drw, int shape)
|
||||
{
|
||||
Cur *cur;
|
||||
|
||||
if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
|
||||
return NULL;
|
||||
|
||||
cur->cursor = XCreateFontCursor(drw->dpy, shape);
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
void
|
||||
drw_cur_free(Drw *drw, Cur *cursor)
|
||||
{
|
||||
if (!cursor)
|
||||
return;
|
||||
|
||||
XFreeCursor(drw->dpy, cursor->cursor);
|
||||
free(cursor);
|
||||
}
|
57
drw.h
Normal file
57
drw.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
typedef struct {
|
||||
Cursor cursor;
|
||||
} Cur;
|
||||
|
||||
typedef struct Fnt {
|
||||
Display *dpy;
|
||||
unsigned int h;
|
||||
XftFont *xfont;
|
||||
FcPattern *pattern;
|
||||
struct Fnt *next;
|
||||
} Fnt;
|
||||
|
||||
enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */
|
||||
typedef XftColor Clr;
|
||||
|
||||
typedef struct {
|
||||
unsigned int w, h;
|
||||
Display *dpy;
|
||||
int screen;
|
||||
Window root;
|
||||
Drawable drawable;
|
||||
GC gc;
|
||||
Clr *scheme;
|
||||
Fnt *fonts;
|
||||
} Drw;
|
||||
|
||||
/* Drawable abstraction */
|
||||
Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h);
|
||||
void drw_resize(Drw *drw, unsigned int w, unsigned int h);
|
||||
void drw_free(Drw *drw);
|
||||
|
||||
/* Fnt abstraction */
|
||||
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
|
||||
void drw_fontset_free(Fnt* set);
|
||||
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
|
||||
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
|
||||
|
||||
/* Colorscheme abstraction */
|
||||
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
|
||||
Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount);
|
||||
|
||||
/* Cursor abstraction */
|
||||
Cur *drw_cur_create(Drw *drw, int shape);
|
||||
void drw_cur_free(Drw *drw, Cur *cursor);
|
||||
|
||||
/* Drawing context manipulation */
|
||||
void drw_setfontset(Drw *drw, Fnt *set);
|
||||
void drw_setscheme(Drw *drw, Clr *scm);
|
||||
|
||||
/* Drawing functions */
|
||||
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
|
||||
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
|
||||
|
||||
/* Map functions */
|
||||
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
|
548
dwm-msg.c
Normal file
548
dwm-msg.c
Normal file
@ -0,0 +1,548 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <yajl/yajl_gen.h>
|
||||
|
||||
#define IPC_MAGIC "DWM-IPC"
|
||||
// clang-format off
|
||||
#define IPC_MAGIC_ARR { 'D', 'W', 'M', '-', 'I', 'P', 'C' }
|
||||
// clang-format on
|
||||
#define IPC_MAGIC_LEN 7 // Not including null char
|
||||
|
||||
#define IPC_EVENT_TAG_CHANGE "tag_change_event"
|
||||
#define IPC_EVENT_CLIENT_FOCUS_CHANGE "client_focus_change_event"
|
||||
#define IPC_EVENT_LAYOUT_CHANGE "layout_change_event"
|
||||
#define IPC_EVENT_MONITOR_FOCUS_CHANGE "monitor_focus_change_event"
|
||||
#define IPC_EVENT_FOCUSED_TITLE_CHANGE "focused_title_change_event"
|
||||
#define IPC_EVENT_FOCUSED_STATE_CHANGE "focused_state_change_event"
|
||||
|
||||
#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str))
|
||||
#define YINT(num) yajl_gen_integer(gen, num)
|
||||
#define YDOUBLE(num) yajl_gen_double(gen, num)
|
||||
#define YBOOL(v) yajl_gen_bool(gen, v)
|
||||
#define YNULL() yajl_gen_null(gen)
|
||||
#define YARR(body) \
|
||||
{ \
|
||||
yajl_gen_array_open(gen); \
|
||||
body; \
|
||||
yajl_gen_array_close(gen); \
|
||||
}
|
||||
#define YMAP(body) \
|
||||
{ \
|
||||
yajl_gen_map_open(gen); \
|
||||
body; \
|
||||
yajl_gen_map_close(gen); \
|
||||
}
|
||||
|
||||
typedef unsigned long Window;
|
||||
|
||||
const char *DEFAULT_SOCKET_PATH = "/tmp/dwm.sock";
|
||||
static int sock_fd = -1;
|
||||
static unsigned int ignore_reply = 0;
|
||||
|
||||
typedef enum IPCMessageType {
|
||||
IPC_TYPE_RUN_COMMAND = 0,
|
||||
IPC_TYPE_GET_MONITORS = 1,
|
||||
IPC_TYPE_GET_TAGS = 2,
|
||||
IPC_TYPE_GET_LAYOUTS = 3,
|
||||
IPC_TYPE_GET_DWM_CLIENT = 4,
|
||||
IPC_TYPE_SUBSCRIBE = 5,
|
||||
IPC_TYPE_EVENT = 6
|
||||
} IPCMessageType;
|
||||
|
||||
// Every IPC message must begin with this
|
||||
typedef struct dwm_ipc_header {
|
||||
uint8_t magic[IPC_MAGIC_LEN];
|
||||
uint32_t size;
|
||||
uint8_t type;
|
||||
} __attribute((packed)) dwm_ipc_header_t;
|
||||
|
||||
static int
|
||||
recv_message(uint8_t *msg_type, uint32_t *reply_size, uint8_t **reply)
|
||||
{
|
||||
uint32_t read_bytes = 0;
|
||||
const int32_t to_read = sizeof(dwm_ipc_header_t);
|
||||
char header[to_read];
|
||||
char *walk = header;
|
||||
|
||||
// Try to read header
|
||||
while (read_bytes < to_read) {
|
||||
ssize_t n = read(sock_fd, header + read_bytes, to_read - read_bytes);
|
||||
|
||||
if (n == 0) {
|
||||
if (read_bytes == 0) {
|
||||
fprintf(stderr, "Unexpectedly reached EOF while reading header.");
|
||||
fprintf(stderr,
|
||||
"Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n",
|
||||
read_bytes, to_read);
|
||||
return -2;
|
||||
} else {
|
||||
fprintf(stderr, "Unexpectedly reached EOF while reading header.");
|
||||
fprintf(stderr,
|
||||
"Read %" PRIu32 " bytes, expected %" PRIu32 " total bytes.\n",
|
||||
read_bytes, to_read);
|
||||
return -3;
|
||||
}
|
||||
} else if (n == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
read_bytes += n;
|
||||
}
|
||||
|
||||
// Check if magic string in header matches
|
||||
if (memcmp(walk, IPC_MAGIC, IPC_MAGIC_LEN) != 0) {
|
||||
fprintf(stderr, "Invalid magic string. Got '%.*s', expected '%s'\n",
|
||||
IPC_MAGIC_LEN, walk, IPC_MAGIC);
|
||||
return -3;
|
||||
}
|
||||
|
||||
walk += IPC_MAGIC_LEN;
|
||||
|
||||
// Extract reply size
|
||||
memcpy(reply_size, walk, sizeof(uint32_t));
|
||||
walk += sizeof(uint32_t);
|
||||
|
||||
// Extract message type
|
||||
memcpy(msg_type, walk, sizeof(uint8_t));
|
||||
walk += sizeof(uint8_t);
|
||||
|
||||
(*reply) = malloc(*reply_size);
|
||||
|
||||
// Extract payload
|
||||
read_bytes = 0;
|
||||
while (read_bytes < *reply_size) {
|
||||
ssize_t n = read(sock_fd, *reply + read_bytes, *reply_size - read_bytes);
|
||||
|
||||
if (n == 0) {
|
||||
fprintf(stderr, "Unexpectedly reached EOF while reading payload.");
|
||||
fprintf(stderr, "Read %" PRIu32 " bytes, expected %" PRIu32 " bytes.\n",
|
||||
read_bytes, *reply_size);
|
||||
free(*reply);
|
||||
return -2;
|
||||
} else if (n == -1) {
|
||||
if (errno == EINTR || errno == EAGAIN) continue;
|
||||
free(*reply);
|
||||
return -1;
|
||||
}
|
||||
|
||||
read_bytes += n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
read_socket(IPCMessageType *msg_type, uint32_t *msg_size, char **msg)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
while (ret != 0) {
|
||||
ret = recv_message((uint8_t *)msg_type, msg_size, (uint8_t **)msg);
|
||||
|
||||
if (ret < 0) {
|
||||
// Try again (non-fatal error)
|
||||
if (ret == -1 && (errno == EINTR || errno == EAGAIN)) continue;
|
||||
|
||||
fprintf(stderr, "Error receiving response from socket. ");
|
||||
fprintf(stderr, "The connection might have been lost.\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
write_socket(const void *buf, size_t count)
|
||||
{
|
||||
size_t written = 0;
|
||||
|
||||
while (written < count) {
|
||||
const ssize_t n =
|
||||
write(sock_fd, ((uint8_t *)buf) + written, count - written);
|
||||
|
||||
if (n == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
return n;
|
||||
}
|
||||
written += n;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
static void
|
||||
connect_to_socket()
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
|
||||
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
// Initialize struct to 0
|
||||
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, DEFAULT_SOCKET_PATH);
|
||||
|
||||
connect(sock, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un));
|
||||
|
||||
sock_fd = sock;
|
||||
}
|
||||
|
||||
static int
|
||||
send_message(IPCMessageType msg_type, uint32_t msg_size, uint8_t *msg)
|
||||
{
|
||||
dwm_ipc_header_t header = {
|
||||
.magic = IPC_MAGIC_ARR, .size = msg_size, .type = msg_type};
|
||||
|
||||
size_t header_size = sizeof(dwm_ipc_header_t);
|
||||
size_t total_size = header_size + msg_size;
|
||||
|
||||
uint8_t buffer[total_size];
|
||||
|
||||
// Copy header to buffer
|
||||
memcpy(buffer, &header, header_size);
|
||||
// Copy message to buffer
|
||||
memcpy(buffer + header_size, msg, header.size);
|
||||
|
||||
write_socket(buffer, total_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
is_float(const char *s)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
int is_dot_used = 0;
|
||||
int is_minus_used = 0;
|
||||
|
||||
// Floats can only have one decimal point in between or digits
|
||||
// Optionally, floats can also be below zero (negative)
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isdigit(s[i]))
|
||||
continue;
|
||||
else if (!is_dot_used && s[i] == '.' && i != 0 && i != len - 1) {
|
||||
is_dot_used = 1;
|
||||
continue;
|
||||
} else if (!is_minus_used && s[i] == '-' && i == 0) {
|
||||
is_minus_used = 1;
|
||||
continue;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
is_unsigned_int(const char *s)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
|
||||
// Unsigned int can only have digits
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isdigit(s[i]))
|
||||
continue;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
is_signed_int(const char *s)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
|
||||
// Signed int can only have digits and a negative sign at the start
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isdigit(s[i]))
|
||||
continue;
|
||||
else if (i == 0 && s[i] == '-') {
|
||||
continue;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
flush_socket_reply()
|
||||
{
|
||||
IPCMessageType reply_type;
|
||||
uint32_t reply_size;
|
||||
char *reply;
|
||||
|
||||
read_socket(&reply_type, &reply_size, &reply);
|
||||
|
||||
free(reply);
|
||||
}
|
||||
|
||||
static void
|
||||
print_socket_reply()
|
||||
{
|
||||
IPCMessageType reply_type;
|
||||
uint32_t reply_size;
|
||||
char *reply;
|
||||
|
||||
read_socket(&reply_type, &reply_size, &reply);
|
||||
|
||||
printf("%.*s\n", reply_size, reply);
|
||||
fflush(stdout);
|
||||
free(reply);
|
||||
}
|
||||
|
||||
static int
|
||||
run_command(const char *name, char *args[], int argc)
|
||||
{
|
||||
const unsigned char *msg;
|
||||
size_t msg_size;
|
||||
|
||||
yajl_gen gen = yajl_gen_alloc(NULL);
|
||||
|
||||
// Message format:
|
||||
// {
|
||||
// "command": "<name>",
|
||||
// "args": [ ... ]
|
||||
// }
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("command"); YSTR(name);
|
||||
YSTR("args"); YARR(
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (is_signed_int(args[i])) {
|
||||
long long num = atoll(args[i]);
|
||||
YINT(num);
|
||||
} else if (is_float(args[i])) {
|
||||
float num = atof(args[i]);
|
||||
YDOUBLE(num);
|
||||
} else {
|
||||
YSTR(args[i]);
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
yajl_gen_get_buf(gen, &msg, &msg_size);
|
||||
|
||||
send_message(IPC_TYPE_RUN_COMMAND, msg_size, (uint8_t *)msg);
|
||||
|
||||
if (!ignore_reply)
|
||||
print_socket_reply();
|
||||
else
|
||||
flush_socket_reply();
|
||||
|
||||
yajl_gen_free(gen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_monitors()
|
||||
{
|
||||
send_message(IPC_TYPE_GET_MONITORS, 1, (uint8_t *)"");
|
||||
print_socket_reply();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_tags()
|
||||
{
|
||||
send_message(IPC_TYPE_GET_TAGS, 1, (uint8_t *)"");
|
||||
print_socket_reply();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_layouts()
|
||||
{
|
||||
send_message(IPC_TYPE_GET_LAYOUTS, 1, (uint8_t *)"");
|
||||
print_socket_reply();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_dwm_client(Window win)
|
||||
{
|
||||
const unsigned char *msg;
|
||||
size_t msg_size;
|
||||
|
||||
yajl_gen gen = yajl_gen_alloc(NULL);
|
||||
|
||||
// Message format:
|
||||
// {
|
||||
// "client_window_id": "<win>"
|
||||
// }
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("client_window_id"); YINT(win);
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
yajl_gen_get_buf(gen, &msg, &msg_size);
|
||||
|
||||
send_message(IPC_TYPE_GET_DWM_CLIENT, msg_size, (uint8_t *)msg);
|
||||
|
||||
print_socket_reply();
|
||||
|
||||
yajl_gen_free(gen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
subscribe(const char *event)
|
||||
{
|
||||
const unsigned char *msg;
|
||||
size_t msg_size;
|
||||
|
||||
yajl_gen gen = yajl_gen_alloc(NULL);
|
||||
|
||||
// Message format:
|
||||
// {
|
||||
// "event": "<event>",
|
||||
// "action": "subscribe"
|
||||
// }
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("event"); YSTR(event);
|
||||
YSTR("action"); YSTR("subscribe");
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
yajl_gen_get_buf(gen, &msg, &msg_size);
|
||||
|
||||
send_message(IPC_TYPE_SUBSCRIBE, msg_size, (uint8_t *)msg);
|
||||
|
||||
if (!ignore_reply)
|
||||
print_socket_reply();
|
||||
else
|
||||
flush_socket_reply();
|
||||
|
||||
yajl_gen_free(gen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
usage_error(const char *prog_name, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
fprintf(stderr, "Error: ");
|
||||
vfprintf(stderr, format, args);
|
||||
fprintf(stderr, "\nusage: %s <command> [...]\n", prog_name);
|
||||
fprintf(stderr, "Try '%s help'\n", prog_name);
|
||||
|
||||
va_end(args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
print_usage(const char *name)
|
||||
{
|
||||
printf("usage: %s [options] <command> [...]\n", name);
|
||||
puts("");
|
||||
puts("Commands:");
|
||||
puts(" run_command <name> [args...] Run an IPC command");
|
||||
puts("");
|
||||
puts(" get_monitors Get monitor properties");
|
||||
puts("");
|
||||
puts(" get_tags Get list of tags");
|
||||
puts("");
|
||||
puts(" get_layouts Get list of layouts");
|
||||
puts("");
|
||||
puts(" get_dwm_client <window_id> Get dwm client proprties");
|
||||
puts("");
|
||||
puts(" subscribe [events...] Subscribe to specified events");
|
||||
puts(" Options: " IPC_EVENT_TAG_CHANGE ",");
|
||||
puts(" " IPC_EVENT_LAYOUT_CHANGE ",");
|
||||
puts(" " IPC_EVENT_CLIENT_FOCUS_CHANGE ",");
|
||||
puts(" " IPC_EVENT_MONITOR_FOCUS_CHANGE ",");
|
||||
puts(" " IPC_EVENT_FOCUSED_TITLE_CHANGE ",");
|
||||
puts(" " IPC_EVENT_FOCUSED_STATE_CHANGE);
|
||||
puts("");
|
||||
puts(" help Display this message");
|
||||
puts("");
|
||||
puts("Options:");
|
||||
puts(" --ignore-reply Don't print reply messages from");
|
||||
puts(" run_command and subscribe.");
|
||||
puts("");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const char *prog_name = argv[0];
|
||||
|
||||
connect_to_socket();
|
||||
if (sock_fd == -1) {
|
||||
fprintf(stderr, "Failed to connect to socket\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int i = 1;
|
||||
if (i < argc && strcmp(argv[i], "--ignore-reply") == 0) {
|
||||
ignore_reply = 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i >= argc) usage_error(prog_name, "Expected an argument, got none");
|
||||
|
||||
if (strcmp(argv[i], "help") == 0)
|
||||
print_usage(prog_name);
|
||||
else if (strcmp(argv[i], "run_command") == 0) {
|
||||
if (++i >= argc) usage_error(prog_name, "No command specified");
|
||||
// Command name
|
||||
char *command = argv[i];
|
||||
// Command arguments are everything after command name
|
||||
char **command_args = argv + ++i;
|
||||
// Number of command arguments
|
||||
int command_argc = argc - i;
|
||||
run_command(command, command_args, command_argc);
|
||||
} else if (strcmp(argv[i], "get_monitors") == 0) {
|
||||
get_monitors();
|
||||
} else if (strcmp(argv[i], "get_tags") == 0) {
|
||||
get_tags();
|
||||
} else if (strcmp(argv[i], "get_layouts") == 0) {
|
||||
get_layouts();
|
||||
} else if (strcmp(argv[i], "get_dwm_client") == 0) {
|
||||
if (++i < argc) {
|
||||
if (is_unsigned_int(argv[i])) {
|
||||
Window win = atol(argv[i]);
|
||||
get_dwm_client(win);
|
||||
} else
|
||||
usage_error(prog_name, "Expected unsigned integer argument");
|
||||
} else
|
||||
usage_error(prog_name, "Expected the window id");
|
||||
} else if (strcmp(argv[i], "subscribe") == 0) {
|
||||
if (++i < argc) {
|
||||
for (int j = i; j < argc; j++) subscribe(argv[j]);
|
||||
} else
|
||||
usage_error(prog_name, "Expected event name");
|
||||
// Keep listening for events forever
|
||||
while (1) {
|
||||
print_socket_reply();
|
||||
}
|
||||
} else
|
||||
usage_error(prog_name, "Invalid argument '%s'", argv[i]);
|
||||
|
||||
return 0;
|
||||
}
|
193
dwm.1
193
dwm.1
@ -5,38 +5,45 @@ dwm \- dynamic window manager
|
||||
.B dwm
|
||||
.RB [ \-v ]
|
||||
.SH DESCRIPTION
|
||||
dwm is a dynamic window manager for X. It manages windows in tiled and
|
||||
floating layouts. Either layout can be applied dynamically, optimizing the
|
||||
dwm is a dynamic window manager for X. It manages windows in tiled, monocle
|
||||
and floating layouts. Either layout can be applied dynamically, optimising the
|
||||
environment for the application in use and the task performed.
|
||||
.P
|
||||
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 layout applied.
|
||||
In tiled layouts windows are managed in a master and stacking area. The master
|
||||
area on the left contains one window by default, and the stacking area on the
|
||||
right contains all other windows. The number of master area windows can be
|
||||
adjusted from zero to an arbitrary number. In monocle layout all windows are
|
||||
maximised to the screen size. In floating layout windows can be resized and
|
||||
moved freely. Dialog windows are always managed floating, 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 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.
|
||||
Each screen contains a small status bar which displays all available tags, the
|
||||
layout, the title of the focused window, and the text read from the root window
|
||||
name property, if the screen is focused. A floating window is indicated with an
|
||||
empty square and a maximised 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
|
||||
The attach below patch makes newly spawned windows attach after the currently
|
||||
selected window
|
||||
.P
|
||||
dwm draws a small border around windows to indicate the focus state.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-v
|
||||
prints version information to standard output, then exits.
|
||||
prints version information to stderr, then exits.
|
||||
.SH USAGE
|
||||
.SS Status bar
|
||||
.TP
|
||||
.B Standard input
|
||||
is read and displayed in the status text area.
|
||||
.B X root window name
|
||||
is read and displayed in the status text area. It can be set with the
|
||||
.BR xsetroot (1)
|
||||
command.
|
||||
.TP
|
||||
.B Button1
|
||||
click on a tag label to display all windows with that tag, click on the layout
|
||||
@ -54,16 +61,45 @@ click on a tag label adds/removes that tag to/from the focused window.
|
||||
.TP
|
||||
.B Mod1\-Shift\-Return
|
||||
Start
|
||||
.BR xterm.
|
||||
.BR st(1).
|
||||
.TP
|
||||
.B Mod1\-Return
|
||||
Zooms/cycles current window to/from master area (tiled layout only).
|
||||
.B Mod1\-p
|
||||
Spawn
|
||||
.BR dmenu(1)
|
||||
for launching other programs.
|
||||
.TP
|
||||
.B Mod1\-,
|
||||
Focus previous screen, if any.
|
||||
.TP
|
||||
.B Mod1\-.
|
||||
Focus next screen, if any.
|
||||
.TP
|
||||
.B Mod1\-Shift\-,
|
||||
Send focused window to previous screen, if any.
|
||||
.TP
|
||||
.B Mod1\-Shift\-.
|
||||
Send focused window to next screen, if any.
|
||||
.TP
|
||||
.B Mod1\-b
|
||||
Shows/hides the status bar.
|
||||
Toggles bar on and off.
|
||||
.TP
|
||||
.B Mod1\-h
|
||||
Decreases the master area width about 5% (tiled layout only).
|
||||
.B Mod1\-t
|
||||
Sets tiled layout.
|
||||
.TP
|
||||
.B Mod1\-f
|
||||
Sets floating layout.
|
||||
.TP
|
||||
.B Mod1\-m
|
||||
Sets monocle layout.
|
||||
.TP
|
||||
.B Mod1\-space
|
||||
Toggles between current and previous layout.
|
||||
.TP
|
||||
.B Mod1\-Control\-,
|
||||
Cycles backwards in layout list.
|
||||
.TP
|
||||
.B Mod1\-Control\-.
|
||||
Cycles forwards in layout list.
|
||||
.TP
|
||||
.B Mod1\-j
|
||||
Focus next window.
|
||||
@ -71,83 +107,100 @@ Focus next window.
|
||||
.B Mod1\-k
|
||||
Focus previous window.
|
||||
.TP
|
||||
.B Mod1\-i
|
||||
Increase number of windows in master area.
|
||||
.TP
|
||||
.B Mod1\-d
|
||||
Decrease number of windows in master area.
|
||||
.TP
|
||||
.B Mod1\-l
|
||||
Increases the master area width about 5% (tiled layout only).
|
||||
Increase master area size.
|
||||
.TP
|
||||
.B Mod1\-m
|
||||
Toggles maximization of current window (floating layout only).
|
||||
.B Mod1\-h
|
||||
Decrease master area size.
|
||||
.TP
|
||||
.B Mod1\-Shift\-[1..n]
|
||||
Apply
|
||||
.RB nth
|
||||
tag to current window.
|
||||
.B Mod1\-Shift\-l
|
||||
Increase client weight (cfacts patch).
|
||||
.TP
|
||||
.B Mod1\-Shift\-0
|
||||
Apply all tags to current window.
|
||||
.B Mod1\-Shift\-h
|
||||
Decrease client weight (cfacts patch).
|
||||
.TP
|
||||
.B Mod1\-Control\-Shift\-[1..n]
|
||||
Add/remove
|
||||
.B nth
|
||||
tag to/from current window.
|
||||
.B Mod1\-Shift\-o
|
||||
Reset client weight (cfacts patch).
|
||||
.TP
|
||||
.B Mod1\-Return
|
||||
Zooms/cycles focused window to/from master area (tiled layouts only).
|
||||
.TP
|
||||
.B Mod1\-Shift\-c
|
||||
Close focused window.
|
||||
.TP
|
||||
.B Mod1\-space
|
||||
Toggle between tiled and floating layout (affects all windows).
|
||||
.TP
|
||||
.B Mod1\-Shift\-space
|
||||
Toggle focused window between tiled and floating state.
|
||||
.TP
|
||||
.B Mod1\-Control\-f
|
||||
Toggle fullscreen (actualfullscreen patch).
|
||||
.TP
|
||||
.B Mod1\-Control\-tab
|
||||
Toggle attach below (attachbelow patch).
|
||||
.TP
|
||||
.B Mod1\-Tab
|
||||
Toggles to the previously selected tags.
|
||||
.TP
|
||||
.B Mod1\-Shift\-j
|
||||
Increase window size while maintaining aspect ratio (aspectresize patch).
|
||||
.TP
|
||||
.B Mod1\-Shift\-k
|
||||
Decrease window size while maintaining aspect ratio (aspectresize patch).
|
||||
.TP
|
||||
.B Mod1\-Shift\-[1..n]
|
||||
Apply nth tag to focused window.
|
||||
.TP
|
||||
.B Mod1\-Shift\-0
|
||||
Apply all tags to focused window.
|
||||
.TP
|
||||
.B Mod1\-Control\-Shift\-[1..n]
|
||||
Add/remove nth tag to/from focused window.
|
||||
.TP
|
||||
.B Mod1\-[1..n]
|
||||
View all windows with
|
||||
.BR nth
|
||||
tag.
|
||||
View all windows with nth tag.
|
||||
.TP
|
||||
.B Mod1\-0
|
||||
View all windows with any tag.
|
||||
.TP
|
||||
.B Mod1\-Control\-[1..n]
|
||||
Add/remove all windows with
|
||||
.BR nth
|
||||
tag to/from the view.
|
||||
Add/remove all windows with nth tag to/from the view.
|
||||
.TP
|
||||
.B Mod1\-Shift\-q
|
||||
Quit dwm.
|
||||
.SS Mouse commands
|
||||
.TP
|
||||
.B Mod1\-Button1
|
||||
Move current window while dragging (floating layout only).
|
||||
Move focused window while dragging. Tiled windows will be toggled to the floating state.
|
||||
.TP
|
||||
.B Mod1\-Button2
|
||||
Zooms/cycles current window to/from master area (tiled layout only).
|
||||
Toggles focused window between floating and tiled state.
|
||||
.TP
|
||||
.B Mod1\-Button3
|
||||
Resize current window while dragging (floating layout only).
|
||||
Resize focused window while dragging. Tiled windows will be toggled to the floating state.
|
||||
.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 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
|
||||
.BR xdm (1),
|
||||
because those close standard output before executing dwm.
|
||||
.P
|
||||
.BR dmenu (1),
|
||||
.BR st (1)
|
||||
.SH ISSUES
|
||||
Java applications which use the XToolkit/XAWT backend may draw grey windows
|
||||
only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early
|
||||
JDK 1.6 versions, because it assumes a reparenting window manager. As a workaround
|
||||
you can use JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or you
|
||||
can set the following environment variable (to use the older Motif
|
||||
backend instead):
|
||||
.BR AWT_TOOLKIT=MToolkit .
|
||||
.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.
|
||||
JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds
|
||||
are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the
|
||||
environment variable
|
||||
.BR AWT_TOOLKIT=MToolkit
|
||||
(to use the older Motif backend instead) or running
|
||||
.B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D
|
||||
or
|
||||
.B wmname LG3D
|
||||
(to pretend that a non-reparenting window manager is running that the
|
||||
XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable
|
||||
.BR _JAVA_AWT_WM_NONREPARENTING=1 .
|
||||
.SH BUGS
|
||||
Send all bug reports with a patch to hackers@suckless.org.
|
||||
|
146
dwm.h
146
dwm.h
@ -1,146 +0,0 @@
|
||||
/* 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
|
||||
* manager selects for SubstructureRedirectMask on the root window, to receive
|
||||
* events about window (dis-)appearance. Only one X connection at a time is
|
||||
* allowed to select for this event mask.
|
||||
*
|
||||
* Calls to fetch an X event from the event queue are blocking. Due reading
|
||||
* status text from standard input, a select()-driven main loop has been
|
||||
* implemented which selects for reads on the X connection and STDIN_FILENO to
|
||||
* handle all data smoothly. The event handlers of dwm are organized in an
|
||||
* array which is accessed whenever a new event has been fetched. This allows
|
||||
* event dispatching in O(1) time.
|
||||
*
|
||||
* Each child of the root window is called a client, except windows which have
|
||||
* set the override_redirect flag. Clients are organized in a global
|
||||
* doubly-linked client list, the focus history is remembered through a global
|
||||
* stack list. Each client contains an array of Bools of the same size as the
|
||||
* global tags array to indicate the tags of a client. For each client dwm
|
||||
* creates a small title window, which is resized whenever the (_NET_)WM_NAME
|
||||
* properties are updated or the client is moved/resized.
|
||||
*
|
||||
* 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 layout is
|
||||
* represented by the lt pointer.
|
||||
*
|
||||
* To understand everything else, start reading main.c:main().
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
/* mask shorthands, used in event.c and client.c */
|
||||
#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask)
|
||||
|
||||
enum { BarTop, BarBot, BarOff }; /* bar position */
|
||||
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
|
||||
enum { ColBorder, ColFG, ColBG, ColLast }; /* color */
|
||||
enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */
|
||||
enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */
|
||||
|
||||
typedef struct Client Client;
|
||||
struct Client {
|
||||
char name[256];
|
||||
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, oldborder;
|
||||
Bool isbanned, isfixed, ismax, isfloating;
|
||||
Bool *tags;
|
||||
Client *next;
|
||||
Client *prev;
|
||||
Client *snext;
|
||||
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 screen, sx, sy, sw, sh; /* screen geometry */
|
||||
extern int wax, way, wah, waw; /* windowarea geometry */
|
||||
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 Atom wmatom[WMLast], netatom[NetLast];
|
||||
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 */
|
||||
extern Display *dpy;
|
||||
extern Window root, barwin;
|
||||
|
||||
/* client.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 */
|
||||
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 */
|
||||
void grabkeys(void); /* grab all keys defined in config.h */
|
||||
|
||||
/* main.c */
|
||||
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 */
|
||||
|
||||
/* 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 */
|
||||
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 */
|
40
dwmc
Executable file
40
dwmc
Executable file
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
signal() {
|
||||
xsetroot -name "fsignal:$*"
|
||||
}
|
||||
|
||||
case $# in
|
||||
1)
|
||||
case $1 in
|
||||
setlayout | view | viewall | togglebar | togglefloating | zoom | killclient | quit)
|
||||
signal $1
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command or missing one argument."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
2)
|
||||
case $1 in
|
||||
view)
|
||||
signal $1 ui $2
|
||||
;;
|
||||
viewex | toggleviewex | tagex | toggletagex | setlayoutex | focusstack | incnmaster | focusmon | tagmon)
|
||||
signal $1 i $2
|
||||
;;
|
||||
setmfact)
|
||||
signal $1 f $2
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command or one too many arguments."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Too many arguments."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
375
event.c
375
event.c
@ -1,375 +0,0 @@
|
||||
/* 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)(const char *arg);
|
||||
const char *arg;
|
||||
} Key;
|
||||
|
||||
#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, nx, ny;
|
||||
unsigned int dui;
|
||||
Window dummy;
|
||||
XEvent ev;
|
||||
|
||||
ocx = nx = c->x;
|
||||
ocy = ny = c->y;
|
||||
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
|
||||
None, cursor[CurMove], CurrentTime) != GrabSuccess)
|
||||
return;
|
||||
c->ismax = False;
|
||||
XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
|
||||
for(;;) {
|
||||
XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev);
|
||||
switch (ev.type) {
|
||||
case ButtonRelease:
|
||||
XUngrabPointer(dpy, CurrentTime);
|
||||
return;
|
||||
case ConfigureRequest:
|
||||
case Expose:
|
||||
case MapRequest:
|
||||
handler[ev.type](&ev);
|
||||
break;
|
||||
case MotionNotify:
|
||||
XSync(dpy, 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
resizemouse(Client *c) {
|
||||
int ocx, ocy;
|
||||
int nw, nh;
|
||||
XEvent ev;
|
||||
|
||||
ocx = c->x;
|
||||
ocy = c->y;
|
||||
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
|
||||
None, cursor[CurResize], CurrentTime) != GrabSuccess)
|
||||
return;
|
||||
c->ismax = False;
|
||||
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1);
|
||||
for(;;) {
|
||||
XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev);
|
||||
switch(ev.type) {
|
||||
case ButtonRelease:
|
||||
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:
|
||||
case MapRequest:
|
||||
handler[ev.type](&ev);
|
||||
break;
|
||||
case MotionNotify:
|
||||
XSync(dpy, False);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
buttonpress(XEvent *e) {
|
||||
unsigned int i, x;
|
||||
Client *c;
|
||||
XButtonPressedEvent *ev = &e->xbutton;
|
||||
|
||||
if(barwin == ev->window) {
|
||||
x = 0;
|
||||
for(i = 0; i < ntags; i++) {
|
||||
x += textw(tags[i]);
|
||||
if(ev->x < x) {
|
||||
if(ev->button == Button1) {
|
||||
if(ev->state & MODKEY)
|
||||
tag(tags[i]);
|
||||
else
|
||||
view(tags[i]);
|
||||
}
|
||||
else if(ev->button == Button3) {
|
||||
if(ev->state & MODKEY)
|
||||
toggletag(tags[i]);
|
||||
else
|
||||
toggleview(tags[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
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 && (isfloating() || c->isfloating)) {
|
||||
restack();
|
||||
movemouse(c);
|
||||
}
|
||||
else if(ev->button == Button2)
|
||||
zoom(NULL);
|
||||
else if(ev->button == Button3
|
||||
&& (isfloating() || c->isfloating) && !c->isfixed)
|
||||
{
|
||||
restack();
|
||||
resizemouse(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
configurerequest(XEvent *e) {
|
||||
Client *c;
|
||||
XConfigureRequestEvent *ev = &e->xconfigurerequest;
|
||||
XWindowChanges wc;
|
||||
|
||||
if((c = getclient(ev->window))) {
|
||||
c->ismax = False;
|
||||
if(ev->value_mask & CWBorderWidth)
|
||||
c->border = ev->border_width;
|
||||
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
|
||||
configure(c);
|
||||
}
|
||||
else {
|
||||
wc.x = ev->x;
|
||||
wc.y = ev->y;
|
||||
wc.width = ev->width;
|
||||
wc.height = ev->height;
|
||||
wc.border_width = ev->border_width;
|
||||
wc.sibling = ev->above;
|
||||
wc.stack_mode = ev->detail;
|
||||
XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
|
||||
}
|
||||
XSync(dpy, False);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroynotify(XEvent *e) {
|
||||
Client *c;
|
||||
XDestroyWindowEvent *ev = &e->xdestroywindow;
|
||||
|
||||
if((c = getclient(ev->window)))
|
||||
unmanage(c);
|
||||
}
|
||||
|
||||
static void
|
||||
enternotify(XEvent *e) {
|
||||
Client *c;
|
||||
XCrossingEvent *ev = &e->xcrossing;
|
||||
|
||||
if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
|
||||
return;
|
||||
if((c = getclient(ev->window)))
|
||||
focus(c);
|
||||
else if(ev->window == root) {
|
||||
selscreen = True;
|
||||
focus(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
expose(XEvent *e) {
|
||||
XExposeEvent *ev = &e->xexpose;
|
||||
|
||||
if(ev->count == 0) {
|
||||
if(barwin == ev->window)
|
||||
drawstatus();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
keypress(XEvent *e) {
|
||||
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 == keys[i].keysym
|
||||
&& CLEANMASK(keys[i].mod) == CLEANMASK(ev->state))
|
||||
{
|
||||
if(keys[i].func)
|
||||
keys[i].func(keys[i].arg);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
leavenotify(XEvent *e) {
|
||||
XCrossingEvent *ev = &e->xcrossing;
|
||||
|
||||
if((ev->window == root) && !ev->same_screen) {
|
||||
selscreen = False;
|
||||
focus(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mappingnotify(XEvent *e) {
|
||||
XMappingEvent *ev = &e->xmapping;
|
||||
|
||||
XRefreshKeyboardMapping(ev);
|
||||
if(ev->request == MappingKeyboard)
|
||||
grabkeys();
|
||||
}
|
||||
|
||||
static void
|
||||
maprequest(XEvent *e) {
|
||||
static XWindowAttributes wa;
|
||||
XMapRequestEvent *ev = &e->xmaprequest;
|
||||
|
||||
if(!XGetWindowAttributes(dpy, ev->window, &wa))
|
||||
return;
|
||||
if(wa.override_redirect)
|
||||
return;
|
||||
if(!getclient(ev->window))
|
||||
manage(ev->window, &wa);
|
||||
}
|
||||
|
||||
static void
|
||||
propertynotify(XEvent *e) {
|
||||
Client *c;
|
||||
Window trans;
|
||||
XPropertyEvent *ev = &e->xproperty;
|
||||
|
||||
if(ev->state == PropertyDelete)
|
||||
return; /* ignore */
|
||||
if((c = getclient(ev->window))) {
|
||||
switch (ev->atom) {
|
||||
default: break;
|
||||
case XA_WM_TRANSIENT_FOR:
|
||||
XGetTransientForHint(dpy, c->win, &trans);
|
||||
if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL)))
|
||||
arrange();
|
||||
break;
|
||||
case XA_WM_NORMAL_HINTS:
|
||||
updatesizehints(c);
|
||||
break;
|
||||
}
|
||||
if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
|
||||
updatetitle(c);
|
||||
if(c == sel)
|
||||
drawstatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unmapnotify(XEvent *e) {
|
||||
Client *c;
|
||||
XUnmapEvent *ev = &e->xunmap;
|
||||
|
||||
if((c = getclient(ev->window)))
|
||||
unmanage(c);
|
||||
}
|
||||
|
||||
/* extern */
|
||||
|
||||
void (*handler[LASTEvent]) (XEvent *) = {
|
||||
[ButtonPress] = buttonpress,
|
||||
[ConfigureRequest] = configurerequest,
|
||||
[ConfigureNotify] = configurenotify,
|
||||
[DestroyNotify] = destroynotify,
|
||||
[EnterNotify] = enternotify,
|
||||
[LeaveNotify] = leavenotify,
|
||||
[Expose] = expose,
|
||||
[KeyPress] = keypress,
|
||||
[MappingNotify] = mappingnotify,
|
||||
[MapRequest] = maprequest,
|
||||
[PropertyNotify] = propertynotify,
|
||||
[UnmapNotify] = unmapnotify
|
||||
};
|
||||
|
||||
void
|
||||
grabkeys(void) {
|
||||
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, keys[i].keysym);
|
||||
XGrabKey(dpy, code, keys[i].mod, root, True,
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True,
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True,
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
}
|
||||
}
|
320
ipc.h
Normal file
320
ipc.h
Normal file
@ -0,0 +1,320 @@
|
||||
#ifndef IPC_H_
|
||||
#define IPC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <yajl/yajl_gen.h>
|
||||
|
||||
#include "IPCClient.h"
|
||||
|
||||
// clang-format off
|
||||
#define IPC_MAGIC "DWM-IPC"
|
||||
#define IPC_MAGIC_ARR { 'D', 'W', 'M', '-', 'I', 'P', 'C'}
|
||||
#define IPC_MAGIC_LEN 7 // Not including null char
|
||||
|
||||
#define IPCCOMMAND(FUNC, ARGC, TYPES) \
|
||||
{ #FUNC, {FUNC }, ARGC, (ArgType[ARGC])TYPES }
|
||||
// clang-format on
|
||||
|
||||
typedef enum IPCMessageType {
|
||||
IPC_TYPE_RUN_COMMAND = 0,
|
||||
IPC_TYPE_GET_MONITORS = 1,
|
||||
IPC_TYPE_GET_TAGS = 2,
|
||||
IPC_TYPE_GET_LAYOUTS = 3,
|
||||
IPC_TYPE_GET_DWM_CLIENT = 4,
|
||||
IPC_TYPE_SUBSCRIBE = 5,
|
||||
IPC_TYPE_EVENT = 6
|
||||
} IPCMessageType;
|
||||
|
||||
typedef enum IPCEvent {
|
||||
IPC_EVENT_TAG_CHANGE = 1 << 0,
|
||||
IPC_EVENT_CLIENT_FOCUS_CHANGE = 1 << 1,
|
||||
IPC_EVENT_LAYOUT_CHANGE = 1 << 2,
|
||||
IPC_EVENT_MONITOR_FOCUS_CHANGE = 1 << 3,
|
||||
IPC_EVENT_FOCUSED_TITLE_CHANGE = 1 << 4,
|
||||
IPC_EVENT_FOCUSED_STATE_CHANGE = 1 << 5
|
||||
} IPCEvent;
|
||||
|
||||
typedef enum IPCSubscriptionAction {
|
||||
IPC_ACTION_UNSUBSCRIBE = 0,
|
||||
IPC_ACTION_SUBSCRIBE = 1
|
||||
} IPCSubscriptionAction;
|
||||
|
||||
/**
|
||||
* Every IPC packet starts with this structure
|
||||
*/
|
||||
typedef struct dwm_ipc_header {
|
||||
uint8_t magic[IPC_MAGIC_LEN];
|
||||
uint32_t size;
|
||||
uint8_t type;
|
||||
} __attribute((packed)) dwm_ipc_header_t;
|
||||
|
||||
typedef enum ArgType {
|
||||
ARG_TYPE_NONE = 0,
|
||||
ARG_TYPE_UINT = 1,
|
||||
ARG_TYPE_SINT = 2,
|
||||
ARG_TYPE_FLOAT = 3,
|
||||
ARG_TYPE_PTR = 4,
|
||||
ARG_TYPE_STR = 5
|
||||
} ArgType;
|
||||
|
||||
/**
|
||||
* An IPCCommand function can have either of these function signatures
|
||||
*/
|
||||
typedef union ArgFunction {
|
||||
void (*single_param)(const Arg *);
|
||||
void (*array_param)(const Arg *, int);
|
||||
} ArgFunction;
|
||||
|
||||
typedef struct IPCCommand {
|
||||
char *name;
|
||||
ArgFunction func;
|
||||
unsigned int argc;
|
||||
ArgType *arg_types;
|
||||
} IPCCommand;
|
||||
|
||||
typedef struct IPCParsedCommand {
|
||||
char *name;
|
||||
Arg *args;
|
||||
ArgType *arg_types;
|
||||
unsigned int argc;
|
||||
} IPCParsedCommand;
|
||||
|
||||
/**
|
||||
* Initialize the IPC socket and the IPC module
|
||||
*
|
||||
* @param socket_path Path to create the socket at
|
||||
* @param epoll_fd File descriptor for epoll
|
||||
* @param commands Address of IPCCommands array defined in config.h
|
||||
* @param commands_len Length of commands[] array
|
||||
*
|
||||
* @return int The file descriptor of the socket if it was successfully created,
|
||||
* -1 otherwise
|
||||
*/
|
||||
int ipc_init(const char *socket_path, const int p_epoll_fd,
|
||||
IPCCommand commands[], const int commands_len);
|
||||
|
||||
/**
|
||||
* Uninitialize the socket and module. Free allocated memory and restore static
|
||||
* variables to their state before ipc_init
|
||||
*/
|
||||
void ipc_cleanup();
|
||||
|
||||
/**
|
||||
* Get the file descriptor of the IPC socket
|
||||
*
|
||||
* @return int File descriptor of IPC socket, -1 if socket not created.
|
||||
*/
|
||||
int ipc_get_sock_fd();
|
||||
|
||||
/**
|
||||
* Get address to IPCClient with specified file descriptor
|
||||
*
|
||||
* @param fd File descriptor of IPC Client
|
||||
*
|
||||
* @return Address to IPCClient with specified file descriptor, -1 otherwise
|
||||
*/
|
||||
IPCClient *ipc_get_client(int fd);
|
||||
|
||||
/**
|
||||
* Check if an IPC client exists with the specified file descriptor
|
||||
*
|
||||
* @param fd File descriptor
|
||||
*
|
||||
* @return int 1 if client exists, 0 otherwise
|
||||
*/
|
||||
int ipc_is_client_registered(int fd);
|
||||
|
||||
/**
|
||||
* Disconnect an IPCClient from the socket and remove the client from the list
|
||||
* of known connected clients
|
||||
*
|
||||
* @param c Address of IPCClient
|
||||
*
|
||||
* @return 0 if the client's file descriptor was closed successfully, the
|
||||
* result of executing close() on the file descriptor otherwise.
|
||||
*/
|
||||
int ipc_drop_client(IPCClient *c);
|
||||
|
||||
/**
|
||||
* Accept an IPC Client requesting to connect to the socket and add it to the
|
||||
* list of clients
|
||||
*
|
||||
* @return File descriptor of new client, -1 on error
|
||||
*/
|
||||
int ipc_accept_client();
|
||||
|
||||
/**
|
||||
* Read an incoming message from an accepted IPC client
|
||||
*
|
||||
* @param c Address of IPCClient
|
||||
* @param msg_type Address to IPCMessageType variable which will be assigned
|
||||
* the message type of the received message
|
||||
* @param msg_size Address to uint32_t variable which will be assigned the size
|
||||
* of the received message
|
||||
* @param msg Address to char* variable which will be assigned the address of
|
||||
* the received message. This must be freed using free().
|
||||
*
|
||||
* @return 0 on success, -1 on error reading message, -2 if reading the message
|
||||
* resulted in EAGAIN, EINTR, or EWOULDBLOCK.
|
||||
*/
|
||||
int ipc_read_client(IPCClient *c, IPCMessageType *msg_type, uint32_t *msg_size,
|
||||
char **msg);
|
||||
|
||||
/**
|
||||
* Write any pending buffer of the client to the client's socket
|
||||
*
|
||||
* @param c Client whose buffer to write
|
||||
*
|
||||
* @return Number of bytes written >= 0, -1 otherwise. errno will still be set
|
||||
* from the write operation.
|
||||
*/
|
||||
ssize_t ipc_write_client(IPCClient *c);
|
||||
|
||||
/**
|
||||
* Prepare a message in the specified client's buffer.
|
||||
*
|
||||
* @param c Client to prepare message for
|
||||
* @param msg_type Type of message to prepare
|
||||
* @param msg_size Size of the message in bytes. Should not exceed
|
||||
* MAX_MESSAGE_SIZE
|
||||
* @param msg Message to prepare (not including header). This pointer can be
|
||||
* freed after the function invocation.
|
||||
*/
|
||||
void ipc_prepare_send_message(IPCClient *c, const IPCMessageType msg_type,
|
||||
const uint32_t msg_size, const char *msg);
|
||||
|
||||
/**
|
||||
* Prepare an error message in the specified client's buffer
|
||||
*
|
||||
* @param c Client to prepare message for
|
||||
* @param msg_type Type of message
|
||||
* @param format Format string following vsprintf
|
||||
* @param ... Arguments for format string
|
||||
*/
|
||||
void ipc_prepare_reply_failure(IPCClient *c, IPCMessageType msg_type,
|
||||
const char *format, ...);
|
||||
|
||||
/**
|
||||
* Prepare a success message in the specified client's buffer
|
||||
*
|
||||
* @param c Client to prepare message for
|
||||
* @param msg_type Type of message
|
||||
*/
|
||||
void ipc_prepare_reply_success(IPCClient *c, IPCMessageType msg_type);
|
||||
|
||||
/**
|
||||
* Send a tag_change_event to all subscribers. Should be called only when there
|
||||
* has been a tag state change.
|
||||
*
|
||||
* @param mon_num The index of the monitor (Monitor.num property)
|
||||
* @param old_state The old tag state
|
||||
* @param new_state The new (now current) tag state
|
||||
*/
|
||||
void ipc_tag_change_event(const int mon_num, TagState old_state,
|
||||
TagState new_state);
|
||||
|
||||
/**
|
||||
* Send a client_focus_change_event to all subscribers. Should be called only
|
||||
* when the client focus changes.
|
||||
*
|
||||
* @param mon_num The index of the monitor (Monitor.num property)
|
||||
* @param old_client The old DWM client selection (Monitor.oldsel)
|
||||
* @param new_client The new (now current) DWM client selection
|
||||
*/
|
||||
void ipc_client_focus_change_event(const int mon_num, Client *old_client,
|
||||
Client *new_client);
|
||||
|
||||
/**
|
||||
* Send a layout_change_event to all subscribers. Should be called only
|
||||
* when there has been a layout change.
|
||||
*
|
||||
* @param mon_num The index of the monitor (Monitor.num property)
|
||||
* @param old_symbol The old layout symbol
|
||||
* @param old_layout Address to the old Layout
|
||||
* @param new_symbol The new (now current) layout symbol
|
||||
* @param new_layout Address to the new Layout
|
||||
*/
|
||||
void ipc_layout_change_event(const int mon_num, const char *old_symbol,
|
||||
const Layout *old_layout, const char *new_symbol,
|
||||
const Layout *new_layout);
|
||||
|
||||
/**
|
||||
* Send a monitor_focus_change_event to all subscribers. Should be called only
|
||||
* when the monitor focus changes.
|
||||
*
|
||||
* @param last_mon_num The index of the previously selected monitor
|
||||
* @param new_mon_num The index of the newly selected monitor
|
||||
*/
|
||||
void ipc_monitor_focus_change_event(const int last_mon_num,
|
||||
const int new_mon_num);
|
||||
|
||||
/**
|
||||
* Send a focused_title_change_event to all subscribers. Should only be called
|
||||
* if a selected client has a title change.
|
||||
*
|
||||
* @param mon_num Index of the client's monitor
|
||||
* @param client_id Window XID of client
|
||||
* @param old_name Old name of the client window
|
||||
* @param new_name New name of the client window
|
||||
*/
|
||||
void ipc_focused_title_change_event(const int mon_num, const Window client_id,
|
||||
const char *old_name, const char *new_name);
|
||||
|
||||
/**
|
||||
* Send a focused_state_change_event to all subscribers. Should only be called
|
||||
* if a selected client has a state change.
|
||||
*
|
||||
* @param mon_num Index of the client's monitor
|
||||
* @param client_id Window XID of client
|
||||
* @param old_state Old state of the client
|
||||
* @param new_state New state of the client
|
||||
*/
|
||||
void ipc_focused_state_change_event(const int mon_num, const Window client_id,
|
||||
const ClientState *old_state,
|
||||
const ClientState *new_state);
|
||||
/**
|
||||
* Check to see if an event has occured and call the *_change_event functions
|
||||
* accordingly
|
||||
*
|
||||
* @param mons Address of Monitor pointing to start of linked list
|
||||
* @param lastselmon Address of pointer to previously selected monitor
|
||||
* @param selmon Address of selected Monitor
|
||||
*/
|
||||
void ipc_send_events(Monitor *mons, Monitor **lastselmon, Monitor *selmon);
|
||||
|
||||
/**
|
||||
* Handle an epoll event caused by a registered IPC client. Read, process, and
|
||||
* handle any received messages from clients. Write pending buffer to client if
|
||||
* the client is ready to receive messages. Drop clients that have sent an
|
||||
* EPOLLHUP.
|
||||
*
|
||||
* @param ev Associated epoll event returned by epoll_wait
|
||||
* @param mons Address of Monitor pointing to start of linked list
|
||||
* @param selmon Address of selected Monitor
|
||||
* @param lastselmon Address of pointer to previously selected monitor
|
||||
* @param tags Array of tag names
|
||||
* @param tags_len Length of tags array
|
||||
* @param layouts Array of available layouts
|
||||
* @param layouts_len Length of layouts array
|
||||
*
|
||||
* @return 0 if event was successfully handled, -1 on any error receiving
|
||||
* or handling incoming messages or unhandled epoll event.
|
||||
*/
|
||||
int ipc_handle_client_epoll_event(struct epoll_event *ev, Monitor *mons,
|
||||
Monitor **lastselmon, Monitor *selmon,
|
||||
const char *tags[], const int tags_len,
|
||||
const Layout *layouts, const int layouts_len);
|
||||
|
||||
/**
|
||||
* Handle an epoll event caused by the IPC socket. This function only handles an
|
||||
* EPOLLIN event indicating a new client requesting to connect to the socket.
|
||||
*
|
||||
* @param ev Associated epoll event returned by epoll_wait
|
||||
*
|
||||
* @return 0, if the event was successfully handled, -1 if not an EPOLLIN event
|
||||
* or if a new IPC client connection request could not be accepted.
|
||||
*/
|
||||
int ipc_handle_socket_epoll_event(struct epoll_event *ev);
|
||||
|
||||
#endif /* IPC_H_ */
|
373
main.c
373
main.c
@ -1,373 +0,0 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
#include "dwm.h"
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/select.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
/* extern */
|
||||
|
||||
char stext[256];
|
||||
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 *seltags;
|
||||
Bool selscreen = True;
|
||||
Client *clients = NULL;
|
||||
Client *sel = NULL;
|
||||
Client *stack = NULL;
|
||||
Cursor cursor[CurLast];
|
||||
Display *dpy;
|
||||
DC dc = {0};
|
||||
Window root, barwin;
|
||||
|
||||
/* static */
|
||||
|
||||
static int (*xerrorxlib)(Display *, XErrorEvent *);
|
||||
static Bool otherwm, readin;
|
||||
static Bool running = True;
|
||||
|
||||
static void
|
||||
cleanup(void) {
|
||||
close(STDIN_FILENO);
|
||||
while(stack) {
|
||||
unban(stack);
|
||||
unmanage(stack);
|
||||
}
|
||||
if(dc.font.set)
|
||||
XFreeFontSet(dpy, dc.font.set);
|
||||
else
|
||||
XFreeFont(dpy, dc.font.xfont);
|
||||
XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
||||
XFreePixmap(dpy, dc.drawable);
|
||||
XFreeGC(dpy, dc.gc);
|
||||
XDestroyWindow(dpy, barwin);
|
||||
XFreeCursor(dpy, cursor[CurNormal]);
|
||||
XFreeCursor(dpy, cursor[CurResize]);
|
||||
XFreeCursor(dpy, cursor[CurMove]);
|
||||
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
|
||||
XSync(dpy, False);
|
||||
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
|
||||
scan(void) {
|
||||
unsigned int i, num;
|
||||
Window *wins, d1, d2;
|
||||
XWindowAttributes wa;
|
||||
|
||||
wins = NULL;
|
||||
if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
|
||||
for(i = 0; i < num; i++) {
|
||||
if(!XGetWindowAttributes(dpy, wins[i], &wa)
|
||||
|| 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(XGetTransientForHint(dpy, wins[i], &d1)
|
||||
&& (wa.map_state == IsViewable || getstate(wins[i]) == IconicState))
|
||||
manage(wins[i], &wa);
|
||||
}
|
||||
}
|
||||
if(wins)
|
||||
XFree(wins);
|
||||
}
|
||||
|
||||
static void
|
||||
setup(void) {
|
||||
int i, j;
|
||||
unsigned int mask;
|
||||
Window w;
|
||||
XModifierKeymap *modmap;
|
||||
XSetWindowAttributes wa;
|
||||
|
||||
/* 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,
|
||||
PropModeReplace, (unsigned char *) netatom, NetLast);
|
||||
/* init cursors */
|
||||
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
|
||||
cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
|
||||
cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
|
||||
/* init modifier map */
|
||||
modmap = XGetModifierMapping(dpy);
|
||||
for (i = 0; i < 8; i++)
|
||||
for (j = 0; j < modmap->max_keypermod; j++) {
|
||||
if(modmap->modifiermap[i * modmap->max_keypermod + j]
|
||||
== XKeysymToKeycode(dpy, XK_Num_Lock))
|
||||
numlockmask = (1 << i);
|
||||
}
|
||||
XFreeModifiermap(modmap);
|
||||
/* select for events */
|
||||
wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
|
||||
| EnterWindowMask | LeaveWindowMask | StructureNotifyMask;
|
||||
wa.cursor = cursor[CurNormal];
|
||||
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
|
||||
XSelectInput(dpy, root, wa.event_mask);
|
||||
grabkeys();
|
||||
compileregs();
|
||||
for(ntags = 0; tags[ntags]; ntags++);
|
||||
seltags = emallocz(sizeof(Bool) * ntags);
|
||||
seltags[0] = True;
|
||||
/* style */
|
||||
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);
|
||||
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),
|
||||
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
|
||||
XDefineCursor(dpy, barwin, cursor[CurNormal]);
|
||||
updatebarpos();
|
||||
XMapRaised(dpy, barwin);
|
||||
strcpy(stext, "dwm-"VERSION);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Startup Error handler to check if another window manager
|
||||
* is already running.
|
||||
*/
|
||||
static int
|
||||
xerrorstart(Display *dsply, XErrorEvent *ee) {
|
||||
otherwm = True;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* extern */
|
||||
|
||||
Bool
|
||||
gettextprop(Window w, Atom atom, char *text, unsigned int size) {
|
||||
char **list = NULL;
|
||||
int n;
|
||||
XTextProperty name;
|
||||
|
||||
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
|
||||
quit(const char *arg) {
|
||||
readin = running = False;
|
||||
}
|
||||
|
||||
/* There's no way to check accesses to destroyed windows, thus those cases are
|
||||
* ignored (especially on UnmapNotify's). Other types of errors call Xlibs
|
||||
* default error handler, which may call exit.
|
||||
*/
|
||||
int
|
||||
xerror(Display *dpy, XErrorEvent *ee) {
|
||||
if(ee->error_code == BadWindow
|
||||
|| (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
|
||||
|| (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
|
||||
|| (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
|
||||
|| (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
|
||||
|| (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)
|
||||
|| (ee->request_code == X_GrabKey && ee->error_code == BadAccess)
|
||||
|| (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
|
||||
return 0;
|
||||
fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
|
||||
ee->request_code, ee->error_code);
|
||||
return xerrorxlib(dpy, ee); /* may call exit */
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
char *p;
|
||||
int r, xfd;
|
||||
fd_set rd;
|
||||
XEvent ev;
|
||||
|
||||
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, "");
|
||||
if(!(dpy = XOpenDisplay(0)))
|
||||
eprint("dwm: cannot open display\n");
|
||||
xfd = ConnectionNumber(dpy);
|
||||
screen = DefaultScreen(dpy);
|
||||
root = RootWindow(dpy, screen);
|
||||
otherwm = False;
|
||||
XSetErrorHandler(xerrorstart);
|
||||
/* this causes an error if some other window manager is running */
|
||||
XSelectInput(dpy, root, SubstructureRedirectMask);
|
||||
XSync(dpy, False);
|
||||
if(otherwm)
|
||||
eprint("dwm: another window manager is already running\n");
|
||||
|
||||
XSync(dpy, False);
|
||||
XSetErrorHandler(NULL);
|
||||
xerrorxlib = XSetErrorHandler(xerror);
|
||||
XSync(dpy, False);
|
||||
setup();
|
||||
drawstatus();
|
||||
scan();
|
||||
|
||||
/* main event loop, also reads status text from stdin */
|
||||
XSync(dpy, False);
|
||||
readin = True;
|
||||
while(running) {
|
||||
FD_ZERO(&rd);
|
||||
if(readin)
|
||||
FD_SET(STDIN_FILENO, &rd);
|
||||
FD_SET(xfd, &rd);
|
||||
if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) {
|
||||
if(errno == EINTR)
|
||||
continue;
|
||||
eprint("select failed\n");
|
||||
}
|
||||
if(FD_ISSET(STDIN_FILENO, &rd)) {
|
||||
switch(r = read(STDIN_FILENO, stext, sizeof stext - 1)) {
|
||||
case -1:
|
||||
strncpy(stext, strerror(errno), sizeof stext - 1);
|
||||
stext[sizeof stext - 1] = '\0';
|
||||
readin = False;
|
||||
break;
|
||||
case 0:
|
||||
strncpy(stext, "EOF", 4);
|
||||
readin = False;
|
||||
break;
|
||||
default:
|
||||
for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0');
|
||||
for(; p >= stext && *p != '\n'; --p);
|
||||
if(p > stext)
|
||||
strncpy(stext, p + 1, sizeof stext);
|
||||
}
|
||||
drawstatus();
|
||||
}
|
||||
while(XPending(dpy)) {
|
||||
XNextEvent(dpy, &ev);
|
||||
if(handler[ev.type])
|
||||
(handler[ev.type])(&ev); /* call handler */
|
||||
}
|
||||
}
|
||||
cleanup();
|
||||
XCloseDisplay(dpy);
|
||||
return 0;
|
||||
}
|
49
movestack.c
Normal file
49
movestack.c
Normal file
@ -0,0 +1,49 @@
|
||||
void
|
||||
movestack(const Arg *arg) {
|
||||
Client *c = NULL, *p = NULL, *pc = NULL, *i;
|
||||
|
||||
if(arg->i > 0) {
|
||||
/* find the client after selmon->sel */
|
||||
for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
|
||||
if(!c)
|
||||
for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
|
||||
|
||||
}
|
||||
else {
|
||||
/* find the client before selmon->sel */
|
||||
for(i = selmon->clients; i != selmon->sel; i = i->next)
|
||||
if(ISVISIBLE(i) && !i->isfloating)
|
||||
c = i;
|
||||
if(!c)
|
||||
for(; i; i = i->next)
|
||||
if(ISVISIBLE(i) && !i->isfloating)
|
||||
c = i;
|
||||
}
|
||||
/* find the client before selmon->sel and c */
|
||||
for(i = selmon->clients; i && (!p || !pc); i = i->next) {
|
||||
if(i->next == selmon->sel)
|
||||
p = i;
|
||||
if(i->next == c)
|
||||
pc = i;
|
||||
}
|
||||
|
||||
/* swap c and selmon->sel selmon->clients in the selmon->clients list */
|
||||
if(c && c != selmon->sel) {
|
||||
Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next;
|
||||
selmon->sel->next = c->next==selmon->sel?c:c->next;
|
||||
c->next = temp;
|
||||
|
||||
if(p && p != c)
|
||||
p->next = c;
|
||||
if(pc && pc != selmon->sel)
|
||||
pc->next = selmon->sel;
|
||||
|
||||
if(selmon->sel == selmon->clients)
|
||||
selmon->clients = c;
|
||||
else if(c == selmon->clients)
|
||||
selmon->clients = selmon->sel;
|
||||
|
||||
arrange(selmon);
|
||||
}
|
||||
}
|
||||
|
53
patches/dwm-actualfullscreen-20191112-cb3f58a.diff
Normal file
53
patches/dwm-actualfullscreen-20191112-cb3f58a.diff
Normal file
@ -0,0 +1,53 @@
|
||||
From 3a16816a6f5d38014c2a06ce395873c545c8789a Mon Sep 17 00:00:00 2001
|
||||
From: Soenke Lambert <s.lambert@mittwald.de>
|
||||
Date: Tue, 12 Nov 2019 10:44:02 +0100
|
||||
Subject: [PATCH] Fullscreen current window with [Alt]+[Shift]+[f]
|
||||
|
||||
This actually fullscreens a window, instead of just hiding the statusbar
|
||||
and applying the monocle layout.
|
||||
---
|
||||
config.def.h | 1 +
|
||||
dwm.c | 8 ++++++++
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..8cd3204 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -78,6 +78,7 @@ static Key keys[] = {
|
||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
||||
{ MODKEY, XK_space, setlayout, {0} },
|
||||
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
||||
+ { MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
|
||||
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
||||
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
|
||||
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 4465af1..c1b899a 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -211,6 +211,7 @@ static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *);
|
||||
static void togglebar(const Arg *arg);
|
||||
static void togglefloating(const Arg *arg);
|
||||
+static void togglefullscr(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
static void toggleview(const Arg *arg);
|
||||
static void unfocus(Client *c, int setfocus);
|
||||
@@ -1719,6 +1720,13 @@ togglefloating(const Arg *arg)
|
||||
arrange(selmon);
|
||||
}
|
||||
|
||||
+void
|
||||
+togglefullscr(const Arg *arg)
|
||||
+{
|
||||
+ if(selmon->sel)
|
||||
+ setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
|
||||
+}
|
||||
+
|
||||
void
|
||||
toggletag(const Arg *arg)
|
||||
{
|
||||
--
|
||||
2.17.1
|
||||
|
13
patches/dwm-alwaysfullscreen-6.1.diff
Normal file
13
patches/dwm-alwaysfullscreen-6.1.diff
Normal file
@ -0,0 +1,13 @@
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 0362114..a5cab76 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -847,7 +847,7 @@ focusstack(const Arg *arg)
|
||||
{
|
||||
Client *c = NULL, *i;
|
||||
|
||||
- if (!selmon->sel)
|
||||
+ if (!selmon->sel || selmon->sel->isfullscreen)
|
||||
return;
|
||||
if (arg->i > 0) {
|
||||
for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
|
446
patches/dwm-anybar-polybar-tray-fix-20200905-bb2e722.diff
Normal file
446
patches/dwm-anybar-polybar-tray-fix-20200905-bb2e722.diff
Normal file
@ -0,0 +1,446 @@
|
||||
From a046eabd24a430ee2a7348a807057dc7c42f7cec Mon Sep 17 00:00:00 2001
|
||||
From: mihirlad55 <mihirlad55@gmail.com>
|
||||
Date: Sat, 5 Sep 2020 00:51:33 +0000
|
||||
Subject: [PATCH] Add support for managing external status bars
|
||||
|
||||
This patch allows dwm to manage other status bars such as
|
||||
polybar/lemonbar without them needing to set override-redirect. For
|
||||
all intents and purposes, DWM treats this bar as if it were its own
|
||||
and as a result helps the status bar and DWM live in harmony.
|
||||
|
||||
This has a few advantages
|
||||
* The bar does not block fullscreen windows
|
||||
* DWM makes room for the status bar, so windows do not overlap the bar
|
||||
* The bar can be hidden/killed and DWM will not keep an unsightly gap
|
||||
where the bar was
|
||||
* DWM receives EnterNotify events when your cursor enters the bar
|
||||
|
||||
To use another status bar, set usealtbar to 1 in your config.h and set
|
||||
altbarclass to the class name (can be found using xprop) to the class
|
||||
name of your status bar. Also make sure that if your status bar will
|
||||
be displayed on top, topbar is set to 1 in your config, and if it will
|
||||
be displayed on bottom, topbar is set to 0. This patch does not
|
||||
support bars that are not docked at the top or at the bottom of your
|
||||
monitor.
|
||||
|
||||
This verison of the patch fixes handling of polybar's tray.
|
||||
|
||||
The patch is developed at https://github.com/mihirlad55/dwm-anybar
|
||||
---
|
||||
config.def.h | 4 ++
|
||||
dwm.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
2 files changed, 182 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..f45211b 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -5,6 +5,10 @@ static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const unsigned int snap = 32; /* snap pixel */
|
||||
static const int showbar = 1; /* 0 means no bar */
|
||||
static const int topbar = 1; /* 0 means bottom bar */
|
||||
+static const int usealtbar = 1; /* 1 means use non-dwm status bar */
|
||||
+static const char *altbarclass = "Polybar"; /* Alternate bar class name */
|
||||
+static const char *alttrayname = "tray"; /* Polybar tray instance name */
|
||||
+static const char *altbarcmd = "$HOME/bar.sh"; /* Alternate bar launch command */
|
||||
static const char *fonts[] = { "monospace:size=10" };
|
||||
static const char dmenufont[] = "monospace:size=10";
|
||||
static const char col_gray1[] = "#222222";
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 9fd0286..7bb5307 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -47,8 +47,8 @@
|
||||
/* macros */
|
||||
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
|
||||
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
|
||||
-#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
|
||||
- * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
|
||||
+#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - MAX((x),(m)->mx)) \
|
||||
+ * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my)))
|
||||
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
|
||||
#define LENGTH(X) (sizeof X / sizeof X[0])
|
||||
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
|
||||
@@ -116,7 +116,8 @@ struct Monitor {
|
||||
float mfact;
|
||||
int nmaster;
|
||||
int num;
|
||||
- int by; /* bar geometry */
|
||||
+ int by, bh; /* bar geometry */
|
||||
+ int tx, tw; /* bar tray geometry */
|
||||
int mx, my, mw, mh; /* screen size */
|
||||
int wx, wy, ww, wh; /* window area */
|
||||
unsigned int seltags;
|
||||
@@ -129,6 +130,7 @@ struct Monitor {
|
||||
Client *stack;
|
||||
Monitor *next;
|
||||
Window barwin;
|
||||
+ Window traywin;
|
||||
const Layout *lt[2];
|
||||
};
|
||||
|
||||
@@ -179,6 +181,8 @@ static void incnmaster(const Arg *arg);
|
||||
static void keypress(XEvent *e);
|
||||
static void killclient(const Arg *arg);
|
||||
static void manage(Window w, XWindowAttributes *wa);
|
||||
+static void managealtbar(Window win, XWindowAttributes *wa);
|
||||
+static void managetray(Window win, XWindowAttributes *wa);
|
||||
static void mappingnotify(XEvent *e);
|
||||
static void maprequest(XEvent *e);
|
||||
static void monocle(Monitor *m);
|
||||
@@ -195,6 +199,7 @@ static void resizemouse(const Arg *arg);
|
||||
static void restack(Monitor *m);
|
||||
static void run(void);
|
||||
static void scan(void);
|
||||
+static void scantray(void);
|
||||
static int sendevent(Client *c, Atom proto);
|
||||
static void sendmon(Client *c, Monitor *m);
|
||||
static void setclientstate(Client *c, long state);
|
||||
@@ -207,6 +212,7 @@ static void seturgent(Client *c, int urg);
|
||||
static void showhide(Client *c);
|
||||
static void sigchld(int unused);
|
||||
static void spawn(const Arg *arg);
|
||||
+static void spawnbar();
|
||||
static void tag(const Arg *arg);
|
||||
static void tagmon(const Arg *arg);
|
||||
static void tile(Monitor *);
|
||||
@@ -216,6 +222,8 @@ static void toggletag(const Arg *arg);
|
||||
static void toggleview(const Arg *arg);
|
||||
static void unfocus(Client *c, int setfocus);
|
||||
static void unmanage(Client *c, int destroyed);
|
||||
+static void unmanagealtbar(Window w);
|
||||
+static void unmanagetray(Window w);
|
||||
static void unmapnotify(XEvent *e);
|
||||
static void updatebarpos(Monitor *m);
|
||||
static void updatebars(void);
|
||||
@@ -230,6 +238,7 @@ static void updatewmhints(Client *c);
|
||||
static void view(const Arg *arg);
|
||||
static Client *wintoclient(Window w);
|
||||
static Monitor *wintomon(Window w);
|
||||
+static int wmclasscontains(Window win, const char *class, const char *name);
|
||||
static int xerror(Display *dpy, XErrorEvent *ee);
|
||||
static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
||||
@@ -505,8 +514,10 @@ cleanupmon(Monitor *mon)
|
||||
for (m = mons; m && m->next != mon; m = m->next);
|
||||
m->next = mon->next;
|
||||
}
|
||||
- XUnmapWindow(dpy, mon->barwin);
|
||||
- XDestroyWindow(dpy, mon->barwin);
|
||||
+ if (!usealtbar) {
|
||||
+ XUnmapWindow(dpy, mon->barwin);
|
||||
+ XDestroyWindow(dpy, mon->barwin);
|
||||
+ }
|
||||
free(mon);
|
||||
}
|
||||
|
||||
@@ -568,7 +579,7 @@ configurenotify(XEvent *e)
|
||||
for (c = m->clients; c; c = c->next)
|
||||
if (c->isfullscreen)
|
||||
resizeclient(c, m->mx, m->my, m->mw, m->mh);
|
||||
- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
|
||||
+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, m->bh);
|
||||
}
|
||||
focus(NULL);
|
||||
arrange(NULL);
|
||||
@@ -639,6 +650,7 @@ createmon(void)
|
||||
m->nmaster = nmaster;
|
||||
m->showbar = showbar;
|
||||
m->topbar = topbar;
|
||||
+ m->bh = bh;
|
||||
m->lt[0] = &layouts[0];
|
||||
m->lt[1] = &layouts[1 % LENGTH(layouts)];
|
||||
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
|
||||
@@ -649,10 +661,15 @@ void
|
||||
destroynotify(XEvent *e)
|
||||
{
|
||||
Client *c;
|
||||
+ Monitor *m;
|
||||
XDestroyWindowEvent *ev = &e->xdestroywindow;
|
||||
|
||||
if ((c = wintoclient(ev->window)))
|
||||
unmanage(c, 1);
|
||||
+ else if (usealtbar && (m = wintomon(ev->window)) && m->barwin == ev->window)
|
||||
+ unmanagealtbar(ev->window);
|
||||
+ else if (usealtbar && m->traywin == ev->window)
|
||||
+ unmanagetray(ev->window);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -696,6 +713,9 @@ dirtomon(int dir)
|
||||
void
|
||||
drawbar(Monitor *m)
|
||||
{
|
||||
+ if (usealtbar)
|
||||
+ return;
|
||||
+
|
||||
int x, w, tw = 0;
|
||||
int boxs = drw->fonts->h / 9;
|
||||
int boxw = drw->fonts->h / 6 + 2;
|
||||
@@ -1077,6 +1097,45 @@ manage(Window w, XWindowAttributes *wa)
|
||||
focus(NULL);
|
||||
}
|
||||
|
||||
+void
|
||||
+managealtbar(Window win, XWindowAttributes *wa)
|
||||
+{
|
||||
+ Monitor *m;
|
||||
+ if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
|
||||
+ return;
|
||||
+
|
||||
+ m->barwin = win;
|
||||
+ m->by = wa->y;
|
||||
+ bh = m->bh = wa->height;
|
||||
+ updatebarpos(m);
|
||||
+ arrange(m);
|
||||
+ XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
|
||||
+ XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height);
|
||||
+ XMapWindow(dpy, win);
|
||||
+ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
|
||||
+ (unsigned char *) &win, 1);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+managetray(Window win, XWindowAttributes *wa)
|
||||
+{
|
||||
+ Monitor *m;
|
||||
+ if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
|
||||
+ return;
|
||||
+
|
||||
+ m->traywin = win;
|
||||
+ m->tx = wa->x;
|
||||
+ m->tw = wa->width;
|
||||
+ updatebarpos(m);
|
||||
+ arrange(m);
|
||||
+ XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
|
||||
+ XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height);
|
||||
+ XMapWindow(dpy, win);
|
||||
+ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
|
||||
+ (unsigned char *) &win, 1);
|
||||
+}
|
||||
+
|
||||
+
|
||||
void
|
||||
mappingnotify(XEvent *e)
|
||||
{
|
||||
@@ -1097,7 +1156,9 @@ maprequest(XEvent *e)
|
||||
return;
|
||||
if (wa.override_redirect)
|
||||
return;
|
||||
- if (!wintoclient(ev->window))
|
||||
+ if (usealtbar && wmclasscontains(ev->window, altbarclass, ""))
|
||||
+ managealtbar(ev->window, &wa);
|
||||
+ else if (!wintoclient(ev->window))
|
||||
manage(ev->window, &wa);
|
||||
}
|
||||
|
||||
@@ -1393,7 +1454,9 @@ scan(void)
|
||||
if (!XGetWindowAttributes(dpy, wins[i], &wa)
|
||||
|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
|
||||
continue;
|
||||
- if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
|
||||
+ if (usealtbar && wmclasscontains(wins[i], altbarclass, ""))
|
||||
+ managealtbar(wins[i], &wa);
|
||||
+ else if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
|
||||
manage(wins[i], &wa);
|
||||
}
|
||||
for (i = 0; i < num; i++) { /* now the transients */
|
||||
@@ -1408,6 +1471,29 @@ scan(void)
|
||||
}
|
||||
}
|
||||
|
||||
+void
|
||||
+scantray(void)
|
||||
+{
|
||||
+ unsigned int num;
|
||||
+ Window d1, d2, *wins = NULL;
|
||||
+ XWindowAttributes wa;
|
||||
+
|
||||
+ if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
|
||||
+ for (unsigned int i = 0; i < num; i++) {
|
||||
+ if (wmclasscontains(wins[i], altbarclass, alttrayname)) {
|
||||
+ if (!XGetWindowAttributes(dpy, wins[i], &wa))
|
||||
+ break;
|
||||
+ managetray(wins[i], &wa);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (wins)
|
||||
+ XFree(wins);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
void
|
||||
sendmon(Client *c, Monitor *m)
|
||||
{
|
||||
@@ -1546,7 +1632,7 @@ setup(void)
|
||||
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
|
||||
die("no fonts could be loaded.");
|
||||
lrpad = drw->fonts->h;
|
||||
- bh = drw->fonts->h + 2;
|
||||
+ bh = usealtbar ? 0 : drw->fonts->h + 2;
|
||||
updategeom();
|
||||
/* init atoms */
|
||||
utf8string = XInternAtom(dpy, "UTF8_STRING", False);
|
||||
@@ -1595,6 +1681,7 @@ setup(void)
|
||||
XSelectInput(dpy, root, wa.event_mask);
|
||||
grabkeys();
|
||||
focus(NULL);
|
||||
+ spawnbar();
|
||||
}
|
||||
|
||||
|
||||
@@ -1653,6 +1740,13 @@ spawn(const Arg *arg)
|
||||
}
|
||||
}
|
||||
|
||||
+void
|
||||
+spawnbar()
|
||||
+{
|
||||
+ if (*altbarcmd)
|
||||
+ system(altbarcmd);
|
||||
+}
|
||||
+
|
||||
void
|
||||
tag(const Arg *arg)
|
||||
{
|
||||
@@ -1702,9 +1796,19 @@ tile(Monitor *m)
|
||||
void
|
||||
togglebar(const Arg *arg)
|
||||
{
|
||||
+ /**
|
||||
+ * Polybar tray does not raise maprequest event. It must be manually scanned
|
||||
+ * for. Scanning it too early while the tray is being populated would give
|
||||
+ * wrong dimensions.
|
||||
+ */
|
||||
+ if (usealtbar && !selmon->traywin)
|
||||
+ scantray();
|
||||
+
|
||||
selmon->showbar = !selmon->showbar;
|
||||
updatebarpos(selmon);
|
||||
- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
|
||||
+ XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, selmon->bh);
|
||||
+ if (usealtbar)
|
||||
+ XMoveResizeWindow(dpy, selmon->traywin, selmon->tx, selmon->by, selmon->tw, selmon->bh);
|
||||
arrange(selmon);
|
||||
}
|
||||
|
||||
@@ -1787,10 +1891,41 @@ unmanage(Client *c, int destroyed)
|
||||
arrange(m);
|
||||
}
|
||||
|
||||
+void
|
||||
+unmanagealtbar(Window w)
|
||||
+{
|
||||
+ Monitor *m = wintomon(w);
|
||||
+
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+
|
||||
+ m->barwin = 0;
|
||||
+ m->by = 0;
|
||||
+ m->bh = 0;
|
||||
+ updatebarpos(m);
|
||||
+ arrange(m);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+unmanagetray(Window w)
|
||||
+{
|
||||
+ Monitor *m = wintomon(w);
|
||||
+
|
||||
+ if (!m)
|
||||
+ return;
|
||||
+
|
||||
+ m->traywin = 0;
|
||||
+ m->tx = 0;
|
||||
+ m->tw = 0;
|
||||
+ updatebarpos(m);
|
||||
+ arrange(m);
|
||||
+}
|
||||
+
|
||||
void
|
||||
unmapnotify(XEvent *e)
|
||||
{
|
||||
Client *c;
|
||||
+ Monitor *m;
|
||||
XUnmapEvent *ev = &e->xunmap;
|
||||
|
||||
if ((c = wintoclient(ev->window))) {
|
||||
@@ -1798,12 +1933,18 @@ unmapnotify(XEvent *e)
|
||||
setclientstate(c, WithdrawnState);
|
||||
else
|
||||
unmanage(c, 0);
|
||||
- }
|
||||
+ } else if (usealtbar && (m = wintomon(ev->window)) && m->barwin == ev->window)
|
||||
+ unmanagealtbar(ev->window);
|
||||
+ else if (usealtbar && m->traywin == ev->window)
|
||||
+ unmanagetray(ev->window);
|
||||
}
|
||||
|
||||
void
|
||||
updatebars(void)
|
||||
{
|
||||
+ if (usealtbar)
|
||||
+ return;
|
||||
+
|
||||
Monitor *m;
|
||||
XSetWindowAttributes wa = {
|
||||
.override_redirect = True,
|
||||
@@ -1829,11 +1970,11 @@ updatebarpos(Monitor *m)
|
||||
m->wy = m->my;
|
||||
m->wh = m->mh;
|
||||
if (m->showbar) {
|
||||
- m->wh -= bh;
|
||||
+ m->wh -= m->bh;
|
||||
m->by = m->topbar ? m->wy : m->wy + m->wh;
|
||||
- m->wy = m->topbar ? m->wy + bh : m->wy;
|
||||
+ m->wy = m->topbar ? m->wy + m->bh : m->wy;
|
||||
} else
|
||||
- m->by = -bh;
|
||||
+ m->by = -m->bh;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2070,13 +2211,35 @@ wintomon(Window w)
|
||||
if (w == root && getrootptr(&x, &y))
|
||||
return recttomon(x, y, 1, 1);
|
||||
for (m = mons; m; m = m->next)
|
||||
- if (w == m->barwin)
|
||||
+ if (w == m->barwin || w == m->traywin)
|
||||
return m;
|
||||
if ((c = wintoclient(w)))
|
||||
return c->mon;
|
||||
return selmon;
|
||||
}
|
||||
|
||||
+int
|
||||
+wmclasscontains(Window win, const char *class, const char *name)
|
||||
+{
|
||||
+ XClassHint ch = { NULL, NULL };
|
||||
+ int res = 1;
|
||||
+
|
||||
+ if (XGetClassHint(dpy, win, &ch)) {
|
||||
+ if (ch.res_name && strstr(ch.res_name, name) == NULL)
|
||||
+ res = 0;
|
||||
+ if (ch.res_class && strstr(ch.res_class, class) == NULL)
|
||||
+ res = 0;
|
||||
+ } else
|
||||
+ res = 0;
|
||||
+
|
||||
+ if (ch.res_class)
|
||||
+ XFree(ch.res_class);
|
||||
+ if (ch.res_name)
|
||||
+ XFree(ch.res_name);
|
||||
+
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
/* There's no way to check accesses to destroyed windows, thus those cases are
|
||||
* ignored (especially on UnmapNotify's). Other types of errors call Xlibs
|
||||
* default error handler, which may call exit. */
|
||||
--
|
||||
2.28.0
|
||||
|
56
patches/dwm-aspectresize-6.2.diff
Normal file
56
patches/dwm-aspectresize-6.2.diff
Normal file
@ -0,0 +1,56 @@
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..2fcc30d 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -72,6 +72,8 @@ static Key keys[] = {
|
||||
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||
{ MODKEY, XK_Return, zoom, {0} },
|
||||
{ MODKEY, XK_Tab, view, {0} },
|
||||
+ { MODKEY|ShiftMask, XK_j, aspectresize, {.i = +24} },
|
||||
+ { MODKEY|ShiftMask, XK_k, aspectresize, {.i = -24} },
|
||||
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
||||
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 9fd0286..6a02119 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -146,6 +146,7 @@ static void applyrules(Client *c);
|
||||
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
|
||||
static void arrange(Monitor *m);
|
||||
static void arrangemon(Monitor *m);
|
||||
+static void aspectresize(const Arg *arg);
|
||||
static void attach(Client *c);
|
||||
static void attachstack(Client *c);
|
||||
static void buttonpress(XEvent *e);
|
||||
@@ -400,6 +401,30 @@ arrangemon(Monitor *m)
|
||||
m->lt[m->sellt]->arrange(m);
|
||||
}
|
||||
|
||||
+void
|
||||
+aspectresize(const Arg *arg) {
|
||||
+ /* only floating windows can be moved */
|
||||
+ Client *c;
|
||||
+ c = selmon->sel;
|
||||
+ float ratio;
|
||||
+ int w, h,nw, nh;
|
||||
+
|
||||
+ if (!c || !arg)
|
||||
+ return;
|
||||
+ if (selmon->lt[selmon->sellt]->arrange && !c->isfloating)
|
||||
+ return;
|
||||
+
|
||||
+ ratio = (float)c->w / (float)c->h;
|
||||
+ h = arg->i;
|
||||
+ w = (int)(ratio * h);
|
||||
+
|
||||
+ nw = c->w + w;
|
||||
+ nh = c->h + h;
|
||||
+
|
||||
+ XRaiseWindow(dpy, c->win);
|
||||
+ resize(c, c->x, c->y, nw, nh, True);
|
||||
+}
|
||||
+
|
||||
void
|
||||
attach(Client *c)
|
||||
{
|
199
patches/dwm-attachbelow-toggleable-6.2.diff
Normal file
199
patches/dwm-attachbelow-toggleable-6.2.diff
Normal file
@ -0,0 +1,199 @@
|
||||
From ee036687ed9e1bb973b9e34694a57cf5dd67652d Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Hodgson <git@jonathanh.co.uk>
|
||||
Date: Mon, 6 May 2019 18:34:40 +0100
|
||||
Subject: [PATCH 1/4] Adds attach below option
|
||||
|
||||
---
|
||||
config.def.h | 1 +
|
||||
dwm.c | 31 ++++++++++++++++++++++++++++---
|
||||
2 files changed, 29 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..51ad933 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -35,6 +35,7 @@ static const Rule rules[] = {
|
||||
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
||||
static const int nmaster = 1; /* number of clients in master area */
|
||||
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
||||
+static const int attachbelow = 1; /* 1 means attach at the end */
|
||||
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 4465af1..bd715a2 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -147,6 +147,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac
|
||||
static void arrange(Monitor *m);
|
||||
static void arrangemon(Monitor *m);
|
||||
static void attach(Client *c);
|
||||
+static void attachBelow(Client *c);
|
||||
static void attachstack(Client *c);
|
||||
static void buttonpress(XEvent *e);
|
||||
static void checkotherwm(void);
|
||||
@@ -405,6 +406,21 @@ attach(Client *c)
|
||||
c->next = c->mon->clients;
|
||||
c->mon->clients = c;
|
||||
}
|
||||
+void
|
||||
+attachBelow(Client *c)
|
||||
+{
|
||||
+ //If there is nothing on the monitor or the selected client is floating, attach as normal
|
||||
+ if(c->mon->sel == NULL || c->mon->sel == c || c->mon->sel->isfloating) {
|
||||
+ attach(c);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ //Set the new client's next property to the same as the currently selected clients next
|
||||
+ c->next = c->mon->sel->next;
|
||||
+ //Set the currently selected clients next property to the new client
|
||||
+ c->mon->sel->next = c;
|
||||
+
|
||||
+}
|
||||
|
||||
void
|
||||
attachstack(Client *c)
|
||||
@@ -1062,7 +1078,10 @@ manage(Window w, XWindowAttributes *wa)
|
||||
c->isfloating = c->oldstate = trans != None || c->isfixed;
|
||||
if (c->isfloating)
|
||||
XRaiseWindow(dpy, c->win);
|
||||
- attach(c);
|
||||
+ if( attachbelow )
|
||||
+ attachBelow(c);
|
||||
+ else
|
||||
+ attach(c);
|
||||
attachstack(c);
|
||||
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
|
||||
(unsigned char *) &(c->win), 1);
|
||||
@@ -1417,7 +1436,10 @@ sendmon(Client *c, Monitor *m)
|
||||
detachstack(c);
|
||||
c->mon = m;
|
||||
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
|
||||
- attach(c);
|
||||
+ if( attachbelow )
|
||||
+ attachBelow(c);
|
||||
+ else
|
||||
+ attach(c);
|
||||
attachstack(c);
|
||||
focus(NULL);
|
||||
arrange(NULL);
|
||||
@@ -1897,7 +1919,10 @@ updategeom(void)
|
||||
m->clients = c->next;
|
||||
detachstack(c);
|
||||
c->mon = mons;
|
||||
- attach(c);
|
||||
+ if( attachbelow )
|
||||
+ attachBelow(c);
|
||||
+ else
|
||||
+ attach(c);
|
||||
attachstack(c);
|
||||
}
|
||||
if (m == selmon)
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
||||
From e212c1d8cbdcc56c33c717131dfa7c1689e27e9f Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Hodgson <git@jonathanh.co.uk>
|
||||
Date: Mon, 6 May 2019 19:27:57 +0100
|
||||
Subject: [PATCH 2/4] fixes comment
|
||||
|
||||
---
|
||||
config.def.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 51ad933..cb8053a 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -35,7 +35,7 @@ static const Rule rules[] = {
|
||||
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
||||
static const int nmaster = 1; /* number of clients in master area */
|
||||
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
||||
-static const int attachbelow = 1; /* 1 means attach at the end */
|
||||
+static const int attachbelow = 1; /* 1 means attach after the currently active window */
|
||||
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
||||
From 7568ea3f8756e7e82b30c4943556ae646a445d1c Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Hodgson <git@jonathanh.co.uk>
|
||||
Date: Mon, 6 May 2019 20:00:30 +0100
|
||||
Subject: [PATCH 3/4] Makes changes to man page to reflect attach below patch
|
||||
|
||||
---
|
||||
dwm.1 | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/dwm.1 b/dwm.1
|
||||
index 13b3729..fb6e76c 100644
|
||||
--- a/dwm.1
|
||||
+++ b/dwm.1
|
||||
@@ -29,6 +29,9 @@ 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
|
||||
+The attach below patch makes newly spawned windows attach after the currently
|
||||
+selected window
|
||||
+.P
|
||||
dwm draws a small border around windows to indicate the focus state.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
||||
From 362b95a5b9f91673f27f3e3343b5738df3c9d6e9 Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Hodgson <git@jonathanh.co.uk>
|
||||
Date: Sun, 2 Jun 2019 15:11:57 +0100
|
||||
Subject: [PATCH 4/4] Allows attach below to be toggled
|
||||
|
||||
---
|
||||
config.def.h | 2 +-
|
||||
dwm.c | 6 ++++++
|
||||
2 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index cb8053a..b4d35aa 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -35,7 +35,7 @@ static const Rule rules[] = {
|
||||
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
||||
static const int nmaster = 1; /* number of clients in master area */
|
||||
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
||||
-static const int attachbelow = 1; /* 1 means attach after the currently active window */
|
||||
+static int attachbelow = 1; /* 1 means attach after the currently active window */
|
||||
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index bd715a2..5d88653 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -148,6 +148,7 @@ static void arrange(Monitor *m);
|
||||
static void arrangemon(Monitor *m);
|
||||
static void attach(Client *c);
|
||||
static void attachBelow(Client *c);
|
||||
+static void toggleAttachBelow();
|
||||
static void attachstack(Client *c);
|
||||
static void buttonpress(XEvent *e);
|
||||
static void checkotherwm(void);
|
||||
@@ -422,6 +423,11 @@ attachBelow(Client *c)
|
||||
|
||||
}
|
||||
|
||||
+void toggleAttachBelow()
|
||||
+{
|
||||
+ attachbelow = !attachbelow;
|
||||
+}
|
||||
+
|
||||
void
|
||||
attachstack(Client *c)
|
||||
{
|
||||
--
|
||||
2.21.0
|
||||
|
35
patches/dwm-autoresize-6.1.diff
Normal file
35
patches/dwm-autoresize-6.1.diff
Normal file
@ -0,0 +1,35 @@
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 0362114..e4e8514 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -92,7 +92,7 @@ struct Client {
|
||||
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
|
||||
int bw, oldbw;
|
||||
unsigned int tags;
|
||||
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
|
||||
+ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, needresize;
|
||||
Client *next;
|
||||
Client *snext;
|
||||
Monitor *mon;
|
||||
@@ -621,6 +621,8 @@ configurerequest(XEvent *e)
|
||||
configure(c);
|
||||
if (ISVISIBLE(c))
|
||||
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
|
||||
+ else
|
||||
+ c->needresize = 1;
|
||||
} else
|
||||
configure(c);
|
||||
} else {
|
||||
@@ -1611,6 +1613,12 @@ showhide(Client *c)
|
||||
if (ISVISIBLE(c)) {
|
||||
/* show clients top down */
|
||||
XMoveWindow(dpy, c->win, c->x, c->y);
|
||||
+ if (c->needresize) {
|
||||
+ c->needresize = 0;
|
||||
+ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
|
||||
+ } else {
|
||||
+ XMoveWindow(dpy, c->win, c->x, c->y);
|
||||
+ }
|
||||
if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
|
||||
resize(c, c->x, c->y, c->w, c->h, 0);
|
||||
showhide(c->snext);
|
90
patches/dwm-center-6.2.diff
Normal file
90
patches/dwm-center-6.2.diff
Normal file
@ -0,0 +1,90 @@
|
||||
From 69f91089d9248fa9695eb925956e255a215171b8 Mon Sep 17 00:00:00 2001
|
||||
From: bakkeby <bakkeby@gmail.com>
|
||||
Date: Tue, 7 Apr 2020 12:29:08 +0200
|
||||
Subject: [PATCH] Adding 6.2 center patch with multi-monitor fix and
|
||||
auto-centering of floating popup windows
|
||||
---
|
||||
config.def.h | 6 +++---
|
||||
dwm.c | 13 +++++++++++--
|
||||
2 files changed, 14 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..44b46e5 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -26,9 +26,9 @@ static const Rule rules[] = {
|
||||
* WM_CLASS(STRING) = instance, class
|
||||
* WM_NAME(STRING) = title
|
||||
*/
|
||||
- /* class instance title tags mask isfloating monitor */
|
||||
- { "Gimp", NULL, NULL, 0, 1, -1 },
|
||||
- { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
|
||||
+ /* class instance title tags mask iscentered isfloating monitor */
|
||||
+ { "Gimp", NULL, NULL, 0, 0, 1, -1 },
|
||||
+ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1 },
|
||||
};
|
||||
|
||||
/* layout(s) */
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 4465af1..ab33757 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -92,7 +92,7 @@ struct Client {
|
||||
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
|
||||
int bw, oldbw;
|
||||
unsigned int tags;
|
||||
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
|
||||
+ int isfixed, iscentered, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
|
||||
Client *next;
|
||||
Client *snext;
|
||||
Monitor *mon;
|
||||
@@ -137,6 +137,7 @@ typedef struct {
|
||||
const char *instance;
|
||||
const char *title;
|
||||
unsigned int tags;
|
||||
+ int iscentered;
|
||||
int isfloating;
|
||||
int monitor;
|
||||
} Rule;
|
||||
@@ -285,6 +286,7 @@ applyrules(Client *c)
|
||||
XClassHint ch = { NULL, NULL };
|
||||
|
||||
/* rule matching */
|
||||
+ c->iscentered = 0;
|
||||
c->isfloating = 0;
|
||||
c->tags = 0;
|
||||
XGetClassHint(dpy, c->win, &ch);
|
||||
@@ -297,6 +299,7 @@ applyrules(Client *c)
|
||||
&& (!r->class || strstr(class, r->class))
|
||||
&& (!r->instance || strstr(instance, r->instance)))
|
||||
{
|
||||
+ c->iscentered = r->iscentered;
|
||||
c->isfloating = r->isfloating;
|
||||
c->tags |= r->tags;
|
||||
for (m = mons; m && m->num != r->monitor; m = m->next);
|
||||
@@ -1056,6 +1059,10 @@ manage(Window w, XWindowAttributes *wa)
|
||||
updatewindowtype(c);
|
||||
updatesizehints(c);
|
||||
updatewmhints(c);
|
||||
+ if (c->iscentered) {
|
||||
+ c->x = c->mon->mx + (c->mon->mw - WIDTH(c)) / 2;
|
||||
+ c->y = c->mon->my + (c->mon->mh - HEIGHT(c)) / 2;
|
||||
+ }
|
||||
XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
|
||||
grabbuttons(c, 0);
|
||||
if (!c->isfloating)
|
||||
@@ -2009,8 +2016,10 @@ updatewindowtype(Client *c)
|
||||
|
||||
if (state == netatom[NetWMFullscreen])
|
||||
setfullscreen(c, 1);
|
||||
- if (wtype == netatom[NetWMWindowTypeDialog])
|
||||
+ if (wtype == netatom[NetWMWindowTypeDialog]) {
|
||||
+ c->iscentered = 1;
|
||||
c->isfloating = 1;
|
||||
+ }
|
||||
}
|
||||
|
||||
void
|
||||
--
|
||||
2.17.1
|
||||
|
117
patches/dwm-cfacts-20200913-61bb8b2.diff
Normal file
117
patches/dwm-cfacts-20200913-61bb8b2.diff
Normal file
@ -0,0 +1,117 @@
|
||||
From c32a879432573d71dec7fcb4bf68927d2f4cdf10 Mon Sep 17 00:00:00 2001
|
||||
From: iofq <cjriddz@protonmail.com>
|
||||
Date: Sat, 12 Sep 2020 22:28:09 -0500
|
||||
Subject: [PATCH] Fixed 'cfacts' patch failure due to upstream commit
|
||||
'f09418bbb...'
|
||||
|
||||
---
|
||||
config.def.h | 3 +++
|
||||
dwm.c | 34 +++++++++++++++++++++++++++++++---
|
||||
2 files changed, 34 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..83910c1 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -70,6 +70,9 @@ static Key keys[] = {
|
||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
||||
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||
+ { MODKEY|ShiftMask, XK_h, setcfact, {.f = +0.25} },
|
||||
+ { MODKEY|ShiftMask, XK_l, setcfact, {.f = -0.25} },
|
||||
+ { MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} },
|
||||
{ MODKEY, XK_Return, zoom, {0} },
|
||||
{ MODKEY, XK_Tab, view, {0} },
|
||||
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 664c527..5233229 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -87,6 +87,7 @@ typedef struct Client Client;
|
||||
struct Client {
|
||||
char name[256];
|
||||
float mina, maxa;
|
||||
+ float cfact;
|
||||
int x, y, w, h;
|
||||
int oldx, oldy, oldw, oldh;
|
||||
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
|
||||
@@ -201,6 +202,7 @@ static void setclientstate(Client *c, long state);
|
||||
static void setfocus(Client *c);
|
||||
static void setfullscreen(Client *c, int fullscreen);
|
||||
static void setlayout(const Arg *arg);
|
||||
+static void setcfact(const Arg *arg);
|
||||
static void setmfact(const Arg *arg);
|
||||
static void setup(void);
|
||||
static void seturgent(Client *c, int urg);
|
||||
@@ -1030,6 +1032,7 @@ manage(Window w, XWindowAttributes *wa)
|
||||
c->w = c->oldw = wa->width;
|
||||
c->h = c->oldh = wa->height;
|
||||
c->oldbw = wa->border_width;
|
||||
+ c->cfact = 1.0;
|
||||
|
||||
updatetitle(c);
|
||||
if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
|
||||
@@ -1512,6 +1515,23 @@ setlayout(const Arg *arg)
|
||||
drawbar(selmon);
|
||||
}
|
||||
|
||||
+void setcfact(const Arg *arg) {
|
||||
+ float f;
|
||||
+ Client *c;
|
||||
+
|
||||
+ c = selmon->sel;
|
||||
+
|
||||
+ if(!arg || !c || !selmon->lt[selmon->sellt]->arrange)
|
||||
+ return;
|
||||
+ f = arg->f + c->cfact;
|
||||
+ if(arg->f == 0.0)
|
||||
+ f = 1.0;
|
||||
+ else if(f < 0.25 || f > 4.0)
|
||||
+ return;
|
||||
+ c->cfact = f;
|
||||
+ arrange(selmon);
|
||||
+}
|
||||
+
|
||||
/* arg > 1.0 will set mfact absolutely */
|
||||
void
|
||||
setmfact(const Arg *arg)
|
||||
@@ -1675,9 +1695,15 @@ void
|
||||
tile(Monitor *m)
|
||||
{
|
||||
unsigned int i, n, h, mw, my, ty;
|
||||
+ float mfacts = 0, sfacts = 0;
|
||||
Client *c;
|
||||
|
||||
- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
|
||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) {
|
||||
+ if (n < m->nmaster)
|
||||
+ mfacts += c->cfact;
|
||||
+ else
|
||||
+ sfacts += c->cfact;
|
||||
+ }
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
@@ -1687,15 +1713,17 @@ tile(Monitor *m)
|
||||
mw = m->ww;
|
||||
for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
if (i < m->nmaster) {
|
||||
- h = (m->wh - my) / (MIN(n, m->nmaster) - i);
|
||||
+ h = (m->wh - my) * (c->cfact / mfacts);
|
||||
resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
|
||||
if (my + HEIGHT(c) < m->wh)
|
||||
my += HEIGHT(c);
|
||||
+ mfacts -= c->cfact;
|
||||
} else {
|
||||
- h = (m->wh - ty) / (n - i);
|
||||
+ h = (m->wh - ty) * (c->cfact / sfacts);
|
||||
resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0);
|
||||
if (ty + HEIGHT(c) < m->wh)
|
||||
ty += HEIGHT(c);
|
||||
+ sfacts -= c->cfact;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.28.0
|
||||
|
992
patches/dwm-cfacts-vanitygaps-6.2.diff
Normal file
992
patches/dwm-cfacts-vanitygaps-6.2.diff
Normal file
@ -0,0 +1,992 @@
|
||||
From 051e4de72079bb0b8e50d2faa61b9a0ef36434b5 Mon Sep 17 00:00:00 2001
|
||||
From: bakkeby <bakkeby@gmail.com>
|
||||
Date: Fri, 8 May 2020 16:51:00 +0200
|
||||
Subject: [PATCH 2/2] vanitygaps - adds gaps to layouts
|
||||
|
||||
This patch differentiates between inner and outer gaps as well as
|
||||
horizontal and vertical gaps.
|
||||
|
||||
The logic of these layouts also aims to be pixel perfect by ensuring
|
||||
an even split of the available space and re-distributing the remainder
|
||||
among the available clients.
|
||||
---
|
||||
config.def.h | 38 ++-
|
||||
dwm.c | 43 +--
|
||||
vanitygaps.c | 822 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 867 insertions(+), 36 deletions(-)
|
||||
create mode 100644 vanitygaps.c
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 83910c1..91a9cfc 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -3,6 +3,11 @@
|
||||
/* appearance */
|
||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const unsigned int snap = 32; /* snap pixel */
|
||||
+static const unsigned int gappih = 20; /* horiz inner gap between windows */
|
||||
+static const unsigned int gappiv = 10; /* vert inner gap between windows */
|
||||
+static const unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */
|
||||
+static const unsigned int gappov = 30; /* vert outer gap between windows and screen edge */
|
||||
+static int smartgaps = 0; /* 1 means no outer gap when there is only one window */
|
||||
static const int showbar = 1; /* 0 means no bar */
|
||||
static const int topbar = 1; /* 0 means bottom bar */
|
||||
static const char *fonts[] = { "monospace:size=10" };
|
||||
@@ -36,11 +41,26 @@ static const float mfact = 0.55; /* factor of master area size [0.05..0.95]
|
||||
static const int nmaster = 1; /* number of clients in master area */
|
||||
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
||||
|
||||
+#define FORCE_VSPLIT 1 /* nrowgrid layout: force two clients to always split vertically */
|
||||
+#include "vanitygaps.c"
|
||||
+
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
{ "[]=", tile }, /* first entry is default */
|
||||
- { "><>", NULL }, /* no layout function means floating behavior */
|
||||
{ "[M]", monocle },
|
||||
+ { "[@]", spiral },
|
||||
+ { "[\\]", dwindle },
|
||||
+ { "H[]", deck },
|
||||
+ { "TTT", bstack },
|
||||
+ { "===", bstackhoriz },
|
||||
+ { "HHH", grid },
|
||||
+ { "###", nrowgrid },
|
||||
+ { "---", horizgrid },
|
||||
+ { ":::", gaplessgrid },
|
||||
+ { "|M|", centeredmaster },
|
||||
+ { ">M>", centeredfloatingmaster },
|
||||
+ { "><>", NULL }, /* no layout function means floating behavior */
|
||||
+ { NULL, NULL },
|
||||
};
|
||||
|
||||
/* key definitions */
|
||||
@@ -74,6 +94,22 @@ static Key keys[] = {
|
||||
{ MODKEY|ShiftMask, XK_l, setcfact, {.f = -0.25} },
|
||||
{ MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} },
|
||||
{ MODKEY, XK_Return, zoom, {0} },
|
||||
+ { MODKEY|Mod4Mask, XK_u, incrgaps, {.i = +1 } },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_u, incrgaps, {.i = -1 } },
|
||||
+ { MODKEY|Mod4Mask, XK_i, incrigaps, {.i = +1 } },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_i, incrigaps, {.i = -1 } },
|
||||
+ { MODKEY|Mod4Mask, XK_o, incrogaps, {.i = +1 } },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_o, incrogaps, {.i = -1 } },
|
||||
+ { MODKEY|Mod4Mask, XK_6, incrihgaps, {.i = +1 } },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_6, incrihgaps, {.i = -1 } },
|
||||
+ { MODKEY|Mod4Mask, XK_7, incrivgaps, {.i = +1 } },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_7, incrivgaps, {.i = -1 } },
|
||||
+ { MODKEY|Mod4Mask, XK_8, incrohgaps, {.i = +1 } },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_8, incrohgaps, {.i = -1 } },
|
||||
+ { MODKEY|Mod4Mask, XK_9, incrovgaps, {.i = +1 } },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_9, incrovgaps, {.i = -1 } },
|
||||
+ { MODKEY|Mod4Mask, XK_0, togglegaps, {0} },
|
||||
+ { MODKEY|Mod4Mask|ShiftMask, XK_0, defaultgaps, {0} },
|
||||
{ MODKEY, XK_Tab, view, {0} },
|
||||
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 5592c57..7d503cb 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -120,6 +120,10 @@ struct Monitor {
|
||||
int by; /* bar geometry */
|
||||
int mx, my, mw, mh; /* screen size */
|
||||
int wx, wy, ww, wh; /* window area */
|
||||
+ int gappih; /* horizontal gap between windows */
|
||||
+ int gappiv; /* vertical gap between windows */
|
||||
+ int gappoh; /* horizontal outer gaps */
|
||||
+ int gappov; /* vertical outer gaps */
|
||||
unsigned int seltags;
|
||||
unsigned int sellt;
|
||||
unsigned int tagset[2];
|
||||
@@ -210,7 +214,6 @@ static void sigchld(int unused);
|
||||
static void spawn(const Arg *arg);
|
||||
static void tag(const Arg *arg);
|
||||
static void tagmon(const Arg *arg);
|
||||
-static void tile(Monitor *);
|
||||
static void togglebar(const Arg *arg);
|
||||
static void togglefloating(const Arg *arg);
|
||||
static void toggletag(const Arg *arg);
|
||||
@@ -640,6 +643,10 @@ createmon(void)
|
||||
m->nmaster = nmaster;
|
||||
m->showbar = showbar;
|
||||
m->topbar = topbar;
|
||||
+ m->gappih = gappih;
|
||||
+ m->gappiv = gappiv;
|
||||
+ m->gappoh = gappoh;
|
||||
+ m->gappov = gappov;
|
||||
m->lt[0] = &layouts[0];
|
||||
m->lt[1] = &layouts[1 % LENGTH(layouts)];
|
||||
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
|
||||
@@ -1691,40 +1698,6 @@ tagmon(const Arg *arg)
|
||||
sendmon(selmon->sel, dirtomon(arg->i));
|
||||
}
|
||||
|
||||
-void
|
||||
-tile(Monitor *m)
|
||||
-{
|
||||
- unsigned int i, n, h, mw, my, ty;
|
||||
- float mfacts = 0, sfacts = 0;
|
||||
- Client *c;
|
||||
-
|
||||
- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) {
|
||||
- if (n < m->nmaster)
|
||||
- mfacts += c->cfact;
|
||||
- else
|
||||
- sfacts += c->cfact;
|
||||
- }
|
||||
- if (n == 0)
|
||||
- return;
|
||||
-
|
||||
- if (n > m->nmaster)
|
||||
- mw = m->nmaster ? m->ww * m->mfact : 0;
|
||||
- else
|
||||
- mw = m->ww;
|
||||
- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
- if (i < m->nmaster) {
|
||||
- h = (m->wh - my) * (c->cfact / mfacts);
|
||||
- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
|
||||
- my += HEIGHT(c);
|
||||
- mfacts -= c->cfact;
|
||||
- } else {
|
||||
- h = (m->wh - ty) * (c->cfact / sfacts);
|
||||
- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0);
|
||||
- ty += HEIGHT(c);
|
||||
- sfacts -= c->cfact;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
void
|
||||
togglebar(const Arg *arg)
|
||||
{
|
||||
diff --git a/vanitygaps.c b/vanitygaps.c
|
||||
new file mode 100644
|
||||
index 0000000..1a816b6
|
||||
--- /dev/null
|
||||
+++ b/vanitygaps.c
|
||||
@@ -0,0 +1,822 @@
|
||||
+/* Key binding functions */
|
||||
+static void defaultgaps(const Arg *arg);
|
||||
+static void incrgaps(const Arg *arg);
|
||||
+static void incrigaps(const Arg *arg);
|
||||
+static void incrogaps(const Arg *arg);
|
||||
+static void incrohgaps(const Arg *arg);
|
||||
+static void incrovgaps(const Arg *arg);
|
||||
+static void incrihgaps(const Arg *arg);
|
||||
+static void incrivgaps(const Arg *arg);
|
||||
+static void togglegaps(const Arg *arg);
|
||||
+/* Layouts (delete the ones you do not need) */
|
||||
+static void bstack(Monitor *m);
|
||||
+static void bstackhoriz(Monitor *m);
|
||||
+static void centeredmaster(Monitor *m);
|
||||
+static void centeredfloatingmaster(Monitor *m);
|
||||
+static void deck(Monitor *m);
|
||||
+static void dwindle(Monitor *m);
|
||||
+static void fibonacci(Monitor *m, int s);
|
||||
+static void grid(Monitor *m);
|
||||
+static void nrowgrid(Monitor *m);
|
||||
+static void spiral(Monitor *m);
|
||||
+static void tile(Monitor *m);
|
||||
+/* Internals */
|
||||
+static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc);
|
||||
+static void getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr);
|
||||
+static void setgaps(int oh, int ov, int ih, int iv);
|
||||
+
|
||||
+/* Settings */
|
||||
+#if !PERTAG_PATCH
|
||||
+static int enablegaps = 1;
|
||||
+#endif // PERTAG_PATCH
|
||||
+
|
||||
+void
|
||||
+setgaps(int oh, int ov, int ih, int iv)
|
||||
+{
|
||||
+ if (oh < 0) oh = 0;
|
||||
+ if (ov < 0) ov = 0;
|
||||
+ if (ih < 0) ih = 0;
|
||||
+ if (iv < 0) iv = 0;
|
||||
+
|
||||
+ selmon->gappoh = oh;
|
||||
+ selmon->gappov = ov;
|
||||
+ selmon->gappih = ih;
|
||||
+ selmon->gappiv = iv;
|
||||
+ arrange(selmon);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+togglegaps(const Arg *arg)
|
||||
+{
|
||||
+ #if PERTAG_PATCH
|
||||
+ selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag];
|
||||
+ #else
|
||||
+ enablegaps = !enablegaps;
|
||||
+ #endif // PERTAG_PATCH
|
||||
+ arrange(NULL);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+defaultgaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(gappoh, gappov, gappih, gappiv);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+incrgaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(
|
||||
+ selmon->gappoh + arg->i,
|
||||
+ selmon->gappov + arg->i,
|
||||
+ selmon->gappih + arg->i,
|
||||
+ selmon->gappiv + arg->i
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+incrigaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(
|
||||
+ selmon->gappoh,
|
||||
+ selmon->gappov,
|
||||
+ selmon->gappih + arg->i,
|
||||
+ selmon->gappiv + arg->i
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+incrogaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(
|
||||
+ selmon->gappoh + arg->i,
|
||||
+ selmon->gappov + arg->i,
|
||||
+ selmon->gappih,
|
||||
+ selmon->gappiv
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+incrohgaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(
|
||||
+ selmon->gappoh + arg->i,
|
||||
+ selmon->gappov,
|
||||
+ selmon->gappih,
|
||||
+ selmon->gappiv
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+incrovgaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(
|
||||
+ selmon->gappoh,
|
||||
+ selmon->gappov + arg->i,
|
||||
+ selmon->gappih,
|
||||
+ selmon->gappiv
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+incrihgaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(
|
||||
+ selmon->gappoh,
|
||||
+ selmon->gappov,
|
||||
+ selmon->gappih + arg->i,
|
||||
+ selmon->gappiv
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+incrivgaps(const Arg *arg)
|
||||
+{
|
||||
+ setgaps(
|
||||
+ selmon->gappoh,
|
||||
+ selmon->gappov,
|
||||
+ selmon->gappih,
|
||||
+ selmon->gappiv + arg->i
|
||||
+ );
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc)
|
||||
+{
|
||||
+ unsigned int n, oe, ie;
|
||||
+ #if PERTAG_PATCH
|
||||
+ oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag];
|
||||
+ #else
|
||||
+ oe = ie = enablegaps;
|
||||
+ #endif // PERTAG_PATCH
|
||||
+ Client *c;
|
||||
+
|
||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
|
||||
+ if (smartgaps && n == 1) {
|
||||
+ oe = 0; // outer gaps disabled when only one client
|
||||
+ }
|
||||
+
|
||||
+ *oh = m->gappoh*oe; // outer horizontal gap
|
||||
+ *ov = m->gappov*oe; // outer vertical gap
|
||||
+ *ih = m->gappih*ie; // inner horizontal gap
|
||||
+ *iv = m->gappiv*ie; // inner vertical gap
|
||||
+ *nc = n; // number of clients
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr)
|
||||
+{
|
||||
+ unsigned int n;
|
||||
+ float mfacts = 0, sfacts = 0;
|
||||
+ int mtotal = 0, stotal = 0;
|
||||
+ Client *c;
|
||||
+
|
||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
|
||||
+ if (n < m->nmaster)
|
||||
+ mfacts += c->cfact;
|
||||
+ else
|
||||
+ sfacts += c->cfact;
|
||||
+
|
||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
|
||||
+ if (n < m->nmaster)
|
||||
+ mtotal += msize * (c->cfact / mfacts);
|
||||
+ else
|
||||
+ stotal += ssize * (c->cfact / sfacts);
|
||||
+
|
||||
+ *mf = mfacts; // total factor of master area
|
||||
+ *sf = sfacts; // total factor of stack area
|
||||
+ *mr = msize - mtotal; // the remainder (rest) of pixels after a cfacts master split
|
||||
+ *sr = ssize - stotal; // the remainder (rest) of pixels after a cfacts stack split
|
||||
+}
|
||||
+
|
||||
+/***
|
||||
+ * Layouts
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Bottomstack layout + gaps
|
||||
+ * https://dwm.suckless.org/patches/bottomstack/
|
||||
+ */
|
||||
+static void
|
||||
+bstack(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
+ int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
+ float mfacts, sfacts;
|
||||
+ int mrest, srest;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ sx = mx = m->wx + ov;
|
||||
+ sy = my = m->wy + oh;
|
||||
+ sh = mh = m->wh - 2*oh;
|
||||
+ mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
|
||||
+ sw = m->ww - 2*ov - iv * (n - m->nmaster - 1);
|
||||
+
|
||||
+ if (m->nmaster && n > m->nmaster) {
|
||||
+ sh = (mh - ih) * (1 - m->mfact);
|
||||
+ mh = mh - ih - sh;
|
||||
+ sx = mx;
|
||||
+ sy = my + mh + ih;
|
||||
+ }
|
||||
+
|
||||
+ getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
+ if (i < m->nmaster) {
|
||||
+ resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
+ mx += WIDTH(c) + iv;
|
||||
+ } else {
|
||||
+ resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
||||
+ sx += WIDTH(c) + iv;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+bstackhoriz(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
+ int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
+ float mfacts, sfacts;
|
||||
+ int mrest, srest;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ sx = mx = m->wx + ov;
|
||||
+ sy = my = m->wy + oh;
|
||||
+ mh = m->wh - 2*oh;
|
||||
+ sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
|
||||
+ mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
|
||||
+ sw = m->ww - 2*ov;
|
||||
+
|
||||
+ if (m->nmaster && n > m->nmaster) {
|
||||
+ sh = (mh - ih) * (1 - m->mfact);
|
||||
+ mh = mh - ih - sh;
|
||||
+ sy = my + mh + ih;
|
||||
+ sh = m->wh - mh - 2*oh - ih * (n - m->nmaster);
|
||||
+ }
|
||||
+
|
||||
+ getfacts(m, mw, sh, &mfacts, &sfacts, &mrest, &srest);
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
+ if (i < m->nmaster) {
|
||||
+ resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
+ mx += WIDTH(c) + iv;
|
||||
+ } else {
|
||||
+ resize(c, sx, sy, sw - (2*c->bw), sh * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
|
||||
+ sy += HEIGHT(c) + ih;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Centred master layout + gaps
|
||||
+ * https://dwm.suckless.org/patches/centeredmaster/
|
||||
+ */
|
||||
+void
|
||||
+centeredmaster(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
+ int lx = 0, ly = 0, lw = 0, lh = 0;
|
||||
+ int rx = 0, ry = 0, rw = 0, rh = 0;
|
||||
+ float mfacts = 0, lfacts = 0, rfacts = 0;
|
||||
+ int mtotal = 0, ltotal = 0, rtotal = 0;
|
||||
+ int mrest = 0, lrest = 0, rrest = 0;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ /* initialize areas */
|
||||
+ mx = m->wx + ov;
|
||||
+ my = m->wy + oh;
|
||||
+ mh = m->wh - 2*oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1);
|
||||
+ mw = m->ww - 2*ov;
|
||||
+ lh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - 1);
|
||||
+ rh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1));
|
||||
+
|
||||
+ if (m->nmaster && n > m->nmaster) {
|
||||
+ /* go mfact box in the center if more than nmaster clients */
|
||||
+ if (n - m->nmaster > 1) {
|
||||
+ /* ||<-S->|<---M--->|<-S->|| */
|
||||
+ mw = (m->ww - 2*ov - 2*iv) * m->mfact;
|
||||
+ lw = (m->ww - mw - 2*ov - 2*iv) / 2;
|
||||
+ rw = (m->ww - mw - 2*ov - 2*iv) - lw;
|
||||
+ mx += lw + iv;
|
||||
+ } else {
|
||||
+ /* ||<---M--->|<-S->|| */
|
||||
+ mw = (mw - iv) * m->mfact;
|
||||
+ lw = 0;
|
||||
+ rw = m->ww - mw - iv - 2*ov;
|
||||
+ }
|
||||
+ lx = m->wx + ov;
|
||||
+ ly = m->wy + oh;
|
||||
+ rx = mx + mw + iv;
|
||||
+ ry = m->wy + oh;
|
||||
+ }
|
||||
+
|
||||
+ /* calculate facts */
|
||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) {
|
||||
+ if (!m->nmaster || n < m->nmaster)
|
||||
+ mfacts += c->cfact;
|
||||
+ else if ((n - m->nmaster) % 2)
|
||||
+ lfacts += c->cfact; // total factor of left hand stack area
|
||||
+ else
|
||||
+ rfacts += c->cfact; // total factor of right hand stack area
|
||||
+ }
|
||||
+
|
||||
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
|
||||
+ if (!m->nmaster || n < m->nmaster)
|
||||
+ mtotal += mh * (c->cfact / mfacts);
|
||||
+ else if ((n - m->nmaster) % 2)
|
||||
+ ltotal += lh * (c->cfact / lfacts);
|
||||
+ else
|
||||
+ rtotal += rh * (c->cfact / rfacts);
|
||||
+
|
||||
+ mrest = mh - mtotal;
|
||||
+ lrest = lh - ltotal;
|
||||
+ rrest = rh - rtotal;
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
+ if (!m->nmaster || i < m->nmaster) {
|
||||
+ /* nmaster clients are stacked vertically, in the center of the screen */
|
||||
+ resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
||||
+ my += HEIGHT(c) + ih;
|
||||
+ } else {
|
||||
+ /* stack clients are stacked vertically */
|
||||
+ if ((i - m->nmaster) % 2 ) {
|
||||
+ resize(c, lx, ly, lw - (2*c->bw), lh * (c->cfact / lfacts) + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0);
|
||||
+ ly += HEIGHT(c) + ih;
|
||||
+ } else {
|
||||
+ resize(c, rx, ry, rw - (2*c->bw), rh * (c->cfact / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0);
|
||||
+ ry += HEIGHT(c) + ih;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+centeredfloatingmaster(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ float mfacts, sfacts;
|
||||
+ float mivf = 1.0; // master inner vertical gap factor
|
||||
+ int oh, ov, ih, iv, mrest, srest;
|
||||
+ int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
+ int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ sx = mx = m->wx + ov;
|
||||
+ sy = my = m->wy + oh;
|
||||
+ sh = mh = m->wh - 2*oh;
|
||||
+ mw = m->ww - 2*ov - iv*(n - 1);
|
||||
+ sw = m->ww - 2*ov - iv*(n - m->nmaster - 1);
|
||||
+
|
||||
+ if (m->nmaster && n > m->nmaster) {
|
||||
+ mivf = 0.8;
|
||||
+ /* go mfact box in the center if more than nmaster clients */
|
||||
+ if (m->ww > m->wh) {
|
||||
+ mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->nmaster) - 1);
|
||||
+ mh = m->wh * 0.9;
|
||||
+ } else {
|
||||
+ mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->nmaster) - 1);
|
||||
+ mh = m->wh * m->mfact;
|
||||
+ }
|
||||
+ mx = m->wx + (m->ww - mw) / 2;
|
||||
+ my = m->wy + (m->wh - mh - 2*oh) / 2;
|
||||
+
|
||||
+ sx = m->wx + ov;
|
||||
+ sy = m->wy + oh;
|
||||
+ sh = m->wh - 2*oh;
|
||||
+ }
|
||||
+
|
||||
+ getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
+ if (i < m->nmaster) {
|
||||
+ /* nmaster clients are stacked horizontally, in the center of the screen */
|
||||
+ resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
+ mx += WIDTH(c) + iv*mivf;
|
||||
+ } else {
|
||||
+ /* stack clients are stacked horizontally */
|
||||
+ resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
||||
+ sx += WIDTH(c) + iv;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Deck layout + gaps
|
||||
+ * https://dwm.suckless.org/patches/deck/
|
||||
+ */
|
||||
+void
|
||||
+deck(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
+ int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
+ float mfacts, sfacts;
|
||||
+ int mrest, srest;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ sx = mx = m->wx + ov;
|
||||
+ sy = my = m->wy + oh;
|
||||
+ sh = mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
|
||||
+ sw = mw = m->ww - 2*ov;
|
||||
+
|
||||
+ if (m->nmaster && n > m->nmaster) {
|
||||
+ sw = (mw - iv) * (1 - m->mfact);
|
||||
+ mw = mw - iv - sw;
|
||||
+ sx = mx + mw + iv;
|
||||
+ sh = m->wh - 2*oh;
|
||||
+ }
|
||||
+
|
||||
+ getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
|
||||
+
|
||||
+ if (n - m->nmaster > 0) /* override layout symbol */
|
||||
+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster);
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
+ if (i < m->nmaster) {
|
||||
+ resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
||||
+ my += HEIGHT(c) + ih;
|
||||
+ } else {
|
||||
+ resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Fibonacci layout + gaps
|
||||
+ * https://dwm.suckless.org/patches/fibonacci/
|
||||
+ */
|
||||
+void
|
||||
+fibonacci(Monitor *m, int s)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int nx, ny, nw, nh;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ int nv, hrest = 0, wrest = 0, r = 1;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ nx = m->wx + ov;
|
||||
+ ny = m->wy + oh;
|
||||
+ nw = m->ww - 2*ov;
|
||||
+ nh = m->wh - 2*oh;
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
|
||||
+ if (r) {
|
||||
+ if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw))
|
||||
+ || (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) {
|
||||
+ r = 0;
|
||||
+ }
|
||||
+ if (r && i < n - 1) {
|
||||
+ if (i % 2) {
|
||||
+ nv = (nh - ih) / 2;
|
||||
+ hrest = nh - 2*nv - ih;
|
||||
+ nh = nv;
|
||||
+ } else {
|
||||
+ nv = (nw - iv) / 2;
|
||||
+ wrest = nw - 2*nv - iv;
|
||||
+ nw = nv;
|
||||
+ }
|
||||
+
|
||||
+ if ((i % 4) == 2 && !s)
|
||||
+ nx += nw + iv;
|
||||
+ else if ((i % 4) == 3 && !s)
|
||||
+ ny += nh + ih;
|
||||
+ }
|
||||
+
|
||||
+ if ((i % 4) == 0) {
|
||||
+ if (s) {
|
||||
+ ny += nh + ih;
|
||||
+ nh += hrest;
|
||||
+ }
|
||||
+ else {
|
||||
+ nh -= hrest;
|
||||
+ ny -= nh + ih;
|
||||
+ }
|
||||
+ }
|
||||
+ else if ((i % 4) == 1) {
|
||||
+ nx += nw + iv;
|
||||
+ nw += wrest;
|
||||
+ }
|
||||
+ else if ((i % 4) == 2) {
|
||||
+ ny += nh + ih;
|
||||
+ nh += hrest;
|
||||
+ if (i < n - 1)
|
||||
+ nw += wrest;
|
||||
+ }
|
||||
+ else if ((i % 4) == 3) {
|
||||
+ if (s) {
|
||||
+ nx += nw + iv;
|
||||
+ nw -= wrest;
|
||||
+ } else {
|
||||
+ nw -= wrest;
|
||||
+ nx -= nw + iv;
|
||||
+ nh += hrest;
|
||||
+ }
|
||||
+ }
|
||||
+ if (i == 0) {
|
||||
+ if (n != 1) {
|
||||
+ nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact);
|
||||
+ wrest = 0;
|
||||
+ }
|
||||
+ ny = m->wy + oh;
|
||||
+ }
|
||||
+ else if (i == 1)
|
||||
+ nw = m->ww - nw - iv - 2*ov;
|
||||
+ i++;
|
||||
+ }
|
||||
+
|
||||
+ resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+dwindle(Monitor *m)
|
||||
+{
|
||||
+ fibonacci(m, 1);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+spiral(Monitor *m)
|
||||
+{
|
||||
+ fibonacci(m, 0);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Gappless grid layout + gaps (ironically)
|
||||
+ * https://dwm.suckless.org/patches/gaplessgrid/
|
||||
+ */
|
||||
+void
|
||||
+gaplessgrid(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters
|
||||
+ int oh, ov, ih, iv;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ /* grid dimensions */
|
||||
+ for (cols = 0; cols <= n/2; cols++)
|
||||
+ if (cols*cols >= n)
|
||||
+ break;
|
||||
+ if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
|
||||
+ cols = 2;
|
||||
+ rows = n/cols;
|
||||
+ cn = rn = 0; // reset column no, row no, client count
|
||||
+
|
||||
+ ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
|
||||
+ cw = (m->ww - 2*ov - iv * (cols - 1)) / cols;
|
||||
+ rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
||||
+ crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
|
||||
+ x = m->wx + ov;
|
||||
+ y = m->wy + oh;
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) {
|
||||
+ if (i/rows + 1 > cols - n%cols) {
|
||||
+ rows = n/cols + 1;
|
||||
+ ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
|
||||
+ rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
||||
+ }
|
||||
+ resize(c,
|
||||
+ x,
|
||||
+ y + rn*(ch + ih) + MIN(rn, rrest),
|
||||
+ cw + (cn < crest ? 1 : 0) - 2*c->bw,
|
||||
+ ch + (rn < rrest ? 1 : 0) - 2*c->bw,
|
||||
+ 0);
|
||||
+ rn++;
|
||||
+ if (rn >= rows) {
|
||||
+ rn = 0;
|
||||
+ x += cw + ih + (cn < crest ? 1 : 0);
|
||||
+ cn++;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Gridmode layout + gaps
|
||||
+ * https://dwm.suckless.org/patches/gridmode/
|
||||
+ */
|
||||
+void
|
||||
+grid(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+
|
||||
+ /* grid dimensions */
|
||||
+ for (rows = 0; rows <= n/2; rows++)
|
||||
+ if (rows*rows >= n)
|
||||
+ break;
|
||||
+ cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
|
||||
+
|
||||
+ /* window geoms (cell height/width) */
|
||||
+ ch = (m->wh - 2*oh - ih * (rows - 1)) / (rows ? rows : 1);
|
||||
+ cw = (m->ww - 2*ov - iv * (cols - 1)) / (cols ? cols : 1);
|
||||
+ chrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
||||
+ cwrest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
+ cc = i / rows;
|
||||
+ cr = i % rows;
|
||||
+ cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest);
|
||||
+ cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest);
|
||||
+ resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Horizontal grid layout + gaps
|
||||
+ * https://dwm.suckless.org/patches/horizgrid/
|
||||
+ */
|
||||
+void
|
||||
+horizgrid(Monitor *m) {
|
||||
+ Client *c;
|
||||
+ unsigned int n, i;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
+ int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
+ int ntop, nbottom = 1;
|
||||
+ float mfacts = 0, sfacts = 0;
|
||||
+ int mrest, srest, mtotal = 0, stotal = 0;
|
||||
+
|
||||
+ /* Count windows */
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ if (n <= 2)
|
||||
+ ntop = n;
|
||||
+ else {
|
||||
+ ntop = n / 2;
|
||||
+ nbottom = n - ntop;
|
||||
+ }
|
||||
+ sx = mx = m->wx + ov;
|
||||
+ sy = my = m->wy + oh;
|
||||
+ sh = mh = m->wh - 2*oh;
|
||||
+ sw = mw = m->ww - 2*ov;
|
||||
+
|
||||
+ if (n > ntop) {
|
||||
+ sh = (mh - ih) / 2;
|
||||
+ mh = mh - ih - sh;
|
||||
+ sy = my + mh + ih;
|
||||
+ mw = m->ww - 2*ov - iv * (ntop - 1);
|
||||
+ sw = m->ww - 2*ov - iv * (nbottom - 1);
|
||||
+ }
|
||||
+
|
||||
+ /* calculate facts */
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
+ if (i < ntop)
|
||||
+ mfacts += c->cfact;
|
||||
+ else
|
||||
+ sfacts += c->cfact;
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
+ if (i < ntop)
|
||||
+ mtotal += mh * (c->cfact / mfacts);
|
||||
+ else
|
||||
+ stotal += sw * (c->cfact / sfacts);
|
||||
+
|
||||
+ mrest = mh - mtotal;
|
||||
+ srest = sw - stotal;
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
+ if (i < ntop) {
|
||||
+ resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
+ mx += WIDTH(c) + iv;
|
||||
+ } else {
|
||||
+ resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
||||
+ sx += WIDTH(c) + iv;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * nrowgrid layout + gaps
|
||||
+ * https://dwm.suckless.org/patches/nrowgrid/
|
||||
+ */
|
||||
+void
|
||||
+nrowgrid(Monitor *m)
|
||||
+{
|
||||
+ unsigned int n;
|
||||
+ int ri = 0, ci = 0; /* counters */
|
||||
+ int oh, ov, ih, iv; /* vanitygap settings */
|
||||
+ unsigned int cx, cy, cw, ch; /* client geometry */
|
||||
+ unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */
|
||||
+ unsigned int cols, rows = m->nmaster + 1;
|
||||
+ Client *c;
|
||||
+
|
||||
+ /* count clients */
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+
|
||||
+ /* nothing to do here */
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ /* force 2 clients to always split vertically */
|
||||
+ if (FORCE_VSPLIT && n == 2)
|
||||
+ rows = 1;
|
||||
+
|
||||
+ /* never allow empty rows */
|
||||
+ if (n < rows)
|
||||
+ rows = n;
|
||||
+
|
||||
+ /* define first row */
|
||||
+ cols = n / rows;
|
||||
+ uc = cols;
|
||||
+ cy = m->wy + oh;
|
||||
+ ch = (m->wh - 2*oh - ih*(rows - 1)) / rows;
|
||||
+ uh = ch;
|
||||
+
|
||||
+ for (c = nexttiled(m->clients); c; c = nexttiled(c->next), ci++) {
|
||||
+ if (ci == cols) {
|
||||
+ uw = 0;
|
||||
+ ci = 0;
|
||||
+ ri++;
|
||||
+
|
||||
+ /* next row */
|
||||
+ cols = (n - uc) / (rows - ri);
|
||||
+ uc += cols;
|
||||
+ cy = m->wy + oh + uh + ih;
|
||||
+ uh += ch + ih;
|
||||
+ }
|
||||
+
|
||||
+ cx = m->wx + ov + uw;
|
||||
+ cw = (m->ww - 2*ov - uw) / (cols - ci);
|
||||
+ uw += cw + iv;
|
||||
+
|
||||
+ resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Default tile layout + gaps
|
||||
+ */
|
||||
+static void
|
||||
+tile(Monitor *m)
|
||||
+{
|
||||
+ unsigned int i, n;
|
||||
+ int oh, ov, ih, iv;
|
||||
+ int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
+ int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
+ float mfacts, sfacts;
|
||||
+ int mrest, srest;
|
||||
+ Client *c;
|
||||
+
|
||||
+ getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
+ if (n == 0)
|
||||
+ return;
|
||||
+
|
||||
+ sx = mx = m->wx + ov;
|
||||
+ sy = my = m->wy + oh;
|
||||
+ mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
|
||||
+ sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
|
||||
+ sw = mw = m->ww - 2*ov;
|
||||
+
|
||||
+ if (m->nmaster && n > m->nmaster) {
|
||||
+ sw = (mw - iv) * (1 - m->mfact);
|
||||
+ mw = mw - iv - sw;
|
||||
+ sx = mx + mw + iv;
|
||||
+ }
|
||||
+
|
||||
+ getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
|
||||
+
|
||||
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
+ if (i < m->nmaster) {
|
||||
+ resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
||||
+ my += HEIGHT(c) + ih;
|
||||
+ } else {
|
||||
+ resize(c, sx, sy, sw - (2*c->bw), sh * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
|
||||
+ sy += HEIGHT(c) + ih;
|
||||
+ }
|
||||
+}
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.19.1
|
||||
|
75
patches/dwm-combo-6.1.diff
Normal file
75
patches/dwm-combo-6.1.diff
Normal file
@ -0,0 +1,75 @@
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 0362114..40b7a99 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -234,6 +234,11 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
||||
static void zoom(const Arg *arg);
|
||||
|
||||
+static void keyrelease(XEvent *e);
|
||||
+static void combotag(const Arg *arg);
|
||||
+static void comboview(const Arg *arg);
|
||||
+
|
||||
+
|
||||
/* variables */
|
||||
static const char broken[] = "broken";
|
||||
static char stext[256];
|
||||
@@ -244,6 +249,7 @@ static int (*xerrorxlib)(Display *, XErrorEvent *);
|
||||
static unsigned int numlockmask = 0;
|
||||
static void (*handler[LASTEvent]) (XEvent *) = {
|
||||
[ButtonPress] = buttonpress,
|
||||
+ [ButtonRelease] = keyrelease,
|
||||
[ClientMessage] = clientmessage,
|
||||
[ConfigureRequest] = configurerequest,
|
||||
[ConfigureNotify] = configurenotify,
|
||||
@@ -251,6 +257,7 @@ static void (*handler[LASTEvent]) (XEvent *) = {
|
||||
[EnterNotify] = enternotify,
|
||||
[Expose] = expose,
|
||||
[FocusIn] = focusin,
|
||||
+ [KeyRelease] = keyrelease,
|
||||
[KeyPress] = keypress,
|
||||
[MappingNotify] = mappingnotify,
|
||||
[MapRequest] = maprequest,
|
||||
@@ -274,6 +281,42 @@ static Window root;
|
||||
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
|
||||
|
||||
/* function implementations */
|
||||
+static int combo = 0;
|
||||
+
|
||||
+void
|
||||
+keyrelease(XEvent *e) {
|
||||
+ combo = 0;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+combotag(const Arg *arg) {
|
||||
+ if(selmon->sel && arg->ui & TAGMASK) {
|
||||
+ if (combo) {
|
||||
+ selmon->sel->tags |= arg->ui & TAGMASK;
|
||||
+ } else {
|
||||
+ combo = 1;
|
||||
+ selmon->sel->tags = arg->ui & TAGMASK;
|
||||
+ }
|
||||
+ focus(NULL);
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+comboview(const Arg *arg) {
|
||||
+ unsigned newtags = arg->ui & TAGMASK;
|
||||
+ if (combo) {
|
||||
+ selmon->tagset[selmon->seltags] |= newtags;
|
||||
+ } else {
|
||||
+ selmon->seltags ^= 1; /*toggle tagset*/
|
||||
+ combo = 1;
|
||||
+ if (newtags)
|
||||
+ selmon->tagset[selmon->seltags] = newtags;
|
||||
+ }
|
||||
+ focus(NULL);
|
||||
+ arrange(selmon);
|
||||
+}
|
||||
+
|
||||
void
|
||||
applyrules(Client *c)
|
||||
{
|
116
patches/dwm-cool-autostart-6.2.diff
Normal file
116
patches/dwm-cool-autostart-6.2.diff
Normal file
@ -0,0 +1,116 @@
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..ed056a4 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -18,6 +18,11 @@ static const char *colors[][3] = {
|
||||
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
|
||||
};
|
||||
|
||||
+static const char *const autostart[] = {
|
||||
+ "st", NULL,
|
||||
+ NULL /* terminate */
|
||||
+};
|
||||
+
|
||||
/* tagging */
|
||||
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
||||
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 9fd0286..1facd56 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -234,6 +234,7 @@ static int xerror(Display *dpy, XErrorEvent *ee);
|
||||
static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
||||
static void zoom(const Arg *arg);
|
||||
+static void autostart_exec(void);
|
||||
|
||||
/* variables */
|
||||
static const char broken[] = "broken";
|
||||
@@ -275,6 +276,34 @@ static Window root, wmcheckwin;
|
||||
/* compile-time check if all tags fit into an unsigned int bit array. */
|
||||
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
|
||||
|
||||
+/* dwm will keep pid's of processes from autostart array and kill them at quit */
|
||||
+static pid_t *autostart_pids;
|
||||
+static size_t autostart_len;
|
||||
+
|
||||
+/* execute command from autostart array */
|
||||
+static void
|
||||
+autostart_exec() {
|
||||
+ const char *const *p;
|
||||
+ size_t i = 0;
|
||||
+
|
||||
+ /* count entries */
|
||||
+ for (p = autostart; *p; autostart_len++, p++)
|
||||
+ while (*++p);
|
||||
+
|
||||
+ autostart_pids = malloc(autostart_len * sizeof(pid_t));
|
||||
+ for (p = autostart; *p; i++, p++) {
|
||||
+ if ((autostart_pids[i] = fork()) == 0) {
|
||||
+ setsid();
|
||||
+ execvp(*p, (char *const *)p);
|
||||
+ fprintf(stderr, "dwm: execvp %s\n", *p);
|
||||
+ perror(" failed");
|
||||
+ _exit(EXIT_FAILURE);
|
||||
+ }
|
||||
+ /* skip arguments */
|
||||
+ while (*++p);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* function implementations */
|
||||
void
|
||||
applyrules(Client *c)
|
||||
@@ -1249,6 +1278,16 @@ propertynotify(XEvent *e)
|
||||
void
|
||||
quit(const Arg *arg)
|
||||
{
|
||||
+ size_t i;
|
||||
+
|
||||
+ /* kill child processes */
|
||||
+ for (i = 0; i < autostart_len; i++) {
|
||||
+ if (0 < autostart_pids[i]) {
|
||||
+ kill(autostart_pids[i], SIGTERM);
|
||||
+ waitpid(autostart_pids[i], NULL, 0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
running = 0;
|
||||
}
|
||||
|
||||
@@ -1632,9 +1671,25 @@ showhide(Client *c)
|
||||
void
|
||||
sigchld(int unused)
|
||||
{
|
||||
+ pid_t pid;
|
||||
+
|
||||
if (signal(SIGCHLD, sigchld) == SIG_ERR)
|
||||
die("can't install SIGCHLD handler:");
|
||||
- while (0 < waitpid(-1, NULL, WNOHANG));
|
||||
+ while (0 < (pid = waitpid(-1, NULL, WNOHANG))) {
|
||||
+ pid_t *p, *lim;
|
||||
+
|
||||
+ if (!(p = autostart_pids))
|
||||
+ continue;
|
||||
+ lim = &p[autostart_len];
|
||||
+
|
||||
+ for (; p < lim; p++) {
|
||||
+ if (*p == pid) {
|
||||
+ *p = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2139,6 +2194,7 @@ main(int argc, char *argv[])
|
||||
if (!(dpy = XOpenDisplay(NULL)))
|
||||
die("dwm: cannot open display");
|
||||
checkotherwm();
|
||||
+ autostart_exec();
|
||||
setup();
|
||||
#ifdef __OpenBSD__
|
||||
if (pledge("stdio rpath proc exec", NULL) == -1)
|
||||
|
93
patches/dwm-cyclelayouts-20180524-6.2.diff
Normal file
93
patches/dwm-cyclelayouts-20180524-6.2.diff
Normal file
@ -0,0 +1,93 @@
|
||||
From a09e766a4342f580582082a92b2de65f33208eb4 Mon Sep 17 00:00:00 2001
|
||||
From: Christopher Drelich <cd@cdrakka.com>
|
||||
Date: Thu, 24 May 2018 00:56:56 -0400
|
||||
Subject: [PATCH] Function to cycle through available layouts.
|
||||
|
||||
MOD-CTRL-, and MOD-CTRL-.
|
||||
cycle backwards and forwards through available layouts.
|
||||
Probably only useful if you have a lot of additional layouts.
|
||||
The NULL, NULL layout should always be the last layout in your list,
|
||||
in order to guarantee consistent behavior.
|
||||
---
|
||||
config.def.h | 3 +++
|
||||
dwm.1 | 6 ++++++
|
||||
dwm.c | 18 ++++++++++++++++++
|
||||
3 files changed, 27 insertions(+)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index a9ac303..153b880 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -41,6 +41,7 @@ static const Layout layouts[] = {
|
||||
{ "[]=", tile }, /* first entry is default */
|
||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||
{ "[M]", monocle },
|
||||
+ { NULL, NULL },
|
||||
};
|
||||
|
||||
/* key definitions */
|
||||
@@ -76,6 +77,8 @@ static Key keys[] = {
|
||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
||||
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
||||
+ { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } },
|
||||
+ { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } },
|
||||
{ MODKEY, XK_space, setlayout, {0} },
|
||||
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
||||
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
||||
diff --git a/dwm.1 b/dwm.1
|
||||
index 13b3729..165891b 100644
|
||||
--- a/dwm.1
|
||||
+++ b/dwm.1
|
||||
@@ -92,6 +92,12 @@ Sets monocle layout.
|
||||
.B Mod1\-space
|
||||
Toggles between current and previous layout.
|
||||
.TP
|
||||
+.B Mod1\-Control\-,
|
||||
+Cycles backwards in layout list.
|
||||
+.TP
|
||||
+.B Mod1\-Control\-.
|
||||
+Cycles forwards in layout list.
|
||||
+.TP
|
||||
.B Mod1\-j
|
||||
Focus next window.
|
||||
.TP
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index bb95e26..db73000 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -157,6 +157,7 @@ static void configure(Client *c);
|
||||
static void configurenotify(XEvent *e);
|
||||
static void configurerequest(XEvent *e);
|
||||
static Monitor *createmon(void);
|
||||
+static void cyclelayout(const Arg *arg);
|
||||
static void destroynotify(XEvent *e);
|
||||
static void detach(Client *c);
|
||||
static void detachstack(Client *c);
|
||||
@@ -645,6 +646,23 @@ createmon(void)
|
||||
}
|
||||
|
||||
void
|
||||
+cyclelayout(const Arg *arg) {
|
||||
+ Layout *l;
|
||||
+ for(l = (Layout *)layouts; l != selmon->lt[selmon->sellt]; l++);
|
||||
+ if(arg->i > 0) {
|
||||
+ if(l->symbol && (l + 1)->symbol)
|
||||
+ setlayout(&((Arg) { .v = (l + 1) }));
|
||||
+ else
|
||||
+ setlayout(&((Arg) { .v = layouts }));
|
||||
+ } else {
|
||||
+ if(l != layouts && (l - 1)->symbol)
|
||||
+ setlayout(&((Arg) { .v = (l - 1) }));
|
||||
+ else
|
||||
+ setlayout(&((Arg) { .v = &layouts[LENGTH(layouts) - 2] }));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
destroynotify(XEvent *e)
|
||||
{
|
||||
Client *c;
|
||||
--
|
||||
2.7.4
|
||||
|
240
patches/dwm-dwmc-6.2.diff
Normal file
240
patches/dwm-dwmc-6.2.diff
Normal file
@ -0,0 +1,240 @@
|
||||
From d94cb6f1a553d19127f44dbdc96e8bb5041956c2 Mon Sep 17 00:00:00 2001
|
||||
From: Nihal Jere <noocsharp@gmail.com>
|
||||
Date: Sat, 21 Mar 2020 15:16:49 -0500
|
||||
Subject: [PATCH] dwm-client
|
||||
|
||||
---
|
||||
Makefile | 2 +-
|
||||
config.def.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
dwm.c | 55 +++++++++++++++++++++++++++++++++++++++--
|
||||
dwmc | 40 ++++++++++++++++++++++++++++++
|
||||
4 files changed, 164 insertions(+), 3 deletions(-)
|
||||
create mode 100755 dwmc
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 77bcbc0..f837f5c 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -38,7 +38,7 @@ dist: clean
|
||||
|
||||
install: all
|
||||
mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||
- cp -f dwm ${DESTDIR}${PREFIX}/bin
|
||||
+ cp -f dwm dwmc ${DESTDIR}${PREFIX}/bin
|
||||
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
|
||||
mkdir -p ${DESTDIR}${MANPREFIX}/man1
|
||||
sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..efbae79 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -113,3 +113,73 @@ static Button buttons[] = {
|
||||
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
||||
};
|
||||
|
||||
+void
|
||||
+setlayoutex(const Arg *arg)
|
||||
+{
|
||||
+ setlayout(&((Arg) { .v = &layouts[arg->i] }));
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+viewex(const Arg *arg)
|
||||
+{
|
||||
+ view(&((Arg) { .ui = 1 << arg->ui }));
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+viewall(const Arg *arg)
|
||||
+{
|
||||
+ view(&((Arg){.ui = ~0}));
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+toggleviewex(const Arg *arg)
|
||||
+{
|
||||
+ toggleview(&((Arg) { .ui = 1 << arg->ui }));
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+tagex(const Arg *arg)
|
||||
+{
|
||||
+ tag(&((Arg) { .ui = 1 << arg->ui }));
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+toggletagex(const Arg *arg)
|
||||
+{
|
||||
+ toggletag(&((Arg) { .ui = 1 << arg->ui }));
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+tagall(const Arg *arg)
|
||||
+{
|
||||
+ tag(&((Arg){.ui = ~0}));
|
||||
+}
|
||||
+
|
||||
+/* signal definitions */
|
||||
+/* signum must be greater than 0 */
|
||||
+/* trigger signals using `xsetroot -name "fsignal:<signame> [<type> <value>]"` */
|
||||
+static Signal signals[] = {
|
||||
+ /* signum function */
|
||||
+ { "focusstack", focusstack },
|
||||
+ { "setmfact", setmfact },
|
||||
+ { "togglebar", togglebar },
|
||||
+ { "incnmaster", incnmaster },
|
||||
+ { "togglefloating", togglefloating },
|
||||
+ { "focusmon", focusmon },
|
||||
+ { "tagmon", tagmon },
|
||||
+ { "zoom", zoom },
|
||||
+ { "view", view },
|
||||
+ { "viewall", viewall },
|
||||
+ { "viewex", viewex },
|
||||
+ { "toggleview", view },
|
||||
+ { "toggleviewex", toggleviewex },
|
||||
+ { "tag", tag },
|
||||
+ { "tagall", tagall },
|
||||
+ { "tagex", tagex },
|
||||
+ { "toggletag", tag },
|
||||
+ { "toggletagex", toggletagex },
|
||||
+ { "killclient", killclient },
|
||||
+ { "quit", quit },
|
||||
+ { "setlayout", setlayout },
|
||||
+ { "setlayoutex", setlayoutex },
|
||||
+};
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 4465af1..aa53706 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -106,6 +106,11 @@ typedef struct {
|
||||
const Arg arg;
|
||||
} Key;
|
||||
|
||||
+typedef struct {
|
||||
+ const char * sig;
|
||||
+ void (*func)(const Arg *);
|
||||
+} Signal;
|
||||
+
|
||||
typedef struct {
|
||||
const char *symbol;
|
||||
void (*arrange)(Monitor *);
|
||||
@@ -148,6 +153,7 @@ static void arrange(Monitor *m);
|
||||
static void arrangemon(Monitor *m);
|
||||
static void attach(Client *c);
|
||||
static void attachstack(Client *c);
|
||||
+static int fake_signal(void);
|
||||
static void buttonpress(XEvent *e);
|
||||
static void checkotherwm(void);
|
||||
static void cleanup(void);
|
||||
@@ -998,6 +1004,49 @@ keypress(XEvent *e)
|
||||
keys[i].func(&(keys[i].arg));
|
||||
}
|
||||
|
||||
+int
|
||||
+fake_signal(void)
|
||||
+{
|
||||
+ char fsignal[256];
|
||||
+ char indicator[9] = "fsignal:";
|
||||
+ char str_sig[50];
|
||||
+ char param[16];
|
||||
+ int i, len_str_sig, n, paramn;
|
||||
+ size_t len_fsignal, len_indicator = strlen(indicator);
|
||||
+ Arg arg;
|
||||
+
|
||||
+ // Get root name property
|
||||
+ if (gettextprop(root, XA_WM_NAME, fsignal, sizeof(fsignal))) {
|
||||
+ len_fsignal = strlen(fsignal);
|
||||
+
|
||||
+ // Check if this is indeed a fake signal
|
||||
+ if (len_indicator > len_fsignal ? 0 : strncmp(indicator, fsignal, len_indicator) == 0) {
|
||||
+ paramn = sscanf(fsignal+len_indicator, "%s%n%s%n", str_sig, &len_str_sig, param, &n);
|
||||
+
|
||||
+ if (paramn == 1) arg = (Arg) {0};
|
||||
+ else if (paramn > 2) return 1;
|
||||
+ else if (strncmp(param, "i", n - len_str_sig) == 0)
|
||||
+ sscanf(fsignal + len_indicator + n, "%i", &(arg.i));
|
||||
+ else if (strncmp(param, "ui", n - len_str_sig) == 0)
|
||||
+ sscanf(fsignal + len_indicator + n, "%u", &(arg.ui));
|
||||
+ else if (strncmp(param, "f", n - len_str_sig) == 0)
|
||||
+ sscanf(fsignal + len_indicator + n, "%f", &(arg.f));
|
||||
+ else return 1;
|
||||
+
|
||||
+ // Check if a signal was found, and if so handle it
|
||||
+ for (i = 0; i < LENGTH(signals); i++)
|
||||
+ if (strncmp(str_sig, signals[i].sig, len_str_sig) == 0 && signals[i].func)
|
||||
+ signals[i].func(&(arg));
|
||||
+
|
||||
+ // A fake signal was sent
|
||||
+ return 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // No fake signal was sent, so proceed with update
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
void
|
||||
killclient(const Arg *arg)
|
||||
{
|
||||
@@ -1215,8 +1264,10 @@ propertynotify(XEvent *e)
|
||||
Window trans;
|
||||
XPropertyEvent *ev = &e->xproperty;
|
||||
|
||||
- if ((ev->window == root) && (ev->atom == XA_WM_NAME))
|
||||
- updatestatus();
|
||||
+ if ((ev->window == root) && (ev->atom == XA_WM_NAME)) {
|
||||
+ if (!fake_signal())
|
||||
+ updatestatus();
|
||||
+ }
|
||||
else if (ev->state == PropertyDelete)
|
||||
return; /* ignore */
|
||||
else if ((c = wintoclient(ev->window))) {
|
||||
diff --git a/dwmc b/dwmc
|
||||
new file mode 100755
|
||||
index 0000000..5ff8dbc
|
||||
--- /dev/null
|
||||
+++ b/dwmc
|
||||
@@ -0,0 +1,40 @@
|
||||
+#!/usr/bin/env sh
|
||||
+
|
||||
+signal() {
|
||||
+ xsetroot -name "fsignal:$*"
|
||||
+}
|
||||
+
|
||||
+case $# in
|
||||
+1)
|
||||
+ case $1 in
|
||||
+ setlayout | view | viewall | togglebar | togglefloating | zoom | killclient | quit)
|
||||
+ signal $1
|
||||
+ ;;
|
||||
+ *)
|
||||
+ echo "Unknown command or missing one argument."
|
||||
+ exit 1
|
||||
+ ;;
|
||||
+ esac
|
||||
+ ;;
|
||||
+2)
|
||||
+ case $1 in
|
||||
+ view)
|
||||
+ signal $1 ui $2
|
||||
+ ;;
|
||||
+ viewex | toggleviewex | tagex | toggletagex | setlayoutex | focusstack | incnmaster | focusmon | tagmon)
|
||||
+ signal $1 i $2
|
||||
+ ;;
|
||||
+ setmfact)
|
||||
+ signal $1 f $2
|
||||
+ ;;
|
||||
+ *)
|
||||
+ echo "Unknown command or one too many arguments."
|
||||
+ exit 1
|
||||
+ ;;
|
||||
+ esac
|
||||
+ ;;
|
||||
+*)
|
||||
+ echo "Too many arguments."
|
||||
+ exit 1
|
||||
+ ;;
|
||||
+esac
|
||||
--
|
||||
2.25.1
|
||||
|
27
patches/dwm-fixborders-6.2.diff
Normal file
27
patches/dwm-fixborders-6.2.diff
Normal file
@ -0,0 +1,27 @@
|
||||
From 1529909466206016f2101457bbf37c67195714c8 Mon Sep 17 00:00:00 2001
|
||||
From: Jakub Leszczak <szatan@gecc.xyz>
|
||||
Date: Fri, 22 Nov 2019 10:46:53 +0800
|
||||
Subject: [PATCH] Fix transparent borders
|
||||
|
||||
When terminal has transparency then its borders also become transparent.
|
||||
Fix it by removing transparency from any pixels drawn.
|
||||
---
|
||||
drw.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/drw.c b/drw.c
|
||||
index 8fd1ca4..490a592 100644
|
||||
--- a/drw.c
|
||||
+++ b/drw.c
|
||||
@@ -202,6 +202,8 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
|
||||
DefaultColormap(drw->dpy, drw->screen),
|
||||
clrname, dest))
|
||||
die("error, cannot allocate color '%s'", clrname);
|
||||
+
|
||||
+ dest->pixel |= 0xff << 24;
|
||||
}
|
||||
|
||||
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
||||
--
|
||||
2.26.2
|
||||
|
3246
patches/dwm-ipc-20201106-f04cac6.diff
Normal file
3246
patches/dwm-ipc-20201106-f04cac6.diff
Normal file
File diff suppressed because it is too large
Load Diff
73
patches/dwm-movestack-6.1.diff
Normal file
73
patches/dwm-movestack-6.1.diff
Normal file
@ -0,0 +1,73 @@
|
||||
diff -r 050d521d66d8 config.def.h
|
||||
--- a/config.def.h Tue Aug 24 13:13:20 2010 +0100
|
||||
+++ b/config.def.h Sun Sep 05 18:43:07 2010 +0200
|
||||
@@ -57,6 +57,7 @@
|
||||
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
|
||||
static const char *termcmd[] = { "st", NULL };
|
||||
|
||||
+#include "movestack.c"
|
||||
static Key keys[] = {
|
||||
/* modifier key function argument */
|
||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
||||
@@ -68,6 +69,8 @@
|
||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
||||
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||
+ { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
|
||||
+ { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
|
||||
{ MODKEY, XK_Return, zoom, {0} },
|
||||
{ MODKEY, XK_Tab, view, {0} },
|
||||
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||
diff -r 050d521d66d8 movestack.c
|
||||
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
|
||||
+++ b/movestack.c Sun Sep 05 18:43:07 2010 +0200
|
||||
@@ -0,0 +1,49 @@
|
||||
+void
|
||||
+movestack(const Arg *arg) {
|
||||
+ Client *c = NULL, *p = NULL, *pc = NULL, *i;
|
||||
+
|
||||
+ if(arg->i > 0) {
|
||||
+ /* find the client after selmon->sel */
|
||||
+ for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
|
||||
+ if(!c)
|
||||
+ for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
|
||||
+
|
||||
+ }
|
||||
+ else {
|
||||
+ /* find the client before selmon->sel */
|
||||
+ for(i = selmon->clients; i != selmon->sel; i = i->next)
|
||||
+ if(ISVISIBLE(i) && !i->isfloating)
|
||||
+ c = i;
|
||||
+ if(!c)
|
||||
+ for(; i; i = i->next)
|
||||
+ if(ISVISIBLE(i) && !i->isfloating)
|
||||
+ c = i;
|
||||
+ }
|
||||
+ /* find the client before selmon->sel and c */
|
||||
+ for(i = selmon->clients; i && (!p || !pc); i = i->next) {
|
||||
+ if(i->next == selmon->sel)
|
||||
+ p = i;
|
||||
+ if(i->next == c)
|
||||
+ pc = i;
|
||||
+ }
|
||||
+
|
||||
+ /* swap c and selmon->sel selmon->clients in the selmon->clients list */
|
||||
+ if(c && c != selmon->sel) {
|
||||
+ Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next;
|
||||
+ selmon->sel->next = c->next==selmon->sel?c:c->next;
|
||||
+ c->next = temp;
|
||||
+
|
||||
+ if(p && p != c)
|
||||
+ p->next = c;
|
||||
+ if(pc && pc != selmon->sel)
|
||||
+ pc->next = selmon->sel;
|
||||
+
|
||||
+ if(selmon->sel == selmon->clients)
|
||||
+ selmon->clients = c;
|
||||
+ else if(c == selmon->clients)
|
||||
+ selmon->clients = selmon->sel;
|
||||
+
|
||||
+ arrange(selmon);
|
||||
+ }
|
||||
+}
|
||||
+
|
31
patches/dwm-noborderfloatingfix-6.2.diff
Normal file
31
patches/dwm-noborderfloatingfix-6.2.diff
Normal file
@ -0,0 +1,31 @@
|
||||
From 700b0bdea872f4c00182b2bd925b41fe03f8d222 Mon Sep 17 00:00:00 2001
|
||||
From: Aidan Hall <aidan.hall@outlook.com>
|
||||
Date: Tue, 2 Jun 2020 14:41:53 +0000
|
||||
Subject: [PATCH] Prevents hiding the border if layout is floating.
|
||||
|
||||
---
|
||||
dwm.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 4465af1..2dd959d 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -1282,6 +1282,14 @@ resizeclient(Client *c, int x, int y, int w, int h)
|
||||
c->oldw = c->w; c->w = wc.width = w;
|
||||
c->oldh = c->h; c->h = wc.height = h;
|
||||
wc.border_width = c->bw;
|
||||
+ if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next))
|
||||
+ || &monocle == c->mon->lt[c->mon->sellt]->arrange)
|
||||
+ && !c->isfullscreen && !c->isfloating
|
||||
+ && NULL != c->mon->lt[c->mon->sellt]->arrange) {
|
||||
+ c->w = wc.width += c->bw * 2;
|
||||
+ c->h = wc.height += c->bw * 2;
|
||||
+ wc.border_width = 0;
|
||||
+ }
|
||||
XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
|
||||
configure(c);
|
||||
XSync(dpy, False);
|
||||
--
|
||||
2.26.2
|
||||
|
412
patches/dwm-swallow-20200807-b2de9b0.diff
Normal file
412
patches/dwm-swallow-20200807-b2de9b0.diff
Normal file
@ -0,0 +1,412 @@
|
||||
From b2de9b0fd7988241db516a8f032f26cb9cf32be1 Mon Sep 17 00:00:00 2001
|
||||
From: Ben <ben@0x1bi.net>
|
||||
Date: Fri, 7 Aug 2020 20:14:29 -0400
|
||||
Subject: [PATCH] added openbsd support for swallowing
|
||||
|
||||
---
|
||||
config.def.h | 9 +-
|
||||
config.mk | 3 +-
|
||||
dwm.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
3 files changed, 237 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..fe51476 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -3,6 +3,7 @@
|
||||
/* appearance */
|
||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const unsigned int snap = 32; /* snap pixel */
|
||||
+static const int swallowfloating = 0; /* 1 means swallow floating windows by default */
|
||||
static const int showbar = 1; /* 0 means no bar */
|
||||
static const int topbar = 1; /* 0 means bottom bar */
|
||||
static const char *fonts[] = { "monospace:size=10" };
|
||||
@@ -26,9 +27,11 @@ static const Rule rules[] = {
|
||||
* WM_CLASS(STRING) = instance, class
|
||||
* WM_NAME(STRING) = title
|
||||
*/
|
||||
- /* class instance title tags mask isfloating monitor */
|
||||
- { "Gimp", NULL, NULL, 0, 1, -1 },
|
||||
- { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
|
||||
+ /* class instance title tags mask isfloating isterminal noswallow monitor */
|
||||
+ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 },
|
||||
+ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 },
|
||||
+ { "St", NULL, NULL, 0, 0, 1, 0, -1 },
|
||||
+ { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */
|
||||
};
|
||||
|
||||
/* layout(s) */
|
||||
diff --git a/config.mk b/config.mk
|
||||
index 7084c33..ff9e508 100644
|
||||
--- a/config.mk
|
||||
+++ b/config.mk
|
||||
@@ -19,10 +19,11 @@ FREETYPELIBS = -lfontconfig -lXft
|
||||
FREETYPEINC = /usr/include/freetype2
|
||||
# OpenBSD (uncomment)
|
||||
#FREETYPEINC = ${X11INC}/freetype2
|
||||
+#KVMLIB = -lkvm
|
||||
|
||||
# includes and libs
|
||||
INCS = -I${X11INC} -I${FREETYPEINC}
|
||||
-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
|
||||
+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB}
|
||||
|
||||
# flags
|
||||
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 9fd0286..e9f08f7 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -40,6 +40,12 @@
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
#endif /* XINERAMA */
|
||||
#include <X11/Xft/Xft.h>
|
||||
+#include <X11/Xlib-xcb.h>
|
||||
+#include <xcb/res.h>
|
||||
+#ifdef __OpenBSD__
|
||||
+#include <sys/sysctl.h>
|
||||
+#include <kvm.h>
|
||||
+#endif /* __OpenBSD */
|
||||
|
||||
#include "drw.h"
|
||||
#include "util.h"
|
||||
@@ -92,9 +98,11 @@ struct Client {
|
||||
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
|
||||
int bw, oldbw;
|
||||
unsigned int tags;
|
||||
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
|
||||
+ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow;
|
||||
+ pid_t pid;
|
||||
Client *next;
|
||||
Client *snext;
|
||||
+ Client *swallowing;
|
||||
Monitor *mon;
|
||||
Window win;
|
||||
};
|
||||
@@ -138,6 +146,8 @@ typedef struct {
|
||||
const char *title;
|
||||
unsigned int tags;
|
||||
int isfloating;
|
||||
+ int isterminal;
|
||||
+ int noswallow;
|
||||
int monitor;
|
||||
} Rule;
|
||||
|
||||
@@ -235,6 +245,12 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
||||
static void zoom(const Arg *arg);
|
||||
|
||||
+static pid_t getparentprocess(pid_t p);
|
||||
+static int isdescprocess(pid_t p, pid_t c);
|
||||
+static Client *swallowingclient(Window w);
|
||||
+static Client *termforwin(const Client *c);
|
||||
+static pid_t winpid(Window w);
|
||||
+
|
||||
/* variables */
|
||||
static const char broken[] = "broken";
|
||||
static char stext[256];
|
||||
@@ -269,6 +285,8 @@ static Drw *drw;
|
||||
static Monitor *mons, *selmon;
|
||||
static Window root, wmcheckwin;
|
||||
|
||||
+static xcb_connection_t *xcon;
|
||||
+
|
||||
/* configuration, allows nested code to access above variables */
|
||||
#include "config.h"
|
||||
|
||||
@@ -298,6 +316,8 @@ applyrules(Client *c)
|
||||
&& (!r->class || strstr(class, r->class))
|
||||
&& (!r->instance || strstr(instance, r->instance)))
|
||||
{
|
||||
+ c->isterminal = r->isterminal;
|
||||
+ c->noswallow = r->noswallow;
|
||||
c->isfloating = r->isfloating;
|
||||
c->tags |= r->tags;
|
||||
for (m = mons; m && m->num != r->monitor; m = m->next);
|
||||
@@ -414,6 +434,53 @@ attachstack(Client *c)
|
||||
c->mon->stack = c;
|
||||
}
|
||||
|
||||
+void
|
||||
+swallow(Client *p, Client *c)
|
||||
+{
|
||||
+
|
||||
+ if (c->noswallow || c->isterminal)
|
||||
+ return;
|
||||
+ if (c->noswallow && !swallowfloating && c->isfloating)
|
||||
+ return;
|
||||
+
|
||||
+ detach(c);
|
||||
+ detachstack(c);
|
||||
+
|
||||
+ setclientstate(c, WithdrawnState);
|
||||
+ XUnmapWindow(dpy, p->win);
|
||||
+
|
||||
+ p->swallowing = c;
|
||||
+ c->mon = p->mon;
|
||||
+
|
||||
+ Window w = p->win;
|
||||
+ p->win = c->win;
|
||||
+ c->win = w;
|
||||
+ updatetitle(p);
|
||||
+ XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h);
|
||||
+ arrange(p->mon);
|
||||
+ configure(p);
|
||||
+ updateclientlist();
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+unswallow(Client *c)
|
||||
+{
|
||||
+ c->win = c->swallowing->win;
|
||||
+
|
||||
+ free(c->swallowing);
|
||||
+ c->swallowing = NULL;
|
||||
+
|
||||
+ /* unfullscreen the client */
|
||||
+ setfullscreen(c, 0);
|
||||
+ updatetitle(c);
|
||||
+ arrange(c->mon);
|
||||
+ XMapWindow(dpy, c->win);
|
||||
+ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
|
||||
+ setclientstate(c, NormalState);
|
||||
+ focus(NULL);
|
||||
+ arrange(c->mon);
|
||||
+}
|
||||
+
|
||||
void
|
||||
buttonpress(XEvent *e)
|
||||
{
|
||||
@@ -653,6 +720,9 @@ destroynotify(XEvent *e)
|
||||
|
||||
if ((c = wintoclient(ev->window)))
|
||||
unmanage(c, 1);
|
||||
+
|
||||
+ else if ((c = swallowingclient(ev->window)))
|
||||
+ unmanage(c->swallowing, 1);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1018,12 +1088,13 @@ killclient(const Arg *arg)
|
||||
void
|
||||
manage(Window w, XWindowAttributes *wa)
|
||||
{
|
||||
- Client *c, *t = NULL;
|
||||
+ Client *c, *t = NULL, *term = NULL;
|
||||
Window trans = None;
|
||||
XWindowChanges wc;
|
||||
|
||||
c = ecalloc(1, sizeof(Client));
|
||||
c->win = w;
|
||||
+ c->pid = winpid(w);
|
||||
/* geometry */
|
||||
c->x = c->oldx = wa->x;
|
||||
c->y = c->oldy = wa->y;
|
||||
@@ -1038,6 +1109,7 @@ manage(Window w, XWindowAttributes *wa)
|
||||
} else {
|
||||
c->mon = selmon;
|
||||
applyrules(c);
|
||||
+ term = termforwin(c);
|
||||
}
|
||||
|
||||
if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
|
||||
@@ -1074,6 +1146,8 @@ manage(Window w, XWindowAttributes *wa)
|
||||
c->mon->sel = c;
|
||||
arrange(c->mon);
|
||||
XMapWindow(dpy, c->win);
|
||||
+ if (term)
|
||||
+ swallow(term, c);
|
||||
focus(NULL);
|
||||
}
|
||||
|
||||
@@ -1768,6 +1842,20 @@ unmanage(Client *c, int destroyed)
|
||||
Monitor *m = c->mon;
|
||||
XWindowChanges wc;
|
||||
|
||||
+ if (c->swallowing) {
|
||||
+ unswallow(c);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ Client *s = swallowingclient(c->win);
|
||||
+ if (s) {
|
||||
+ free(s->swallowing);
|
||||
+ s->swallowing = NULL;
|
||||
+ arrange(m);
|
||||
+ focus(NULL);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
detach(c);
|
||||
detachstack(c);
|
||||
if (!destroyed) {
|
||||
@@ -1782,9 +1870,12 @@ unmanage(Client *c, int destroyed)
|
||||
XUngrabServer(dpy);
|
||||
}
|
||||
free(c);
|
||||
- focus(NULL);
|
||||
- updateclientlist();
|
||||
- arrange(m);
|
||||
+
|
||||
+ if (!s) {
|
||||
+ arrange(m);
|
||||
+ focus(NULL);
|
||||
+ updateclientlist();
|
||||
+ }
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2047,6 +2138,136 @@ view(const Arg *arg)
|
||||
arrange(selmon);
|
||||
}
|
||||
|
||||
+pid_t
|
||||
+winpid(Window w)
|
||||
+{
|
||||
+
|
||||
+ pid_t result = 0;
|
||||
+
|
||||
+ #ifdef __linux__
|
||||
+ xcb_res_client_id_spec_t spec = {0};
|
||||
+ spec.client = w;
|
||||
+ spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
|
||||
+
|
||||
+ xcb_generic_error_t *e = NULL;
|
||||
+ xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec);
|
||||
+ xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e);
|
||||
+
|
||||
+ if (!r)
|
||||
+ return (pid_t)0;
|
||||
+
|
||||
+ xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r);
|
||||
+ for (; i.rem; xcb_res_client_id_value_next(&i)) {
|
||||
+ spec = i.data->spec;
|
||||
+ if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
|
||||
+ uint32_t *t = xcb_res_client_id_value_value(i.data);
|
||||
+ result = *t;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ free(r);
|
||||
+
|
||||
+ if (result == (pid_t)-1)
|
||||
+ result = 0;
|
||||
+
|
||||
+ #endif /* __linux__ */
|
||||
+
|
||||
+ #ifdef __OpenBSD__
|
||||
+ Atom type;
|
||||
+ int format;
|
||||
+ unsigned long len, bytes;
|
||||
+ unsigned char *prop;
|
||||
+ pid_t ret;
|
||||
+
|
||||
+ if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 1), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop)
|
||||
+ return 0;
|
||||
+
|
||||
+ ret = *(pid_t*)prop;
|
||||
+ XFree(prop);
|
||||
+ result = ret;
|
||||
+
|
||||
+ #endif /* __OpenBSD__ */
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+pid_t
|
||||
+getparentprocess(pid_t p)
|
||||
+{
|
||||
+ unsigned int v = 0;
|
||||
+
|
||||
+#ifdef __linux__
|
||||
+ FILE *f;
|
||||
+ char buf[256];
|
||||
+ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
|
||||
+
|
||||
+ if (!(f = fopen(buf, "r")))
|
||||
+ return 0;
|
||||
+
|
||||
+ fscanf(f, "%*u %*s %*c %u", &v);
|
||||
+ fclose(f);
|
||||
+#endif /* __linux__*/
|
||||
+
|
||||
+#ifdef __OpenBSD__
|
||||
+ int n;
|
||||
+ kvm_t *kd;
|
||||
+ struct kinfo_proc *kp;
|
||||
+
|
||||
+ kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL);
|
||||
+ if (!kd)
|
||||
+ return 0;
|
||||
+
|
||||
+ kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n);
|
||||
+ v = kp->p_ppid;
|
||||
+#endif /* __OpenBSD__ */
|
||||
+
|
||||
+ return (pid_t)v;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+isdescprocess(pid_t p, pid_t c)
|
||||
+{
|
||||
+ while (p != c && c != 0)
|
||||
+ c = getparentprocess(c);
|
||||
+
|
||||
+ return (int)c;
|
||||
+}
|
||||
+
|
||||
+Client *
|
||||
+termforwin(const Client *w)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ Monitor *m;
|
||||
+
|
||||
+ if (!w->pid || w->isterminal)
|
||||
+ return NULL;
|
||||
+
|
||||
+ for (m = mons; m; m = m->next) {
|
||||
+ for (c = m->clients; c; c = c->next) {
|
||||
+ if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
|
||||
+ return c;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+Client *
|
||||
+swallowingclient(Window w)
|
||||
+{
|
||||
+ Client *c;
|
||||
+ Monitor *m;
|
||||
+
|
||||
+ for (m = mons; m; m = m->next) {
|
||||
+ for (c = m->clients; c; c = c->next) {
|
||||
+ if (c->swallowing && c->swallowing->win == w)
|
||||
+ return c;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
Client *
|
||||
wintoclient(Window w)
|
||||
{
|
||||
@@ -2138,10 +2359,12 @@ main(int argc, char *argv[])
|
||||
fputs("warning: no locale support\n", stderr);
|
||||
if (!(dpy = XOpenDisplay(NULL)))
|
||||
die("dwm: cannot open display");
|
||||
+ if (!(xcon = XGetXCBConnection(dpy)))
|
||||
+ die("dwm: cannot get xcb connection\n");
|
||||
checkotherwm();
|
||||
setup();
|
||||
#ifdef __OpenBSD__
|
||||
- if (pledge("stdio rpath proc exec", NULL) == -1)
|
||||
+ if (pledge("stdio rpath proc exec ps", NULL) == -1)
|
||||
die("pledge");
|
||||
#endif /* __OpenBSD__ */
|
||||
scan();
|
||||
--
|
||||
2.26.2
|
||||
|
38
patches/dwm-unfloatvisible-6.2.diff
Normal file
38
patches/dwm-unfloatvisible-6.2.diff
Normal file
@ -0,0 +1,38 @@
|
||||
From a972569532c9d46f79776b0f687ebbbd67a6b69f Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Courtis <alex@courtis.org>
|
||||
Date: Mon, 22 Apr 2019 22:23:12 +1000
|
||||
Subject: [PATCH] unfloat any visible windows which have isfloating set
|
||||
|
||||
optionally takes a layout to also apply
|
||||
|
||||
e.g.
|
||||
{ MODKEY|ShiftMask, XK_space, unfloatvisible, {0} },
|
||||
{ MODKEY|ShiftMask, XK_t, unfloatvisible, {.v = &layouts[1]} },
|
||||
---
|
||||
unfloat.c | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
create mode 100644 unfloat.c
|
||||
|
||||
diff --git a/unfloat.c b/unfloat.c
|
||||
new file mode 100644
|
||||
index 0000000..ef84111
|
||||
--- /dev/null
|
||||
+++ b/unfloat.c
|
||||
@@ -0,0 +1,14 @@
|
||||
+void
|
||||
+unfloatvisible(const Arg *arg)
|
||||
+{
|
||||
+ Client *c;
|
||||
+
|
||||
+ for (c = selmon->clients; c; c = c->next)
|
||||
+ if (ISVISIBLE(c) && c->isfloating)
|
||||
+ c->isfloating = c->isfixed;
|
||||
+
|
||||
+ if (arg && arg->v)
|
||||
+ setlayout(arg);
|
||||
+ else
|
||||
+ arrange(selmon);
|
||||
+}
|
||||
--
|
||||
2.21.0
|
||||
|
235
patches/dwm-xresources-6.2.diff
Normal file
235
patches/dwm-xresources-6.2.diff
Normal file
@ -0,0 +1,235 @@
|
||||
From 2832bd78a690606a48a7e1d370cd60fd92ee4988 Mon Sep 17 00:00:00 2001
|
||||
From: MLquest8 <miskuzius@gmail.com>
|
||||
Date: Fri, 12 Jun 2020 15:43:31 +0400
|
||||
Subject: [PATCH] handle various setting of various types from Xresources
|
||||
|
||||
---
|
||||
config.def.h | 54 ++++++++++++++++++++++++++-------------
|
||||
drw.c | 2 +-
|
||||
drw.h | 2 +-
|
||||
dwm.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 111 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/config.def.h b/config.def.h
|
||||
index 1c0b587..e69f288 100644
|
||||
--- a/config.def.h
|
||||
+++ b/config.def.h
|
||||
@@ -1,21 +1,22 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
/* appearance */
|
||||
-static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
-static const unsigned int snap = 32; /* snap pixel */
|
||||
-static const int showbar = 1; /* 0 means no bar */
|
||||
-static const int topbar = 1; /* 0 means bottom bar */
|
||||
+static unsigned int borderpx = 1; /* border pixel of windows */
|
||||
+static unsigned int snap = 32; /* snap pixel */
|
||||
+static int showbar = 1; /* 0 means no bar */
|
||||
+static int topbar = 1; /* 0 means bottom bar */
|
||||
static const char *fonts[] = { "monospace:size=10" };
|
||||
static const char dmenufont[] = "monospace:size=10";
|
||||
-static const char col_gray1[] = "#222222";
|
||||
-static const char col_gray2[] = "#444444";
|
||||
-static const char col_gray3[] = "#bbbbbb";
|
||||
-static const char col_gray4[] = "#eeeeee";
|
||||
-static const char col_cyan[] = "#005577";
|
||||
-static const char *colors[][3] = {
|
||||
- /* fg bg border */
|
||||
- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
|
||||
- [SchemeSel] = { col_gray4, col_cyan, col_cyan },
|
||||
+static char normbgcolor[] = "#222222";
|
||||
+static char normbordercolor[] = "#444444";
|
||||
+static char normfgcolor[] = "#bbbbbb";
|
||||
+static char selfgcolor[] = "#eeeeee";
|
||||
+static char selbordercolor[] = "#005577";
|
||||
+static char selbgcolor[] = "#005577";
|
||||
+static char *colors[][3] = {
|
||||
+ /* fg bg border */
|
||||
+ [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor },
|
||||
+ [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor },
|
||||
};
|
||||
|
||||
/* tagging */
|
||||
@@ -32,9 +33,9 @@ static const Rule rules[] = {
|
||||
};
|
||||
|
||||
/* layout(s) */
|
||||
-static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
||||
-static const int nmaster = 1; /* number of clients in master area */
|
||||
-static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
||||
+static float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
||||
+static int nmaster = 1; /* number of clients in master area */
|
||||
+static int resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
||||
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
@@ -56,9 +57,28 @@ static const Layout layouts[] = {
|
||||
|
||||
/* commands */
|
||||
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
||||
-static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
|
||||
+static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL };
|
||||
static const char *termcmd[] = { "st", NULL };
|
||||
|
||||
+/*
|
||||
+ * Xresources preferences to load at startup
|
||||
+ */
|
||||
+ResourcePref resources[] = {
|
||||
+ { "normbgcolor", STRING, &normbgcolor },
|
||||
+ { "normbordercolor", STRING, &normbordercolor },
|
||||
+ { "normfgcolor", STRING, &normfgcolor },
|
||||
+ { "selbgcolor", STRING, &selbgcolor },
|
||||
+ { "selbordercolor", STRING, &selbordercolor },
|
||||
+ { "selfgcolor", STRING, &selfgcolor },
|
||||
+ { "borderpx", INTEGER, &borderpx },
|
||||
+ { "snap", INTEGER, &snap },
|
||||
+ { "showbar", INTEGER, &showbar },
|
||||
+ { "topbar", INTEGER, &topbar },
|
||||
+ { "nmaster", INTEGER, &nmaster },
|
||||
+ { "resizehints", INTEGER, &resizehints },
|
||||
+ { "mfact", FLOAT, &mfact },
|
||||
+};
|
||||
+
|
||||
static Key keys[] = {
|
||||
/* modifier key function argument */
|
||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
||||
diff --git a/drw.c b/drw.c
|
||||
index 4cdbcbe..8f1059e 100644
|
||||
--- a/drw.c
|
||||
+++ b/drw.c
|
||||
@@ -208,7 +208,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
|
||||
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
||||
* returned color scheme when done using it. */
|
||||
Clr *
|
||||
-drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
|
||||
+drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount)
|
||||
{
|
||||
size_t i;
|
||||
Clr *ret;
|
||||
diff --git a/drw.h b/drw.h
|
||||
index 4bcd5ad..42b04ce 100644
|
||||
--- a/drw.h
|
||||
+++ b/drw.h
|
||||
@@ -39,7 +39,7 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in
|
||||
|
||||
/* Colorscheme abstraction */
|
||||
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
|
||||
-Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
|
||||
+Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount);
|
||||
|
||||
/* Cursor abstraction */
|
||||
Cur *drw_cur_create(Drw *drw, int shape);
|
||||
diff --git a/dwm.c b/dwm.c
|
||||
index 9fd0286..dc0d219 100644
|
||||
--- a/dwm.c
|
||||
+++ b/dwm.c
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/Xutil.h>
|
||||
+#include <X11/Xresource.h>
|
||||
#ifdef XINERAMA
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
#endif /* XINERAMA */
|
||||
@@ -141,6 +142,19 @@ typedef struct {
|
||||
int monitor;
|
||||
} Rule;
|
||||
|
||||
+/* Xresources preferences */
|
||||
+enum resource_type {
|
||||
+ STRING = 0,
|
||||
+ INTEGER = 1,
|
||||
+ FLOAT = 2
|
||||
+};
|
||||
+
|
||||
+typedef struct {
|
||||
+ char *name;
|
||||
+ enum resource_type type;
|
||||
+ void *dst;
|
||||
+} ResourcePref;
|
||||
+
|
||||
/* function declarations */
|
||||
static void applyrules(Client *c);
|
||||
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
|
||||
@@ -234,6 +248,8 @@ static int xerror(Display *dpy, XErrorEvent *ee);
|
||||
static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
||||
static void zoom(const Arg *arg);
|
||||
+static void load_xresources(void);
|
||||
+static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst);
|
||||
|
||||
/* variables */
|
||||
static const char broken[] = "broken";
|
||||
@@ -2127,6 +2143,60 @@ zoom(const Arg *arg)
|
||||
pop(c);
|
||||
}
|
||||
|
||||
+void
|
||||
+resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
|
||||
+{
|
||||
+ char *sdst = NULL;
|
||||
+ int *idst = NULL;
|
||||
+ float *fdst = NULL;
|
||||
+
|
||||
+ sdst = dst;
|
||||
+ idst = dst;
|
||||
+ fdst = dst;
|
||||
+
|
||||
+ char fullname[256];
|
||||
+ char *type;
|
||||
+ XrmValue ret;
|
||||
+
|
||||
+ snprintf(fullname, sizeof(fullname), "%s.%s", "dwm", name);
|
||||
+ fullname[sizeof(fullname) - 1] = '\0';
|
||||
+
|
||||
+ XrmGetResource(db, fullname, "*", &type, &ret);
|
||||
+ if (!(ret.addr == NULL || strncmp("String", type, 64)))
|
||||
+ {
|
||||
+ switch (rtype) {
|
||||
+ case STRING:
|
||||
+ strcpy(sdst, ret.addr);
|
||||
+ break;
|
||||
+ case INTEGER:
|
||||
+ *idst = strtoul(ret.addr, NULL, 10);
|
||||
+ break;
|
||||
+ case FLOAT:
|
||||
+ *fdst = strtof(ret.addr, NULL);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+load_xresources(void)
|
||||
+{
|
||||
+ Display *display;
|
||||
+ char *resm;
|
||||
+ XrmDatabase db;
|
||||
+ ResourcePref *p;
|
||||
+
|
||||
+ display = XOpenDisplay(NULL);
|
||||
+ resm = XResourceManagerString(display);
|
||||
+ if (!resm)
|
||||
+ return;
|
||||
+
|
||||
+ db = XrmGetStringDatabase(resm);
|
||||
+ for (p = resources; p < resources + LENGTH(resources); p++)
|
||||
+ resource_load(db, p->name, p->type, p->dst);
|
||||
+ XCloseDisplay(display);
|
||||
+}
|
||||
+
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
@@ -2139,6 +2209,8 @@ main(int argc, char *argv[])
|
||||
if (!(dpy = XOpenDisplay(NULL)))
|
||||
die("dwm: cannot open display");
|
||||
checkotherwm();
|
||||
+ XrmInitialize();
|
||||
+ load_xresources();
|
||||
setup();
|
||||
#ifdef __OpenBSD__
|
||||
if (pledge("stdio rpath proc exec", NULL) == -1)
|
||||
--
|
||||
2.26.2
|
||||
|
376
screen.c
376
screen.c
@ -1,376 +0,0 @@
|
||||
/* 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)
|
||||
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();
|
||||
}
|
85
tile.c
85
tile.c
@ -1,85 +0,0 @@
|
||||
/* 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), i++) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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
6
tile.h
@ -1,6 +0,0 @@
|
||||
/* 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 */
|
42
transient.c
Normal file
42
transient.c
Normal file
@ -0,0 +1,42 @@
|
||||
/* cc transient.c -o transient -lX11 */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
int main(void) {
|
||||
Display *d;
|
||||
Window r, f, t = None;
|
||||
XSizeHints h;
|
||||
XEvent e;
|
||||
|
||||
d = XOpenDisplay(NULL);
|
||||
if (!d)
|
||||
exit(1);
|
||||
r = DefaultRootWindow(d);
|
||||
|
||||
f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0);
|
||||
h.min_width = h.max_width = h.min_height = h.max_height = 400;
|
||||
h.flags = PMinSize | PMaxSize;
|
||||
XSetWMNormalHints(d, f, &h);
|
||||
XStoreName(d, f, "floating");
|
||||
XMapWindow(d, f);
|
||||
|
||||
XSelectInput(d, f, ExposureMask);
|
||||
while (1) {
|
||||
XNextEvent(d, &e);
|
||||
|
||||
if (t == None) {
|
||||
sleep(5);
|
||||
t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0);
|
||||
XSetTransientForHint(d, t, f);
|
||||
XStoreName(d, t, "transient");
|
||||
XMapWindow(d, t);
|
||||
XSelectInput(d, t, ExposureMask);
|
||||
}
|
||||
}
|
||||
|
||||
XCloseDisplay(d);
|
||||
exit(0);
|
||||
}
|
14
unfloat.c
Normal file
14
unfloat.c
Normal file
@ -0,0 +1,14 @@
|
||||
void
|
||||
unfloatvisible(const Arg *arg)
|
||||
{
|
||||
Client *c;
|
||||
|
||||
for (c = selmon->clients; c; c = c->next)
|
||||
if (ISVISIBLE(c) && c->isfloating)
|
||||
c->isfloating = c->isfixed;
|
||||
|
||||
if (arg && arg->v)
|
||||
setlayout(arg);
|
||||
else
|
||||
arrange(selmon);
|
||||
}
|
182
util.c
182
util.c
@ -1,52 +1,170 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
#include "dwm.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* extern */
|
||||
#include "util.h"
|
||||
|
||||
void *
|
||||
emallocz(unsigned int size) {
|
||||
void *res = calloc(1, size);
|
||||
ecalloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if(!res)
|
||||
eprint("fatal: could not malloc() %u bytes\n", size);
|
||||
return res;
|
||||
if (!(p = calloc(nmemb, size)))
|
||||
die("calloc:");
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
eprint(const char *errstr, ...) {
|
||||
die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, errstr);
|
||||
vfprintf(stderr, errstr, ap);
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
|
||||
fputc(' ', stderr);
|
||||
perror(NULL);
|
||||
} else {
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
void
|
||||
spawn(const char *arg) {
|
||||
static char *shell = NULL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(!shell && !(shell = getenv("SHELL")))
|
||||
shell = "/bin/sh";
|
||||
if(!arg)
|
||||
return;
|
||||
/* The double-fork construct avoids zombie processes and keeps the code
|
||||
* clean from stupid signal handlers. */
|
||||
if(fork() == 0) {
|
||||
if(fork() == 0) {
|
||||
if(dpy)
|
||||
close(ConnectionNumber(dpy));
|
||||
setsid();
|
||||
execl(shell, shell, "-c", arg, (char *)NULL);
|
||||
fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg);
|
||||
perror(" failed");
|
||||
int
|
||||
normalizepath(const char *path, char **normal)
|
||||
{
|
||||
size_t len = strlen(path);
|
||||
*normal = (char *)malloc((len + 1) * sizeof(char));
|
||||
const char *walk = path;
|
||||
const char *match;
|
||||
size_t newlen = 0;
|
||||
|
||||
while ((match = strchr(walk, '/'))) {
|
||||
// Copy everything between match and walk
|
||||
strncpy(*normal + newlen, walk, match - walk);
|
||||
newlen += match - walk;
|
||||
walk += match - walk;
|
||||
|
||||
// Skip all repeating slashes
|
||||
while (*walk == '/')
|
||||
walk++;
|
||||
|
||||
// If not last character in path
|
||||
if (walk != path + len)
|
||||
(*normal)[newlen++] = '/';
|
||||
}
|
||||
exit(0);
|
||||
|
||||
(*normal)[newlen++] = '\0';
|
||||
|
||||
// Copy remaining path
|
||||
strcat(*normal, walk);
|
||||
newlen += strlen(walk);
|
||||
|
||||
*normal = (char *)realloc(*normal, newlen * sizeof(char));
|
||||
|
||||
return 0;
|
||||
}
|
||||
wait(0);
|
||||
|
||||
int
|
||||
parentdir(const char *path, char **parent)
|
||||
{
|
||||
char *normal;
|
||||
char *walk;
|
||||
|
||||
normalizepath(path, &normal);
|
||||
|
||||
// Pointer to last '/'
|
||||
if (!(walk = strrchr(normal, '/'))) {
|
||||
free(normal);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get path up to last '/'
|
||||
size_t len = walk - normal;
|
||||
*parent = (char *)malloc((len + 1) * sizeof(char));
|
||||
|
||||
// Copy path up to last '/'
|
||||
strncpy(*parent, normal, len);
|
||||
// Add null char
|
||||
(*parent)[len] = '\0';
|
||||
|
||||
free(normal);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mkdirp(const char *path)
|
||||
{
|
||||
char *normal;
|
||||
char *walk;
|
||||
size_t normallen;
|
||||
|
||||
normalizepath(path, &normal);
|
||||
normallen = strlen(normal);
|
||||
walk = normal;
|
||||
|
||||
while (walk < normal + normallen + 1) {
|
||||
// Get length from walk to next /
|
||||
size_t n = strcspn(walk, "/");
|
||||
|
||||
// Skip path /
|
||||
if (n == 0) {
|
||||
walk++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Length of current path segment
|
||||
size_t curpathlen = walk - normal + n;
|
||||
char curpath[curpathlen + 1];
|
||||
struct stat s;
|
||||
|
||||
// Copy path segment to stat
|
||||
strncpy(curpath, normal, curpathlen);
|
||||
strcpy(curpath + curpathlen, "");
|
||||
int res = stat(curpath, &s);
|
||||
|
||||
if (res < 0) {
|
||||
if (errno == ENOENT) {
|
||||
DEBUG("Making directory %s\n", curpath);
|
||||
if (mkdir(curpath, 0700) < 0) {
|
||||
fprintf(stderr, "Failed to make directory %s\n", curpath);
|
||||
perror("");
|
||||
free(normal);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Error statting directory %s\n", curpath);
|
||||
perror("");
|
||||
free(normal);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Continue to next path segment
|
||||
walk += n;
|
||||
}
|
||||
|
||||
free(normal);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nullterminate(char **str, size_t *len)
|
||||
{
|
||||
if ((*str)[*len - 1] == '\0')
|
||||
return 0;
|
||||
|
||||
(*len)++;
|
||||
*str = (char*)realloc(*str, *len * sizeof(char));
|
||||
(*str)[*len - 1] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
18
util.h
Normal file
18
util.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG(...)
|
||||
#endif
|
||||
|
||||
void die(const char *fmt, ...);
|
||||
void *ecalloc(size_t nmemb, size_t size);
|
||||
int normalizepath(const char *path, char **normal);
|
||||
int mkdirp(const char *path);
|
||||
int parentdir(const char *path, char **parent);
|
||||
int nullterminate(char **str, size_t *len);
|
822
vanitygaps.c
Normal file
822
vanitygaps.c
Normal file
@ -0,0 +1,822 @@
|
||||
/* Key binding functions */
|
||||
static void defaultgaps(const Arg *arg);
|
||||
static void incrgaps(const Arg *arg);
|
||||
static void incrigaps(const Arg *arg);
|
||||
static void incrogaps(const Arg *arg);
|
||||
static void incrohgaps(const Arg *arg);
|
||||
static void incrovgaps(const Arg *arg);
|
||||
static void incrihgaps(const Arg *arg);
|
||||
static void incrivgaps(const Arg *arg);
|
||||
static void togglegaps(const Arg *arg);
|
||||
/* Layouts (delete the ones you do not need) */
|
||||
static void bstack(Monitor *m);
|
||||
static void bstackhoriz(Monitor *m);
|
||||
static void centeredmaster(Monitor *m);
|
||||
static void centeredfloatingmaster(Monitor *m);
|
||||
static void deck(Monitor *m);
|
||||
static void dwindle(Monitor *m);
|
||||
static void fibonacci(Monitor *m, int s);
|
||||
static void grid(Monitor *m);
|
||||
static void nrowgrid(Monitor *m);
|
||||
static void spiral(Monitor *m);
|
||||
static void tile(Monitor *m);
|
||||
/* Internals */
|
||||
static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc);
|
||||
static void getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr);
|
||||
static void setgaps(int oh, int ov, int ih, int iv);
|
||||
|
||||
/* Settings */
|
||||
#if !PERTAG_PATCH
|
||||
static int enablegaps = 1;
|
||||
#endif // PERTAG_PATCH
|
||||
|
||||
void
|
||||
setgaps(int oh, int ov, int ih, int iv)
|
||||
{
|
||||
if (oh < 0) oh = 0;
|
||||
if (ov < 0) ov = 0;
|
||||
if (ih < 0) ih = 0;
|
||||
if (iv < 0) iv = 0;
|
||||
|
||||
selmon->gappoh = oh;
|
||||
selmon->gappov = ov;
|
||||
selmon->gappih = ih;
|
||||
selmon->gappiv = iv;
|
||||
arrange(selmon);
|
||||
}
|
||||
|
||||
void
|
||||
togglegaps(const Arg *arg)
|
||||
{
|
||||
#if PERTAG_PATCH
|
||||
selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag];
|
||||
#else
|
||||
enablegaps = !enablegaps;
|
||||
#endif // PERTAG_PATCH
|
||||
arrange(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
defaultgaps(const Arg *arg)
|
||||
{
|
||||
setgaps(gappoh, gappov, gappih, gappiv);
|
||||
}
|
||||
|
||||
void
|
||||
incrgaps(const Arg *arg)
|
||||
{
|
||||
setgaps(
|
||||
selmon->gappoh + arg->i,
|
||||
selmon->gappov + arg->i,
|
||||
selmon->gappih + arg->i,
|
||||
selmon->gappiv + arg->i
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
incrigaps(const Arg *arg)
|
||||
{
|
||||
setgaps(
|
||||
selmon->gappoh,
|
||||
selmon->gappov,
|
||||
selmon->gappih + arg->i,
|
||||
selmon->gappiv + arg->i
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
incrogaps(const Arg *arg)
|
||||
{
|
||||
setgaps(
|
||||
selmon->gappoh + arg->i,
|
||||
selmon->gappov + arg->i,
|
||||
selmon->gappih,
|
||||
selmon->gappiv
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
incrohgaps(const Arg *arg)
|
||||
{
|
||||
setgaps(
|
||||
selmon->gappoh + arg->i,
|
||||
selmon->gappov,
|
||||
selmon->gappih,
|
||||
selmon->gappiv
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
incrovgaps(const Arg *arg)
|
||||
{
|
||||
setgaps(
|
||||
selmon->gappoh,
|
||||
selmon->gappov + arg->i,
|
||||
selmon->gappih,
|
||||
selmon->gappiv
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
incrihgaps(const Arg *arg)
|
||||
{
|
||||
setgaps(
|
||||
selmon->gappoh,
|
||||
selmon->gappov,
|
||||
selmon->gappih + arg->i,
|
||||
selmon->gappiv
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
incrivgaps(const Arg *arg)
|
||||
{
|
||||
setgaps(
|
||||
selmon->gappoh,
|
||||
selmon->gappov,
|
||||
selmon->gappih,
|
||||
selmon->gappiv + arg->i
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc)
|
||||
{
|
||||
unsigned int n, oe, ie;
|
||||
#if PERTAG_PATCH
|
||||
oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag];
|
||||
#else
|
||||
oe = ie = enablegaps;
|
||||
#endif // PERTAG_PATCH
|
||||
Client *c;
|
||||
|
||||
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
|
||||
if (smartgaps && n == 1) {
|
||||
oe = 0; // outer gaps disabled when only one client
|
||||
}
|
||||
|
||||
*oh = m->gappoh*oe; // outer horizontal gap
|
||||
*ov = m->gappov*oe; // outer vertical gap
|
||||
*ih = m->gappih*ie; // inner horizontal gap
|
||||
*iv = m->gappiv*ie; // inner vertical gap
|
||||
*nc = n; // number of clients
|
||||
}
|
||||
|
||||
void
|
||||
getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr)
|
||||
{
|
||||
unsigned int n;
|
||||
float mfacts = 0, sfacts = 0;
|
||||
int mtotal = 0, stotal = 0;
|
||||
Client *c;
|
||||
|
||||
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
|
||||
if (n < m->nmaster)
|
||||
mfacts += c->cfact;
|
||||
else
|
||||
sfacts += c->cfact;
|
||||
|
||||
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
|
||||
if (n < m->nmaster)
|
||||
mtotal += msize * (c->cfact / mfacts);
|
||||
else
|
||||
stotal += ssize * (c->cfact / sfacts);
|
||||
|
||||
*mf = mfacts; // total factor of master area
|
||||
*sf = sfacts; // total factor of stack area
|
||||
*mr = msize - mtotal; // the remainder (rest) of pixels after a cfacts master split
|
||||
*sr = ssize - stotal; // the remainder (rest) of pixels after a cfacts stack split
|
||||
}
|
||||
|
||||
/***
|
||||
* Layouts
|
||||
*/
|
||||
|
||||
/*
|
||||
* Bottomstack layout + gaps
|
||||
* https://dwm.suckless.org/patches/bottomstack/
|
||||
*/
|
||||
static void
|
||||
bstack(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int oh, ov, ih, iv;
|
||||
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
float mfacts, sfacts;
|
||||
int mrest, srest;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
sx = mx = m->wx + ov;
|
||||
sy = my = m->wy + oh;
|
||||
sh = mh = m->wh - 2*oh;
|
||||
mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
|
||||
sw = m->ww - 2*ov - iv * (n - m->nmaster - 1);
|
||||
|
||||
if (m->nmaster && n > m->nmaster) {
|
||||
sh = (mh - ih) * (1 - m->mfact);
|
||||
mh = mh - ih - sh;
|
||||
sx = mx;
|
||||
sy = my + mh + ih;
|
||||
}
|
||||
|
||||
getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
if (i < m->nmaster) {
|
||||
resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
mx += WIDTH(c) + iv;
|
||||
} else {
|
||||
resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
||||
sx += WIDTH(c) + iv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bstackhoriz(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int oh, ov, ih, iv;
|
||||
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
float mfacts, sfacts;
|
||||
int mrest, srest;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
sx = mx = m->wx + ov;
|
||||
sy = my = m->wy + oh;
|
||||
mh = m->wh - 2*oh;
|
||||
sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
|
||||
mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
|
||||
sw = m->ww - 2*ov;
|
||||
|
||||
if (m->nmaster && n > m->nmaster) {
|
||||
sh = (mh - ih) * (1 - m->mfact);
|
||||
mh = mh - ih - sh;
|
||||
sy = my + mh + ih;
|
||||
sh = m->wh - mh - 2*oh - ih * (n - m->nmaster);
|
||||
}
|
||||
|
||||
getfacts(m, mw, sh, &mfacts, &sfacts, &mrest, &srest);
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
if (i < m->nmaster) {
|
||||
resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
mx += WIDTH(c) + iv;
|
||||
} else {
|
||||
resize(c, sx, sy, sw - (2*c->bw), sh * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
|
||||
sy += HEIGHT(c) + ih;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Centred master layout + gaps
|
||||
* https://dwm.suckless.org/patches/centeredmaster/
|
||||
*/
|
||||
void
|
||||
centeredmaster(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int oh, ov, ih, iv;
|
||||
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
int lx = 0, ly = 0, lw = 0, lh = 0;
|
||||
int rx = 0, ry = 0, rw = 0, rh = 0;
|
||||
float mfacts = 0, lfacts = 0, rfacts = 0;
|
||||
int mtotal = 0, ltotal = 0, rtotal = 0;
|
||||
int mrest = 0, lrest = 0, rrest = 0;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
/* initialize areas */
|
||||
mx = m->wx + ov;
|
||||
my = m->wy + oh;
|
||||
mh = m->wh - 2*oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1);
|
||||
mw = m->ww - 2*ov;
|
||||
lh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - 1);
|
||||
rh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1));
|
||||
|
||||
if (m->nmaster && n > m->nmaster) {
|
||||
/* go mfact box in the center if more than nmaster clients */
|
||||
if (n - m->nmaster > 1) {
|
||||
/* ||<-S->|<---M--->|<-S->|| */
|
||||
mw = (m->ww - 2*ov - 2*iv) * m->mfact;
|
||||
lw = (m->ww - mw - 2*ov - 2*iv) / 2;
|
||||
rw = (m->ww - mw - 2*ov - 2*iv) - lw;
|
||||
mx += lw + iv;
|
||||
} else {
|
||||
/* ||<---M--->|<-S->|| */
|
||||
mw = (mw - iv) * m->mfact;
|
||||
lw = 0;
|
||||
rw = m->ww - mw - iv - 2*ov;
|
||||
}
|
||||
lx = m->wx + ov;
|
||||
ly = m->wy + oh;
|
||||
rx = mx + mw + iv;
|
||||
ry = m->wy + oh;
|
||||
}
|
||||
|
||||
/* calculate facts */
|
||||
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) {
|
||||
if (!m->nmaster || n < m->nmaster)
|
||||
mfacts += c->cfact;
|
||||
else if ((n - m->nmaster) % 2)
|
||||
lfacts += c->cfact; // total factor of left hand stack area
|
||||
else
|
||||
rfacts += c->cfact; // total factor of right hand stack area
|
||||
}
|
||||
|
||||
for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
|
||||
if (!m->nmaster || n < m->nmaster)
|
||||
mtotal += mh * (c->cfact / mfacts);
|
||||
else if ((n - m->nmaster) % 2)
|
||||
ltotal += lh * (c->cfact / lfacts);
|
||||
else
|
||||
rtotal += rh * (c->cfact / rfacts);
|
||||
|
||||
mrest = mh - mtotal;
|
||||
lrest = lh - ltotal;
|
||||
rrest = rh - rtotal;
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
if (!m->nmaster || i < m->nmaster) {
|
||||
/* nmaster clients are stacked vertically, in the center of the screen */
|
||||
resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
||||
my += HEIGHT(c) + ih;
|
||||
} else {
|
||||
/* stack clients are stacked vertically */
|
||||
if ((i - m->nmaster) % 2 ) {
|
||||
resize(c, lx, ly, lw - (2*c->bw), lh * (c->cfact / lfacts) + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0);
|
||||
ly += HEIGHT(c) + ih;
|
||||
} else {
|
||||
resize(c, rx, ry, rw - (2*c->bw), rh * (c->cfact / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0);
|
||||
ry += HEIGHT(c) + ih;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
centeredfloatingmaster(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
float mfacts, sfacts;
|
||||
float mivf = 1.0; // master inner vertical gap factor
|
||||
int oh, ov, ih, iv, mrest, srest;
|
||||
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
sx = mx = m->wx + ov;
|
||||
sy = my = m->wy + oh;
|
||||
sh = mh = m->wh - 2*oh;
|
||||
mw = m->ww - 2*ov - iv*(n - 1);
|
||||
sw = m->ww - 2*ov - iv*(n - m->nmaster - 1);
|
||||
|
||||
if (m->nmaster && n > m->nmaster) {
|
||||
mivf = 0.8;
|
||||
/* go mfact box in the center if more than nmaster clients */
|
||||
if (m->ww > m->wh) {
|
||||
mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->nmaster) - 1);
|
||||
mh = m->wh * 0.9;
|
||||
} else {
|
||||
mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->nmaster) - 1);
|
||||
mh = m->wh * m->mfact;
|
||||
}
|
||||
mx = m->wx + (m->ww - mw) / 2;
|
||||
my = m->wy + (m->wh - mh - 2*oh) / 2;
|
||||
|
||||
sx = m->wx + ov;
|
||||
sy = m->wy + oh;
|
||||
sh = m->wh - 2*oh;
|
||||
}
|
||||
|
||||
getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
if (i < m->nmaster) {
|
||||
/* nmaster clients are stacked horizontally, in the center of the screen */
|
||||
resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
mx += WIDTH(c) + iv*mivf;
|
||||
} else {
|
||||
/* stack clients are stacked horizontally */
|
||||
resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
||||
sx += WIDTH(c) + iv;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deck layout + gaps
|
||||
* https://dwm.suckless.org/patches/deck/
|
||||
*/
|
||||
void
|
||||
deck(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int oh, ov, ih, iv;
|
||||
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
float mfacts, sfacts;
|
||||
int mrest, srest;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
sx = mx = m->wx + ov;
|
||||
sy = my = m->wy + oh;
|
||||
sh = mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
|
||||
sw = mw = m->ww - 2*ov;
|
||||
|
||||
if (m->nmaster && n > m->nmaster) {
|
||||
sw = (mw - iv) * (1 - m->mfact);
|
||||
mw = mw - iv - sw;
|
||||
sx = mx + mw + iv;
|
||||
sh = m->wh - 2*oh;
|
||||
}
|
||||
|
||||
getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
|
||||
|
||||
if (n - m->nmaster > 0) /* override layout symbol */
|
||||
snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster);
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
if (i < m->nmaster) {
|
||||
resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
||||
my += HEIGHT(c) + ih;
|
||||
} else {
|
||||
resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fibonacci layout + gaps
|
||||
* https://dwm.suckless.org/patches/fibonacci/
|
||||
*/
|
||||
void
|
||||
fibonacci(Monitor *m, int s)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int nx, ny, nw, nh;
|
||||
int oh, ov, ih, iv;
|
||||
int nv, hrest = 0, wrest = 0, r = 1;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
nx = m->wx + ov;
|
||||
ny = m->wy + oh;
|
||||
nw = m->ww - 2*ov;
|
||||
nh = m->wh - 2*oh;
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
|
||||
if (r) {
|
||||
if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw))
|
||||
|| (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) {
|
||||
r = 0;
|
||||
}
|
||||
if (r && i < n - 1) {
|
||||
if (i % 2) {
|
||||
nv = (nh - ih) / 2;
|
||||
hrest = nh - 2*nv - ih;
|
||||
nh = nv;
|
||||
} else {
|
||||
nv = (nw - iv) / 2;
|
||||
wrest = nw - 2*nv - iv;
|
||||
nw = nv;
|
||||
}
|
||||
|
||||
if ((i % 4) == 2 && !s)
|
||||
nx += nw + iv;
|
||||
else if ((i % 4) == 3 && !s)
|
||||
ny += nh + ih;
|
||||
}
|
||||
|
||||
if ((i % 4) == 0) {
|
||||
if (s) {
|
||||
ny += nh + ih;
|
||||
nh += hrest;
|
||||
}
|
||||
else {
|
||||
nh -= hrest;
|
||||
ny -= nh + ih;
|
||||
}
|
||||
}
|
||||
else if ((i % 4) == 1) {
|
||||
nx += nw + iv;
|
||||
nw += wrest;
|
||||
}
|
||||
else if ((i % 4) == 2) {
|
||||
ny += nh + ih;
|
||||
nh += hrest;
|
||||
if (i < n - 1)
|
||||
nw += wrest;
|
||||
}
|
||||
else if ((i % 4) == 3) {
|
||||
if (s) {
|
||||
nx += nw + iv;
|
||||
nw -= wrest;
|
||||
} else {
|
||||
nw -= wrest;
|
||||
nx -= nw + iv;
|
||||
nh += hrest;
|
||||
}
|
||||
}
|
||||
if (i == 0) {
|
||||
if (n != 1) {
|
||||
nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact);
|
||||
wrest = 0;
|
||||
}
|
||||
ny = m->wy + oh;
|
||||
}
|
||||
else if (i == 1)
|
||||
nw = m->ww - nw - iv - 2*ov;
|
||||
i++;
|
||||
}
|
||||
|
||||
resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dwindle(Monitor *m)
|
||||
{
|
||||
fibonacci(m, 1);
|
||||
}
|
||||
|
||||
void
|
||||
spiral(Monitor *m)
|
||||
{
|
||||
fibonacci(m, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Gappless grid layout + gaps (ironically)
|
||||
* https://dwm.suckless.org/patches/gaplessgrid/
|
||||
*/
|
||||
void
|
||||
gaplessgrid(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters
|
||||
int oh, ov, ih, iv;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
/* grid dimensions */
|
||||
for (cols = 0; cols <= n/2; cols++)
|
||||
if (cols*cols >= n)
|
||||
break;
|
||||
if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
|
||||
cols = 2;
|
||||
rows = n/cols;
|
||||
cn = rn = 0; // reset column no, row no, client count
|
||||
|
||||
ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
|
||||
cw = (m->ww - 2*ov - iv * (cols - 1)) / cols;
|
||||
rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
||||
crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
|
||||
x = m->wx + ov;
|
||||
y = m->wy + oh;
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) {
|
||||
if (i/rows + 1 > cols - n%cols) {
|
||||
rows = n/cols + 1;
|
||||
ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
|
||||
rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
||||
}
|
||||
resize(c,
|
||||
x,
|
||||
y + rn*(ch + ih) + MIN(rn, rrest),
|
||||
cw + (cn < crest ? 1 : 0) - 2*c->bw,
|
||||
ch + (rn < rrest ? 1 : 0) - 2*c->bw,
|
||||
0);
|
||||
rn++;
|
||||
if (rn >= rows) {
|
||||
rn = 0;
|
||||
x += cw + ih + (cn < crest ? 1 : 0);
|
||||
cn++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gridmode layout + gaps
|
||||
* https://dwm.suckless.org/patches/gridmode/
|
||||
*/
|
||||
void
|
||||
grid(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows;
|
||||
int oh, ov, ih, iv;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
|
||||
/* grid dimensions */
|
||||
for (rows = 0; rows <= n/2; rows++)
|
||||
if (rows*rows >= n)
|
||||
break;
|
||||
cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
|
||||
|
||||
/* window geoms (cell height/width) */
|
||||
ch = (m->wh - 2*oh - ih * (rows - 1)) / (rows ? rows : 1);
|
||||
cw = (m->ww - 2*ov - iv * (cols - 1)) / (cols ? cols : 1);
|
||||
chrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
||||
cwrest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
|
||||
cc = i / rows;
|
||||
cr = i % rows;
|
||||
cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest);
|
||||
cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest);
|
||||
resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Horizontal grid layout + gaps
|
||||
* https://dwm.suckless.org/patches/horizgrid/
|
||||
*/
|
||||
void
|
||||
horizgrid(Monitor *m) {
|
||||
Client *c;
|
||||
unsigned int n, i;
|
||||
int oh, ov, ih, iv;
|
||||
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
int ntop, nbottom = 1;
|
||||
float mfacts = 0, sfacts = 0;
|
||||
int mrest, srest, mtotal = 0, stotal = 0;
|
||||
|
||||
/* Count windows */
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
if (n <= 2)
|
||||
ntop = n;
|
||||
else {
|
||||
ntop = n / 2;
|
||||
nbottom = n - ntop;
|
||||
}
|
||||
sx = mx = m->wx + ov;
|
||||
sy = my = m->wy + oh;
|
||||
sh = mh = m->wh - 2*oh;
|
||||
sw = mw = m->ww - 2*ov;
|
||||
|
||||
if (n > ntop) {
|
||||
sh = (mh - ih) / 2;
|
||||
mh = mh - ih - sh;
|
||||
sy = my + mh + ih;
|
||||
mw = m->ww - 2*ov - iv * (ntop - 1);
|
||||
sw = m->ww - 2*ov - iv * (nbottom - 1);
|
||||
}
|
||||
|
||||
/* calculate facts */
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
if (i < ntop)
|
||||
mfacts += c->cfact;
|
||||
else
|
||||
sfacts += c->cfact;
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
if (i < ntop)
|
||||
mtotal += mh * (c->cfact / mfacts);
|
||||
else
|
||||
stotal += sw * (c->cfact / sfacts);
|
||||
|
||||
mrest = mh - mtotal;
|
||||
srest = sw - stotal;
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
if (i < ntop) {
|
||||
resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
||||
mx += WIDTH(c) + iv;
|
||||
} else {
|
||||
resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
||||
sx += WIDTH(c) + iv;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nrowgrid layout + gaps
|
||||
* https://dwm.suckless.org/patches/nrowgrid/
|
||||
*/
|
||||
void
|
||||
nrowgrid(Monitor *m)
|
||||
{
|
||||
unsigned int n;
|
||||
int ri = 0, ci = 0; /* counters */
|
||||
int oh, ov, ih, iv; /* vanitygap settings */
|
||||
unsigned int cx, cy, cw, ch; /* client geometry */
|
||||
unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */
|
||||
unsigned int cols, rows = m->nmaster + 1;
|
||||
Client *c;
|
||||
|
||||
/* count clients */
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
|
||||
/* nothing to do here */
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
/* force 2 clients to always split vertically */
|
||||
if (FORCE_VSPLIT && n == 2)
|
||||
rows = 1;
|
||||
|
||||
/* never allow empty rows */
|
||||
if (n < rows)
|
||||
rows = n;
|
||||
|
||||
/* define first row */
|
||||
cols = n / rows;
|
||||
uc = cols;
|
||||
cy = m->wy + oh;
|
||||
ch = (m->wh - 2*oh - ih*(rows - 1)) / rows;
|
||||
uh = ch;
|
||||
|
||||
for (c = nexttiled(m->clients); c; c = nexttiled(c->next), ci++) {
|
||||
if (ci == cols) {
|
||||
uw = 0;
|
||||
ci = 0;
|
||||
ri++;
|
||||
|
||||
/* next row */
|
||||
cols = (n - uc) / (rows - ri);
|
||||
uc += cols;
|
||||
cy = m->wy + oh + uh + ih;
|
||||
uh += ch + ih;
|
||||
}
|
||||
|
||||
cx = m->wx + ov + uw;
|
||||
cw = (m->ww - 2*ov - uw) / (cols - ci);
|
||||
uw += cw + iv;
|
||||
|
||||
resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Default tile layout + gaps
|
||||
*/
|
||||
static void
|
||||
tile(Monitor *m)
|
||||
{
|
||||
unsigned int i, n;
|
||||
int oh, ov, ih, iv;
|
||||
int mx = 0, my = 0, mh = 0, mw = 0;
|
||||
int sx = 0, sy = 0, sh = 0, sw = 0;
|
||||
float mfacts, sfacts;
|
||||
int mrest, srest;
|
||||
Client *c;
|
||||
|
||||
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
sx = mx = m->wx + ov;
|
||||
sy = my = m->wy + oh;
|
||||
mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
|
||||
sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
|
||||
sw = mw = m->ww - 2*ov;
|
||||
|
||||
if (m->nmaster && n > m->nmaster) {
|
||||
sw = (mw - iv) * (1 - m->mfact);
|
||||
mw = mw - iv - sw;
|
||||
sx = mx + mw + iv;
|
||||
}
|
||||
|
||||
getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
|
||||
|
||||
for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
|
||||
if (i < m->nmaster) {
|
||||
resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
||||
my += HEIGHT(c) + ih;
|
||||
} else {
|
||||
resize(c, sx, sy, sw - (2*c->bw), sh * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
|
||||
sy += HEIGHT(c) + ih;
|
||||
}
|
||||
}
|
351
yajl_dumps.c
Normal file
351
yajl_dumps.c
Normal file
@ -0,0 +1,351 @@
|
||||
#include "yajl_dumps.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int
|
||||
dump_tag(yajl_gen gen, const char *name, const int tag_mask)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("bit_mask"); YINT(tag_mask);
|
||||
YSTR("name"); YSTR(name);
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_tags(yajl_gen gen, const char *tags[], int tags_len)
|
||||
{
|
||||
// clang-format off
|
||||
YARR(
|
||||
for (int i = 0; i < tags_len; i++)
|
||||
dump_tag(gen, tags[i], 1 << i);
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_client(yajl_gen gen, Client *c)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("name"); YSTR(c->name);
|
||||
YSTR("tags"); YINT(c->tags);
|
||||
YSTR("window_id"); YINT(c->win);
|
||||
YSTR("monitor_number"); YINT(c->mon->num);
|
||||
|
||||
YSTR("geometry"); YMAP(
|
||||
YSTR("current"); YMAP (
|
||||
YSTR("x"); YINT(c->x);
|
||||
YSTR("y"); YINT(c->y);
|
||||
YSTR("width"); YINT(c->w);
|
||||
YSTR("height"); YINT(c->h);
|
||||
)
|
||||
YSTR("old"); YMAP(
|
||||
YSTR("x"); YINT(c->oldx);
|
||||
YSTR("y"); YINT(c->oldy);
|
||||
YSTR("width"); YINT(c->oldw);
|
||||
YSTR("height"); YINT(c->oldh);
|
||||
)
|
||||
)
|
||||
|
||||
YSTR("size_hints"); YMAP(
|
||||
YSTR("base"); YMAP(
|
||||
YSTR("width"); YINT(c->basew);
|
||||
YSTR("height"); YINT(c->baseh);
|
||||
)
|
||||
YSTR("step"); YMAP(
|
||||
YSTR("width"); YINT(c->incw);
|
||||
YSTR("height"); YINT(c->inch);
|
||||
)
|
||||
YSTR("max"); YMAP(
|
||||
YSTR("width"); YINT(c->maxw);
|
||||
YSTR("height"); YINT(c->maxh);
|
||||
)
|
||||
YSTR("min"); YMAP(
|
||||
YSTR("width"); YINT(c->minw);
|
||||
YSTR("height"); YINT(c->minh);
|
||||
)
|
||||
YSTR("aspect_ratio"); YMAP(
|
||||
YSTR("min"); YDOUBLE(c->mina);
|
||||
YSTR("max"); YDOUBLE(c->maxa);
|
||||
)
|
||||
)
|
||||
|
||||
YSTR("border_width"); YMAP(
|
||||
YSTR("current"); YINT(c->bw);
|
||||
YSTR("old"); YINT(c->oldbw);
|
||||
)
|
||||
|
||||
YSTR("states"); YMAP(
|
||||
YSTR("is_fixed"); YBOOL(c->isfixed);
|
||||
YSTR("is_floating"); YBOOL(c->isfloating);
|
||||
YSTR("is_urgent"); YBOOL(c->isurgent);
|
||||
YSTR("never_focus"); YBOOL(c->neverfocus);
|
||||
YSTR("old_state"); YBOOL(c->oldstate);
|
||||
YSTR("is_fullscreen"); YBOOL(c->isfullscreen);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_monitor(yajl_gen gen, Monitor *mon, int is_selected)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("master_factor"); YDOUBLE(mon->mfact);
|
||||
YSTR("num_master"); YINT(mon->nmaster);
|
||||
YSTR("num"); YINT(mon->num);
|
||||
YSTR("is_selected"); YBOOL(is_selected);
|
||||
|
||||
YSTR("monitor_geometry"); YMAP(
|
||||
YSTR("x"); YINT(mon->mx);
|
||||
YSTR("y"); YINT(mon->my);
|
||||
YSTR("width"); YINT(mon->mw);
|
||||
YSTR("height"); YINT(mon->mh);
|
||||
)
|
||||
|
||||
YSTR("window_geometry"); YMAP(
|
||||
YSTR("x"); YINT(mon->wx);
|
||||
YSTR("y"); YINT(mon->wy);
|
||||
YSTR("width"); YINT(mon->ww);
|
||||
YSTR("height"); YINT(mon->wh);
|
||||
)
|
||||
|
||||
YSTR("tagset"); YMAP(
|
||||
YSTR("current"); YINT(mon->tagset[mon->seltags]);
|
||||
YSTR("old"); YINT(mon->tagset[mon->seltags ^ 1]);
|
||||
)
|
||||
|
||||
YSTR("tag_state"); dump_tag_state(gen, mon->tagstate);
|
||||
|
||||
YSTR("clients"); YMAP(
|
||||
YSTR("selected"); YINT(mon->sel ? mon->sel->win : 0);
|
||||
YSTR("stack"); YARR(
|
||||
for (Client* c = mon->stack; c; c = c->snext)
|
||||
YINT(c->win);
|
||||
)
|
||||
YSTR("all"); YARR(
|
||||
for (Client* c = mon->clients; c; c = c->next)
|
||||
YINT(c->win);
|
||||
)
|
||||
)
|
||||
|
||||
YSTR("layout"); YMAP(
|
||||
YSTR("symbol"); YMAP(
|
||||
YSTR("current"); YSTR(mon->ltsymbol);
|
||||
YSTR("old"); YSTR(mon->lastltsymbol);
|
||||
)
|
||||
YSTR("address"); YMAP(
|
||||
YSTR("current"); YINT((uintptr_t)mon->lt[mon->sellt]);
|
||||
YSTR("old"); YINT((uintptr_t)mon->lt[mon->sellt ^ 1]);
|
||||
)
|
||||
)
|
||||
|
||||
YSTR("bar"); YMAP(
|
||||
YSTR("y"); YINT(mon->by);
|
||||
YSTR("is_shown"); YBOOL(mon->showbar);
|
||||
YSTR("is_top"); YBOOL(mon->topbar);
|
||||
YSTR("window_id"); YINT(mon->barwin);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_monitors(yajl_gen gen, Monitor *mons, Monitor *selmon)
|
||||
{
|
||||
// clang-format off
|
||||
YARR(
|
||||
for (Monitor *mon = mons; mon; mon = mon->next) {
|
||||
if (mon == selmon)
|
||||
dump_monitor(gen, mon, 1);
|
||||
else
|
||||
dump_monitor(gen, mon, 0);
|
||||
}
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_layouts(yajl_gen gen, const Layout layouts[], const int layouts_len)
|
||||
{
|
||||
// clang-format off
|
||||
YARR(
|
||||
for (int i = 0; i < layouts_len; i++) {
|
||||
YMAP(
|
||||
// Check for a NULL pointer. The cycle layouts patch adds an entry at
|
||||
// the end of the layouts array with a NULL pointer for the symbol
|
||||
YSTR("symbol"); YSTR((layouts[i].symbol ? layouts[i].symbol : ""));
|
||||
YSTR("address"); YINT((uintptr_t)(layouts + i));
|
||||
)
|
||||
}
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_tag_state(yajl_gen gen, TagState state)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("selected"); YINT(state.selected);
|
||||
YSTR("occupied"); YINT(state.occupied);
|
||||
YSTR("urgent"); YINT(state.urgent);
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_tag_event(yajl_gen gen, int mon_num, TagState old_state,
|
||||
TagState new_state)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("tag_change_event"); YMAP(
|
||||
YSTR("monitor_number"); YINT(mon_num);
|
||||
YSTR("old_state"); dump_tag_state(gen, old_state);
|
||||
YSTR("new_state"); dump_tag_state(gen, new_state);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_client_focus_change_event(yajl_gen gen, Client *old_client,
|
||||
Client *new_client, int mon_num)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("client_focus_change_event"); YMAP(
|
||||
YSTR("monitor_number"); YINT(mon_num);
|
||||
YSTR("old_win_id"); old_client == NULL ? YNULL() : YINT(old_client->win);
|
||||
YSTR("new_win_id"); new_client == NULL ? YNULL() : YINT(new_client->win);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_layout_change_event(yajl_gen gen, const int mon_num,
|
||||
const char *old_symbol, const Layout *old_layout,
|
||||
const char *new_symbol, const Layout *new_layout)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("layout_change_event"); YMAP(
|
||||
YSTR("monitor_number"); YINT(mon_num);
|
||||
YSTR("old_symbol"); YSTR(old_symbol);
|
||||
YSTR("old_address"); YINT((uintptr_t)old_layout);
|
||||
YSTR("new_symbol"); YSTR(new_symbol);
|
||||
YSTR("new_address"); YINT((uintptr_t)new_layout);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num,
|
||||
const int new_mon_num)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("monitor_focus_change_event"); YMAP(
|
||||
YSTR("old_monitor_number"); YINT(last_mon_num);
|
||||
YSTR("new_monitor_number"); YINT(new_mon_num);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_focused_title_change_event(yajl_gen gen, const int mon_num,
|
||||
const Window client_id, const char *old_name,
|
||||
const char *new_name)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("focused_title_change_event"); YMAP(
|
||||
YSTR("monitor_number"); YINT(mon_num);
|
||||
YSTR("client_window_id"); YINT(client_id);
|
||||
YSTR("old_name"); YSTR(old_name);
|
||||
YSTR("new_name"); YSTR(new_name);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_client_state(yajl_gen gen, const ClientState *state)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("old_state"); YBOOL(state->oldstate);
|
||||
YSTR("is_fixed"); YBOOL(state->isfixed);
|
||||
YSTR("is_floating"); YBOOL(state->isfloating);
|
||||
YSTR("is_fullscreen"); YBOOL(state->isfullscreen);
|
||||
YSTR("is_urgent"); YBOOL(state->isurgent);
|
||||
YSTR("never_focus"); YBOOL(state->neverfocus);
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_focused_state_change_event(yajl_gen gen, const int mon_num,
|
||||
const Window client_id,
|
||||
const ClientState *old_state,
|
||||
const ClientState *new_state)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("focused_state_change_event"); YMAP(
|
||||
YSTR("monitor_number"); YINT(mon_num);
|
||||
YSTR("client_window_id"); YINT(client_id);
|
||||
YSTR("old_state"); dump_client_state(gen, old_state);
|
||||
YSTR("new_state"); dump_client_state(gen, new_state);
|
||||
)
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dump_error_message(yajl_gen gen, const char *reason)
|
||||
{
|
||||
// clang-format off
|
||||
YMAP(
|
||||
YSTR("result"); YSTR("error");
|
||||
YSTR("reason"); YSTR(reason);
|
||||
)
|
||||
// clang-format on
|
||||
|
||||
return 0;
|
||||
}
|
65
yajl_dumps.h
Normal file
65
yajl_dumps.h
Normal file
@ -0,0 +1,65 @@
|
||||
#ifndef YAJL_DUMPS_H_
|
||||
#define YAJL_DUMPS_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <yajl/yajl_gen.h>
|
||||
|
||||
#define YSTR(str) yajl_gen_string(gen, (unsigned char *)str, strlen(str))
|
||||
#define YINT(num) yajl_gen_integer(gen, num)
|
||||
#define YDOUBLE(num) yajl_gen_double(gen, num)
|
||||
#define YBOOL(v) yajl_gen_bool(gen, v)
|
||||
#define YNULL() yajl_gen_null(gen)
|
||||
#define YARR(body) \
|
||||
{ \
|
||||
yajl_gen_array_open(gen); \
|
||||
body; \
|
||||
yajl_gen_array_close(gen); \
|
||||
}
|
||||
#define YMAP(body) \
|
||||
{ \
|
||||
yajl_gen_map_open(gen); \
|
||||
body; \
|
||||
yajl_gen_map_close(gen); \
|
||||
}
|
||||
|
||||
int dump_tag(yajl_gen gen, const char *name, const int tag_mask);
|
||||
|
||||
int dump_tags(yajl_gen gen, const char *tags[], int tags_len);
|
||||
|
||||
int dump_client(yajl_gen gen, Client *c);
|
||||
|
||||
int dump_monitor(yajl_gen gen, Monitor *mon, int is_selected);
|
||||
|
||||
int dump_monitors(yajl_gen gen, Monitor *mons, Monitor *selmon);
|
||||
|
||||
int dump_layouts(yajl_gen gen, const Layout layouts[], const int layouts_len);
|
||||
|
||||
int dump_tag_state(yajl_gen gen, TagState state);
|
||||
|
||||
int dump_tag_event(yajl_gen gen, int mon_num, TagState old_state,
|
||||
TagState new_state);
|
||||
|
||||
int dump_client_focus_change_event(yajl_gen gen, Client *old_client,
|
||||
Client *new_client, int mon_num);
|
||||
|
||||
int dump_layout_change_event(yajl_gen gen, const int mon_num,
|
||||
const char *old_symbol, const Layout *old_layout,
|
||||
const char *new_symbol, const Layout *new_layout);
|
||||
|
||||
int dump_monitor_focus_change_event(yajl_gen gen, const int last_mon_num,
|
||||
const int new_mon_num);
|
||||
|
||||
int dump_focused_title_change_event(yajl_gen gen, const int mon_num,
|
||||
const Window client_id,
|
||||
const char *old_name, const char *new_name);
|
||||
|
||||
int dump_client_state(yajl_gen gen, const ClientState *state);
|
||||
|
||||
int dump_focused_state_change_event(yajl_gen gen, const int mon_num,
|
||||
const Window client_id,
|
||||
const ClientState *old_state,
|
||||
const ClientState *new_state);
|
||||
|
||||
int dump_error_message(yajl_gen gen, const char *reason);
|
||||
|
||||
#endif // YAJL_DUMPS_H_
|
Reference in New Issue
Block a user