Compare commits
1482 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 | ||
|
a92cf496c1 | ||
|
cc7970010b | ||
|
67a1141f44 | ||
|
8be3f3ec9e | ||
|
5762e92994 | ||
|
36672d0401 | ||
|
b18e684015 | ||
|
fc109ea8f7 | ||
|
b975c47280 | ||
|
47765f7286 | ||
|
96d7fe16ea | ||
|
78d1a22d4e | ||
|
0c60620410 | ||
|
50be6c8b67 | ||
|
7d156dee1e | ||
|
55d8dda9f4 | ||
|
86953bd682 | ||
|
a923298d35 | ||
|
04dec4c943 | ||
|
e40448fd63 | ||
|
10bc0ce912 | ||
|
e8792d95a1 | ||
|
feec92df84 | ||
|
10d13f01ff | ||
|
8fcc4ff0ae | ||
|
f2512243f4 | ||
|
b32cd4454b | ||
|
9e56e1ded6 | ||
|
e4ad320599 | ||
|
a200c39635 | ||
|
77044e8765 | ||
|
2feb3afe78 | ||
|
0937cc78bf | ||
|
f6e41b0bc3 | ||
|
2c6087e3d2 | ||
|
2d81b78b85 | ||
|
b5eea45a31 | ||
|
aa53e39ec0 | ||
|
4216bf801f | ||
|
2cd1609770 | ||
|
85c9ebf2fc | ||
|
796925089c | ||
|
da91dfc948 | ||
|
4135e34dfa | ||
|
846128a498 | ||
|
e461e60997 | ||
|
28c10330bd | ||
|
0d40590c2c | ||
|
8fda28be35 | ||
|
a54cf2ecef | ||
|
4b9337a01e | ||
|
154497541d | ||
|
e0cfe07648 | ||
|
82be289985 | ||
|
f2190c8fc2 | ||
|
c31648d15d | ||
|
52250e7c1e | ||
|
51a94a2f14 | ||
|
c95bf3db9d | ||
|
4bf3b01953 | ||
|
ff957d1eac | ||
|
83aa110c6f | ||
|
5a1a2edf0e | ||
|
b3419f49a3 | ||
|
141beb2704 | ||
|
4e49d5a0ad | ||
|
2c6be7239f | ||
|
d934296476 | ||
|
39ae286861 | ||
|
59e65d1709 | ||
|
9fdd2cd1a9 | ||
|
e1deda9e04 | ||
|
199a601611 | ||
|
492c6f10fc | ||
|
caa7ab5362 | ||
|
f3e672efd8 | ||
|
02d5dddc00 | ||
|
c789941bba | ||
|
e45b3ced67 | ||
|
5a9af492ae | ||
|
32563abe86 | ||
|
70c7b432ea | ||
|
69dfcaa317 | ||
|
6ee8e3e93b | ||
|
8439369db9 | ||
|
81658eaab3 | ||
|
81aebf8cae | ||
|
fa32f02a43 | ||
|
598e22907e | ||
|
1e826ddd3e | ||
|
a967d7f664 | ||
|
ce450c5bf1 | ||
|
8f5f7a5b5a | ||
|
5ad2828c57 | ||
|
b896b58d6d | ||
|
fef6c5c66b | ||
|
37e062b0ed | ||
|
cf58091736 | ||
|
2aef8b9b4c | ||
|
d96307cbe4 | ||
|
124866e269 | ||
|
ab3d6a7dfe | ||
|
c67dbb28e4 | ||
|
b8bccb4ac5 | ||
|
b6b2f584ec | ||
|
f7bdb39d9e | ||
|
ecd9c3e222 | ||
|
216099d072 | ||
|
fc2e3eae20 | ||
|
f9e7a33019 | ||
|
7c9fa2566f | ||
|
22399a3bc0 | ||
|
ad2508f957 | ||
|
b078599833 | ||
|
1e80207876 | ||
|
464fc2cd18 | ||
|
be8d6d40f6 | ||
|
f0c2353393 | ||
|
a730213c3b | ||
|
399993c6b5 | ||
|
4d318060a2 | ||
|
540d5eed46 | ||
|
7d071ce2bd | ||
|
93aeaa53c9 | ||
|
06f9f346e6 | ||
|
5c48012ad2 | ||
|
a686c9ccd2 | ||
|
9ca5c3b108 | ||
|
bab5b1178d | ||
|
ee8fb0c6e4 | ||
|
0d9d3e79e9 | ||
|
12280f0253 | ||
|
a58731e835 | ||
|
1df45593ed | ||
|
2122e39ce1 | ||
|
e70139428a | ||
|
3d1d75a224 | ||
|
35f08f4231 | ||
|
0ea0343a63 | ||
|
338c083858 | ||
|
671442e89d | ||
|
8d111632f5 | ||
|
fe5acb939a | ||
|
cac492b0e9 | ||
|
ef9b3e173c | ||
|
5a13632afb | ||
|
587100873a | ||
|
27b0595af7 | ||
|
12d5a26fd2 | ||
|
89b7f1503e | ||
|
5711609203 | ||
|
825b7c3eb1 | ||
|
ba96131af0 | ||
|
2c477cf661 | ||
|
986ca73074 | ||
|
288098893c | ||
|
cb9607c284 | ||
|
4bd4f421d3 | ||
|
84432e6b36 | ||
|
1a25414ace | ||
|
3171371498 | ||
|
92105e7862 | ||
|
6ee9f13457 | ||
|
352cae4380 | ||
|
b3b58c08e4 | ||
|
204f0a340d | ||
|
78666b99b8 | ||
|
0bdcf75e25 | ||
|
f1009285d8 | ||
|
f76b3a4685 | ||
|
84ae6e12eb | ||
|
784659565a | ||
|
7ae0c198b3 | ||
|
dc6623728d | ||
|
7541f1ad49 | ||
|
74cbbe5f35 | ||
|
52f0b9e2e3 | ||
|
29c26b88e7 | ||
|
f196b71e4d | ||
|
ab83872134 | ||
|
ad4962c7eb | ||
|
d180ba418c | ||
|
138b7fbd05 | ||
|
e7508783e8 | ||
|
f4d15b1fec | ||
|
355beb53f0 | ||
|
8012fcf333 | ||
|
6bc4556ebd | ||
|
879241c05c | ||
|
3794c62945 | ||
|
5a03daf47f | ||
|
6d5f67a092 | ||
|
cee56d3863 | ||
|
7c4da24465 | ||
|
cdbc84b9a8 | ||
|
b2f895166a | ||
|
ebe68f650a | ||
|
df9fd28f9a | ||
|
e9c49ddd7a | ||
|
f8415019d4 | ||
|
238dd5d2b1 | ||
|
64871a7045 | ||
|
2e95bc0413 | ||
|
4cdbd523e5 | ||
|
b3d7e07f18 | ||
|
30af19d442 | ||
|
5d9146ff37 | ||
|
5cc27f1b3c | ||
|
39ed54a468 | ||
|
b61f91361c | ||
|
3167373512 | ||
|
4cff744438 | ||
|
c3527bea57 | ||
|
de6695792a | ||
|
6e22ccf7b1 | ||
|
8a5f002c41 | ||
|
3ce8c9f338 | ||
|
0d095ae2ff | ||
|
2d7f59424c | ||
|
e256afe31e | ||
|
64cfebc5e7 | ||
|
7a095d0ce2 | ||
|
5052c538d9 | ||
|
22d8c6fd18 | ||
|
71857b87ee | ||
|
6ba400ee0f | ||
|
35e65ea640 | ||
|
d0d986dd0e | ||
|
9685e7dbc2 | ||
|
37f39afb8e | ||
|
dc9f62f393 | ||
|
7055315725 | ||
|
fd995dac78 | ||
|
e5765cdd84 | ||
|
8d0e58f80b | ||
|
8fcd1bfda8 | ||
|
e39e697998 | ||
|
d2dd58eabd | ||
|
c6fc6b173d | ||
|
4590d7877c | ||
|
f577fe4e27 | ||
|
9ed5de00b6 | ||
|
28ffff801b | ||
|
44ef3f5a07 | ||
|
dafbd0dcb0 | ||
|
2ddc78720a | ||
|
7ece30ebc0 | ||
|
3d48f33025 | ||
|
19fd903d40 | ||
|
5732e471ae | ||
|
042297b27b | ||
|
a5cb80b86c | ||
|
7e98db251e | ||
|
bced9077f9 | ||
|
82fed986f9 | ||
|
2c1db7ed35 | ||
|
ea4827a578 | ||
|
55be4d6137 | ||
|
1f18466409 | ||
|
b65a1e3379 | ||
|
87836d79ef | ||
|
c8a12a0852 | ||
|
71b84c2114 | ||
|
edb2660a2e | ||
|
17ec726b49 | ||
|
373b11de11 | ||
|
04a2b74529 | ||
|
fcd98308ba | ||
|
b233089815 | ||
|
201c56f6d3 | ||
|
1e051d71f5 | ||
|
ddc79603f9 | ||
|
dee5ea2335 | ||
|
b1c9f5f144 | ||
|
a542bdf658 | ||
|
96e1b25c8c | ||
|
caf5a16271 | ||
|
936e11fd54 | ||
|
9715ba82aa | ||
|
3c35b90dd3 | ||
|
1d63030665 | ||
|
6a5b41203e | ||
|
fbd310972d | ||
|
3059c9c507 | ||
|
3b18f17d4d | ||
|
72faa1919e | ||
|
f8181f64e2 | ||
|
0045ad87df | ||
|
ceea528eff | ||
|
6c5dc7017c | ||
|
ae0b4fdd92 | ||
|
b3cea4d388 | ||
|
d296081321 | ||
|
177ed7e5de | ||
|
f679125206 | ||
|
58beead14d | ||
|
e1811c37ca | ||
|
a24a6701c8 | ||
|
d108cfa7fc | ||
|
92cb5ebb7c | ||
|
653826572d | ||
|
5a5851bac2 | ||
|
1d4a24dae0 | ||
|
a768ea93fd | ||
|
c95fe6e24b | ||
|
c75168186b | ||
|
3a96c9a8d5 | ||
|
1617b95598 | ||
|
726ae5bf6d | ||
|
3e11b38349 | ||
|
16ed879524 | ||
|
20d7b5d058 | ||
|
11a08b9cfc | ||
|
c2b753d917 | ||
|
6c767072a3 | ||
|
e9cfae7aba | ||
|
7ac0de8350 | ||
|
0b7c0f10ee | ||
|
51f6405b0d | ||
|
6096f8a113 | ||
|
d939f301fa | ||
|
8c4623da80 | ||
|
0faaba04a5 | ||
|
ec7a5ffff1 | ||
|
98afb7b9d0 | ||
|
06bae9dfb7 | ||
|
0b80d1842d | ||
|
d7ec23a5db | ||
|
2cf8ef9520 | ||
|
184471b4bb | ||
|
21898c6049 | ||
|
6a9300e815 | ||
|
ac24f132db | ||
|
cb4aa5bc35 | ||
|
beac539f31 | ||
|
b5d297f02f | ||
|
9056d7ea88 | ||
|
ebd17e4827 | ||
|
7e59c89250 | ||
|
9e4e4d9022 | ||
|
71fd06f843 | ||
|
58e6866d86 | ||
|
c7da124149 | ||
|
21bd90d7d3 | ||
|
c8f96b5b4c | ||
|
ded60365d4 | ||
|
629647dfee | ||
|
4ca3d861f0 | ||
|
069e7a6e24 | ||
|
ac6e34ea06 | ||
|
a308b7507a | ||
|
630e7ff26f | ||
|
3764ab471b | ||
|
a3319c6f8e | ||
|
66c699a701 | ||
|
aaf1e44da9 | ||
|
1ef2307ec4 | ||
|
d42c3ba2dc | ||
|
4b06155873 | ||
|
857d825eeb | ||
|
6b345353e3 | ||
|
ab3b3a8f61 | ||
|
71b82fb1f6 | ||
|
9bd9ea423e | ||
|
99964398e7 | ||
|
7009ebfa69 | ||
|
760e23dd3a | ||
|
c53d9d516a | ||
|
7739e6b466 | ||
|
4881857458 | ||
|
c73d5cb7b6 | ||
|
6458803d21 | ||
|
6e72d781f7 | ||
|
4e926a9ef2 | ||
|
4ba3cfaee9 | ||
|
e655e8a7d5 | ||
|
c34e4e4b39 | ||
|
a678ee6365 | ||
|
49f0ee329d | ||
|
0c9d9a3d94 | ||
|
89e1acb0bb | ||
|
c2ed26b711 | ||
|
42fd392e05 | ||
|
e06447ee88 | ||
|
683dabe5e6 | ||
|
3aff96177c | ||
|
0a915eba8f | ||
|
19dcbc5717 | ||
|
d2a4952956 | ||
|
0c97b21b61 | ||
|
19390b1a91 | ||
|
8dc86051df | ||
|
46d5f9d1bf | ||
|
35e96b8deb | ||
|
2210ea7e3b | ||
|
61a1910f91 | ||
|
27ef73507b | ||
|
2b35fb643e | ||
|
478f6f95f1 | ||
|
44411d2d48 | ||
|
a2175cf71a | ||
|
4606d218c3 | ||
|
d37d0f24e6 | ||
|
321e8d51ed | ||
|
78f4b51757 | ||
|
7d168a2621 | ||
|
931e712eac | ||
|
4ec04209e0 | ||
|
82ddba88a2 | ||
|
52a8cc8d46 | ||
|
d175df8aa3 | ||
|
b003a35fde | ||
|
df1a0f9445 | ||
|
5b07b85838 | ||
|
f320cd203b | ||
|
f78c16f8c6 | ||
|
0c5f47e720 | ||
|
4b5b3d90af | ||
|
2cce4b95cd | ||
|
8e6eb52196 | ||
|
04b633ddf3 | ||
|
b76561a212 | ||
|
51c7589c87 | ||
|
99785382ae | ||
|
dc1690ce0f | ||
|
b6614261ea | ||
|
91e569ca37 | ||
|
0f395c1b11 | ||
|
2b13e7466f | ||
|
0982e47408 | ||
|
b93ebcf42f | ||
|
a08d83ba62 | ||
|
2b7c275ce8 | ||
|
040d0f48a0 | ||
|
724f35a664 | ||
|
6f3872edbd | ||
|
87324e680c | ||
|
c2b908f603 | ||
|
d7734f996f | ||
|
8b68890650 | ||
|
b60406cb9b | ||
|
ce9a9934ec | ||
|
720b2abe17 | ||
|
5983c00b95 | ||
|
6651dd7fd9 | ||
|
acdea31916 | ||
|
10885d349a | ||
|
1c1d09f3e9 | ||
|
0384faeee5 | ||
|
6cca3999c8 | ||
|
69408d384d | ||
|
4aea423f06 | ||
|
6fc8a63041 | ||
|
2583a7c0d1 | ||
|
0ef6e3103c | ||
|
7c052b37c8 | ||
|
d9c475d7f4 | ||
|
c8e57332d1 | ||
|
c045459917 | ||
|
e0f64e63db | ||
|
dddd58a8cd | ||
|
010fd21b20 | ||
|
1802fad2f9 | ||
|
f833d109d1 | ||
|
7225c99903 | ||
|
36178933ed | ||
|
ad0da9a571 | ||
|
6646468125 | ||
|
fee8df6ccf | ||
|
8fa47ac679 | ||
|
b427a2c6cb | ||
|
14d05e7c72 | ||
|
a118a57fe3 | ||
|
02cea3b47e | ||
|
1c2d673ded | ||
|
c34df2c1b6 | ||
|
6092aa977e | ||
|
c9cc2b385a | ||
|
b39d0c521a | ||
|
e87bed6df2 | ||
|
4ee05b3294 | ||
|
e81eb46a78 | ||
|
f315832f75 | ||
|
97ced11e53 | ||
|
4d6c4d36ce | ||
|
b4d53bf194 | ||
|
67bc08d1b9 | ||
|
bcb07de750 | ||
|
7d7cde0fd6 | ||
|
6b25d06d7d | ||
|
cff951c650 | ||
|
114cc3ec02 | ||
|
3c4b7672a8 | ||
|
6de149eb22 | ||
|
da909dd1e8 | ||
|
67986e81ee | ||
|
346bdea946 | ||
|
05c10c5776 | ||
|
b2cb925d99 | ||
|
9fb6502b3b | ||
|
9eb226ff78 | ||
|
e34c4eaf61 | ||
|
9e75bcfc75 | ||
|
d800ec05ff | ||
|
bda53ac6ad | ||
|
4230932563 | ||
|
f17e898bd1 | ||
|
886b2088f1 | ||
|
551d6bb23d | ||
|
d504005e91 | ||
|
2511b5c675 | ||
|
28aba061ec | ||
|
8e37c78ce3 | ||
|
ca68975ff8 | ||
|
529be52fea | ||
|
ca65478c89 | ||
|
a1e9362d38 | ||
|
cbfc69e310 | ||
|
1d7674bb22 | ||
|
e6cc22396a | ||
|
868159fd0a | ||
|
b597fa4637 | ||
|
d2d394eccf | ||
|
438beeabde | ||
|
281f0981a6 | ||
|
6ff346bed9 | ||
|
0925dd588c | ||
|
6f20315dff | ||
|
2e68f22118 | ||
|
8aa860d270 | ||
|
15abade272 | ||
|
7ab8c87281 | ||
|
4ff8f71643 | ||
|
d22abeee86 | ||
|
a33150eb4b | ||
|
fd00b3a186 | ||
|
e8389a4cc0 | ||
|
6078d756bc | ||
|
57c49fe867 | ||
|
c60de1acd4 | ||
|
69b738c097 | ||
|
da0b2a2f31 | ||
|
2378a558a2 | ||
|
f18ed615ae | ||
|
f6656fffb4 | ||
|
aaad7bfd15 | ||
|
0915da8842 | ||
|
0d0e8bde13 | ||
|
838a1ff950 | ||
|
e1315fd40c | ||
|
52a3ab1042 | ||
|
a82e7b765e | ||
|
0ed0fa4d5b | ||
|
ec85fddb9a | ||
|
3a1343a245 | ||
|
9066ee2eb4 | ||
|
40bd21ce63 | ||
|
4633fbec61 | ||
|
25060031a5 | ||
|
c7ae6334b7 | ||
|
eac04882b4 | ||
|
6499fc4f93 | ||
|
04f27a5438 | ||
|
1b3903d6e9 | ||
|
cc05093b0d | ||
|
6436dd4438 | ||
|
26c50c780e | ||
|
01d13b0c49 | ||
|
f15f45a9f8 | ||
|
1b2e149cb4 | ||
|
6136640ec9 | ||
|
95d8423823 | ||
|
de6411c338 | ||
|
e316cf53f6 | ||
|
c107db57db | ||
|
d39d00057c | ||
|
26157e6973 | ||
|
6d22782e8f | ||
|
1836b6740d | ||
|
924a088812 | ||
|
bab575c868 | ||
|
daae3bba50 | ||
|
05fbbbd8dc | ||
|
4c368bcd24 | ||
|
9927b9e642 | ||
|
1b492dffc8 | ||
|
140be1b4b3 | ||
|
79259acc12 | ||
|
5a3bea2d69 | ||
|
30d928591d | ||
|
70a3e62257 | ||
|
6828fba7a0 | ||
|
aa1bda8164 | ||
|
157ea539a2 | ||
|
c3c94c0e0a | ||
|
9d73909075 | ||
|
016c54196e | ||
|
5056bb952d | ||
|
8a6679b3b4 | ||
|
7b6d5ff298 | ||
|
846850914d | ||
|
4e6c513ac2 | ||
|
db9cda6a7d | ||
|
a50b15a9e9 | ||
|
0a25fe9188 | ||
|
2dd5212a79 | ||
|
00e95e1f38 | ||
|
0a0759132c | ||
|
5cf362c7d0 | ||
|
413be1112a | ||
|
8233dc8568 | ||
|
afa8b3bcd9 | ||
|
c518345f40 | ||
|
afe6ac9923 | ||
|
e995c1b532 | ||
|
e36929292e | ||
|
03128f78df | ||
|
7d4a5e654c | ||
|
41ba7a7984 | ||
|
aa471f2d65 | ||
|
d37dfa1bed | ||
|
9f35cc52fe | ||
|
f1fe19bc2b | ||
|
b55bd709ee | ||
|
9833610356 | ||
|
de7fc0011e | ||
|
2e0c767d74 | ||
|
a5379e901c | ||
|
a039d51d5f | ||
|
60b3dceccf | ||
|
c2ac851b90 | ||
|
c976bc6c2c | ||
|
2e834e941f | ||
|
77e5f3167c | ||
|
7e597ae204 | ||
|
c39df91ab9 | ||
|
af1158d105 | ||
|
b739721d9e | ||
|
7711ab6707 | ||
|
d370c32f69 | ||
|
d6a6eca71d | ||
|
39ffc18635 | ||
|
3e972ec84d | ||
|
b5159dfd2f | ||
|
07c2659806 | ||
|
dc83b9e988 | ||
|
8b4bc8270a | ||
|
0ff80653d3 | ||
|
352e1b4c81 | ||
|
aa13727067 | ||
|
595028614b | ||
|
6a3ae5e26a | ||
|
8c334ee078 | ||
|
f60fe2a4f9 | ||
|
b112257bf2 | ||
|
eb88adcd8a | ||
|
950a1ab5af | ||
|
1b9fe55025 | ||
|
2272df9d31 | ||
|
08d85d6d66 | ||
|
b43989207a | ||
|
2eebebf262 | ||
|
8c1fffe106 | ||
|
5e9acbc952 | ||
|
a420ceab50 | ||
|
0e1c649dca | ||
|
67c2124fa9 | ||
|
a635743c6d | ||
|
b5c2412d84 | ||
|
ad2e77d635 | ||
|
a20b10d01f | ||
|
4cc0551948 | ||
|
56130c3689 | ||
|
14f7380308 | ||
|
727449d1e7 | ||
|
80bf2aa559 | ||
|
b9cd0c4331 | ||
|
f77a87137c | ||
|
65dfe8fdce | ||
|
e3bb595d77 | ||
|
a1682b8927 | ||
|
24d91e3b8a | ||
|
ce04a66528 | ||
|
df74b26e5d | ||
|
b6ad663f87 | ||
|
ee31e38dc7 | ||
|
442334641e | ||
|
dfa5ea6360 | ||
|
3e06edeb5d | ||
|
78b050c13c | ||
|
4ad20ffc2c | ||
|
57e6e3bb80 | ||
|
19da197f58 | ||
|
666fae97e6 | ||
|
823fb1118a | ||
|
db1d62e184 | ||
|
d26ffc7fa3 | ||
|
0f3acce042 | ||
|
9eef9f7b02 | ||
|
aff4c787f4 | ||
|
fe3dfbbe90 | ||
|
2ffdc1936c | ||
|
0fe52c63ea | ||
|
28a52197c4 | ||
|
2c0d1cc87b | ||
|
375a251d16 | ||
|
d4b7a9a373 | ||
|
4d67199a4b | ||
|
95766d6241 | ||
|
4cb78a170c | ||
|
2c66b422e7 | ||
|
e571de83e9 | ||
|
4bb89e2cb1 | ||
|
349cadacf6 | ||
|
292ccc4c43 | ||
|
d7413ffd2d | ||
|
50729a2e73 | ||
|
a3e3f0b9ed | ||
|
45aea23355 | ||
|
975b459c17 | ||
|
2b35faee06 | ||
|
84818bdbb5 | ||
|
895902b57a | ||
|
7d4184dc5c | ||
|
8278f0a6be | ||
|
d3969634ac | ||
|
735ca9ccd6 | ||
|
4ee661d908 | ||
|
9fce8215b7 | ||
|
6521c2dd41 | ||
|
9ee9ce7e14 | ||
|
9d39da6452 | ||
|
0228dcd58f | ||
|
3d35ea99bb |
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# DWM Files
|
||||
*.o
|
||||
*.orig
|
||||
dwm
|
||||
dwm-msg
|
||||
config.h
|
7
.hgtags
7
.hgtags
@@ -1,7 +0,0 @@
|
||||
d31b5ad96b0ba7b5b0a30928fcf000428339a577 0.1
|
||||
0a6472e2203994bc5738d40a340d26f7ec9d6062 0.2
|
||||
7e66082e5092fb0bccd18a3695a0bec52c80fdb2 0.3
|
||||
eb3165734f00fe7f7da8aeebaed00e60a57caac9 0.4
|
||||
22213b9a2114167ee8ba019a012e27da0422a61a 0.5
|
||||
c11f86db4550cac5d0a648a3fe4d6d3b9a4fcf7e 0.6
|
||||
3fb41412e2492f66476d92ce8f007a8b48fb1d2a 0.7
|
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_
|
36
LICENSE
36
LICENSE
@@ -1,21 +1,37 @@
|
||||
MIT/X Consortium License
|
||||
|
||||
(C)opyright MMVI 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>
|
||||
© 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"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
60
Makefile
60
Makefile
@@ -1,13 +1,12 @@
|
||||
# dwm - dynamic window manager
|
||||
# (C)opyright MMVI Anselm R. Garbe
|
||||
# See LICENSE file for copyright and license details.
|
||||
|
||||
include config.mk
|
||||
|
||||
SRC = client.c draw.c event.c main.c tag.c util.c
|
||||
SRC = drw.c dwm.c util.c
|
||||
OBJ = ${SRC:.c=.o}
|
||||
|
||||
all: options dwm
|
||||
@echo finished
|
||||
all: options dwm dwm-msg
|
||||
|
||||
options:
|
||||
@echo dwm build options:
|
||||
@@ -16,47 +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 LD $@
|
||||
@${CC} -o $@ ${OBJ} ${LDFLAGS}
|
||||
@strip $@
|
||||
${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 ${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 X11 window manager.
|
||||
|
||||
|
||||
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/.*://; s/,//g'`
|
||||
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)
|
486
client.c
486
client.c
@@ -1,486 +0,0 @@
|
||||
/*
|
||||
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
#include "dwm.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
/* static functions */
|
||||
|
||||
static void
|
||||
resizetitle(Client *c)
|
||||
{
|
||||
int i;
|
||||
|
||||
c->tw = 0;
|
||||
for(i = 0; i < ntags; i++)
|
||||
if(c->tags[i])
|
||||
c->tw += textw(tags[i]);
|
||||
c->tw += textw(c->name);
|
||||
if(c->tw > c->w)
|
||||
c->tw = c->w + 2;
|
||||
c->tx = c->x + c->w - c->tw + 2;
|
||||
c->ty = c->y;
|
||||
if(c->tags[tsel])
|
||||
XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th);
|
||||
else
|
||||
XMoveResizeWindow(dpy, c->title, c->tx + 2 * sw, c->ty, c->tw, c->th);
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
xerrordummy(Display *dsply, XErrorEvent *ee)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* extern functions */
|
||||
|
||||
void
|
||||
ban(Client *c)
|
||||
{
|
||||
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
|
||||
XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty);
|
||||
}
|
||||
|
||||
void
|
||||
focus(Client *c)
|
||||
{
|
||||
if (!issel)
|
||||
return;
|
||||
Client *old = sel;
|
||||
XEvent ev;
|
||||
|
||||
sel = c;
|
||||
if(old && old != c)
|
||||
drawtitle(old);
|
||||
drawtitle(c);
|
||||
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
|
||||
XSync(dpy, False);
|
||||
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
|
||||
}
|
||||
|
||||
void
|
||||
focusnext(Arg *arg)
|
||||
{
|
||||
Client *c;
|
||||
|
||||
if(!sel)
|
||||
return;
|
||||
|
||||
if(sel->ismax)
|
||||
togglemax(NULL);
|
||||
|
||||
if(!(c = getnext(sel->next)))
|
||||
c = getnext(clients);
|
||||
if(c) {
|
||||
higher(c);
|
||||
focus(c);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
focusprev(Arg *arg)
|
||||
{
|
||||
Client *c;
|
||||
|
||||
if(!sel)
|
||||
return;
|
||||
|
||||
if(sel->ismax)
|
||||
togglemax(NULL);
|
||||
|
||||
if(!(c = getprev(sel->prev))) {
|
||||
for(c = clients; c && c->next; c = c->next);
|
||||
c = getprev(c);
|
||||
}
|
||||
if(c) {
|
||||
higher(c);
|
||||
focus(c);
|
||||
}
|
||||
}
|
||||
|
||||
Client *
|
||||
getclient(Window w)
|
||||
{
|
||||
Client *c;
|
||||
|
||||
for(c = clients; c; c = c->next)
|
||||
if(c->win == w)
|
||||
return c;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Client *
|
||||
getctitle(Window w)
|
||||
{
|
||||
Client *c;
|
||||
|
||||
for(c = clients; c; c = c->next)
|
||||
if(c->title == w)
|
||||
return c;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gravitate(Client *c, Bool invert)
|
||||
{
|
||||
int dx = 0, dy = 0;
|
||||
|
||||
switch(c->grav) {
|
||||
default:
|
||||
break;
|
||||
case StaticGravity:
|
||||
case NorthWestGravity:
|
||||
case NorthGravity:
|
||||
case NorthEastGravity:
|
||||
dy = c->border;
|
||||
break;
|
||||
case EastGravity:
|
||||
case CenterGravity:
|
||||
case WestGravity:
|
||||
dy = -(c->h / 2) + c->border;
|
||||
break;
|
||||
case SouthEastGravity:
|
||||
case SouthGravity:
|
||||
case SouthWestGravity:
|
||||
dy = -(c->h);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c->grav) {
|
||||
default:
|
||||
break;
|
||||
case StaticGravity:
|
||||
case NorthWestGravity:
|
||||
case WestGravity:
|
||||
case SouthWestGravity:
|
||||
dx = c->border;
|
||||
break;
|
||||
case NorthGravity:
|
||||
case CenterGravity:
|
||||
case SouthGravity:
|
||||
dx = -(c->w / 2) + c->border;
|
||||
break;
|
||||
case NorthEastGravity:
|
||||
case EastGravity:
|
||||
case SouthEastGravity:
|
||||
dx = -(c->w + c->border);
|
||||
break;
|
||||
}
|
||||
|
||||
if(invert) {
|
||||
dx = -dx;
|
||||
dy = -dy;
|
||||
}
|
||||
c->x += dx;
|
||||
c->y += dy;
|
||||
}
|
||||
|
||||
void
|
||||
higher(Client *c)
|
||||
{
|
||||
XRaiseWindow(dpy, c->win);
|
||||
XRaiseWindow(dpy, c->title);
|
||||
}
|
||||
|
||||
void
|
||||
killclient(Arg *arg)
|
||||
{
|
||||
if(!sel)
|
||||
return;
|
||||
if(sel->proto & PROTODELWIN)
|
||||
sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]);
|
||||
else
|
||||
XKillClient(dpy, sel->win);
|
||||
}
|
||||
|
||||
void
|
||||
manage(Window w, XWindowAttributes *wa)
|
||||
{
|
||||
Client *c;
|
||||
Window trans;
|
||||
XSetWindowAttributes twa;
|
||||
|
||||
c = emallocz(sizeof(Client));
|
||||
c->tags = emallocz(ntags * sizeof(Bool));
|
||||
c->win = w;
|
||||
c->x = c->tx = wa->x;
|
||||
c->y = c->ty = wa->y;
|
||||
c->w = c->tw = wa->width;
|
||||
c->h = wa->height;
|
||||
c->th = bh;
|
||||
|
||||
c->border = 0;
|
||||
setsize(c);
|
||||
|
||||
if(c->h != sh && c->y < bh)
|
||||
c->y = c->ty = bh;
|
||||
|
||||
c->proto = getproto(c->win);
|
||||
XSelectInput(dpy, c->win,
|
||||
StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
|
||||
XGetTransientForHint(dpy, c->win, &trans);
|
||||
twa.override_redirect = 1;
|
||||
twa.background_pixmap = ParentRelative;
|
||||
twa.event_mask = ExposureMask | EnterWindowMask;
|
||||
|
||||
c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th,
|
||||
0, DefaultDepth(dpy, screen), CopyFromParent,
|
||||
DefaultVisual(dpy, screen),
|
||||
CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
|
||||
|
||||
if(clients)
|
||||
clients->prev = c;
|
||||
c->next = clients;
|
||||
clients = c;
|
||||
|
||||
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);
|
||||
|
||||
settags(c);
|
||||
if(!c->isfloat)
|
||||
c->isfloat = trans
|
||||
|| (c->maxw && c->minw &&
|
||||
c->maxw == c->minw && c->maxh == c->minh);
|
||||
settitle(c);
|
||||
arrange(NULL);
|
||||
|
||||
/* mapping the window now prevents flicker */
|
||||
XMapRaised(dpy, c->win);
|
||||
XMapRaised(dpy, c->title);
|
||||
if(c->tags[tsel])
|
||||
focus(c);
|
||||
}
|
||||
|
||||
void
|
||||
resize(Client *c, Bool sizehints, Corner sticky)
|
||||
{
|
||||
int bottom = c->y + c->h;
|
||||
int right = c->x + c->w;
|
||||
/*XConfigureEvent e;*/
|
||||
XWindowChanges wc;
|
||||
|
||||
if(sizehints) {
|
||||
if(c->incw)
|
||||
c->w -= (c->w - c->basew) % c->incw;
|
||||
if(c->inch)
|
||||
c->h -= (c->h - c->baseh) % c->inch;
|
||||
if(c->minw && c->w < c->minw)
|
||||
c->w = c->minw;
|
||||
if(c->minh && c->h < c->minh)
|
||||
c->h = c->minh;
|
||||
if(c->maxw && c->w > c->maxw)
|
||||
c->w = c->maxw;
|
||||
if(c->maxh && c->h > c->maxh)
|
||||
c->h = c->maxh;
|
||||
}
|
||||
if(c->x > right) /* might happen on restart */
|
||||
c->x = right - c->w;
|
||||
if(c->y > bottom)
|
||||
c->y = bottom - c->h;
|
||||
if(sticky == TopRight || sticky == BotRight)
|
||||
c->x = right - c->w;
|
||||
if(sticky == BotLeft || sticky == BotRight)
|
||||
c->y = bottom - c->h;
|
||||
|
||||
resizetitle(c);
|
||||
wc.x = c->x;
|
||||
wc.y = c->y;
|
||||
wc.width = c->w;
|
||||
wc.height = c->h;
|
||||
if(c->w == sw && c->h == sh)
|
||||
wc.border_width = 0;
|
||||
else
|
||||
wc.border_width = 1;
|
||||
XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
|
||||
XSync(dpy, False);
|
||||
}
|
||||
|
||||
void
|
||||
setsize(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
|
||||
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
|
||||
c->minw = c->minh = 0;
|
||||
if(c->flags & PWinGravity)
|
||||
c->grav = size.win_gravity;
|
||||
else
|
||||
c->grav = NorthWestGravity;
|
||||
}
|
||||
|
||||
void
|
||||
settitle(Client *c)
|
||||
{
|
||||
char **list = NULL;
|
||||
int n;
|
||||
XTextProperty name;
|
||||
|
||||
name.nitems = 0;
|
||||
c->name[0] = 0;
|
||||
XGetTextProperty(dpy, c->win, &name, netatom[NetWMName]);
|
||||
if(!name.nitems)
|
||||
XGetWMName(dpy, c->win, &name);
|
||||
if(!name.nitems)
|
||||
return;
|
||||
if(name.encoding == XA_STRING)
|
||||
strncpy(c->name, (char *)name.value, sizeof(c->name));
|
||||
else {
|
||||
if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
|
||||
&& n > 0 && *list)
|
||||
{
|
||||
strncpy(c->name, *list, sizeof(c->name));
|
||||
XFreeStringList(list);
|
||||
}
|
||||
}
|
||||
XFree(name.value);
|
||||
resizetitle(c);
|
||||
}
|
||||
|
||||
void
|
||||
togglemax(Arg *arg)
|
||||
{
|
||||
int ox, oy, ow, oh;
|
||||
XEvent ev;
|
||||
|
||||
if(!sel)
|
||||
return;
|
||||
|
||||
if((sel->ismax = !sel->ismax)) {
|
||||
ox = sel->x;
|
||||
oy = sel->y;
|
||||
ow = sel->w;
|
||||
oh = sel->h;
|
||||
sel->x = sx;
|
||||
sel->y = sy + bh;
|
||||
sel->w = sw - 2;
|
||||
sel->h = sh - 2 - bh;
|
||||
|
||||
higher(sel);
|
||||
resize(sel, False, TopLeft);
|
||||
|
||||
sel->x = ox;
|
||||
sel->y = oy;
|
||||
sel->w = ow;
|
||||
sel->h = oh;
|
||||
}
|
||||
else
|
||||
resize(sel, False, TopLeft);
|
||||
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
|
||||
}
|
||||
|
||||
void
|
||||
unmanage(Client *c)
|
||||
{
|
||||
XGrabServer(dpy);
|
||||
XSetErrorHandler(xerrordummy);
|
||||
|
||||
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
|
||||
XDestroyWindow(dpy, c->title);
|
||||
|
||||
if(c->prev)
|
||||
c->prev->next = c->next;
|
||||
if(c->next)
|
||||
c->next->prev = c->prev;
|
||||
if(c == clients)
|
||||
clients = c->next;
|
||||
if(sel == c) {
|
||||
sel = getnext(c->next);
|
||||
if(!sel)
|
||||
sel = getprev(c->prev);
|
||||
if(!sel)
|
||||
sel = clients;
|
||||
}
|
||||
free(c->tags);
|
||||
free(c);
|
||||
|
||||
XSync(dpy, False);
|
||||
XSetErrorHandler(xerror);
|
||||
XUngrabServer(dpy);
|
||||
arrange(NULL);
|
||||
if(sel)
|
||||
focus(sel);
|
||||
}
|
||||
|
||||
void
|
||||
zoom(Arg *arg)
|
||||
{
|
||||
Client *c;
|
||||
|
||||
if(!sel || (arrange != dotile) || sel->isfloat)
|
||||
return;
|
||||
|
||||
if(sel == getnext(clients)) {
|
||||
if((c = getnext(sel->next)))
|
||||
sel = c;
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
/* pop */
|
||||
if(sel->prev)
|
||||
sel->prev->next = sel->next;
|
||||
if(sel->next)
|
||||
sel->next->prev = sel->prev;
|
||||
sel->prev = NULL;
|
||||
if(clients)
|
||||
clients->prev = sel;
|
||||
sel->next = clients;
|
||||
clients = sel;
|
||||
arrange(NULL);
|
||||
focus(sel);
|
||||
}
|
55
config.arg.h
55
config.arg.h
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
|
||||
#define TAGS \
|
||||
const char *tags[] = { "work", "net", "fnord", NULL };
|
||||
|
||||
#define DEFMODE dotile /* dofloat */
|
||||
#define DEFTAG 0 /* index */
|
||||
#define FONT "-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*"
|
||||
#define BGCOLOR "#eeeeee"
|
||||
#define FGCOLOR "#666699"
|
||||
#define BORDERCOLOR "#9999CC"
|
||||
#define MODKEY Mod1Mask
|
||||
#define NUMLOCKMASK Mod2Mask
|
||||
#define MASTERW 60 /* percent */
|
||||
|
||||
#define KEYS \
|
||||
static Key key[] = { \
|
||||
/* modifier key function arguments */ \
|
||||
{ MODKEY, XK_1, view, { .i = 0 } }, \
|
||||
{ MODKEY, XK_2, view, { .i = 1 } }, \
|
||||
{ MODKEY, XK_3, view, { .i = 2 } }, \
|
||||
{ MODKEY, XK_h, viewprev, { 0 } }, \
|
||||
{ MODKEY, XK_j, focusnext, { 0 } }, \
|
||||
{ MODKEY, XK_k, focusprev, { 0 } }, \
|
||||
{ MODKEY, XK_l, viewnext, { 0 } }, \
|
||||
{ MODKEY, XK_m, togglemax, { 0 } }, \
|
||||
{ MODKEY, XK_p, spawn, \
|
||||
{ .cmd = "exec `ls -lL /usr/bin /usr/local/bin 2>/dev/null | " \
|
||||
"awk 'NF>2 && $1 ~ /^[^d].*x/ {print $NF}' | sort | uniq | dmenu`" } }, \
|
||||
{ MODKEY, XK_space, togglemode, { 0 } }, \
|
||||
{ MODKEY, XK_Return, zoom, { 0 } }, \
|
||||
{ MODKEY|ControlMask, XK_1, appendtag, { .i = 0 } }, \
|
||||
{ MODKEY|ControlMask, XK_2, appendtag, { .i = 1 } }, \
|
||||
{ MODKEY|ControlMask, XK_3, appendtag, { .i = 2 } }, \
|
||||
{ MODKEY|ShiftMask, XK_1, replacetag, { .i = 0 } }, \
|
||||
{ MODKEY|ShiftMask, XK_2, replacetag, { .i = 1 } }, \
|
||||
{ MODKEY|ShiftMask, XK_3, replacetag, { .i = 2 } }, \
|
||||
{ MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \
|
||||
{ MODKEY|ShiftMask, XK_q, quit, { 0 } }, \
|
||||
{ MODKEY|ShiftMask, XK_Return, spawn, \
|
||||
{ .cmd = "exec uxterm -bg '#dddddd' -fg '#000000' -cr '#000000' +sb " \
|
||||
"-fn '-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*'" } }, \
|
||||
};
|
||||
|
||||
#define RULES \
|
||||
static Rule rule[] = { \
|
||||
/* class:instance regex tags regex isfloat */ \
|
||||
{ "Firefox.*", "net", False }, \
|
||||
{ "Gimp.*", NULL, True}, \
|
||||
{ "MPlayer.*", NULL, True}, \
|
||||
{ "Acroread.*", NULL, True}, \
|
||||
};
|
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,54 +0,0 @@
|
||||
/*
|
||||
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
|
||||
#define TAGS \
|
||||
const char *tags[] = { "0", "1", "2", "3", "4", NULL };
|
||||
|
||||
#define DEFMODE dotile /* dofloat */
|
||||
#define DEFTAG 1 /* index */
|
||||
#define FONT "fixed"
|
||||
#define BGCOLOR "#666699"
|
||||
#define FGCOLOR "#eeeeee"
|
||||
#define BORDERCOLOR "#9999CC"
|
||||
#define MODKEY Mod1Mask
|
||||
#define NUMLOCKMASK Mod2Mask
|
||||
#define MASTERW 60 /* percent */
|
||||
|
||||
#define KEYS \
|
||||
static Key key[] = { \
|
||||
/* modifier key function arguments */ \
|
||||
{ MODKEY, XK_0, view, { .i = 0 } }, \
|
||||
{ MODKEY, XK_1, view, { .i = 1 } }, \
|
||||
{ MODKEY, XK_2, view, { .i = 2 } }, \
|
||||
{ MODKEY, XK_3, view, { .i = 3 } }, \
|
||||
{ MODKEY, XK_4, view, { .i = 4 } }, \
|
||||
{ MODKEY, XK_h, viewprev, { 0 } }, \
|
||||
{ MODKEY, XK_j, focusnext, { 0 } }, \
|
||||
{ MODKEY, XK_k, focusprev, { 0 } }, \
|
||||
{ MODKEY, XK_l, viewnext, { 0 } }, \
|
||||
{ MODKEY, XK_m, togglemax, { 0 } }, \
|
||||
{ MODKEY, XK_space, togglemode, { 0 } }, \
|
||||
{ MODKEY, XK_Return, zoom, { 0 } }, \
|
||||
{ MODKEY|ControlMask, XK_0, appendtag, { .i = 0 } }, \
|
||||
{ MODKEY|ControlMask, XK_1, appendtag, { .i = 1 } }, \
|
||||
{ MODKEY|ControlMask, XK_2, appendtag, { .i = 2 } }, \
|
||||
{ MODKEY|ControlMask, XK_3, appendtag, { .i = 3 } }, \
|
||||
{ MODKEY|ControlMask, XK_4, appendtag, { .i = 4 } }, \
|
||||
{ MODKEY|ShiftMask, XK_0, replacetag, { .i = 0 } }, \
|
||||
{ MODKEY|ShiftMask, XK_1, replacetag, { .i = 1 } }, \
|
||||
{ MODKEY|ShiftMask, XK_2, replacetag, { .i = 2 } }, \
|
||||
{ MODKEY|ShiftMask, XK_3, replacetag, { .i = 3 } }, \
|
||||
{ MODKEY|ShiftMask, XK_4, replacetag, { .i = 4 } }, \
|
||||
{ MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \
|
||||
{ MODKEY|ShiftMask, XK_q, quit, { 0 } }, \
|
||||
{ MODKEY|ShiftMask, XK_Return, spawn, { .cmd = "exec xterm" } }, \
|
||||
};
|
||||
|
||||
#define RULES \
|
||||
static Rule rule[] = { \
|
||||
/* class:instance regex tags regex isfloat */ \
|
||||
{ "Firefox.*", "2", False }, \
|
||||
{ "Gimp.*", NULL, True}, \
|
||||
};
|
35
config.mk
35
config.mk
@@ -1,5 +1,5 @@
|
||||
# dwm version
|
||||
VERSION = 0.8
|
||||
VERSION = 6.2
|
||||
|
||||
# Customize below to fit your system
|
||||
|
||||
@@ -10,15 +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/usr/lib -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 = ${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}
|
||||
|
||||
# compiler
|
||||
# Solaris
|
||||
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
|
||||
#LDFLAGS = ${LIBS}
|
||||
|
||||
# compiler and linker
|
||||
CC = cc
|
||||
|
233
draw.c
233
draw.c
@@ -1,233 +0,0 @@
|
||||
/*
|
||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
#include "dwm.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlocale.h>
|
||||
|
||||
/* static */
|
||||
|
||||
static void
|
||||
drawborder(void)
|
||||
{
|
||||
XPoint points[5];
|
||||
|
||||
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
|
||||
XSetForeground(dpy, dc.gc, dc.border);
|
||||
points[0].x = dc.x;
|
||||
points[0].y = dc.y;
|
||||
points[1].x = dc.w - 1;
|
||||
points[1].y = 0;
|
||||
points[2].x = 0;
|
||||
points[2].y = dc.h - 1;
|
||||
points[3].x = -(dc.w - 1);
|
||||
points[3].y = 0;
|
||||
points[4].x = 0;
|
||||
points[4].y = -(dc.h - 1);
|
||||
XDrawLines(dpy, dc.drawable, dc.gc, points, 5, CoordModePrevious);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
textnw(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);
|
||||
}
|
||||
|
||||
static void
|
||||
drawtext(const char *text, Bool invert)
|
||||
{
|
||||
int x, y, w, h;
|
||||
static char buf[256];
|
||||
unsigned int len;
|
||||
XGCValues gcv;
|
||||
XRectangle r = { dc.x, dc.y, dc.w, dc.h };
|
||||
|
||||
XSetForeground(dpy, dc.gc, invert ? dc.fg : dc.bg);
|
||||
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
|
||||
drawborder();
|
||||
|
||||
if(!text)
|
||||
return;
|
||||
|
||||
w = 0;
|
||||
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(w > dc.w)
|
||||
return; /* too long */
|
||||
|
||||
gcv.foreground = invert ? dc.bg : dc.fg;
|
||||
gcv.background = invert ? dc.fg : dc.bg;
|
||||
if(dc.font.set) {
|
||||
XChangeGC(dpy, dc.gc, GCForeground | GCBackground, &gcv);
|
||||
XmbDrawImageString(dpy, dc.drawable, dc.font.set, dc.gc,
|
||||
x, y, buf, len);
|
||||
}
|
||||
else {
|
||||
gcv.font = dc.font.xfont->fid;
|
||||
XChangeGC(dpy, dc.gc, GCForeground | GCBackground | GCFont, &gcv);
|
||||
XDrawImageString(dpy, dc.drawable, dc.gc, x, y, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
/* extern */
|
||||
|
||||
void
|
||||
drawall()
|
||||
{
|
||||
Client *c;
|
||||
|
||||
for(c = clients; c; c = getnext(c->next))
|
||||
drawtitle(c);
|
||||
drawstatus();
|
||||
}
|
||||
|
||||
void
|
||||
drawstatus()
|
||||
{
|
||||
int i, x;
|
||||
Bool istile = arrange == dotile;
|
||||
|
||||
dc.x = dc.y = 0;
|
||||
dc.w = bw;
|
||||
drawtext(NULL, !istile);
|
||||
|
||||
dc.w = 0;
|
||||
for(i = 0; i < ntags; i++) {
|
||||
dc.x += dc.w;
|
||||
dc.w = textw(tags[i]);
|
||||
if(istile)
|
||||
drawtext(tags[i], (i == tsel));
|
||||
else
|
||||
drawtext(tags[i], (i != tsel));
|
||||
}
|
||||
x = dc.x + dc.w;
|
||||
dc.w = textw(stext);
|
||||
dc.x = bx + bw - dc.w;
|
||||
drawtext(stext, !istile);
|
||||
if(sel && ((dc.w = dc.x - x) >= bh)) {
|
||||
dc.x = x;
|
||||
drawtext(sel->name, istile);
|
||||
}
|
||||
XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0);
|
||||
XSync(dpy, False);
|
||||
}
|
||||
|
||||
void
|
||||
drawtitle(Client *c)
|
||||
{
|
||||
int i;
|
||||
Bool istile = arrange == dotile;
|
||||
|
||||
if(c == sel && issel) {
|
||||
drawstatus();
|
||||
XUnmapWindow(dpy, c->title);
|
||||
XSetWindowBorder(dpy, c->win, dc.fg);
|
||||
return;
|
||||
}
|
||||
|
||||
XSetWindowBorder(dpy, c->win, dc.bg);
|
||||
XMapWindow(dpy, c->title);
|
||||
|
||||
dc.x = dc.y = 0;
|
||||
|
||||
dc.w = 0;
|
||||
for(i = 0; i < ntags; i++) {
|
||||
if(c->tags[i]) {
|
||||
dc.x += dc.w;
|
||||
dc.w = textw(tags[i]);
|
||||
drawtext(tags[i], !istile);
|
||||
}
|
||||
}
|
||||
dc.x += dc.w;
|
||||
dc.w = textw(c->name);
|
||||
drawtext(c->name, !istile);
|
||||
XCopyArea(dpy, dc.drawable, c->title, dc.gc, 0, 0, c->tw, c->th, 0, 0);
|
||||
XSync(dpy, False);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
getcolor(const char *colstr)
|
||||
{
|
||||
Colormap cmap = DefaultColormap(dpy, screen);
|
||||
XColor color;
|
||||
|
||||
XAllocNamedColor(dpy, cmap, colstr, &color, &color);
|
||||
return color.pixel;
|
||||
}
|
||||
|
||||
void
|
||||
setfont(const char *fontstr)
|
||||
{
|
||||
char **missing, *def;
|
||||
int i, n;
|
||||
|
||||
missing = NULL;
|
||||
setlocale(LC_ALL, "");
|
||||
if(dc.font.set)
|
||||
XFreeFontSet(dpy, dc.font.set);
|
||||
dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
|
||||
if(missing) {
|
||||
while(n--)
|
||||
fprintf(stderr, "missing fontset: %s\n", missing[n]);
|
||||
XFreeStringList(missing);
|
||||
if(dc.font.set) {
|
||||
XFreeFontSet(dpy, dc.font.set);
|
||||
dc.font.set = NULL;
|
||||
}
|
||||
}
|
||||
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;
|
||||
dc.font.xfont = XLoadQueryFont(dpy, fontstr);
|
||||
if (!dc.font.xfont)
|
||||
dc.font.xfont = XLoadQueryFont(dpy, "fixed");
|
||||
if (!dc.font.xfont)
|
||||
eprint("error, cannot init 'fixed' font\n");
|
||||
dc.font.ascent = dc.font.xfont->ascent;
|
||||
dc.font.descent = dc.font.xfont->descent;
|
||||
}
|
||||
dc.font.height = dc.font.ascent + dc.font.descent;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
265
dwm.1
265
dwm.1
@@ -1,115 +1,206 @@
|
||||
.TH DWM 1 dwm-VERSION
|
||||
.TH DWM 1 dwm\-VERSION
|
||||
.SH NAME
|
||||
dwm \- dynamic window manager
|
||||
.SH SYNOPSIS
|
||||
.B dwm
|
||||
.RB [ \-v ]
|
||||
.SH DESCRIPTION
|
||||
.B dwm
|
||||
is a dynamic window manager for X11. It manages windows in tiling and floating
|
||||
modes. Either mode can be applied dynamically, optimizing the environment for
|
||||
the application in use and the task performed.
|
||||
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 tiling mode windows are managed in a master and stacking column. The master
|
||||
column contains the window which currently needs most attention, whereas the
|
||||
stacking column contains all other windows. In floating mode windows can be
|
||||
resized and moved freely. Dialog windows are always managed floating,
|
||||
regardless of the mode selected.
|
||||
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 a certain tag for viewing will display all windows with that
|
||||
tag.
|
||||
tags. Selecting certain tags displays all windows with these tags.
|
||||
.P
|
||||
.B dwm
|
||||
has a small status bar which displays the text read from standard
|
||||
input, if written. Besides that, it displays all available tags, and the title
|
||||
of the focused window. It draws a 1-pixel border around windows to
|
||||
indicate the focus state. Unfocused windows contain a small bar in front of
|
||||
them displaying their tags and title.
|
||||
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 Mod1-Return
|
||||
Zoom current
|
||||
.B window
|
||||
to the
|
||||
.B master
|
||||
column.
|
||||
.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 Mod1-h
|
||||
Focus previous
|
||||
.B tag.
|
||||
.B Button1
|
||||
click on a tag label to display all windows with that tag, click on the layout
|
||||
label toggles between tiled and floating layout.
|
||||
.TP
|
||||
.B Mod1-j
|
||||
Focus next
|
||||
.B window.
|
||||
.B Button3
|
||||
click on a tag label adds/removes all windows with that tag to/from the view.
|
||||
.TP
|
||||
.B Mod1-k
|
||||
Focus previous
|
||||
.B window.
|
||||
.B Mod1\-Button1
|
||||
click on a tag label applies that tag to the focused window.
|
||||
.TP
|
||||
.B Mod1-l
|
||||
Focus next
|
||||
.B tag.
|
||||
.B Mod1\-Button3
|
||||
click on a tag label adds/removes that tag to/from the focused window.
|
||||
.SS Keyboard commands
|
||||
.TP
|
||||
.B Mod1-m
|
||||
Maximize current
|
||||
.B window.
|
||||
.TP
|
||||
.B Mod1-[0..n]
|
||||
Focus
|
||||
.B nth tag.
|
||||
.TP
|
||||
.B Mod1-space
|
||||
Toggle between
|
||||
.B tiled
|
||||
and
|
||||
.B floating
|
||||
mode (affects
|
||||
.BR "all windows" ).
|
||||
.TP
|
||||
.B Mod1-Shift-[0..n]
|
||||
Apply
|
||||
.B nth tag
|
||||
to current
|
||||
.B window.
|
||||
.TP
|
||||
.B Mod1-Shift-q
|
||||
Quit
|
||||
.B dwm.
|
||||
.TP
|
||||
.B Mod1-Shift-Return
|
||||
.B Mod1\-Shift\-Return
|
||||
Start
|
||||
.B terminal.
|
||||
.BR st(1).
|
||||
.TP
|
||||
.B Mod1-Control-[0..n]
|
||||
Append
|
||||
.B nth tag
|
||||
to current
|
||||
.B window.
|
||||
.B Mod1\-p
|
||||
Spawn
|
||||
.BR dmenu(1)
|
||||
for launching other programs.
|
||||
.TP
|
||||
.B Mod1-Button1
|
||||
Move current
|
||||
.B window
|
||||
while dragging.
|
||||
.B Mod1\-,
|
||||
Focus previous screen, if any.
|
||||
.TP
|
||||
.B Mod1-Button2
|
||||
Zoom current
|
||||
.B window
|
||||
to the
|
||||
.B master
|
||||
column.
|
||||
.B Mod1\-.
|
||||
Focus next screen, if any.
|
||||
.TP
|
||||
.B Mod1-Button3
|
||||
Resize current
|
||||
.B window
|
||||
while dragging.
|
||||
.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
|
||||
Toggles bar on and off.
|
||||
.TP
|
||||
.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.
|
||||
.TP
|
||||
.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
|
||||
Increase master area size.
|
||||
.TP
|
||||
.B Mod1\-h
|
||||
Decrease master area size.
|
||||
.TP
|
||||
.B Mod1\-Shift\-l
|
||||
Increase client weight (cfacts patch).
|
||||
.TP
|
||||
.B Mod1\-Shift\-h
|
||||
Decrease client weight (cfacts patch).
|
||||
.TP
|
||||
.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\-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 nth tag.
|
||||
.TP
|
||||
.B Mod1\-0
|
||||
View all windows with any tag.
|
||||
.TP
|
||||
.B Mod1\-Control\-[1..n]
|
||||
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 focused window while dragging. Tiled windows will be toggled to the floating state.
|
||||
.TP
|
||||
.B Mod1\-Button2
|
||||
Toggles focused window between floating and tiled state.
|
||||
.TP
|
||||
.B Mod1\-Button3
|
||||
Resize focused window while dragging. Tiled windows will be toggled to the floating state.
|
||||
.SH CUSTOMIZATION
|
||||
.B dwm
|
||||
is customized by creating a custom config.h and (re)compiling the source
|
||||
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)
|
||||
.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. 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.
|
||||
|
136
dwm.h
136
dwm.h
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
/* mask shorthands, used in event.c and client.c */
|
||||
#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask)
|
||||
#define MOUSEMASK (BUTTONMASK | PointerMotionMask)
|
||||
#define PROTODELWIN 1
|
||||
|
||||
typedef union Arg Arg;
|
||||
typedef struct Client Client;
|
||||
typedef struct DC DC;
|
||||
typedef struct Fnt Fnt;
|
||||
|
||||
union Arg {
|
||||
const char *cmd;
|
||||
int i;
|
||||
};
|
||||
|
||||
/* atoms */
|
||||
enum { NetSupported, NetWMName, NetLast };
|
||||
enum { WMProtocols, WMDelete, WMLast };
|
||||
|
||||
/* cursor */
|
||||
enum { CurNormal, CurResize, CurMove, CurLast };
|
||||
|
||||
/* windowcorners */
|
||||
typedef enum { TopLeft, TopRight, BotLeft, BotRight } Corner;
|
||||
|
||||
struct Fnt {
|
||||
int ascent;
|
||||
int descent;
|
||||
int height;
|
||||
XFontSet set;
|
||||
XFontStruct *xfont;
|
||||
};
|
||||
|
||||
struct DC { /* draw context */
|
||||
int x, y, w, h;
|
||||
unsigned long bg;
|
||||
unsigned long fg;
|
||||
unsigned long border;
|
||||
Drawable drawable;
|
||||
Fnt font;
|
||||
GC gc;
|
||||
};
|
||||
|
||||
struct Client {
|
||||
char name[256];
|
||||
int proto;
|
||||
int x, y, w, h;
|
||||
int tx, ty, tw, th; /* title */
|
||||
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
|
||||
int grav;
|
||||
long flags;
|
||||
unsigned int border;
|
||||
Bool isfloat;
|
||||
Bool ismax;
|
||||
Bool *tags;
|
||||
Client *next;
|
||||
Client *prev;
|
||||
Window win;
|
||||
Window title;
|
||||
};
|
||||
|
||||
extern const char *tags[];
|
||||
extern char stext[1024];
|
||||
extern int tsel, screen, sx, sy, sw, sh, bx, by, bw, bh, mw;
|
||||
extern unsigned int ntags;
|
||||
extern void (*handler[LASTEvent])(XEvent *);
|
||||
extern void (*arrange)(Arg *);
|
||||
extern Atom wmatom[WMLast], netatom[NetLast];
|
||||
extern Bool running, issel;
|
||||
extern Client *clients, *sel;
|
||||
extern Cursor cursor[CurLast];
|
||||
extern DC dc;
|
||||
extern Display *dpy;
|
||||
extern Window root, barwin;
|
||||
|
||||
/* client.c */
|
||||
extern void ban(Client *c);
|
||||
extern void focus(Client *c);
|
||||
extern void focusnext(Arg *arg);
|
||||
extern void focusprev(Arg *arg);
|
||||
extern Client *getclient(Window w);
|
||||
extern Client *getctitle(Window w);
|
||||
extern void gravitate(Client *c, Bool invert);
|
||||
extern void higher(Client *c);
|
||||
extern void killclient(Arg *arg);
|
||||
extern void manage(Window w, XWindowAttributes *wa);
|
||||
extern void resize(Client *c, Bool sizehints, Corner sticky);
|
||||
extern void setsize(Client *c);
|
||||
extern void settitle(Client *c);
|
||||
extern void togglemax(Arg *arg);
|
||||
extern void unmanage(Client *c);
|
||||
extern void zoom(Arg *arg);
|
||||
|
||||
/* draw.c */
|
||||
extern void drawall();
|
||||
extern void drawstatus();
|
||||
extern void drawtitle(Client *c);
|
||||
extern unsigned long getcolor(const char *colstr);
|
||||
extern void setfont(const char *fontstr);
|
||||
extern unsigned int textw(const char *text);
|
||||
|
||||
/* event.c */
|
||||
extern void grabkeys();
|
||||
|
||||
/* main.c */
|
||||
extern int getproto(Window w);
|
||||
extern void quit(Arg *arg);
|
||||
extern void sendevent(Window w, Atom a, long value);
|
||||
extern int xerror(Display *dsply, XErrorEvent *ee);
|
||||
|
||||
/* tag.c */
|
||||
extern void appendtag(Arg *arg);
|
||||
extern void dofloat(Arg *arg);
|
||||
extern void dotile(Arg *arg);
|
||||
extern void initrregs();
|
||||
extern Client *getnext(Client *c);
|
||||
extern Client *getprev(Client *c);
|
||||
extern void replacetag(Arg *arg);
|
||||
extern void settags(Client *c);
|
||||
extern void togglemode(Arg *arg);
|
||||
extern void view(Arg *arg);
|
||||
extern void viewnext(Arg *arg);
|
||||
extern void viewprev(Arg *arg);
|
||||
|
||||
/* util.c */
|
||||
extern void *emallocz(unsigned int size);
|
||||
extern void eprint(const char *errstr, ...);
|
||||
extern void spawn(Arg *arg);
|
126
dwm.html
126
dwm.html
@@ -1,126 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>dwm - dynamic window manager</title>
|
||||
<meta name="author" content="Anselm R. Garbe">
|
||||
<meta name="generator" content="ed">
|
||||
<meta name="copyright" content="(C)opyright 2006 by Anselm R. Garbe">
|
||||
<style type="text/css">
|
||||
body {
|
||||
color: #000000;
|
||||
font-family: sans-serif;
|
||||
margin: 20px 20px 20px 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<img src="dwm.png"/><br />
|
||||
<h3>dynamic window manager</h3>
|
||||
</center>
|
||||
<h3>Description</h3>
|
||||
<p>
|
||||
dwm is a dynamic window manager for X11.
|
||||
</p>
|
||||
<h4>Background</h4>
|
||||
<p>
|
||||
As founder and main developer of wmii I came to the conclusion that
|
||||
wmii is too clunky for my needs. I don't need so many funky features
|
||||
and all this hype about remote control through a 9P service, I only
|
||||
want to manage my windows in a simple, but dynamic way. wmii never got
|
||||
finished because I listened to users, who proposed arbitrary ideas I
|
||||
considered useful. This resulted in an extreme <a
|
||||
href="http://www.jwz.org/doc/cadt.html">CADT</a> development model,
|
||||
which was a mistake. Thus the philosophy of dwm is simply <i>to fit my
|
||||
needs</i> (maybe yours as well). That's it.
|
||||
</p>
|
||||
<h4>Differences to ion, larswm, and wmii</h4>
|
||||
<p>
|
||||
In contrast to ion, larswm, and wmii, dwm is much smaller, faster and simpler.
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
dwm has no Lua integration, no 9P support, no editable
|
||||
tagbars, no shell-based configuration, no remote control, and comes
|
||||
without any additional tools like printing the selection or warping
|
||||
the mouse.
|
||||
</li>
|
||||
<li>
|
||||
dwm is only a single binary, it's source code is intended to never
|
||||
exceed 2000 SLOC.
|
||||
</li>
|
||||
<li>
|
||||
dwm is based on tagging and dynamic window management (however
|
||||
simpler than ion, wmii or larswm). It manages windows in
|
||||
tiling and floating modes. Either mode can be applied dynamically,
|
||||
depending on the application in use and the task performed.
|
||||
</li>
|
||||
<li>
|
||||
dwm don't distinguishes between layers, there is no floating or
|
||||
tiled layer. Wether the clients of currently selected tag are in
|
||||
tiled mode or not, you can re-arrange all clients on the fly.
|
||||
Popup- and fixed-size windows are treated floating, however.
|
||||
</li>
|
||||
<li>
|
||||
dwm is customized through editing its source code, that makes it
|
||||
extremely fast and secure - it does not process any input data
|
||||
which hasn't been known at compile time, except window title names
|
||||
and status text read from standard input. You don't have to learn
|
||||
Lua/sh/ruby or some weird configuration file format (like X
|
||||
resource files), beside C to customize it for your needs,
|
||||
you <b>only</b> have to learn C (at least editing header files).
|
||||
</li>
|
||||
<li>
|
||||
Because dwm is customized through editing its source code, it's
|
||||
pointless to make binary packages of it. This keeps its userbase
|
||||
small and elitist. No novices asking stupid questions.
|
||||
</li>
|
||||
<li>
|
||||
dwm uses 1-pixel borders to provide the maximum of screen real
|
||||
estate to clients. Small titlebars are only drawn in front of
|
||||
unfocused clients.
|
||||
</li>
|
||||
<li>
|
||||
dwm reads from standard input to print arbitrary status text (like
|
||||
the date, load, battery charge). That's much simpler than
|
||||
larsremote, wmiir and what not...
|
||||
</li>
|
||||
<li>
|
||||
It can be downloaded and distributed under the conditions
|
||||
of the <a href="http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm?f=f10eb1139362;file=LICENSE;style=raw">MIT/X Consortium license</a>.
|
||||
</li>
|
||||
<li>
|
||||
Optionally you can install <b>dmenu</b> to extend dwm with a wmii-alike menu.
|
||||
</li>
|
||||
</ul>
|
||||
<h4>Links</h4>
|
||||
<ul>
|
||||
<li><a href="http://10kloc.org/cgi-bin/man/man2html?query=dwm">Man page</a></li>
|
||||
<li><a href="http://10kloc.org/shots/dwm-20060810a.png">Screenshot of tiled mode</a> (20060810)</li>
|
||||
<li><a href="http://10kloc.org/shots/dwm-20060810b.png">Screenshotof floating mode</a> (20060810)</li>
|
||||
<li><a href="http://10kloc.org/download/poster.ps">A4 poster (PostScript)</a></li>
|
||||
<li>Mailing List: <a href="http://10kloc.org/cgi-bin/mailman/listinfo/dwm">dwm at wmii dot de</a> <a href="http://10kloc.org/pipermail/dwm/">(Archives)</a></li>
|
||||
<li>IRC channel: <code>#dwm</code> at <code>irc.oftc.net</code></li>
|
||||
</ul>
|
||||
<h3>Download</h3>
|
||||
<ul>
|
||||
<li><a href="http://10kloc.org/download/dwm-0.8.tar.gz">dwm 0.8</a> (14kb) (20060810)</li>
|
||||
<li><a href="http://10kloc.org/download/dmenu-0.3.tar.gz">dmenu 0.3</a> (7kb) (20060810)</li>
|
||||
</ul>
|
||||
<h3>Development</h3>
|
||||
<p>
|
||||
dwm is actively developed in parallel to wmii. You can <a href="http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm">browse</a> its source code repository or get a copy using <a href="http://www.selenic.com/mercurial/">Mercurial</a> with following command:
|
||||
</p>
|
||||
<p>
|
||||
<code>hg clone http://10kloc.org/cgi-bin/hgwebdir.cgi/dwm</code>
|
||||
</p>
|
||||
<p>
|
||||
<code>hg clone http://10kloc.org/cgi-bin/hgwebdir.cgi/dmenu</code>
|
||||
</p>
|
||||
<h3>Miscellaneous</h3>
|
||||
<p>
|
||||
You can purchase this <a href="https://www.spreadshirt.net/shop.php?op=article&article_id=3298632&view=403">tricot</a>
|
||||
if you like dwm and the dwm logo, which has been designed by Anselm.
|
||||
</p>
|
||||
<p><small>--Anselm</small></p>
|
||||
</body>
|
||||
</html>
|
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
|
374
event.c
374
event.c
@@ -1,374 +0,0 @@
|
||||
/*
|
||||
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
#include "dwm.h"
|
||||
#include <stdlib.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
/* static */
|
||||
|
||||
typedef struct {
|
||||
unsigned long mod;
|
||||
KeySym keysym;
|
||||
void (*func)(Arg *arg);
|
||||
Arg arg;
|
||||
} Key;
|
||||
|
||||
KEYS
|
||||
|
||||
#define CLEANMASK(mask) (mask & ~(NUMLOCKMASK | LockMask))
|
||||
|
||||
static void
|
||||
movemouse(Client *c)
|
||||
{
|
||||
int x1, y1, ocx, ocy, di;
|
||||
unsigned int dui;
|
||||
Window dummy;
|
||||
XEvent ev;
|
||||
|
||||
ocx = c->x;
|
||||
ocy = c->y;
|
||||
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
|
||||
None, cursor[CurMove], CurrentTime) != GrabSuccess)
|
||||
return;
|
||||
XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
|
||||
for(;;) {
|
||||
XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
|
||||
switch (ev.type) {
|
||||
default: break;
|
||||
case Expose:
|
||||
handler[Expose](&ev);
|
||||
break;
|
||||
case MotionNotify:
|
||||
XSync(dpy, False);
|
||||
c->x = ocx + (ev.xmotion.x - x1);
|
||||
c->y = ocy + (ev.xmotion.y - y1);
|
||||
resize(c, False, TopLeft);
|
||||
break;
|
||||
case ButtonRelease:
|
||||
XUngrabPointer(dpy, CurrentTime);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
resizemouse(Client *c)
|
||||
{
|
||||
int ocx, ocy;
|
||||
Corner sticky;
|
||||
XEvent ev;
|
||||
|
||||
ocx = c->x;
|
||||
ocy = c->y;
|
||||
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
|
||||
None, cursor[CurResize], CurrentTime) != GrabSuccess)
|
||||
return;
|
||||
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
|
||||
for(;;) {
|
||||
XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
|
||||
switch(ev.type) {
|
||||
default: break;
|
||||
case Expose:
|
||||
handler[Expose](&ev);
|
||||
break;
|
||||
case MotionNotify:
|
||||
XSync(dpy, False);
|
||||
c->w = abs(ocx - ev.xmotion.x);
|
||||
c->h = abs(ocy - ev.xmotion.y);
|
||||
c->x = (ocx <= ev.xmotion.x) ? ocx : ocx - c->w;
|
||||
c->y = (ocy <= ev.xmotion.y) ? ocy : ocy - c->h;
|
||||
if(ocx <= ev.xmotion.x)
|
||||
sticky = (ocy <= ev.xmotion.y) ? TopLeft : BotLeft;
|
||||
else
|
||||
sticky = (ocy <= ev.xmotion.y) ? TopRight : BotRight;
|
||||
resize(c, True, sticky);
|
||||
break;
|
||||
case ButtonRelease:
|
||||
XUngrabPointer(dpy, CurrentTime);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
buttonpress(XEvent *e)
|
||||
{
|
||||
int x;
|
||||
Arg a;
|
||||
Client *c;
|
||||
XButtonPressedEvent *ev = &e->xbutton;
|
||||
|
||||
if(barwin == ev->window) {
|
||||
switch(ev->button) {
|
||||
default:
|
||||
x = 0;
|
||||
for(a.i = 0; a.i < ntags; a.i++) {
|
||||
x += textw(tags[a.i]);
|
||||
if(ev->x < x) {
|
||||
view(&a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Button4:
|
||||
viewprev(&a);
|
||||
break;
|
||||
case Button5:
|
||||
viewnext(&a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if((c = getclient(ev->window))) {
|
||||
higher(c);
|
||||
focus(c);
|
||||
switch(ev->button) {
|
||||
default:
|
||||
break;
|
||||
case Button1:
|
||||
if(!c->ismax && (arrange == dofloat || c->isfloat))
|
||||
movemouse(c);
|
||||
break;
|
||||
case Button2:
|
||||
if(!c->ismax && arrange != dofloat && !c->isfloat)
|
||||
zoom(NULL);
|
||||
break;
|
||||
case Button3:
|
||||
if(!c->ismax && (arrange == dofloat || c->isfloat))
|
||||
resizemouse(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
configurerequest(XEvent *e)
|
||||
{
|
||||
Client *c;
|
||||
XConfigureRequestEvent *ev = &e->xconfigurerequest;
|
||||
XEvent synev;
|
||||
XWindowChanges wc;
|
||||
unsigned long newmask;
|
||||
|
||||
if((c = getclient(ev->window))) {
|
||||
gravitate(c, True);
|
||||
if(ev->value_mask & CWX)
|
||||
c->x = ev->x;
|
||||
if(ev->value_mask & CWY)
|
||||
c->y = ev->y;
|
||||
if(ev->value_mask & CWWidth)
|
||||
c->w = ev->width;
|
||||
if(ev->value_mask & CWHeight)
|
||||
c->h = ev->height;
|
||||
if(ev->value_mask & CWBorderWidth)
|
||||
c->border = ev->border_width;
|
||||
gravitate(c, False);
|
||||
wc.x = c->x;
|
||||
wc.y = c->y;
|
||||
wc.width = c->w;
|
||||
wc.height = c->h;
|
||||
newmask = ev->value_mask & (~(CWSibling | CWStackMode | CWBorderWidth));
|
||||
if(newmask)
|
||||
XConfigureWindow(dpy, c->win, newmask, &wc);
|
||||
else {
|
||||
synev.type = ConfigureNotify;
|
||||
synev.xconfigure.display = dpy;
|
||||
synev.xconfigure.event = c->win;
|
||||
synev.xconfigure.window = c->win;
|
||||
synev.xconfigure.x = c->x;
|
||||
synev.xconfigure.y = c->y;
|
||||
synev.xconfigure.width = c->w;
|
||||
synev.xconfigure.height = c->h;
|
||||
synev.xconfigure.border_width = c->border;
|
||||
synev.xconfigure.above = None;
|
||||
/* Send synthetic ConfigureNotify */
|
||||
XSendEvent(dpy, c->win, True, NoEventMask, &synev);
|
||||
}
|
||||
XSync(dpy, False);
|
||||
if(c->isfloat)
|
||||
resize(c, False, TopLeft);
|
||||
else
|
||||
arrange(NULL);
|
||||
}
|
||||
else {
|
||||
wc.x = ev->x;
|
||||
wc.y = ev->y;
|
||||
wc.width = ev->width;
|
||||
wc.height = ev->height;
|
||||
wc.border_width = ev->border_width;
|
||||
wc.sibling = ev->above;
|
||||
wc.stack_mode = ev->detail;
|
||||
XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
|
||||
XSync(dpy, False);
|
||||
}
|
||||
}
|
||||
|
||||
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)) || (c = getctitle(ev->window)))
|
||||
focus(c);
|
||||
else if(ev->window == root) {
|
||||
issel = True;
|
||||
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
|
||||
drawall();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
expose(XEvent *e)
|
||||
{
|
||||
Client *c;
|
||||
XExposeEvent *ev = &e->xexpose;
|
||||
|
||||
if(ev->count == 0) {
|
||||
if(barwin == ev->window)
|
||||
drawstatus();
|
||||
else if((c = getctitle(ev->window)))
|
||||
drawtitle(c);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
keypress(XEvent *e)
|
||||
{
|
||||
static unsigned int len = sizeof(key) / sizeof(key[0]);
|
||||
unsigned int i;
|
||||
KeySym keysym;
|
||||
XKeyEvent *ev = &e->xkey;
|
||||
|
||||
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
|
||||
for(i = 0; i < len; i++)
|
||||
if(keysym == key[i].keysym &&
|
||||
CLEANMASK(key[i].mod) == CLEANMASK(ev->state)) {
|
||||
if(key[i].func)
|
||||
key[i].func(&key[i].arg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
leavenotify(XEvent *e)
|
||||
{
|
||||
XCrossingEvent *ev = &e->xcrossing;
|
||||
|
||||
if((ev->window == root) && !ev->same_screen) {
|
||||
issel = False;
|
||||
drawall();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
maprequest(XEvent *e)
|
||||
{
|
||||
static XWindowAttributes wa;
|
||||
XMapRequestEvent *ev = &e->xmaprequest;
|
||||
|
||||
if(!XGetWindowAttributes(dpy, ev->window, &wa))
|
||||
return;
|
||||
|
||||
if(wa.override_redirect) {
|
||||
XSelectInput(dpy, ev->window,
|
||||
(StructureNotifyMask | PropertyChangeMask));
|
||||
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))) {
|
||||
if(ev->atom == wmatom[WMProtocols]) {
|
||||
c->proto = getproto(c->win);
|
||||
return;
|
||||
}
|
||||
switch (ev->atom) {
|
||||
default: break;
|
||||
case XA_WM_TRANSIENT_FOR:
|
||||
XGetTransientForHint(dpy, c->win, &trans);
|
||||
if(!c->isfloat && (c->isfloat = (trans != 0)))
|
||||
arrange(NULL);
|
||||
break;
|
||||
case XA_WM_NORMAL_HINTS:
|
||||
setsize(c);
|
||||
break;
|
||||
}
|
||||
if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
|
||||
settitle(c);
|
||||
drawtitle(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
[DestroyNotify] = destroynotify,
|
||||
[EnterNotify] = enternotify,
|
||||
[LeaveNotify] = leavenotify,
|
||||
[Expose] = expose,
|
||||
[KeyPress] = keypress,
|
||||
[MapRequest] = maprequest,
|
||||
[PropertyNotify] = propertynotify,
|
||||
[UnmapNotify] = unmapnotify
|
||||
};
|
||||
|
||||
void
|
||||
grabkeys()
|
||||
{
|
||||
static unsigned int len = sizeof(key) / sizeof(key[0]);
|
||||
unsigned int i;
|
||||
KeyCode code;
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
code = XKeysymToKeycode(dpy, key[i].keysym);
|
||||
XGrabKey(dpy, code, key[i].mod, root, True,
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, key[i].mod | LockMask, root, True,
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, key[i].mod | NUMLOCKMASK, root, True,
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, key[i].mod | NUMLOCKMASK | LockMask, root, True,
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
}
|
||||
}
|
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_ */
|
291
main.c
291
main.c
@@ -1,291 +0,0 @@
|
||||
/*
|
||||
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
|
||||
#include "dwm.h"
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/select.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xproto.h>
|
||||
|
||||
/* static */
|
||||
|
||||
static int (*xerrorxlib)(Display *, XErrorEvent *);
|
||||
static Bool otherwm;
|
||||
|
||||
static void
|
||||
cleanup()
|
||||
{
|
||||
while(sel) {
|
||||
resize(sel, True, TopLeft);
|
||||
unmanage(sel);
|
||||
}
|
||||
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
|
||||
}
|
||||
|
||||
static void
|
||||
scan()
|
||||
{
|
||||
unsigned int i, num;
|
||||
Window *wins, d1, d2;
|
||||
XWindowAttributes wa;
|
||||
|
||||
if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
|
||||
for(i = 0; i < num; i++) {
|
||||
if(!XGetWindowAttributes(dpy, wins[i], &wa))
|
||||
continue;
|
||||
if(wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
|
||||
continue;
|
||||
if(wa.map_state == IsViewable)
|
||||
manage(wins[i], &wa);
|
||||
}
|
||||
}
|
||||
if(wins)
|
||||
XFree(wins);
|
||||
}
|
||||
|
||||
static int
|
||||
win_property(Window w, Atom a, Atom t, long l, unsigned char **prop)
|
||||
{
|
||||
int status, format;
|
||||
unsigned long res, extra;
|
||||
Atom real;
|
||||
|
||||
status = XGetWindowProperty(dpy, w, a, 0L, l, False, t, &real, &format,
|
||||
&res, &extra, prop);
|
||||
|
||||
if(status != Success || *prop == 0) {
|
||||
return 0;
|
||||
}
|
||||
if(res == 0) {
|
||||
free((void *) *prop);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Startup Error handler to check if another window manager
|
||||
* is already running.
|
||||
*/
|
||||
static int
|
||||
xerrorstart(Display *dsply, XErrorEvent *ee)
|
||||
{
|
||||
otherwm = True;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* extern */
|
||||
|
||||
char stext[1024];
|
||||
int tsel = DEFTAG;
|
||||
int screen, sx, sy, sw, sh, bx, by, bw, bh, mw;
|
||||
unsigned int ntags;
|
||||
Atom wmatom[WMLast], netatom[NetLast];
|
||||
Bool running = True;
|
||||
Bool issel = True;
|
||||
Client *clients = NULL;
|
||||
Client *sel = NULL;
|
||||
Cursor cursor[CurLast];
|
||||
Display *dpy;
|
||||
DC dc = {0};
|
||||
Window root, barwin;
|
||||
|
||||
int
|
||||
getproto(Window w)
|
||||
{
|
||||
int protos = 0;
|
||||
int i;
|
||||
long res;
|
||||
Atom *protocols;
|
||||
|
||||
res = win_property(w, wmatom[WMProtocols], XA_ATOM, 20L,
|
||||
((unsigned char **)&protocols));
|
||||
if(res <= 0) {
|
||||
return protos;
|
||||
}
|
||||
for(i = 0; i < res; i++) {
|
||||
if(protocols[i] == wmatom[WMDelete])
|
||||
protos |= PROTODELWIN;
|
||||
}
|
||||
free((char *) protocols);
|
||||
return protos;
|
||||
}
|
||||
|
||||
void
|
||||
sendevent(Window w, Atom a, long value)
|
||||
{
|
||||
XEvent e;
|
||||
|
||||
e.type = ClientMessage;
|
||||
e.xclient.window = w;
|
||||
e.xclient.message_type = a;
|
||||
e.xclient.format = 32;
|
||||
e.xclient.data.l[0] = value;
|
||||
e.xclient.data.l[1] = CurrentTime;
|
||||
XSendEvent(dpy, w, False, NoEventMask, &e);
|
||||
XSync(dpy, False);
|
||||
}
|
||||
|
||||
void
|
||||
quit(Arg *arg)
|
||||
{
|
||||
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 calls 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))
|
||||
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[])
|
||||
{
|
||||
int i;
|
||||
unsigned int mask;
|
||||
fd_set rd;
|
||||
Bool readin = True;
|
||||
Window w;
|
||||
XEvent ev;
|
||||
XSetWindowAttributes wa;
|
||||
|
||||
if(argc == 2 && !strncmp("-v", argv[1], 3)) {
|
||||
fputs("dwm-"VERSION", (C)opyright MMVI Anselm R. Garbe\n", stdout);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
else if(argc != 1)
|
||||
eprint("usage: dwm [-v]\n");
|
||||
|
||||
dpy = XOpenDisplay(0);
|
||||
if(!dpy)
|
||||
eprint("dwm: cannot open display\n");
|
||||
|
||||
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");
|
||||
|
||||
XSetErrorHandler(NULL);
|
||||
xerrorxlib = XSetErrorHandler(xerror);
|
||||
|
||||
/* init atoms */
|
||||
wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
|
||||
wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
|
||||
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
|
||||
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
|
||||
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
|
||||
PropModeReplace, (unsigned char *) netatom, NetLast);
|
||||
|
||||
/* init cursors */
|
||||
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
|
||||
cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
|
||||
cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
|
||||
|
||||
grabkeys();
|
||||
initrregs();
|
||||
|
||||
for(ntags = 0; tags[ntags]; ntags++);
|
||||
|
||||
/* style */
|
||||
dc.bg = getcolor(BGCOLOR);
|
||||
dc.fg = getcolor(FGCOLOR);
|
||||
dc.border = getcolor(BORDERCOLOR);
|
||||
setfont(FONT);
|
||||
|
||||
sx = sy = 0;
|
||||
sw = DisplayWidth(dpy, screen);
|
||||
sh = DisplayHeight(dpy, screen);
|
||||
mw = (sw * MASTERW) / 100;
|
||||
|
||||
wa.override_redirect = 1;
|
||||
wa.background_pixmap = ParentRelative;
|
||||
wa.event_mask = ButtonPressMask | ExposureMask;
|
||||
|
||||
bx = by = 0;
|
||||
bw = sw;
|
||||
dc.h = bh = dc.font.height + 4;
|
||||
barwin = XCreateWindow(dpy, root, bx, by, bw, bh, 0, DefaultDepth(dpy, screen),
|
||||
CopyFromParent, DefaultVisual(dpy, screen),
|
||||
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
|
||||
XDefineCursor(dpy, barwin, cursor[CurNormal]);
|
||||
XMapRaised(dpy, barwin);
|
||||
|
||||
dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
|
||||
dc.gc = XCreateGC(dpy, root, 0, 0);
|
||||
|
||||
strcpy(stext, "dwm-"VERSION);
|
||||
drawstatus();
|
||||
|
||||
issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
|
||||
|
||||
wa.event_mask = SubstructureRedirectMask | EnterWindowMask | LeaveWindowMask;
|
||||
wa.cursor = cursor[CurNormal];
|
||||
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
|
||||
|
||||
scan();
|
||||
|
||||
/* main event loop, also reads status text from stdin */
|
||||
XSync(dpy, False);
|
||||
while(running) {
|
||||
FD_ZERO(&rd);
|
||||
if(readin)
|
||||
FD_SET(STDIN_FILENO, &rd);
|
||||
FD_SET(ConnectionNumber(dpy), &rd);
|
||||
|
||||
i = select(ConnectionNumber(dpy) + 1, &rd, 0, 0, 0);
|
||||
if(i == -1 && errno == EINTR)
|
||||
continue;
|
||||
if(i < 0)
|
||||
eprint("select failed\n");
|
||||
else if(i > 0) {
|
||||
if(FD_ISSET(ConnectionNumber(dpy), &rd)) {
|
||||
while(XPending(dpy)) {
|
||||
XNextEvent(dpy, &ev);
|
||||
if(handler[ev.type])
|
||||
(handler[ev.type])(&ev); /* call handler */
|
||||
}
|
||||
}
|
||||
if(readin && FD_ISSET(STDIN_FILENO, &rd)) {
|
||||
readin = NULL != fgets(stext, sizeof(stext), stdin);
|
||||
if(readin)
|
||||
stext[strlen(stext) - 1] = 0;
|
||||
else
|
||||
strcpy(stext, "broken pipe");
|
||||
drawstatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
250
tag.c
250
tag.c
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
#include "dwm.h"
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
const char *clpattern;
|
||||
const char *tpattern;
|
||||
Bool isfloat;
|
||||
} Rule;
|
||||
|
||||
typedef struct {
|
||||
regex_t *clregex;
|
||||
regex_t *tregex;
|
||||
} RReg;
|
||||
|
||||
/* static */
|
||||
|
||||
TAGS
|
||||
RULES
|
||||
|
||||
static RReg *rreg = NULL;
|
||||
static unsigned int len = 0;
|
||||
|
||||
void (*arrange)(Arg *) = DEFMODE;
|
||||
|
||||
/* extern */
|
||||
|
||||
void
|
||||
appendtag(Arg *arg)
|
||||
{
|
||||
if(!sel)
|
||||
return;
|
||||
|
||||
sel->tags[arg->i] = True;
|
||||
arrange(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
dofloat(Arg *arg)
|
||||
{
|
||||
Client *c;
|
||||
|
||||
for(c = clients; c; c = c->next) {
|
||||
c->ismax = False;
|
||||
if(c->tags[tsel]) {
|
||||
resize(c, True, TopLeft);
|
||||
}
|
||||
else
|
||||
ban(c);
|
||||
}
|
||||
if((sel = getnext(clients))) {
|
||||
higher(sel);
|
||||
focus(sel);
|
||||
}
|
||||
else
|
||||
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
|
||||
drawall();
|
||||
}
|
||||
|
||||
void
|
||||
dotile(Arg *arg)
|
||||
{
|
||||
int n, i, w, h;
|
||||
Client *c;
|
||||
|
||||
w = sw - mw;
|
||||
for(n = 0, c = clients; c; c = c->next)
|
||||
if(c->tags[tsel] && !c->isfloat)
|
||||
n++;
|
||||
|
||||
if(n > 1)
|
||||
h = (sh - bh) / (n - 1);
|
||||
else
|
||||
h = sh - bh;
|
||||
|
||||
for(i = 0, c = clients; c; c = c->next) {
|
||||
c->ismax = False;
|
||||
if(c->tags[tsel]) {
|
||||
if(c->isfloat) {
|
||||
higher(c);
|
||||
resize(c, True, TopLeft);
|
||||
continue;
|
||||
}
|
||||
if(n == 1) {
|
||||
c->x = sx;
|
||||
c->y = sy + bh;
|
||||
c->w = sw - 2;
|
||||
c->h = sh - 2 - bh;
|
||||
}
|
||||
else if(i == 0) {
|
||||
c->x = sx;
|
||||
c->y = sy + bh;
|
||||
c->w = mw - 2;
|
||||
c->h = sh - 2 - bh;
|
||||
}
|
||||
else if(h > bh) {
|
||||
c->x = sx + mw;
|
||||
c->y = sy + (i - 1) * h + bh;
|
||||
c->w = w - 2;
|
||||
if(i + 1 == n)
|
||||
c->h = sh - c->y - 2;
|
||||
else
|
||||
c->h = h - 2;
|
||||
}
|
||||
else { /* fallback if h < bh */
|
||||
c->x = sx + mw;
|
||||
c->y = sy + bh;
|
||||
c->w = w - 2;
|
||||
c->h = sh - 2 - bh;
|
||||
}
|
||||
resize(c, False, TopLeft);
|
||||
i++;
|
||||
}
|
||||
else
|
||||
ban(c);
|
||||
}
|
||||
if((sel = getnext(clients))) {
|
||||
higher(sel);
|
||||
focus(sel);
|
||||
}
|
||||
else
|
||||
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
|
||||
drawall();
|
||||
}
|
||||
|
||||
Client *
|
||||
getnext(Client *c)
|
||||
{
|
||||
for(; c && !c->tags[tsel]; c = c->next);
|
||||
return c;
|
||||
}
|
||||
|
||||
Client *
|
||||
getprev(Client *c)
|
||||
{
|
||||
for(; c && !c->tags[tsel]; c = c->prev);
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
initrregs()
|
||||
{
|
||||
unsigned int i;
|
||||
regex_t *reg;
|
||||
|
||||
if(rreg)
|
||||
return;
|
||||
len = sizeof(rule) / sizeof(rule[0]);
|
||||
rreg = emallocz(len * sizeof(RReg));
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
if(rule[i].clpattern) {
|
||||
reg = emallocz(sizeof(regex_t));
|
||||
if(regcomp(reg, rule[i].clpattern, 0))
|
||||
free(reg);
|
||||
else
|
||||
rreg[i].clregex = reg;
|
||||
}
|
||||
if(rule[i].tpattern) {
|
||||
reg = emallocz(sizeof(regex_t));
|
||||
if(regcomp(reg, rule[i].tpattern, 0))
|
||||
free(reg);
|
||||
else
|
||||
rreg[i].tregex = reg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
replacetag(Arg *arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(!sel)
|
||||
return;
|
||||
|
||||
for(i = 0; i < ntags; i++)
|
||||
sel->tags[i] = False;
|
||||
appendtag(arg);
|
||||
}
|
||||
|
||||
void
|
||||
settags(Client *c)
|
||||
{
|
||||
char classinst[256];
|
||||
unsigned int i, j;
|
||||
regmatch_t tmp;
|
||||
Bool matched = False;
|
||||
XClassHint ch;
|
||||
|
||||
if(XGetClassHint(dpy, c->win, &ch)) {
|
||||
snprintf(classinst, sizeof(classinst), "%s:%s",
|
||||
ch.res_class ? ch.res_class : "",
|
||||
ch.res_name ? ch.res_name : "");
|
||||
for(i = 0; !matched && i < len; i++)
|
||||
if(rreg[i].clregex && !regexec(rreg[i].clregex, classinst, 1, &tmp, 0)) {
|
||||
c->isfloat = rule[i].isfloat;
|
||||
for(j = 0; rreg[i].tregex && j < ntags; j++) {
|
||||
if(!regexec(rreg[i].tregex, tags[j], 1, &tmp, 0)) {
|
||||
matched = True;
|
||||
c->tags[j] = True;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ch.res_class)
|
||||
XFree(ch.res_class);
|
||||
if(ch.res_name)
|
||||
XFree(ch.res_name);
|
||||
}
|
||||
if(!matched)
|
||||
c->tags[tsel] = True;
|
||||
}
|
||||
|
||||
void
|
||||
togglemode(Arg *arg)
|
||||
{
|
||||
arrange = arrange == dofloat ? dotile : dofloat;
|
||||
arrange(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
view(Arg *arg)
|
||||
{
|
||||
tsel = arg->i;
|
||||
arrange(NULL);
|
||||
drawall();
|
||||
}
|
||||
|
||||
void
|
||||
viewnext(Arg *arg)
|
||||
{
|
||||
arg->i = (tsel < ntags-1) ? tsel+1 : 0;
|
||||
view(arg);
|
||||
}
|
||||
|
||||
void
|
||||
viewprev(Arg *arg)
|
||||
{
|
||||
arg->i = (tsel > 0) ? tsel-1 : ntags-1;
|
||||
view(arg);
|
||||
}
|
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);
|
||||
}
|
201
util.c
201
util.c
@@ -1,65 +1,170 @@
|
||||
/*
|
||||
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
#include "dwm.h"
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
#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>
|
||||
|
||||
/* static */
|
||||
|
||||
static void
|
||||
bad_malloc(unsigned int size)
|
||||
{
|
||||
eprint("fatal: could not malloc() %u bytes\n", size);
|
||||
}
|
||||
|
||||
/* extern */
|
||||
#include "util.h"
|
||||
|
||||
void *
|
||||
emallocz(unsigned int size)
|
||||
ecalloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *res = calloc(1, size);
|
||||
void *p;
|
||||
|
||||
if(!res)
|
||||
bad_malloc(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);
|
||||
}
|
||||
|
||||
void
|
||||
spawn(Arg *arg)
|
||||
{
|
||||
static char *shell = NULL;
|
||||
|
||||
if(!shell && !(shell = getenv("SHELL")))
|
||||
shell = "/bin/sh";
|
||||
|
||||
if(!arg->cmd)
|
||||
return;
|
||||
if(fork() == 0) {
|
||||
if(fork() == 0) {
|
||||
if(dpy)
|
||||
close(ConnectionNumber(dpy));
|
||||
setsid();
|
||||
execl(shell, shell, "-c", arg->cmd, NULL);
|
||||
fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg->cmd);
|
||||
perror(" failed");
|
||||
}
|
||||
exit(0);
|
||||
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
|
||||
fputc(' ', stderr);
|
||||
perror(NULL);
|
||||
} else {
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
wait(0);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
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++] = '/';
|
||||
}
|
||||
|
||||
(*normal)[newlen++] = '\0';
|
||||
|
||||
// Copy remaining path
|
||||
strcat(*normal, walk);
|
||||
newlen += strlen(walk);
|
||||
|
||||
*normal = (char *)realloc(*normal, newlen * sizeof(char));
|
||||
|
||||
return 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