Compare commits
752 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
0f594732b0 | ||
|
312411fc70 | ||
|
70add904c4 | ||
|
5ca4823128 | ||
|
0500213086 | ||
|
b0fca6eaf0 | ||
|
4988e00b1d | ||
|
0fad7a0bb0 | ||
|
727f1b54cd | ||
|
c80457be02 | ||
|
4a42c5ed20 | ||
|
bd6d6e7f33 | ||
|
027140b731 | ||
|
ea10592ad3 | ||
|
9b54342baa | ||
|
8f9887b0c9 | ||
|
fa39df4731 | ||
|
f7249bd331 | ||
|
6934e7aa2b | ||
|
8bbeee2041 | ||
|
7a24e564f4 | ||
|
4b5b8a7630 | ||
|
5b1375141b | ||
|
4af9410dc2 | ||
|
a6315b0af4 | ||
|
cac59fefec | ||
|
1ac2fc3f7e | ||
|
cf6a1716ae | ||
|
10d7219807 | ||
|
838ed87d6f | ||
|
76b82fdde7 | ||
|
c5fd577181 | ||
|
fbd6354393 | ||
|
fd8d8e122e | ||
|
1c9d56998d | ||
|
242e06b242 | ||
|
25e72949a1 | ||
|
259dcd838e | ||
|
ef33198e8f | ||
|
604eb21a7e | ||
|
92a0dd164e | ||
|
b9b8e6220f | ||
|
a95df6b57e | ||
|
9642311ac2 | ||
|
98e99cd03d | ||
|
8210a1d7ac | ||
|
d105c7403c | ||
|
00ee1cf98e | ||
|
7dd0f76e5a | ||
|
17ed4fc04c | ||
|
6a8824253c | ||
|
eb42adc4c0 | ||
|
09dbcabcc7 | ||
|
72c7818ae6 | ||
|
1ea47950f4 | ||
|
8d6c18076f | ||
|
9c5a37a797 | ||
|
ca85455a8e | ||
|
28f6c2df59 | ||
|
83ab3ae0af | ||
|
b672118f92 | ||
|
aac90d9279 | ||
|
66586c38f5 | ||
|
82c67e61a9 | ||
|
e45e606fbd | ||
|
688fe5c147 | ||
|
a3b75559b3 | ||
|
df4f222482 | ||
|
3b663f4afc | ||
|
f634b9e61a | ||
|
bdb296a83c | ||
|
4fa63104c9 | ||
|
a437e44a6a | ||
|
cae937c51b | ||
|
8162fae377 | ||
|
c5786be695 | ||
|
1b1ecf77e0 | ||
|
883463f9dd | ||
|
3e7325af57 | ||
|
946ed1f32a | ||
|
4eff224a7f | ||
|
c86db7bbb0 | ||
|
272d904870 | ||
|
01e3da4d51 | ||
|
33015546c6 | ||
|
83d88fa564 | ||
|
11dfb8397b | ||
|
f4045ab8d0 | ||
|
fa12efdd2a | ||
|
bf611fbbf3 | ||
|
5afc4dc42e | ||
|
50348a3ddb | ||
|
279ec1c291 | ||
|
1006663b6e | ||
|
b2a18aa80a | ||
|
d21a6b12b8 | ||
|
912e7ba82d | ||
|
92744b5b9a | ||
|
c5feee1e35 | ||
|
1840a907a8 | ||
|
682b30fba8 | ||
|
12d9901472 | ||
|
15f942000e | ||
|
520e91238f | ||
|
0c56be74a3 | ||
|
069faa4027 | ||
|
c30dfe92ee | ||
|
d85ae306c5 | ||
|
197f880790 | ||
|
3b4aabe04c | ||
|
c5ec079c6f | ||
|
4aec237ec0 | ||
|
39df1f4dbf | ||
|
77cf651825 | ||
|
c7b72790bd | ||
|
3fa6db1e7a | ||
|
d361fcbd85 | ||
|
df9d830117 | ||
|
118d4e1001 | ||
|
511eea71c6 | ||
|
01ff5fdf6a | ||
|
0bf9ceb53b | ||
|
4fdc0d55e4 | ||
|
8b37e81374 | ||
|
fd1d4e288e | ||
|
4b4971c06f | ||
|
83a334f97d | ||
|
9a09eac79b | ||
|
2d552fbaa2 | ||
|
ea72831541 | ||
|
a399f98c68 | ||
|
3e00d7dde7 | ||
|
d5bc3eb1fa | ||
|
99e9cb5107 | ||
|
f36c625e37 | ||
|
2e3dc17a7e | ||
|
b2717cf7fd | ||
|
3d82d199f0 | ||
|
a05da63d85 | ||
|
5b736a4a66 | ||
|
fa6ee51367 | ||
|
b0a70f63e3 | ||
|
d597ae41b9 | ||
|
640d161851 | ||
|
0e86808e59 | ||
|
2b520571e8 | ||
|
5dd2c27b63 | ||
|
4ae89e1f22 | ||
|
51ffd7fa6f | ||
|
ae50f8614d | ||
|
9f5a57ff45 | ||
|
4141e67550 | ||
|
be2dfa36ef | ||
|
1fa4b7d79b | ||
|
592b4a709c | ||
|
09bb5658b7 | ||
|
ab0a3268e0 | ||
|
c8873b958d | ||
|
60571cd5cc | ||
|
5edfa627b4 | ||
|
95959789b7 | ||
|
8c02b3c267 | ||
|
5b7057c479 | ||
|
37e1411e8d | ||
|
5489682799 | ||
|
e989a0bcff | ||
|
8a5f9bbb39 | ||
|
3b9b5346b8 | ||
|
8ec3dc4c09 | ||
|
cc7c117fe7 | ||
|
1c221240d0 | ||
|
c1afc82a4c | ||
|
f3a9f9ec45 | ||
|
10e631053a | ||
|
46c6efeab3 | ||
|
68ee4dda5e | ||
|
743e98f0c0 | ||
|
e673220340 | ||
|
9c38b0fdbe | ||
|
60b663e276 | ||
|
01560c9d7c | ||
|
3a1afb53fd | ||
|
23a8f06594 | ||
|
70468857da | ||
|
87699575e1 | ||
|
33e513d489 | ||
|
6e6c61b9e8 | ||
|
a9d87bd666 | ||
|
7df9b01d48 | ||
|
256db08aed | ||
|
73d09953e8 | ||
|
fcff2dcac2 | ||
|
3cc2028def | ||
|
9b6ae4f77b | ||
|
bc86afea7e | ||
|
6edfdd63a1 | ||
|
04b40ea2ec | ||
|
55ceca4cdd | ||
|
10e8af00d6 | ||
|
ad711ef421 | ||
|
ae638d997d | ||
|
141cd09bd3 | ||
|
0243271544 | ||
|
729b47d46d | ||
|
84227eb587 | ||
|
daed75219f | ||
|
ec672b1ab9 | ||
|
963816b9a6 | ||
|
534fdb5a37 | ||
|
682865632f | ||
|
76610d9fb0 | ||
|
57371b93a0 | ||
|
33a5c8ce32 | ||
|
a0d15a0b7b | ||
|
cd942ad12d | ||
|
daf5fad190 | ||
|
4beac91cbd | ||
|
391f1ae838 | ||
|
381cb2d833 | ||
|
a0be3de0e8 | ||
|
3e543d2ce8 | ||
|
735e3c6c56 | ||
|
b16fb9770c | ||
|
f2b6ebbf54 | ||
|
fe19754887 | ||
|
72bce7efd5 | ||
|
99088eaed8 | ||
|
2da3cfb422 | ||
|
e2efecc24e | ||
|
8a4548e430 | ||
|
a5f58a3126 | ||
|
077494ee85 | ||
|
752604cfe9 | ||
|
3c758db95c | ||
|
7c68236a51 | ||
|
4c3b035162 | ||
|
f17f8b219c | ||
|
e8374e0792 | ||
|
77b134e23b | ||
|
87db950189 | ||
|
5bae7f150b | ||
|
83a5395eaa | ||
|
d03fa94c2c | ||
|
511e9ccdd1 | ||
|
3132f0275e | ||
|
1797319a07 | ||
|
5979ceb56b | ||
|
672bf1f867 | ||
|
33e933e2a0 | ||
|
341fb4497f | ||
|
cbaac6deaf | ||
|
3b6bcd6ddc | ||
|
e6fc9873b5 | ||
|
db1f5cd137 | ||
|
928d1dd38a | ||
|
faa157e162 | ||
|
7f624d2236 | ||
|
f7fb7e7e49 | ||
|
efcbcd7297 | ||
|
043b859ea2 | ||
|
cf373d315e | ||
|
016da234d0 | ||
|
f642fb97df | ||
|
9b0993cc49 | ||
|
efccf25fcc | ||
|
8e15f91c24 | ||
|
300228b503 | ||
|
293e687389 | ||
|
da956c8a97 | ||
|
bd526822de | ||
|
f442f435d3 | ||
|
bc6b0880dd | ||
|
ed6c701144 | ||
|
45c4898423 | ||
|
a770a88e09 | ||
|
1f64668953 | ||
|
13bc7e1e14 | ||
|
7486576fa7 | ||
|
f85c6416c6 | ||
|
e728e56cbc | ||
|
9ff83f4aa9 | ||
|
3247d18a7c | ||
|
a443902abc | ||
|
b03f41efec | ||
|
648f824b9e | ||
|
22138ac259 | ||
|
19fb13e6cf | ||
|
ede1e63f69 | ||
|
cc98594c3a | ||
|
0502c3f62b | ||
|
0a6e83005f | ||
|
e894d5e964 | ||
|
8bb75a223d | ||
|
6247a6b537 | ||
|
2fa57f2dc4 | ||
|
e58fd3bfb0 | ||
|
d7ea1b7785 | ||
|
4d6f96f74f | ||
|
8ff9410d2c | ||
|
718afe271e | ||
|
1f43a5c859 | ||
|
9c5dd59d4b | ||
|
d16c6aa1db | ||
|
ac11771348 | ||
|
f2dc48d92f | ||
|
e4d09aa3a9 | ||
|
c338acbb7d | ||
|
95782de966 | ||
|
3ba3d20ad3 | ||
|
1d70962892 | ||
|
918d8340af | ||
|
4f7113972e | ||
|
8121e66f34 | ||
|
784c0b5ccb | ||
|
eef207ce0a | ||
|
4dd2b5902e | ||
|
cff0123ce6 | ||
|
8a68199a0c | ||
|
e09addf8de | ||
|
315f16d501 | ||
|
7f09646ab8 | ||
|
0b924f541c | ||
|
4778afe2e6 | ||
|
fa022901cf | ||
|
4a8b13ea4f | ||
|
8cf2ca1966 | ||
|
fabc30df52 | ||
|
d6de248b0d | ||
|
c1e21719a2 | ||
|
def5fcb212 | ||
|
65f04f265c | ||
|
6d21014a50 | ||
|
20a465f69d | ||
|
fb15b7aa2a | ||
|
6e5804b53d | ||
|
e0e3c4c6ae | ||
|
b98e0876d3 | ||
|
236150b3c5 | ||
|
d1340bd1d8 | ||
|
28ce0e0f80 | ||
|
a9c7a0830f | ||
|
785d062887 | ||
|
1360677478 | ||
|
14ab0ecc5e | ||
|
9cb3bf1cac | ||
|
b15be9c77d | ||
|
d5ef10abf4 | ||
|
172ee1cada | ||
|
738530e62e | ||
|
069a21a34e | ||
|
2031af82fa | ||
|
d0a6fa7aa6 | ||
|
648ac8a00b | ||
|
43c75f17eb | ||
|
1b5444494d | ||
|
3eaf35f1e2 | ||
|
2566d81884 | ||
|
1f5fd7e64a | ||
|
908bec1564 | ||
|
89f795da98 | ||
|
91fe58f8f2 | ||
|
77f44bfcab | ||
|
6c24dc0bb1 | ||
|
46ef6653be | ||
|
fb82f6bcd7 | ||
|
32aca88752 | ||
|
df0c014ba0 | ||
|
cb63398f07 | ||
|
2f278dc883 | ||
|
12ce06f39b | ||
|
a357fa3e0a | ||
|
a9d53a2252 | ||
|
b2590b58c5 | ||
|
9cd5b3587c | ||
|
8055b1c00a | ||
|
5de273a144 | ||
|
4842eb83b4 | ||
|
e6d10539af | ||
|
9e781040d9 | ||
|
a54f98c203 | ||
|
d677ac6f87 | ||
|
a9d7befc36 | ||
|
0e18da8467 | ||
|
18ee9ece9c | ||
|
38132ffaf5 | ||
|
a99f314106 | ||
|
9d7d5ec3c8 | ||
|
c7e85e26f7 | ||
|
1bae19ce85 | ||
|
f687105eff | ||
|
32283ed706 | ||
|
8412ffcc42 | ||
|
b6bf4afb48 | ||
|
e1b05f8eaf | ||
|
21b9e31bf4 | ||
|
1c388e52fb | ||
|
8c64a4bad7 | ||
|
1f46296ea0 | ||
|
809820921d | ||
|
90d0097716 | ||
|
b17381eb81 | ||
|
811429bfd4 | ||
|
ea2501d455 | ||
|
7ba2c31822 | ||
|
cef6aad28f | ||
|
89a3c90613 | ||
|
b16af45c4a | ||
|
1423707dbe | ||
|
121c6ac3ea | ||
|
722b846ac5 | ||
|
4168b8c17b | ||
|
1f71d5f5c1 | ||
|
bf75723f27 | ||
|
c62f0015ae | ||
|
9994b73ad0 | ||
|
d724556b7e | ||
|
7789caad39 | ||
|
3fb079a2a3 | ||
|
211353dc34 | ||
|
10e02076b1 | ||
|
5b6d54cae0 | ||
|
6967a31450 | ||
|
c31d9ef417 | ||
|
6b6b02c27a | ||
|
40ce17bbbd | ||
|
41e1147dfc | ||
|
9bc00897fc | ||
|
d6337146bb | ||
|
429cff340d | ||
|
af5f24929d | ||
|
c95845b148 | ||
|
82099fd1c0 | ||
|
155fe6f165 | ||
|
fefa55d406 | ||
|
098ac916a6 | ||
|
d0a224a491 | ||
|
5517cc506b | ||
|
0ac0f32671 | ||
|
b30c7125d7 | ||
|
3fd6c1b30e | ||
|
eaecf7db14 | ||
|
e08195d240 | ||
|
66acdfe2ad | ||
|
0ebb43c1a3 | ||
|
a54ab30160 | ||
|
df6ebe358b | ||
|
a60c7283e6 | ||
|
ebf258788e | ||
|
73b133d015 | ||
|
722d537a91 | ||
|
506d0c06e6 | ||
|
546a486bab | ||
|
db5d39a66f | ||
|
553232a3e4 | ||
|
addd3e7f1a | ||
|
a71207434c | ||
|
71c2ff3105 | ||
|
90f262aada | ||
|
2ff95bba3f | ||
|
ce17961aad | ||
|
6d67b84469 | ||
|
0d6eae0523 | ||
|
52684b7d90 | ||
|
4e42107d25 | ||
|
eea0a6a704 | ||
|
255272ea18 | ||
|
df80fbf706 | ||
|
25b9446949 | ||
|
7ad9116de8 | ||
|
62401d5b3f | ||
|
3775776a07 | ||
|
155ae3721c | ||
|
93fea89043 | ||
|
e419ef1873 | ||
|
3c907f7830 | ||
|
4daa5c0658 | ||
|
baef55da1d | ||
|
f8857e6072 | ||
|
c21a5a9340 | ||
|
2ead1fd221 | ||
|
49485ba36a | ||
|
fe23d2b639 | ||
|
9518cec833 | ||
|
23cd4c7998 | ||
|
0cb8fbe18e | ||
|
f21b6fe576 | ||
|
f91431465b | ||
|
a66cfe0fbe | ||
|
7173f0c9e7 | ||
|
abbe71d26d | ||
|
a2643e11a0 | ||
|
3ac0e7ead1 | ||
|
d693c44836 | ||
|
ca0833c9ed | ||
|
de9798fcf9 | ||
|
7e8c0b7f30 | ||
|
9eec4cb670 | ||
|
a8522db683 | ||
|
b9c58b6e75 | ||
|
3fe5280ce9 | ||
|
3381e2b55b | ||
|
7fbe05a250 | ||
|
31890026ea | ||
|
94c20a1863 | ||
|
3eeaea5be9 | ||
|
eed1361f39 | ||
|
7eeee2c94e | ||
|
fc72df8e58 | ||
|
0cfdde3d1a | ||
|
121d3a7213 | ||
|
4cdddcfe46 | ||
|
d0a4a0e0d8 | ||
|
1584679004 | ||
|
ba69652193 | ||
|
47874f09f4 | ||
|
60be4298e1 | ||
|
4c625ce673 | ||
|
064bdb06f1 | ||
|
fd35b35000 | ||
|
2ccd45a844 | ||
|
ff93820bbb | ||
|
071f6977df | ||
|
c8ae9a2e83 | ||
|
cee639d9df | ||
|
6be765b7a1 | ||
|
33a7b7bb6b | ||
|
15072831cf | ||
|
8562d38477 | ||
|
494b9415a1 | ||
|
b6a7fb9e91 | ||
|
3529fbc6d4 | ||
|
ed3a888fc2 | ||
|
a8ab1b1679 | ||
|
6e594e4416 | ||
|
19186de118 | ||
|
38911d6df4 | ||
|
37a84c5223 | ||
|
c19903eaf8 | ||
|
cc4ac52309 | ||
|
2549f0cc97 | ||
|
3374229118 | ||
|
2ba6bb69c4 | ||
|
db30ff63e6 | ||
|
a7e23d2f1e | ||
|
1753059b07 | ||
|
b0861b6709 | ||
|
7cf810b181 | ||
|
51b0da2c0d | ||
|
4f26ae70fd | ||
|
eeebbc0e7e | ||
|
635a02d83f | ||
|
85f7f69046 | ||
|
fe4737fb9d | ||
|
d7aed240db | ||
|
c98acaed62 | ||
|
67a5377b41 | ||
|
84e8d1810d | ||
|
ed411f53bd | ||
|
e4e84064f2 | ||
|
6a988d9276 | ||
|
d1ad490cda | ||
|
36d32973dd | ||
|
70b5e6df70 | ||
|
5e7925eaeb | ||
|
57a12476de | ||
|
601210878d | ||
|
22a86fd7a2 | ||
|
598bbd186b | ||
|
6ccc22194c | ||
|
ec092bd601 | ||
|
2bcc8d303f | ||
|
375e77e398 | ||
|
96365309de | ||
|
0acad88c3c | ||
|
57e76f91d9 | ||
|
0c446ec5f4 | ||
|
fa69de8ab6 | ||
|
05e4a3f1a8 | ||
|
a8a04c746b | ||
|
cddeec47a1 | ||
|
c7fbc30bfd | ||
|
1ed1ce9506 | ||
|
589f758d94 | ||
|
f15513309b | ||
|
99aa34db6e | ||
|
03ebad3cbf | ||
|
aaf35b9f1f | ||
|
62eadad20f | ||
|
0b215c5f24 | ||
|
a3309b51a2 | ||
|
cba1ade848 | ||
|
c77b60c910 | ||
|
c951c4f8a1 | ||
|
25964e5a2b | ||
|
2d40046f24 | ||
|
40201a760a | ||
|
a3b4923c42 | ||
|
1237732b97 | ||
|
1d2acbe193 | ||
|
1c73beaf9b | ||
|
8a2269272b | ||
|
d5bf15387a | ||
|
387127b12a | ||
|
41cf94faaa | ||
|
0623cfabc9 | ||
|
2755297670 | ||
|
7d49819b5e | ||
|
6aa2d123ae | ||
|
a3ca016d42 | ||
|
eeb78ef965 | ||
|
8427824719 | ||
|
d0229d6e1e | ||
|
56de72f357 | ||
|
02bfb2857e | ||
|
0237e39f74 | ||
|
47b087950d | ||
|
8bcccf9f0f | ||
|
4ed6b69b68 | ||
|
d2899a6c27 | ||
|
ed58cc4c31 | ||
|
3d09c6d526 | ||
|
70ebc3add3 | ||
|
a09103cd38 | ||
|
dbb8b294d6 | ||
|
1f6657f037 | ||
|
90e1411315 | ||
|
d7a48cf478 | ||
|
07e070012b | ||
|
801437cd54 | ||
|
62ae2b3f40 | ||
|
5edc32930d | ||
|
5e6f7b1cdb | ||
|
f2b03e9679 | ||
|
86133983a9 | ||
|
39595aaca3 | ||
|
a783cd8f40 | ||
|
33e0bb1478 | ||
|
a5a6480917 | ||
|
d20ee31210 | ||
|
95a5e75c26 | ||
|
335015fe2d | ||
|
f7815dab42 | ||
|
b164e67d8b | ||
|
28c8561924 | ||
|
82a6fba6ec | ||
|
2e763764bf | ||
|
90a53aed59 | ||
|
55490637aa | ||
|
e400a288d0 | ||
|
bca7804bb6 | ||
|
25aec3ac8c | ||
|
f94264928a | ||
|
d9ec2785cb | ||
|
1d40af64d3 | ||
|
e87227e00a | ||
|
faa9017043 | ||
|
0652a20bd3 | ||
|
9fc3cb5629 | ||
|
01df3b73d8 | ||
|
ecf282d331 | ||
|
72e31d3335 | ||
|
3878f806ff | ||
|
d86eec332f | ||
|
4540d8ccd5 | ||
|
d27b5985c1 | ||
|
932a0cd777 | ||
|
9fe409800b | ||
|
8aecd4f253 | ||
|
608eff600d | ||
|
81bb4eb2f6 | ||
|
e5fa0007a5 | ||
|
29b0529542 | ||
|
0d1bb65c75 | ||
|
34413d1f36 | ||
|
31d055f6d4 | ||
|
d119513749 | ||
|
bb4646bbdf | ||
|
a2366f78f0 | ||
|
cf3596a96d | ||
|
4f1214c7e9 | ||
|
aab1df50ab | ||
|
5fdd0bceac | ||
|
5262292abc | ||
|
c3ec16f494 | ||
|
29308b94ca | ||
|
7778f01194 | ||
|
da839f20f1 | ||
|
855a516596 | ||
|
012a2802e0 | ||
|
741c75d907 | ||
|
dafc9ed4eb | ||
|
e91513a5e8 | ||
|
450343b7b8 | ||
|
e1644e91ea | ||
|
cbed4fa5ec | ||
|
a4f38a07d7 | ||
|
019d4900cb | ||
|
448e3208ca | ||
|
8afdb8403b | ||
|
f041d763ae | ||
|
f587c3e0ba | ||
|
87173bd09d | ||
|
ed69502ff6 | ||
|
4954dcbbb3 | ||
|
55f1f3fedf | ||
|
75c87bde3c | ||
|
d9fe1d0f58 | ||
|
e823b5d693 | ||
|
e69bc5b870 | ||
|
f47c89d495 | ||
|
93e5d7ca5a | ||
|
1ce21fdb3e | ||
|
4dc07c4378 | ||
|
8ca28dd510 | ||
|
9ce9bd9b0f | ||
|
7c3bd4c19f | ||
|
30e4b404f2 | ||
|
a141bbbea5 | ||
|
a10a6fff55 | ||
|
4ad739ec63 | ||
|
1055e6bee6 | ||
|
84ee839ca6 | ||
|
a945346064 | ||
|
ea47e8c92a | ||
|
ea95449402 | ||
|
5c97b96278 | ||
|
10caa03ce5 | ||
|
1ebc32f5f4 | ||
|
b52a49b4c4 | ||
|
1016faea53 | ||
|
dd39cd7e42 | ||
|
4d0a635237 | ||
|
82222342f1 | ||
|
78b04c3a76 | ||
|
e57a2d7ec8 | ||
|
e8e02e81e8 | ||
|
fe7b748eb6 | ||
|
eeca50e3dc | ||
|
9a66514e26 | ||
|
32555e98dd | ||
|
79a139c949 | ||
|
c99803af15 | ||
|
02cbf049d2 | ||
|
ccbdce7c85 | ||
|
3dbf8e936e | ||
|
d1c2d524a0 | ||
|
2ea367839b | ||
|
1719905e7f | ||
|
ce4c36392d | ||
|
67f47fbdcc | ||
|
043a40cd7a | ||
|
fd7ea4f27c |
37
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -5,15 +5,33 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before opening a new issue, take a moment to search through the current open ones.
|
||||
## Before opening a new issue, please take a moment to search through the current open and closed issues to check if it already exists.
|
||||
|
||||
---
|
||||
|
||||
- type: dropdown
|
||||
id: type
|
||||
attributes:
|
||||
label: Regression?
|
||||
description: |
|
||||
Regression means that something used to work but no longer does.
|
||||
**BEFORE CONTINUING**, please check if this bug is a regression or not, and if it is, we need you to bisect with the help of the wiki: https://wiki.hyprland.org/Crashes-and-Bugs/#bisecting-an-issue
|
||||
multiple: true
|
||||
options:
|
||||
- "Yes"
|
||||
- "No"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: ver
|
||||
attributes:
|
||||
label: Hyprland Version
|
||||
description: "Paste the output of `hyprctl systeminfo` here."
|
||||
label: System Info and Version
|
||||
description: |
|
||||
Paste the output of `hyprctl systeminfo -c` here (If you are on a
|
||||
version that shows you help menu, omit the `-c` and attach config files
|
||||
to the issue). If you have configs outside of the main config shown
|
||||
here, please attach.
|
||||
value: "<details>
|
||||
<summary>System/Version info</summary>
|
||||
|
||||
@@ -29,17 +47,6 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: type
|
||||
attributes:
|
||||
label: Bug or Regression?
|
||||
description: Is this a bug or a regression?
|
||||
options:
|
||||
- Bug
|
||||
- Regression
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: desc
|
||||
attributes:
|
||||
@@ -62,6 +69,6 @@ body:
|
||||
label: Crash reports, logs, images, videos
|
||||
description: |
|
||||
Anything that can help. Please always ATTACH and not paste them.
|
||||
Logs can be found in /tmp/hypr
|
||||
Logs can be found in $XDG_RUNTIME_DIR/hypr
|
||||
Crash reports are stored in ~/.cache/hyprland or $XDG_CACHE_HOME/hyprland
|
||||
|
||||
|
20
.github/actions/setup_base/action.yml
vendored
@@ -12,7 +12,6 @@ runs:
|
||||
- name: Get required pacman pkgs
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i -e "1i [extra-testing]\nInclude = /etc/pacman.d/mirrorlist" "/etc/pacman.conf"
|
||||
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
||||
pacman --noconfirm --noprogressbar -Syyu
|
||||
pacman --noconfirm --noprogressbar -Sy \
|
||||
@@ -25,6 +24,7 @@ runs:
|
||||
glslang \
|
||||
go \
|
||||
hyprlang \
|
||||
hyprcursor \
|
||||
jq \
|
||||
libc++ \
|
||||
libdisplay-info \
|
||||
@@ -34,6 +34,7 @@ runs:
|
||||
libglvnd \
|
||||
libinput \
|
||||
libliftoff \
|
||||
libxcursor \
|
||||
libxcvt \
|
||||
libxfont2 \
|
||||
libxkbcommon \
|
||||
@@ -44,6 +45,7 @@ runs:
|
||||
pango \
|
||||
pixman \
|
||||
pkgconf \
|
||||
pugixml \
|
||||
scdoc \
|
||||
seatd \
|
||||
systemd \
|
||||
@@ -58,15 +60,25 @@ runs:
|
||||
libzip \
|
||||
librsvg
|
||||
|
||||
- name: Get hyprcursor-git
|
||||
- name: Get hyprwayland-scanner-git
|
||||
shell: bash
|
||||
run: |
|
||||
git clone https://github.com/hyprwm/hyprcursor --recursive
|
||||
cd hyprcursor
|
||||
git clone https://github.com/hyprwm/hyprwayland-scanner --recursive
|
||||
cd hyprwayland-scanner
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
cmake --install build
|
||||
|
||||
- name: Get hyprutils-git
|
||||
shell: bash
|
||||
run: |
|
||||
git clone https://github.com/hyprwm/hyprutils && cd hyprutils && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target hyprutils && cmake --install build
|
||||
|
||||
- name: Get aquamarine-git
|
||||
shell: bash
|
||||
run: |
|
||||
git clone https://github.com/hyprwm/aquamarine && cd aquamarine && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target aquamarine && cmake --install build
|
||||
|
||||
- name: Get Xorg pacman pkgs
|
||||
shell: bash
|
||||
if: inputs.INSTALL_XORG_PKGS == 'true'
|
||||
|
83
.github/labeler.yml
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
assets:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "assets/**"
|
||||
|
||||
docs:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "docs/**"
|
||||
|
||||
hyprctl:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "hyprctl/**"
|
||||
|
||||
hyprpm:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "hyprpm/**"
|
||||
|
||||
nix:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "nix/**"
|
||||
|
||||
protocols:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ["protocols/**", "src/protocols/**"]
|
||||
|
||||
core:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/**"
|
||||
|
||||
config:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/config/**"
|
||||
|
||||
debug:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/debug/**"
|
||||
|
||||
desktop:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/desktop/**"
|
||||
|
||||
devices:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/devices/**"
|
||||
|
||||
events:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/events/**"
|
||||
|
||||
helpers:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/helpers/**"
|
||||
|
||||
hyprerror:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/hyprerror/**"
|
||||
|
||||
init:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/init/**"
|
||||
|
||||
layout:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/layout/**"
|
||||
|
||||
managers:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/managers/**"
|
||||
|
||||
pch:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/pch/**"
|
||||
|
||||
plugins:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/plugins/**"
|
||||
|
||||
render:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/render/**"
|
||||
|
||||
xwayland:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "src/xwayland/**"
|
24
.github/workflows/ci.yaml
vendored
@@ -3,6 +3,7 @@ name: Build Hyprland
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
jobs:
|
||||
gcc:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Build Hyprland (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
@@ -44,6 +45,7 @@ jobs:
|
||||
path: Hyprland.tar.xz
|
||||
|
||||
meson:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Build Hyprland with Meson (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
@@ -63,7 +65,28 @@ jobs:
|
||||
- name: Compile
|
||||
run: ninja -C build
|
||||
|
||||
no-pch:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Build Hyprland without precompiled headers (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: archlinux
|
||||
steps:
|
||||
- name: Checkout repository actions
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: .github/actions
|
||||
|
||||
- name: Setup base
|
||||
uses: ./.github/actions/setup_base
|
||||
with:
|
||||
INSTALL_XORG_PKGS: true
|
||||
|
||||
- name: Compile
|
||||
run: make nopch
|
||||
|
||||
noxwayland:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Build Hyprland in pure Wayland (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
@@ -84,6 +107,7 @@ jobs:
|
||||
run: make release
|
||||
|
||||
clang-format:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: "Code Style (Arch)"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
|
12
.github/workflows/labeler.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
name: "Pull Request Labeler"
|
||||
on:
|
||||
- pull_request_target
|
||||
|
||||
jobs:
|
||||
labeler:
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v5
|
13
.github/workflows/nix-build.yml
vendored
@@ -1,3 +1,5 @@
|
||||
name: Nix (Build)
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
@@ -15,15 +17,16 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
submodules: recursive
|
||||
|
||||
- uses: cachix/install-nix-action@v25
|
||||
- uses: cachix/install-nix-action@v27
|
||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||
- uses: cachix/cachix-action@v12
|
||||
- uses: cachix/cachix-action@v15
|
||||
with:
|
||||
name: hyprland
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- run: nix build .#${{ matrix.package }} -L
|
||||
- run: nix build '.?submodules=1#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org"
|
||||
|
12
.github/workflows/nix-ci.yml
vendored
@@ -1,15 +1,15 @@
|
||||
name: Nix
|
||||
name: Nix (CI)
|
||||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
wlroots:
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: ./.github/workflows/nix-update-wlroots.yml
|
||||
update-inputs:
|
||||
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
|
||||
uses: ./.github/workflows/nix-update-inputs.yml
|
||||
secrets: inherit
|
||||
|
||||
build:
|
||||
if: always() && !cancelled() && !contains(needs.*.result, 'failure')
|
||||
needs: wlroots
|
||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork) && !contains(needs.*.result, 'failure')
|
||||
needs: update-inputs
|
||||
uses: ./.github/workflows/nix-build.yml
|
||||
secrets: inherit
|
||||
|
14
.github/workflows/nix-update-inputs.yml
vendored
@@ -1,11 +1,14 @@
|
||||
name: Nix
|
||||
name: Nix (Update Inputs)
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *' # check daily
|
||||
workflow_call:
|
||||
secrets:
|
||||
PAT:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
update:
|
||||
if: github.repository == 'hyprwm/Hyprland'
|
||||
name: inputs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -22,8 +25,3 @@ jobs:
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: "[gha] Nix: update inputs"
|
||||
|
||||
update-build:
|
||||
needs: update
|
||||
uses: ./.github/workflows/nix-build.yml
|
||||
secrets: inherit
|
||||
|
26
.github/workflows/nix-update-wlroots.yml
vendored
@@ -1,26 +0,0 @@
|
||||
name: Nix
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
PAT:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
update:
|
||||
name: wlroots
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
token: ${{ secrets.PAT }}
|
||||
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
- name: Update lockfile
|
||||
run: nix/update-wlroots.sh
|
||||
|
||||
- name: Commit
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: "[gha] Nix: update wlroots"
|
1
.github/workflows/release.yaml
vendored
@@ -18,6 +18,7 @@ jobs:
|
||||
- name: Generate version
|
||||
id: genversion
|
||||
run: |
|
||||
git fetch --unshallow || echo "failed unshallowing"
|
||||
bash -c scripts/generateVersion.sh
|
||||
mv scripts/generateVersion.sh scripts/generateVersion.sh.bak
|
||||
|
||||
|
1
.github/workflows/security-checks.yml
vendored
@@ -4,6 +4,7 @@ on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
flawfinder:
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
||||
name: Flawfinder Checks
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
|
8
.github/workflows/stale.yml
vendored
@@ -7,12 +7,12 @@ name: Mark stale issues and pull requests
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '7 */4 * * *'
|
||||
- cron: "7 */4 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
|
||||
if: github.repository == 'hyprwm/Hyprland'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
repo-token: ${{ secrets.STALEBOT_PAT }}
|
||||
stale-issue-label: 'stale'
|
||||
stale-pr-label: 'stale'
|
||||
stale-issue-label: "stale"
|
||||
stale-pr-label: "stale"
|
||||
operations-per-run: 40
|
||||
days-before-close: -1
|
||||
|
14
.gitignore
vendored
@@ -7,6 +7,9 @@ cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
CPackConfig.cmake
|
||||
CPackSourceConfig.cmake
|
||||
hyprland.pc
|
||||
_deps
|
||||
|
||||
build/
|
||||
@@ -15,10 +18,13 @@ result*
|
||||
/.idea/
|
||||
.envrc
|
||||
.cache
|
||||
.direnv
|
||||
/.cmake/
|
||||
/.worktree/
|
||||
|
||||
*.o
|
||||
*-protocol.c
|
||||
*-protocol.h
|
||||
protocols/*.c*
|
||||
protocols/*.h*
|
||||
.ccls-cache
|
||||
*.so
|
||||
|
||||
@@ -31,5 +37,5 @@ gmon.out
|
||||
PKGBUILD
|
||||
|
||||
src/version.h
|
||||
|
||||
.direnv
|
||||
hyprpm/Makefile
|
||||
hyprctl/Makefile
|
||||
|
3
.gitmodules
vendored
@@ -7,6 +7,3 @@
|
||||
[submodule "subprojects/tracy"]
|
||||
path = subprojects/tracy
|
||||
url = https://github.com/wolfpld/tracy
|
||||
[submodule "subprojects/wlroots-hyprland"]
|
||||
path = subprojects/wlroots-hyprland
|
||||
url = https://github.com/hyprwm/wlroots-hyprland
|
||||
|
334
CMakeLists.txt
Executable file → Normal file
@@ -1,39 +1,33 @@
|
||||
cmake_minimum_required(VERSION 3.27)
|
||||
include(CheckIncludeFile)
|
||||
|
||||
# Get version
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/props.json PROPS)
|
||||
string(JSON VER GET ${PROPS} version)
|
||||
file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW)
|
||||
string(STRIP ${VER_RAW} VER)
|
||||
|
||||
project(Hyprland
|
||||
project(
|
||||
Hyprland
|
||||
DESCRIPTION "A Modern C++ Wayland Compositor"
|
||||
VERSION ${VER}
|
||||
)
|
||||
VERSION ${VER})
|
||||
|
||||
include(CheckIncludeFile)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(HYPRLAND_VERSION ${VER})
|
||||
set(PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
set(INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
configure_file(hyprland.pc.in hyprland.pc @ONLY)
|
||||
|
||||
set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")
|
||||
|
||||
message(STATUS "Gathering git info")
|
||||
|
||||
# Get git info
|
||||
# hash and branch
|
||||
execute_process(
|
||||
COMMAND ./scripts/generateVersion.sh
|
||||
# Get git info hash and branch
|
||||
execute_process(COMMAND ./scripts/generateVersion.sh
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
#
|
||||
#
|
||||
|
||||
# udis
|
||||
add_subdirectory("subprojects/udis86")
|
||||
|
||||
# wlroots
|
||||
message(STATUS "Setting up wlroots")
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
if(CMAKE_BUILD_TYPE)
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER)
|
||||
if(BUILDTYPE_LOWER STREQUAL "release")
|
||||
@@ -53,24 +47,13 @@ else()
|
||||
set(BUILDTYPE_LOWER "release")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(
|
||||
wlroots-hyprland
|
||||
PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland
|
||||
SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland
|
||||
CONFIGURE_COMMAND meson setup --reconfigure build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dxwayland=$<IF:$<BOOL:${NO_XWAYLAND}>,disabled,enabled> -Dexamples=false -Drenderers=gles2 -Dbackends=drm,libinput $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none>
|
||||
BUILD_COMMAND ninja -C build
|
||||
BUILD_ALWAYS true
|
||||
BUILD_IN_SOURCE true
|
||||
BUILD_BYPRODUCTS ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland/build/libwlroots.a
|
||||
INSTALL_COMMAND echo "wlroots-hyprland: install not needed"
|
||||
)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_get_variable(WaylandScanner wayland-scanner wayland_scanner)
|
||||
message(STATUS "Found WaylandScanner at ${WaylandScanner}")
|
||||
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
|
||||
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
|
||||
pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir)
|
||||
message(
|
||||
STATUS "Found wayland-scanner pkgdatadir at ${WAYLAND_SCANNER_PKGDATA_DIR}")
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
message(STATUS "Configuring Hyprland in Debug with CMake")
|
||||
@@ -80,18 +63,20 @@ else()
|
||||
message(STATUS "Configuring Hyprland in Release with CMake")
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
.
|
||||
"src/"
|
||||
"subprojects/wlroots-hyprland/include/"
|
||||
"subprojects/wlroots-hyprland/build/include/"
|
||||
"subprojects/udis86/"
|
||||
"protocols/")
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
add_compile_definitions(WLR_USE_UNSTABLE)
|
||||
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing -Wno-pointer-arith)
|
||||
include_directories(. "src/" "subprojects/udis86/" "protocols/")
|
||||
set(CMAKE_CXX_STANDARD 26)
|
||||
add_compile_options(
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wno-unused-parameter
|
||||
-Wno-unused-value
|
||||
-Wno-missing-field-initializers
|
||||
-Wno-narrowing
|
||||
-Wno-pointer-arith
|
||||
-fmacro-prefix-map=${CMAKE_SOURCE_DIR}/=)
|
||||
|
||||
set(CMAKE_EXECUTABLE_ENABLE_EXPORTS TRUE)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
|
||||
|
||||
message(STATUS "Checking deps...")
|
||||
|
||||
@@ -104,15 +89,33 @@ else()
|
||||
endif()
|
||||
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
|
||||
|
||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET
|
||||
xkbcommon
|
||||
wayland-server wayland-client wayland-cursor wayland-protocols
|
||||
cairo pango pangocairo pixman-1
|
||||
libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm
|
||||
hyprlang>=0.3.2 hyprcursor
|
||||
)
|
||||
pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.1)
|
||||
|
||||
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||
pkg_check_modules(
|
||||
deps
|
||||
REQUIRED
|
||||
IMPORTED_TARGET
|
||||
aquamarine
|
||||
xkbcommon
|
||||
uuid
|
||||
wayland-server
|
||||
wayland-protocols
|
||||
cairo
|
||||
pango
|
||||
pangocairo
|
||||
pixman-1
|
||||
xcursor
|
||||
libdrm
|
||||
libinput
|
||||
gbm
|
||||
gio-2.0
|
||||
hyprlang>=0.3.2
|
||||
hyprcursor>=0.1.7
|
||||
hyprutils>=0.2.1)
|
||||
|
||||
find_package(hyprwayland-scanner 0.3.10 REQUIRED)
|
||||
|
||||
file(GLOB_RECURSE SRCFILES "src/*.cpp")
|
||||
|
||||
set(TRACY_CPP_FILES "")
|
||||
if(USE_TRACY)
|
||||
@@ -121,12 +124,13 @@ if(USE_TRACY)
|
||||
endif()
|
||||
|
||||
add_executable(Hyprland ${SRCFILES} ${TRACY_CPP_FILES})
|
||||
add_dependencies(Hyprland wlroots-hyprland)
|
||||
|
||||
set(USE_GPROF ON)
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
message(STATUS "Setting debug flags")
|
||||
|
||||
if (WITH_ASAN)
|
||||
if(WITH_ASAN)
|
||||
message(STATUS "Enabling ASan")
|
||||
|
||||
target_link_libraries(Hyprland asan)
|
||||
@@ -136,9 +140,9 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
if(USE_TRACY)
|
||||
message(STATUS "Tracy is turned on")
|
||||
|
||||
option( TRACY_ENABLE "" ON)
|
||||
option( TRACY_ON_DEMAND "" ON)
|
||||
add_subdirectory (subprojects/tracy)
|
||||
option(TRACY_ENABLE "" ON)
|
||||
option(TRACY_ON_DEMAND "" ON)
|
||||
add_subdirectory(subprojects/tracy)
|
||||
|
||||
target_link_libraries(Hyprland Tracy::TracyClient)
|
||||
|
||||
@@ -148,8 +152,12 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_compile_options(-pg -no-pie -fno-builtin)
|
||||
add_link_options(-pg -no-pie -fno-builtin)
|
||||
add_compile_options(-fno-pie -fno-builtin)
|
||||
add_link_options(-no-pie -fno-builtin)
|
||||
if(USE_GPROF)
|
||||
add_compile_options(-pg)
|
||||
add_link_options(-pg)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
check_include_file("execinfo.h" EXECINFOH)
|
||||
@@ -164,6 +172,12 @@ if(HAVE_LIBEXECINFO)
|
||||
target_link_libraries(Hyprland execinfo)
|
||||
endif()
|
||||
|
||||
check_include_file("sys/timerfd.h" HAS_TIMERFD)
|
||||
pkg_check_modules(epoll IMPORTED_TARGET epoll-shim)
|
||||
if(NOT HAS_TIMERFD AND epoll_FOUND)
|
||||
target_link_libraries(Hyprland PkgConfig::epoll)
|
||||
endif()
|
||||
|
||||
if(LEGACY_RENDERER)
|
||||
message(STATUS "Using the legacy GLES2 renderer!")
|
||||
add_compile_definitions(LEGACY_RENDERER)
|
||||
@@ -174,31 +188,25 @@ if(NO_XWAYLAND)
|
||||
add_compile_definitions(NO_XWAYLAND)
|
||||
else()
|
||||
message(STATUS "XWAYLAND Enabled (NO_XWAYLAND not defined) checking deps...")
|
||||
pkg_check_modules(xdeps REQUIRED IMPORTED_TARGET xcb xwayland xcb-util xcb-render xcb-image xcb-xfixes xcb-icccm xcb-composite xcb-res xcb-ewmh)
|
||||
pkg_check_modules(xcb_errors IMPORTED_TARGET xcb-errors)
|
||||
pkg_check_modules(
|
||||
xdeps
|
||||
REQUIRED
|
||||
IMPORTED_TARGET
|
||||
xcb
|
||||
xcb-render
|
||||
xcb-xfixes
|
||||
xcb-icccm
|
||||
xcb-composite
|
||||
xcb-res
|
||||
xcb-errors)
|
||||
target_link_libraries(Hyprland PkgConfig::xdeps)
|
||||
if(xcb_errors_FOUND)
|
||||
target_link_libraries(Hyprland PkgConfig::xcb_errors)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NO_SYSTEMD)
|
||||
message(STATUS "SYSTEMD support is disabled...")
|
||||
else()
|
||||
message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined) checking deps...")
|
||||
check_include_file("systemd/sd-daemon.h" SYSTEMDH)
|
||||
if(SYSTEMDH)
|
||||
pkg_check_modules(LIBSYSTEMD libsystemd)
|
||||
if (LIBSYSTEMD_FOUND)
|
||||
message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined)...")
|
||||
add_compile_definitions(USES_SYSTEMD)
|
||||
target_link_libraries(Hyprland "${LIBSYSTEMD_LIBRARIES}")
|
||||
message(STATUS "Systemd found")
|
||||
else()
|
||||
message(WARNING "Systemd support requested but systemd libraries were not found")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Systemd support requested but systemd headers were not found")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
|
||||
@@ -207,57 +215,155 @@ include(CPack)
|
||||
|
||||
message(STATUS "Setting precompiled headers")
|
||||
|
||||
target_precompile_headers(Hyprland PRIVATE $<$<COMPILE_LANGUAGE:CXX>:src/pch/pch.hpp>)
|
||||
target_precompile_headers(Hyprland PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:CXX>:src/pch/pch.hpp>)
|
||||
|
||||
message(STATUS "Setting link libraries")
|
||||
|
||||
target_link_libraries(Hyprland rt PkgConfig::deps)
|
||||
|
||||
function(protocol protoPath protoName external)
|
||||
if (external)
|
||||
execute_process(
|
||||
COMMAND ${WaylandScanner} server-header ${protoPath} protocols/${protoName}-protocol.h
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
execute_process(
|
||||
COMMAND ${WaylandScanner} private-code ${protoPath} protocols/${protoName}-protocol.c
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
target_sources(Hyprland PRIVATE protocols/${protoName}-protocol.c)
|
||||
# used by `make installheaders`, to ensure the headers are generated
|
||||
add_custom_target(generate-protocol-headers)
|
||||
|
||||
function(protocolnew protoPath protoName external)
|
||||
if(external)
|
||||
set(path ${CMAKE_SOURCE_DIR}/${protoPath})
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND ${WaylandScanner} server-header ${WAYLAND_PROTOCOLS_DIR}/${protoPath} protocols/${protoName}-protocol.h
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
execute_process(
|
||||
COMMAND ${WaylandScanner} private-code ${WAYLAND_PROTOCOLS_DIR}/${protoPath} protocols/${protoName}-protocol.c
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
target_sources(Hyprland PRIVATE protocols/${protoName}-protocol.c)
|
||||
set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath})
|
||||
endif()
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}.cpp
|
||||
${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp
|
||||
COMMAND hyprwayland-scanner ${path}/${protoName}.xml
|
||||
${CMAKE_SOURCE_DIR}/protocols/
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
target_sources(Hyprland PRIVATE protocols/${protoName}.cpp
|
||||
protocols/${protoName}.hpp)
|
||||
target_sources(generate-protocol-headers
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp)
|
||||
endfunction()
|
||||
function(protocolWayland)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/wayland.cpp
|
||||
${CMAKE_SOURCE_DIR}/protocols/wayland.hpp
|
||||
COMMAND
|
||||
hyprwayland-scanner --wayland-enums
|
||||
${WAYLAND_SCANNER_PKGDATA_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
target_sources(Hyprland PRIVATE protocols/wayland.cpp protocols/wayland.hpp)
|
||||
target_sources(generate-protocol-headers
|
||||
PRIVATE ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp)
|
||||
endfunction()
|
||||
|
||||
target_link_libraries(Hyprland
|
||||
${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland/build/libwlroots.a
|
||||
OpenGL::EGL
|
||||
OpenGL::GL
|
||||
Threads::Threads
|
||||
libudis86
|
||||
)
|
||||
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads
|
||||
libudis86)
|
||||
|
||||
protocol("protocols/idle.xml" "idle" true)
|
||||
protocol("protocols/pointer-constraints-unstable-v1.xml" "pointer-constraints-unstable-v1" true)
|
||||
protocol("protocols/tablet-unstable-v2.xml" "tablet-unstable-v2" true)
|
||||
protocol("protocols/wlr-foreign-toplevel-management-unstable-v1.xml" "wlr-foreign-toplevel-management-unstable-v1" true)
|
||||
protocol("protocols/wlr-layer-shell-unstable-v1.xml" "wlr-layer-shell-unstable-v1" true)
|
||||
protocol("protocols/wlr-output-power-management-unstable-v1.xml" "wlr-output-power-management-unstable-v1" true)
|
||||
protocol("protocols/wlr-screencopy-unstable-v1.xml" "wlr-screencopy-unstable-v1" true)
|
||||
protocol("subprojects/hyprland-protocols/protocols/hyprland-global-shortcuts-v1.xml" "hyprland-global-shortcuts-v1" true)
|
||||
protocol("subprojects/hyprland-protocols/protocols/hyprland-toplevel-export-v1.xml" "hyprland-toplevel-export-v1" true)
|
||||
protocol("stable/xdg-shell/xdg-shell.xml" "xdg-shell" false)
|
||||
protocol("unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml" "linux-dmabuf-unstable-v1" false)
|
||||
protocol("unstable/xdg-output/xdg-output-unstable-v1.xml" "xdg-output-unstable-v1" false)
|
||||
protocol("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1" false)
|
||||
protocol("staging/tearing-control/tearing-control-v1.xml" "tearing-control-v1" false)
|
||||
protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false)
|
||||
protocol("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false)
|
||||
protocolnew("subprojects/hyprland-protocols/protocols"
|
||||
"hyprland-global-shortcuts-v1" true)
|
||||
protocolnew("unstable/text-input" "text-input-unstable-v1" false)
|
||||
protocolnew("subprojects/hyprland-protocols/protocols"
|
||||
"hyprland-toplevel-export-v1" true)
|
||||
protocolnew("protocols" "wlr-screencopy-unstable-v1" true)
|
||||
protocolnew("protocols" "wlr-gamma-control-unstable-v1" true)
|
||||
protocolnew("protocols" "wlr-foreign-toplevel-management-unstable-v1" true)
|
||||
protocolnew("protocols" "wlr-output-power-management-unstable-v1" true)
|
||||
protocolnew("protocols" "virtual-keyboard-unstable-v1" true)
|
||||
protocolnew("protocols" "wlr-virtual-pointer-unstable-v1" true)
|
||||
protocolnew("protocols" "input-method-unstable-v2" true)
|
||||
protocolnew("protocols" "wlr-output-management-unstable-v1" true)
|
||||
protocolnew("protocols" "kde-server-decoration" true)
|
||||
protocolnew("protocols" "wlr-data-control-unstable-v1" true)
|
||||
protocolnew("subprojects/hyprland-protocols/protocols" "hyprland-focus-grab-v1"
|
||||
true)
|
||||
protocolnew("protocols" "wlr-layer-shell-unstable-v1" true)
|
||||
protocolnew("protocols" "wayland-drm" true)
|
||||
protocolnew("staging/tearing-control" "tearing-control-v1" false)
|
||||
protocolnew("staging/fractional-scale" "fractional-scale-v1" false)
|
||||
protocolnew("unstable/xdg-output" "xdg-output-unstable-v1" false)
|
||||
protocolnew("staging/cursor-shape" "cursor-shape-v1" false)
|
||||
protocolnew("unstable/idle-inhibit" "idle-inhibit-unstable-v1" false)
|
||||
protocolnew("unstable/relative-pointer" "relative-pointer-unstable-v1" false)
|
||||
protocolnew("unstable/xdg-decoration" "xdg-decoration-unstable-v1" false)
|
||||
protocolnew("staging/alpha-modifier" "alpha-modifier-v1" false)
|
||||
protocolnew("staging/ext-foreign-toplevel-list" "ext-foreign-toplevel-list-v1"
|
||||
false)
|
||||
protocolnew("unstable/pointer-gestures" "pointer-gestures-unstable-v1" false)
|
||||
protocolnew("unstable/keyboard-shortcuts-inhibit"
|
||||
"keyboard-shortcuts-inhibit-unstable-v1" false)
|
||||
protocolnew("unstable/text-input" "text-input-unstable-v3" false)
|
||||
protocolnew("unstable/pointer-constraints" "pointer-constraints-unstable-v1"
|
||||
false)
|
||||
protocolnew("staging/xdg-activation" "xdg-activation-v1" false)
|
||||
protocolnew("staging/ext-idle-notify" "ext-idle-notify-v1" false)
|
||||
protocolnew("staging/ext-session-lock" "ext-session-lock-v1" false)
|
||||
protocolnew("stable/tablet" "tablet-v2" false)
|
||||
protocolnew("stable/presentation-time" "presentation-time" false)
|
||||
protocolnew("stable/xdg-shell" "xdg-shell" false)
|
||||
protocolnew("unstable/primary-selection" "primary-selection-unstable-v1" false)
|
||||
protocolnew("staging/xwayland-shell" "xwayland-shell-v1" false)
|
||||
protocolnew("stable/viewporter" "viewporter" false)
|
||||
protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false)
|
||||
protocolnew("staging/drm-lease" "drm-lease-v1" false)
|
||||
protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false)
|
||||
protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false)
|
||||
|
||||
protocolwayland()
|
||||
|
||||
# tools
|
||||
add_subdirectory(hyprctl)
|
||||
add_subdirectory(hyprpm)
|
||||
|
||||
# binary and symlink
|
||||
install(TARGETS Hyprland)
|
||||
|
||||
install(
|
||||
CODE "execute_process( \
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink \
|
||||
${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \
|
||||
\"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/hyprland\" \
|
||||
)")
|
||||
|
||||
# session file
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions)
|
||||
|
||||
# allow Hyprland to find assets
|
||||
add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}")
|
||||
|
||||
# installable assets
|
||||
file(GLOB_RECURSE INSTALLABLE_ASSETS "assets/install/*")
|
||||
list(FILTER INSTALLABLE_ASSETS EXCLUDE REGEX "meson.build")
|
||||
install(FILES ${INSTALLABLE_ASSETS}
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
|
||||
|
||||
# default config
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.conf
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
|
||||
|
||||
# portal config
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/assets/hyprland-portals.conf
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/xdg-desktop-portal)
|
||||
|
||||
# man pages
|
||||
file(GLOB_RECURSE MANPAGES "docs/*.1")
|
||||
install(FILES ${MANPAGES} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
|
||||
|
||||
# pkgconfig entry
|
||||
install(FILES ${CMAKE_BINARY_DIR}/hyprland.pc
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)
|
||||
|
||||
# protocol headers
|
||||
set(HEADERS_PROTO "${CMAKE_CURRENT_SOURCE_DIR}/protocols")
|
||||
install(
|
||||
DIRECTORY ${HEADERS_PROTO}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland
|
||||
FILES_MATCHING
|
||||
PATTERN "*.h*")
|
||||
|
||||
# hyprland headers
|
||||
set(HEADERS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||
install(
|
||||
DIRECTORY ${HEADERS_SRC}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hyprland
|
||||
FILES_MATCHING
|
||||
PATTERN "*.h*")
|
||||
|
80
Makefile
@@ -2,82 +2,41 @@ PREFIX = /usr/local
|
||||
|
||||
legacyrenderer:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
cmake --build ./build --config Release --target all
|
||||
chmod -R 777 ./build
|
||||
|
||||
legacyrendererdebug:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
cmake --build ./build --config Release --target all
|
||||
chmod -R 777 ./build
|
||||
|
||||
release:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
cmake --build ./build --config Release --target all
|
||||
chmod -R 777 ./build
|
||||
|
||||
debug:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
cmake --build ./build --config Debug --target all
|
||||
chmod -R 777 ./build
|
||||
|
||||
nopch:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all
|
||||
|
||||
clear:
|
||||
rm -rf build
|
||||
rm -f ./protocols/*-protocol.h ./protocols/*-protocol.c
|
||||
rm -rf ./subprojects/wlroots-hyprland/build
|
||||
rm -f ./protocols/*.h ./protocols/*.c ./protocols/*.cpp ./protocols/*.hpp
|
||||
|
||||
all:
|
||||
@if [[ "$EUID" = 0 ]]; then echo -en "Avoid running $(MAKE) all as sudo.\n"; fi
|
||||
$(MAKE) clear
|
||||
$(MAKE) release
|
||||
|
||||
install:
|
||||
@if [ ! -f ./build/Hyprland ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi
|
||||
@echo -en "!NOTE: Please note make install does not compile Hyprland and only installs the already built files."
|
||||
|
||||
mkdir -p ${PREFIX}/share/wayland-sessions
|
||||
mkdir -p ${PREFIX}/bin
|
||||
mkdir -p ${PREFIX}/share/hyprland
|
||||
mkdir -p ${PREFIX}/share/bash-completion/completions
|
||||
mkdir -p ${PREFIX}/share/fish/vendor_completions.d
|
||||
mkdir -p ${PREFIX}/share/zsh/site-functions
|
||||
cp -f ./build/Hyprland ${PREFIX}/bin
|
||||
cp -f ./build/hyprctl/hyprctl ${PREFIX}/bin
|
||||
cp -f ./build/hyprpm/hyprpm ${PREFIX}/bin
|
||||
cp -f ./hyprctl/hyprctl.bash ${PREFIX}/share/bash-completion/completions/hyprctl
|
||||
cp -f ./hyprctl/hyprctl.fish ${PREFIX}/share/fish/vendor_completions.d/hyprctl.fish
|
||||
cp -f ./hyprctl/hyprctl.zsh ${PREFIX}/share/zsh/site-functions/_hyprctl
|
||||
cp -f ./hyprpm/hyprpm.bash ${PREFIX}/share/bash-completion/completions/hyprpm
|
||||
cp -f ./hyprpm/hyprpm.fish ${PREFIX}/share/fish/vendor_completions.d/hyprpm.fish
|
||||
cp -f ./hyprpm/hyprpm.zsh ${PREFIX}/share/zsh/site-functions/_hyprpm
|
||||
chmod 755 ${PREFIX}/bin/Hyprland
|
||||
chmod 755 ${PREFIX}/bin/hyprctl
|
||||
chmod 755 ${PREFIX}/bin/hyprpm
|
||||
cd ${PREFIX}/bin && ln -sf Hyprland hyprland
|
||||
if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi
|
||||
cp ./assets/wall* ${PREFIX}/share/hyprland
|
||||
mkdir -p ${PREFIX}/share/xdg-desktop-portal
|
||||
cp ./assets/hyprland-portals.conf ${PREFIX}/share/xdg-desktop-portal
|
||||
|
||||
mkdir -p ${PREFIX}/share/man/man1
|
||||
install -m644 ./docs/*.1 ${PREFIX}/share/man/man1
|
||||
|
||||
$(MAKE) installheaders
|
||||
cmake --install ./build
|
||||
|
||||
uninstall:
|
||||
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
|
||||
rm -f ${PREFIX}/bin/Hyprland
|
||||
rm -f ${PREFIX}/bin/hyprland
|
||||
rm -f ${PREFIX}/bin/hyprctl
|
||||
rm -f ${PREFIX}/bin/hyprpm
|
||||
rm -rf ${PREFIX}/share/hyprland
|
||||
rm -f ${PREFIX}/share/man/man1/Hyprland.1
|
||||
rm -f ${PREFIX}/share/man/man1/hyprctl.1
|
||||
rm -f ${PREFIX}/share/bash-completion/completions/hyprctl
|
||||
rm -f ${PREFIX}/share/fish/vendor_completions.d/hyprctl.fish
|
||||
rm -f ${PREFIX}/share/zsh/site-functions/_hyprctl
|
||||
rm -f ${PREFIX}/share/bash-completion/completions/hyprpm
|
||||
rm -f ${PREFIX}/share/fish/vendor_completions.d/hyprpm.fish
|
||||
rm -f ${PREFIX}/share/zsh/site-functions/_hyprpm
|
||||
xargs rm < ./build/install_manifest.txt
|
||||
|
||||
pluginenv:
|
||||
@echo -en "$(MAKE) pluginenv has been deprecated.\nPlease run $(MAKE) all && sudo $(MAKE) installheaders\n"
|
||||
@@ -86,16 +45,16 @@ pluginenv:
|
||||
installheaders:
|
||||
@if [ ! -f ./src/version.h ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi
|
||||
|
||||
# remove previous headers from hyprpm's dir
|
||||
rm -fr ${PREFIX}/include/hyprland
|
||||
mkdir -p ${PREFIX}/include/hyprland
|
||||
mkdir -p ${PREFIX}/include/hyprland/protocols
|
||||
mkdir -p ${PREFIX}/include/hyprland/wlroots-hyprland
|
||||
mkdir -p ${PREFIX}/share/pkgconfig
|
||||
|
||||
cmake --build ./build --config Release --target generate-protocol-headers
|
||||
|
||||
find src -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland
|
||||
cd subprojects/wlroots-hyprland/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots-hyprland && cd ../../..
|
||||
cd subprojects/wlroots-hyprland/build/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots-hyprland && cd ../../../..
|
||||
cp ./protocols/*-protocol.h ${PREFIX}/include/hyprland/protocols
|
||||
cp ./protocols/*.h* ${PREFIX}/include/hyprland/protocols
|
||||
cp ./build/hyprland.pc ${PREFIX}/share/pkgconfig
|
||||
if [ -d /usr/share/pkgconfig ]; then cp ./build/hyprland.pc /usr/share/pkgconfig 2>/dev/null || true; fi
|
||||
|
||||
@@ -125,11 +84,11 @@ asan:
|
||||
@pidof Hyprland > /dev/null && exit 1 || echo ""
|
||||
|
||||
rm -rf ./wayland
|
||||
git reset --hard
|
||||
#git reset --hard
|
||||
|
||||
@echo -en "If you want to apply a patch, input its path (leave empty for none):\n"
|
||||
@read patchvar
|
||||
@if [-n "$patchvar"]; then patch -p1 < $patchvar || echo ""; else echo "No patch specified"; fi
|
||||
@read patchvar; \
|
||||
if [ -n "$$patchvar" ]; then patch -p1 < "$$patchvar" || echo ""; else echo "No patch specified"; fi
|
||||
|
||||
git clone --recursive https://gitlab.freedesktop.org/wayland/wayland
|
||||
cd wayland && patch -p1 < ../scripts/waylandStatic.diff && meson setup build --buildtype=debug -Db_sanitize=address -Ddocumentation=false && ninja -C build && cd ..
|
||||
@@ -138,8 +97,7 @@ asan:
|
||||
|
||||
patch -p1 < ./scripts/hyprlandStaticAsan.diff
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DWITH_ASAN:STRING=True -DUSE_TRACY:STRING=False -DUSE_TRACY_GPU:STRING=False -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
cmake --build ./build --config Debug --target all
|
||||
@echo "Hyprland done"
|
||||
|
||||
ASAN_OPTIONS="detect_odr_violation=0,log_path=asan.log" HYPRLAND_NO_CRASHREPORTER=1 ./build/Hyprland -c ~/.config/hypr/hyprland.conf
|
||||
|
||||
|
17
README.md
@@ -1,6 +1,6 @@
|
||||
<div align = center>
|
||||
|
||||
<img src="https://raw.githubusercontent.com/vaxerski/Hyprland/main/assets/header.svg" width="750" height="300" alt="banner">
|
||||
<img src="https://raw.githubusercontent.com/hyprwm/Hyprland/main/assets/header.svg" width="750" height="300" alt="banner">
|
||||
|
||||
<br>
|
||||
|
||||
@@ -10,14 +10,13 @@
|
||||
[![Badge Pull Requests]][Pull Requests]
|
||||
[![Badge Issues]][Issues]
|
||||
![Badge Hi Mom]<br>
|
||||
[![Badge Discord]][Discord]
|
||||
|
||||
<br>
|
||||
|
||||
Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks.
|
||||
Hyprland is a 100% independent, dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
|
||||
|
||||
It provides the latest Wayland features, is highly customizable, has all the eyecandy, the most powerful plugins,
|
||||
easy IPC, much more QoL stuff than other wlr-based compositors and more...
|
||||
easy IPC, much more QoL stuff than other compositors and more...
|
||||
<br>
|
||||
<br>
|
||||
|
||||
@@ -38,18 +37,17 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
|
||||
|
||||
- All of the eyecandy: gradient borders, blur, animations, shadows and much more
|
||||
- A lot of customization
|
||||
- Much more QoL stuff than other wlr-based compositors
|
||||
- 100% independent, no wlroots, no libweston, no kwin, no mutter.
|
||||
- Custom bezier curves for the best animations
|
||||
- Powerful plugin support
|
||||
- Built-in plugin manager
|
||||
- Tearing support for better gaming performance
|
||||
- Easily expandable and readable codebase
|
||||
- Fast and active development
|
||||
- Not scared to provide bleeding-edge features
|
||||
- Not afraid to provide bleeding-edge features
|
||||
- Config reloaded instantly upon saving
|
||||
- Fully dynamic workspaces
|
||||
- Two built-in layouts and more available as plugins
|
||||
- Closely follows `wlroots-git`
|
||||
- Global keybinds passed to your apps of choice
|
||||
- Tiling/pseudotiling/floating/fullscreen windows
|
||||
- Special workspaces (scratchpads)
|
||||
@@ -87,7 +85,7 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
|
||||
|
||||
<br>
|
||||
|
||||
**[wlroots]** - *For their amazing library*
|
||||
**[wlroots]** - *For powering Hyprland in the past*
|
||||
|
||||
**[tinywl]** - *For showing how 2 do stuff*
|
||||
|
||||
@@ -103,7 +101,6 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
|
||||
<!----------------------------------------------------------------------------->
|
||||
|
||||
[Configure]: https://wiki.hyprland.org/Configuring/Configuring-Hyprland/
|
||||
[Discord]: https://discord.gg/hQ9XvMUjjr
|
||||
[Stars]: https://starchart.cc/hyprwm/Hyprland
|
||||
[Hypr]: https://github.com/hyprwm/Hypr
|
||||
|
||||
@@ -128,7 +125,6 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
|
||||
|
||||
<!----------------------------------{ Images }--------------------------------->
|
||||
|
||||
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
|
||||
[Preview A]: https://i.ibb.co/C1yTb0r/falf.png
|
||||
[Preview B]: https://linfindel.github.io/cdn/hyprland-preview-b.png
|
||||
[Preview C]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png
|
||||
@@ -138,7 +134,6 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
|
||||
|
||||
[Badge Workflow]: https://github.com/hyprwm/Hyprland/actions/workflows/ci.yaml/badge.svg
|
||||
|
||||
[Badge Discord]: https://img.shields.io/badge/Join%20the-Discord%20server-6666ff
|
||||
[Badge Issues]: https://img.shields.io/github/issues/hyprwm/Hyprland
|
||||
[Badge Pull Requests]: https://img.shields.io/github/issues-pr/hyprwm/Hyprland
|
||||
[Badge Language]: https://img.shields.io/github/languages/top/hyprwm/Hyprland
|
||||
|
BIN
assets/install/lockdead.png
Executable file
After Width: | Height: | Size: 110 KiB |
BIN
assets/install/lockdead2.png
Normal file
After Width: | Height: | Size: 48 KiB |
6
assets/install/meson.build
Normal file
@@ -0,0 +1,6 @@
|
||||
globber = run_command('sh', '-c', 'find . -type f -not -name "*.build"', check: true)
|
||||
files = globber.stdout().strip().split('\n')
|
||||
|
||||
foreach file : files
|
||||
install_data(file, install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime')
|
||||
endforeach
|
Before Width: | Height: | Size: 14 MiB After Width: | Height: | Size: 14 MiB |
Before Width: | Height: | Size: 5.9 MiB After Width: | Height: | Size: 5.9 MiB |
Before Width: | Height: | Size: 27 MiB After Width: | Height: | Size: 27 MiB |
@@ -1,7 +1,2 @@
|
||||
wallpapers = ['0', '1', '2']
|
||||
|
||||
foreach type : wallpapers
|
||||
install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
||||
endforeach
|
||||
|
||||
install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime')
|
||||
subdir('install')
|
||||
|
@@ -32,6 +32,12 @@ Show command usage.
|
||||
.TP
|
||||
\f[B]-c\f[R], \f[B]--config\f[R]
|
||||
Specify config file to use.
|
||||
.TP
|
||||
\f[B]--socket\f[R]
|
||||
Sets the Wayland socket name (for Wayland socket handover)
|
||||
.TP
|
||||
\f[B]--wayland-fd\f[R]
|
||||
Sets the Wayland socket file descriptor (for Wayland socket handover)
|
||||
.SH BUGS
|
||||
.TP
|
||||
Submit bug reports and request features online at:
|
||||
|
@@ -41,6 +41,12 @@ OPTIONS
|
||||
**-c**, **--config**
|
||||
Specify config file to use.
|
||||
|
||||
**--socket**
|
||||
Sets the Wayland socket name (for Wayland socket handover)
|
||||
|
||||
**--wayland-fd**
|
||||
Sets the Wayland socket file descriptor (for Wayland socket handover)
|
||||
|
||||
BUGS
|
||||
====
|
||||
|
||||
|
@@ -34,16 +34,16 @@ If your bug crashes Hyprland, append additionally:
|
||||
## Obtaining the Hyprland log
|
||||
If you are in a TTY, and the hyprland session that crashed was the last one you launched, the log will be printed with
|
||||
```
|
||||
cat /tmp/hypr/$(ls -t /tmp/hypr/ | head -n 1)/hyprland.log
|
||||
cat $XDG_RUNTIME_DIR/hypr/$(ls -t $XDG_RUNTIME_DIR/hypr | head -n 1)/hyprland.log
|
||||
```
|
||||
feel free to send it to a file, save, copy, etc.
|
||||
|
||||
if you are in a Hyprland session, and you want the log of the last session, use
|
||||
```
|
||||
cat /tmp/hypr/$(ls -t /tmp/hypr/ | head -n 2 | tail -n 1)/hyprland.log
|
||||
cat $XDG_RUNTIME_DIR/hypr/$(ls -t $XDG_RUNTIME_DIR/hypr | head -n 2 | tail -n 1)/hyprland.log
|
||||
```
|
||||
|
||||
basically, directories in /tmp/hypr are your sessions.
|
||||
basically, directories in $XDG_RUNTIME_DIR/hypr are your sessions.
|
||||
|
||||
## Obtaining the Hyprland Crash Report (v0.22.0beta and up)
|
||||
|
||||
|
14
example/hyprland-session.service
Normal file
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=Hyprland - Tiling compositor with the looks
|
||||
Documentation=man:Hyprland(1)
|
||||
BindsTo=graphical-session.target
|
||||
Before=graphical-session.target
|
||||
Wants=graphical-session-pre.target
|
||||
After=graphical-session-pre.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
ExecStart=/usr/bin/Hyprland
|
||||
ExecStop=/usr/bin/hyprctl dispatch exit
|
||||
Restart=on-failure
|
||||
Slice=session.slice
|
5
example/hyprland-systemd.desktop
Normal file
@@ -0,0 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Name=Hyprland
|
||||
Comment=An intelligent dynamic tiling Wayland compositor
|
||||
Exec=systemctl --user start --wait hyprland-session
|
||||
Type=Application
|
@@ -1,70 +1,97 @@
|
||||
# This is an example Hyprland config file.
|
||||
#
|
||||
# Refer to the wiki for more information.
|
||||
# https://wiki.hyprland.org/Configuring/Configuring-Hyprland/
|
||||
|
||||
#
|
||||
# Please note not all available settings / options are set here.
|
||||
# For a full list, see the wiki
|
||||
#
|
||||
|
||||
# You can split this configuration into multiple files
|
||||
# Create your files separately and then link them to this file like this:
|
||||
# source = ~/.config/hypr/myColors.conf
|
||||
|
||||
|
||||
################
|
||||
### MONITORS ###
|
||||
################
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Monitors/
|
||||
monitor=,preferred,auto,auto
|
||||
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||
###################
|
||||
### MY PROGRAMS ###
|
||||
###################
|
||||
|
||||
# Execute your favorite apps at launch
|
||||
# exec-once = waybar & hyprpaper & firefox
|
||||
|
||||
# Source a file (multi-file configs)
|
||||
# source = ~/.config/hypr/myColors.conf
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/
|
||||
|
||||
# Set programs that you use
|
||||
$terminal = kitty
|
||||
$fileManager = dolphin
|
||||
$menu = wofi --show drun
|
||||
|
||||
# Some default env vars.
|
||||
|
||||
#################
|
||||
### AUTOSTART ###
|
||||
#################
|
||||
|
||||
# Autostart necessary processes (like notifications daemons, status bars, etc.)
|
||||
# Or execute your favorite apps at launch like this:
|
||||
|
||||
# exec-once = $terminal
|
||||
# exec-once = nm-applet &
|
||||
# exec-once = waybar & hyprpaper & firefox
|
||||
|
||||
|
||||
#############################
|
||||
### ENVIRONMENT VARIABLES ###
|
||||
#############################
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Environment-variables/
|
||||
|
||||
env = XCURSOR_SIZE,24
|
||||
env = QT_QPA_PLATFORMTHEME,qt5ct # change to qt6ct if you have that
|
||||
env = HYPRCURSOR_SIZE,24
|
||||
|
||||
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
|
||||
input {
|
||||
kb_layout = us
|
||||
kb_variant =
|
||||
kb_model =
|
||||
kb_options =
|
||||
kb_rules =
|
||||
|
||||
follow_mouse = 1
|
||||
#####################
|
||||
### LOOK AND FEEL ###
|
||||
#####################
|
||||
|
||||
touchpad {
|
||||
natural_scroll = false
|
||||
}
|
||||
|
||||
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
|
||||
}
|
||||
# Refer to https://wiki.hyprland.org/Configuring/Variables/
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#general
|
||||
general {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
|
||||
gaps_in = 5
|
||||
gaps_out = 20
|
||||
|
||||
border_size = 2
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#variable-types for info about colors
|
||||
col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
|
||||
col.inactive_border = rgba(595959aa)
|
||||
|
||||
layout = dwindle
|
||||
# Set to true enable resizing windows by clicking and dragging on borders and gaps
|
||||
resize_on_border = false
|
||||
|
||||
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
|
||||
allow_tearing = false
|
||||
|
||||
layout = dwindle
|
||||
}
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#decoration
|
||||
decoration {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
|
||||
rounding = 10
|
||||
|
||||
# Change transparency of focused and unfocused windows
|
||||
active_opacity = 1.0
|
||||
inactive_opacity = 1.0
|
||||
|
||||
drop_shadow = true
|
||||
shadow_range = 4
|
||||
shadow_render_power = 3
|
||||
col.shadow = rgba(1a1a1aee)
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#blur
|
||||
blur {
|
||||
enabled = true
|
||||
size = 3
|
||||
@@ -72,17 +99,13 @@ decoration {
|
||||
|
||||
vibrancy = 0.1696
|
||||
}
|
||||
|
||||
drop_shadow = true
|
||||
shadow_range = 4
|
||||
shadow_render_power = 3
|
||||
col.shadow = rgba(1a1a1aee)
|
||||
}
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#animations
|
||||
animations {
|
||||
enabled = true
|
||||
|
||||
# Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
|
||||
# Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
|
||||
|
||||
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
|
||||
|
||||
@@ -94,25 +117,48 @@ animations {
|
||||
animation = workspaces, 1, 6, default
|
||||
}
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
|
||||
dwindle {
|
||||
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
|
||||
pseudotile = true # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
||||
preserve_split = true # you probably want this
|
||||
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
||||
preserve_split = true # You probably want this
|
||||
}
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
|
||||
master {
|
||||
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
|
||||
new_is_master = true
|
||||
}
|
||||
|
||||
gestures {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
workspace_swipe = false
|
||||
new_status = master
|
||||
}
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#misc
|
||||
misc {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
|
||||
disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :(
|
||||
}
|
||||
|
||||
|
||||
#############
|
||||
### INPUT ###
|
||||
#############
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#input
|
||||
input {
|
||||
kb_layout = us
|
||||
kb_variant =
|
||||
kb_model =
|
||||
kb_options =
|
||||
kb_rules =
|
||||
|
||||
follow_mouse = 1
|
||||
|
||||
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
|
||||
|
||||
touchpad {
|
||||
natural_scroll = false
|
||||
}
|
||||
}
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#gestures
|
||||
gestures {
|
||||
workspace_swipe = false
|
||||
}
|
||||
|
||||
# Example per-device config
|
||||
@@ -122,16 +168,13 @@ device {
|
||||
sensitivity = -0.5
|
||||
}
|
||||
|
||||
# Example windowrule v1
|
||||
# windowrule = float, ^(kitty)$
|
||||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||
|
||||
###################
|
||||
### KEYBINDINGS ###
|
||||
###################
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||
$mainMod = SUPER
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/
|
||||
$mainMod = SUPER # Sets "Windows" key as main modifier
|
||||
|
||||
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
|
||||
bind = $mainMod, Q, exec, $terminal
|
||||
@@ -184,3 +227,27 @@ bind = $mainMod, mouse_up, workspace, e-1
|
||||
# Move/resize windows with mainMod + LMB/RMB and dragging
|
||||
bindm = $mainMod, mouse:272, movewindow
|
||||
bindm = $mainMod, mouse:273, resizewindow
|
||||
|
||||
# Laptop multimedia keys for volume and LCD brightness
|
||||
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
|
||||
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
|
||||
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
|
||||
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
|
||||
bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
|
||||
bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
|
||||
|
||||
|
||||
##############################
|
||||
### WINDOWS AND WORKSPACES ###
|
||||
##############################
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||
# See https://wiki.hyprland.org/Configuring/Workspace-Rules/ for workspace rules
|
||||
|
||||
# Example windowrule v1
|
||||
# windowrule = float, ^(kitty)$
|
||||
|
||||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
|
||||
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||
|
@@ -1,2 +1,2 @@
|
||||
install_data('hyprland.conf', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
|
||||
install_data('hyprland.conf', install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime')
|
||||
install_data('hyprland.desktop', install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), install_tag: 'runtime')
|
||||
|
136
flake.lock
generated
@@ -1,5 +1,34 @@
|
||||
{
|
||||
"nodes": {
|
||||
"aquamarine": {
|
||||
"inputs": {
|
||||
"hyprutils": [
|
||||
"hyprutils"
|
||||
],
|
||||
"hyprwayland-scanner": [
|
||||
"hyprwayland-scanner"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1725199881,
|
||||
"narHash": "sha256-jsmipf/u1GFZE5tBUkr56CHMN6VpUWCAjfLIhvQijU0=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "aquamarine",
|
||||
"rev": "f8a687dd29ff019657498f1bd14da2fbbf0e604b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "aquamarine",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprcursor": {
|
||||
"inputs": {
|
||||
"hyprlang": [
|
||||
@@ -13,11 +42,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1712434681,
|
||||
"narHash": "sha256-qwmR2p1oc48Bj7gUDvb1oGL19Rjs2PmEmk4ChV01A5o=",
|
||||
"lastModified": 1722623071,
|
||||
"narHash": "sha256-sLADpVgebpCBFXkA1FlCXtvEPu1tdEsTfqK1hfeHySE=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprcursor",
|
||||
"rev": "818d8c4b69e0997483d60b75f701fe14b561a7a3",
|
||||
"rev": "912d56025f03d41b1ad29510c423757b4379eb1c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -29,18 +58,20 @@
|
||||
"hyprland-protocols": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"xdph",
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"xdph",
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1691753796,
|
||||
"narHash": "sha256-zOEwiWoXk3j3+EoF3ySUJmberFewWlagvewDRuWYAso=",
|
||||
"lastModified": 1721326555,
|
||||
"narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-protocols",
|
||||
"rev": "0c2ce70625cb30aef199cb388f99e19a61a6ce03",
|
||||
"rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -51,6 +82,9 @@
|
||||
},
|
||||
"hyprlang": {
|
||||
"inputs": {
|
||||
"hyprutils": [
|
||||
"hyprutils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
@@ -59,11 +93,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1711671891,
|
||||
"narHash": "sha256-C/Wwsy/RLxHP1axFFl+AnwJRWfd8gxDKKoa8nt8Qk3c=",
|
||||
"lastModified": 1725188252,
|
||||
"narHash": "sha256-yBH8c4GDaEAtBrh+BqIlrx5vp6gG/Gu8fQQK63KAQgs=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprlang",
|
||||
"rev": "c1402612146ba06606ebf64963a02bc1efe11e74",
|
||||
"rev": "c12ab785ce1982f82594aff03b3104c598186ddd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -72,13 +106,59 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprutils": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1724966483,
|
||||
"narHash": "sha256-WXDgKIbzjYKczxSZOsJplCS1i1yrTUpsDPuJV/xpYLo=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"rev": "8976e3f6a5357da953a09511d0c7f6a890fb6ec2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprwayland-scanner": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721324119,
|
||||
"narHash": "sha256-SOOqIT27/X792+vsLSeFdrNTF+OSRp5qXv6Te+fb2Qg=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprwayland-scanner",
|
||||
"rev": "a048a6cb015340bd82f97c1f40a4b595ca85cc30",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprwayland-scanner",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1712439257,
|
||||
"narHash": "sha256-aSpiNepFOMk9932HOax0XwNxbA38GOUVOiXfUVPOrck=",
|
||||
"lastModified": 1725103162,
|
||||
"narHash": "sha256-Ym04C5+qovuQDYL/rKWSR+WESseQBbNAe5DsXNx5trY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ff0dbd94265ac470dda06a657d5fe49de93b4599",
|
||||
"rev": "12228ff1752d7b7624a54e9c1af4b222b3c1073b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -90,12 +170,13 @@
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"aquamarine": "aquamarine",
|
||||
"hyprcursor": "hyprcursor",
|
||||
"hyprland-protocols": "hyprland-protocols",
|
||||
"hyprlang": "hyprlang",
|
||||
"hyprutils": "hyprutils",
|
||||
"hyprwayland-scanner": "hyprwayland-scanner",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"systems": "systems",
|
||||
"wlroots": "wlroots",
|
||||
"xdph": "xdph"
|
||||
}
|
||||
},
|
||||
@@ -114,28 +195,9 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"wlroots": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1712935342,
|
||||
"narHash": "sha256-zzIbTFNFd/as42jyGx23fil2uBDYYv+8GA5JmRq5y9c=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "wlroots-hyprland",
|
||||
"rev": "62eeffbe233d199f520a5755c344e85f8eab7940",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "wlroots-hyprland",
|
||||
"rev": "62eeffbe233d199f520a5755c344e85f8eab7940",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"xdph": {
|
||||
"inputs": {
|
||||
"hyprland-protocols": [
|
||||
"hyprland-protocols"
|
||||
],
|
||||
"hyprland-protocols": "hyprland-protocols",
|
||||
"hyprlang": [
|
||||
"hyprlang"
|
||||
],
|
||||
@@ -147,11 +209,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709299639,
|
||||
"narHash": "sha256-jYqJM5khksLIbqSxCLUUcqEgI+O2LdlSlcMEBs39CAU=",
|
||||
"lastModified": 1725203932,
|
||||
"narHash": "sha256-VLULC/OnI+6R9KEP2OIGk+uLJJsfRlaLouZ5gyFd2+Y=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "2d2fb547178ec025da643db57d40a971507b82fe",
|
||||
"rev": "2425e8f541525fa7409d9f26a8ffaf92a3767251",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
52
flake.nix
@@ -7,12 +7,12 @@
|
||||
# <https://github.com/nix-systems/nix-systems>
|
||||
systems.url = "github:nix-systems/default-linux";
|
||||
|
||||
wlroots = {
|
||||
type = "github";
|
||||
owner = "hyprwm";
|
||||
repo = "wlroots-hyprland";
|
||||
rev = "62eeffbe233d199f520a5755c344e85f8eab7940";
|
||||
flake = false;
|
||||
aquamarine = {
|
||||
url = "github:hyprwm/aquamarine";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
inputs.hyprutils.follows = "hyprutils";
|
||||
inputs.hyprwayland-scanner.follows = "hyprwayland-scanner";
|
||||
};
|
||||
|
||||
hyprcursor = {
|
||||
@@ -22,14 +22,21 @@
|
||||
inputs.hyprlang.follows = "hyprlang";
|
||||
};
|
||||
|
||||
hyprland-protocols = {
|
||||
url = "github:hyprwm/hyprland-protocols";
|
||||
hyprlang = {
|
||||
url = "github:hyprwm/hyprlang";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
inputs.hyprutils.follows = "hyprutils";
|
||||
};
|
||||
|
||||
hyprutils = {
|
||||
url = "github:hyprwm/hyprutils";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
};
|
||||
|
||||
hyprlang = {
|
||||
url = "github:hyprwm/hyprlang";
|
||||
hyprwayland-scanner = {
|
||||
url = "github:hyprwm/hyprwayland-scanner";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
};
|
||||
@@ -38,7 +45,6 @@
|
||||
url = "github:hyprwm/xdg-desktop-portal-hyprland";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
inputs.hyprland-protocols.follows = "hyprland-protocols";
|
||||
inputs.hyprlang.follows = "hyprlang";
|
||||
};
|
||||
};
|
||||
@@ -83,27 +89,22 @@
|
||||
# hyprland-extras
|
||||
|
||||
xdg-desktop-portal-hyprland
|
||||
# dependencies
|
||||
|
||||
hyprland-protocols
|
||||
wlroots-hyprland
|
||||
udis86
|
||||
;
|
||||
});
|
||||
|
||||
devShells = eachSystem (system: {
|
||||
default =
|
||||
pkgsFor.${system}.mkShell.override {
|
||||
stdenv = pkgsFor.${system}.gcc13Stdenv;
|
||||
stdenv = pkgsFor.${system}.gcc14Stdenv;
|
||||
} {
|
||||
name = "hyprland-shell";
|
||||
nativeBuildInputs = with pkgsFor.${system}; [cmake python3 expat libxml2];
|
||||
buildInputs = [self.packages.${system}.wlroots-hyprland];
|
||||
hardeningDisable = ["fortify"];
|
||||
inputsFrom = [
|
||||
self.packages.${system}.wlroots-hyprland
|
||||
self.packages.${system}.hyprland
|
||||
nativeBuildInputs = with pkgsFor.${system}; [
|
||||
expat
|
||||
libxml2
|
||||
];
|
||||
hardeningDisable = ["fortify"];
|
||||
inputsFrom = [pkgsFor.${system}.hyprland];
|
||||
packages = [pkgsFor.${system}.clang-tools];
|
||||
};
|
||||
});
|
||||
|
||||
@@ -112,9 +113,4 @@
|
||||
nixosModules.default = import ./nix/module.nix inputs;
|
||||
homeManagerModules.default = import ./nix/hm-module.nix self;
|
||||
};
|
||||
|
||||
nixConfig = {
|
||||
extra-substituters = ["https://hyprland.cachix.org"];
|
||||
extra-trusted-public-keys = ["hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc="];
|
||||
};
|
||||
}
|
||||
|
@@ -5,4 +5,21 @@ project(
|
||||
DESCRIPTION "Control utility for Hyprland"
|
||||
)
|
||||
|
||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET hyprutils>=0.1.1)
|
||||
|
||||
add_executable(hyprctl "main.cpp")
|
||||
|
||||
target_link_libraries(hyprctl PUBLIC PkgConfig::hyprctl_deps)
|
||||
|
||||
# binary
|
||||
install(TARGETS hyprctl)
|
||||
|
||||
# shell completions
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/hyprctl.bash
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/bash-completion/completions
|
||||
RENAME hyprctl)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/hyprctl.fish
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/fish/vendor_completions.d)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/hyprctl.zsh
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/zsh/site-functions
|
||||
RENAME _hyprctl)
|
||||
|
@@ -1,4 +0,0 @@
|
||||
all:
|
||||
$(CXX) $(CXXFLAGS) -std=c++2b ./main.cpp -o ./hyprctl
|
||||
clean:
|
||||
rm ./hyprctl
|
@@ -38,7 +38,8 @@ commands:
|
||||
plugin ... → Issue a plugin request
|
||||
reload [config-only] → Issue a reload to force reload the config. Pass
|
||||
'config-only' to disable monitor reload
|
||||
rollinglog → Prints tail of the log
|
||||
rollinglog → Prints tail of the log. Also supports -f/--follow
|
||||
option
|
||||
setcursor <theme> <size> → Sets the cursor theme and reloads the cursor
|
||||
manager
|
||||
seterror <color> <message...> → Sets the hyprctl error string. Color has
|
||||
@@ -60,6 +61,7 @@ flags:
|
||||
--batch → Execute a batch of commands, separated by ';'
|
||||
--instance (-i) → use a specific instance. Can be either signature or
|
||||
index in hyprctl instances (0, 1, etc)
|
||||
--quiet (-q) → Disable the output of hyprctl
|
||||
|
||||
--help:
|
||||
Can be used to print command's arguments that did not fit into this page
|
||||
|
@@ -1,19 +1,19 @@
|
||||
_hyprctl_cmd_2 () {
|
||||
hyprctl monitors | grep Monitor | awk '{ print $2 }'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_1 () {
|
||||
hyprpm list | grep "Plugin" | awk '{print $4}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_0 () {
|
||||
hyprctl clients | grep class | awk '{print $2}'
|
||||
hyprctl monitors | awk '/Monitor/{ print $2 }'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_3 () {
|
||||
hyprctl clients | awk '/class/{print $2}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_2 () {
|
||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_0 () {
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
}
|
||||
|
||||
_hyprctl () {
|
||||
if [[ $(type -t _get_comp_words_by_ref) != function ]]; then
|
||||
echo _get_comp_words_by_ref: function not defined. Make sure the bash-completions system package is installed
|
||||
@@ -23,25 +23,25 @@ _hyprctl () {
|
||||
local words cword
|
||||
_get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword
|
||||
|
||||
local -a literals=("cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow")
|
||||
|
||||
declare -a literals=(resizeactive 2 changegroupactive -r moveintogroup forceallowsinput 4 ::= systeminfo all layouts setprop animationstyle switchxkblayout create denywindowfromgroup headless activebordercolor exec setcursor wayland focusurgentorlast workspacerules movecurrentworkspacetomonitor movetoworkspacesilent hyprpaper alpha inactivebordercolor movegroupwindow movecursortocorner movewindowpixel prev movewindow globalshortcuts clients dimaround setignoregrouplock splash execr monitors 0 forcenoborder -q animations 1 nomaxsize splitratio moveactive pass swapnext devices layers rounding lockactivegroup 5 moveworkspacetomonitor -f -i --quiet forcenodim pin 0 1 forceopaque forcenoshadow setfloating minsize alphaoverride sendshortcut workspaces cyclenext alterzorder togglegroup lockgroups bordersize dpms focuscurrentorlast -1 --batch notify remove instances 1 3 moveoutofgroup killactive 2 movetoworkspace movecursor configerrors closewindow swapwindow tagwindow forcerendererreload centerwindow auto focuswindow seterror nofocus alphafullscreen binds version -h togglespecialworkspace fullscreen windowdancecompat 0 keyword toggleopaque 3 --instance togglefloating renameworkspace alphafullscreenoverride activeworkspace x11 kill forceopaqueoverriden output global dispatch reload forcenoblur -j event --help disable -1 activewindow keepaspectratio dismissnotify focusmonitor movefocus plugin exit workspace fullscreenstate getoption alphainactiveoverride alphainactive decorations settiled config-only descriptions resizewindowpixel fakefullscreen rollinglog swapactiveworkspaces submap next movewindoworgroup cursorpos forcenoanims focusworkspaceoncurrentmonitor maxsize)
|
||||
declare -A literal_transitions
|
||||
literal_transitions[0]="([103]=1 [74]=2 [33]=3 [1]=2 [2]=2 [77]=2 [105]=4 [36]=2 [108]=5 [40]=2 [45]=2 [112]=2 [84]=6 [113]=8 [51]=2 [53]=2 [88]=9 [117]=2 [119]=2 [121]=2 [15]=2 [58]=10 [59]=2 [17]=11 [122]=12 [19]=2 [124]=2 [126]=2 [25]=13 [67]=2 [96]=5 [97]=2 [27]=2 [28]=14 [100]=2 [102]=5)"
|
||||
literal_transitions[3]="([72]=18 [13]=2 [32]=18 [54]=18 [55]=18 [89]=18 [104]=2 [120]=2 [76]=1 [16]=2 [123]=18 [3]=1 [5]=2 [63]=18 [127]=2 [129]=18 [80]=18 [130]=18 [83]=18 [31]=18 [48]=2 [12]=2 [85]=18 [10]=18 [86]=18 [137]=18)"
|
||||
literal_transitions[7]="([103]=1 [74]=2 [33]=3 [1]=2 [2]=2 [77]=2 [105]=4 [36]=2 [40]=2 [45]=2 [112]=2 [84]=6 [113]=8 [51]=2 [53]=2 [88]=9 [117]=2 [119]=2 [121]=2 [15]=2 [58]=10 [59]=2 [17]=11 [122]=12 [19]=2 [124]=2 [126]=2 [25]=13 [67]=2 [97]=2 [27]=2 [28]=14 [100]=2)"
|
||||
literal_transitions[8]="([128]=2 [131]=2 [0]=2 [73]=2 [35]=2 [106]=2 [37]=2 [107]=2 [4]=2 [78]=2 [39]=2 [79]=2 [110]=2 [6]=2 [41]=2 [42]=2 [81]=2 [82]=2 [46]=2 [47]=2 [9]=2 [109]=2 [50]=2 [52]=2 [11]=2 [115]=2 [87]=2 [49]=2 [56]=2 [90]=2 [57]=2 [91]=2 [92]=2 [60]=2 [61]=2 [125]=2 [93]=2 [62]=2 [20]=2 [95]=2 [22]=2 [23]=2 [64]=2 [65]=2 [24]=2 [132]=2 [26]=2 [68]=2 [98]=2 [69]=2 [29]=2 [136]=2 [70]=2 [99]=2)"
|
||||
literal_transitions[9]="([114]=15 [111]=16)"
|
||||
literal_transitions[11]="([101]=2)"
|
||||
literal_transitions[13]="([21]=1 [116]=1 [30]=1 [135]=1 [118]=1 [43]=1 [71]=1)"
|
||||
literal_transitions[14]="([38]=2)"
|
||||
literal_transitions[15]="([8]=2 [66]=2 [14]=2 [133]=2)"
|
||||
literal_transitions[17]="([75]=19)"
|
||||
literal_transitions[18]="([18]=2 [7]=2)"
|
||||
literal_transitions[19]="([34]=5 [44]=5)"
|
||||
literal_transitions[20]="([134]=2 [94]=2)"
|
||||
|
||||
declare -A match_anything_transitions
|
||||
match_anything_transitions=([1]=2 [0]=7 [6]=2 [20]=2 [10]=2 [2]=17 [7]=7 [12]=2 [14]=17 [16]=2 [4]=20 [11]=17)
|
||||
literal_transitions[0]="([120]=14 [43]=2 [125]=21 [81]=2 [3]=21 [51]=2 [50]=2 [128]=2 [89]=2 [58]=21 [8]=2 [10]=2 [11]=3 [130]=4 [13]=5 [97]=6 [101]=2 [102]=21 [133]=7 [100]=2 [137]=2 [22]=2 [19]=2 [140]=8 [25]=2 [143]=2 [107]=9 [146]=10 [69]=2 [33]=2 [34]=2 [78]=21 [114]=2 [37]=2 [151]=2 [116]=2 [121]=13 [123]=21 [39]=11 [42]=21 [79]=15 [118]=12)"
|
||||
literal_transitions[1]="([81]=2 [51]=2 [50]=2 [128]=2 [8]=2 [89]=2 [10]=2 [11]=3 [130]=4 [13]=5 [97]=6 [101]=2 [133]=7 [100]=2 [22]=2 [19]=2 [137]=2 [140]=8 [25]=2 [143]=2 [107]=9 [146]=10 [69]=2 [33]=2 [34]=2 [114]=2 [37]=2 [151]=2 [116]=2 [39]=11 [118]=12 [121]=13 [120]=14 [79]=15 [43]=2)"
|
||||
literal_transitions[3]="([139]=2 [63]=16 [64]=16 [45]=16 [105]=16 [27]=2 [26]=2 [52]=4 [5]=16 [66]=2 [67]=16 [129]=16 [113]=16 [12]=2 [74]=4 [99]=2 [35]=16 [152]=16 [98]=16 [59]=16 [117]=16 [41]=16 [17]=2 [138]=16 [154]=2 [122]=16)"
|
||||
literal_transitions[6]="([126]=2)"
|
||||
literal_transitions[10]="([56]=2)"
|
||||
literal_transitions[11]="([9]=2)"
|
||||
literal_transitions[12]="([14]=19 [80]=22)"
|
||||
literal_transitions[13]="([142]=2)"
|
||||
literal_transitions[14]="([0]=2 [84]=2 [2]=2 [85]=2 [4]=2 [87]=2 [88]=2 [90]=2 [91]=2 [92]=2 [93]=2 [94]=2 [96]=2 [15]=2 [18]=2 [103]=2 [21]=2 [104]=2 [23]=2 [24]=2 [28]=2 [29]=2 [30]=2 [108]=2 [111]=2 [32]=2 [112]=2 [36]=2 [38]=2 [119]=2 [124]=2 [46]=2 [47]=2 [48]=2 [49]=2 [53]=2 [55]=2 [131]=2 [132]=2 [134]=2 [135]=2 [60]=2 [136]=20 [141]=2 [65]=2 [144]=2 [145]=2 [68]=2 [147]=2 [70]=2 [71]=2 [72]=2 [73]=2 [148]=2 [75]=2 [76]=2 [150]=2 [153]=2)"
|
||||
literal_transitions[15]="([86]=4 [6]=4 [109]=4 [61]=4 [77]=4 [54]=4 [62]=4)"
|
||||
literal_transitions[16]="([40]=2 [44]=2)"
|
||||
literal_transitions[17]="([7]=23)"
|
||||
literal_transitions[18]="([31]=2 [149]=2)"
|
||||
literal_transitions[19]="([95]=2 [16]=2 [115]=2 [20]=2)"
|
||||
literal_transitions[20]="([106]=2 [82]=2 [127]=2 [1]=2 [83]=2)"
|
||||
literal_transitions[23]="([57]=21 [110]=21)"
|
||||
declare -A match_anything_transitions=([6]=17 [7]=2 [0]=1 [22]=2 [5]=18 [4]=2 [2]=17 [18]=2 [11]=17 [8]=2 [9]=2 [13]=17 [10]=17 [1]=1)
|
||||
declare -A subword_transitions
|
||||
|
||||
local state=0
|
||||
@@ -79,21 +79,9 @@ _hyprctl () {
|
||||
done
|
||||
|
||||
|
||||
local -a matches=()
|
||||
|
||||
local prefix="${words[$cword]}"
|
||||
|
||||
local shortest_suffix="$word"
|
||||
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
|
||||
local char="${COMP_WORDBREAKS:$i:1}"
|
||||
local candidate="${word##*$char}"
|
||||
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
|
||||
shortest_suffix=$candidate
|
||||
fi
|
||||
done
|
||||
local superfluous_prefix=""
|
||||
if [[ "$shortest_suffix" != "$word" ]]; then
|
||||
local superfluous_prefix=${word%$shortest_suffix}
|
||||
fi
|
||||
|
||||
if [[ -v "literal_transitions[$state]" ]]; then
|
||||
local state_transitions_initializer=${literal_transitions[$state]}
|
||||
declare -A state_transitions
|
||||
@@ -102,25 +90,38 @@ _hyprctl () {
|
||||
for literal_id in "${!state_transitions[@]}"; do
|
||||
local literal="${literals[$literal_id]}"
|
||||
if [[ $literal = "${prefix}"* ]]; then
|
||||
local completion=${literal#"$superfluous_prefix"}
|
||||
COMPREPLY+=("$completion ")
|
||||
matches+=("$literal ")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
declare -A commands
|
||||
commands=([16]=2 [4]=3 [12]=1 [10]=0)
|
||||
commands=([7]=0 [22]=1 [8]=3 [5]=2)
|
||||
if [[ -v "commands[$state]" ]]; then
|
||||
local command_id=${commands[$state]}
|
||||
local completions=()
|
||||
mapfile -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1)
|
||||
readarray -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1)
|
||||
for item in "${completions[@]}"; do
|
||||
if [[ $item = "${prefix}"* ]]; then
|
||||
COMPREPLY+=("$item")
|
||||
matches+=("$item")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
local shortest_suffix="$prefix"
|
||||
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
|
||||
local char="${COMP_WORDBREAKS:$i:1}"
|
||||
local candidate=${prefix##*$char}
|
||||
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
|
||||
shortest_suffix=$candidate
|
||||
fi
|
||||
done
|
||||
local superfluous_prefix=""
|
||||
if [[ "$shortest_suffix" != "$prefix" ]]; then
|
||||
local superfluous_prefix=${prefix%$shortest_suffix}
|
||||
fi
|
||||
COMPREPLY=("${matches[@]#$superfluous_prefix}")
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
@@ -1,23 +1,23 @@
|
||||
function _hyprctl_3
|
||||
set 1 $argv[1]
|
||||
hyprctl monitors | grep Monitor | awk '{ print $2 }'
|
||||
end
|
||||
|
||||
function _hyprctl_2
|
||||
set 1 $argv[1]
|
||||
hyprpm list | grep "Plugin" | awk '{print $4}'
|
||||
end
|
||||
|
||||
function _hyprctl_1
|
||||
set 1 $argv[1]
|
||||
hyprctl clients | grep class | awk '{print $2}'
|
||||
hyprctl monitors | awk '/Monitor/{ print $2 }'
|
||||
end
|
||||
|
||||
function _hyprctl_4
|
||||
set 1 $argv[1]
|
||||
hyprctl clients | awk '/class/{print $2}'
|
||||
end
|
||||
|
||||
function _hyprctl_3
|
||||
set 1 $argv[1]
|
||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
||||
end
|
||||
|
||||
function _hyprctl_1
|
||||
set 1 $argv[1]
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
end
|
||||
|
||||
function _hyprctl
|
||||
set COMP_LINE (commandline --cut-at-cursor)
|
||||
|
||||
@@ -29,141 +29,160 @@ function _hyprctl
|
||||
set COMP_CWORD (count $COMP_WORDS)
|
||||
end
|
||||
|
||||
set --local literals "cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow"
|
||||
set literals "resizeactive" "2" "changegroupactive" "-r" "moveintogroup" "forceallowsinput" "4" "::=" "systeminfo" "all" "layouts" "setprop" "animationstyle" "switchxkblayout" "create" "denywindowfromgroup" "headless" "activebordercolor" "exec" "setcursor" "wayland" "focusurgentorlast" "workspacerules" "movecurrentworkspacetomonitor" "movetoworkspacesilent" "hyprpaper" "alpha" "inactivebordercolor" "movegroupwindow" "movecursortocorner" "movewindowpixel" "prev" "movewindow" "globalshortcuts" "clients" "dimaround" "setignoregrouplock" "splash" "execr" "monitors" "0" "forcenoborder" "-q" "animations" "1" "nomaxsize" "splitratio" "moveactive" "pass" "swapnext" "devices" "layers" "rounding" "lockactivegroup" "5" "moveworkspacetomonitor" "-f" "-i" "--quiet" "forcenodim" "pin" "0" "1" "forceopaque" "forcenoshadow" "setfloating" "minsize" "alphaoverride" "sendshortcut" "workspaces" "cyclenext" "alterzorder" "togglegroup" "lockgroups" "bordersize" "dpms" "focuscurrentorlast" "-1" "--batch" "notify" "remove" "instances" "1" "3" "moveoutofgroup" "killactive" "2" "movetoworkspace" "movecursor" "configerrors" "closewindow" "swapwindow" "tagwindow" "forcerendererreload" "centerwindow" "auto" "focuswindow" "seterror" "nofocus" "alphafullscreen" "binds" "version" "-h" "togglespecialworkspace" "fullscreen" "windowdancecompat" "0" "keyword" "toggleopaque" "3" "--instance" "togglefloating" "renameworkspace" "alphafullscreenoverride" "activeworkspace" "x11" "kill" "forceopaqueoverriden" "output" "global" "dispatch" "reload" "forcenoblur" "-j" "event" "--help" "disable" "-1" "activewindow" "keepaspectratio" "dismissnotify" "focusmonitor" "movefocus" "plugin" "exit" "workspace" "fullscreenstate" "getoption" "alphainactiveoverride" "alphainactive" "decorations" "settiled" "config-only" "descriptions" "resizewindowpixel" "fakefullscreen" "rollinglog" "swapactiveworkspaces" "submap" "next" "movewindoworgroup" "cursorpos" "forcenoanims" "focusworkspaceoncurrentmonitor" "maxsize"
|
||||
|
||||
set --local descriptions
|
||||
set descriptions[1] "Focus the next window on a workspace"
|
||||
set descriptions[3] "Get the current cursor pos in global layout coordinates"
|
||||
set descriptions[5] "Rename a workspace"
|
||||
set descriptions[7] "Focus the first window matching"
|
||||
set descriptions[10] "Swap the focused window with the next window"
|
||||
set descriptions[12] "Move the active window"
|
||||
set descriptions[16] "List the layers"
|
||||
set descriptions[18] "List active outputs with their properties"
|
||||
set descriptions[20] "Get into a kill mode, where you can kill an app by clicking on it"
|
||||
set descriptions[21] "Set the current window's floating state to false"
|
||||
set descriptions[22] "ERROR"
|
||||
set descriptions[23] "Focus a monitor"
|
||||
set descriptions[24] "Swap the active window with another window"
|
||||
set descriptions[25] "Move the active window out of a group"
|
||||
set descriptions[26] "Send a notification using the built-in Hyprland notification system"
|
||||
set descriptions[27] "Move the cursor to a specified position"
|
||||
set descriptions[28] "Set the cursor theme and reloads the cursor manager"
|
||||
set descriptions[29] "Set the hyprctl error string"
|
||||
set descriptions[30] "Move the active workspace to a monitor"
|
||||
set descriptions[31] "CONFUSED"
|
||||
set descriptions[34] "Set a property of a window"
|
||||
set descriptions[35] "Specify the Hyprland instance"
|
||||
set descriptions[36] "Toggle the current window's floating state"
|
||||
set descriptions[37] "Get the list of defined workspace rules"
|
||||
set descriptions[38] "Move the focused window to a workspace"
|
||||
set descriptions[40] "Temporarily enable or disable binds:ignore_group_lock"
|
||||
set descriptions[41] "List all workspaces with their properties"
|
||||
set descriptions[42] "Swap the active window with the next or previous in a group"
|
||||
set descriptions[43] "Close a specified window"
|
||||
set descriptions[44] "WARNING"
|
||||
set descriptions[45] "Specify the Hyprland instance"
|
||||
set descriptions[46] "List all registered binds"
|
||||
set descriptions[47] "Move the active window in a direction or to a monitor"
|
||||
set descriptions[48] "Change the split ratio"
|
||||
set descriptions[50] "Prohibit the active window from becoming or being inserted into group"
|
||||
set descriptions[51] "Change the workspace"
|
||||
set descriptions[52] "List all current config parsing errors"
|
||||
set descriptions[53] "Toggle the current active window into a group"
|
||||
set descriptions[54] "Get the config option status (values)"
|
||||
set descriptions[57] "Close the active window"
|
||||
set descriptions[58] "Pass the key to a specified window"
|
||||
set descriptions[59] "List all decorations and their info"
|
||||
set descriptions[60] "List all connected keyboards and mice"
|
||||
set descriptions[61] "Switch focus from current to previously focused window"
|
||||
set descriptions[62] "Change the current mapping group"
|
||||
set descriptions[63] "Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
set descriptions[65] "Force the renderer to reload all resources and outputs"
|
||||
set descriptions[66] "Move a selected window"
|
||||
set descriptions[68] "Print the Hyprland version: flags, commit and branch of build"
|
||||
set descriptions[69] "Set all monitors' DPMS status"
|
||||
set descriptions[70] "Resize the active window"
|
||||
set descriptions[71] "Move the active window into a group"
|
||||
set descriptions[72] "OK"
|
||||
set descriptions[74] "Set the current window's floating state to true"
|
||||
set descriptions[75] "Print tail of the log"
|
||||
set descriptions[78] "List all layouts available (including plugin ones)"
|
||||
set descriptions[79] "Move a workspace to a monitor"
|
||||
set descriptions[80] "Execute a shell command"
|
||||
set descriptions[82] "Modify the window stack order of the active or specified window"
|
||||
set descriptions[83] "Toggle the focused window's internal fullscreen state"
|
||||
set descriptions[85] "Issue a keyword to call a config keyword dynamically"
|
||||
set descriptions[88] "Pin a window"
|
||||
set descriptions[89] "Allows adding/removing fake outputs to a specific backend"
|
||||
set descriptions[91] "Toggle a special workspace on/off"
|
||||
set descriptions[92] "Toggle the focused window's fullscreen state"
|
||||
set descriptions[93] "Toggle the current window to always be opaque"
|
||||
set descriptions[94] "Focus the requested workspace"
|
||||
set descriptions[96] "Switch to the next window in a group"
|
||||
set descriptions[97] "Output in JSON format"
|
||||
set descriptions[98] "List all running Hyprland instances and their info"
|
||||
set descriptions[99] "Execute a raw shell command"
|
||||
set descriptions[100] "Exit the compositor with no questions asked"
|
||||
set descriptions[101] "List all windows with their properties"
|
||||
set descriptions[103] "Execute a batch of commands separated by ;"
|
||||
set descriptions[104] "Dismiss all or up to amount of notifications"
|
||||
set descriptions[106] "Set the xkb layout index for a keyboard"
|
||||
set descriptions[107] "Move window doesnt switch to the workspace"
|
||||
set descriptions[108] "Behave as moveintogroup"
|
||||
set descriptions[109] "Refresh state after issuing the command"
|
||||
set descriptions[110] "Move the focus in a direction"
|
||||
set descriptions[111] "Focus the urgent window or the last window"
|
||||
set descriptions[113] "Get the active workspace name and its properties"
|
||||
set descriptions[114] "Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
set descriptions[116] "Center the active window"
|
||||
set descriptions[117] "HINT"
|
||||
set descriptions[118] "Interact with hyprpaper if present"
|
||||
set descriptions[119] "No Icon"
|
||||
set descriptions[120] "Force reload the config"
|
||||
set descriptions[122] "Print system info"
|
||||
set descriptions[123] "Interact with a plugin"
|
||||
set descriptions[125] "Get the active window name and its properties"
|
||||
set descriptions[126] "Swap the active workspaces between two monitors"
|
||||
set descriptions[127] "Print the current random splash"
|
||||
set descriptions[129] "Lock the focused group"
|
||||
set descriptions[132] "Lock the groups"
|
||||
set descriptions[133] "Move the cursor to the corner of the active window"
|
||||
set descriptions[136] "INFO"
|
||||
set descriptions[137] "Resize a selected window"
|
||||
set descriptions
|
||||
set descriptions[1] "Resize the active window"
|
||||
set descriptions[2] "Fullscreen"
|
||||
set descriptions[3] "Switch to the next window in a group"
|
||||
set descriptions[4] "Refresh state after issuing the command"
|
||||
set descriptions[5] "Move the active window into a group"
|
||||
set descriptions[7] "CONFUSED"
|
||||
set descriptions[9] "Print system info"
|
||||
set descriptions[11] "List all layouts available (including plugin ones)"
|
||||
set descriptions[12] "Set a property of a window"
|
||||
set descriptions[14] "Set the xkb layout index for a keyboard"
|
||||
set descriptions[16] "Prohibit the active window from becoming or being inserted into group"
|
||||
set descriptions[19] "Execute a shell command"
|
||||
set descriptions[20] "Set the cursor theme and reloads the cursor manager"
|
||||
set descriptions[22] "Focus the urgent window or the last window"
|
||||
set descriptions[23] "Get the list of defined workspace rules"
|
||||
set descriptions[24] "Move the active workspace to a monitor"
|
||||
set descriptions[25] "Move window doesnt switch to the workspace"
|
||||
set descriptions[26] "Interact with hyprpaper if present"
|
||||
set descriptions[29] "Swap the active window with the next or previous in a group"
|
||||
set descriptions[30] "Move the cursor to the corner of the active window"
|
||||
set descriptions[31] "Move a selected window"
|
||||
set descriptions[33] "Move the active window in a direction or to a monitor"
|
||||
set descriptions[34] "Lists all global shortcuts"
|
||||
set descriptions[35] "List all windows with their properties"
|
||||
set descriptions[37] "Temporarily enable or disable binds:ignore_group_lock"
|
||||
set descriptions[38] "Print the current random splash"
|
||||
set descriptions[39] "Execute a raw shell command"
|
||||
set descriptions[40] "List active outputs with their properties"
|
||||
set descriptions[43] "Disable output"
|
||||
set descriptions[44] "Gets the current config info about animations and beziers"
|
||||
set descriptions[47] "Change the split ratio"
|
||||
set descriptions[48] "Move the active window"
|
||||
set descriptions[49] "Pass the key to a specified window"
|
||||
set descriptions[50] "Swap the focused window with the next window"
|
||||
set descriptions[51] "List all connected keyboards and mice"
|
||||
set descriptions[52] "List the layers"
|
||||
set descriptions[54] "Lock the focused group"
|
||||
set descriptions[55] "OK"
|
||||
set descriptions[56] "Move a workspace to a monitor"
|
||||
set descriptions[58] "Specify the Hyprland instance"
|
||||
set descriptions[59] "Disable output"
|
||||
set descriptions[61] "Pin a window"
|
||||
set descriptions[62] "WARNING"
|
||||
set descriptions[63] "INFO"
|
||||
set descriptions[66] "Set the current window's floating state to true"
|
||||
set descriptions[69] "On shortcut X sends shortcut Y to a specified window"
|
||||
set descriptions[70] "List all workspaces with their properties"
|
||||
set descriptions[71] "Focus the next window on a workspace"
|
||||
set descriptions[72] "Modify the window stack order of the active or specified window"
|
||||
set descriptions[73] "Toggle the current active window into a group"
|
||||
set descriptions[74] "Lock the groups"
|
||||
set descriptions[76] "Set all monitors' DPMS status"
|
||||
set descriptions[77] "Switch focus from current to previously focused window"
|
||||
set descriptions[78] "No Icon"
|
||||
set descriptions[79] "Execute a batch of commands separated by ;"
|
||||
set descriptions[80] "Send a notification using the built-in Hyprland notification system"
|
||||
set descriptions[82] "List all running Hyprland instances and their info"
|
||||
set descriptions[83] "Maximize no fullscreen"
|
||||
set descriptions[84] "Maximize and fullscreen"
|
||||
set descriptions[85] "Move the active window out of a group"
|
||||
set descriptions[86] "Close the active window"
|
||||
set descriptions[87] "HINT"
|
||||
set descriptions[88] "Move the focused window to a workspace"
|
||||
set descriptions[89] "Move the cursor to a specified position"
|
||||
set descriptions[90] "List all current config parsing errors"
|
||||
set descriptions[91] "Close a specified window"
|
||||
set descriptions[92] "Swap the active window with another window"
|
||||
set descriptions[93] "Apply a tag to the window"
|
||||
set descriptions[94] "Force the renderer to reload all resources and outputs"
|
||||
set descriptions[95] "Center the active window"
|
||||
set descriptions[97] "Focus the first window matching"
|
||||
set descriptions[98] "Set the hyprctl error string"
|
||||
set descriptions[101] "List all registered binds"
|
||||
set descriptions[102] "Print the Hyprland version: flags, commit and branch of build"
|
||||
set descriptions[103] "Prints the help message"
|
||||
set descriptions[104] "Toggle a special workspace on/off"
|
||||
set descriptions[105] "Toggle the focused window's fullscreen state"
|
||||
set descriptions[107] "None"
|
||||
set descriptions[108] "Issue a keyword to call a config keyword dynamically"
|
||||
set descriptions[109] "Toggle the current window to always be opaque"
|
||||
set descriptions[110] "ERROR"
|
||||
set descriptions[111] "Specify the Hyprland instance"
|
||||
set descriptions[112] "Toggle the current window's floating state"
|
||||
set descriptions[113] "Rename a workspace"
|
||||
set descriptions[115] "Get the active workspace name and its properties"
|
||||
set descriptions[117] "Get into a kill mode, where you can kill an app by clicking on it"
|
||||
set descriptions[119] "Allows adding/removing fake outputs to a specific backend"
|
||||
set descriptions[120] "Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
set descriptions[121] "Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
set descriptions[122] "Force reload the config"
|
||||
set descriptions[124] "Output in JSON format"
|
||||
set descriptions[125] "Emits a custom event to socket2"
|
||||
set descriptions[126] "Prints the help message"
|
||||
set descriptions[128] "Current"
|
||||
set descriptions[129] "Get the active window name and its properties"
|
||||
set descriptions[131] "Dismiss all or up to amount of notifications"
|
||||
set descriptions[132] "Focus a monitor"
|
||||
set descriptions[133] "Move the focus in a direction"
|
||||
set descriptions[134] "Interact with a plugin"
|
||||
set descriptions[135] "Exit the compositor with no questions asked"
|
||||
set descriptions[136] "Change the workspace"
|
||||
set descriptions[137] "Sets the focused window’s fullscreen mode and the one sent to the client"
|
||||
set descriptions[138] "Get the config option status (values)"
|
||||
set descriptions[141] "List all decorations and their info"
|
||||
set descriptions[142] "Set the current window's floating state to false"
|
||||
set descriptions[144] "Return a parsable JSON with all the config options, descriptions, value types and ranges"
|
||||
set descriptions[145] "Resize a selected window"
|
||||
set descriptions[146] "Toggle the focused window's internal fullscreen state"
|
||||
set descriptions[147] "Print tail of the log"
|
||||
set descriptions[148] "Swap the active workspaces between two monitors"
|
||||
set descriptions[149] "Change the current mapping group"
|
||||
set descriptions[151] "Behave as moveintogroup"
|
||||
set descriptions[152] "Get the current cursor pos in global layout coordinates"
|
||||
set descriptions[154] "Focus the requested workspace"
|
||||
|
||||
set --local literal_transitions
|
||||
set literal_transitions[1] "set inputs 104 75 34 2 3 78 106 37 109 41 46 113 85 114 52 54 89 118 120 122 16 59 60 18 123 20 125 127 26 68 97 98 28 29 101 103; set tos 2 3 4 3 3 3 5 3 6 3 3 3 7 9 3 3 10 3 3 3 3 11 3 12 13 3 3 3 14 3 6 3 3 15 3 6"
|
||||
set literal_transitions[4] "set inputs 73 14 33 55 56 90 105 121 77 17 124 4 6 64 128 130 81 131 84 32 49 13 86 11 87 138; set tos 19 3 19 19 19 19 3 3 2 3 19 2 3 19 3 19 19 19 19 19 3 3 19 19 19 19"
|
||||
set literal_transitions[8] "set inputs 104 75 34 2 3 78 106 37 41 46 113 85 114 52 54 89 118 120 122 16 59 60 18 123 20 125 127 26 68 98 28 29 101; set tos 2 3 4 3 3 3 5 3 3 3 3 7 9 3 3 10 3 3 3 3 11 3 12 13 3 3 3 14 3 3 3 15 3"
|
||||
set literal_transitions[9] "set inputs 129 132 1 74 36 107 38 108 5 79 40 80 111 7 42 43 82 83 47 48 10 110 51 53 12 116 88 50 57 91 58 92 93 61 62 126 94 63 21 96 23 24 65 66 25 133 27 69 99 70 30 137 71 100; set tos 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3"
|
||||
set literal_transitions[10] "set inputs 115 112; set tos 16 17"
|
||||
set literal_transitions[12] "set inputs 102; set tos 3"
|
||||
set literal_transitions[14] "set inputs 22 117 31 136 119 44 72; set tos 2 2 2 2 2 2 2"
|
||||
set literal_transitions[15] "set inputs 39; set tos 3"
|
||||
set literal_transitions[16] "set inputs 9 67 15 134; set tos 3 3 3 3"
|
||||
set literal_transitions[18] "set inputs 76; set tos 20"
|
||||
set literal_transitions[19] "set inputs 19 8; set tos 3 3"
|
||||
set literal_transitions[20] "set inputs 35 45; set tos 6 6"
|
||||
set literal_transitions[21] "set inputs 135 95; set tos 3 3"
|
||||
set literal_transitions
|
||||
set literal_transitions[1] "set inputs 121 44 126 82 4 52 51 129 90 59 9 11 12 131 14 98 102 103 134 101 138 23 20 141 26 144 108 147 70 34 35 79 115 38 152 117 122 124 40 43 80 119; set tos 15 3 22 3 22 3 3 3 3 22 3 3 4 5 6 7 3 22 8 3 3 3 3 9 3 3 10 11 3 3 3 22 3 3 3 3 14 22 12 22 16 13"
|
||||
set literal_transitions[2] "set inputs 82 52 51 129 9 90 11 12 131 14 98 102 134 101 23 20 138 141 26 144 108 147 70 34 35 115 38 152 117 40 119 122 121 80 44; set tos 3 3 3 3 3 3 3 4 5 6 7 3 8 3 3 3 3 9 3 3 10 11 3 3 3 3 3 3 3 12 13 14 15 16 3"
|
||||
set literal_transitions[4] "set inputs 140 64 65 46 106 28 27 53 6 67 68 130 114 13 75 100 36 153 99 60 118 42 18 139 155 123; set tos 3 17 17 17 17 3 3 5 17 3 17 17 17 3 5 3 17 17 17 17 17 17 3 17 3 17"
|
||||
set literal_transitions[7] "set inputs 127; set tos 3"
|
||||
set literal_transitions[11] "set inputs 57; set tos 3"
|
||||
set literal_transitions[12] "set inputs 10; set tos 3"
|
||||
set literal_transitions[13] "set inputs 15 81; set tos 20 23"
|
||||
set literal_transitions[14] "set inputs 143; set tos 3"
|
||||
set literal_transitions[15] "set inputs 1 85 3 86 5 88 89 91 92 93 94 95 97 16 19 104 22 105 24 25 29 30 31 109 112 33 113 37 39 120 125 47 48 49 50 54 56 132 133 135 136 61 137 142 66 145 146 69 148 71 72 73 74 149 76 77 151 154; set tos 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 21 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3"
|
||||
set literal_transitions[16] "set inputs 87 7 110 62 78 55 63; set tos 5 5 5 5 5 5 5"
|
||||
set literal_transitions[17] "set inputs 41 45; set tos 3 3"
|
||||
set literal_transitions[18] "set inputs 8; set tos 24"
|
||||
set literal_transitions[19] "set inputs 32 150; set tos 3 3"
|
||||
set literal_transitions[20] "set inputs 96 17 116 21; set tos 3 3 3 3"
|
||||
set literal_transitions[21] "set inputs 107 83 128 2 84; set tos 3 3 3 3 3"
|
||||
set literal_transitions[24] "set inputs 58 111; set tos 22 22"
|
||||
|
||||
set --local match_anything_transitions_from 2 1 7 21 11 3 8 13 15 17 5 12
|
||||
set --local match_anything_transitions_to 3 8 3 3 3 18 8 3 18 3 21 18
|
||||
set match_anything_transitions_from 7 8 1 23 6 5 3 19 12 9 10 14 11 2
|
||||
set match_anything_transitions_to 18 3 2 3 19 3 18 3 18 3 3 18 18 2
|
||||
|
||||
set --local state 1
|
||||
set --local word_index 2
|
||||
set state 1
|
||||
set word_index 2
|
||||
while test $word_index -lt $COMP_CWORD
|
||||
set --local -- word $COMP_WORDS[$word_index]
|
||||
set -- word $COMP_WORDS[$word_index]
|
||||
|
||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
eval $literal_transitions[$state]
|
||||
|
||||
if contains -- $word $literals
|
||||
set --local literal_matched 0
|
||||
set literal_matched 0
|
||||
for literal_id in (seq 1 (count $literals))
|
||||
if test $literals[$literal_id] = $word
|
||||
set --local index (contains --index -- $literal_id $inputs)
|
||||
set index (contains --index -- $literal_id $inputs)
|
||||
set state $tos[$index]
|
||||
set word_index (math $word_index + 1)
|
||||
set literal_matched 1
|
||||
@@ -177,7 +196,7 @@ function _hyprctl
|
||||
end
|
||||
|
||||
if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state]
|
||||
set --local index (contains --index -- $state $match_anything_transitions_from)
|
||||
set index (contains --index -- $state $match_anything_transitions_from)
|
||||
set state $match_anything_transitions_to[$index]
|
||||
set word_index (math $word_index + 1)
|
||||
continue
|
||||
@@ -187,8 +206,8 @@ function _hyprctl
|
||||
end
|
||||
|
||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
eval $literal_transitions[$state]
|
||||
for literal_id in $inputs
|
||||
if test -n $descriptions[$literal_id]
|
||||
@@ -199,14 +218,14 @@ function _hyprctl
|
||||
end
|
||||
end
|
||||
|
||||
set command_states 17 5 13 11
|
||||
set command_ids 3 4 2 1
|
||||
set command_states 8 23 9 6
|
||||
set command_ids 1 2 4 3
|
||||
if contains $state $command_states
|
||||
set --local index (contains --index $state $command_states)
|
||||
set --local function_id $command_ids[$index]
|
||||
set --local function_name _hyprctl_$function_id
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set index (contains --index $state $command_states)
|
||||
set function_id $command_ids[$index]
|
||||
set function_name _hyprctl_$function_id
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
$function_name "$COMP_WORDS[$COMP_CWORD]"
|
||||
end
|
||||
|
||||
|
@@ -8,13 +8,15 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
||||
| (-j) "Output in JSON format"
|
||||
| (-r) "Refresh state after issuing the command"
|
||||
| (--batch) "Execute a batch of commands separated by ;"
|
||||
| (-q | --quiet) "Disable output"
|
||||
| (-h | --help) "Prints the help message"
|
||||
;
|
||||
|
||||
<WINDOWS> ::= {{{ hyprctl clients | grep class | awk '{print $2}' }}};
|
||||
<WINDOWS> ::= {{{ hyprctl clients | awk '/class/{print $2}' }}};
|
||||
|
||||
<AVAILABLE_PLUGINS> ::= {{{ hyprpm list | grep "Plugin" | awk '{print $4}' }}};
|
||||
<AVAILABLE_PLUGINS> ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}};
|
||||
|
||||
<MONITORS> ::= {{{ hyprctl monitors | grep Monitor | awk '{ print $2 }' }}};
|
||||
<MONITORS> ::= {{{ hyprctl monitors | awk '/Monitor/{ print $2 }' }}};
|
||||
|
||||
<KEYBOARDS> ::= {{{ hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' }}};
|
||||
|
||||
@@ -58,16 +60,18 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
||||
|
||||
<ARGUMENTS> ::= (activewindow) "Get the active window name and its properties"
|
||||
| (activeworkspace) "Get the active workspace name and its properties"
|
||||
| (animations) "Gets the current config info about animations and beziers"
|
||||
| (binds) "List all registered binds"
|
||||
| (clients) "List all windows with their properties"
|
||||
| (configerrors) "List all current config parsing errors"
|
||||
| (cursorpos) "Get the current cursor pos in global layout coordinates"
|
||||
| (decorations <WINDOWS>) "List all decorations and their info"
|
||||
| (descriptions) "Return a parsable JSON with all the config options, descriptions, value types and ranges"
|
||||
| (devices) "List all connected keyboards and mice"
|
||||
| (dismissnotify <NUM>) "Dismiss all or up to amount of notifications"
|
||||
| (dispatch <DISPATCHERS>) "Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
| (getoption) "Get the config option status (values)"
|
||||
| (globalshortcuts) ""
|
||||
| (globalshortcuts) "Lists all global shortcuts"
|
||||
| (hyprpaper) "Interact with hyprpaper if present"
|
||||
| (instances) "List all running Hyprland instances and their info"
|
||||
| (keyword <KEYWORDS>) "Issue a keyword to call a config keyword dynamically"
|
||||
@@ -78,8 +82,8 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
||||
| (notify <NOTIFICATION_TYPES> <NUM>) "Send a notification using the built-in Hyprland notification system"
|
||||
| (output (create (wayland | x11 | headless | auto) | remove <MONITORS>)) "Allows adding/removing fake outputs to a specific backend"
|
||||
| (plugin <AVAILABLE_PLUGINS>) "Interact with a plugin"
|
||||
| (reload) "Force reload the config"
|
||||
| (rollinglog) "Print tail of the log"
|
||||
| (reload [config-only]) "Force reload the config"
|
||||
| (rollinglog [-f]) "Print tail of the log"
|
||||
| (setcursor) "Set the cursor theme and reloads the cursor manager"
|
||||
| (seterror [disable]) "Set the hyprctl error string"
|
||||
| (setprop <PROPS>) "Set a property of a window"
|
||||
@@ -91,9 +95,17 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
||||
| (workspaces) "List all workspaces with their properties"
|
||||
;
|
||||
|
||||
<WINDOW_STATE> ::= (-1) "Current"
|
||||
| (0) "None"
|
||||
| (1) "Maximize no fullscreen"
|
||||
| (2) "Fullscreen"
|
||||
| (3) "Maximize and fullscreen"
|
||||
;
|
||||
|
||||
<DISPATCHERS> ::= (exec) "Execute a shell command"
|
||||
| (execr) "Execute a raw shell command"
|
||||
| (pass) "Pass the key to a specified window"
|
||||
| (sendshortcut) "On shortcut X sends shortcut Y to a specified window"
|
||||
| (killactive) "Close the active window"
|
||||
| (closewindow) "Close a specified window"
|
||||
| (workspace) "Change the workspace"
|
||||
@@ -104,6 +116,7 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
||||
| (settiled) "Set the current window's floating state to false"
|
||||
| (fullscreen) "Toggle the focused window's fullscreen state"
|
||||
| (fakefullscreen) "Toggle the focused window's internal fullscreen state"
|
||||
| (fullscreenstate <WINDOW_STATE>) "Sets the focused window’s fullscreen mode and the one sent to the client"
|
||||
| (dpms) "Set all monitors' DPMS status"
|
||||
| (pin) "Pin a window"
|
||||
| (movefocus) "Move the focus in a direction"
|
||||
@@ -116,6 +129,7 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
||||
| (movewindowpixel) "Move a selected window"
|
||||
| (cyclenext) "Focus the next window on a workspace"
|
||||
| (swapnext) "Swap the focused window with the next window"
|
||||
| (tagwindow) "Apply a tag to the window"
|
||||
| (focuswindow) "Focus the first window matching"
|
||||
| (focusmonitor) "Focus a monitor"
|
||||
| (splitratio) "Change the split ratio"
|
||||
@@ -145,4 +159,5 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
|
||||
| (setignoregrouplock) "Temporarily enable or disable binds:ignore_group_lock"
|
||||
| (global) "Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
| (submap) "Change the current mapping group"
|
||||
| (event) "Emits a custom event to socket2"
|
||||
;
|
||||
|
@@ -1,141 +1,160 @@
|
||||
#compdef hyprctl
|
||||
|
||||
_hyprctl_cmd_2 () {
|
||||
hyprctl monitors | grep Monitor | awk '{ print $2 }'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_1 () {
|
||||
hyprpm list | grep "Plugin" | awk '{print $4}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_0 () {
|
||||
hyprctl clients | grep class | awk '{print $2}'
|
||||
hyprctl monitors | awk '/Monitor/{ print $2 }'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_3 () {
|
||||
hyprctl clients | awk '/class/{print $2}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_2 () {
|
||||
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
|
||||
}
|
||||
|
||||
_hyprctl_cmd_0 () {
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
}
|
||||
|
||||
_hyprctl () {
|
||||
local -a literals=("cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow")
|
||||
local -a literals=("resizeactive" "2" "changegroupactive" "-r" "moveintogroup" "forceallowsinput" "4" "::=" "systeminfo" "all" "layouts" "setprop" "animationstyle" "switchxkblayout" "create" "denywindowfromgroup" "headless" "activebordercolor" "exec" "setcursor" "wayland" "focusurgentorlast" "workspacerules" "movecurrentworkspacetomonitor" "movetoworkspacesilent" "hyprpaper" "alpha" "inactivebordercolor" "movegroupwindow" "movecursortocorner" "movewindowpixel" "prev" "movewindow" "globalshortcuts" "clients" "dimaround" "setignoregrouplock" "splash" "execr" "monitors" "0" "forcenoborder" "-q" "animations" "1" "nomaxsize" "splitratio" "moveactive" "pass" "swapnext" "devices" "layers" "rounding" "lockactivegroup" "5" "moveworkspacetomonitor" "-f" "-i" "--quiet" "forcenodim" "pin" "0" "1" "forceopaque" "forcenoshadow" "setfloating" "minsize" "alphaoverride" "sendshortcut" "workspaces" "cyclenext" "alterzorder" "togglegroup" "lockgroups" "bordersize" "dpms" "focuscurrentorlast" "-1" "--batch" "notify" "remove" "instances" "1" "3" "moveoutofgroup" "killactive" "2" "movetoworkspace" "movecursor" "configerrors" "closewindow" "swapwindow" "tagwindow" "forcerendererreload" "centerwindow" "auto" "focuswindow" "seterror" "nofocus" "alphafullscreen" "binds" "version" "-h" "togglespecialworkspace" "fullscreen" "windowdancecompat" "0" "keyword" "toggleopaque" "3" "--instance" "togglefloating" "renameworkspace" "alphafullscreenoverride" "activeworkspace" "x11" "kill" "forceopaqueoverriden" "output" "global" "dispatch" "reload" "forcenoblur" "-j" "event" "--help" "disable" "-1" "activewindow" "keepaspectratio" "dismissnotify" "focusmonitor" "movefocus" "plugin" "exit" "workspace" "fullscreenstate" "getoption" "alphainactiveoverride" "alphainactive" "decorations" "settiled" "config-only" "descriptions" "resizewindowpixel" "fakefullscreen" "rollinglog" "swapactiveworkspaces" "submap" "next" "movewindoworgroup" "cursorpos" "forcenoanims" "focusworkspaceoncurrentmonitor" "maxsize")
|
||||
|
||||
local -A descriptions
|
||||
descriptions[1]="Focus the next window on a workspace"
|
||||
descriptions[3]="Get the current cursor pos in global layout coordinates"
|
||||
descriptions[5]="Rename a workspace"
|
||||
descriptions[7]="Focus the first window matching"
|
||||
descriptions[10]="Swap the focused window with the next window"
|
||||
descriptions[12]="Move the active window"
|
||||
descriptions[16]="List the layers"
|
||||
descriptions[18]="List active outputs with their properties"
|
||||
descriptions[20]="Get into a kill mode, where you can kill an app by clicking on it"
|
||||
descriptions[21]="Set the current window's floating state to false"
|
||||
descriptions[22]="ERROR"
|
||||
descriptions[23]="Focus a monitor"
|
||||
descriptions[24]="Swap the active window with another window"
|
||||
descriptions[25]="Move the active window out of a group"
|
||||
descriptions[26]="Send a notification using the built-in Hyprland notification system"
|
||||
descriptions[27]="Move the cursor to a specified position"
|
||||
descriptions[28]="Set the cursor theme and reloads the cursor manager"
|
||||
descriptions[29]="Set the hyprctl error string"
|
||||
descriptions[30]="Move the active workspace to a monitor"
|
||||
descriptions[31]="CONFUSED"
|
||||
descriptions[34]="Set a property of a window"
|
||||
descriptions[35]="Specify the Hyprland instance"
|
||||
descriptions[36]="Toggle the current window's floating state"
|
||||
descriptions[37]="Get the list of defined workspace rules"
|
||||
descriptions[38]="Move the focused window to a workspace"
|
||||
descriptions[40]="Temporarily enable or disable binds:ignore_group_lock"
|
||||
descriptions[41]="List all workspaces with their properties"
|
||||
descriptions[42]="Swap the active window with the next or previous in a group"
|
||||
descriptions[43]="Close a specified window"
|
||||
descriptions[44]="WARNING"
|
||||
descriptions[45]="Specify the Hyprland instance"
|
||||
descriptions[46]="List all registered binds"
|
||||
descriptions[47]="Move the active window in a direction or to a monitor"
|
||||
descriptions[48]="Change the split ratio"
|
||||
descriptions[50]="Prohibit the active window from becoming or being inserted into group"
|
||||
descriptions[51]="Change the workspace"
|
||||
descriptions[52]="List all current config parsing errors"
|
||||
descriptions[53]="Toggle the current active window into a group"
|
||||
descriptions[54]="Get the config option status (values)"
|
||||
descriptions[57]="Close the active window"
|
||||
descriptions[58]="Pass the key to a specified window"
|
||||
descriptions[59]="List all decorations and their info"
|
||||
descriptions[60]="List all connected keyboards and mice"
|
||||
descriptions[61]="Switch focus from current to previously focused window"
|
||||
descriptions[62]="Change the current mapping group"
|
||||
descriptions[63]="Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
descriptions[65]="Force the renderer to reload all resources and outputs"
|
||||
descriptions[66]="Move a selected window"
|
||||
descriptions[68]="Print the Hyprland version: flags, commit and branch of build"
|
||||
descriptions[69]="Set all monitors' DPMS status"
|
||||
descriptions[70]="Resize the active window"
|
||||
descriptions[71]="Move the active window into a group"
|
||||
descriptions[72]="OK"
|
||||
descriptions[74]="Set the current window's floating state to true"
|
||||
descriptions[75]="Print tail of the log"
|
||||
descriptions[78]="List all layouts available (including plugin ones)"
|
||||
descriptions[79]="Move a workspace to a monitor"
|
||||
descriptions[80]="Execute a shell command"
|
||||
descriptions[82]="Modify the window stack order of the active or specified window"
|
||||
descriptions[83]="Toggle the focused window's internal fullscreen state"
|
||||
descriptions[85]="Issue a keyword to call a config keyword dynamically"
|
||||
descriptions[88]="Pin a window"
|
||||
descriptions[89]="Allows adding/removing fake outputs to a specific backend"
|
||||
descriptions[91]="Toggle a special workspace on/off"
|
||||
descriptions[92]="Toggle the focused window's fullscreen state"
|
||||
descriptions[93]="Toggle the current window to always be opaque"
|
||||
descriptions[94]="Focus the requested workspace"
|
||||
descriptions[96]="Switch to the next window in a group"
|
||||
descriptions[97]="Output in JSON format"
|
||||
descriptions[98]="List all running Hyprland instances and their info"
|
||||
descriptions[99]="Execute a raw shell command"
|
||||
descriptions[100]="Exit the compositor with no questions asked"
|
||||
descriptions[101]="List all windows with their properties"
|
||||
descriptions[103]="Execute a batch of commands separated by ;"
|
||||
descriptions[104]="Dismiss all or up to amount of notifications"
|
||||
descriptions[106]="Set the xkb layout index for a keyboard"
|
||||
descriptions[107]="Move window doesnt switch to the workspace"
|
||||
descriptions[108]="Behave as moveintogroup"
|
||||
descriptions[109]="Refresh state after issuing the command"
|
||||
descriptions[110]="Move the focus in a direction"
|
||||
descriptions[111]="Focus the urgent window or the last window"
|
||||
descriptions[113]="Get the active workspace name and its properties"
|
||||
descriptions[114]="Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
descriptions[116]="Center the active window"
|
||||
descriptions[117]="HINT"
|
||||
descriptions[118]="Interact with hyprpaper if present"
|
||||
descriptions[119]="No Icon"
|
||||
descriptions[120]="Force reload the config"
|
||||
descriptions[122]="Print system info"
|
||||
descriptions[123]="Interact with a plugin"
|
||||
descriptions[125]="Get the active window name and its properties"
|
||||
descriptions[126]="Swap the active workspaces between two monitors"
|
||||
descriptions[127]="Print the current random splash"
|
||||
descriptions[129]="Lock the focused group"
|
||||
descriptions[132]="Lock the groups"
|
||||
descriptions[133]="Move the cursor to the corner of the active window"
|
||||
descriptions[136]="INFO"
|
||||
descriptions[137]="Resize a selected window"
|
||||
descriptions[1]="Resize the active window"
|
||||
descriptions[2]="Fullscreen"
|
||||
descriptions[3]="Switch to the next window in a group"
|
||||
descriptions[4]="Refresh state after issuing the command"
|
||||
descriptions[5]="Move the active window into a group"
|
||||
descriptions[7]="CONFUSED"
|
||||
descriptions[9]="Print system info"
|
||||
descriptions[11]="List all layouts available (including plugin ones)"
|
||||
descriptions[12]="Set a property of a window"
|
||||
descriptions[14]="Set the xkb layout index for a keyboard"
|
||||
descriptions[16]="Prohibit the active window from becoming or being inserted into group"
|
||||
descriptions[19]="Execute a shell command"
|
||||
descriptions[20]="Set the cursor theme and reloads the cursor manager"
|
||||
descriptions[22]="Focus the urgent window or the last window"
|
||||
descriptions[23]="Get the list of defined workspace rules"
|
||||
descriptions[24]="Move the active workspace to a monitor"
|
||||
descriptions[25]="Move window doesnt switch to the workspace"
|
||||
descriptions[26]="Interact with hyprpaper if present"
|
||||
descriptions[29]="Swap the active window with the next or previous in a group"
|
||||
descriptions[30]="Move the cursor to the corner of the active window"
|
||||
descriptions[31]="Move a selected window"
|
||||
descriptions[33]="Move the active window in a direction or to a monitor"
|
||||
descriptions[34]="Lists all global shortcuts"
|
||||
descriptions[35]="List all windows with their properties"
|
||||
descriptions[37]="Temporarily enable or disable binds:ignore_group_lock"
|
||||
descriptions[38]="Print the current random splash"
|
||||
descriptions[39]="Execute a raw shell command"
|
||||
descriptions[40]="List active outputs with their properties"
|
||||
descriptions[43]="Disable output"
|
||||
descriptions[44]="Gets the current config info about animations and beziers"
|
||||
descriptions[47]="Change the split ratio"
|
||||
descriptions[48]="Move the active window"
|
||||
descriptions[49]="Pass the key to a specified window"
|
||||
descriptions[50]="Swap the focused window with the next window"
|
||||
descriptions[51]="List all connected keyboards and mice"
|
||||
descriptions[52]="List the layers"
|
||||
descriptions[54]="Lock the focused group"
|
||||
descriptions[55]="OK"
|
||||
descriptions[56]="Move a workspace to a monitor"
|
||||
descriptions[58]="Specify the Hyprland instance"
|
||||
descriptions[59]="Disable output"
|
||||
descriptions[61]="Pin a window"
|
||||
descriptions[62]="WARNING"
|
||||
descriptions[63]="INFO"
|
||||
descriptions[66]="Set the current window's floating state to true"
|
||||
descriptions[69]="On shortcut X sends shortcut Y to a specified window"
|
||||
descriptions[70]="List all workspaces with their properties"
|
||||
descriptions[71]="Focus the next window on a workspace"
|
||||
descriptions[72]="Modify the window stack order of the active or specified window"
|
||||
descriptions[73]="Toggle the current active window into a group"
|
||||
descriptions[74]="Lock the groups"
|
||||
descriptions[76]="Set all monitors' DPMS status"
|
||||
descriptions[77]="Switch focus from current to previously focused window"
|
||||
descriptions[78]="No Icon"
|
||||
descriptions[79]="Execute a batch of commands separated by ;"
|
||||
descriptions[80]="Send a notification using the built-in Hyprland notification system"
|
||||
descriptions[82]="List all running Hyprland instances and their info"
|
||||
descriptions[83]="Maximize no fullscreen"
|
||||
descriptions[84]="Maximize and fullscreen"
|
||||
descriptions[85]="Move the active window out of a group"
|
||||
descriptions[86]="Close the active window"
|
||||
descriptions[87]="HINT"
|
||||
descriptions[88]="Move the focused window to a workspace"
|
||||
descriptions[89]="Move the cursor to a specified position"
|
||||
descriptions[90]="List all current config parsing errors"
|
||||
descriptions[91]="Close a specified window"
|
||||
descriptions[92]="Swap the active window with another window"
|
||||
descriptions[93]="Apply a tag to the window"
|
||||
descriptions[94]="Force the renderer to reload all resources and outputs"
|
||||
descriptions[95]="Center the active window"
|
||||
descriptions[97]="Focus the first window matching"
|
||||
descriptions[98]="Set the hyprctl error string"
|
||||
descriptions[101]="List all registered binds"
|
||||
descriptions[102]="Print the Hyprland version: flags, commit and branch of build"
|
||||
descriptions[103]="Prints the help message"
|
||||
descriptions[104]="Toggle a special workspace on/off"
|
||||
descriptions[105]="Toggle the focused window's fullscreen state"
|
||||
descriptions[107]="None"
|
||||
descriptions[108]="Issue a keyword to call a config keyword dynamically"
|
||||
descriptions[109]="Toggle the current window to always be opaque"
|
||||
descriptions[110]="ERROR"
|
||||
descriptions[111]="Specify the Hyprland instance"
|
||||
descriptions[112]="Toggle the current window's floating state"
|
||||
descriptions[113]="Rename a workspace"
|
||||
descriptions[115]="Get the active workspace name and its properties"
|
||||
descriptions[117]="Get into a kill mode, where you can kill an app by clicking on it"
|
||||
descriptions[119]="Allows adding/removing fake outputs to a specific backend"
|
||||
descriptions[120]="Execute a Global Shortcut using the GlobalShortcuts portal"
|
||||
descriptions[121]="Issue a dispatch to call a keybind dispatcher with an arg"
|
||||
descriptions[122]="Force reload the config"
|
||||
descriptions[124]="Output in JSON format"
|
||||
descriptions[125]="Emits a custom event to socket2"
|
||||
descriptions[126]="Prints the help message"
|
||||
descriptions[128]="Current"
|
||||
descriptions[129]="Get the active window name and its properties"
|
||||
descriptions[131]="Dismiss all or up to amount of notifications"
|
||||
descriptions[132]="Focus a monitor"
|
||||
descriptions[133]="Move the focus in a direction"
|
||||
descriptions[134]="Interact with a plugin"
|
||||
descriptions[135]="Exit the compositor with no questions asked"
|
||||
descriptions[136]="Change the workspace"
|
||||
descriptions[137]="Sets the focused window’s fullscreen mode and the one sent to the client"
|
||||
descriptions[138]="Get the config option status (values)"
|
||||
descriptions[141]="List all decorations and their info"
|
||||
descriptions[142]="Set the current window's floating state to false"
|
||||
descriptions[144]="Return a parsable JSON with all the config options, descriptions, value types and ranges"
|
||||
descriptions[145]="Resize a selected window"
|
||||
descriptions[146]="Toggle the focused window's internal fullscreen state"
|
||||
descriptions[147]="Print tail of the log"
|
||||
descriptions[148]="Swap the active workspaces between two monitors"
|
||||
descriptions[149]="Change the current mapping group"
|
||||
descriptions[151]="Behave as moveintogroup"
|
||||
descriptions[152]="Get the current cursor pos in global layout coordinates"
|
||||
descriptions[154]="Focus the requested workspace"
|
||||
|
||||
local -A literal_transitions
|
||||
literal_transitions[1]="([104]=2 [75]=3 [34]=4 [2]=3 [3]=3 [78]=3 [106]=5 [37]=3 [109]=6 [41]=3 [46]=3 [113]=3 [85]=7 [114]=9 [52]=3 [54]=3 [89]=10 [118]=3 [120]=3 [122]=3 [16]=3 [59]=11 [60]=3 [18]=12 [123]=13 [20]=3 [125]=3 [127]=3 [26]=14 [68]=3 [97]=6 [98]=3 [28]=3 [29]=15 [101]=3 [103]=6)"
|
||||
literal_transitions[4]="([73]=19 [14]=3 [33]=19 [55]=19 [56]=19 [90]=19 [105]=3 [121]=3 [77]=2 [17]=3 [124]=19 [4]=2 [6]=3 [64]=19 [128]=3 [130]=19 [81]=19 [131]=19 [84]=19 [32]=19 [49]=3 [13]=3 [86]=19 [11]=19 [87]=19 [138]=19)"
|
||||
literal_transitions[8]="([104]=2 [75]=3 [34]=4 [2]=3 [3]=3 [78]=3 [106]=5 [37]=3 [41]=3 [46]=3 [113]=3 [85]=7 [114]=9 [52]=3 [54]=3 [89]=10 [118]=3 [120]=3 [122]=3 [16]=3 [59]=11 [60]=3 [18]=12 [123]=13 [20]=3 [125]=3 [127]=3 [26]=14 [68]=3 [98]=3 [28]=3 [29]=15 [101]=3)"
|
||||
literal_transitions[9]="([129]=3 [132]=3 [1]=3 [74]=3 [36]=3 [107]=3 [38]=3 [108]=3 [5]=3 [79]=3 [40]=3 [80]=3 [111]=3 [7]=3 [42]=3 [43]=3 [82]=3 [83]=3 [47]=3 [48]=3 [10]=3 [110]=3 [51]=3 [53]=3 [12]=3 [116]=3 [88]=3 [50]=3 [57]=3 [91]=3 [58]=3 [92]=3 [93]=3 [61]=3 [62]=3 [126]=3 [94]=3 [63]=3 [21]=3 [96]=3 [23]=3 [24]=3 [65]=3 [66]=3 [25]=3 [133]=3 [27]=3 [69]=3 [99]=3 [70]=3 [30]=3 [137]=3 [71]=3 [100]=3)"
|
||||
literal_transitions[10]="([115]=16 [112]=17)"
|
||||
literal_transitions[12]="([102]=3)"
|
||||
literal_transitions[14]="([22]=2 [117]=2 [31]=2 [136]=2 [119]=2 [44]=2 [72]=2)"
|
||||
literal_transitions[15]="([39]=3)"
|
||||
literal_transitions[16]="([9]=3 [67]=3 [15]=3 [134]=3)"
|
||||
literal_transitions[18]="([76]=20)"
|
||||
literal_transitions[19]="([19]=3 [8]=3)"
|
||||
literal_transitions[20]="([35]=6 [45]=6)"
|
||||
literal_transitions[21]="([135]=3 [95]=3)"
|
||||
literal_transitions[1]="([121]=15 [44]=3 [126]=22 [82]=3 [4]=22 [52]=3 [51]=3 [129]=3 [90]=3 [59]=22 [9]=3 [11]=3 [12]=4 [131]=5 [14]=6 [98]=7 [102]=3 [103]=22 [134]=8 [101]=3 [138]=3 [23]=3 [20]=3 [141]=9 [26]=3 [144]=3 [108]=10 [147]=11 [70]=3 [34]=3 [35]=3 [79]=22 [115]=3 [38]=3 [152]=3 [117]=3 [122]=14 [124]=22 [40]=12 [43]=22 [80]=16 [119]=13)"
|
||||
literal_transitions[2]="([82]=3 [52]=3 [51]=3 [129]=3 [9]=3 [90]=3 [11]=3 [12]=4 [131]=5 [14]=6 [98]=7 [102]=3 [134]=8 [101]=3 [23]=3 [20]=3 [138]=3 [141]=9 [26]=3 [144]=3 [108]=10 [147]=11 [70]=3 [34]=3 [35]=3 [115]=3 [38]=3 [152]=3 [117]=3 [40]=12 [119]=13 [122]=14 [121]=15 [80]=16 [44]=3)"
|
||||
literal_transitions[4]="([140]=3 [64]=17 [65]=17 [46]=17 [106]=17 [28]=3 [27]=3 [53]=5 [6]=17 [67]=3 [68]=17 [130]=17 [114]=17 [13]=3 [75]=5 [100]=3 [36]=17 [153]=17 [99]=17 [60]=17 [118]=17 [42]=17 [18]=3 [139]=17 [155]=3 [123]=17)"
|
||||
literal_transitions[7]="([127]=3)"
|
||||
literal_transitions[11]="([57]=3)"
|
||||
literal_transitions[12]="([10]=3)"
|
||||
literal_transitions[13]="([15]=20 [81]=23)"
|
||||
literal_transitions[14]="([143]=3)"
|
||||
literal_transitions[15]="([1]=3 [85]=3 [3]=3 [86]=3 [5]=3 [88]=3 [89]=3 [91]=3 [92]=3 [93]=3 [94]=3 [95]=3 [97]=3 [16]=3 [19]=3 [104]=3 [22]=3 [105]=3 [24]=3 [25]=3 [29]=3 [30]=3 [31]=3 [109]=3 [112]=3 [33]=3 [113]=3 [37]=3 [39]=3 [120]=3 [125]=3 [47]=3 [48]=3 [49]=3 [50]=3 [54]=3 [56]=3 [132]=3 [133]=3 [135]=3 [136]=3 [61]=3 [137]=21 [142]=3 [66]=3 [145]=3 [146]=3 [69]=3 [148]=3 [71]=3 [72]=3 [73]=3 [74]=3 [149]=3 [76]=3 [77]=3 [151]=3 [154]=3)"
|
||||
literal_transitions[16]="([87]=5 [7]=5 [110]=5 [62]=5 [78]=5 [55]=5 [63]=5)"
|
||||
literal_transitions[17]="([41]=3 [45]=3)"
|
||||
literal_transitions[18]="([8]=24)"
|
||||
literal_transitions[19]="([32]=3 [150]=3)"
|
||||
literal_transitions[20]="([96]=3 [17]=3 [116]=3 [21]=3)"
|
||||
literal_transitions[21]="([107]=3 [83]=3 [128]=3 [2]=3 [84]=3)"
|
||||
literal_transitions[24]="([58]=22 [111]=22)"
|
||||
|
||||
local -A match_anything_transitions
|
||||
match_anything_transitions=([2]=3 [1]=8 [7]=3 [21]=3 [11]=3 [3]=18 [8]=8 [13]=3 [15]=18 [17]=3 [5]=21 [12]=18)
|
||||
match_anything_transitions=([7]=18 [8]=3 [1]=2 [23]=3 [6]=19 [5]=3 [3]=18 [19]=3 [12]=18 [9]=3 [10]=3 [14]=18 [11]=18 [2]=2)
|
||||
|
||||
declare -A subword_transitions
|
||||
|
||||
@@ -195,7 +214,7 @@ _hyprctl () {
|
||||
fi
|
||||
done
|
||||
fi
|
||||
local -A commands=([17]=2 [5]=3 [13]=1 [11]=0)
|
||||
local -A commands=([8]=0 [23]=1 [9]=3 [6]=2)
|
||||
|
||||
if [[ -v "commands[$state]" ]]; then
|
||||
local command_id=${commands[$state]}
|
||||
@@ -248,4 +267,8 @@ _hyprctl () {
|
||||
return 0
|
||||
}
|
||||
|
||||
compdef _hyprctl hyprctl
|
||||
if [[ $ZSH_EVAL_CONTEXT =~ :file$ ]]; then
|
||||
compdef _hyprctl hyprctl
|
||||
else
|
||||
_hyprctl
|
||||
fi
|
||||
|
221
hyprctl/main.cpp
@@ -1,17 +1,18 @@
|
||||
#include <ctype.h>
|
||||
#include <cctype>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <ranges>
|
||||
#include <algorithm>
|
||||
#include <signal.h>
|
||||
#include <csignal>
|
||||
#include <format>
|
||||
|
||||
#include <iostream>
|
||||
@@ -21,14 +22,19 @@
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <filesystem>
|
||||
#include <stdarg.h>
|
||||
#include <cstdarg>
|
||||
#include <regex>
|
||||
#include <sys/socket.h>
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <cstring>
|
||||
using namespace Hyprutils::String;
|
||||
|
||||
#include "Strings.hpp"
|
||||
|
||||
#define PAD
|
||||
|
||||
std::string instanceSignature;
|
||||
bool quiet = false;
|
||||
|
||||
struct SInstanceData {
|
||||
std::string id;
|
||||
@@ -38,24 +44,41 @@ struct SInstanceData {
|
||||
bool valid = true;
|
||||
};
|
||||
|
||||
void log(std::string str) {
|
||||
if (quiet)
|
||||
return;
|
||||
|
||||
std::cout << str << "\n";
|
||||
}
|
||||
|
||||
std::string getRuntimeDir() {
|
||||
const auto XDG = getenv("XDG_RUNTIME_DIR");
|
||||
|
||||
if (!XDG) {
|
||||
const std::string USERID = std::to_string(getpwuid(getuid())->pw_uid);
|
||||
return "/run/user/" + USERID + "/hypr";
|
||||
}
|
||||
|
||||
return std::string{XDG} + "/hypr";
|
||||
}
|
||||
|
||||
std::vector<SInstanceData> instances() {
|
||||
std::vector<SInstanceData> result;
|
||||
|
||||
for (const auto& el : std::filesystem::directory_iterator("/tmp/hypr")) {
|
||||
if (el.is_directory() || !el.path().string().ends_with(".lock"))
|
||||
for (const auto& el : std::filesystem::directory_iterator(getRuntimeDir())) {
|
||||
if (!el.is_directory() || !std::filesystem::exists(el.path().string() + "/hyprland.lock"))
|
||||
continue;
|
||||
|
||||
// read lock
|
||||
SInstanceData* data = &result.emplace_back();
|
||||
data->id = el.path().string();
|
||||
data->id = data->id.substr(data->id.find_last_of('/') + 1, data->id.find(".lock") - data->id.find_last_of('/') - 1);
|
||||
data->id = el.path().filename().string();
|
||||
|
||||
try {
|
||||
data->time = std::stoull(data->id.substr(data->id.find_first_of('_') + 1));
|
||||
data->time = std::stoull(data->id.substr(data->id.find_first_of('_') + 1, data->id.find_last_of('_') - (data->id.find_first_of('_') + 1)));
|
||||
} catch (std::exception& e) { continue; }
|
||||
|
||||
// read file
|
||||
std::ifstream ifs(el.path().string());
|
||||
std::ifstream ifs(el.path().string() + "/hyprland.lock");
|
||||
|
||||
int i = 0;
|
||||
for (std::string line; std::getline(ifs, line); ++i) {
|
||||
@@ -79,53 +102,100 @@ std::vector<SInstanceData> instances() {
|
||||
return result;
|
||||
}
|
||||
|
||||
void request(std::string arg, int minArgs = 0) {
|
||||
static volatile bool sigintReceived = false;
|
||||
void intHandler(int sig) {
|
||||
sigintReceived = true;
|
||||
std::cout << "[hyprctl] SIGINT received, closing connection" << std::endl;
|
||||
}
|
||||
|
||||
int rollingRead(const int socket) {
|
||||
sigintReceived = false;
|
||||
signal(SIGINT, intHandler);
|
||||
|
||||
constexpr size_t BUFFER_SIZE = 8192;
|
||||
std::array<char, BUFFER_SIZE> buffer = {0};
|
||||
long sizeWritten = 0;
|
||||
std::cout << "[hyprctl] reading from socket following up log:" << std::endl;
|
||||
while (!sigintReceived) {
|
||||
sizeWritten = read(socket, buffer.data(), BUFFER_SIZE);
|
||||
if (sizeWritten < 0 && errno != EAGAIN) {
|
||||
if (errno != EINTR)
|
||||
std::cout << "Couldn't read (5) " << strerror(errno) << ":" << errno << std::endl;
|
||||
close(socket);
|
||||
return 5;
|
||||
}
|
||||
|
||||
if (sizeWritten == 0)
|
||||
break;
|
||||
|
||||
if (sizeWritten > 0) {
|
||||
std::cout << std::string(buffer.data(), sizeWritten);
|
||||
buffer.fill('\0');
|
||||
}
|
||||
|
||||
usleep(100000);
|
||||
}
|
||||
close(socket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int request(std::string arg, int minArgs = 0, bool needRoll = false) {
|
||||
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
auto t = timeval{.tv_sec = 5, .tv_usec = 0};
|
||||
setsockopt(SERVERSOCKET, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval));
|
||||
|
||||
const auto ARGS = std::count(arg.begin(), arg.end(), ' ');
|
||||
|
||||
if (ARGS < minArgs) {
|
||||
std::cout << "Not enough arguments, expected at least " << minArgs;
|
||||
return;
|
||||
log(std::format("Not enough arguments in '{}', expected at least {}", arg, minArgs));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SERVERSOCKET < 0) {
|
||||
std::cout << "Couldn't open a socket (1)";
|
||||
return;
|
||||
log("Couldn't open a socket (1)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (instanceSignature.empty()) {
|
||||
std::cout << "HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)";
|
||||
return;
|
||||
log("HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)");
|
||||
return 2;
|
||||
}
|
||||
|
||||
const std::string USERID = std::to_string(getpwuid(getuid())->pw_uid);
|
||||
|
||||
sockaddr_un serverAddress = {0};
|
||||
serverAddress.sun_family = AF_UNIX;
|
||||
|
||||
std::string socketPath = "/tmp/hypr/" + instanceSignature + "/.socket.sock";
|
||||
std::string socketPath = getRuntimeDir() + "/" + instanceSignature + "/.socket.sock";
|
||||
|
||||
strncpy(serverAddress.sun_path, socketPath.c_str(), sizeof(serverAddress.sun_path) - 1);
|
||||
|
||||
if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN(&serverAddress)) < 0) {
|
||||
std::cout << "Couldn't connect to " << socketPath << ". (3)";
|
||||
return;
|
||||
log("Couldn't connect to " + socketPath + ". (3)");
|
||||
return 3;
|
||||
}
|
||||
|
||||
auto sizeWritten = write(SERVERSOCKET, arg.c_str(), arg.length());
|
||||
|
||||
if (sizeWritten < 0) {
|
||||
std::cout << "Couldn't write (4)";
|
||||
return;
|
||||
log("Couldn't write (4)");
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (needRoll)
|
||||
return rollingRead(SERVERSOCKET);
|
||||
|
||||
std::string reply = "";
|
||||
char buffer[8192] = {0};
|
||||
|
||||
sizeWritten = read(SERVERSOCKET, buffer, 8192);
|
||||
|
||||
if (sizeWritten < 0) {
|
||||
std::cout << "Couldn't read (5)";
|
||||
return;
|
||||
if (errno == EWOULDBLOCK)
|
||||
log("Hyprland IPC didn't respond in time\n");
|
||||
log("Couldn't read (5)");
|
||||
return 5;
|
||||
}
|
||||
|
||||
reply += std::string(buffer, sizeWritten);
|
||||
@@ -133,40 +203,44 @@ void request(std::string arg, int minArgs = 0) {
|
||||
while (sizeWritten == 8192) {
|
||||
sizeWritten = read(SERVERSOCKET, buffer, 8192);
|
||||
if (sizeWritten < 0) {
|
||||
std::cout << "Couldn't read (5)";
|
||||
return;
|
||||
log("Couldn't read (5)");
|
||||
return 5;
|
||||
}
|
||||
reply += std::string(buffer, sizeWritten);
|
||||
}
|
||||
|
||||
close(SERVERSOCKET);
|
||||
|
||||
std::cout << reply;
|
||||
log(reply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void requestHyprpaper(std::string arg) {
|
||||
int requestHyprpaper(std::string arg) {
|
||||
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
if (SERVERSOCKET < 0) {
|
||||
std::cout << "Couldn't open a socket (1)";
|
||||
return;
|
||||
log("Couldn't open a socket (1)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (instanceSignature.empty()) {
|
||||
std::cout << "HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)";
|
||||
return;
|
||||
log("HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)");
|
||||
return 2;
|
||||
}
|
||||
|
||||
sockaddr_un serverAddress = {0};
|
||||
serverAddress.sun_family = AF_UNIX;
|
||||
|
||||
std::string socketPath = "/tmp/hypr/" + instanceSignature + "/.hyprpaper.sock";
|
||||
const std::string USERID = std::to_string(getpwuid(getuid())->pw_uid);
|
||||
|
||||
std::string socketPath = getRuntimeDir() + "/" + instanceSignature + "/.hyprpaper.sock";
|
||||
|
||||
strncpy(serverAddress.sun_path, socketPath.c_str(), sizeof(serverAddress.sun_path) - 1);
|
||||
|
||||
if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN(&serverAddress)) < 0) {
|
||||
std::cout << "Couldn't connect to " << socketPath << ". (3)";
|
||||
return;
|
||||
log("Couldn't connect to " + socketPath + ". (3)");
|
||||
return 3;
|
||||
}
|
||||
|
||||
arg = arg.substr(arg.find_first_of('/') + 1); // strip flags
|
||||
@@ -175,8 +249,8 @@ void requestHyprpaper(std::string arg) {
|
||||
auto sizeWritten = write(SERVERSOCKET, arg.c_str(), arg.length());
|
||||
|
||||
if (sizeWritten < 0) {
|
||||
std::cout << "Couldn't write (4)";
|
||||
return;
|
||||
log("Couldn't write (4)");
|
||||
return 4;
|
||||
}
|
||||
|
||||
char buffer[8192] = {0};
|
||||
@@ -184,13 +258,15 @@ void requestHyprpaper(std::string arg) {
|
||||
sizeWritten = read(SERVERSOCKET, buffer, 8192);
|
||||
|
||||
if (sizeWritten < 0) {
|
||||
std::cout << "Couldn't read (5)";
|
||||
return;
|
||||
log("Couldn't read (5)");
|
||||
return 5;
|
||||
}
|
||||
|
||||
close(SERVERSOCKET);
|
||||
|
||||
std::cout << std::string(buffer);
|
||||
log(std::string(buffer));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void batchRequest(std::string arg, bool json) {
|
||||
@@ -211,12 +287,12 @@ void instancesRequest(bool json) {
|
||||
std::vector<SInstanceData> inst = instances();
|
||||
|
||||
if (!json) {
|
||||
for (auto& el : inst) {
|
||||
for (auto const& el : inst) {
|
||||
result += std::format("instance {}:\n\ttime: {}\n\tpid: {}\n\twl socket: {}\n\n", el.id, el.time, el.pid, el.wlSocket);
|
||||
}
|
||||
} else {
|
||||
result += '[';
|
||||
for (auto& el : inst) {
|
||||
for (auto const& el : inst) {
|
||||
result += std::format(R"#(
|
||||
{{
|
||||
"instance": "{}",
|
||||
@@ -231,7 +307,7 @@ void instancesRequest(bool json) {
|
||||
result += "\n]";
|
||||
}
|
||||
|
||||
std::cout << result << "\n";
|
||||
log(result + "\n");
|
||||
}
|
||||
|
||||
std::deque<std::string> splitArgs(int argc, char** argv) {
|
||||
@@ -243,12 +319,6 @@ std::deque<std::string> splitArgs(int argc, char** argv) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool isNumber(const std::string& str, bool allowfloat) {
|
||||
if (str.empty())
|
||||
return false;
|
||||
return std::ranges::all_of(str.begin(), str.end(), [&](char c) { return isdigit(c) != 0 || c == '-' || (allowfloat && c == '.'); });
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
bool parseArgs = true;
|
||||
|
||||
@@ -261,6 +331,7 @@ int main(int argc, char** argv) {
|
||||
std::string fullArgs = "";
|
||||
const auto ARGS = splitArgs(argc, argv);
|
||||
bool json = false;
|
||||
bool needRoll = false;
|
||||
std::string overrideInstance = "";
|
||||
|
||||
for (std::size_t i = 0; i < ARGS.size(); ++i) {
|
||||
@@ -278,6 +349,11 @@ int main(int argc, char** argv) {
|
||||
fullArgs += "r";
|
||||
} else if (ARGS[i] == "-a" && !fullArgs.contains("a")) {
|
||||
fullArgs += "a";
|
||||
} else if ((ARGS[i] == "-c" || ARGS[i] == "--config") && !fullArgs.contains("c")) {
|
||||
fullArgs += "c";
|
||||
} else if ((ARGS[i] == "-f" || ARGS[i] == "--follow") && !fullArgs.contains("f")) {
|
||||
fullArgs += "f";
|
||||
needRoll = true;
|
||||
} else if (ARGS[i] == "--batch") {
|
||||
fullRequest = "--batch ";
|
||||
} else if (ARGS[i] == "--instance" || ARGS[i] == "-i") {
|
||||
@@ -289,6 +365,8 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
overrideInstance = ARGS[i];
|
||||
} else if (ARGS[i] == "-q" || ARGS[i] == "--quiet") {
|
||||
quiet = true;
|
||||
} else if (ARGS[i] == "--help") {
|
||||
const std::string& cmd = ARGS[0];
|
||||
|
||||
@@ -335,11 +413,16 @@ int main(int argc, char** argv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (needRoll && !fullRequest.contains("/rollinglog")) {
|
||||
log("only 'rollinglog' command supports '--follow' option");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (overrideInstance.contains("_"))
|
||||
instanceSignature = overrideInstance;
|
||||
else if (!overrideInstance.empty()) {
|
||||
if (!isNumber(overrideInstance, false)) {
|
||||
std::cout << "instance invalid\n";
|
||||
log("instance invalid\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -348,7 +431,7 @@ int main(int argc, char** argv) {
|
||||
const auto INSTANCES = instances();
|
||||
|
||||
if (INSTANCENO < 0 || static_cast<std::size_t>(INSTANCENO) >= INSTANCES.size()) {
|
||||
std::cout << "no such instance\n";
|
||||
log("no such instance\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -357,7 +440,7 @@ int main(int argc, char** argv) {
|
||||
const auto ISIG = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
||||
|
||||
if (!ISIG) {
|
||||
std::cout << "HYPRLAND_INSTANCE_SIGNATURE not set! (is hyprland running?)\n";
|
||||
log("HYPRLAND_INSTANCE_SIGNATURE not set! (is hyprland running?)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -369,35 +452,37 @@ int main(int argc, char** argv) {
|
||||
if (fullRequest.contains("/--batch"))
|
||||
batchRequest(fullRequest, json);
|
||||
else if (fullRequest.contains("/hyprpaper"))
|
||||
requestHyprpaper(fullRequest);
|
||||
exitStatus = requestHyprpaper(fullRequest);
|
||||
else if (fullRequest.contains("/switchxkblayout"))
|
||||
request(fullRequest, 2);
|
||||
exitStatus = request(fullRequest, 2);
|
||||
else if (fullRequest.contains("/seterror"))
|
||||
request(fullRequest, 1);
|
||||
exitStatus = request(fullRequest, 1);
|
||||
else if (fullRequest.contains("/setprop"))
|
||||
request(fullRequest, 3);
|
||||
exitStatus = request(fullRequest, 3);
|
||||
else if (fullRequest.contains("/plugin"))
|
||||
request(fullRequest, 1);
|
||||
exitStatus = request(fullRequest, 1);
|
||||
else if (fullRequest.contains("/dismissnotify"))
|
||||
request(fullRequest, 0);
|
||||
exitStatus = request(fullRequest, 0);
|
||||
else if (fullRequest.contains("/notify"))
|
||||
request(fullRequest, 2);
|
||||
exitStatus = request(fullRequest, 2);
|
||||
else if (fullRequest.contains("/output"))
|
||||
request(fullRequest, 2);
|
||||
exitStatus = request(fullRequest, 2);
|
||||
else if (fullRequest.contains("/setcursor"))
|
||||
request(fullRequest, 1);
|
||||
exitStatus = request(fullRequest, 1);
|
||||
else if (fullRequest.contains("/dispatch"))
|
||||
request(fullRequest, 1);
|
||||
exitStatus = request(fullRequest, 1);
|
||||
else if (fullRequest.contains("/keyword"))
|
||||
request(fullRequest, 2);
|
||||
exitStatus = request(fullRequest, 2);
|
||||
else if (fullRequest.contains("/decorations"))
|
||||
request(fullRequest, 1);
|
||||
exitStatus = request(fullRequest, 1);
|
||||
else if (fullRequest.contains("/--help"))
|
||||
std::cout << USAGE << std::endl;
|
||||
else if (fullRequest.contains("/rollinglog") && needRoll)
|
||||
exitStatus = request(fullRequest, 0, true);
|
||||
else {
|
||||
request(fullRequest);
|
||||
exitStatus = request(fullRequest);
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
std::cout << std::flush;
|
||||
return exitStatus;
|
||||
}
|
||||
|
@@ -1,7 +1,10 @@
|
||||
executable('hyprctl', 'main.cpp',
|
||||
dependencies: [
|
||||
dependency('hyprutils', version: '>= 0.1.1'),
|
||||
],
|
||||
install: true
|
||||
)
|
||||
|
||||
install_data('hyprctl.bash', install_dir: join_paths(get_option('datadir'), 'bash-completions'), install_tag: 'runtime', rename: 'hyprctl')
|
||||
install_data('hyprctl.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprctl')
|
||||
install_data('hyprctl.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime')
|
||||
install_data('hyprctl.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprctl')
|
||||
|
@@ -1,8 +1,7 @@
|
||||
prefix="@PREFIX@"
|
||||
includedir="${prefix}/include"
|
||||
prefix=@PREFIX@/@INCLUDEDIR@
|
||||
|
||||
Name: Hyprland
|
||||
URL: https://github.com/hyprwm/Hyprland
|
||||
Description: Hyprland header files
|
||||
Version: @HYPRLAND_VERSION@
|
||||
Cflags: -I"${includedir}/hyprland/protocols" -I"${includedir}/hyprland/wlroots-hyprland" -I"${includedir}"
|
||||
Cflags: -I${prefix} -I${prefix}/hyprland/protocols -I${prefix}/hyprland
|
||||
|
@@ -9,8 +9,21 @@ file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
pkg_check_modules(tomlplusplus REQUIRED IMPORTED_TARGET tomlplusplus)
|
||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.1.1)
|
||||
|
||||
add_executable(hyprpm ${SRCFILES})
|
||||
|
||||
target_link_libraries(hyprpm PUBLIC PkgConfig::tomlplusplus)
|
||||
target_link_libraries(hyprpm PUBLIC PkgConfig::deps)
|
||||
|
||||
# binary
|
||||
install(TARGETS hyprpm)
|
||||
|
||||
# shell completions
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/hyprpm.bash
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/bash-completion/completions
|
||||
RENAME hyprpm)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/hyprpm.fish
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/fish/vendor_completions.d)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/hyprpm.zsh
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/zsh/site-functions
|
||||
RENAME _hyprpm)
|
||||
|
@@ -1,5 +1,9 @@
|
||||
_hyprpm_cmd_0 () {
|
||||
hyprpm list | grep Plugin | awk '{print $4}'
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
}
|
||||
|
||||
_hyprpm_cmd_1 () {
|
||||
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
|
||||
}
|
||||
|
||||
_hyprpm () {
|
||||
@@ -11,16 +15,13 @@ _hyprpm () {
|
||||
local words cword
|
||||
_get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword
|
||||
|
||||
local -a literals=("-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f")
|
||||
|
||||
declare -a literals=(--no-shallow -n ::= disable list --help update add --verbose -v --force -s remove enable --notify -h reload -f)
|
||||
declare -A literal_transitions
|
||||
literal_transitions[0]="([9]=6 [2]=2 [7]=6 [8]=6 [4]=6 [10]=2 [11]=3 [5]=2 [13]=6 [3]=3 [14]=2 [15]=6 [6]=2)"
|
||||
literal_transitions[1]="([10]=2 [11]=3 [3]=3 [2]=2 [14]=2 [5]=2 [6]=2)"
|
||||
literal_transitions[4]="([1]=5)"
|
||||
literal_transitions[5]="([0]=6 [12]=6)"
|
||||
|
||||
declare -A match_anything_transitions
|
||||
match_anything_transitions=([3]=2 [2]=4 [0]=1 [1]=1)
|
||||
literal_transitions[0]="([0]=7 [3]=3 [4]=4 [8]=7 [9]=7 [6]=4 [7]=4 [11]=7 [5]=7 [10]=7 [12]=2 [13]=3 [15]=7 [16]=4 [17]=7)"
|
||||
literal_transitions[1]="([12]=2 [13]=3 [3]=3 [4]=4 [16]=4 [6]=4 [7]=4)"
|
||||
literal_transitions[5]="([2]=6)"
|
||||
literal_transitions[6]="([1]=7 [14]=7)"
|
||||
declare -A match_anything_transitions=([1]=1 [4]=5 [3]=4 [2]=4 [0]=1)
|
||||
declare -A subword_transitions
|
||||
|
||||
local state=0
|
||||
@@ -58,21 +59,9 @@ _hyprpm () {
|
||||
done
|
||||
|
||||
|
||||
local -a matches=()
|
||||
|
||||
local prefix="${words[$cword]}"
|
||||
|
||||
local shortest_suffix="$word"
|
||||
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
|
||||
local char="${COMP_WORDBREAKS:$i:1}"
|
||||
local candidate="${word##*$char}"
|
||||
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
|
||||
shortest_suffix=$candidate
|
||||
fi
|
||||
done
|
||||
local superfluous_prefix=""
|
||||
if [[ "$shortest_suffix" != "$word" ]]; then
|
||||
local superfluous_prefix=${word%$shortest_suffix}
|
||||
fi
|
||||
|
||||
if [[ -v "literal_transitions[$state]" ]]; then
|
||||
local state_transitions_initializer=${literal_transitions[$state]}
|
||||
declare -A state_transitions
|
||||
@@ -81,25 +70,38 @@ _hyprpm () {
|
||||
for literal_id in "${!state_transitions[@]}"; do
|
||||
local literal="${literals[$literal_id]}"
|
||||
if [[ $literal = "${prefix}"* ]]; then
|
||||
local completion=${literal#"$superfluous_prefix"}
|
||||
COMPREPLY+=("$completion ")
|
||||
matches+=("$literal ")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
declare -A commands
|
||||
commands=([3]=0)
|
||||
commands=([3]=0 [2]=1)
|
||||
if [[ -v "commands[$state]" ]]; then
|
||||
local command_id=${commands[$state]}
|
||||
local completions=()
|
||||
mapfile -t completions < <(_hyprpm_cmd_${command_id} "$prefix" | cut -f1)
|
||||
readarray -t completions < <(_hyprpm_cmd_${command_id} "$prefix" | cut -f1)
|
||||
for item in "${completions[@]}"; do
|
||||
if [[ $item = "${prefix}"* ]]; then
|
||||
COMPREPLY+=("$item")
|
||||
matches+=("$item")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
local shortest_suffix="$prefix"
|
||||
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
|
||||
local char="${COMP_WORDBREAKS:$i:1}"
|
||||
local candidate=${prefix##*$char}
|
||||
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
|
||||
shortest_suffix=$candidate
|
||||
fi
|
||||
done
|
||||
local superfluous_prefix=""
|
||||
if [[ "$shortest_suffix" != "$prefix" ]]; then
|
||||
local superfluous_prefix=${prefix%$shortest_suffix}
|
||||
fi
|
||||
COMPREPLY=("${matches[@]#$superfluous_prefix}")
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,11 @@
|
||||
function _hyprpm_1
|
||||
set 1 $argv[1]
|
||||
hyprpm list | grep Plugin | awk '{print $4}'
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
end
|
||||
|
||||
function _hyprpm_2
|
||||
set 1 $argv[1]
|
||||
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
|
||||
end
|
||||
|
||||
function _hyprpm
|
||||
@@ -14,49 +19,51 @@ function _hyprpm
|
||||
set COMP_CWORD (count $COMP_WORDS)
|
||||
end
|
||||
|
||||
set --local literals "-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f"
|
||||
set literals "--no-shallow" "-n" "::=" "disable" "list" "--help" "update" "add" "--verbose" "-v" "--force" "-s" "remove" "enable" "--notify" "-h" "reload" "-f"
|
||||
|
||||
set --local descriptions
|
||||
set descriptions[1] "Send a hyprland notification for important events (e.g. load fail)"
|
||||
set descriptions[3] "List all installed plugins"
|
||||
set descriptions
|
||||
set descriptions[1] "Disable shallow cloning of Hyprland sources"
|
||||
set descriptions[2] "Send a hyprland notification for important events (e.g. load fail)"
|
||||
set descriptions[4] "Unload a plugin"
|
||||
set descriptions[5] "Show help menu"
|
||||
set descriptions[6] "Check and update all plugins if needed"
|
||||
set descriptions[7] "Install a new plugin repository from git"
|
||||
set descriptions[8] "Enable too much loggin"
|
||||
set descriptions[5] "List all installed plugins"
|
||||
set descriptions[6] "Show help menu"
|
||||
set descriptions[7] "Check and update all plugins if needed"
|
||||
set descriptions[8] "Install a new plugin repository from git"
|
||||
set descriptions[9] "Enable too much loggin"
|
||||
set descriptions[10] "Force an operation ignoring checks (e.g. update -f)"
|
||||
set descriptions[11] "Remove a plugin repository"
|
||||
set descriptions[12] "Load a plugin"
|
||||
set descriptions[13] "Send a hyprland notification for important events (e.g. load fail)"
|
||||
set descriptions[14] "Show help menu"
|
||||
set descriptions[15] "Reload all plugins"
|
||||
set descriptions[16] "Force an operation ignoring checks (e.g. update -f)"
|
||||
set descriptions[10] "Enable too much loggin"
|
||||
set descriptions[11] "Force an operation ignoring checks (e.g. update -f)"
|
||||
set descriptions[12] "Disable shallow cloning of Hyprland sources"
|
||||
set descriptions[13] "Remove a plugin repository"
|
||||
set descriptions[14] "Load a plugin"
|
||||
set descriptions[15] "Send a hyprland notification for important events (e.g. load fail)"
|
||||
set descriptions[16] "Show help menu"
|
||||
set descriptions[17] "Reload all plugins"
|
||||
set descriptions[18] "Force an operation ignoring checks (e.g. update -f)"
|
||||
|
||||
set --local literal_transitions
|
||||
set literal_transitions[1] "set inputs 10 3 8 9 5 11 12 6 14 4 15 16 7; set tos 7 3 7 7 7 3 4 3 7 4 3 7 3"
|
||||
set literal_transitions[2] "set inputs 11 12 4 3 15 6 7; set tos 3 4 4 3 3 3 3"
|
||||
set literal_transitions[5] "set inputs 2; set tos 6"
|
||||
set literal_transitions[6] "set inputs 1 13; set tos 7 7"
|
||||
set literal_transitions
|
||||
set literal_transitions[1] "set inputs 1 4 5 9 10 7 8 12 6 11 13 14 16 17 18; set tos 8 4 5 8 8 5 5 8 8 8 3 4 8 5 8"
|
||||
set literal_transitions[2] "set inputs 13 14 4 5 17 7 8; set tos 3 4 4 5 5 5 5"
|
||||
set literal_transitions[6] "set inputs 3; set tos 7"
|
||||
set literal_transitions[7] "set inputs 2 15; set tos 8 8"
|
||||
|
||||
set --local match_anything_transitions_from 4 3 1 2
|
||||
set --local match_anything_transitions_to 3 5 2 2
|
||||
set match_anything_transitions_from 2 5 4 3 1
|
||||
set match_anything_transitions_to 2 6 5 5 2
|
||||
|
||||
set --local state 1
|
||||
set --local word_index 2
|
||||
set state 1
|
||||
set word_index 2
|
||||
while test $word_index -lt $COMP_CWORD
|
||||
set --local -- word $COMP_WORDS[$word_index]
|
||||
set -- word $COMP_WORDS[$word_index]
|
||||
|
||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
eval $literal_transitions[$state]
|
||||
|
||||
if contains -- $word $literals
|
||||
set --local literal_matched 0
|
||||
set literal_matched 0
|
||||
for literal_id in (seq 1 (count $literals))
|
||||
if test $literals[$literal_id] = $word
|
||||
set --local index (contains --index -- $literal_id $inputs)
|
||||
set index (contains --index -- $literal_id $inputs)
|
||||
set state $tos[$index]
|
||||
set word_index (math $word_index + 1)
|
||||
set literal_matched 1
|
||||
@@ -70,7 +77,7 @@ function _hyprpm
|
||||
end
|
||||
|
||||
if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state]
|
||||
set --local index (contains --index -- $state $match_anything_transitions_from)
|
||||
set index (contains --index -- $state $match_anything_transitions_from)
|
||||
set state $match_anything_transitions_to[$index]
|
||||
set word_index (math $word_index + 1)
|
||||
continue
|
||||
@@ -80,8 +87,8 @@ function _hyprpm
|
||||
end
|
||||
|
||||
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
eval $literal_transitions[$state]
|
||||
for literal_id in $inputs
|
||||
if test -n $descriptions[$literal_id]
|
||||
@@ -92,14 +99,14 @@ function _hyprpm
|
||||
end
|
||||
end
|
||||
|
||||
set command_states 4
|
||||
set command_ids 1
|
||||
set command_states 4 3
|
||||
set command_ids 1 2
|
||||
if contains $state $command_states
|
||||
set --local index (contains --index $state $command_states)
|
||||
set --local function_id $command_ids[$index]
|
||||
set --local function_name _hyprpm_$function_id
|
||||
set --local --erase inputs
|
||||
set --local --erase tos
|
||||
set index (contains --index $state $command_states)
|
||||
set function_id $command_ids[$index]
|
||||
set function_name _hyprpm_$function_id
|
||||
set --erase inputs
|
||||
set --erase tos
|
||||
$function_name "$COMP_WORDS[$COMP_CWORD]"
|
||||
end
|
||||
|
||||
|
@@ -5,10 +5,11 @@ hyprpm [<FLAGS>]... <ARGUMENT>
|
||||
| (--help | -h) "Show help menu"
|
||||
| (--verbose | -v) "Enable too much loggin"
|
||||
| (--force | -f) "Force an operation ignoring checks (e.g. update -f)"
|
||||
| (--no-shallow | -s) "Disable shallow cloning of Hyprland sources"
|
||||
;
|
||||
|
||||
<ARGUMENT> ::= (add) "Install a new plugin repository from git"
|
||||
| (remove) "Remove a plugin repository"
|
||||
| (remove <PLUGIN_REPOS>) "Remove a plugin repository"
|
||||
| (update) "Check and update all plugins if needed"
|
||||
| (list) "List all installed plugins"
|
||||
| (enable <PLUGINS>) "Load a plugin"
|
||||
@@ -16,4 +17,5 @@ hyprpm [<FLAGS>]... <ARGUMENT>
|
||||
| (reload) "Reload all plugins"
|
||||
;
|
||||
|
||||
<PLUGINS> ::= {{{ hyprpm list | grep Plugin | awk '{print $4}' }}};
|
||||
<PLUGINS> ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}};
|
||||
<PLUGIN_REPOS> ::= {{{ hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//' }}};
|
||||
|
@@ -1,37 +1,43 @@
|
||||
#compdef hyprpm
|
||||
|
||||
_hyprpm_cmd_0 () {
|
||||
hyprpm list | grep Plugin | awk '{print $4}'
|
||||
hyprpm list | awk '/Plugin/{print $4}'
|
||||
}
|
||||
|
||||
_hyprpm_cmd_1 () {
|
||||
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
|
||||
}
|
||||
|
||||
_hyprpm () {
|
||||
local -a literals=("-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f")
|
||||
local -a literals=("--no-shallow" "-n" "::=" "disable" "list" "--help" "update" "add" "--verbose" "-v" "--force" "-s" "remove" "enable" "--notify" "-h" "reload" "-f")
|
||||
|
||||
local -A descriptions
|
||||
descriptions[1]="Send a hyprland notification for important events (e.g. load fail)"
|
||||
descriptions[3]="List all installed plugins"
|
||||
descriptions[1]="Disable shallow cloning of Hyprland sources"
|
||||
descriptions[2]="Send a hyprland notification for important events (e.g. load fail)"
|
||||
descriptions[4]="Unload a plugin"
|
||||
descriptions[5]="Show help menu"
|
||||
descriptions[6]="Check and update all plugins if needed"
|
||||
descriptions[7]="Install a new plugin repository from git"
|
||||
descriptions[8]="Enable too much loggin"
|
||||
descriptions[5]="List all installed plugins"
|
||||
descriptions[6]="Show help menu"
|
||||
descriptions[7]="Check and update all plugins if needed"
|
||||
descriptions[8]="Install a new plugin repository from git"
|
||||
descriptions[9]="Enable too much loggin"
|
||||
descriptions[10]="Force an operation ignoring checks (e.g. update -f)"
|
||||
descriptions[11]="Remove a plugin repository"
|
||||
descriptions[12]="Load a plugin"
|
||||
descriptions[13]="Send a hyprland notification for important events (e.g. load fail)"
|
||||
descriptions[14]="Show help menu"
|
||||
descriptions[15]="Reload all plugins"
|
||||
descriptions[16]="Force an operation ignoring checks (e.g. update -f)"
|
||||
descriptions[10]="Enable too much loggin"
|
||||
descriptions[11]="Force an operation ignoring checks (e.g. update -f)"
|
||||
descriptions[12]="Disable shallow cloning of Hyprland sources"
|
||||
descriptions[13]="Remove a plugin repository"
|
||||
descriptions[14]="Load a plugin"
|
||||
descriptions[15]="Send a hyprland notification for important events (e.g. load fail)"
|
||||
descriptions[16]="Show help menu"
|
||||
descriptions[17]="Reload all plugins"
|
||||
descriptions[18]="Force an operation ignoring checks (e.g. update -f)"
|
||||
|
||||
local -A literal_transitions
|
||||
literal_transitions[1]="([10]=7 [3]=3 [8]=7 [9]=7 [5]=7 [11]=3 [12]=4 [6]=3 [14]=7 [4]=4 [15]=3 [16]=7 [7]=3)"
|
||||
literal_transitions[2]="([11]=3 [12]=4 [4]=4 [3]=3 [15]=3 [6]=3 [7]=3)"
|
||||
literal_transitions[5]="([2]=6)"
|
||||
literal_transitions[6]="([1]=7 [13]=7)"
|
||||
literal_transitions[1]="([1]=8 [4]=4 [5]=5 [9]=8 [10]=8 [7]=5 [8]=5 [12]=8 [6]=8 [11]=8 [13]=3 [14]=4 [16]=8 [17]=5 [18]=8)"
|
||||
literal_transitions[2]="([13]=3 [14]=4 [4]=4 [5]=5 [17]=5 [7]=5 [8]=5)"
|
||||
literal_transitions[6]="([3]=7)"
|
||||
literal_transitions[7]="([2]=8 [15]=8)"
|
||||
|
||||
local -A match_anything_transitions
|
||||
match_anything_transitions=([4]=3 [3]=5 [1]=2 [2]=2)
|
||||
match_anything_transitions=([2]=2 [5]=6 [4]=5 [3]=5 [1]=2)
|
||||
|
||||
declare -A subword_transitions
|
||||
|
||||
@@ -91,7 +97,7 @@ _hyprpm () {
|
||||
fi
|
||||
done
|
||||
fi
|
||||
local -A commands=([4]=0)
|
||||
local -A commands=([4]=0 [3]=1)
|
||||
|
||||
if [[ -v "commands[$state]" ]]; then
|
||||
local command_id=${commands[$state]}
|
||||
|
@@ -49,7 +49,7 @@ void DataState::addNewPluginRepo(const SPluginRepository& repo) {
|
||||
{"rev", repo.rev}
|
||||
}}
|
||||
};
|
||||
for (auto& p : repo.plugins) {
|
||||
for (auto const& p : repo.plugins) {
|
||||
// copy .so to the good place
|
||||
if (std::filesystem::exists(p.filename))
|
||||
std::filesystem::copy_file(p.filename, PATH + "/" + p.name + ".so");
|
||||
|
@@ -6,7 +6,7 @@ CManifest::CManifest(const eManifestType type, const std::string& path) {
|
||||
auto manifest = toml::parse_file(path);
|
||||
|
||||
if (type == MANIFEST_HYPRLOAD) {
|
||||
for (auto& [key, val] : manifest) {
|
||||
for (auto const& [key, val] : manifest) {
|
||||
if (key.str().ends_with(".build"))
|
||||
continue;
|
||||
|
||||
@@ -63,7 +63,7 @@ CManifest::CManifest(const eManifestType type, const std::string& path) {
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& [key, val] : manifest) {
|
||||
for (auto const& [key, val] : manifest) {
|
||||
if (key.str() == "repository")
|
||||
continue;
|
||||
|
||||
|
@@ -12,32 +12,22 @@
|
||||
#include <algorithm>
|
||||
#include <format>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <toml++/toml.hpp>
|
||||
|
||||
static std::string removeBeginEndSpacesTabs(std::string str) {
|
||||
if (str.empty())
|
||||
return str;
|
||||
|
||||
int countBefore = 0;
|
||||
while (str[countBefore] == ' ' || str[countBefore] == '\t') {
|
||||
countBefore++;
|
||||
}
|
||||
|
||||
int countAfter = 0;
|
||||
while ((int)str.length() - countAfter - 1 >= 0 && (str[str.length() - countAfter - 1] == ' ' || str[str.length() - 1 - countAfter] == '\t')) {
|
||||
countAfter++;
|
||||
}
|
||||
|
||||
str = str.substr(countBefore, str.length() - countBefore - countAfter);
|
||||
|
||||
return str;
|
||||
}
|
||||
#include <hyprutils/string/String.hpp>
|
||||
using namespace Hyprutils::String;
|
||||
|
||||
static std::string execAndGet(std::string cmd) {
|
||||
cmd += " 2>&1";
|
||||
std::array<char, 128> buffer;
|
||||
std::string result;
|
||||
const std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
|
||||
using PcloseType = int (*)(FILE*);
|
||||
const std::unique_ptr<FILE, PcloseType> pipe(popen(cmd.c_str(), "r"), static_cast<PcloseType>(pclose));
|
||||
if (!pipe)
|
||||
return "";
|
||||
|
||||
@@ -92,9 +82,30 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() {
|
||||
return ver;
|
||||
}
|
||||
|
||||
bool CPluginManager::createSafeDirectory(const std::string& path) {
|
||||
if (path.empty() || !path.starts_with("/tmp"))
|
||||
return false;
|
||||
|
||||
if (std::filesystem::exists(path))
|
||||
std::filesystem::remove_all(path);
|
||||
|
||||
if (std::filesystem::exists(path))
|
||||
return false;
|
||||
|
||||
if (mkdir(path.c_str(), S_IRWXU) < 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& rev) {
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
|
||||
if (!hasDeps()) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DataState::pluginRepoExists(url)) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Repository already installed.\n";
|
||||
return false;
|
||||
@@ -132,28 +143,38 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
if (!std::filesystem::exists("/tmp/hyprpm")) {
|
||||
std::filesystem::create_directory("/tmp/hyprpm");
|
||||
std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace);
|
||||
} else if (!std::filesystem::is_directory("/tmp/hyprpm")) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for hyprpm\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::filesystem::exists("/tmp/hyprpm/new")) {
|
||||
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " old plugin repo build files found in temp directory, removing.");
|
||||
std::filesystem::remove_all("/tmp/hyprpm/new");
|
||||
const std::string USERNAME = getpwuid(getuid())->pw_name;
|
||||
|
||||
m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME;
|
||||
|
||||
if (!createSafeDirectory(m_szWorkingPluginDirectory)) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for repo\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + url);
|
||||
|
||||
std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + url + " new");
|
||||
std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + url + " " + USERNAME);
|
||||
|
||||
if (!std::filesystem::exists("/tmp/hyprpm/new")) {
|
||||
if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. shell returned:\n" << ret << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rev.empty()) {
|
||||
std::string ret = execAndGet("git -C /tmp/hyprpm/new reset --hard --recurse-submodules " + rev);
|
||||
std::string ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " reset --hard --recurse-submodules " + rev);
|
||||
if (ret.compare(0, 6, "fatal:") == 0) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not check out revision " << rev << ". shell returned:\n" << ret << "\n";
|
||||
return false;
|
||||
}
|
||||
ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " submodule update --init");
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "git submodule update --init returned: " << ret << "\n";
|
||||
}
|
||||
|
||||
progress.m_iSteps = 1;
|
||||
@@ -163,12 +184,12 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
|
||||
std::unique_ptr<CManifest> pManifest;
|
||||
|
||||
if (std::filesystem::exists("/tmp/hyprpm/new/hyprpm.toml")) {
|
||||
if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprpm.toml")) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprpm manifest");
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRPM, "/tmp/hyprpm/new/hyprpm.toml");
|
||||
} else if (std::filesystem::exists("/tmp/hyprpm/new/hyprload.toml")) {
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRPM, m_szWorkingPluginDirectory + "/hyprpm.toml");
|
||||
} else if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprload.toml")) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprload manifest");
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRLOAD, "/tmp/hyprpm/new/hyprload.toml");
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRLOAD, m_szWorkingPluginDirectory + "/hyprload.toml");
|
||||
}
|
||||
|
||||
if (!pManifest) {
|
||||
@@ -183,9 +204,9 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
|
||||
progress.m_iSteps = 2;
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " parsed manifest, found " + std::to_string(pManifest->m_vPlugins.size()) + " plugins:");
|
||||
for (auto& pl : pManifest->m_vPlugins) {
|
||||
for (auto const& pl : pManifest->m_vPlugins) {
|
||||
std::string message = std::string{Colors::RESET} + " → " + pl.name + " by ";
|
||||
for (auto& a : pl.authors) {
|
||||
for (auto const& a : pl.authors) {
|
||||
message += a + ", ";
|
||||
}
|
||||
if (pl.authors.size() > 0) {
|
||||
@@ -201,13 +222,19 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking");
|
||||
|
||||
for (auto& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||
for (auto const& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||
if (hl != HLVER.hash)
|
||||
continue;
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting");
|
||||
|
||||
execAndGet("cd /tmp/hyprpm/new/ && git reset --hard --recurse-submodules " + plugin);
|
||||
execAndGet("cd " + m_szWorkingPluginDirectory + " && git reset --hard --recurse-submodules " + plugin);
|
||||
|
||||
ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " submodule update --init");
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "git submodule update --init returned: " << ret << "\n";
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,15 +264,15 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||
|
||||
for (auto& bs : p.buildSteps) {
|
||||
std::string cmd = std::format("cd /tmp/hyprpm/new && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", DataState::getHeadersPath(), bs);
|
||||
for (auto const& bs : p.buildSteps) {
|
||||
std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs);
|
||||
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
|
||||
}
|
||||
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n";
|
||||
|
||||
if (!std::filesystem::exists("/tmp/hyprpm/new/" + p.output)) {
|
||||
if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Plugin " + p.name + " failed to build.\n" +
|
||||
" This likely means that the plugin is either outdated, not yet available for your version, or broken.\n If you are on -git, update "
|
||||
"first.\n Try re-running with -v to see "
|
||||
@@ -265,15 +292,15 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
|
||||
// add repo toml to DataState
|
||||
SPluginRepository repo;
|
||||
std::string repohash = execAndGet("cd /tmp/hyprpm/new/ && git rev-parse HEAD");
|
||||
std::string repohash = execAndGet("cd " + m_szWorkingPluginDirectory + " && git rev-parse HEAD");
|
||||
if (repohash.length() > 0)
|
||||
repohash.pop_back();
|
||||
repo.name = pManifest->m_sRepository.name.empty() ? url.substr(url.find_last_of('/') + 1) : pManifest->m_sRepository.name;
|
||||
repo.url = url;
|
||||
repo.rev = rev;
|
||||
repo.hash = repohash;
|
||||
for (auto& p : pManifest->m_vPlugins) {
|
||||
repo.plugins.push_back(SPlugin{p.name, "/tmp/hyprpm/new/" + p.output, false, p.failed});
|
||||
for (auto const& p : pManifest->m_vPlugins) {
|
||||
repo.plugins.push_back(SPlugin{p.name, m_szWorkingPluginDirectory + "/" + p.output, false, p.failed});
|
||||
}
|
||||
DataState::addNewPluginRepo(repo);
|
||||
|
||||
@@ -286,7 +313,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
|
||||
std::cout << "\n";
|
||||
|
||||
// remove build files
|
||||
std::filesystem::remove_all("/tmp/hyprpm/new");
|
||||
std::filesystem::remove_all(m_szWorkingPluginDirectory);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -338,10 +365,10 @@ eHeadersErrors CPluginManager::headersValid() {
|
||||
else
|
||||
headers = "";
|
||||
|
||||
if (PATH.ends_with("protocols") || PATH.ends_with("wlroots-hyprland"))
|
||||
if (PATH.ends_with("protocols"))
|
||||
continue;
|
||||
|
||||
verHeader = removeBeginEndSpacesTabs(PATH.substr(2)) + "/hyprland/src/version.h";
|
||||
verHeader = trim(PATH.substr(2)) + "/hyprland/src/version.h";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -378,6 +405,11 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
|
||||
const auto HLVER = getHyprlandVersion();
|
||||
|
||||
if (!hasDeps()) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not update. Dependencies not satisfied. Hyprpm requires: cmake, meson, cpio\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists("/tmp/hyprpm")) {
|
||||
std::filesystem::create_directory("/tmp/hyprpm");
|
||||
std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace);
|
||||
@@ -394,16 +426,35 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
progress.m_szCurrentMessage = "Cloning the hyprland repository";
|
||||
progress.print();
|
||||
|
||||
if (std::filesystem::exists("/tmp/hyprpm/hyprland")) {
|
||||
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " old hyprland source files found in temp directory, removing.");
|
||||
std::filesystem::remove_all("/tmp/hyprpm/hyprland");
|
||||
const std::string USERNAME = getpwuid(getuid())->pw_name;
|
||||
const auto WORKINGDIR = "/tmp/hyprpm/hyprland-" + USERNAME;
|
||||
|
||||
if (!createSafeDirectory(WORKINGDIR)) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for hl\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment.");
|
||||
|
||||
std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland --shallow-since='" + HLVER.date + "'");
|
||||
const bool bShallow = (HLVER.branch == "main" || HLVER.branch == "") && !m_bNoShallow;
|
||||
|
||||
if (!std::filesystem::exists("/tmp/hyprpm/hyprland")) {
|
||||
// let us give a bit of leg-room for shallowing
|
||||
// due to timezones, etc.
|
||||
const std::string SHALLOW_DATE =
|
||||
trim(HLVER.date).empty() ? "" : execAndGet("LC_TIME=\"en_US.UTF-8\" date --date='" + HLVER.date + " - 1 weeks' '+\%a \%b \%d \%H:\%M:\%S \%Y'");
|
||||
|
||||
if (m_bVerbose && bShallow)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will shallow since: " + SHALLOW_DATE);
|
||||
|
||||
std::string ret =
|
||||
execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME + (bShallow ? " --shallow-since='" + SHALLOW_DATE + "'" : ""));
|
||||
|
||||
if (!std::filesystem::exists(WORKINGDIR)) {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Clone failed. Retrying without shallow.");
|
||||
ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME);
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(WORKINGDIR + "/.git")) {
|
||||
std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the hyprland repository. shell returned:\n" << ret << "\n";
|
||||
return false;
|
||||
}
|
||||
@@ -413,11 +464,25 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
progress.m_szCurrentMessage = "Checking out sources";
|
||||
progress.print();
|
||||
|
||||
ret = execAndGet("cd /tmp/hyprpm/hyprland && git checkout " + HLVER.branch +
|
||||
" 2>&1 && git rm subprojects/tracy && git submodule update --init 2>&1 && git reset --hard --recurse-submodules " + HLVER.hash);
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will run: " + "cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1");
|
||||
|
||||
ret = execAndGet("cd " + WORKINGDIR + " && git checkout " + HLVER.hash + " 2>&1");
|
||||
|
||||
if (ret.contains("fatal: unable to read tree")) {
|
||||
std::cerr << "\n"
|
||||
<< Colors::RED << "✖" << Colors::RESET
|
||||
<< " Could not checkout the running Hyprland commit. If you are on -git, try updating.\nYou can also try re-running hyprpm update with --no-shallow.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned: " + ret);
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (co): " + ret);
|
||||
|
||||
ret = execAndGet("cd " + WORKINGDIR + " ; git rm subprojects/tracy ; git submodule update --init 2>&1 ; git reset --hard --recurse-submodules " + HLVER.hash);
|
||||
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (rs): " + ret);
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " checked out to running ver");
|
||||
progress.m_iSteps = 3;
|
||||
@@ -429,24 +494,31 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "setting PREFIX for cmake to " + DataState::getHeadersPath());
|
||||
|
||||
ret = execAndGet(
|
||||
std::format("cd /tmp/hyprpm/hyprland && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=\"{}\" -S . -B ./build -G Ninja",
|
||||
ret = execAndGet(std::format("cd {} && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=\"{}\" -S . -B ./build -G Ninja", WORKINGDIR,
|
||||
DataState::getHeadersPath()));
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "cmake returned: " + ret);
|
||||
|
||||
// le hack. Wlroots has to generate its build/include
|
||||
ret = execAndGet("cd /tmp/hyprpm/hyprland/subprojects/wlroots-hyprland && meson setup -Drenderers=gles2 -Dexamples=false build");
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "meson returned: " + ret);
|
||||
if (ret.contains("CMake Error at")) {
|
||||
// missing deps, let the user know.
|
||||
std::string missing = ret.substr(ret.find("CMake Error at"));
|
||||
missing = ret.substr(ret.find_first_of('\n') + 1);
|
||||
missing = missing.substr(0, missing.find("-- Configuring incomplete"));
|
||||
missing = missing.substr(0, missing.find_last_of('\n'));
|
||||
|
||||
std::cerr << "\n"
|
||||
<< Colors::RED << "✖" << Colors::RESET << " Could not configure the hyprland source, cmake complained:\n"
|
||||
<< missing << "\n\nThis likely means that you are missing the above dependencies or they are out of date.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " configured Hyprland");
|
||||
progress.m_iSteps = 4;
|
||||
progress.m_szCurrentMessage = "Installing sources";
|
||||
progress.print();
|
||||
|
||||
std::string cmd = std::format("sed -i -e \"s#PREFIX = /usr/local#PREFIX = {}#\" /tmp/hyprpm/hyprland/Makefile && cd /tmp/hyprpm/hyprland && make installheaders",
|
||||
DataState::getHeadersPath());
|
||||
std::string cmd =
|
||||
std::format("sed -i -e \"s#PREFIX = /usr/local#PREFIX = {}#\" {}/Makefile && cd {} && make installheaders", DataState::getHeadersPath(), WORKINGDIR, WORKINGDIR);
|
||||
if (m_bVerbose)
|
||||
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "installation will run: " + cmd);
|
||||
|
||||
@@ -456,7 +528,7 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "installer returned: " << ret << "\n";
|
||||
|
||||
// remove build files
|
||||
std::filesystem::remove_all("/tmp/hyprpm/hyprland");
|
||||
std::filesystem::remove_all(WORKINGDIR);
|
||||
|
||||
auto HEADERSVALID = headersValid();
|
||||
if (HEADERSVALID == HEADERS_OK) {
|
||||
@@ -467,7 +539,8 @@ bool CPluginManager::updateHeaders(bool force) {
|
||||
|
||||
std::cout << "\n";
|
||||
} else {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID));
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID) + " (" +
|
||||
headerErrorShort(HEADERSVALID) + ")");
|
||||
progress.m_iSteps = 5;
|
||||
progress.m_szCurrentMessage = "Failed";
|
||||
progress.print();
|
||||
@@ -503,7 +576,10 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
progress.m_szCurrentMessage = "Updating repositories";
|
||||
progress.print();
|
||||
|
||||
for (auto& repo : REPOS) {
|
||||
const std::string USERNAME = getpwuid(getuid())->pw_name;
|
||||
m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME;
|
||||
|
||||
for (auto const& repo : REPOS) {
|
||||
bool update = forceUpdateAll;
|
||||
|
||||
progress.m_iSteps++;
|
||||
@@ -512,16 +588,13 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → checking for updates for " + repo.name);
|
||||
|
||||
if (std::filesystem::exists("/tmp/hyprpm/update")) {
|
||||
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " old update build files found in temp directory, removing.");
|
||||
std::filesystem::remove_all("/tmp/hyprpm/update");
|
||||
}
|
||||
createSafeDirectory(m_szWorkingPluginDirectory);
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + repo.url);
|
||||
|
||||
std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + repo.url + " update");
|
||||
std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + repo.url + " " + USERNAME);
|
||||
|
||||
if (!std::filesystem::exists("/tmp/hyprpm/update")) {
|
||||
if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) {
|
||||
std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " could not clone repo: shell returned:\n" + ret;
|
||||
return false;
|
||||
}
|
||||
@@ -529,7 +602,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
if (!repo.rev.empty()) {
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Plugin has revision set, resetting: " + repo.rev);
|
||||
|
||||
std::string ret = execAndGet("git -C /tmp/hyprpm/update reset --hard --recurse-submodules " + repo.rev);
|
||||
std::string ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " reset --hard --recurse-submodules " + repo.rev);
|
||||
if (ret.compare(0, 6, "fatal:") == 0) {
|
||||
std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " could not check out revision " + repo.rev + ": shell returned:\n" + ret;
|
||||
return false;
|
||||
@@ -538,7 +611,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
|
||||
if (!update) {
|
||||
// check if git has updates
|
||||
std::string hash = execAndGet("cd /tmp/hyprpm/update && git rev-parse HEAD");
|
||||
std::string hash = execAndGet("cd " + m_szWorkingPluginDirectory + " && git rev-parse HEAD");
|
||||
if (!hash.empty())
|
||||
hash.pop_back();
|
||||
|
||||
@@ -546,7 +619,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
}
|
||||
|
||||
if (!update) {
|
||||
std::filesystem::remove_all("/tmp/hyprpm/update");
|
||||
std::filesystem::remove_all(m_szWorkingPluginDirectory);
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " repository " + repo.name + " is up-to-date.");
|
||||
progress.m_iSteps++;
|
||||
progress.print();
|
||||
@@ -562,12 +635,12 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
|
||||
std::unique_ptr<CManifest> pManifest;
|
||||
|
||||
if (std::filesystem::exists("/tmp/hyprpm/update/hyprpm.toml")) {
|
||||
if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprpm.toml")) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprpm manifest");
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRPM, "/tmp/hyprpm/update/hyprpm.toml");
|
||||
} else if (std::filesystem::exists("/tmp/hyprpm/update/hyprload.toml")) {
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRPM, m_szWorkingPluginDirectory + "/hyprpm.toml");
|
||||
} else if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprload.toml")) {
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprload manifest");
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRLOAD, "/tmp/hyprpm/update/hyprload.toml");
|
||||
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRLOAD, m_szWorkingPluginDirectory + "/hyprload.toml");
|
||||
}
|
||||
|
||||
if (!pManifest) {
|
||||
@@ -585,20 +658,20 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking");
|
||||
|
||||
for (auto& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||
for (auto const& [hl, plugin] : pManifest->m_sRepository.commitPins) {
|
||||
if (hl != HLVER.hash)
|
||||
continue;
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting");
|
||||
|
||||
execAndGet("cd /tmp/hyprpm/update/ && git reset --hard --recurse-submodules " + plugin);
|
||||
execAndGet("cd " + m_szWorkingPluginDirectory + " && git reset --hard --recurse-submodules " + plugin);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& p : pManifest->m_vPlugins) {
|
||||
std::string out;
|
||||
|
||||
if (p.since > HLVER.commits && HLVER.commits >= 1 /* for --depth 1 clones, we can't check this. */) {
|
||||
if (p.since > HLVER.commits && HLVER.commits >= 1000 /* for shallow clones, we can't check this. 1000 is an arbitrary number I chose. */) {
|
||||
progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Not building " + p.name + ": your Hyprland version is too old.\n");
|
||||
p.failed = true;
|
||||
continue;
|
||||
@@ -606,15 +679,15 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
|
||||
|
||||
for (auto& bs : p.buildSteps) {
|
||||
std::string cmd = std::format("cd /tmp/hyprpm/update && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", DataState::getHeadersPath(), bs);
|
||||
for (auto const& bs : p.buildSteps) {
|
||||
std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs);
|
||||
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
|
||||
}
|
||||
|
||||
if (m_bVerbose)
|
||||
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n";
|
||||
|
||||
if (!std::filesystem::exists("/tmp/hyprpm/update/" + p.output)) {
|
||||
if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) {
|
||||
std::cerr << "\n"
|
||||
<< Colors::RED << "✖" << Colors::RESET << " Plugin " << p.name << " failed to build.\n"
|
||||
<< " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n If you are on -git, update first.\n Try "
|
||||
@@ -630,20 +703,20 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
|
||||
// add repo toml to DataState
|
||||
SPluginRepository newrepo = repo;
|
||||
newrepo.plugins.clear();
|
||||
execAndGet(
|
||||
"cd /tmp/hyprpm/update/ && git pull --recurse-submodules && git reset --hard --recurse-submodules"); // repo hash in the state.toml has to match head and not any pin
|
||||
std::string repohash = execAndGet("cd /tmp/hyprpm/update && git rev-parse HEAD");
|
||||
execAndGet("cd " + m_szWorkingPluginDirectory +
|
||||
" && git pull --recurse-submodules && git reset --hard --recurse-submodules"); // repo hash in the state.toml has to match head and not any pin
|
||||
std::string repohash = execAndGet("cd " + m_szWorkingPluginDirectory + " && git rev-parse HEAD");
|
||||
if (repohash.length() > 0)
|
||||
repohash.pop_back();
|
||||
newrepo.hash = repohash;
|
||||
for (auto& p : pManifest->m_vPlugins) {
|
||||
for (auto const& p : pManifest->m_vPlugins) {
|
||||
const auto OLDPLUGINIT = std::find_if(repo.plugins.begin(), repo.plugins.end(), [&](const auto& other) { return other.name == p.name; });
|
||||
newrepo.plugins.push_back(SPlugin{p.name, "/tmp/hyprpm/update/" + p.output, OLDPLUGINIT != repo.plugins.end() ? OLDPLUGINIT->enabled : false});
|
||||
newrepo.plugins.push_back(SPlugin{p.name, m_szWorkingPluginDirectory + "/" + p.output, OLDPLUGINIT != repo.plugins.end() ? OLDPLUGINIT->enabled : false});
|
||||
}
|
||||
DataState::removePluginRepo(newrepo.name);
|
||||
DataState::addNewPluginRepo(newrepo);
|
||||
|
||||
std::filesystem::remove_all("/tmp/hyprpm/update");
|
||||
std::filesystem::remove_all(m_szWorkingPluginDirectory);
|
||||
|
||||
progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " updated " + repo.name);
|
||||
}
|
||||
@@ -721,8 +794,8 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
||||
const auto REPOS = DataState::getAllRepositories();
|
||||
|
||||
auto enabled = [REPOS](const std::string& plugin) -> bool {
|
||||
for (auto& r : REPOS) {
|
||||
for (auto& p : r.plugins) {
|
||||
for (auto const& r : REPOS) {
|
||||
for (auto const& p : r.plugins) {
|
||||
if (p.name == plugin && p.enabled)
|
||||
return true;
|
||||
}
|
||||
@@ -732,8 +805,8 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
||||
};
|
||||
|
||||
auto repoForName = [REPOS](const std::string& name) -> std::string {
|
||||
for (auto& r : REPOS) {
|
||||
for (auto& p : r.plugins) {
|
||||
for (auto const& r : REPOS) {
|
||||
for (auto const& p : r.plugins) {
|
||||
if (p.name == name)
|
||||
return r.name;
|
||||
}
|
||||
@@ -743,7 +816,7 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
||||
};
|
||||
|
||||
// unload disabled plugins
|
||||
for (auto& p : loadedPlugins) {
|
||||
for (auto const& p : loadedPlugins) {
|
||||
if (!enabled(p)) {
|
||||
// unload
|
||||
loadUnloadPlugin(HYPRPMPATH + repoForName(p) + "/" + p + ".so", false);
|
||||
@@ -752,8 +825,8 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
|
||||
}
|
||||
|
||||
// load enabled plugins
|
||||
for (auto& r : REPOS) {
|
||||
for (auto& p : r.plugins) {
|
||||
for (auto const& r : REPOS) {
|
||||
for (auto const& p : r.plugins) {
|
||||
if (!p.enabled)
|
||||
continue;
|
||||
|
||||
@@ -782,10 +855,10 @@ bool CPluginManager::loadUnloadPlugin(const std::string& path, bool load) {
|
||||
void CPluginManager::listAllPlugins() {
|
||||
const auto REPOS = DataState::getAllRepositories();
|
||||
|
||||
for (auto& r : REPOS) {
|
||||
for (auto const& r : REPOS) {
|
||||
std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n";
|
||||
|
||||
for (auto& p : r.plugins) {
|
||||
for (auto const& p : r.plugins) {
|
||||
|
||||
std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name;
|
||||
|
||||
@@ -817,3 +890,25 @@ std::string CPluginManager::headerError(const eHeadersErrors err) {
|
||||
|
||||
return std::string{Colors::RED} + "✖" + Colors::RESET + " Unknown header error. Please run hyprpm update to fix those.\n";
|
||||
}
|
||||
|
||||
std::string CPluginManager::headerErrorShort(const eHeadersErrors err) {
|
||||
switch (err) {
|
||||
case HEADERS_CORRUPTED: return "Headers corrupted";
|
||||
case HEADERS_MISMATCHED: return "Headers version mismatched";
|
||||
case HEADERS_NOT_HYPRLAND: return "Not running on Hyprland";
|
||||
case HEADERS_MISSING: return "Headers missing";
|
||||
case HEADERS_DUPLICATED: return "Headers duplicated";
|
||||
default: break;
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
bool CPluginManager::hasDeps() {
|
||||
std::vector<std::string> deps = {"meson", "cpio", "cmake", "pkg-config"};
|
||||
for (auto const& d : deps) {
|
||||
if (!execAndGet("command -v " + d).contains("/"))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -56,10 +56,19 @@ class CPluginManager {
|
||||
|
||||
void notify(const eNotifyIcons icon, uint32_t color, int durationMs, const std::string& message);
|
||||
|
||||
bool hasDeps();
|
||||
|
||||
bool m_bVerbose = false;
|
||||
bool m_bNoShallow = false;
|
||||
|
||||
// will delete recursively if exists!!
|
||||
bool createSafeDirectory(const std::string& path);
|
||||
|
||||
private:
|
||||
std::string headerError(const eHeadersErrors err);
|
||||
std::string headerErrorShort(const eHeadersErrors err);
|
||||
|
||||
std::string m_szWorkingPluginDirectory = "";
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CPluginManager> g_pPluginManager;
|
||||
|
@@ -26,6 +26,7 @@ const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
|
||||
┣ --help | -h → Show this menu
|
||||
┣ --verbose | -v → Enable too much logging
|
||||
┣ --force | -f → Force an operation ignoring checks (e.g. update -f)
|
||||
┣ --no-shallow | -s → Disable shallow cloning of Hyprland sources
|
||||
┗
|
||||
)#";
|
||||
|
||||
@@ -41,7 +42,7 @@ int main(int argc, char** argv, char** envp) {
|
||||
}
|
||||
|
||||
std::vector<std::string> command;
|
||||
bool notify = false, verbose = false, force = false;
|
||||
bool notify = false, verbose = false, force = false, noShallow = false;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (ARGS[i].starts_with("-")) {
|
||||
@@ -52,6 +53,8 @@ int main(int argc, char** argv, char** envp) {
|
||||
notify = true;
|
||||
} else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") {
|
||||
verbose = true;
|
||||
} else if (ARGS[i] == "--no-shallow" || ARGS[i] == "-s") {
|
||||
noShallow = true;
|
||||
} else if (ARGS[i] == "--force" || ARGS[i] == "-f") {
|
||||
force = true;
|
||||
std::cout << Colors::RED << "!" << Colors::RESET << " Using --force, I hope you know what you are doing.\n";
|
||||
@@ -71,6 +74,7 @@ int main(int argc, char** argv, char** envp) {
|
||||
|
||||
g_pPluginManager = std::make_unique<CPluginManager>();
|
||||
g_pPluginManager->m_bVerbose = verbose;
|
||||
g_pPluginManager->m_bNoShallow = noShallow;
|
||||
|
||||
if (command[0] == "add") {
|
||||
if (command.size() < 2) {
|
||||
|
@@ -3,12 +3,13 @@ src = globber.stdout().strip().split('\n')
|
||||
|
||||
executable('hyprpm', src,
|
||||
dependencies: [
|
||||
dependency('hyprutils', version: '>= 0.1.1'),
|
||||
dependency('threads'),
|
||||
dependency('tomlplusplus')
|
||||
],
|
||||
install : true
|
||||
)
|
||||
|
||||
install_data('../hyprpm.bash', install_dir: join_paths(get_option('datadir'), 'bash-completions'), install_tag: 'runtime', rename: 'hyprpm')
|
||||
install_data('../hyprpm.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprpm')
|
||||
install_data('../hyprpm.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime')
|
||||
install_data('../hyprpm.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprpm')
|
||||
|
48
meson.build
@@ -1,64 +1,54 @@
|
||||
project('Hyprland', 'cpp', 'c',
|
||||
version : run_command('jq', '-r', '.version', join_paths(meson.source_root(), 'props.json'), check: true).stdout().strip(),
|
||||
version : run_command('cat', join_paths(meson.source_root(), 'VERSION'), check: true).stdout().strip(),
|
||||
default_options : [
|
||||
'warning_level=2',
|
||||
'default_library=static',
|
||||
'optimization=3',
|
||||
'buildtype=release',
|
||||
'debug=false'
|
||||
# 'cpp_std=c++23' # not yet supported by meson, as of version 0.63.0
|
||||
'debug=false',
|
||||
'cpp_std=c++26',
|
||||
])
|
||||
|
||||
# clang v14.0.6 uses C++2b instead of C++23, so we've gotta account for that
|
||||
# replace the following with a project default option once meson gets support for C++23
|
||||
cpp_compiler = meson.get_compiler('cpp')
|
||||
if cpp_compiler.has_argument('-std=c++23')
|
||||
add_global_arguments('-std=c++23', language: 'cpp')
|
||||
elif cpp_compiler.has_argument('-std=c++2b')
|
||||
add_global_arguments('-std=c++2b', language: 'cpp')
|
||||
else
|
||||
error('Could not configure current C++ compiler (' + cpp_compiler.get_id() + ' ' + cpp_compiler.version() + ') with required C++ standard (C++23)')
|
||||
endif
|
||||
|
||||
datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"'
|
||||
add_project_arguments(
|
||||
[
|
||||
'-Wno-unused-parameter',
|
||||
'-Wno-unused-value',
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-narrowing',
|
||||
'-Wno-pointer-arith',
|
||||
datarootdir,
|
||||
],
|
||||
language: 'cpp')
|
||||
|
||||
cpp_compiler = meson.get_compiler('cpp')
|
||||
if cpp_compiler.check_header('execinfo.h')
|
||||
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
|
||||
endif
|
||||
|
||||
wlroots = subproject('wlroots-hyprland', default_options: ['examples=false', 'renderers=gles2'])
|
||||
have_xwlr = wlroots.get_variable('features').get('xwayland')
|
||||
xcb_dep = dependency('xcb', required: get_option('xwayland'))
|
||||
xcb_composite_dep = dependency('xcb-composite', required: get_option('xwayland'))
|
||||
xcb_errors_dep = dependency('xcb-errors', required: get_option('xwayland'))
|
||||
xcb_icccm_dep = dependency('xcb-icccm', required: get_option('xwayland'))
|
||||
xcb_render_dep = dependency('xcb-render', required: get_option('xwayland'))
|
||||
xcb_res_dep = dependency('xcb-res', required: get_option('xwayland'))
|
||||
xcb_xfixes_dep = dependency('xcb-xfixes', required: get_option('xwayland'))
|
||||
|
||||
gio_dep = dependency('gio-2.0', required:true)
|
||||
|
||||
cmake = import('cmake')
|
||||
udis = cmake.subproject('udis86')
|
||||
udis86 = udis.dependency('libudis86')
|
||||
|
||||
if get_option('xwayland').enabled() and not have_xwlr
|
||||
error('Cannot enable Xwayland in Hyprland: wlroots has been built without Xwayland support')
|
||||
endif
|
||||
have_xwayland = xcb_dep.found() and have_xwlr
|
||||
|
||||
if not have_xwayland
|
||||
if not xcb_dep.found()
|
||||
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
||||
endif
|
||||
|
||||
backtrace_dep = cpp_compiler.find_library('execinfo', required: false)
|
||||
systemd_dep = dependency('libsystemd', required: get_option('systemd'))
|
||||
epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs
|
||||
|
||||
if get_option('systemd').enabled()
|
||||
if systemd_dep.found()
|
||||
add_project_arguments('-DUSES_SYSTEMD', language: 'cpp')
|
||||
else
|
||||
error('Cannot enable systemd in Hyprland: libsystemd was not found')
|
||||
endif
|
||||
endif
|
||||
|
||||
if get_option('legacy_renderer').enabled()
|
||||
@@ -69,7 +59,7 @@ if get_option('buildtype') == 'debug'
|
||||
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
|
||||
endif
|
||||
|
||||
version_h = run_command('sh', '-c', 'scripts/generateVersion.sh')
|
||||
version_h = run_command('sh', '-c', 'scripts/generateVersion.sh', check: true)
|
||||
|
||||
globber = run_command('find', 'src', '-name', '*.h*', check: true)
|
||||
headers = globber.stdout().strip().split('\n')
|
||||
@@ -93,5 +83,5 @@ import('pkgconfig').generate(
|
||||
url: 'https://github.com/hyprwm/Hyprland',
|
||||
description: 'Hyprland header files',
|
||||
install_dir: pkg_install_dir,
|
||||
subdirs: ['', 'hyprland/protocols', 'hyprland/wlroots'],
|
||||
subdirs: ['', 'hyprland/protocols', 'hyprland'],
|
||||
)
|
||||
|
113
nix/default.nix
@@ -4,32 +4,33 @@
|
||||
pkg-config,
|
||||
pkgconf,
|
||||
makeWrapper,
|
||||
meson,
|
||||
cmake,
|
||||
ninja,
|
||||
aquamarine,
|
||||
binutils,
|
||||
cairo,
|
||||
git,
|
||||
hyprcursor,
|
||||
hyprland-protocols,
|
||||
hyprlang,
|
||||
hyprutils,
|
||||
hyprwayland-scanner,
|
||||
jq,
|
||||
libGL,
|
||||
libdrm,
|
||||
libexecinfo,
|
||||
libinput,
|
||||
libxcb,
|
||||
libxkbcommon,
|
||||
libuuid,
|
||||
mesa,
|
||||
pango,
|
||||
pciutils,
|
||||
python3,
|
||||
systemd,
|
||||
tomlplusplus,
|
||||
udis86,
|
||||
wayland,
|
||||
wayland-protocols,
|
||||
wayland-scanner,
|
||||
wlroots-hyprland,
|
||||
xcbutilwm,
|
||||
xorg,
|
||||
xwayland,
|
||||
debug ? false,
|
||||
enableXWayland ? true,
|
||||
@@ -38,6 +39,7 @@
|
||||
wrapRuntimeDeps ? true,
|
||||
version ? "git",
|
||||
commit,
|
||||
revCount,
|
||||
date,
|
||||
# deprecated flags
|
||||
enableNvidiaPatches ? false,
|
||||
@@ -46,9 +48,7 @@
|
||||
}:
|
||||
assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed.";
|
||||
assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed.";
|
||||
assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; let
|
||||
wlr = wlroots-hyprland.override {inherit enableXWayland;};
|
||||
in
|
||||
assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland";
|
||||
stdenv.mkDerivation {
|
||||
pname = "hyprland${lib.optionalString debug "-debug"}";
|
||||
inherit version;
|
||||
@@ -62,35 +62,35 @@ in
|
||||
};
|
||||
|
||||
patches = [
|
||||
# make meson use the provided wlroots instead of the git submodule
|
||||
./patches/meson-build.patch
|
||||
# forces GCC to use -std=c++26
|
||||
./stdcxx.patch
|
||||
];
|
||||
|
||||
postPatch = ''
|
||||
# Fix hardcoded paths to /usr installation
|
||||
sed -i "s#/usr#$out#" src/render/OpenGL.cpp
|
||||
|
||||
# Generate version.h
|
||||
cp src/version.h.in src/version.h
|
||||
substituteInPlace src/version.h \
|
||||
--replace "@HASH@" '${commit}' \
|
||||
--replace "@BRANCH@" "" \
|
||||
--replace "@MESSAGE@" "" \
|
||||
--replace "@DATE@" "${date}" \
|
||||
--replace "@TAG@" "" \
|
||||
--replace "@DIRTY@" '${
|
||||
if commit == ""
|
||||
then "dirty"
|
||||
else ""
|
||||
}'
|
||||
# Remove extra @PREFIX@ to fix pkg-config paths
|
||||
sed -i "s#@PREFIX@/##g" hyprland.pc.in
|
||||
'';
|
||||
|
||||
COMMITS = revCount;
|
||||
DATE = date;
|
||||
DIRTY = lib.optionalString (commit == "") "dirty";
|
||||
HASH = commit;
|
||||
|
||||
depsBuildBuild = [
|
||||
pkg-config
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
hyprwayland-scanner
|
||||
jq
|
||||
makeWrapper
|
||||
meson
|
||||
cmake
|
||||
ninja
|
||||
pkg-config
|
||||
python3 # for udis86
|
||||
wayland-scanner
|
||||
];
|
||||
|
||||
@@ -100,51 +100,64 @@ in
|
||||
"dev"
|
||||
];
|
||||
|
||||
buildInputs =
|
||||
wlr.buildInputs
|
||||
++ [
|
||||
buildInputs = lib.concatLists [
|
||||
[
|
||||
aquamarine
|
||||
cairo
|
||||
# expat
|
||||
# fribidi
|
||||
git
|
||||
hyprcursor.dev
|
||||
hyprland-protocols
|
||||
hyprcursor
|
||||
hyprlang
|
||||
hyprutils
|
||||
# libdatrie
|
||||
libdrm
|
||||
libGL
|
||||
libinput
|
||||
# libselinux
|
||||
# libsepol
|
||||
# libthai
|
||||
libuuid
|
||||
libxkbcommon
|
||||
mesa
|
||||
pango
|
||||
pciutils
|
||||
# pcre2
|
||||
tomlplusplus
|
||||
udis86
|
||||
wayland
|
||||
wayland-protocols
|
||||
wlr
|
||||
xorg.libXcursor
|
||||
]
|
||||
++ lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]
|
||||
++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland]
|
||||
++ lib.optionals withSystemd [systemd];
|
||||
(lib.optionals stdenv.hostPlatform.isMusl [libexecinfo])
|
||||
(lib.optionals enableXWayland [
|
||||
xorg.libxcb
|
||||
xorg.libXdmcp
|
||||
xorg.xcbutilerrors
|
||||
xorg.xcbutilrenderutil
|
||||
xorg.xcbutilwm
|
||||
xwayland
|
||||
])
|
||||
(lib.optionals withSystemd [systemd])
|
||||
];
|
||||
|
||||
mesonBuildType =
|
||||
cmakeBuildType =
|
||||
if debug
|
||||
then "debug"
|
||||
else "release";
|
||||
then "Debug"
|
||||
else "RelWithDebInfo";
|
||||
|
||||
mesonAutoFeatures = "disabled";
|
||||
# we want as much debug info as possible
|
||||
dontStrip = debug;
|
||||
|
||||
mesonFlags = [
|
||||
(lib.mesonEnable "xwayland" enableXWayland)
|
||||
(lib.mesonEnable "legacy_renderer" legacyRenderer)
|
||||
(lib.mesonEnable "systemd" withSystemd)
|
||||
cmakeFlags = [
|
||||
(lib.cmakeBool "NO_XWAYLAND" (!enableXWayland))
|
||||
(lib.cmakeBool "LEGACY_RENDERER" legacyRenderer)
|
||||
(lib.cmakeBool "NO_SYSTEMD" (!withSystemd))
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
ln -s ${wlr}/include/wlr $dev/include/hyprland/wlroots
|
||||
|
||||
${lib.optionalString wrapRuntimeDeps ''
|
||||
wrapProgram $out/bin/Hyprland \
|
||||
--suffix PATH : ${lib.makeBinPath [
|
||||
stdenv.cc
|
||||
binutils
|
||||
pciutils
|
||||
pkgconf
|
||||
@@ -154,11 +167,11 @@ in
|
||||
|
||||
passthru.providedSessions = ["hyprland"];
|
||||
|
||||
meta = with lib; {
|
||||
meta = {
|
||||
homepage = "https://github.com/hyprwm/Hyprland";
|
||||
description = "A dynamic tiling Wayland compositor that doesn't sacrifice on its looks";
|
||||
license = licenses.bsd3;
|
||||
platforms = wlr.meta.platforms;
|
||||
description = "Dynamic tiling Wayland compositor that doesn't sacrifice on its looks";
|
||||
license = lib.licenses.bsd3;
|
||||
platforms = lib.platforms.linux;
|
||||
mainProgram = "Hyprland";
|
||||
};
|
||||
}
|
||||
|
@@ -3,13 +3,12 @@
|
||||
lib,
|
||||
inputs,
|
||||
}: let
|
||||
props = builtins.fromJSON (builtins.readFile ../props.json);
|
||||
|
||||
mkDate = longDate: (lib.concatStringsSep "-" [
|
||||
(builtins.substring 0 4 longDate)
|
||||
(builtins.substring 4 2 longDate)
|
||||
(builtins.substring 6 2 longDate)
|
||||
]);
|
||||
version = lib.removeSuffix "\n" (builtins.readFile ../VERSION);
|
||||
in {
|
||||
# Contains what a user is most likely to care about:
|
||||
# Hyprland itself, XDPH and the Share Picker.
|
||||
@@ -21,32 +20,35 @@ in {
|
||||
# Packages for variations of Hyprland, dependencies included.
|
||||
hyprland-packages = lib.composeManyExtensions [
|
||||
# Dependencies
|
||||
inputs.aquamarine.overlays.default
|
||||
inputs.hyprcursor.overlays.default
|
||||
inputs.hyprland-protocols.overlays.default
|
||||
inputs.hyprlang.overlays.default
|
||||
self.overlays.wlroots-hyprland
|
||||
self.overlays.udis86
|
||||
inputs.hyprutils.overlays.default
|
||||
inputs.hyprwayland-scanner.overlays.default
|
||||
|
||||
# Hyprland packages themselves
|
||||
(final: prev: let
|
||||
date = mkDate (self.lastModifiedDate or "19700101");
|
||||
in {
|
||||
hyprland = final.callPackage ./default.nix {
|
||||
stdenv = final.gcc13Stdenv;
|
||||
version = "${props.version}+date=${date}_${self.shortRev or "dirty"}";
|
||||
stdenv = final.gcc14Stdenv;
|
||||
version = "${version}+date=${date}_${self.shortRev or "dirty"}";
|
||||
commit = self.rev or "";
|
||||
udis86 = final.udis86-hyprland; # explicit override until decided on breaking change of the name
|
||||
inherit (final) wlroots-hyprland; # explicit override until decided on breaking change of the name
|
||||
revCount = self.sourceInfo.revCount or "";
|
||||
inherit date;
|
||||
};
|
||||
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};
|
||||
hyprland-debug = final.hyprland.override {debug = true;};
|
||||
hyprland-legacy-renderer = final.hyprland.override {legacyRenderer = true;};
|
||||
|
||||
# deprecated packages
|
||||
hyprland-nvidia =
|
||||
builtins.trace ''
|
||||
hyprland-nvidia was removed. Please use the hyprland package.
|
||||
Nvidia patches are no longer needed.
|
||||
''
|
||||
final.hyprland;
|
||||
|
||||
hyprland-hidpi =
|
||||
builtins.trace ''
|
||||
hyprland-hidpi was removed. Please use the hyprland package.
|
||||
@@ -61,18 +63,4 @@ in {
|
||||
hyprland-extras = lib.composeManyExtensions [
|
||||
inputs.xdph.overlays.xdg-desktop-portal-hyprland
|
||||
];
|
||||
|
||||
udis86 = final: prev: {
|
||||
udis86-hyprland = final.callPackage ./udis86.nix {};
|
||||
};
|
||||
|
||||
# Patched version of wlroots for Hyprland.
|
||||
# It is under a new package name so as to not conflict with
|
||||
# the standard version in nixpkgs.
|
||||
wlroots-hyprland = final: prev: {
|
||||
wlroots-hyprland = final.callPackage ./wlroots.nix {
|
||||
version = "${mkDate (inputs.wlroots.lastModifiedDate or "19700101")}_${inputs.wlroots.shortRev or "dirty"}";
|
||||
src = inputs.wlroots;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@@ -1,61 +0,0 @@
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 1d2c7f9f..c5ef4e67 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -33,20 +33,7 @@ if cpp_compiler.check_header('execinfo.h')
|
||||
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
|
||||
endif
|
||||
|
||||
-wlroots = subproject('wlroots-hyprland', default_options: ['examples=false', 'renderers=gles2'])
|
||||
-have_xwlr = wlroots.get_variable('features').get('xwayland')
|
||||
-xcb_dep = dependency('xcb', required: get_option('xwayland'))
|
||||
-
|
||||
-cmake = import('cmake')
|
||||
-udis = cmake.subproject('udis86')
|
||||
-udis86 = udis.dependency('libudis86')
|
||||
-
|
||||
-if get_option('xwayland').enabled() and not have_xwlr
|
||||
- error('Cannot enable Xwayland in Hyprland: wlroots has been built without Xwayland support')
|
||||
-endif
|
||||
-have_xwayland = xcb_dep.found() and have_xwlr
|
||||
-
|
||||
-if not have_xwayland
|
||||
+if get_option('xwayland').disabled()
|
||||
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
||||
endif
|
||||
|
||||
@@ -69,8 +56,6 @@ if get_option('buildtype') == 'debug'
|
||||
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
|
||||
endif
|
||||
|
||||
-version_h = run_command('sh', '-c', 'scripts/generateVersion.sh')
|
||||
-
|
||||
globber = run_command('find', 'src', '-name', '*.h*', check: true)
|
||||
headers = globber.stdout().strip().split('\n')
|
||||
foreach file : headers
|
||||
diff --git a/src/meson.build b/src/meson.build
|
||||
index 45701f5f..3505cefe 100644
|
||||
--- a/src/meson.build
|
||||
+++ b/src/meson.build
|
||||
@@ -9,7 +9,7 @@ executable('Hyprland', src,
|
||||
server_protos,
|
||||
dependency('wayland-server'),
|
||||
dependency('wayland-client'),
|
||||
- wlroots.get_variable('wlroots'),
|
||||
+ dependency('wlroots'),
|
||||
dependency('cairo'),
|
||||
dependency('hyprcursor'),
|
||||
dependency('hyprlang', version: '>= 0.3.2'),
|
||||
@@ -16,12 +16,12 @@ executable('Hyprland', src,
|
||||
dependency('egl'),
|
||||
dependency('xkbcommon'),
|
||||
dependency('libinput'),
|
||||
- xcb_dep,
|
||||
+ dependency('xcb', required: get_option('xwayland')),
|
||||
backtrace_dep,
|
||||
systemd_dep,
|
||||
- udis86,
|
||||
+ dependency('udis86'),
|
||||
|
||||
dependency('pixman-1'),
|
||||
dependency('gl', 'opengl'),
|
12
nix/stdcxx.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index cfbd431f..73e8e0c2 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -64,6 +64,7 @@ endif()
|
||||
include_directories(. "src/" "subprojects/udis86/" "protocols/")
|
||||
set(CMAKE_CXX_STANDARD 26)
|
||||
add_compile_options(
|
||||
+ -std=c++26
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wno-unused-parameter
|
@@ -1,32 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
autoreconfHook,
|
||||
python3,
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
pname = "udis86";
|
||||
version = "unstable-2022-10-13";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "canihavesomecoffee";
|
||||
repo = "udis86";
|
||||
rev = "5336633af70f3917760a6d441ff02d93477b0c86";
|
||||
hash = "sha256-HifdUQPGsKQKQprByeIznvRLONdOXeolOsU5nkwIv3g=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [autoreconfHook python3];
|
||||
|
||||
configureFlags = ["--enable-shared"];
|
||||
|
||||
outputs = ["bin" "out" "dev" "lib"];
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://udis86.sourceforge.net";
|
||||
license = licenses.bsd2;
|
||||
mainProgram = "udcli";
|
||||
description = "Easy-to-use, minimalistic x86 disassembler library (libudis86)";
|
||||
platforms = platforms.all;
|
||||
};
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env -S nix shell nixpkgs#gawk nixpkgs#git nixpkgs#gnused nixpkgs#ripgrep -c bash
|
||||
|
||||
# get wlroots revision from submodule
|
||||
SUB_REV=$(git submodule status | rg wlroots | awk '{ print substr($1,2) }')
|
||||
# and from lockfile
|
||||
CRT_REV=$(rg rev flake.nix | awk '{ print substr($3, 2, 40) }')
|
||||
|
||||
if [ "$SUB_REV" != "$CRT_REV" ]; then
|
||||
echo "Updating wlroots..."
|
||||
# update wlroots to submodule revision
|
||||
sed -Ei "s/\w{40}/$SUB_REV/g" flake.nix
|
||||
nix flake lock
|
||||
|
||||
echo "wlroots: $CRT_REV -> $SUB_REV"
|
||||
else
|
||||
echo "wlroots is up to date!"
|
||||
fi
|
@@ -1,13 +0,0 @@
|
||||
{
|
||||
version,
|
||||
src,
|
||||
wlroots,
|
||||
enableXWayland ? true,
|
||||
}:
|
||||
wlroots.overrideAttrs (old: {
|
||||
inherit version src enableXWayland;
|
||||
|
||||
pname = "${old.pname}-hyprland";
|
||||
|
||||
patches = [ ]; # don't inherit old.patches
|
||||
})
|
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"version": "0.39.0"
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="idle">
|
||||
<copyright><![CDATA[
|
||||
Copyright (C) 2015 Martin Gräßlin
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
]]></copyright>
|
||||
<interface name="org_kde_kwin_idle" version="1">
|
||||
<description summary="User idle time manager">
|
||||
This interface allows to monitor user idle time on a given seat. The interface
|
||||
allows to register timers which trigger after no user activity was registered
|
||||
on the seat for a given interval. It notifies when user activity resumes.
|
||||
|
||||
This is useful for applications wanting to perform actions when the user is not
|
||||
interacting with the system, e.g. chat applications setting the user as away, power
|
||||
management features to dim screen, etc..
|
||||
</description>
|
||||
<request name="get_idle_timeout">
|
||||
<arg name="id" type="new_id" interface="org_kde_kwin_idle_timeout"/>
|
||||
<arg name="seat" type="object" interface="wl_seat"/>
|
||||
<arg name="timeout" type="uint" summary="The idle timeout in msec"/>
|
||||
</request>
|
||||
</interface>
|
||||
<interface name="org_kde_kwin_idle_timeout" version="1">
|
||||
<request name="release" type="destructor">
|
||||
<description summary="release the timeout object"/>
|
||||
</request>
|
||||
<request name="simulate_user_activity">
|
||||
<description summary="Simulates user activity for this timeout, behaves just like real user activity on the seat"/>
|
||||
</request>
|
||||
<event name="idle">
|
||||
<description summary="Triggered when there has not been any user activity in the requested idle time interval"/>
|
||||
</event>
|
||||
<event name="resumed">
|
||||
<description summary="Triggered on the first user activity after an idle event"/>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
494
protocols/input-method-unstable-v2.xml
Normal file
@@ -0,0 +1,494 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="input_method_unstable_v2">
|
||||
|
||||
<copyright>
|
||||
Copyright © 2008-2011 Kristian Høgsberg
|
||||
Copyright © 2010-2011 Intel Corporation
|
||||
Copyright © 2012-2013 Collabora, Ltd.
|
||||
Copyright © 2012, 2013 Intel Corporation
|
||||
Copyright © 2015, 2016 Jan Arne Petersen
|
||||
Copyright © 2017, 2018 Red Hat, Inc.
|
||||
Copyright © 2018 Purism SPC
|
||||
|
||||
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
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) 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
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<description summary="Protocol for creating input methods">
|
||||
This protocol allows applications to act as input methods for compositors.
|
||||
|
||||
An input method context is used to manage the state of the input method.
|
||||
|
||||
Text strings are UTF-8 encoded, their indices and lengths are in bytes.
|
||||
|
||||
This document adheres to the RFC 2119 when using words like "must",
|
||||
"should", "may", etc.
|
||||
|
||||
Warning! The protocol described in this file is experimental and
|
||||
backward incompatible changes may be made. Backward compatible changes
|
||||
may be added together with the corresponding interface version bump.
|
||||
Backward incompatible changes are done by bumping the version number in
|
||||
the protocol and interface names and resetting the interface version.
|
||||
Once the protocol is to be declared stable, the 'z' prefix and the
|
||||
version number in the protocol and interface names are removed and the
|
||||
interface version number is reset.
|
||||
</description>
|
||||
|
||||
<interface name="zwp_input_method_v2" version="1">
|
||||
<description summary="input method">
|
||||
An input method object allows for clients to compose text.
|
||||
|
||||
The objects connects the client to a text input in an application, and
|
||||
lets the client to serve as an input method for a seat.
|
||||
|
||||
The zwp_input_method_v2 object can occupy two distinct states: active and
|
||||
inactive. In the active state, the object is associated to and
|
||||
communicates with a text input. In the inactive state, there is no
|
||||
associated text input, and the only communication is with the compositor.
|
||||
Initially, the input method is in the inactive state.
|
||||
|
||||
Requests issued in the inactive state must be accepted by the compositor.
|
||||
Because of the serial mechanism, and the state reset on activate event,
|
||||
they will not have any effect on the state of the next text input.
|
||||
|
||||
There must be no more than one input method object per seat.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="role" value="0" summary="wl_surface has another role"/>
|
||||
</enum>
|
||||
|
||||
<event name="activate">
|
||||
<description summary="input method has been requested">
|
||||
Notification that a text input focused on this seat requested the input
|
||||
method to be activated.
|
||||
|
||||
This event serves the purpose of providing the compositor with an
|
||||
active input method.
|
||||
|
||||
This event resets all state associated with previous enable, disable,
|
||||
surrounding_text, text_change_cause, and content_type events, as well
|
||||
as the state associated with set_preedit_string, commit_string, and
|
||||
delete_surrounding_text requests. In addition, it marks the
|
||||
zwp_input_method_v2 object as active, and makes any existing
|
||||
zwp_input_popup_surface_v2 objects visible.
|
||||
|
||||
The surrounding_text, and content_type events must follow before the
|
||||
next done event if the text input supports the respective
|
||||
functionality.
|
||||
|
||||
State set with this event is double-buffered. It will get applied on
|
||||
the next zwp_input_method_v2.done event, and stay valid until changed.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="deactivate">
|
||||
<description summary="deactivate event">
|
||||
Notification that no focused text input currently needs an active
|
||||
input method on this seat.
|
||||
|
||||
This event marks the zwp_input_method_v2 object as inactive. The
|
||||
compositor must make all existing zwp_input_popup_surface_v2 objects
|
||||
invisible until the next activate event.
|
||||
|
||||
State set with this event is double-buffered. It will get applied on
|
||||
the next zwp_input_method_v2.done event, and stay valid until changed.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="surrounding_text">
|
||||
<description summary="surrounding text event">
|
||||
Updates the surrounding plain text around the cursor, excluding the
|
||||
preedit text.
|
||||
|
||||
If any preedit text is present, it is replaced with the cursor for the
|
||||
purpose of this event.
|
||||
|
||||
The argument text is a buffer containing the preedit string, and must
|
||||
include the cursor position, and the complete selection. It should
|
||||
contain additional characters before and after these. There is a
|
||||
maximum length of wayland messages, so text can not be longer than 4000
|
||||
bytes.
|
||||
|
||||
cursor is the byte offset of the cursor within the text buffer.
|
||||
|
||||
anchor is the byte offset of the selection anchor within the text
|
||||
buffer. If there is no selected text, anchor must be the same as
|
||||
cursor.
|
||||
|
||||
If this event does not arrive before the first done event, the input
|
||||
method may assume that the text input does not support this
|
||||
functionality and ignore following surrounding_text events.
|
||||
|
||||
Values set with this event are double-buffered. They will get applied
|
||||
and set to initial values on the next zwp_input_method_v2.done
|
||||
event.
|
||||
|
||||
The initial state for affected fields is empty, meaning that the text
|
||||
input does not support sending surrounding text. If the empty values
|
||||
get applied, subsequent attempts to change them may have no effect.
|
||||
</description>
|
||||
<arg name="text" type="string"/>
|
||||
<arg name="cursor" type="uint"/>
|
||||
<arg name="anchor" type="uint"/>
|
||||
</event>
|
||||
|
||||
<event name="text_change_cause">
|
||||
<description summary="indicates the cause of surrounding text change">
|
||||
Tells the input method why the text surrounding the cursor changed.
|
||||
|
||||
Whenever the client detects an external change in text, cursor, or
|
||||
anchor position, it must issue this request to the compositor. This
|
||||
request is intended to give the input method a chance to update the
|
||||
preedit text in an appropriate way, e.g. by removing it when the user
|
||||
starts typing with a keyboard.
|
||||
|
||||
cause describes the source of the change.
|
||||
|
||||
The value set with this event is double-buffered. It will get applied
|
||||
and set to its initial value on the next zwp_input_method_v2.done
|
||||
event.
|
||||
|
||||
The initial value of cause is input_method.
|
||||
</description>
|
||||
<arg name="cause" type="uint" enum="zwp_text_input_v3.change_cause"/>
|
||||
</event>
|
||||
|
||||
<event name="content_type">
|
||||
<description summary="content purpose and hint">
|
||||
Indicates the content type and hint for the current
|
||||
zwp_input_method_v2 instance.
|
||||
|
||||
Values set with this event are double-buffered. They will get applied
|
||||
on the next zwp_input_method_v2.done event.
|
||||
|
||||
The initial value for hint is none, and the initial value for purpose
|
||||
is normal.
|
||||
</description>
|
||||
<arg name="hint" type="uint" enum="zwp_text_input_v3.content_hint"/>
|
||||
<arg name="purpose" type="uint" enum="zwp_text_input_v3.content_purpose"/>
|
||||
</event>
|
||||
|
||||
<event name="done">
|
||||
<description summary="apply state">
|
||||
Atomically applies state changes recently sent to the client.
|
||||
|
||||
The done event establishes and updates the state of the client, and
|
||||
must be issued after any changes to apply them.
|
||||
|
||||
Text input state (content purpose, content hint, surrounding text, and
|
||||
change cause) is conceptually double-buffered within an input method
|
||||
context.
|
||||
|
||||
Events modify the pending state, as opposed to the current state in use
|
||||
by the input method. A done event atomically applies all pending state,
|
||||
replacing the current state. After done, the new pending state is as
|
||||
documented for each related request.
|
||||
|
||||
Events must be applied in the order of arrival.
|
||||
|
||||
Neither current nor pending state are modified unless noted otherwise.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="commit_string">
|
||||
<description summary="commit string">
|
||||
Send the commit string text for insertion to the application.
|
||||
|
||||
Inserts a string at current cursor position (see commit event
|
||||
sequence). The string to commit could be either just a single character
|
||||
after a key press or the result of some composing.
|
||||
|
||||
The argument text is a buffer containing the string to insert. There is
|
||||
a maximum length of wayland messages, so text can not be longer than
|
||||
4000 bytes.
|
||||
|
||||
Values set with this event are double-buffered. They must be applied
|
||||
and reset to initial on the next zwp_text_input_v3.commit request.
|
||||
|
||||
The initial value of text is an empty string.
|
||||
</description>
|
||||
<arg name="text" type="string"/>
|
||||
</request>
|
||||
|
||||
<request name="set_preedit_string">
|
||||
<description summary="pre-edit string">
|
||||
Send the pre-edit string text to the application text input.
|
||||
|
||||
Place a new composing text (pre-edit) at the current cursor position.
|
||||
Any previously set composing text must be removed. Any previously
|
||||
existing selected text must be removed. The cursor is moved to a new
|
||||
position within the preedit string.
|
||||
|
||||
The argument text is a buffer containing the preedit string. There is
|
||||
a maximum length of wayland messages, so text can not be longer than
|
||||
4000 bytes.
|
||||
|
||||
The arguments cursor_begin and cursor_end are counted in bytes relative
|
||||
to the beginning of the submitted string buffer. Cursor should be
|
||||
hidden by the text input when both are equal to -1.
|
||||
|
||||
cursor_begin indicates the beginning of the cursor. cursor_end
|
||||
indicates the end of the cursor. It may be equal or different than
|
||||
cursor_begin.
|
||||
|
||||
Values set with this event are double-buffered. They must be applied on
|
||||
the next zwp_input_method_v2.commit event.
|
||||
|
||||
The initial value of text is an empty string. The initial value of
|
||||
cursor_begin, and cursor_end are both 0.
|
||||
</description>
|
||||
<arg name="text" type="string"/>
|
||||
<arg name="cursor_begin" type="int"/>
|
||||
<arg name="cursor_end" type="int"/>
|
||||
</request>
|
||||
|
||||
<request name="delete_surrounding_text">
|
||||
<description summary="delete text">
|
||||
Remove the surrounding text.
|
||||
|
||||
before_length and after_length are the number of bytes before and after
|
||||
the current cursor index (excluding the preedit text) to delete.
|
||||
|
||||
If any preedit text is present, it is replaced with the cursor for the
|
||||
purpose of this event. In effect before_length is counted from the
|
||||
beginning of preedit text, and after_length from its end (see commit
|
||||
event sequence).
|
||||
|
||||
Values set with this event are double-buffered. They must be applied
|
||||
and reset to initial on the next zwp_input_method_v2.commit request.
|
||||
|
||||
The initial values of both before_length and after_length are 0.
|
||||
</description>
|
||||
<arg name="before_length" type="uint"/>
|
||||
<arg name="after_length" type="uint"/>
|
||||
</request>
|
||||
|
||||
<request name="commit">
|
||||
<description summary="apply state">
|
||||
Apply state changes from commit_string, set_preedit_string and
|
||||
delete_surrounding_text requests.
|
||||
|
||||
The state relating to these events is double-buffered, and each one
|
||||
modifies the pending state. This request replaces the current state
|
||||
with the pending state.
|
||||
|
||||
The connected text input is expected to proceed by evaluating the
|
||||
changes in the following order:
|
||||
|
||||
1. Replace existing preedit string with the cursor.
|
||||
2. Delete requested surrounding text.
|
||||
3. Insert commit string with the cursor at its end.
|
||||
4. Calculate surrounding text to send.
|
||||
5. Insert new preedit text in cursor position.
|
||||
6. Place cursor inside preedit text.
|
||||
|
||||
The serial number reflects the last state of the zwp_input_method_v2
|
||||
object known to the client. The value of the serial argument must be
|
||||
equal to the number of done events already issued by that object. When
|
||||
the compositor receives a commit request with a serial different than
|
||||
the number of past done events, it must proceed as normal, except it
|
||||
should not change the current state of the zwp_input_method_v2 object.
|
||||
</description>
|
||||
<arg name="serial" type="uint"/>
|
||||
</request>
|
||||
|
||||
<request name="get_input_popup_surface">
|
||||
<description summary="create popup surface">
|
||||
Creates a new zwp_input_popup_surface_v2 object wrapping a given
|
||||
surface.
|
||||
|
||||
The surface gets assigned the "input_popup" role. If the surface
|
||||
already has an assigned role, the compositor must issue a protocol
|
||||
error.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwp_input_popup_surface_v2"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
|
||||
<request name="grab_keyboard">
|
||||
<description summary="grab hardware keyboard">
|
||||
Allow an input method to receive hardware keyboard input and process
|
||||
key events to generate text events (with pre-edit) over the wire. This
|
||||
allows input methods which compose multiple key events for inputting
|
||||
text like it is done for CJK languages.
|
||||
|
||||
The compositor should send all keyboard events on the seat to the grab
|
||||
holder via the returned wl_keyboard object. Nevertheless, the
|
||||
compositor may decide not to forward any particular event. The
|
||||
compositor must not further process any event after it has been
|
||||
forwarded to the grab holder.
|
||||
|
||||
Releasing the resulting wl_keyboard object releases the grab.
|
||||
</description>
|
||||
<arg name="keyboard" type="new_id"
|
||||
interface="zwp_input_method_keyboard_grab_v2"/>
|
||||
</request>
|
||||
|
||||
<event name="unavailable">
|
||||
<description summary="input method unavailable">
|
||||
The input method ceased to be available.
|
||||
|
||||
The compositor must issue this event as the only event on the object if
|
||||
there was another input_method object associated with the same seat at
|
||||
the time of its creation.
|
||||
|
||||
The compositor must issue this request when the object is no longer
|
||||
usable, e.g. due to seat removal.
|
||||
|
||||
The input method context becomes inert and should be destroyed after
|
||||
deactivation is handled. Any further requests and events except for the
|
||||
destroy request must be ignored.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the text input">
|
||||
Destroys the zwp_text_input_v2 object and any associated child
|
||||
objects, i.e. zwp_input_popup_surface_v2 and
|
||||
zwp_input_method_keyboard_grab_v2.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zwp_input_popup_surface_v2" version="1">
|
||||
<description summary="popup surface">
|
||||
This interface marks a surface as a popup for interacting with an input
|
||||
method.
|
||||
|
||||
The compositor should place it near the active text input area. It must
|
||||
be visible if and only if the input method is in the active state.
|
||||
|
||||
The client must not destroy the underlying wl_surface while the
|
||||
zwp_input_popup_surface_v2 object exists.
|
||||
</description>
|
||||
|
||||
<event name="text_input_rectangle">
|
||||
<description summary="set text input area position">
|
||||
Notify about the position of the area of the text input expressed as a
|
||||
rectangle in surface local coordinates.
|
||||
|
||||
This is a hint to the input method telling it the relative position of
|
||||
the text being entered.
|
||||
</description>
|
||||
<arg name="x" type="int"/>
|
||||
<arg name="y" type="int"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
</event>
|
||||
|
||||
<request name="destroy" type="destructor"/>
|
||||
</interface>
|
||||
|
||||
<interface name="zwp_input_method_keyboard_grab_v2" version="1">
|
||||
<!-- Closely follows wl_keyboard version 6 -->
|
||||
<description summary="keyboard grab">
|
||||
The zwp_input_method_keyboard_grab_v2 interface represents an exclusive
|
||||
grab of the wl_keyboard interface associated with the seat.
|
||||
</description>
|
||||
|
||||
<event name="keymap">
|
||||
<description summary="keyboard mapping">
|
||||
This event provides a file descriptor to the client which can be
|
||||
memory-mapped to provide a keyboard mapping description.
|
||||
</description>
|
||||
<arg name="format" type="uint" enum="wl_keyboard.keymap_format"
|
||||
summary="keymap format"/>
|
||||
<arg name="fd" type="fd" summary="keymap file descriptor"/>
|
||||
<arg name="size" type="uint" summary="keymap size, in bytes"/>
|
||||
</event>
|
||||
|
||||
<event name="key">
|
||||
<description summary="key event">
|
||||
A key was pressed or released.
|
||||
The time argument is a timestamp with millisecond granularity, with an
|
||||
undefined base.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial number of the key event"/>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="key" type="uint" summary="key that produced the event"/>
|
||||
<arg name="state" type="uint" enum="wl_keyboard.key_state"
|
||||
summary="physical state of the key"/>
|
||||
</event>
|
||||
|
||||
<event name="modifiers">
|
||||
<description summary="modifier and group state">
|
||||
Notifies clients that the modifier and/or group state has changed, and
|
||||
it should update its local state.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial number of the modifiers event"/>
|
||||
<arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
|
||||
<arg name="mods_latched" type="uint" summary="latched modifiers"/>
|
||||
<arg name="mods_locked" type="uint" summary="locked modifiers"/>
|
||||
<arg name="group" type="uint" summary="keyboard layout"/>
|
||||
</event>
|
||||
|
||||
<request name="release" type="destructor">
|
||||
<description summary="release the grab object"/>
|
||||
</request>
|
||||
|
||||
<event name="repeat_info">
|
||||
<description summary="repeat rate and delay">
|
||||
Informs the client about the keyboard's repeat rate and delay.
|
||||
|
||||
This event is sent as soon as the zwp_input_method_keyboard_grab_v2
|
||||
object has been created, and is guaranteed to be received by the
|
||||
client before any key press event.
|
||||
|
||||
Negative values for either rate or delay are illegal. A rate of zero
|
||||
will disable any repeating (regardless of the value of delay).
|
||||
|
||||
This event can be sent later on as well with a new value if necessary,
|
||||
so clients should continue listening for the event past the creation
|
||||
of zwp_input_method_keyboard_grab_v2.
|
||||
</description>
|
||||
<arg name="rate" type="int"
|
||||
summary="the rate of repeating keys in characters per second"/>
|
||||
<arg name="delay" type="int"
|
||||
summary="delay in milliseconds since key down until repeating starts"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="zwp_input_method_manager_v2" version="1">
|
||||
<description summary="input method manager">
|
||||
The input method manager allows the client to become the input method on
|
||||
a chosen seat.
|
||||
|
||||
No more than one input method must be associated with any seat at any
|
||||
given time.
|
||||
</description>
|
||||
|
||||
<request name="get_input_method">
|
||||
<description summary="request an input method object">
|
||||
Request a new input zwp_input_method_v2 object associated with a given
|
||||
seat.
|
||||
</description>
|
||||
<arg name="seat" type="object" interface="wl_seat"/>
|
||||
<arg name="input_method" type="new_id" interface="zwp_input_method_v2"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the input method manager">
|
||||
Destroys the zwp_input_method_manager_v2 object.
|
||||
|
||||
The zwp_input_method_v2 objects originating from it remain valid.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
85
protocols/kde-server-decoration.xml
Normal file
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="server_decoration">
|
||||
<copyright><![CDATA[
|
||||
SPDX-FileCopyrightText: 2015 Martin Gräßlin
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
]]></copyright>
|
||||
<interface name="org_kde_kwin_server_decoration_manager" version="1">
|
||||
<description summary="Server side window decoration manager">
|
||||
This interface allows to coordinate whether the server should create
|
||||
a server-side window decoration around a wl_surface representing a
|
||||
shell surface (wl_shell_surface or similar). By announcing support
|
||||
for this interface the server indicates that it supports server
|
||||
side decorations.
|
||||
|
||||
Use in conjunction with zxdg_decoration_manager_v1 is undefined.
|
||||
</description>
|
||||
<request name="create">
|
||||
<description summary="Create a server-side decoration object for a given surface">
|
||||
When a client creates a server-side decoration object it indicates
|
||||
that it supports the protocol. The client is supposed to tell the
|
||||
server whether it wants server-side decorations or will provide
|
||||
client-side decorations.
|
||||
|
||||
If the client does not create a server-side decoration object for
|
||||
a surface the server interprets this as lack of support for this
|
||||
protocol and considers it as client-side decorated. Nevertheless a
|
||||
client-side decorated surface should use this protocol to indicate
|
||||
to the server that it does not want a server-side deco.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="org_kde_kwin_server_decoration"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
<enum name="mode">
|
||||
<description summary="Possible values to use in request_mode and the event mode."/>
|
||||
<entry name="None" value="0" summary="Undecorated: The surface is not decorated at all, neither server nor client-side. An example is a popup surface which should not be decorated."/>
|
||||
<entry name="Client" value="1" summary="Client-side decoration: The decoration is part of the surface and the client."/>
|
||||
<entry name="Server" value="2" summary="Server-side decoration: The server embeds the surface into a decoration frame."/>
|
||||
</enum>
|
||||
<event name="default_mode">
|
||||
<description summary="The default mode used on the server">
|
||||
This event is emitted directly after binding the interface. It contains
|
||||
the default mode for the decoration. When a new server decoration object
|
||||
is created this new object will be in the default mode until the first
|
||||
request_mode is requested.
|
||||
|
||||
The server may change the default mode at any time.
|
||||
</description>
|
||||
<arg name="mode" type="uint" summary="The default decoration mode applied to newly created server decorations."/>
|
||||
</event>
|
||||
</interface>
|
||||
<interface name="org_kde_kwin_server_decoration" version="1">
|
||||
<request name="release" type="destructor">
|
||||
<description summary="release the server decoration object"/>
|
||||
</request>
|
||||
<enum name="mode">
|
||||
<description summary="Possible values to use in request_mode and the event mode."/>
|
||||
<entry name="None" value="0" summary="Undecorated: The surface is not decorated at all, neither server nor client-side. An example is a popup surface which should not be decorated."/>
|
||||
<entry name="Client" value="1" summary="Client-side decoration: The decoration is part of the surface and the client."/>
|
||||
<entry name="Server" value="2" summary="Server-side decoration: The server embeds the surface into a decoration frame."/>
|
||||
</enum>
|
||||
<request name="request_mode">
|
||||
<description summary="The decoration mode the surface wants to use."/>
|
||||
<arg name="mode" type="uint" summary="The mode this surface wants to use."/>
|
||||
</request>
|
||||
<event name="mode">
|
||||
<description summary="The new decoration mode applied by the server">
|
||||
This event is emitted directly after the decoration is created and
|
||||
represents the base decoration policy by the server. E.g. a server
|
||||
which wants all surfaces to be client-side decorated will send Client,
|
||||
a server which wants server-side decoration will send Server.
|
||||
|
||||
The client can request a different mode through the decoration request.
|
||||
The server will acknowledge this by another event with the same mode. So
|
||||
even if a server prefers server-side decoration it's possible to force a
|
||||
client-side decoration.
|
||||
|
||||
The server may emit this event at any time. In this case the client can
|
||||
again request a different mode. It's the responsibility of the server to
|
||||
prevent a feedback loop.
|
||||
</description>
|
||||
<arg name="mode" type="uint" summary="The decoration mode applied to the surface by the server."/>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
@@ -12,59 +12,98 @@ hyprland_protos = dependency('hyprland-protocols',
|
||||
wl_protocol_dir = wayland_protos.get_variable('pkgdatadir')
|
||||
hl_protocol_dir = hyprland_protos.get_variable('pkgdatadir')
|
||||
|
||||
wayland_scanner_dep = dependency('wayland-scanner', native: true)
|
||||
wayland_scanner = find_program(
|
||||
wayland_scanner_dep.get_variable('wayland_scanner'),
|
||||
hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.8', native: true)
|
||||
hyprwayland_scanner = find_program(
|
||||
hyprwayland_scanner_dep.get_variable('hyprwayland_scanner'),
|
||||
native: true,
|
||||
)
|
||||
|
||||
protocols = [
|
||||
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
|
||||
[wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'],
|
||||
new_protocols = [
|
||||
['wlr-gamma-control-unstable-v1.xml'],
|
||||
['wlr-foreign-toplevel-management-unstable-v1.xml'],
|
||||
['wlr-layer-shell-unstable-v1.xml'],
|
||||
['wlr-output-power-management-unstable-v1.xml'],
|
||||
['input-method-unstable-v2.xml'],
|
||||
['virtual-keyboard-unstable-v1.xml'],
|
||||
['wlr-virtual-pointer-unstable-v1.xml'],
|
||||
['wlr-output-management-unstable-v1.xml'],
|
||||
['kde-server-decoration.xml'],
|
||||
['wlr-layer-shell-unstable-v1.xml'],
|
||||
['wayland-drm.xml'],
|
||||
['wlr-data-control-unstable-v1.xml'],
|
||||
['wlr-screencopy-unstable-v1.xml'],
|
||||
['pointer-constraints-unstable-v1.xml'],
|
||||
['tablet-unstable-v2.xml'],
|
||||
['idle.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml'],
|
||||
[hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml']
|
||||
[hl_protocol_dir, 'protocols/hyprland-focus-grab-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/relative-pointer/relative-pointer-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/alpha-modifier/alpha-modifier-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v3.xml'],
|
||||
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/ext-idle-notify/ext-idle-notify-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/ext-session-lock/ext-session-lock-v1.xml'],
|
||||
[wl_protocol_dir, 'stable/tablet/tablet-v2.xml'],
|
||||
[wl_protocol_dir, 'stable/presentation-time/presentation-time.xml'],
|
||||
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
|
||||
[wl_protocol_dir, 'unstable/primary-selection/primary-selection-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/xwayland-shell/xwayland-shell-v1.xml'],
|
||||
[wl_protocol_dir, 'stable/viewporter/viewporter.xml'],
|
||||
[wl_protocol_dir, 'stable/linux-dmabuf/linux-dmabuf-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/drm-lease/drm-lease-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/xdg-dialog/xdg-dialog-v1.xml'],
|
||||
]
|
||||
|
||||
wl_protos_src = []
|
||||
wl_protos_headers = []
|
||||
foreach p : protocols
|
||||
|
||||
new_wl_protos = []
|
||||
foreach p : new_protocols
|
||||
xml = join_paths(p)
|
||||
wl_protos_src += custom_target(
|
||||
xml.underscorify() + '_server_c',
|
||||
input: xml,
|
||||
output: '@BASENAME@-protocol.c',
|
||||
command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'],
|
||||
)
|
||||
wl_protos_headers += custom_target(
|
||||
xml.underscorify() + '_server_h',
|
||||
new_wl_protos += custom_target(
|
||||
xml.underscorify(),
|
||||
input: xml,
|
||||
install: true,
|
||||
install_dir: join_paths(get_option('includedir'), 'hyprland/protocols'),
|
||||
output: '@BASENAME@-protocol.h',
|
||||
command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'],
|
||||
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
|
||||
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
|
||||
command: [hyprwayland_scanner, '@INPUT@', '@OUTDIR@'],
|
||||
)
|
||||
endforeach
|
||||
|
||||
wayland_server = dependency('wayland-server', version: '>=1.20.0')
|
||||
wayland_server_dep = dependency('wayland-server', version: '>=1.20.0')
|
||||
wayland_server_dir = wayland_server_dep.get_variable('pkgdatadir')
|
||||
|
||||
wl_server_protos = [
|
||||
wayland_server_dir / 'wayland.xml'
|
||||
]
|
||||
wl_server_protos_gen = []
|
||||
foreach p : wl_server_protos
|
||||
wl_server_protos_gen += custom_target(
|
||||
p.underscorify(),
|
||||
input: p,
|
||||
install: true,
|
||||
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
|
||||
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
|
||||
command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'],
|
||||
)
|
||||
endforeach
|
||||
|
||||
lib_server_protos = static_library(
|
||||
'server_protos',
|
||||
wl_protos_src + wl_protos_headers,
|
||||
dependencies: wayland_server.partial_dependency(compile_args: true),
|
||||
wl_protos_src + wl_protos_headers + new_wl_protos + wl_server_protos_gen,
|
||||
dependencies: wayland_server_dep.partial_dependency(compile_args: true),
|
||||
)
|
||||
|
||||
server_protos = declare_dependency(
|
||||
link_with: lib_server_protos,
|
||||
sources: wl_protos_headers,
|
||||
sources: wl_protos_headers + new_wl_protos,
|
||||
)
|
||||
|
@@ -1,339 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="pointer_constraints_unstable_v1">
|
||||
|
||||
<copyright>
|
||||
Copyright © 2014 Jonas Ådahl
|
||||
Copyright © 2015 Red Hat Inc.
|
||||
|
||||
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
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) 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
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<description summary="protocol for constraining pointer motions">
|
||||
This protocol specifies a set of interfaces used for adding constraints to
|
||||
the motion of a pointer. Possible constraints include confining pointer
|
||||
motions to a given region, or locking it to its current position.
|
||||
|
||||
In order to constrain the pointer, a client must first bind the global
|
||||
interface "wp_pointer_constraints" which, if a compositor supports pointer
|
||||
constraints, is exposed by the registry. Using the bound global object, the
|
||||
client uses the request that corresponds to the type of constraint it wants
|
||||
to make. See wp_pointer_constraints for more details.
|
||||
|
||||
Warning! The protocol described in this file is experimental and backward
|
||||
incompatible changes may be made. Backward compatible changes may be added
|
||||
together with the corresponding interface version bump. Backward
|
||||
incompatible changes are done by bumping the version number in the protocol
|
||||
and interface names and resetting the interface version. Once the protocol
|
||||
is to be declared stable, the 'z' prefix and the version number in the
|
||||
protocol and interface names are removed and the interface version number is
|
||||
reset.
|
||||
</description>
|
||||
|
||||
<interface name="zwp_pointer_constraints_v1" version="1">
|
||||
<description summary="constrain the movement of a pointer">
|
||||
The global interface exposing pointer constraining functionality. It
|
||||
exposes two requests: lock_pointer for locking the pointer to its
|
||||
position, and confine_pointer for locking the pointer to a region.
|
||||
|
||||
The lock_pointer and confine_pointer requests create the objects
|
||||
wp_locked_pointer and wp_confined_pointer respectively, and the client can
|
||||
use these objects to interact with the lock.
|
||||
|
||||
For any surface, only one lock or confinement may be active across all
|
||||
wl_pointer objects of the same seat. If a lock or confinement is requested
|
||||
when another lock or confinement is active or requested on the same surface
|
||||
and with any of the wl_pointer objects of the same seat, an
|
||||
'already_constrained' error will be raised.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<description summary="wp_pointer_constraints error values">
|
||||
These errors can be emitted in response to wp_pointer_constraints
|
||||
requests.
|
||||
</description>
|
||||
<entry name="already_constrained" value="1"
|
||||
summary="pointer constraint already requested on that surface"/>
|
||||
</enum>
|
||||
|
||||
<enum name="lifetime">
|
||||
<description summary="constraint lifetime">
|
||||
These values represent different lifetime semantics. They are passed
|
||||
as arguments to the factory requests to specify how the constraint
|
||||
lifetimes should be managed.
|
||||
</description>
|
||||
<entry name="oneshot" value="1">
|
||||
<description summary="the pointer constraint is defunct once deactivated">
|
||||
A oneshot pointer constraint will never reactivate once it has been
|
||||
deactivated. See the corresponding deactivation event
|
||||
(wp_locked_pointer.unlocked and wp_confined_pointer.unconfined) for
|
||||
details.
|
||||
</description>
|
||||
</entry>
|
||||
<entry name="persistent" value="2">
|
||||
<description summary="the pointer constraint may reactivate">
|
||||
A persistent pointer constraint may again reactivate once it has
|
||||
been deactivated. See the corresponding deactivation event
|
||||
(wp_locked_pointer.unlocked and wp_confined_pointer.unconfined) for
|
||||
details.
|
||||
</description>
|
||||
</entry>
|
||||
</enum>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the pointer constraints manager object">
|
||||
Used by the client to notify the server that it will no longer use this
|
||||
pointer constraints object.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="lock_pointer">
|
||||
<description summary="lock pointer to a position">
|
||||
The lock_pointer request lets the client request to disable movements of
|
||||
the virtual pointer (i.e. the cursor), effectively locking the pointer
|
||||
to a position. This request may not take effect immediately; in the
|
||||
future, when the compositor deems implementation-specific constraints
|
||||
are satisfied, the pointer lock will be activated and the compositor
|
||||
sends a locked event.
|
||||
|
||||
The protocol provides no guarantee that the constraints are ever
|
||||
satisfied, and does not require the compositor to send an error if the
|
||||
constraints cannot ever be satisfied. It is thus possible to request a
|
||||
lock that will never activate.
|
||||
|
||||
There may not be another pointer constraint of any kind requested or
|
||||
active on the surface for any of the wl_pointer objects of the seat of
|
||||
the passed pointer when requesting a lock. If there is, an error will be
|
||||
raised. See general pointer lock documentation for more details.
|
||||
|
||||
The intersection of the region passed with this request and the input
|
||||
region of the surface is used to determine where the pointer must be
|
||||
in order for the lock to activate. It is up to the compositor whether to
|
||||
warp the pointer or require some kind of user interaction for the lock
|
||||
to activate. If the region is null the surface input region is used.
|
||||
|
||||
A surface may receive pointer focus without the lock being activated.
|
||||
|
||||
The request creates a new object wp_locked_pointer which is used to
|
||||
interact with the lock as well as receive updates about its state. See
|
||||
the the description of wp_locked_pointer for further information.
|
||||
|
||||
Note that while a pointer is locked, the wl_pointer objects of the
|
||||
corresponding seat will not emit any wl_pointer.motion events, but
|
||||
relative motion events will still be emitted via wp_relative_pointer
|
||||
objects of the same seat. wl_pointer.axis and wl_pointer.button events
|
||||
are unaffected.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwp_locked_pointer_v1"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"
|
||||
summary="surface to lock pointer to"/>
|
||||
<arg name="pointer" type="object" interface="wl_pointer"
|
||||
summary="the pointer that should be locked"/>
|
||||
<arg name="region" type="object" interface="wl_region" allow-null="true"
|
||||
summary="region of surface"/>
|
||||
<arg name="lifetime" type="uint" enum="lifetime" summary="lock lifetime"/>
|
||||
</request>
|
||||
|
||||
<request name="confine_pointer">
|
||||
<description summary="confine pointer to a region">
|
||||
The confine_pointer request lets the client request to confine the
|
||||
pointer cursor to a given region. This request may not take effect
|
||||
immediately; in the future, when the compositor deems implementation-
|
||||
specific constraints are satisfied, the pointer confinement will be
|
||||
activated and the compositor sends a confined event.
|
||||
|
||||
The intersection of the region passed with this request and the input
|
||||
region of the surface is used to determine where the pointer must be
|
||||
in order for the confinement to activate. It is up to the compositor
|
||||
whether to warp the pointer or require some kind of user interaction for
|
||||
the confinement to activate. If the region is null the surface input
|
||||
region is used.
|
||||
|
||||
The request will create a new object wp_confined_pointer which is used
|
||||
to interact with the confinement as well as receive updates about its
|
||||
state. See the the description of wp_confined_pointer for further
|
||||
information.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwp_confined_pointer_v1"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"
|
||||
summary="surface to lock pointer to"/>
|
||||
<arg name="pointer" type="object" interface="wl_pointer"
|
||||
summary="the pointer that should be confined"/>
|
||||
<arg name="region" type="object" interface="wl_region" allow-null="true"
|
||||
summary="region of surface"/>
|
||||
<arg name="lifetime" type="uint" enum="lifetime" summary="confinement lifetime"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zwp_locked_pointer_v1" version="1">
|
||||
<description summary="receive relative pointer motion events">
|
||||
The wp_locked_pointer interface represents a locked pointer state.
|
||||
|
||||
While the lock of this object is active, the wl_pointer objects of the
|
||||
associated seat will not emit any wl_pointer.motion events.
|
||||
|
||||
This object will send the event 'locked' when the lock is activated.
|
||||
Whenever the lock is activated, it is guaranteed that the locked surface
|
||||
will already have received pointer focus and that the pointer will be
|
||||
within the region passed to the request creating this object.
|
||||
|
||||
To unlock the pointer, send the destroy request. This will also destroy
|
||||
the wp_locked_pointer object.
|
||||
|
||||
If the compositor decides to unlock the pointer the unlocked event is
|
||||
sent. See wp_locked_pointer.unlock for details.
|
||||
|
||||
When unlocking, the compositor may warp the cursor position to the set
|
||||
cursor position hint. If it does, it will not result in any relative
|
||||
motion events emitted via wp_relative_pointer.
|
||||
|
||||
If the surface the lock was requested on is destroyed and the lock is not
|
||||
yet activated, the wp_locked_pointer object is now defunct and must be
|
||||
destroyed.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the locked pointer object">
|
||||
Destroy the locked pointer object. If applicable, the compositor will
|
||||
unlock the pointer.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_cursor_position_hint">
|
||||
<description summary="set the pointer cursor position hint">
|
||||
Set the cursor position hint relative to the top left corner of the
|
||||
surface.
|
||||
|
||||
If the client is drawing its own cursor, it should update the position
|
||||
hint to the position of its own cursor. A compositor may use this
|
||||
information to warp the pointer upon unlock in order to avoid pointer
|
||||
jumps.
|
||||
|
||||
The cursor position hint is double buffered. The new hint will only take
|
||||
effect when the associated surface gets it pending state applied. See
|
||||
wl_surface.commit for details.
|
||||
</description>
|
||||
<arg name="surface_x" type="fixed"
|
||||
summary="surface-local x coordinate"/>
|
||||
<arg name="surface_y" type="fixed"
|
||||
summary="surface-local y coordinate"/>
|
||||
</request>
|
||||
|
||||
<request name="set_region">
|
||||
<description summary="set a new lock region">
|
||||
Set a new region used to lock the pointer.
|
||||
|
||||
The new lock region is double-buffered. The new lock region will
|
||||
only take effect when the associated surface gets its pending state
|
||||
applied. See wl_surface.commit for details.
|
||||
|
||||
For details about the lock region, see wp_locked_pointer.
|
||||
</description>
|
||||
<arg name="region" type="object" interface="wl_region" allow-null="true"
|
||||
summary="region of surface"/>
|
||||
</request>
|
||||
|
||||
<event name="locked">
|
||||
<description summary="lock activation event">
|
||||
Notification that the pointer lock of the seat's pointer is activated.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="unlocked">
|
||||
<description summary="lock deactivation event">
|
||||
Notification that the pointer lock of the seat's pointer is no longer
|
||||
active. If this is a oneshot pointer lock (see
|
||||
wp_pointer_constraints.lifetime) this object is now defunct and should
|
||||
be destroyed. If this is a persistent pointer lock (see
|
||||
wp_pointer_constraints.lifetime) this pointer lock may again
|
||||
reactivate in the future.
|
||||
</description>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="zwp_confined_pointer_v1" version="1">
|
||||
<description summary="confined pointer object">
|
||||
The wp_confined_pointer interface represents a confined pointer state.
|
||||
|
||||
This object will send the event 'confined' when the confinement is
|
||||
activated. Whenever the confinement is activated, it is guaranteed that
|
||||
the surface the pointer is confined to will already have received pointer
|
||||
focus and that the pointer will be within the region passed to the request
|
||||
creating this object. It is up to the compositor to decide whether this
|
||||
requires some user interaction and if the pointer will warp to within the
|
||||
passed region if outside.
|
||||
|
||||
To unconfine the pointer, send the destroy request. This will also destroy
|
||||
the wp_confined_pointer object.
|
||||
|
||||
If the compositor decides to unconfine the pointer the unconfined event is
|
||||
sent. The wp_confined_pointer object is at this point defunct and should
|
||||
be destroyed.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the confined pointer object">
|
||||
Destroy the confined pointer object. If applicable, the compositor will
|
||||
unconfine the pointer.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_region">
|
||||
<description summary="set a new confine region">
|
||||
Set a new region used to confine the pointer.
|
||||
|
||||
The new confine region is double-buffered. The new confine region will
|
||||
only take effect when the associated surface gets its pending state
|
||||
applied. See wl_surface.commit for details.
|
||||
|
||||
If the confinement is active when the new confinement region is applied
|
||||
and the pointer ends up outside of newly applied region, the pointer may
|
||||
warped to a position within the new confinement region. If warped, a
|
||||
wl_pointer.motion event will be emitted, but no
|
||||
wp_relative_pointer.relative_motion event.
|
||||
|
||||
The compositor may also, instead of using the new region, unconfine the
|
||||
pointer.
|
||||
|
||||
For details about the confine region, see wp_confined_pointer.
|
||||
</description>
|
||||
<arg name="region" type="object" interface="wl_region" allow-null="true"
|
||||
summary="region of surface"/>
|
||||
</request>
|
||||
|
||||
<event name="confined">
|
||||
<description summary="pointer confined">
|
||||
Notification that the pointer confinement of the seat's pointer is
|
||||
activated.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="unconfined">
|
||||
<description summary="pointer unconfined">
|
||||
Notification that the pointer confinement of the seat's pointer is no
|
||||
longer active. If this is a oneshot pointer confinement (see
|
||||
wp_pointer_constraints.lifetime) this object is now defunct and should
|
||||
be destroyed. If this is a persistent pointer confinement (see
|
||||
wp_pointer_constraints.lifetime) this pointer confinement may again
|
||||
reactivate in the future.
|
||||
</description>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
</protocol>
|
113
protocols/virtual-keyboard-unstable-v1.xml
Normal file
@@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="virtual_keyboard_unstable_v1">
|
||||
<copyright>
|
||||
Copyright © 2008-2011 Kristian Høgsberg
|
||||
Copyright © 2010-2013 Intel Corporation
|
||||
Copyright © 2012-2013 Collabora, Ltd.
|
||||
Copyright © 2018 Purism SPC
|
||||
|
||||
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
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) 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
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="zwp_virtual_keyboard_v1" version="1">
|
||||
<description summary="virtual keyboard">
|
||||
The virtual keyboard provides an application with requests which emulate
|
||||
the behaviour of a physical keyboard.
|
||||
|
||||
This interface can be used by clients on its own to provide raw input
|
||||
events, or it can accompany the input method protocol.
|
||||
</description>
|
||||
|
||||
<request name="keymap">
|
||||
<description summary="keyboard mapping">
|
||||
Provide a file descriptor to the compositor which can be
|
||||
memory-mapped to provide a keyboard mapping description.
|
||||
|
||||
Format carries a value from the keymap_format enumeration.
|
||||
</description>
|
||||
<arg name="format" type="uint" summary="keymap format"/>
|
||||
<arg name="fd" type="fd" summary="keymap file descriptor"/>
|
||||
<arg name="size" type="uint" summary="keymap size, in bytes"/>
|
||||
</request>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="no_keymap" value="0" summary="No keymap was set"/>
|
||||
</enum>
|
||||
|
||||
<request name="key">
|
||||
<description summary="key event">
|
||||
A key was pressed or released.
|
||||
The time argument is a timestamp with millisecond granularity, with an
|
||||
undefined base. All requests regarding a single object must share the
|
||||
same clock.
|
||||
|
||||
Keymap must be set before issuing this request.
|
||||
|
||||
State carries a value from the key_state enumeration.
|
||||
</description>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="key" type="uint" summary="key that produced the event"/>
|
||||
<arg name="state" type="uint" summary="physical state of the key"/>
|
||||
</request>
|
||||
|
||||
<request name="modifiers">
|
||||
<description summary="modifier and group state">
|
||||
Notifies the compositor that the modifier and/or group state has
|
||||
changed, and it should update state.
|
||||
|
||||
The client should use wl_keyboard.modifiers event to synchronize its
|
||||
internal state with seat state.
|
||||
|
||||
Keymap must be set before issuing this request.
|
||||
</description>
|
||||
<arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
|
||||
<arg name="mods_latched" type="uint" summary="latched modifiers"/>
|
||||
<arg name="mods_locked" type="uint" summary="locked modifiers"/>
|
||||
<arg name="group" type="uint" summary="keyboard layout"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor" since="1">
|
||||
<description summary="destroy the virtual keyboard keyboard object"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zwp_virtual_keyboard_manager_v1" version="1">
|
||||
<description summary="virtual keyboard manager">
|
||||
A virtual keyboard manager allows an application to provide keyboard
|
||||
input events as if they came from a physical keyboard.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="unauthorized" value="0" summary="client not authorized to use the interface"/>
|
||||
</enum>
|
||||
|
||||
<request name="create_virtual_keyboard">
|
||||
<description summary="Create a new virtual keyboard">
|
||||
Creates a new virtual keyboard associated to a seat.
|
||||
|
||||
If the compositor enables a keyboard to perform arbitrary actions, it
|
||||
should present an error when an untrusted client requests a new
|
||||
keyboard.
|
||||
</description>
|
||||
<arg name="seat" type="object" interface="wl_seat"/>
|
||||
<arg name="id" type="new_id" interface="zwp_virtual_keyboard_v1"/>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
189
protocols/wayland-drm.xml
Normal file
@@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="drm">
|
||||
|
||||
<copyright>
|
||||
Copyright © 2008-2011 Kristian Høgsberg
|
||||
Copyright © 2010-2011 Intel Corporation
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that\n the above copyright notice appear in
|
||||
all copies and that both that copyright notice and this permission
|
||||
notice appear in supporting documentation, and that the name of
|
||||
the copyright holders not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission. The copyright holders make no
|
||||
representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied
|
||||
warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<!-- drm support. This object is created by the server and published
|
||||
using the display's global event. -->
|
||||
<interface name="wl_drm" version="2">
|
||||
<enum name="error">
|
||||
<entry name="authenticate_fail" value="0"/>
|
||||
<entry name="invalid_format" value="1"/>
|
||||
<entry name="invalid_name" value="2"/>
|
||||
</enum>
|
||||
|
||||
<enum name="format">
|
||||
<!-- The drm format codes match the #defines in drm_fourcc.h.
|
||||
The formats actually supported by the compositor will be
|
||||
reported by the format event. New codes must not be added,
|
||||
unless directly taken from drm_fourcc.h. -->
|
||||
<entry name="c8" value="0x20203843"/>
|
||||
<entry name="rgb332" value="0x38424752"/>
|
||||
<entry name="bgr233" value="0x38524742"/>
|
||||
<entry name="xrgb4444" value="0x32315258"/>
|
||||
<entry name="xbgr4444" value="0x32314258"/>
|
||||
<entry name="rgbx4444" value="0x32315852"/>
|
||||
<entry name="bgrx4444" value="0x32315842"/>
|
||||
<entry name="argb4444" value="0x32315241"/>
|
||||
<entry name="abgr4444" value="0x32314241"/>
|
||||
<entry name="rgba4444" value="0x32314152"/>
|
||||
<entry name="bgra4444" value="0x32314142"/>
|
||||
<entry name="xrgb1555" value="0x35315258"/>
|
||||
<entry name="xbgr1555" value="0x35314258"/>
|
||||
<entry name="rgbx5551" value="0x35315852"/>
|
||||
<entry name="bgrx5551" value="0x35315842"/>
|
||||
<entry name="argb1555" value="0x35315241"/>
|
||||
<entry name="abgr1555" value="0x35314241"/>
|
||||
<entry name="rgba5551" value="0x35314152"/>
|
||||
<entry name="bgra5551" value="0x35314142"/>
|
||||
<entry name="rgb565" value="0x36314752"/>
|
||||
<entry name="bgr565" value="0x36314742"/>
|
||||
<entry name="rgb888" value="0x34324752"/>
|
||||
<entry name="bgr888" value="0x34324742"/>
|
||||
<entry name="xrgb8888" value="0x34325258"/>
|
||||
<entry name="xbgr8888" value="0x34324258"/>
|
||||
<entry name="rgbx8888" value="0x34325852"/>
|
||||
<entry name="bgrx8888" value="0x34325842"/>
|
||||
<entry name="argb8888" value="0x34325241"/>
|
||||
<entry name="abgr8888" value="0x34324241"/>
|
||||
<entry name="rgba8888" value="0x34324152"/>
|
||||
<entry name="bgra8888" value="0x34324142"/>
|
||||
<entry name="xrgb2101010" value="0x30335258"/>
|
||||
<entry name="xbgr2101010" value="0x30334258"/>
|
||||
<entry name="rgbx1010102" value="0x30335852"/>
|
||||
<entry name="bgrx1010102" value="0x30335842"/>
|
||||
<entry name="argb2101010" value="0x30335241"/>
|
||||
<entry name="abgr2101010" value="0x30334241"/>
|
||||
<entry name="rgba1010102" value="0x30334152"/>
|
||||
<entry name="bgra1010102" value="0x30334142"/>
|
||||
<entry name="yuyv" value="0x56595559"/>
|
||||
<entry name="yvyu" value="0x55595659"/>
|
||||
<entry name="uyvy" value="0x59565955"/>
|
||||
<entry name="vyuy" value="0x59555956"/>
|
||||
<entry name="ayuv" value="0x56555941"/>
|
||||
<entry name="xyuv8888" value="0x56555958"/>
|
||||
<entry name="nv12" value="0x3231564e"/>
|
||||
<entry name="nv21" value="0x3132564e"/>
|
||||
<entry name="nv16" value="0x3631564e"/>
|
||||
<entry name="nv61" value="0x3136564e"/>
|
||||
<entry name="yuv410" value="0x39565559"/>
|
||||
<entry name="yvu410" value="0x39555659"/>
|
||||
<entry name="yuv411" value="0x31315559"/>
|
||||
<entry name="yvu411" value="0x31315659"/>
|
||||
<entry name="yuv420" value="0x32315559"/>
|
||||
<entry name="yvu420" value="0x32315659"/>
|
||||
<entry name="yuv422" value="0x36315559"/>
|
||||
<entry name="yvu422" value="0x36315659"/>
|
||||
<entry name="yuv444" value="0x34325559"/>
|
||||
<entry name="yvu444" value="0x34325659"/>
|
||||
<entry name="abgr16f" value="0x48344241"/>
|
||||
<entry name="xbgr16f" value="0x48344258"/>
|
||||
</enum>
|
||||
|
||||
<!-- Call this request with the magic received from drmGetMagic().
|
||||
It will be passed on to the drmAuthMagic() or
|
||||
DRIAuthConnection() call. This authentication must be
|
||||
completed before create_buffer could be used. -->
|
||||
<request name="authenticate">
|
||||
<arg name="id" type="uint"/>
|
||||
</request>
|
||||
|
||||
<!-- Create a wayland buffer for the named DRM buffer. The DRM
|
||||
surface must have a name using the flink ioctl -->
|
||||
<request name="create_buffer">
|
||||
<arg name="id" type="new_id" interface="wl_buffer"/>
|
||||
<arg name="name" type="uint"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
<arg name="stride" type="uint"/>
|
||||
<arg name="format" type="uint"/>
|
||||
</request>
|
||||
|
||||
<!-- Create a wayland buffer for the named DRM buffer. The DRM
|
||||
surface must have a name using the flink ioctl -->
|
||||
<request name="create_planar_buffer">
|
||||
<arg name="id" type="new_id" interface="wl_buffer"/>
|
||||
<arg name="name" type="uint"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
<arg name="format" type="uint"/>
|
||||
<arg name="offset0" type="int"/>
|
||||
<arg name="stride0" type="int"/>
|
||||
<arg name="offset1" type="int"/>
|
||||
<arg name="stride1" type="int"/>
|
||||
<arg name="offset2" type="int"/>
|
||||
<arg name="stride2" type="int"/>
|
||||
</request>
|
||||
|
||||
<!-- Notification of the path of the drm device which is used by
|
||||
the server. The client should use this device for creating
|
||||
local buffers. Only buffers created from this device should
|
||||
be be passed to the server using this drm object's
|
||||
create_buffer request. -->
|
||||
<event name="device">
|
||||
<arg name="name" type="string"/>
|
||||
</event>
|
||||
|
||||
<event name="format">
|
||||
<arg name="format" type="uint"/>
|
||||
</event>
|
||||
|
||||
<!-- Raised if the authenticate request succeeded -->
|
||||
<event name="authenticated"/>
|
||||
|
||||
<enum name="capability" since="2">
|
||||
<description summary="wl_drm capability bitmask">
|
||||
Bitmask of capabilities.
|
||||
</description>
|
||||
<entry name="prime" value="1" summary="wl_drm prime available"/>
|
||||
</enum>
|
||||
|
||||
<event name="capabilities">
|
||||
<arg name="value" type="uint"/>
|
||||
</event>
|
||||
|
||||
<!-- Version 2 additions -->
|
||||
|
||||
<!-- Create a wayland buffer for the prime fd. Use for regular and planar
|
||||
buffers. Pass 0 for offset and stride for unused planes. -->
|
||||
<request name="create_prime_buffer" since="2">
|
||||
<arg name="id" type="new_id" interface="wl_buffer"/>
|
||||
<arg name="name" type="fd"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
<arg name="format" type="uint"/>
|
||||
<arg name="offset0" type="int"/>
|
||||
<arg name="stride0" type="int"/>
|
||||
<arg name="offset1" type="int"/>
|
||||
<arg name="stride1" type="int"/>
|
||||
<arg name="offset2" type="int"/>
|
||||
<arg name="stride2" type="int"/>
|
||||
</request>
|
||||
|
||||
</interface>
|
||||
|
||||
</protocol>
|
278
protocols/wlr-data-control-unstable-v1.xml
Normal file
@@ -0,0 +1,278 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="wlr_data_control_unstable_v1">
|
||||
<copyright>
|
||||
Copyright © 2018 Simon Ser
|
||||
Copyright © 2019 Ivan Molodetskikh
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that copyright notice and this permission
|
||||
notice appear in supporting documentation, and that the name of
|
||||
the copyright holders not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission. The copyright holders make no
|
||||
representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied
|
||||
warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<description summary="control data devices">
|
||||
This protocol allows a privileged client to control data devices. In
|
||||
particular, the client will be able to manage the current selection and take
|
||||
the role of a clipboard manager.
|
||||
|
||||
Warning! The protocol described in this file is experimental and
|
||||
backward incompatible changes may be made. Backward compatible changes
|
||||
may be added together with the corresponding interface version bump.
|
||||
Backward incompatible changes are done by bumping the version number in
|
||||
the protocol and interface names and resetting the interface version.
|
||||
Once the protocol is to be declared stable, the 'z' prefix and the
|
||||
version number in the protocol and interface names are removed and the
|
||||
interface version number is reset.
|
||||
</description>
|
||||
|
||||
<interface name="zwlr_data_control_manager_v1" version="2">
|
||||
<description summary="manager to control data devices">
|
||||
This interface is a manager that allows creating per-seat data device
|
||||
controls.
|
||||
</description>
|
||||
|
||||
<request name="create_data_source">
|
||||
<description summary="create a new data source">
|
||||
Create a new data source.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwlr_data_control_source_v1"
|
||||
summary="data source to create"/>
|
||||
</request>
|
||||
|
||||
<request name="get_data_device">
|
||||
<description summary="get a data device for a seat">
|
||||
Create a data device that can be used to manage a seat's selection.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwlr_data_control_device_v1"/>
|
||||
<arg name="seat" type="object" interface="wl_seat"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the manager">
|
||||
All objects created by the manager will still remain valid, until their
|
||||
appropriate destroy request has been called.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_data_control_device_v1" version="2">
|
||||
<description summary="manage a data device for a seat">
|
||||
This interface allows a client to manage a seat's selection.
|
||||
|
||||
When the seat is destroyed, this object becomes inert.
|
||||
</description>
|
||||
|
||||
<request name="set_selection">
|
||||
<description summary="copy data to the selection">
|
||||
This request asks the compositor to set the selection to the data from
|
||||
the source on behalf of the client.
|
||||
|
||||
The given source may not be used in any further set_selection or
|
||||
set_primary_selection requests. Attempting to use a previously used
|
||||
source is a protocol error.
|
||||
|
||||
To unset the selection, set the source to NULL.
|
||||
</description>
|
||||
<arg name="source" type="object" interface="zwlr_data_control_source_v1"
|
||||
allow-null="true"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy this data device">
|
||||
Destroys the data device object.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="data_offer">
|
||||
<description summary="introduce a new wlr_data_control_offer">
|
||||
The data_offer event introduces a new wlr_data_control_offer object,
|
||||
which will subsequently be used in either the
|
||||
wlr_data_control_device.selection event (for the regular clipboard
|
||||
selections) or the wlr_data_control_device.primary_selection event (for
|
||||
the primary clipboard selections). Immediately following the
|
||||
wlr_data_control_device.data_offer event, the new data_offer object
|
||||
will send out wlr_data_control_offer.offer events to describe the MIME
|
||||
types it offers.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwlr_data_control_offer_v1"/>
|
||||
</event>
|
||||
|
||||
<event name="selection">
|
||||
<description summary="advertise new selection">
|
||||
The selection event is sent out to notify the client of a new
|
||||
wlr_data_control_offer for the selection for this device. The
|
||||
wlr_data_control_device.data_offer and the wlr_data_control_offer.offer
|
||||
events are sent out immediately before this event to introduce the data
|
||||
offer object. The selection event is sent to a client when a new
|
||||
selection is set. The wlr_data_control_offer is valid until a new
|
||||
wlr_data_control_offer or NULL is received. The client must destroy the
|
||||
previous selection wlr_data_control_offer, if any, upon receiving this
|
||||
event.
|
||||
|
||||
The first selection event is sent upon binding the
|
||||
wlr_data_control_device object.
|
||||
</description>
|
||||
<arg name="id" type="object" interface="zwlr_data_control_offer_v1"
|
||||
allow-null="true"/>
|
||||
</event>
|
||||
|
||||
<event name="finished">
|
||||
<description summary="this data control is no longer valid">
|
||||
This data control object is no longer valid and should be destroyed by
|
||||
the client.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<!-- Version 2 additions -->
|
||||
|
||||
<event name="primary_selection" since="2">
|
||||
<description summary="advertise new primary selection">
|
||||
The primary_selection event is sent out to notify the client of a new
|
||||
wlr_data_control_offer for the primary selection for this device. The
|
||||
wlr_data_control_device.data_offer and the wlr_data_control_offer.offer
|
||||
events are sent out immediately before this event to introduce the data
|
||||
offer object. The primary_selection event is sent to a client when a
|
||||
new primary selection is set. The wlr_data_control_offer is valid until
|
||||
a new wlr_data_control_offer or NULL is received. The client must
|
||||
destroy the previous primary selection wlr_data_control_offer, if any,
|
||||
upon receiving this event.
|
||||
|
||||
If the compositor supports primary selection, the first
|
||||
primary_selection event is sent upon binding the
|
||||
wlr_data_control_device object.
|
||||
</description>
|
||||
<arg name="id" type="object" interface="zwlr_data_control_offer_v1"
|
||||
allow-null="true"/>
|
||||
</event>
|
||||
|
||||
<request name="set_primary_selection" since="2">
|
||||
<description summary="copy data to the primary selection">
|
||||
This request asks the compositor to set the primary selection to the
|
||||
data from the source on behalf of the client.
|
||||
|
||||
The given source may not be used in any further set_selection or
|
||||
set_primary_selection requests. Attempting to use a previously used
|
||||
source is a protocol error.
|
||||
|
||||
To unset the primary selection, set the source to NULL.
|
||||
|
||||
The compositor will ignore this request if it does not support primary
|
||||
selection.
|
||||
</description>
|
||||
<arg name="source" type="object" interface="zwlr_data_control_source_v1"
|
||||
allow-null="true"/>
|
||||
</request>
|
||||
|
||||
<enum name="error" since="2">
|
||||
<entry name="used_source" value="1"
|
||||
summary="source given to set_selection or set_primary_selection was already used before"/>
|
||||
</enum>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_data_control_source_v1" version="1">
|
||||
<description summary="offer to transfer data">
|
||||
The wlr_data_control_source object is the source side of a
|
||||
wlr_data_control_offer. It is created by the source client in a data
|
||||
transfer and provides a way to describe the offered data and a way to
|
||||
respond to requests to transfer the data.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="invalid_offer" value="1"
|
||||
summary="offer sent after wlr_data_control_device.set_selection"/>
|
||||
</enum>
|
||||
|
||||
<request name="offer">
|
||||
<description summary="add an offered MIME type">
|
||||
This request adds a MIME type to the set of MIME types advertised to
|
||||
targets. Can be called several times to offer multiple types.
|
||||
|
||||
Calling this after wlr_data_control_device.set_selection is a protocol
|
||||
error.
|
||||
</description>
|
||||
<arg name="mime_type" type="string"
|
||||
summary="MIME type offered by the data source"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy this source">
|
||||
Destroys the data source object.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="send">
|
||||
<description summary="send the data">
|
||||
Request for data from the client. Send the data as the specified MIME
|
||||
type over the passed file descriptor, then close it.
|
||||
</description>
|
||||
<arg name="mime_type" type="string" summary="MIME type for the data"/>
|
||||
<arg name="fd" type="fd" summary="file descriptor for the data"/>
|
||||
</event>
|
||||
|
||||
<event name="cancelled">
|
||||
<description summary="selection was cancelled">
|
||||
This data source is no longer valid. The data source has been replaced
|
||||
by another data source.
|
||||
|
||||
The client should clean up and destroy this data source.
|
||||
</description>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_data_control_offer_v1" version="1">
|
||||
<description summary="offer to transfer data">
|
||||
A wlr_data_control_offer represents a piece of data offered for transfer
|
||||
by another client (the source client). The offer describes the different
|
||||
MIME types that the data can be converted to and provides the mechanism
|
||||
for transferring the data directly from the source client.
|
||||
</description>
|
||||
|
||||
<request name="receive">
|
||||
<description summary="request that the data is transferred">
|
||||
To transfer the offered data, the client issues this request and
|
||||
indicates the MIME type it wants to receive. The transfer happens
|
||||
through the passed file descriptor (typically created with the pipe
|
||||
system call). The source client writes the data in the MIME type
|
||||
representation requested and then closes the file descriptor.
|
||||
|
||||
The receiving client reads from the read end of the pipe until EOF and
|
||||
then closes its end, at which point the transfer is complete.
|
||||
|
||||
This request may happen multiple times for different MIME types.
|
||||
</description>
|
||||
<arg name="mime_type" type="string"
|
||||
summary="MIME type desired by receiver"/>
|
||||
<arg name="fd" type="fd" summary="file descriptor for data transfer"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy this offer">
|
||||
Destroys the data offer object.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="offer">
|
||||
<description summary="advertise offered MIME type">
|
||||
Sent immediately after creating the wlr_data_control_offer object.
|
||||
One event per offered MIME type.
|
||||
</description>
|
||||
<arg name="mime_type" type="string" summary="offered MIME type"/>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
126
protocols/wlr-gamma-control-unstable-v1.xml
Normal file
@@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="wlr_gamma_control_unstable_v1">
|
||||
<copyright>
|
||||
Copyright © 2015 Giulio camuffo
|
||||
Copyright © 2018 Simon Ser
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that copyright notice and this permission
|
||||
notice appear in supporting documentation, and that the name of
|
||||
the copyright holders not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission. The copyright holders make no
|
||||
representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied
|
||||
warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<description summary="manage gamma tables of outputs">
|
||||
This protocol allows a privileged client to set the gamma tables for
|
||||
outputs.
|
||||
|
||||
Warning! The protocol described in this file is experimental and
|
||||
backward incompatible changes may be made. Backward compatible changes
|
||||
may be added together with the corresponding interface version bump.
|
||||
Backward incompatible changes are done by bumping the version number in
|
||||
the protocol and interface names and resetting the interface version.
|
||||
Once the protocol is to be declared stable, the 'z' prefix and the
|
||||
version number in the protocol and interface names are removed and the
|
||||
interface version number is reset.
|
||||
</description>
|
||||
|
||||
<interface name="zwlr_gamma_control_manager_v1" version="1">
|
||||
<description summary="manager to create per-output gamma controls">
|
||||
This interface is a manager that allows creating per-output gamma
|
||||
controls.
|
||||
</description>
|
||||
|
||||
<request name="get_gamma_control">
|
||||
<description summary="get a gamma control for an output">
|
||||
Create a gamma control that can be used to adjust gamma tables for the
|
||||
provided output.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwlr_gamma_control_v1"/>
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the manager">
|
||||
All objects created by the manager will still remain valid, until their
|
||||
appropriate destroy request has been called.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_gamma_control_v1" version="1">
|
||||
<description summary="adjust gamma tables for an output">
|
||||
This interface allows a client to adjust gamma tables for a particular
|
||||
output.
|
||||
|
||||
The client will receive the gamma size, and will then be able to set gamma
|
||||
tables. At any time the compositor can send a failed event indicating that
|
||||
this object is no longer valid.
|
||||
|
||||
There can only be at most one gamma control object per output, which
|
||||
has exclusive access to this particular output. When the gamma control
|
||||
object is destroyed, the gamma table is restored to its original value.
|
||||
</description>
|
||||
|
||||
<event name="gamma_size">
|
||||
<description summary="size of gamma ramps">
|
||||
Advertise the size of each gamma ramp.
|
||||
|
||||
This event is sent immediately when the gamma control object is created.
|
||||
</description>
|
||||
<arg name="size" type="uint" summary="number of elements in a ramp"/>
|
||||
</event>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="invalid_gamma" value="1" summary="invalid gamma tables"/>
|
||||
</enum>
|
||||
|
||||
<request name="set_gamma">
|
||||
<description summary="set the gamma table">
|
||||
Set the gamma table. The file descriptor can be memory-mapped to provide
|
||||
the raw gamma table, which contains successive gamma ramps for the red,
|
||||
green and blue channels. Each gamma ramp is an array of 16-byte unsigned
|
||||
integers which has the same length as the gamma size.
|
||||
|
||||
The file descriptor data must have the same length as three times the
|
||||
gamma size.
|
||||
</description>
|
||||
<arg name="fd" type="fd" summary="gamma table file descriptor"/>
|
||||
</request>
|
||||
|
||||
<event name="failed">
|
||||
<description summary="object no longer valid">
|
||||
This event indicates that the gamma control is no longer valid. This
|
||||
can happen for a number of reasons, including:
|
||||
- The output doesn't support gamma tables
|
||||
- Setting the gamma tables failed
|
||||
- Another client already has exclusive gamma control for this output
|
||||
- The compositor has transferred gamma control to another client
|
||||
|
||||
Upon receiving this event, the client should destroy this object.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy this control">
|
||||
Destroys the gamma control object. If the object is still valid, this
|
||||
restores the original gamma tables.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
@@ -25,7 +25,7 @@
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="zwlr_layer_shell_v1" version="4">
|
||||
<interface name="zwlr_layer_shell_v1" version="5">
|
||||
<description summary="create surfaces that are layers of the desktop">
|
||||
Clients can use this interface to assign the surface_layer role to
|
||||
wl_surfaces. Such surfaces are assigned to a "layer" of the output and
|
||||
@@ -100,7 +100,7 @@
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_layer_surface_v1" version="4">
|
||||
<interface name="zwlr_layer_surface_v1" version="5">
|
||||
<description summary="layer metadata interface">
|
||||
An interface that may be implemented by a wl_surface, for surfaces that
|
||||
are designed to be rendered as a layer of a stacked desktop-like
|
||||
@@ -367,6 +367,7 @@
|
||||
<entry name="invalid_size" value="1" summary="size is invalid"/>
|
||||
<entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/>
|
||||
<entry name="invalid_keyboard_interactivity" value="3" summary="keyboard interactivity is invalid"/>
|
||||
<entry name="invalid_exclusive_edge" value="4" summary="exclusive edge is invalid given the surface anchors"/>
|
||||
</enum>
|
||||
|
||||
<enum name="anchor" bitfield="true">
|
||||
@@ -386,5 +387,21 @@
|
||||
</description>
|
||||
<arg name="layer" type="uint" enum="zwlr_layer_shell_v1.layer" summary="layer to move this surface to"/>
|
||||
</request>
|
||||
|
||||
<!-- Version 5 additions -->
|
||||
|
||||
<request name="set_exclusive_edge" since="5">
|
||||
<description summary="set the edge the exclusive zone will be applied to">
|
||||
Requests an edge for the exclusive zone to apply. The exclusive
|
||||
edge will be automatically deduced from anchor points when possible,
|
||||
but when the surface is anchored to a corner, it will be necessary
|
||||
to set it explicitly to disambiguate, as it is not possible to deduce
|
||||
which one of the two corner edges should be used.
|
||||
|
||||
The edge must be one the surface is anchored to, otherwise the
|
||||
invalid_exclusive_edge protocol error will be raised.
|
||||
</description>
|
||||
<arg name="edge" type="uint" enum="anchor"/>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
||||
|
601
protocols/wlr-output-management-unstable-v1.xml
Normal file
@@ -0,0 +1,601 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="wlr_output_management_unstable_v1">
|
||||
<copyright>
|
||||
Copyright © 2019 Purism SPC
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that copyright notice and this permission
|
||||
notice appear in supporting documentation, and that the name of
|
||||
the copyright holders not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission. The copyright holders make no
|
||||
representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied
|
||||
warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<description summary="protocol to configure output devices">
|
||||
This protocol exposes interfaces to obtain and modify output device
|
||||
configuration.
|
||||
|
||||
Warning! The protocol described in this file is experimental and
|
||||
backward incompatible changes may be made. Backward compatible changes
|
||||
may be added together with the corresponding interface version bump.
|
||||
Backward incompatible changes are done by bumping the version number in
|
||||
the protocol and interface names and resetting the interface version.
|
||||
Once the protocol is to be declared stable, the 'z' prefix and the
|
||||
version number in the protocol and interface names are removed and the
|
||||
interface version number is reset.
|
||||
</description>
|
||||
|
||||
<interface name="zwlr_output_manager_v1" version="4">
|
||||
<description summary="output device configuration manager">
|
||||
This interface is a manager that allows reading and writing the current
|
||||
output device configuration.
|
||||
|
||||
Output devices that display pixels (e.g. a physical monitor or a virtual
|
||||
output in a window) are represented as heads. Heads cannot be created nor
|
||||
destroyed by the client, but they can be enabled or disabled and their
|
||||
properties can be changed. Each head may have one or more available modes.
|
||||
|
||||
Whenever a head appears (e.g. a monitor is plugged in), it will be
|
||||
advertised via the head event. Immediately after the output manager is
|
||||
bound, all current heads are advertised.
|
||||
|
||||
Whenever a head's properties change, the relevant wlr_output_head events
|
||||
will be sent. Not all head properties will be sent: only properties that
|
||||
have changed need to.
|
||||
|
||||
Whenever a head disappears (e.g. a monitor is unplugged), a
|
||||
wlr_output_head.finished event will be sent.
|
||||
|
||||
After one or more heads appear, change or disappear, the done event will
|
||||
be sent. It carries a serial which can be used in a create_configuration
|
||||
request to update heads properties.
|
||||
|
||||
The information obtained from this protocol should only be used for output
|
||||
configuration purposes. This protocol is not designed to be a generic
|
||||
output property advertisement protocol for regular clients. Instead,
|
||||
protocols such as xdg-output should be used.
|
||||
</description>
|
||||
|
||||
<event name="head">
|
||||
<description summary="introduce a new head">
|
||||
This event introduces a new head. This happens whenever a new head
|
||||
appears (e.g. a monitor is plugged in) or after the output manager is
|
||||
bound.
|
||||
</description>
|
||||
<arg name="head" type="new_id" interface="zwlr_output_head_v1"/>
|
||||
</event>
|
||||
|
||||
<event name="done">
|
||||
<description summary="sent all information about current configuration">
|
||||
This event is sent after all information has been sent after binding to
|
||||
the output manager object and after any subsequent changes. This applies
|
||||
to child head and mode objects as well. In other words, this event is
|
||||
sent whenever a head or mode is created or destroyed and whenever one of
|
||||
their properties has been changed. Not all state is re-sent each time
|
||||
the current configuration changes: only the actual changes are sent.
|
||||
|
||||
This allows changes to the output configuration to be seen as atomic,
|
||||
even if they happen via multiple events.
|
||||
|
||||
A serial is sent to be used in a future create_configuration request.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="current configuration serial"/>
|
||||
</event>
|
||||
|
||||
<request name="create_configuration">
|
||||
<description summary="create a new output configuration object">
|
||||
Create a new output configuration object. This allows to update head
|
||||
properties.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwlr_output_configuration_v1"/>
|
||||
<arg name="serial" type="uint"/>
|
||||
</request>
|
||||
|
||||
<request name="stop">
|
||||
<description summary="stop sending events">
|
||||
Indicates the client no longer wishes to receive events for output
|
||||
configuration changes. However the compositor may emit further events,
|
||||
until the finished event is emitted.
|
||||
|
||||
The client must not send any more requests after this one.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="finished" type="destructor">
|
||||
<description summary="the compositor has finished with the manager">
|
||||
This event indicates that the compositor is done sending manager events.
|
||||
The compositor will destroy the object immediately after sending this
|
||||
event, so it will become invalid and the client should release any
|
||||
resources associated with it.
|
||||
</description>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_output_head_v1" version="4">
|
||||
<description summary="output device">
|
||||
A head is an output device. The difference between a wl_output object and
|
||||
a head is that heads are advertised even if they are turned off. A head
|
||||
object only advertises properties and cannot be used directly to change
|
||||
them.
|
||||
|
||||
A head has some read-only properties: modes, name, description and
|
||||
physical_size. These cannot be changed by clients.
|
||||
|
||||
Other properties can be updated via a wlr_output_configuration object.
|
||||
|
||||
Properties sent via this interface are applied atomically via the
|
||||
wlr_output_manager.done event. No guarantees are made regarding the order
|
||||
in which properties are sent.
|
||||
</description>
|
||||
|
||||
<event name="name">
|
||||
<description summary="head name">
|
||||
This event describes the head name.
|
||||
|
||||
The naming convention is compositor defined, but limited to alphanumeric
|
||||
characters and dashes (-). Each name is unique among all wlr_output_head
|
||||
objects, but if a wlr_output_head object is destroyed the same name may
|
||||
be reused later. The names will also remain consistent across sessions
|
||||
with the same hardware and software configuration.
|
||||
|
||||
Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do
|
||||
not assume that the name is a reflection of an underlying DRM
|
||||
connector, X11 connection, etc.
|
||||
|
||||
If the compositor implements the xdg-output protocol and this head is
|
||||
enabled, the xdg_output.name event must report the same name.
|
||||
|
||||
The name event is sent after a wlr_output_head object is created. This
|
||||
event is only sent once per object, and the name does not change over
|
||||
the lifetime of the wlr_output_head object.
|
||||
</description>
|
||||
<arg name="name" type="string"/>
|
||||
</event>
|
||||
|
||||
<event name="description">
|
||||
<description summary="head description">
|
||||
This event describes a human-readable description of the head.
|
||||
|
||||
The description is a UTF-8 string with no convention defined for its
|
||||
contents. Examples might include 'Foocorp 11" Display' or 'Virtual X11
|
||||
output via :1'. However, do not assume that the name is a reflection of
|
||||
the make, model, serial of the underlying DRM connector or the display
|
||||
name of the underlying X11 connection, etc.
|
||||
|
||||
If the compositor implements xdg-output and this head is enabled,
|
||||
the xdg_output.description must report the same description.
|
||||
|
||||
The description event is sent after a wlr_output_head object is created.
|
||||
This event is only sent once per object, and the description does not
|
||||
change over the lifetime of the wlr_output_head object.
|
||||
</description>
|
||||
<arg name="description" type="string"/>
|
||||
</event>
|
||||
|
||||
<event name="physical_size">
|
||||
<description summary="head physical size">
|
||||
This event describes the physical size of the head. This event is only
|
||||
sent if the head has a physical size (e.g. is not a projector or a
|
||||
virtual device).
|
||||
</description>
|
||||
<arg name="width" type="int" summary="width in millimeters of the output"/>
|
||||
<arg name="height" type="int" summary="height in millimeters of the output"/>
|
||||
</event>
|
||||
|
||||
<event name="mode">
|
||||
<description summary="introduce a mode">
|
||||
This event introduces a mode for this head. It is sent once per
|
||||
supported mode.
|
||||
</description>
|
||||
<arg name="mode" type="new_id" interface="zwlr_output_mode_v1"/>
|
||||
</event>
|
||||
|
||||
<event name="enabled">
|
||||
<description summary="head is enabled or disabled">
|
||||
This event describes whether the head is enabled. A disabled head is not
|
||||
mapped to a region of the global compositor space.
|
||||
|
||||
When a head is disabled, some properties (current_mode, position,
|
||||
transform and scale) are irrelevant.
|
||||
</description>
|
||||
<arg name="enabled" type="int" summary="zero if disabled, non-zero if enabled"/>
|
||||
</event>
|
||||
|
||||
<event name="current_mode">
|
||||
<description summary="current mode">
|
||||
This event describes the mode currently in use for this head. It is only
|
||||
sent if the output is enabled.
|
||||
</description>
|
||||
<arg name="mode" type="object" interface="zwlr_output_mode_v1"/>
|
||||
</event>
|
||||
|
||||
<event name="position">
|
||||
<description summary="current position">
|
||||
This events describes the position of the head in the global compositor
|
||||
space. It is only sent if the output is enabled.
|
||||
</description>
|
||||
<arg name="x" type="int"
|
||||
summary="x position within the global compositor space"/>
|
||||
<arg name="y" type="int"
|
||||
summary="y position within the global compositor space"/>
|
||||
</event>
|
||||
|
||||
<event name="transform">
|
||||
<description summary="current transformation">
|
||||
This event describes the transformation currently applied to the head.
|
||||
It is only sent if the output is enabled.
|
||||
</description>
|
||||
<arg name="transform" type="int" enum="wl_output.transform"/>
|
||||
</event>
|
||||
|
||||
<event name="scale">
|
||||
<description summary="current scale">
|
||||
This events describes the scale of the head in the global compositor
|
||||
space. It is only sent if the output is enabled.
|
||||
</description>
|
||||
<arg name="scale" type="fixed"/>
|
||||
</event>
|
||||
|
||||
<event name="finished">
|
||||
<description summary="the head has disappeared">
|
||||
This event indicates that the head is no longer available. The head
|
||||
object becomes inert. Clients should send a destroy request and release
|
||||
any resources associated with it.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<!-- Version 2 additions -->
|
||||
|
||||
<event name="make" since="2">
|
||||
<description summary="head manufacturer">
|
||||
This event describes the manufacturer of the head.
|
||||
|
||||
This must report the same make as the wl_output interface does in its
|
||||
geometry event.
|
||||
|
||||
Together with the model and serial_number events the purpose is to
|
||||
allow clients to recognize heads from previous sessions and for example
|
||||
load head-specific configurations back.
|
||||
|
||||
It is not guaranteed this event will be ever sent. A reason for that
|
||||
can be that the compositor does not have information about the make of
|
||||
the head or the definition of a make is not sensible in the current
|
||||
setup, for example in a virtual session. Clients can still try to
|
||||
identify the head by available information from other events but should
|
||||
be aware that there is an increased risk of false positives.
|
||||
|
||||
It is not recommended to display the make string in UI to users. For
|
||||
that the string provided by the description event should be preferred.
|
||||
</description>
|
||||
<arg name="make" type="string"/>
|
||||
</event>
|
||||
|
||||
<event name="model" since="2">
|
||||
<description summary="head model">
|
||||
This event describes the model of the head.
|
||||
|
||||
This must report the same model as the wl_output interface does in its
|
||||
geometry event.
|
||||
|
||||
Together with the make and serial_number events the purpose is to
|
||||
allow clients to recognize heads from previous sessions and for example
|
||||
load head-specific configurations back.
|
||||
|
||||
It is not guaranteed this event will be ever sent. A reason for that
|
||||
can be that the compositor does not have information about the model of
|
||||
the head or the definition of a model is not sensible in the current
|
||||
setup, for example in a virtual session. Clients can still try to
|
||||
identify the head by available information from other events but should
|
||||
be aware that there is an increased risk of false positives.
|
||||
|
||||
It is not recommended to display the model string in UI to users. For
|
||||
that the string provided by the description event should be preferred.
|
||||
</description>
|
||||
<arg name="model" type="string"/>
|
||||
</event>
|
||||
|
||||
<event name="serial_number" since="2">
|
||||
<description summary="head serial number">
|
||||
This event describes the serial number of the head.
|
||||
|
||||
Together with the make and model events the purpose is to allow clients
|
||||
to recognize heads from previous sessions and for example load head-
|
||||
specific configurations back.
|
||||
|
||||
It is not guaranteed this event will be ever sent. A reason for that
|
||||
can be that the compositor does not have information about the serial
|
||||
number of the head or the definition of a serial number is not sensible
|
||||
in the current setup. Clients can still try to identify the head by
|
||||
available information from other events but should be aware that there
|
||||
is an increased risk of false positives.
|
||||
|
||||
It is not recommended to display the serial_number string in UI to
|
||||
users. For that the string provided by the description event should be
|
||||
preferred.
|
||||
</description>
|
||||
<arg name="serial_number" type="string"/>
|
||||
</event>
|
||||
|
||||
<!-- Version 3 additions -->
|
||||
|
||||
<request name="release" type="destructor" since="3">
|
||||
<description summary="destroy the head object">
|
||||
This request indicates that the client will no longer use this head
|
||||
object.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<!-- Version 4 additions -->
|
||||
|
||||
<enum name="adaptive_sync_state" since="4">
|
||||
<entry name="disabled" value="0" summary="adaptive sync is disabled"/>
|
||||
<entry name="enabled" value="1" summary="adaptive sync is enabled"/>
|
||||
</enum>
|
||||
|
||||
<event name="adaptive_sync" since="4">
|
||||
<description summary="current adaptive sync state">
|
||||
This event describes whether adaptive sync is currently enabled for
|
||||
the head or not. Adaptive sync is also known as Variable Refresh
|
||||
Rate or VRR.
|
||||
</description>
|
||||
<arg name="state" type="uint" enum="adaptive_sync_state"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_output_mode_v1" version="3">
|
||||
<description summary="output mode">
|
||||
This object describes an output mode.
|
||||
|
||||
Some heads don't support output modes, in which case modes won't be
|
||||
advertised.
|
||||
|
||||
Properties sent via this interface are applied atomically via the
|
||||
wlr_output_manager.done event. No guarantees are made regarding the order
|
||||
in which properties are sent.
|
||||
</description>
|
||||
|
||||
<event name="size">
|
||||
<description summary="mode size">
|
||||
This event describes the mode size. The size is given in physical
|
||||
hardware units of the output device. This is not necessarily the same as
|
||||
the output size in the global compositor space. For instance, the output
|
||||
may be scaled or transformed.
|
||||
</description>
|
||||
<arg name="width" type="int" summary="width of the mode in hardware units"/>
|
||||
<arg name="height" type="int" summary="height of the mode in hardware units"/>
|
||||
</event>
|
||||
|
||||
<event name="refresh">
|
||||
<description summary="mode refresh rate">
|
||||
This event describes the mode's fixed vertical refresh rate. It is only
|
||||
sent if the mode has a fixed refresh rate.
|
||||
</description>
|
||||
<arg name="refresh" type="int" summary="vertical refresh rate in mHz"/>
|
||||
</event>
|
||||
|
||||
<event name="preferred">
|
||||
<description summary="mode is preferred">
|
||||
This event advertises this mode as preferred.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="finished">
|
||||
<description summary="the mode has disappeared">
|
||||
This event indicates that the mode is no longer available. The mode
|
||||
object becomes inert. Clients should send a destroy request and release
|
||||
any resources associated with it.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<!-- Version 3 additions -->
|
||||
|
||||
<request name="release" type="destructor" since="3">
|
||||
<description summary="destroy the mode object">
|
||||
This request indicates that the client will no longer use this mode
|
||||
object.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_output_configuration_v1" version="4">
|
||||
<description summary="output configuration">
|
||||
This object is used by the client to describe a full output configuration.
|
||||
|
||||
First, the client needs to setup the output configuration. Each head can
|
||||
be either enabled (and configured) or disabled. It is a protocol error to
|
||||
send two enable_head or disable_head requests with the same head. It is a
|
||||
protocol error to omit a head in a configuration.
|
||||
|
||||
Then, the client can apply or test the configuration. The compositor will
|
||||
then reply with a succeeded, failed or cancelled event. Finally the client
|
||||
should destroy the configuration object.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="already_configured_head" value="1"
|
||||
summary="head has been configured twice"/>
|
||||
<entry name="unconfigured_head" value="2"
|
||||
summary="head has not been configured"/>
|
||||
<entry name="already_used" value="3"
|
||||
summary="request sent after configuration has been applied or tested"/>
|
||||
</enum>
|
||||
|
||||
<request name="enable_head">
|
||||
<description summary="enable and configure a head">
|
||||
Enable a head. This request creates a head configuration object that can
|
||||
be used to change the head's properties.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwlr_output_configuration_head_v1"
|
||||
summary="a new object to configure the head"/>
|
||||
<arg name="head" type="object" interface="zwlr_output_head_v1"
|
||||
summary="the head to be enabled"/>
|
||||
</request>
|
||||
|
||||
<request name="disable_head">
|
||||
<description summary="disable a head">
|
||||
Disable a head.
|
||||
</description>
|
||||
<arg name="head" type="object" interface="zwlr_output_head_v1"
|
||||
summary="the head to be disabled"/>
|
||||
</request>
|
||||
|
||||
<request name="apply">
|
||||
<description summary="apply the configuration">
|
||||
Apply the new output configuration.
|
||||
|
||||
In case the configuration is successfully applied, there is no guarantee
|
||||
that the new output state matches completely the requested
|
||||
configuration. For instance, a compositor might round the scale if it
|
||||
doesn't support fractional scaling.
|
||||
|
||||
After this request has been sent, the compositor must respond with an
|
||||
succeeded, failed or cancelled event. Sending a request that isn't the
|
||||
destructor is a protocol error.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="test">
|
||||
<description summary="test the configuration">
|
||||
Test the new output configuration. The configuration won't be applied,
|
||||
but will only be validated.
|
||||
|
||||
Even if the compositor succeeds to test a configuration, applying it may
|
||||
fail.
|
||||
|
||||
After this request has been sent, the compositor must respond with an
|
||||
succeeded, failed or cancelled event. Sending a request that isn't the
|
||||
destructor is a protocol error.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="succeeded">
|
||||
<description summary="configuration changes succeeded">
|
||||
Sent after the compositor has successfully applied the changes or
|
||||
tested them.
|
||||
|
||||
Upon receiving this event, the client should destroy this object.
|
||||
|
||||
If the current configuration has changed, events to describe the changes
|
||||
will be sent followed by a wlr_output_manager.done event.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="failed">
|
||||
<description summary="configuration changes failed">
|
||||
Sent if the compositor rejects the changes or failed to apply them. The
|
||||
compositor should revert any changes made by the apply request that
|
||||
triggered this event.
|
||||
|
||||
Upon receiving this event, the client should destroy this object.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="cancelled">
|
||||
<description summary="configuration has been cancelled">
|
||||
Sent if the compositor cancels the configuration because the state of an
|
||||
output changed and the client has outdated information (e.g. after an
|
||||
output has been hotplugged).
|
||||
|
||||
The client can create a new configuration with a newer serial and try
|
||||
again.
|
||||
|
||||
Upon receiving this event, the client should destroy this object.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the output configuration">
|
||||
Using this request a client can tell the compositor that it is not going
|
||||
to use the configuration object anymore. Any changes to the outputs
|
||||
that have not been applied will be discarded.
|
||||
|
||||
This request also destroys wlr_output_configuration_head objects created
|
||||
via this object.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_output_configuration_head_v1" version="4">
|
||||
<description summary="head configuration">
|
||||
This object is used by the client to update a single head's configuration.
|
||||
|
||||
It is a protocol error to set the same property twice.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="already_set" value="1" summary="property has already been set"/>
|
||||
<entry name="invalid_mode" value="2" summary="mode doesn't belong to head"/>
|
||||
<entry name="invalid_custom_mode" value="3" summary="mode is invalid"/>
|
||||
<entry name="invalid_transform" value="4" summary="transform value outside enum"/>
|
||||
<entry name="invalid_scale" value="5" summary="scale negative or zero"/>
|
||||
<entry name="invalid_adaptive_sync_state" value="6" since="4"
|
||||
summary="invalid enum value used in the set_adaptive_sync request"/>
|
||||
</enum>
|
||||
|
||||
<request name="set_mode">
|
||||
<description summary="set the mode">
|
||||
This request sets the head's mode.
|
||||
</description>
|
||||
<arg name="mode" type="object" interface="zwlr_output_mode_v1"/>
|
||||
</request>
|
||||
|
||||
<request name="set_custom_mode">
|
||||
<description summary="set a custom mode">
|
||||
This request assigns a custom mode to the head. The size is given in
|
||||
physical hardware units of the output device. If set to zero, the
|
||||
refresh rate is unspecified.
|
||||
|
||||
It is a protocol error to set both a mode and a custom mode.
|
||||
</description>
|
||||
<arg name="width" type="int" summary="width of the mode in hardware units"/>
|
||||
<arg name="height" type="int" summary="height of the mode in hardware units"/>
|
||||
<arg name="refresh" type="int" summary="vertical refresh rate in mHz or zero"/>
|
||||
</request>
|
||||
|
||||
<request name="set_position">
|
||||
<description summary="set the position">
|
||||
This request sets the head's position in the global compositor space.
|
||||
</description>
|
||||
<arg name="x" type="int" summary="x position in the global compositor space"/>
|
||||
<arg name="y" type="int" summary="y position in the global compositor space"/>
|
||||
</request>
|
||||
|
||||
<request name="set_transform">
|
||||
<description summary="set the transform">
|
||||
This request sets the head's transform.
|
||||
</description>
|
||||
<arg name="transform" type="int" enum="wl_output.transform"/>
|
||||
</request>
|
||||
|
||||
<request name="set_scale">
|
||||
<description summary="set the scale">
|
||||
This request sets the head's scale.
|
||||
</description>
|
||||
<arg name="scale" type="fixed"/>
|
||||
</request>
|
||||
|
||||
<!-- Version 4 additions -->
|
||||
|
||||
<request name="set_adaptive_sync" since="4">
|
||||
<description summary="enable/disable adaptive sync">
|
||||
This request enables/disables adaptive sync. Adaptive sync is also
|
||||
known as Variable Refresh Rate or VRR.
|
||||
</description>
|
||||
<arg name="state" type="uint" enum="zwlr_output_head_v1.adaptive_sync_state"/>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
152
protocols/wlr-virtual-pointer-unstable-v1.xml
Normal file
@@ -0,0 +1,152 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="wlr_virtual_pointer_unstable_v1">
|
||||
<copyright>
|
||||
Copyright © 2019 Josef Gajdusek
|
||||
|
||||
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
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) 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
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="zwlr_virtual_pointer_v1" version="2">
|
||||
<description summary="virtual pointer">
|
||||
This protocol allows clients to emulate a physical pointer device. The
|
||||
requests are mostly mirror opposites of those specified in wl_pointer.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="invalid_axis" value="0"
|
||||
summary="client sent invalid axis enumeration value" />
|
||||
<entry name="invalid_axis_source" value="1"
|
||||
summary="client sent invalid axis source enumeration value" />
|
||||
</enum>
|
||||
|
||||
<request name="motion">
|
||||
<description summary="pointer relative motion event">
|
||||
The pointer has moved by a relative amount to the previous request.
|
||||
|
||||
Values are in the global compositor space.
|
||||
</description>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="dx" type="fixed" summary="displacement on the x-axis"/>
|
||||
<arg name="dy" type="fixed" summary="displacement on the y-axis"/>
|
||||
</request>
|
||||
|
||||
<request name="motion_absolute">
|
||||
<description summary="pointer absolute motion event">
|
||||
The pointer has moved in an absolute coordinate frame.
|
||||
|
||||
Value of x can range from 0 to x_extent, value of y can range from 0
|
||||
to y_extent.
|
||||
</description>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="x" type="uint" summary="position on the x-axis"/>
|
||||
<arg name="y" type="uint" summary="position on the y-axis"/>
|
||||
<arg name="x_extent" type="uint" summary="extent of the x-axis"/>
|
||||
<arg name="y_extent" type="uint" summary="extent of the y-axis"/>
|
||||
</request>
|
||||
|
||||
<request name="button">
|
||||
<description summary="button event">
|
||||
A button was pressed or released.
|
||||
</description>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="button" type="uint" summary="button that produced the event"/>
|
||||
<arg name="state" type="uint" enum="wl_pointer.button_state" summary="physical state of the button"/>
|
||||
</request>
|
||||
|
||||
<request name="axis">
|
||||
<description summary="axis event">
|
||||
Scroll and other axis requests.
|
||||
</description>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="axis" type="uint" enum="wl_pointer.axis" summary="axis type"/>
|
||||
<arg name="value" type="fixed" summary="length of vector in touchpad coordinates"/>
|
||||
</request>
|
||||
|
||||
<request name="frame">
|
||||
<description summary="end of a pointer event sequence">
|
||||
Indicates the set of events that logically belong together.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="axis_source">
|
||||
<description summary="axis source event">
|
||||
Source information for scroll and other axis.
|
||||
</description>
|
||||
<arg name="axis_source" type="uint" enum="wl_pointer.axis_source" summary="source of the axis event"/>
|
||||
</request>
|
||||
|
||||
<request name="axis_stop">
|
||||
<description summary="axis stop event">
|
||||
Stop notification for scroll and other axes.
|
||||
</description>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="axis" type="uint" enum="wl_pointer.axis" summary="the axis stopped with this event"/>
|
||||
</request>
|
||||
|
||||
<request name="axis_discrete">
|
||||
<description summary="axis click event">
|
||||
Discrete step information for scroll and other axes.
|
||||
|
||||
This event allows the client to extend data normally sent using the axis
|
||||
event with discrete value.
|
||||
</description>
|
||||
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||
<arg name="axis" type="uint" enum="wl_pointer.axis" summary="axis type"/>
|
||||
<arg name="value" type="fixed" summary="length of vector in touchpad coordinates"/>
|
||||
<arg name="discrete" type="int" summary="number of steps"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor" since="1">
|
||||
<description summary="destroy the virtual pointer object"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_virtual_pointer_manager_v1" version="2">
|
||||
<description summary="virtual pointer manager">
|
||||
This object allows clients to create individual virtual pointer objects.
|
||||
</description>
|
||||
|
||||
<request name="create_virtual_pointer">
|
||||
<description summary="Create a new virtual pointer">
|
||||
Creates a new virtual pointer. The optional seat is a suggestion to the
|
||||
compositor.
|
||||
</description>
|
||||
<arg name="seat" type="object" interface="wl_seat" allow-null="true"/>
|
||||
<arg name="id" type="new_id" interface="zwlr_virtual_pointer_v1"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor" since="1">
|
||||
<description summary="destroy the virtual pointer manager"/>
|
||||
</request>
|
||||
|
||||
<!-- Version 2 additions -->
|
||||
<request name="create_virtual_pointer_with_output" since="2">
|
||||
<description summary="Create a new virtual pointer">
|
||||
Creates a new virtual pointer. The seat and the output arguments are
|
||||
optional. If the seat argument is set, the compositor should assign the
|
||||
input device to the requested seat. If the output argument is set, the
|
||||
compositor should map the input device to the requested output.
|
||||
</description>
|
||||
<arg name="seat" type="object" interface="wl_seat" allow-null="true"/>
|
||||
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
||||
<arg name="id" type="new_id" interface="zwlr_virtual_pointer_v1"/>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
@@ -1,13 +1,13 @@
|
||||
#!/bin/sh
|
||||
cp -fr ./src/version.h.in ./src/version.h
|
||||
|
||||
HASH=$(git rev-parse HEAD)
|
||||
BRANCH=$(git branch --show-current)
|
||||
MESSAGE=$(git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1 | sed -e 's/#//g' -e 's/\"//g')
|
||||
DATE=$(git show ${GIT_COMMIT_HASH} --no-patch --format=%cd --date=local)
|
||||
DIRTY=$(git diff-index --quiet HEAD -- || echo dirty)
|
||||
TAG=$(git describe --tags)
|
||||
COMMITS=$(git rev-list --count HEAD)
|
||||
HASH=${HASH-$(git rev-parse HEAD)}
|
||||
BRANCH=${BRANCH-$(git branch --show-current)}
|
||||
MESSAGE=${MESSAGE-$(git show | head -n 5 | tail -n 1 | sed -e 's/#//g' -e 's/\"//g')}
|
||||
DATE=${DATE-$(git show --no-patch --format=%cd --date=local)}
|
||||
DIRTY=${DIRTY-$(git diff-index --quiet HEAD -- || echo dirty)}
|
||||
TAG=${TAG-$(git describe --tags)}
|
||||
COMMITS=${COMMITS-$(git rev-list --count HEAD)}
|
||||
|
||||
sed -i -e "s#@HASH@#${HASH}#" ./src/version.h
|
||||
sed -i -e "s#@BRANCH@#${BRANCH}#" ./src/version.h
|
||||
|
@@ -1,20 +1,13 @@
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 1190876d..0e7573f9 100755
|
||||
index f26a5c3c..3dfef333 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -110,6 +110,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET
|
||||
cairo pango pangocairo pixman-1
|
||||
libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm
|
||||
hyprlang>=0.3.2 hyprcursor
|
||||
+ libffi
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||
@@ -130,6 +131,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
@@ -143,6 +143,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
message(STATUS "Enabling ASan")
|
||||
|
||||
target_link_libraries(Hyprland asan)
|
||||
+ target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/libwayland-server.a)
|
||||
+ pkg_check_modules(ffidep REQUIRED IMPORTED_TARGET libffi)
|
||||
+ target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/libwayland-server.a PkgConfig::ffidep)
|
||||
target_compile_options(Hyprland PUBLIC -fsanitize=address)
|
||||
endif()
|
||||
|
||||
|
1964
src/Compositor.cpp
@@ -3,6 +3,7 @@
|
||||
#include <memory>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include "defines.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
@@ -29,8 +30,14 @@
|
||||
#include "plugins/PluginSystem.hpp"
|
||||
#include "helpers/Watchdog.hpp"
|
||||
|
||||
#include <aquamarine/backend/Backend.hpp>
|
||||
#include <aquamarine/output/Output.hpp>
|
||||
|
||||
class CWLSurfaceResource;
|
||||
|
||||
enum eManagersInitStage {
|
||||
STAGE_PRIORITY = 0,
|
||||
STAGE_BASICINIT,
|
||||
STAGE_LATE
|
||||
};
|
||||
|
||||
@@ -39,203 +46,157 @@ class CCompositor {
|
||||
CCompositor();
|
||||
~CCompositor();
|
||||
|
||||
// ------------------ WLR BASICS ------------------ //
|
||||
wl_display* m_sWLDisplay;
|
||||
wl_event_loop* m_sWLEventLoop;
|
||||
wlr_backend* m_sWLRBackend;
|
||||
wlr_session* m_sWLRSession;
|
||||
wlr_renderer* m_sWLRRenderer;
|
||||
wlr_allocator* m_sWLRAllocator;
|
||||
wlr_compositor* m_sWLRCompositor;
|
||||
wlr_subcompositor* m_sWLRSubCompositor;
|
||||
wlr_data_device_manager* m_sWLRDataDevMgr;
|
||||
wlr_drm* m_sWRLDRM;
|
||||
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
|
||||
wlr_xdg_activation_v1* m_sWLRXDGActivation;
|
||||
wlr_output_layout* m_sWLROutputLayout;
|
||||
wlr_idle_notifier_v1* m_sWLRIdleNotifier;
|
||||
wlr_layer_shell_v1* m_sWLRLayerShell;
|
||||
wlr_xdg_shell* m_sWLRXDGShell;
|
||||
wlr_cursor* m_sWLRCursor;
|
||||
wlr_virtual_keyboard_manager_v1* m_sWLRVKeyboardMgr;
|
||||
wlr_output_manager_v1* m_sWLROutputMgr;
|
||||
wlr_presentation* m_sWLRPresentation;
|
||||
wlr_keyboard_shortcuts_inhibit_manager_v1* m_sWLRKbShInhibitMgr;
|
||||
wlr_egl* m_sWLREGL;
|
||||
int m_iDRMFD;
|
||||
wlr_pointer_constraints_v1* m_sWLRPointerConstraints;
|
||||
wlr_relative_pointer_manager_v1* m_sWLRRelPointerMgr;
|
||||
wlr_server_decoration_manager* m_sWLRServerDecoMgr;
|
||||
wlr_xdg_decoration_manager_v1* m_sWLRXDGDecoMgr;
|
||||
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
|
||||
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
|
||||
wlr_tablet_manager_v2* m_sWLRTabletManager;
|
||||
wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
|
||||
wlr_idle_inhibit_manager_v1* m_sWLRIdleInhibitMgr;
|
||||
wlr_pointer_gestures_v1* m_sWLRPointerGestures;
|
||||
wlr_output_power_manager_v1* m_sWLROutputPowerMgr;
|
||||
wlr_input_method_manager_v2* m_sWLRIMEMgr;
|
||||
wlr_text_input_manager_v3* m_sWLRTextInputMgr;
|
||||
wlr_xdg_activation_v1* m_sWLRActivation;
|
||||
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;
|
||||
wlr_backend* m_sWLRHeadlessBackend;
|
||||
wlr_session_lock_manager_v1* m_sWLRSessionLockMgr;
|
||||
wlr_gamma_control_manager_v1* m_sWLRGammaCtrlMgr;
|
||||
wlr_cursor_shape_manager_v1* m_sWLRCursorShapeMgr;
|
||||
wlr_tearing_control_manager_v1* m_sWLRTearingControlMgr;
|
||||
// ------------------------------------------------- //
|
||||
int m_iDRMFD = -1;
|
||||
bool m_bInitialized = false;
|
||||
SP<Aquamarine::CBackend> m_pAqBackend;
|
||||
|
||||
std::string m_szHyprTempDataRoot = "";
|
||||
|
||||
std::string m_szWLDisplaySocket = "";
|
||||
std::string m_szInstanceSignature = "";
|
||||
std::string m_szInstancePath = "";
|
||||
std::string m_szCurrentSplash = "error";
|
||||
|
||||
std::vector<std::shared_ptr<CMonitor>> m_vMonitors;
|
||||
std::vector<std::shared_ptr<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
|
||||
std::vector<std::unique_ptr<CWindow>> m_vWindows;
|
||||
std::vector<SP<CMonitor>> m_vMonitors;
|
||||
std::vector<SP<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
|
||||
std::vector<PHLWINDOW> m_vWindows;
|
||||
std::vector<PHLLS> m_vLayers;
|
||||
std::vector<PHLWORKSPACE> m_vWorkspaces;
|
||||
std::vector<CWindow*> m_vWindowsFadingOut;
|
||||
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
|
||||
std::vector<PHLWINDOWREF> m_vWindowsFadingOut;
|
||||
std::vector<PHLLSREF> m_vSurfacesFadingOut;
|
||||
|
||||
std::unordered_map<std::string, uint64_t> m_mMonitorIDMap;
|
||||
std::unordered_map<std::string, MONITORID> m_mMonitorIDMap;
|
||||
|
||||
void initServer();
|
||||
void initServer(std::string socketName, int socketFd);
|
||||
void startCompositor();
|
||||
void stopCompositor();
|
||||
void cleanup();
|
||||
void createLockFile();
|
||||
void removeLockFile();
|
||||
void bumpNofile();
|
||||
void restoreNofile();
|
||||
|
||||
wlr_surface* m_pLastFocus = nullptr;
|
||||
CWindow* m_pLastWindow = nullptr;
|
||||
CMonitor* m_pLastMonitor = nullptr;
|
||||
WP<CWLSurfaceResource> m_pLastFocus;
|
||||
PHLWINDOWREF m_pLastWindow;
|
||||
WP<CMonitor> m_pLastMonitor;
|
||||
|
||||
std::vector<CWindow*> m_vWindowFocusHistory; // first element is the most recently focused.
|
||||
|
||||
SSeat m_sSeat;
|
||||
std::vector<PHLWINDOWREF> m_vWindowFocusHistory; // first element is the most recently focused.
|
||||
|
||||
bool m_bReadyToProcess = false;
|
||||
bool m_bSessionActive = true;
|
||||
bool m_bDPMSStateON = true;
|
||||
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
|
||||
bool m_bNextIsUnsafe = false; // because wlroots
|
||||
bool m_bNextIsUnsafe = false;
|
||||
CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
|
||||
bool m_bExitTriggered = false; // For exit dispatcher
|
||||
bool m_bIsShuttingDown = false;
|
||||
bool m_bFinalRequests = false;
|
||||
bool m_bDesktopEnvSet = false;
|
||||
bool m_bEnableXwayland = true;
|
||||
|
||||
// ------------------------------------------------- //
|
||||
|
||||
CMonitor* getMonitorFromID(const int&);
|
||||
CMonitor* getMonitorFromID(const MONITORID&);
|
||||
CMonitor* getMonitorFromName(const std::string&);
|
||||
CMonitor* getMonitorFromDesc(const std::string&);
|
||||
CMonitor* getMonitorFromCursor();
|
||||
CMonitor* getMonitorFromVector(const Vector2D&);
|
||||
void removeWindowFromVectorSafe(CWindow*);
|
||||
void focusWindow(CWindow*, wlr_surface* pSurface = nullptr);
|
||||
void focusSurface(wlr_surface*, CWindow* pWindowOwner = nullptr);
|
||||
bool windowExists(CWindow*);
|
||||
bool windowValidMapped(CWindow*);
|
||||
void removeWindowFromVectorSafe(PHLWINDOW);
|
||||
void focusWindow(PHLWINDOW, SP<CWLSurfaceResource> pSurface = nullptr);
|
||||
void focusSurface(SP<CWLSurfaceResource>, PHLWINDOW pWindowOwner = nullptr);
|
||||
bool monitorExists(CMonitor*);
|
||||
CWindow* vectorToWindowUnified(const Vector2D&, uint8_t properties, CWindow* pIgnoreWindow = nullptr);
|
||||
wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector<std::unique_ptr<SLayerSurface>>*, Vector2D*, SLayerSurface**);
|
||||
wlr_surface* vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, SLayerSurface**);
|
||||
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
|
||||
Vector2D vectorToSurfaceLocal(const Vector2D&, CWindow*, wlr_surface*);
|
||||
CMonitor* getMonitorFromOutput(wlr_output*);
|
||||
CMonitor* getRealMonitorFromOutput(wlr_output*);
|
||||
CWindow* getWindowFromSurface(wlr_surface*);
|
||||
CWindow* getWindowFromHandle(uint32_t);
|
||||
CWindow* getWindowFromZWLRHandle(wl_resource*);
|
||||
PHLWINDOW vectorToWindowUnified(const Vector2D&, uint8_t properties, PHLWINDOW pIgnoreWindow = nullptr);
|
||||
SP<CWLSurfaceResource> vectorToLayerSurface(const Vector2D&, std::vector<PHLLSREF>*, Vector2D*, PHLLS*);
|
||||
SP<CWLSurfaceResource> vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, PHLLS*);
|
||||
SP<CWLSurfaceResource> vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl);
|
||||
Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, SP<CWLSurfaceResource>);
|
||||
CMonitor* getMonitorFromOutput(SP<Aquamarine::IOutput>);
|
||||
CMonitor* getRealMonitorFromOutput(SP<Aquamarine::IOutput>);
|
||||
PHLWINDOW getWindowFromSurface(SP<CWLSurfaceResource>);
|
||||
PHLWINDOW getWindowFromHandle(uint32_t);
|
||||
bool isWorkspaceVisible(PHLWORKSPACE);
|
||||
PHLWORKSPACE getWorkspaceByID(const int&);
|
||||
bool isWorkspaceVisibleNotCovered(PHLWORKSPACE);
|
||||
PHLWORKSPACE getWorkspaceByID(const WORKSPACEID&);
|
||||
PHLWORKSPACE getWorkspaceByName(const std::string&);
|
||||
PHLWORKSPACE getWorkspaceByString(const std::string&);
|
||||
void sanityCheckWorkspaces();
|
||||
void updateWorkspaceWindowDecos(const int&);
|
||||
void updateWorkspaceSpecialRenderData(const int&);
|
||||
int getWindowsOnWorkspace(const int& id, std::optional<bool> onlyTiled = {});
|
||||
int getGroupsOnWorkspace(const int& id, std::optional<bool> onlyTiled = {});
|
||||
CWindow* getUrgentWindow();
|
||||
bool hasUrgentWindowOnWorkspace(const int&);
|
||||
CWindow* getFirstWindowOnWorkspace(const int&);
|
||||
CWindow* getTopLeftWindowOnWorkspace(const int&);
|
||||
CWindow* getFullscreenWindowOnWorkspace(const int&);
|
||||
bool doesSeatAcceptInput(wlr_surface*);
|
||||
bool isWindowActive(CWindow*);
|
||||
void changeWindowZOrder(CWindow*, bool);
|
||||
void cleanupFadingOut(const int& monid);
|
||||
CWindow* getWindowInDirection(CWindow*, char);
|
||||
CWindow* getNextWindowOnWorkspace(CWindow*, bool focusableOnly = false, std::optional<bool> floating = {});
|
||||
CWindow* getPrevWindowOnWorkspace(CWindow*, bool focusableOnly = false, std::optional<bool> floating = {});
|
||||
int getNextAvailableNamedWorkspace();
|
||||
void updateWorkspaceWindowDecos(const WORKSPACEID&);
|
||||
void updateWorkspaceWindowData(const WORKSPACEID&);
|
||||
int getWindowsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
int getGroupsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
|
||||
PHLWINDOW getUrgentWindow();
|
||||
bool hasUrgentWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getFirstWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getTopLeftWindowOnWorkspace(const WORKSPACEID&);
|
||||
PHLWINDOW getFullscreenWindowOnWorkspace(const WORKSPACEID&);
|
||||
bool isWindowActive(PHLWINDOW);
|
||||
void changeWindowZOrder(PHLWINDOW, bool);
|
||||
void cleanupFadingOut(const MONITORID& monid);
|
||||
PHLWINDOW getWindowInDirection(PHLWINDOW, char);
|
||||
PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
|
||||
PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
|
||||
WORKSPACEID getNextAvailableNamedWorkspace();
|
||||
bool isPointOnAnyMonitor(const Vector2D&);
|
||||
bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr);
|
||||
CMonitor* getMonitorInDirection(const char&);
|
||||
CMonitor* getMonitorInDirection(CMonitor*, const char&);
|
||||
void updateAllWindowsAnimatedDecorationValues();
|
||||
void updateWorkspaceWindows(const int64_t& id);
|
||||
void updateWindowAnimatedDecorationValues(CWindow*);
|
||||
int getNextAvailableMonitorID(std::string const& name);
|
||||
void updateWorkspaceWindows(const WORKSPACEID& id);
|
||||
void updateWindowAnimatedDecorationValues(PHLWINDOW);
|
||||
MONITORID getNextAvailableMonitorID(std::string const& name);
|
||||
void moveWorkspaceToMonitor(PHLWORKSPACE, CMonitor*, bool noWarpCursor = false);
|
||||
void swapActiveWorkspaces(CMonitor*, CMonitor*);
|
||||
CMonitor* getMonitorFromString(const std::string&);
|
||||
bool workspaceIDOutOfBounds(const int64_t&);
|
||||
void setWindowFullscreen(CWindow*, bool, eFullscreenMode mode = FULLSCREEN_INVALID);
|
||||
bool workspaceIDOutOfBounds(const WORKSPACEID&);
|
||||
void setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE);
|
||||
void setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE);
|
||||
void setWindowFullscreenState(const PHLWINDOW PWINDOW, const sFullscreenState state);
|
||||
void changeWindowFullscreenModeInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON);
|
||||
void changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON);
|
||||
void updateFullscreenFadeOnWorkspace(PHLWORKSPACE);
|
||||
CWindow* getX11Parent(CWindow*);
|
||||
void scheduleFrameForMonitor(CMonitor*);
|
||||
void addToFadingOutSafe(SLayerSurface*);
|
||||
void addToFadingOutSafe(CWindow*);
|
||||
CWindow* getWindowByRegex(const std::string&);
|
||||
PHLWINDOW getX11Parent(PHLWINDOW);
|
||||
void scheduleFrameForMonitor(CMonitor*, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN);
|
||||
void addToFadingOutSafe(PHLLS);
|
||||
void removeFromFadingOutSafe(PHLLS);
|
||||
void addToFadingOutSafe(PHLWINDOW);
|
||||
PHLWINDOW getWindowByRegex(const std::string&);
|
||||
void warpCursorTo(const Vector2D&, bool force = false);
|
||||
SLayerSurface* getLayerSurfaceFromWlr(wlr_layer_surface_v1*);
|
||||
SLayerSurface* getLayerSurfaceFromSurface(wlr_surface*);
|
||||
void closeWindow(CWindow*);
|
||||
PHLLS getLayerSurfaceFromSurface(SP<CWLSurfaceResource>);
|
||||
void closeWindow(PHLWINDOW);
|
||||
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
|
||||
void forceReportSizesToWindowsOnWorkspace(const int&);
|
||||
PHLWORKSPACE createNewWorkspace(const int&, const int&, const std::string& name = ""); // will be deleted next frame if left empty and unfocused!
|
||||
void renameWorkspace(const int&, const std::string& name = "");
|
||||
void forceReportSizesToWindowsOnWorkspace(const WORKSPACEID&);
|
||||
PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "",
|
||||
bool isEmpty = true); // will be deleted next frame if left empty and unfocused!
|
||||
void renameWorkspace(const WORKSPACEID&, const std::string& name = "");
|
||||
void setActiveMonitor(CMonitor*);
|
||||
bool isWorkspaceSpecial(const int&);
|
||||
int getNewSpecialID();
|
||||
bool isWorkspaceSpecial(const WORKSPACEID&);
|
||||
WORKSPACEID getNewSpecialID();
|
||||
void performUserChecks();
|
||||
void moveWindowToWorkspaceSafe(CWindow* pWindow, PHLWORKSPACE pWorkspace);
|
||||
CWindow* getForceFocus();
|
||||
void notifyIdleActivity();
|
||||
void setIdleActivityInhibit(bool inhibit);
|
||||
void moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace);
|
||||
PHLWINDOW getForceFocus();
|
||||
void arrangeMonitors();
|
||||
void enterUnsafeState();
|
||||
void leaveUnsafeState();
|
||||
void setPreferredScaleForSurface(wlr_surface* pSurface, double scale);
|
||||
void setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform);
|
||||
void setPreferredScaleForSurface(SP<CWLSurfaceResource> pSurface, double scale);
|
||||
void setPreferredTransformForSurface(SP<CWLSurfaceResource> pSurface, wl_output_transform transform);
|
||||
void updateSuspendedStates();
|
||||
PHLWINDOW windowForCPointer(CWindow*);
|
||||
void onNewMonitor(SP<Aquamarine::IOutput> output);
|
||||
|
||||
std::string explicitConfigPath;
|
||||
|
||||
private:
|
||||
void initAllSignals();
|
||||
void removeAllSignals();
|
||||
void cleanEnvironment();
|
||||
void setRandomSplash();
|
||||
void initManagers(eManagersInitStage stage);
|
||||
void prepareFallbackOutput();
|
||||
|
||||
uint64_t m_iHyprlandPID = 0;
|
||||
wl_event_source* m_critSigSource = nullptr;
|
||||
rlimit m_sOriginalNofile = {0};
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CCompositor> g_pCompositor;
|
||||
|
||||
// For XWayland
|
||||
inline std::map<std::string, xcb_atom_t> HYPRATOMS = {HYPRATOM("_NET_WM_WINDOW_TYPE"),
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_NORMAL"),
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_DOCK"),
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_DIALOG"),
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_UTILITY"),
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLBAR"),
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_SPLASH"),
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_MENU"),
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"),
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_POPUP_MENU"),
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLTIP"),
|
||||
HYPRATOM("_NET_WM_WINDOW_TYPE_NOTIFICATION"),
|
||||
HYPRATOM("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE"),
|
||||
HYPRATOM("_NET_SUPPORTING_WM_CHECK"),
|
||||
HYPRATOM("_NET_WM_NAME"),
|
||||
HYPRATOM("UTF8_STRING")};
|
||||
|
@@ -1,7 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "helpers/Vector2D.hpp"
|
||||
#include "helpers/math/Math.hpp"
|
||||
#include <functional>
|
||||
#include <any>
|
||||
#include <hyprutils/math/Box.hpp>
|
||||
|
||||
using namespace Hyprutils::Math;
|
||||
|
||||
enum eIcons {
|
||||
ICON_WARNING = 0,
|
||||
@@ -37,29 +41,6 @@ struct SCallbackInfo {
|
||||
bool cancelled = false; /* on cancellable events, will cancel the event. */
|
||||
};
|
||||
|
||||
struct SWindowDecorationExtents {
|
||||
Vector2D topLeft;
|
||||
Vector2D bottomRight;
|
||||
|
||||
//
|
||||
SWindowDecorationExtents operator*(const double& scale) const {
|
||||
return SWindowDecorationExtents{topLeft * scale, bottomRight * scale};
|
||||
}
|
||||
|
||||
SWindowDecorationExtents round() {
|
||||
return {topLeft.round(), bottomRight.round()};
|
||||
}
|
||||
|
||||
bool operator==(const SWindowDecorationExtents& other) const {
|
||||
return topLeft == other.topLeft && bottomRight == other.bottomRight;
|
||||
}
|
||||
|
||||
void addExtents(const SWindowDecorationExtents& other) {
|
||||
topLeft = topLeft.getComponentMax(other.topLeft);
|
||||
bottomRight = bottomRight.getComponentMax(other.bottomRight);
|
||||
}
|
||||
};
|
||||
|
||||
enum eHyprCtlOutputFormat {
|
||||
FORMAT_NORMAL = 0,
|
||||
FORMAT_JSON
|
||||
@@ -71,4 +52,8 @@ struct SHyprCtlCommand {
|
||||
std::function<std::string(eHyprCtlOutputFormat, std::string)> fn;
|
||||
};
|
||||
|
||||
typedef int64_t WINDOWID;
|
||||
typedef int64_t MONITORID;
|
||||
typedef int64_t WORKSPACEID;
|
||||
|
||||
typedef std::function<void(void*, SCallbackInfo&, std::any)> HOOK_CALLBACK_FN;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/VarList.hpp"
|
||||
#include "../helpers/varlist/VarList.hpp"
|
||||
#include <vector>
|
||||
|
||||
enum eConfigValueDataTypes {
|
||||
@@ -20,11 +20,11 @@ class ICustomConfigValueData {
|
||||
|
||||
class CGradientValueData : public ICustomConfigValueData {
|
||||
public:
|
||||
CGradientValueData(){};
|
||||
CGradientValueData() {};
|
||||
CGradientValueData(CColor col) {
|
||||
m_vColors.push_back(col);
|
||||
};
|
||||
virtual ~CGradientValueData(){};
|
||||
virtual ~CGradientValueData() {};
|
||||
|
||||
virtual eConfigValueDataTypes getDataType() {
|
||||
return CVD_TYPE_GRADIENT;
|
||||
@@ -67,11 +67,11 @@ class CGradientValueData : public ICustomConfigValueData {
|
||||
|
||||
class CCssGapData : public ICustomConfigValueData {
|
||||
public:
|
||||
CCssGapData() : top(0), right(0), bottom(0), left(0){};
|
||||
CCssGapData(int64_t global) : top(global), right(global), bottom(global), left(global){};
|
||||
CCssGapData(int64_t vertical, int64_t horizontal) : top(vertical), right(horizontal), bottom(vertical), left(horizontal){};
|
||||
CCssGapData(int64_t top, int64_t horizontal, int64_t bottom) : top(top), right(horizontal), bottom(bottom), left(horizontal){};
|
||||
CCssGapData(int64_t top, int64_t right, int64_t bottom, int64_t left) : top(top), right(right), bottom(bottom), left(left){};
|
||||
CCssGapData() : top(0), right(0), bottom(0), left(0) {};
|
||||
CCssGapData(int64_t global) : top(global), right(global), bottom(global), left(global) {};
|
||||
CCssGapData(int64_t vertical, int64_t horizontal) : top(vertical), right(horizontal), bottom(vertical), left(horizontal) {};
|
||||
CCssGapData(int64_t top, int64_t horizontal, int64_t bottom) : top(top), right(horizontal), bottom(bottom), left(horizontal) {};
|
||||
CCssGapData(int64_t top, int64_t right, int64_t bottom, int64_t left) : top(top), right(right), bottom(bottom), left(left) {};
|
||||
|
||||
/* Css like directions */
|
||||
int64_t top;
|
||||
|
1369
src/config/ConfigDescriptions.hpp
Normal file
@@ -6,6 +6,7 @@
|
||||
#include "../debug/Log.hpp"
|
||||
#include <unordered_map>
|
||||
#include "../defines.hpp"
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
@@ -15,8 +16,9 @@
|
||||
#include <xf86drmMode.h>
|
||||
#include "../helpers/WLClasses.hpp"
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "../helpers/VarList.hpp"
|
||||
#include "../helpers/varlist/VarList.hpp"
|
||||
#include "../desktop/Window.hpp"
|
||||
#include "../desktop/LayerSurface.hpp"
|
||||
|
||||
#include "defaultConfig.hpp"
|
||||
#include "ConfigDataValues.hpp"
|
||||
@@ -28,22 +30,20 @@
|
||||
|
||||
#define HANDLE void*
|
||||
|
||||
class CWindow;
|
||||
|
||||
struct SWorkspaceRule {
|
||||
std::string monitor = "";
|
||||
std::string workspaceString = "";
|
||||
std::string workspaceName = "";
|
||||
int workspaceId = -1;
|
||||
WORKSPACEID workspaceId = -1;
|
||||
bool isDefault = false;
|
||||
bool isPersistent = false;
|
||||
std::optional<CCssGapData> gapsIn;
|
||||
std::optional<CCssGapData> gapsOut;
|
||||
std::optional<int64_t> borderSize;
|
||||
std::optional<int> border;
|
||||
std::optional<int> rounding;
|
||||
std::optional<int> decorate;
|
||||
std::optional<int> shadow;
|
||||
std::optional<bool> decorate;
|
||||
std::optional<bool> noRounding;
|
||||
std::optional<bool> noBorder;
|
||||
std::optional<bool> noShadow;
|
||||
std::optional<std::string> onCreatedEmptyRunCmd;
|
||||
std::optional<std::string> defaultName;
|
||||
std::map<std::string, std::string> layoutopts;
|
||||
@@ -84,6 +84,70 @@ struct SExecRequestedRule {
|
||||
uint64_t iPid = 0;
|
||||
};
|
||||
|
||||
enum eConfigOptionType : uint16_t {
|
||||
CONFIG_OPTION_BOOL = 0,
|
||||
CONFIG_OPTION_INT = 1, /* e.g. 0/1/2*/
|
||||
CONFIG_OPTION_FLOAT = 2,
|
||||
CONFIG_OPTION_STRING_SHORT = 3, /* e.g. "auto" */
|
||||
CONFIG_OPTION_STRING_LONG = 4, /* e.g. a command */
|
||||
CONFIG_OPTION_COLOR = 5,
|
||||
CONFIG_OPTION_CHOICE = 6, /* e.g. "one", "two", "three" */
|
||||
CONFIG_OPTION_GRADIENT = 7,
|
||||
CONFIG_OPTION_VECTOR = 8,
|
||||
};
|
||||
|
||||
enum eConfigOptionFlags : uint32_t {
|
||||
CONFIG_OPTION_FLAG_PERCENTAGE = (1 << 0),
|
||||
};
|
||||
|
||||
struct SConfigOptionDescription {
|
||||
|
||||
struct SBoolData {
|
||||
bool value = false;
|
||||
};
|
||||
|
||||
struct SRangeData {
|
||||
int value = 0, min = 0, max = 2;
|
||||
};
|
||||
|
||||
struct SFloatData {
|
||||
float value = 0, min = 0, max = 100;
|
||||
};
|
||||
|
||||
struct SStringData {
|
||||
std::string value;
|
||||
};
|
||||
|
||||
struct SColorData {
|
||||
CColor color;
|
||||
};
|
||||
|
||||
struct SChoiceData {
|
||||
int firstIndex = 0;
|
||||
std::string choices; // comma-separated
|
||||
};
|
||||
|
||||
struct SGradientData {
|
||||
std::string gradient;
|
||||
};
|
||||
|
||||
struct SVectorData {
|
||||
Vector2D vec, min, max;
|
||||
};
|
||||
|
||||
std::string value; // e.g. general:gaps_in
|
||||
std::string description;
|
||||
std::string specialCategory; // if value is special (e.g. device:abc) value will be abc and special device
|
||||
bool specialKey = false;
|
||||
eConfigOptionType type = CONFIG_OPTION_BOOL;
|
||||
uint32_t flags = 0; // eConfigOptionFlags
|
||||
|
||||
std::string jsonify() const;
|
||||
|
||||
//
|
||||
std::variant<SBoolData, SRangeData, SFloatData, SStringData, SColorData, SChoiceData, SGradientData, SVectorData> data;
|
||||
};
|
||||
|
||||
class CConfigManager {
|
||||
public:
|
||||
CConfigManager();
|
||||
@@ -102,8 +166,8 @@ class CConfigManager {
|
||||
void* const* getConfigValuePtr(const std::string&);
|
||||
Hyprlang::CConfigValue* getHyprlangConfigValuePtr(const std::string& name, const std::string& specialCat = "");
|
||||
void onPluginLoadUnload(const std::string& name, bool load);
|
||||
static std::string getConfigDir();
|
||||
static std::string getMainConfigPath();
|
||||
const std::string getConfigString();
|
||||
|
||||
SMonitorRule getMonitorRuleFor(const CMonitor&);
|
||||
SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace);
|
||||
@@ -113,8 +177,10 @@ class CConfigManager {
|
||||
std::string getBoundMonitorStringForWS(const std::string&);
|
||||
const std::deque<SWorkspaceRule>& getAllWorkspaceRules();
|
||||
|
||||
std::vector<SWindowRule> getMatchingRules(CWindow*, bool dynamic = true, bool shadowExec = false);
|
||||
std::vector<SLayerRule> getMatchingRules(SLayerSurface*);
|
||||
std::vector<SWindowRule> getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false);
|
||||
std::vector<SLayerRule> getMatchingRules(PHLLS);
|
||||
|
||||
const std::vector<SConfigOptionDescription>& getAllDescriptions();
|
||||
|
||||
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
|
||||
|
||||
@@ -126,11 +192,11 @@ class CConfigManager {
|
||||
|
||||
// no-op when done.
|
||||
void dispatchExecOnce();
|
||||
void dispatchExecShutdown();
|
||||
|
||||
void performMonitorReload();
|
||||
bool m_bWantsMonitorReload = false;
|
||||
bool m_bForceReload = false;
|
||||
bool m_bNoMonitorReload = false;
|
||||
void appendMonitorRule(const SMonitorRule&);
|
||||
bool replaceMonitorRule(const SMonitorRule&);
|
||||
void ensureMonitorStatus();
|
||||
void ensureVRR(CMonitor* pMonitor = nullptr);
|
||||
|
||||
@@ -148,6 +214,7 @@ class CConfigManager {
|
||||
// keywords
|
||||
std::optional<std::string> handleRawExec(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleExecOnce(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleExecShutdown(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleMonitor(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleBind(const std::string&, const std::string&);
|
||||
std::optional<std::string> handleUnbind(const std::string&, const std::string&);
|
||||
@@ -166,6 +233,37 @@ class CConfigManager {
|
||||
|
||||
std::string configCurrentPath;
|
||||
|
||||
std::unordered_map<std::string, std::function<CWindowOverridableVar<bool>*(PHLWINDOW)>> mbWindowProperties = {
|
||||
{"allowsinput", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.allowsInput; }},
|
||||
{"dimaround", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.dimAround; }},
|
||||
{"decorate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.decorate; }},
|
||||
{"focusonactivate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.focusOnActivate; }},
|
||||
{"keepaspectratio", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.keepAspectRatio; }},
|
||||
{"nearestneighbor", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.nearestNeighbor; }},
|
||||
{"noanim", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noAnim; }},
|
||||
{"noblur", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noBlur; }},
|
||||
{"noborder", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noBorder; }},
|
||||
{"nodim", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noDim; }},
|
||||
{"nofocus", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noFocus; }},
|
||||
{"nomaxsize", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noMaxSize; }},
|
||||
{"norounding", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noRounding; }},
|
||||
{"noshadow", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noShadow; }},
|
||||
{"noshortcutsinhibit", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noShortcutsInhibit; }},
|
||||
{"opaque", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.opaque; }},
|
||||
{"forcergbx", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.RGBX; }},
|
||||
{"syncfullscreen", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.syncFullscreen; }},
|
||||
{"immediate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.tearing; }},
|
||||
{"xray", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.xray; }},
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, std::function<CWindowOverridableVar<int>*(PHLWINDOW)>> miWindowProperties = {
|
||||
{"rounding", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.rounding; }}, {"bordersize", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.borderSize; }}};
|
||||
|
||||
bool m_bWantsMonitorReload = false;
|
||||
bool m_bForceReload = false;
|
||||
bool m_bNoMonitorReload = false;
|
||||
bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking
|
||||
|
||||
private:
|
||||
std::unique_ptr<Hyprlang::CConfig> m_pConfig;
|
||||
|
||||
@@ -193,6 +291,7 @@ class CConfigManager {
|
||||
bool firstExecDispatched = false;
|
||||
bool m_bManualCrashInitiated = false;
|
||||
std::deque<std::string> firstExecRequests;
|
||||
std::deque<std::string> finalExecRequests;
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
|
||||
std::string m_szConfigErrors = "";
|
||||
@@ -202,9 +301,11 @@ class CConfigManager {
|
||||
void updateBlurredLS(const std::string&, const bool);
|
||||
void setDefaultAnimationVars();
|
||||
std::optional<std::string> resetHLConfig();
|
||||
std::optional<std::string> verifyConfigExists();
|
||||
static std::optional<std::string> generateConfig(std::string configPath);
|
||||
static std::optional<std::string> verifyConfigExists();
|
||||
void postConfigReload(const Hyprlang::CParseResult& result);
|
||||
void reload();
|
||||
SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&);
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
||||
|
@@ -11,7 +11,7 @@ template <typename T>
|
||||
class CConfigValue {
|
||||
public:
|
||||
CConfigValue(const std::string& val) {
|
||||
const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val.c_str());
|
||||
const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val);
|
||||
|
||||
p_ = PVHYPRLANG->getDataStaticPtr();
|
||||
|
||||
|
@@ -9,87 +9,116 @@ inline const std::string AUTOCONFIG = R"#(
|
||||
# OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
|
||||
# #######################################################################################
|
||||
|
||||
#
|
||||
autogenerated = 1 # remove this line to remove the warning
|
||||
|
||||
# This is an example Hyprland config file.
|
||||
# Refer to the wiki for more information.
|
||||
# https://wiki.hyprland.org/Configuring/Configuring-Hyprland/
|
||||
|
||||
# Please note not all available settings / options are set here.
|
||||
# For a full list, see the wiki
|
||||
#
|
||||
|
||||
autogenerated = 1 # remove this line to remove the warning
|
||||
# You can split this configuration into multiple files
|
||||
# Create your files separately and then link them to this file like this:
|
||||
# source = ~/.config/hypr/myColors.conf
|
||||
|
||||
|
||||
################
|
||||
### MONITORS ###
|
||||
################
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Monitors/
|
||||
monitor=,preferred,auto,auto
|
||||
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||
###################
|
||||
### MY PROGRAMS ###
|
||||
###################
|
||||
|
||||
# Execute your favorite apps at launch
|
||||
# exec-once = waybar & hyprpaper & firefox
|
||||
|
||||
# Source a file (multi-file configs)
|
||||
# source = ~/.config/hypr/myColors.conf
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/
|
||||
|
||||
# Set programs that you use
|
||||
$terminal = kitty
|
||||
$fileManager = dolphin
|
||||
$menu = wofi --show drun
|
||||
|
||||
# Some default env vars.
|
||||
|
||||
#################
|
||||
### AUTOSTART ###
|
||||
#################
|
||||
|
||||
# Autostart necessary processes (like notifications daemons, status bars, etc.)
|
||||
# Or execute your favorite apps at launch like this:
|
||||
|
||||
# exec-once = $terminal
|
||||
# exec-once = nm-applet &
|
||||
# exec-once = waybar & hyprpaper & firefox
|
||||
|
||||
|
||||
#############################
|
||||
### ENVIRONMENT VARIABLES ###
|
||||
#############################
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Environment-variables/
|
||||
|
||||
env = XCURSOR_SIZE,24
|
||||
env = QT_QPA_PLATFORMTHEME,qt5ct # change to qt6ct if you have that
|
||||
env = HYPRCURSOR_SIZE,24
|
||||
|
||||
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
|
||||
input {
|
||||
kb_layout = us
|
||||
kb_variant =
|
||||
kb_model =
|
||||
kb_options =
|
||||
kb_rules =
|
||||
|
||||
follow_mouse = 1
|
||||
#####################
|
||||
### LOOK AND FEEL ###
|
||||
#####################
|
||||
|
||||
touchpad {
|
||||
natural_scroll = no
|
||||
}
|
||||
|
||||
sensitivity = 0 # -1.0 to 1.0, 0 means no modification.
|
||||
}
|
||||
# Refer to https://wiki.hyprland.org/Configuring/Variables/
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#general
|
||||
general {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
|
||||
gaps_in = 5
|
||||
gaps_out = 20
|
||||
|
||||
border_size = 2
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#variable-types for info about colors
|
||||
col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
|
||||
col.inactive_border = rgba(595959aa)
|
||||
|
||||
layout = dwindle
|
||||
# Set to true enable resizing windows by clicking and dragging on borders and gaps
|
||||
resize_on_border = false
|
||||
|
||||
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
|
||||
allow_tearing = false
|
||||
|
||||
layout = dwindle
|
||||
}
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#decoration
|
||||
decoration {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
|
||||
rounding = 10
|
||||
|
||||
# Change transparency of focused and unfocused windows
|
||||
active_opacity = 1.0
|
||||
inactive_opacity = 1.0
|
||||
|
||||
drop_shadow = true
|
||||
shadow_range = 4
|
||||
shadow_render_power = 3
|
||||
col.shadow = rgba(1a1a1aee)
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#blur
|
||||
blur {
|
||||
enabled = true
|
||||
size = 3
|
||||
passes = 1
|
||||
}
|
||||
|
||||
drop_shadow = yes
|
||||
shadow_range = 4
|
||||
shadow_render_power = 3
|
||||
col.shadow = rgba(1a1a1aee)
|
||||
vibrancy = 0.1696
|
||||
}
|
||||
}
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#animations
|
||||
animations {
|
||||
enabled = yes
|
||||
enabled = true
|
||||
|
||||
# Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
|
||||
# Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
|
||||
|
||||
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
|
||||
|
||||
@@ -101,25 +130,48 @@ animations {
|
||||
animation = workspaces, 1, 6, default
|
||||
}
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
|
||||
dwindle {
|
||||
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
|
||||
pseudotile = yes # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
||||
preserve_split = yes # you probably want this
|
||||
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
||||
preserve_split = true # You probably want this
|
||||
}
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
|
||||
master {
|
||||
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
|
||||
new_is_master = true
|
||||
}
|
||||
|
||||
gestures {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
workspace_swipe = off
|
||||
new_status = master
|
||||
}
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#misc
|
||||
misc {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
|
||||
disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :(
|
||||
}
|
||||
|
||||
|
||||
#############
|
||||
### INPUT ###
|
||||
#############
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#input
|
||||
input {
|
||||
kb_layout = us
|
||||
kb_variant =
|
||||
kb_model =
|
||||
kb_options =
|
||||
kb_rules =
|
||||
|
||||
follow_mouse = 1
|
||||
|
||||
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
|
||||
|
||||
touchpad {
|
||||
natural_scroll = false
|
||||
}
|
||||
}
|
||||
|
||||
# https://wiki.hyprland.org/Configuring/Variables/#gestures
|
||||
gestures {
|
||||
workspace_swipe = false
|
||||
}
|
||||
|
||||
# Example per-device config
|
||||
@@ -129,16 +181,13 @@ device {
|
||||
sensitivity = -0.5
|
||||
}
|
||||
|
||||
# Example windowrule v1
|
||||
# windowrule = float, ^(kitty)$
|
||||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||
|
||||
###################
|
||||
### KEYBINDINGS ###
|
||||
###################
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||
$mainMod = SUPER
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/
|
||||
$mainMod = SUPER # Sets "Windows" key as main modifier
|
||||
|
||||
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
|
||||
bind = $mainMod, Q, exec, $terminal
|
||||
@@ -191,4 +240,27 @@ bind = $mainMod, mouse_up, workspace, e-1
|
||||
# Move/resize windows with mainMod + LMB/RMB and dragging
|
||||
bindm = $mainMod, mouse:272, movewindow
|
||||
bindm = $mainMod, mouse:273, resizewindow
|
||||
|
||||
# Laptop multimedia keys for volume and LCD brightness
|
||||
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
|
||||
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
|
||||
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
|
||||
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
|
||||
bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
|
||||
bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
|
||||
|
||||
##############################
|
||||
### WINDOWS AND WORKSPACES ###
|
||||
##############################
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||
# See https://wiki.hyprland.org/Configuring/Workspace-Rules/ for workspace rules
|
||||
|
||||
# Example windowrule v1
|
||||
# windowrule = float, ^(kitty)$
|
||||
|
||||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
|
||||
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
|
||||
)#";
|
||||
|
@@ -1,19 +1,20 @@
|
||||
#include "CrashReporter.hpp"
|
||||
#include <random>
|
||||
#include <fcntl.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <fstream>
|
||||
#include <signal.h>
|
||||
#include <link.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <filesystem>
|
||||
|
||||
#include "../plugins/PluginSystem.hpp"
|
||||
#include "../signal-safe.hpp"
|
||||
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
std::string getRandomMessage() {
|
||||
|
||||
const std::vector<std::string> MESSAGES = {"Sorry, didn't mean to...",
|
||||
static char const* const MESSAGES[] = {"Sorry, didn't mean to...",
|
||||
"This was an accident, I swear!",
|
||||
"Calm down, it was a misinput! MISINPUT!",
|
||||
"Oops",
|
||||
@@ -28,32 +29,112 @@ std::string getRandomMessage() {
|
||||
"I hope you didn't have any unsaved progress.",
|
||||
"All these computers..."};
|
||||
|
||||
std::random_device dev;
|
||||
std::mt19937 engine(dev());
|
||||
std::uniform_int_distribution<> distribution(0, MESSAGES.size() - 1);
|
||||
// <random> is not async-signal-safe, fake it with time(NULL) instead
|
||||
char const* getRandomMessage() {
|
||||
return MESSAGES[time(NULL) % (sizeof(MESSAGES) / sizeof(MESSAGES[0]))];
|
||||
}
|
||||
|
||||
return MESSAGES[distribution(engine)];
|
||||
[[noreturn]] inline void exit_with_error(char const* err) {
|
||||
write(STDERR_FILENO, err, strlen(err));
|
||||
// perror() is not signal-safe, but we use it here
|
||||
// because if the crash-handler already crashed, it can't get any worse.
|
||||
perror("");
|
||||
abort();
|
||||
}
|
||||
|
||||
void CrashReporter::createAndSaveCrash(int sig) {
|
||||
int reportFd;
|
||||
|
||||
// get the backtrace
|
||||
const int PID = getpid();
|
||||
// We're in the signal handler, so we *only* have stack memory.
|
||||
// To save as much stack memory as possible,
|
||||
// destroy things as soon as possible.
|
||||
{
|
||||
MaxLengthCString<255> reportPath;
|
||||
|
||||
std::string finalCrashReport = "";
|
||||
const auto HOME = sig_getenv("HOME");
|
||||
const auto CACHE_HOME = sig_getenv("XDG_CACHE_HOME");
|
||||
|
||||
if (CACHE_HOME && CACHE_HOME[0] != '\0') {
|
||||
reportPath += CACHE_HOME;
|
||||
reportPath += "/hyprland";
|
||||
} else if (HOME && HOME[0] != '\0') {
|
||||
reportPath += HOME;
|
||||
reportPath += "/.cache/hyprland";
|
||||
} else {
|
||||
exit_with_error("$CACHE_HOME and $HOME not set, nowhere to report crash\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int ret = mkdir(reportPath.get_str(), S_IRWXU);
|
||||
//__asm__("int $3");
|
||||
if (ret < 0 && errno != EEXIST) {
|
||||
exit_with_error("failed to mkdir() crash report directory\n");
|
||||
}
|
||||
reportPath += "/hyprlandCrashReport";
|
||||
reportPath.write_num(getpid());
|
||||
reportPath += ".txt";
|
||||
|
||||
{
|
||||
BufFileWriter<64> stderr(2);
|
||||
stderr += "Hyprland has crashed :( Consult the crash report at ";
|
||||
if (!reportPath.boundsExceeded()) {
|
||||
stderr += reportPath.get_str();
|
||||
} else {
|
||||
stderr += "[ERROR: Crash report path does not fit into memory! Check if your $CACHE_HOME/$HOME is too deeply nested. Max 255 characters.]";
|
||||
}
|
||||
stderr += " for more information.\n";
|
||||
stderr.flush();
|
||||
}
|
||||
|
||||
reportFd = open(reportPath.get_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
|
||||
if (reportFd < 0) {
|
||||
exit_with_error("Failed to open crash report path for writing");
|
||||
}
|
||||
}
|
||||
BufFileWriter<512> finalCrashReport(reportFd);
|
||||
|
||||
finalCrashReport += "--------------------------------------------\n Hyprland Crash Report\n--------------------------------------------\n";
|
||||
finalCrashReport += getRandomMessage() + "\n\n";
|
||||
finalCrashReport += getRandomMessage();
|
||||
finalCrashReport += "\n\n";
|
||||
|
||||
finalCrashReport += std::format("Hyprland received signal {} ({})\n\n", sig, (const char*)strsignal(sig));
|
||||
finalCrashReport += "Hyprland received signal ";
|
||||
finalCrashReport.writeNum(sig);
|
||||
finalCrashReport += '(';
|
||||
finalCrashReport += sig_strsignal(sig);
|
||||
finalCrashReport += ")\nVersion: ";
|
||||
finalCrashReport += GIT_COMMIT_HASH;
|
||||
finalCrashReport += "\nTag: ";
|
||||
finalCrashReport += GIT_TAG;
|
||||
finalCrashReport += "\nDate: ";
|
||||
finalCrashReport += GIT_COMMIT_DATE;
|
||||
finalCrashReport += "\nFlags:\n";
|
||||
#ifdef LEGACY_RENDERER
|
||||
finalCrashReport += "legacyrenderer\n";
|
||||
#endif
|
||||
#ifndef ISDEBUG
|
||||
finalCrashReport += "debug\n";
|
||||
#endif
|
||||
#ifdef NO_XWAYLAND
|
||||
finalCrashReport += "no xwayland\n";
|
||||
#endif
|
||||
finalCrashReport += "\n";
|
||||
|
||||
finalCrashReport += std::format("Version: {}\nTag: {}\n\n", GIT_COMMIT_HASH, GIT_TAG);
|
||||
|
||||
if (g_pPluginSystem && !g_pPluginSystem->getAllPlugins().empty()) {
|
||||
if (g_pPluginSystem && g_pPluginSystem->pluginCount() > 0) {
|
||||
finalCrashReport += "Hyprland seems to be running with plugins. This crash might not be Hyprland's fault.\nPlugins:\n";
|
||||
|
||||
for (auto& p : g_pPluginSystem->getAllPlugins()) {
|
||||
finalCrashReport += std::format("\t{} ({}) {}\n", p->name, p->author, p->version);
|
||||
size_t count = g_pPluginSystem->pluginCount();
|
||||
CPlugin* plugins[count];
|
||||
g_pPluginSystem->sig_getPlugins(plugins, count);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
auto p = plugins[i];
|
||||
finalCrashReport += '\t';
|
||||
finalCrashReport += p->name;
|
||||
finalCrashReport += " (";
|
||||
finalCrashReport += p->author;
|
||||
finalCrashReport += ") ";
|
||||
finalCrashReport += p->version;
|
||||
finalCrashReport += '\n';
|
||||
}
|
||||
|
||||
finalCrashReport += "\n\n";
|
||||
@@ -61,21 +142,36 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
|
||||
finalCrashReport += "System info:\n";
|
||||
|
||||
{
|
||||
struct utsname unameInfo;
|
||||
uname(&unameInfo);
|
||||
|
||||
finalCrashReport += std::format("\tSystem name: {}\n\tNode name: {}\n\tRelease: {}\n\tVersion: {}\n\n", std::string{unameInfo.sysname}, std::string{unameInfo.nodename},
|
||||
std::string{unameInfo.release}, std::string{unameInfo.version});
|
||||
finalCrashReport += "\tSystem name: ";
|
||||
finalCrashReport += unameInfo.sysname;
|
||||
finalCrashReport += "\n\tNode name: ";
|
||||
finalCrashReport += unameInfo.nodename;
|
||||
finalCrashReport += "\n\tRelease: ";
|
||||
finalCrashReport += unameInfo.release;
|
||||
finalCrashReport += "\n\tVersion: ";
|
||||
finalCrashReport += unameInfo.version;
|
||||
finalCrashReport += "\n\n";
|
||||
}
|
||||
|
||||
finalCrashReport += "GPU:\n\t";
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga");
|
||||
finalCrashReport.writeCmdOutput("pciconf -lv | fgrep -A4 vga");
|
||||
#else
|
||||
const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA");
|
||||
finalCrashReport.writeCmdOutput("lspci -vnn | grep VGA");
|
||||
#endif
|
||||
|
||||
finalCrashReport += "GPU:\n\t" + GPUINFO;
|
||||
finalCrashReport += "\n\nos-release:\n";
|
||||
finalCrashReport.writeCmdOutput("cat /etc/os-release | sed 's/^/\t/'");
|
||||
|
||||
finalCrashReport += std::format("\n\nos-release:\n\t{}\n\n\n", replaceInString(execAndGet("cat /etc/os-release"), "\n", "\n\t"));
|
||||
// dladdr1()/backtrace_symbols()/this entire section allocates, and hence is NOT async-signal-safe.
|
||||
// Make sure that we save the current known crash report information,
|
||||
// so that if we are caught in a deadlock during a call to malloc(),
|
||||
// there is still something to debug from.
|
||||
finalCrashReport.flush();
|
||||
|
||||
finalCrashReport += "Backtrace:\n";
|
||||
|
||||
@@ -132,7 +228,10 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
std::stringstream ssin(ADDR2LINE);
|
||||
|
||||
for (size_t i = 0; i < CALLSTACK.size(); ++i) {
|
||||
finalCrashReport += std::format("\t#{} | {}", i, CALLSTACK[i].desc);
|
||||
finalCrashReport += "\t#";
|
||||
finalCrashReport.writeNum(i);
|
||||
finalCrashReport += " | ";
|
||||
finalCrashReport += CALLSTACK[i].desc;
|
||||
std::string functionInfo;
|
||||
std::string fileLineInfo;
|
||||
std::getline(ssin, functionInfo);
|
||||
@@ -142,32 +241,5 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
|
||||
finalCrashReport += "\n\nLog tail:\n";
|
||||
|
||||
finalCrashReport += Debug::rollingLog.substr(Debug::rollingLog.find("\n") + 1);
|
||||
|
||||
const auto HOME = getenv("HOME");
|
||||
const auto CACHE_HOME = getenv("XDG_CACHE_HOME");
|
||||
|
||||
if (!HOME)
|
||||
return;
|
||||
|
||||
std::ofstream ofs;
|
||||
std::string reportDir;
|
||||
|
||||
if (!CACHE_HOME || std::string(CACHE_HOME).empty())
|
||||
reportDir = std::string(HOME) + "/.cache/hyprland";
|
||||
else
|
||||
reportDir = std::string(CACHE_HOME) + "/hyprland";
|
||||
|
||||
if (!std::filesystem::exists(reportDir))
|
||||
std::filesystem::create_directory(reportDir);
|
||||
const auto path = reportDir + "/hyprlandCrashReport" + std::to_string(PID) + ".txt";
|
||||
|
||||
ofs.open(path, std::ios::trunc);
|
||||
|
||||
ofs << finalCrashReport;
|
||||
|
||||
ofs.close();
|
||||
|
||||
Debug::disableStdout = false;
|
||||
Debug::log(CRIT, "Hyprland has crashed :( Consult the crash report at {} for more information.", path);
|
||||
finalCrashReport += std::string_view(Debug::rollingLog).substr(Debug::rollingLog.find("\n") + 1);
|
||||
}
|
||||
|
@@ -8,22 +8,30 @@
|
||||
class CHyprCtl {
|
||||
public:
|
||||
CHyprCtl();
|
||||
~CHyprCtl();
|
||||
|
||||
std::string makeDynamicCall(const std::string& input);
|
||||
std::shared_ptr<SHyprCtlCommand> registerCommand(SHyprCtlCommand cmd);
|
||||
void unregisterCommand(const std::shared_ptr<SHyprCtlCommand>& cmd);
|
||||
SP<SHyprCtlCommand> registerCommand(SHyprCtlCommand cmd);
|
||||
void unregisterCommand(const SP<SHyprCtlCommand>& cmd);
|
||||
std::string getReply(std::string);
|
||||
|
||||
int m_iSocketFD = -1;
|
||||
|
||||
struct {
|
||||
bool all = false;
|
||||
bool sysInfoConfig = false;
|
||||
} m_sCurrentRequestParams;
|
||||
|
||||
static std::string getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format);
|
||||
static std::string getWorkspaceData(PHLWORKSPACE w, eHyprCtlOutputFormat format);
|
||||
static std::string getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format);
|
||||
|
||||
private:
|
||||
void startHyprCtlSocket();
|
||||
|
||||
std::vector<std::shared_ptr<SHyprCtlCommand>> m_vCommands;
|
||||
std::vector<SP<SHyprCtlCommand>> m_vCommands;
|
||||
wl_event_source* m_eventSource = nullptr;
|
||||
std::string m_socketPath;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHyprCtl> g_pHyprCtl;
|
@@ -1,8 +1,14 @@
|
||||
#include <pango/pangocairo.h>
|
||||
#include "HyprDebugOverlay.hpp"
|
||||
#include "config/ConfigValue.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
|
||||
m_dLastRenderTimes.push_back(µs / 1000.f);
|
||||
CHyprDebugOverlay::CHyprDebugOverlay() {
|
||||
m_pTexture = makeShared<CTexture>();
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) {
|
||||
m_dLastRenderTimes.push_back(durationUs / 1000.f);
|
||||
|
||||
if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate)
|
||||
m_dLastRenderTimes.pop_front();
|
||||
@@ -11,8 +17,8 @@ void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
|
||||
m_pMonitor = pMonitor;
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) {
|
||||
m_dLastRenderTimesNoOverlay.push_back(µs / 1000.f);
|
||||
void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) {
|
||||
m_dLastRenderTimesNoOverlay.push_back(durationUs / 1000.f);
|
||||
|
||||
if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate)
|
||||
m_dLastRenderTimesNoOverlay.pop_front();
|
||||
@@ -33,7 +39,7 @@ void CHyprMonitorDebugOverlay::frameData(CMonitor* pMonitor) {
|
||||
m_pMonitor = pMonitor;
|
||||
|
||||
// anim data too
|
||||
const auto PMONITORFORTICKS = g_pHyprRenderer->m_pMostHzMonitor ? g_pHyprRenderer->m_pMostHzMonitor : g_pCompositor->m_pLastMonitor;
|
||||
const auto PMONITORFORTICKS = g_pHyprRenderer->m_pMostHzMonitor ? g_pHyprRenderer->m_pMostHzMonitor : g_pCompositor->m_pLastMonitor.get();
|
||||
if (PMONITORFORTICKS) {
|
||||
if (m_dLastAnimationTicks.size() > (long unsigned int)PMONITORFORTICKS->refreshRate)
|
||||
m_dLastAnimationTicks.pop_front();
|
||||
@@ -47,16 +53,11 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
if (!m_pMonitor)
|
||||
return 0;
|
||||
|
||||
int yOffset = offset;
|
||||
cairo_text_extents_t cairoExtents;
|
||||
float maxX = 0;
|
||||
std::string text = "";
|
||||
|
||||
// get avg fps
|
||||
float avgFrametime = 0;
|
||||
float maxFrametime = 0;
|
||||
float minFrametime = 9999;
|
||||
for (auto& ft : m_dLastFrametimes) {
|
||||
for (auto const& ft : m_dLastFrametimes) {
|
||||
if (ft > maxFrametime)
|
||||
maxFrametime = ft;
|
||||
if (ft < minFrametime)
|
||||
@@ -69,7 +70,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
float avgRenderTime = 0;
|
||||
float maxRenderTime = 0;
|
||||
float minRenderTime = 9999;
|
||||
for (auto& rt : m_dLastRenderTimes) {
|
||||
for (auto const& rt : m_dLastRenderTimes) {
|
||||
if (rt > maxRenderTime)
|
||||
maxRenderTime = rt;
|
||||
if (rt < minRenderTime)
|
||||
@@ -82,7 +83,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
float avgRenderTimeNoOverlay = 0;
|
||||
float maxRenderTimeNoOverlay = 0;
|
||||
float minRenderTimeNoOverlay = 9999;
|
||||
for (auto& rt : m_dLastRenderTimesNoOverlay) {
|
||||
for (auto const& rt : m_dLastRenderTimesNoOverlay) {
|
||||
if (rt > maxRenderTimeNoOverlay)
|
||||
maxRenderTimeNoOverlay = rt;
|
||||
if (rt < minRenderTimeNoOverlay)
|
||||
@@ -95,7 +96,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
float avgAnimMgrTick = 0;
|
||||
float maxAnimMgrTick = 0;
|
||||
float minAnimMgrTick = 9999;
|
||||
for (auto& at : m_dLastAnimationTicks) {
|
||||
for (auto const& at : m_dLastAnimationTicks) {
|
||||
if (at > maxAnimMgrTick)
|
||||
maxAnimMgrTick = at;
|
||||
if (at < minAnimMgrTick)
|
||||
@@ -108,20 +109,46 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
const float FPS = 1.f / (avgFrametime / 1000.f); // frametimes are in ms
|
||||
const float idealFPS = m_dLastFrametimes.size();
|
||||
|
||||
cairo_select_font_face(g_pDebugOverlay->m_pCairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||
static auto fontFamily = CConfigValue<std::string>("misc:font_family");
|
||||
PangoLayout* layoutText = pango_cairo_create_layout(g_pDebugOverlay->m_pCairo);
|
||||
PangoFontDescription* pangoFD = pango_font_description_new();
|
||||
|
||||
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
|
||||
pango_font_description_set_family(pangoFD, (*fontFamily).c_str());
|
||||
pango_font_description_set_style(pangoFD, PANGO_STYLE_NORMAL);
|
||||
pango_font_description_set_weight(pangoFD, PANGO_WEIGHT_NORMAL);
|
||||
|
||||
float maxTextW = 0;
|
||||
int fontSize = 0;
|
||||
auto cr = g_pDebugOverlay->m_pCairo;
|
||||
|
||||
auto showText = [cr, layoutText, pangoFD, &maxTextW, &fontSize](const char* text, int size) {
|
||||
if (fontSize != size) {
|
||||
pango_font_description_set_absolute_size(pangoFD, size * PANGO_SCALE);
|
||||
pango_layout_set_font_description(layoutText, pangoFD);
|
||||
fontSize = size;
|
||||
}
|
||||
|
||||
pango_layout_set_text(layoutText, text, -1);
|
||||
pango_cairo_show_layout(cr, layoutText);
|
||||
|
||||
int textW = 0, textH = 0;
|
||||
pango_layout_get_size(layoutText, &textW, &textH);
|
||||
textW /= PANGO_SCALE;
|
||||
textH /= PANGO_SCALE;
|
||||
if (textW > maxTextW)
|
||||
maxTextW = textW;
|
||||
|
||||
// move to next line
|
||||
cairo_rel_move_to(cr, 0, fontSize + 1);
|
||||
};
|
||||
|
||||
const int MARGIN_TOP = 8;
|
||||
const int MARGIN_LEFT = 4;
|
||||
cairo_move_to(cr, MARGIN_LEFT, MARGIN_TOP + offset);
|
||||
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
|
||||
|
||||
yOffset += 10;
|
||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||
text = m_pMonitor->szName;
|
||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||
if (cairoExtents.width > maxX)
|
||||
maxX = cairoExtents.width;
|
||||
|
||||
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 16);
|
||||
std::string text;
|
||||
showText(m_pMonitor->szName.c_str(), 10);
|
||||
|
||||
if (FPS > idealFPS * 0.95f)
|
||||
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 0.2f, 1.f, 0.2f, 1.f);
|
||||
@@ -130,65 +157,43 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
else
|
||||
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 0.2f, 0.2f, 1.f);
|
||||
|
||||
yOffset += 17;
|
||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||
text = std::format("{} FPS", (int)FPS);
|
||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||
if (cairoExtents.width > maxX)
|
||||
maxX = cairoExtents.width;
|
||||
showText(text.c_str(), 16);
|
||||
|
||||
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
|
||||
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
|
||||
|
||||
yOffset += 11;
|
||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||
text = std::format("Avg Frametime: {:.2f}ms (var {:.2f}ms)", avgFrametime, varFrametime);
|
||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||
if (cairoExtents.width > maxX)
|
||||
maxX = cairoExtents.width;
|
||||
showText(text.c_str(), 10);
|
||||
|
||||
yOffset += 11;
|
||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||
text = std::format("Avg Rendertime: {:.2f}ms (var {:.2f}ms)", avgRenderTime, varRenderTime);
|
||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||
if (cairoExtents.width > maxX)
|
||||
maxX = cairoExtents.width;
|
||||
showText(text.c_str(), 10);
|
||||
|
||||
yOffset += 11;
|
||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||
text = std::format("Avg Rendertime (No Overlay): {:.2f}ms (var {:.2f}ms)", avgRenderTimeNoOverlay, varRenderTimeNoOverlay);
|
||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||
if (cairoExtents.width > maxX)
|
||||
maxX = cairoExtents.width;
|
||||
showText(text.c_str(), 10);
|
||||
|
||||
yOffset += 11;
|
||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||
text = std::format("Avg Anim Tick: {:.2f}ms (var {:.2f}ms) ({:.2f} TPS)", avgAnimMgrTick, varAnimMgrTick, 1.0 / (avgAnimMgrTick / 1000.0));
|
||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||
if (cairoExtents.width > maxX)
|
||||
maxX = cairoExtents.width;
|
||||
showText(text.c_str(), 10);
|
||||
|
||||
yOffset += 11;
|
||||
pango_font_description_free(pangoFD);
|
||||
g_object_unref(layoutText);
|
||||
|
||||
double posX = 0, posY = 0;
|
||||
cairo_get_current_point(cr, &posX, &posY);
|
||||
|
||||
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
|
||||
m_wbLastDrawnBox = {(int)g_pCompositor->m_vMonitors.front()->vecPosition.x, (int)g_pCompositor->m_vMonitors.front()->vecPosition.y + offset - 1, (int)maxX + 2,
|
||||
yOffset - offset + 2};
|
||||
m_wbLastDrawnBox = {(int)g_pCompositor->m_vMonitors.front()->vecPosition.x + MARGIN_LEFT - 1, (int)g_pCompositor->m_vMonitors.front()->vecPosition.y + offset + MARGIN_TOP - 1,
|
||||
(int)maxTextW + 2, posY - offset - MARGIN_TOP + 2};
|
||||
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
|
||||
|
||||
return yOffset - offset;
|
||||
return posY - offset;
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
|
||||
m_mMonitorOverlays[pMonitor].renderData(pMonitor, µs);
|
||||
void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) {
|
||||
m_mMonitorOverlays[pMonitor].renderData(pMonitor, durationUs);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) {
|
||||
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, µs);
|
||||
void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) {
|
||||
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, durationUs);
|
||||
}
|
||||
|
||||
void CHyprDebugOverlay::frameData(CMonitor* pMonitor) {
|
||||
@@ -212,7 +217,7 @@ void CHyprDebugOverlay::draw() {
|
||||
|
||||
// draw the things
|
||||
int offsetY = 0;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
offsetY += m_mMonitorOverlays[m.get()].draw(offsetY);
|
||||
offsetY += 5; // for padding between mons
|
||||
}
|
||||
@@ -221,8 +226,8 @@ void CHyprDebugOverlay::draw() {
|
||||
|
||||
// copy the data to an OpenGL texture we have
|
||||
const auto DATA = cairo_image_surface_get_data(m_pCairoSurface);
|
||||
m_tTexture.allocate();
|
||||
glBindTexture(GL_TEXTURE_2D, m_tTexture.m_iTexID);
|
||||
m_pTexture->allocate();
|
||||
glBindTexture(GL_TEXTURE_2D, m_pTexture->m_iTexID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
@@ -234,5 +239,5 @@ void CHyprDebugOverlay::draw() {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
|
||||
CBox pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
|
||||
g_pHyprOpenGL->renderTexture(m_pTexture, &pMonBox, 1.f);
|
||||
}
|
||||
|
@@ -13,8 +13,8 @@ class CHyprMonitorDebugOverlay {
|
||||
public:
|
||||
int draw(int offset);
|
||||
|
||||
void renderData(CMonitor* pMonitor, float µs);
|
||||
void renderDataNoOverlay(CMonitor* pMonitor, float µs);
|
||||
void renderData(CMonitor* pMonitor, float durationUs);
|
||||
void renderDataNoOverlay(CMonitor* pMonitor, float durationUs);
|
||||
void frameData(CMonitor* pMonitor);
|
||||
|
||||
private:
|
||||
@@ -31,9 +31,10 @@ class CHyprMonitorDebugOverlay {
|
||||
|
||||
class CHyprDebugOverlay {
|
||||
public:
|
||||
CHyprDebugOverlay();
|
||||
void draw();
|
||||
void renderData(CMonitor*, float µs);
|
||||
void renderDataNoOverlay(CMonitor*, float µs);
|
||||
void renderData(CMonitor*, float durationUs);
|
||||
void renderDataNoOverlay(CMonitor*, float durationUs);
|
||||
void frameData(CMonitor*);
|
||||
|
||||
private:
|
||||
@@ -42,7 +43,7 @@ class CHyprDebugOverlay {
|
||||
cairo_surface_t* m_pCairoSurface = nullptr;
|
||||
cairo_t* m_pCairo = nullptr;
|
||||
|
||||
CTexture m_tTexture;
|
||||
SP<CTexture> m_pTexture;
|
||||
|
||||
friend class CHyprMonitorDebugOverlay;
|
||||
friend class CHyprRenderer;
|
||||
|
@@ -1,39 +1,37 @@
|
||||
#include <numeric>
|
||||
#include <pango/pangocairo.h>
|
||||
#include "HyprNotificationOverlay.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include <pango/pangocairo.h>
|
||||
#include "../config/ConfigValue.hpp"
|
||||
|
||||
inline auto iconBackendFromLayout(PangoLayout* layout) {
|
||||
// preference: Nerd > FontAwesome > text
|
||||
auto eIconBackendChecks = std::array<eIconBackend, 2>{ICONS_BACKEND_NF, ICONS_BACKEND_FA};
|
||||
for (auto iconID : eIconBackendChecks) {
|
||||
auto iconsText = std::accumulate(ICONS_ARRAY[iconID].begin(), ICONS_ARRAY[iconID].end(), std::string());
|
||||
pango_layout_set_text(layout, iconsText.c_str(), -1);
|
||||
if (pango_layout_get_unknown_glyphs_count(layout) == 0)
|
||||
return iconID;
|
||||
}
|
||||
return ICONS_BACKEND_NONE;
|
||||
}
|
||||
|
||||
CHyprNotificationOverlay::CHyprNotificationOverlay() {
|
||||
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) {
|
||||
static auto P = g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) {
|
||||
if (m_dNotifications.size() == 0)
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->damageBox(&m_bLastDamage);
|
||||
});
|
||||
|
||||
// check for the icon backend
|
||||
std::string fonts = execAndGet("fc-list");
|
||||
std::string fontsLower = fonts;
|
||||
std::transform(fontsLower.begin(), fontsLower.end(), fontsLower.begin(), [&](char& i) { return std::tolower(i); });
|
||||
m_pTexture = makeShared<CTexture>();
|
||||
}
|
||||
|
||||
size_t index = 0;
|
||||
|
||||
if (index = fontsLower.find("nerd"); index != std::string::npos) {
|
||||
m_eIconBackend = ICONS_BACKEND_NF;
|
||||
} else if (index = fontsLower.find("font awesome"); index != std::string::npos) {
|
||||
m_eIconBackend = ICONS_BACKEND_FA;
|
||||
} else if (index = fontsLower.find("fontawesome"); index != std::string::npos) {
|
||||
m_eIconBackend = ICONS_BACKEND_FA;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto LASTNEWLINE = fonts.find_last_of('\n', index);
|
||||
const auto COLON = fonts.find(':', LASTNEWLINE);
|
||||
const auto COMMA = fonts.find(',', COLON);
|
||||
const auto NEWLINE = fonts.find('\n', COLON);
|
||||
const auto LASTCHAR = COMMA < NEWLINE ? COMMA : NEWLINE;
|
||||
|
||||
m_szIconFontName = fonts.substr(COLON + 2, LASTCHAR - (COLON + 2));
|
||||
CHyprNotificationOverlay::~CHyprNotificationOverlay() {
|
||||
if (m_pCairo)
|
||||
cairo_destroy(m_pCairo);
|
||||
if (m_pCairoSurface)
|
||||
cairo_surface_destroy(m_pCairoSurface);
|
||||
}
|
||||
|
||||
void CHyprNotificationOverlay::addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon, const float fontSize) {
|
||||
@@ -46,7 +44,7 @@ void CHyprNotificationOverlay::addNotification(const std::string& text, const CC
|
||||
PNOTIF->icon = icon;
|
||||
PNOTIF->fontSize = fontSize;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto const& m : g_pCompositor->m_vMonitors) {
|
||||
g_pCompositor->scheduleFrameForMonitor(m.get());
|
||||
}
|
||||
}
|
||||
@@ -75,25 +73,24 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
float maxWidth = 0;
|
||||
|
||||
const auto SCALE = pMonitor->scale;
|
||||
const auto MONSIZE = pMonitor->vecTransformedSize;
|
||||
|
||||
const auto MONSIZE = pMonitor->vecPixelSize;
|
||||
static auto fontFamily = CConfigValue<std::string>("misc:font_family");
|
||||
|
||||
cairo_text_extents_t cairoExtents;
|
||||
int iconW = 0, iconH = 0;
|
||||
PangoLayout* layout = pango_cairo_create_layout(m_pCairo);
|
||||
PangoFontDescription* pangoFD = pango_font_description_new();
|
||||
|
||||
cairo_select_font_face(m_pCairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||
pango_font_description_set_family(pangoFD, (*fontFamily).c_str());
|
||||
pango_font_description_set_style(pangoFD, PANGO_STYLE_NORMAL);
|
||||
pango_font_description_set_weight(pangoFD, PANGO_WEIGHT_NORMAL);
|
||||
|
||||
const auto iconBackendID = iconBackendFromLayout(layout);
|
||||
const auto PBEZIER = g_pAnimationManager->getBezier("default");
|
||||
|
||||
for (auto& notif : m_dNotifications) {
|
||||
for (auto const& notif : m_dNotifications) {
|
||||
const auto ICONPADFORNOTIF = notif->icon == ICON_NONE ? 0 : ICON_PAD;
|
||||
const auto FONTSIZE = std::clamp((int)(notif->fontSize * ((pMonitor->vecPixelSize.x * SCALE) / 1920.f)), 8, 40);
|
||||
|
||||
PangoLayout* pangoLayout = pango_cairo_create_layout(m_pCairo);
|
||||
PangoFontDescription* pangoFD = pango_font_description_from_string(("Sans " + std::to_string(FONTSIZE * ICON_SCALE)).c_str());
|
||||
pango_layout_set_font_description(pangoLayout, pangoFD);
|
||||
cairo_set_font_size(m_pCairo, FONTSIZE);
|
||||
|
||||
// first rect (bg, col)
|
||||
const float FIRSTRECTANIMP =
|
||||
(notif->started.getMillis() > (ANIM_DURATION_MS - ANIM_LAG_MS) ?
|
||||
@@ -115,31 +112,37 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
const float THIRDRECTPERC = notif->started.getMillis() / notif->timeMs;
|
||||
|
||||
// get text size
|
||||
cairo_text_extents(m_pCairo, notif->text.c_str(), &cairoExtents);
|
||||
const auto ICON = ICONS_ARRAY[m_eIconBackend][notif->icon];
|
||||
const auto ICON = ICONS_ARRAY[iconBackendID][notif->icon];
|
||||
const auto ICONCOLOR = ICONS_COLORS[notif->icon];
|
||||
pango_layout_set_text(pangoLayout, ICON.c_str(), -1);
|
||||
pango_layout_set_font_description(pangoLayout, pangoFD);
|
||||
pango_cairo_update_layout(m_pCairo, pangoLayout);
|
||||
pango_layout_get_size(pangoLayout, &iconW, &iconH);
|
||||
|
||||
int iconW = 0, iconH = 0;
|
||||
pango_font_description_set_absolute_size(pangoFD, PANGO_SCALE * FONTSIZE * ICON_SCALE);
|
||||
pango_layout_set_font_description(layout, pangoFD);
|
||||
pango_layout_set_text(layout, ICON.c_str(), -1);
|
||||
pango_layout_get_size(layout, &iconW, &iconH);
|
||||
iconW /= PANGO_SCALE;
|
||||
iconH /= PANGO_SCALE;
|
||||
|
||||
cairo_set_source_rgba(m_pCairo, notif->color.r, notif->color.g, notif->color.b, notif->color.a);
|
||||
int textW = 0, textH = 0;
|
||||
pango_font_description_set_absolute_size(pangoFD, PANGO_SCALE * FONTSIZE);
|
||||
pango_layout_set_font_description(layout, pangoFD);
|
||||
pango_layout_set_text(layout, notif->text.c_str(), -1);
|
||||
pango_layout_get_size(layout, &textW, &textH);
|
||||
textW /= PANGO_SCALE;
|
||||
textH /= PANGO_SCALE;
|
||||
|
||||
const auto NOTIFSIZE = Vector2D{cairoExtents.width + 20 + iconW + 2 * ICONPADFORNOTIF, cairoExtents.height + 10};
|
||||
const auto NOTIFSIZE = Vector2D{textW + 20.0 + iconW + 2 * ICONPADFORNOTIF, textH + 10.0};
|
||||
|
||||
// draw rects
|
||||
cairo_set_source_rgba(m_pCairo, notif->color.r, notif->color.g, notif->color.b, notif->color.a);
|
||||
cairo_rectangle(m_pCairo, MONSIZE.x - (NOTIFSIZE.x + NOTIF_LEFTBAR_SIZE) * FIRSTRECTPERC, offsetY, (NOTIFSIZE.x + NOTIF_LEFTBAR_SIZE) * FIRSTRECTPERC, NOTIFSIZE.y);
|
||||
cairo_fill(m_pCairo);
|
||||
|
||||
cairo_set_source_rgb(m_pCairo, 0.f, 0.f, 0.f);
|
||||
|
||||
cairo_rectangle(m_pCairo, MONSIZE.x - NOTIFSIZE.x * SECONDRECTPERC, offsetY, NOTIFSIZE.x * SECONDRECTPERC, NOTIFSIZE.y);
|
||||
cairo_fill(m_pCairo);
|
||||
|
||||
cairo_set_source_rgba(m_pCairo, notif->color.r, notif->color.g, notif->color.b, notif->color.a);
|
||||
|
||||
cairo_rectangle(m_pCairo, MONSIZE.x - NOTIFSIZE.x * SECONDRECTPERC + 3, offsetY + NOTIFSIZE.y - 4, THIRDRECTPERC * (NOTIFSIZE.x - 6), 2);
|
||||
cairo_fill(m_pCairo);
|
||||
|
||||
@@ -157,25 +160,26 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
|
||||
// draw icon
|
||||
cairo_set_source_rgb(m_pCairo, 1.f, 1.f, 1.f);
|
||||
cairo_move_to(m_pCairo, MONSIZE.x - NOTIFSIZE.x * SECONDRECTPERC + NOTIF_LEFTBAR_SIZE + ICONPADFORNOTIF - 1, offsetY + std::round((NOTIFSIZE.y - iconH - 4) / 2.0));
|
||||
pango_cairo_show_layout(m_pCairo, pangoLayout);
|
||||
cairo_move_to(m_pCairo, MONSIZE.x - NOTIFSIZE.x * SECONDRECTPERC + NOTIF_LEFTBAR_SIZE + ICONPADFORNOTIF - 1, offsetY - 2 + std::round((NOTIFSIZE.y - iconH) / 2.0));
|
||||
pango_layout_set_text(layout, ICON.c_str(), -1);
|
||||
pango_cairo_show_layout(m_pCairo, layout);
|
||||
}
|
||||
|
||||
// draw text
|
||||
cairo_set_font_size(m_pCairo, FONTSIZE);
|
||||
cairo_set_source_rgb(m_pCairo, 1.f, 1.f, 1.f);
|
||||
cairo_move_to(m_pCairo, MONSIZE.x - NOTIFSIZE.x * SECONDRECTPERC + NOTIF_LEFTBAR_SIZE + iconW + 2 * ICONPADFORNOTIF, offsetY + FONTSIZE + (FONTSIZE / 10.0));
|
||||
cairo_show_text(m_pCairo, notif->text.c_str());
|
||||
cairo_move_to(m_pCairo, MONSIZE.x - NOTIFSIZE.x * SECONDRECTPERC + NOTIF_LEFTBAR_SIZE + iconW + 2 * ICONPADFORNOTIF, offsetY - 2 + std::round((NOTIFSIZE.y - textH) / 2.0));
|
||||
pango_layout_set_text(layout, notif->text.c_str(), -1);
|
||||
pango_cairo_show_layout(m_pCairo, layout);
|
||||
|
||||
// adjust offset and move on
|
||||
offsetY += NOTIFSIZE.y + 10;
|
||||
|
||||
if (maxWidth < NOTIFSIZE.x)
|
||||
maxWidth = NOTIFSIZE.x;
|
||||
}
|
||||
|
||||
pango_font_description_free(pangoFD);
|
||||
g_object_unref(pangoLayout);
|
||||
}
|
||||
g_object_unref(layout);
|
||||
|
||||
// cleanup notifs
|
||||
std::erase_if(m_dNotifications, [](const auto& notif) { return notif->started.getMillis() > notif->timeMs; });
|
||||
@@ -185,16 +189,19 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
|
||||
void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||
|
||||
if (m_pLastMonitor != pMonitor || !m_pCairo || !m_pCairoSurface) {
|
||||
const auto MONSIZE = pMonitor->vecTransformedSize;
|
||||
|
||||
if (m_pLastMonitor != pMonitor || m_vecLastSize != MONSIZE || !m_pCairo || !m_pCairoSurface) {
|
||||
|
||||
if (m_pCairo && m_pCairoSurface) {
|
||||
cairo_destroy(m_pCairo);
|
||||
cairo_surface_destroy(m_pCairoSurface);
|
||||
}
|
||||
|
||||
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, MONSIZE.x, MONSIZE.y);
|
||||
m_pCairo = cairo_create(m_pCairoSurface);
|
||||
m_pLastMonitor = pMonitor;
|
||||
m_vecLastSize = MONSIZE;
|
||||
}
|
||||
|
||||
// Draw the notifications
|
||||
@@ -222,8 +229,8 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||
|
||||
// copy the data to an OpenGL texture we have
|
||||
const auto DATA = cairo_image_surface_get_data(m_pCairoSurface);
|
||||
m_tTexture.allocate();
|
||||
glBindTexture(GL_TEXTURE_2D, m_tTexture.m_iTexID);
|
||||
m_pTexture->allocate();
|
||||
glBindTexture(GL_TEXTURE_2D, m_pTexture->m_iTexID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
@@ -232,10 +239,10 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
#endif
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MONSIZE.x, MONSIZE.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
|
||||
CBox pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
|
||||
CBox pMonBox = {0, 0, MONSIZE.x, MONSIZE.y};
|
||||
g_pHyprOpenGL->renderTexture(m_pTexture, &pMonBox, 1.f);
|
||||
}
|
||||
|
||||
bool CHyprNotificationOverlay::hasAny() {
|
||||
|
@@ -39,6 +39,7 @@ struct SNotification {
|
||||
class CHyprNotificationOverlay {
|
||||
public:
|
||||
CHyprNotificationOverlay();
|
||||
~CHyprNotificationOverlay();
|
||||
|
||||
void draw(CMonitor* pMonitor);
|
||||
void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f);
|
||||
@@ -55,11 +56,9 @@ class CHyprNotificationOverlay {
|
||||
cairo_t* m_pCairo = nullptr;
|
||||
|
||||
CMonitor* m_pLastMonitor = nullptr;
|
||||
Vector2D m_vecLastSize = Vector2D(-1, -1);
|
||||
|
||||
CTexture m_tTexture;
|
||||
|
||||
eIconBackend m_eIconBackend = ICONS_BACKEND_NONE;
|
||||
std::string m_szIconFontName = "Sans";
|
||||
SP<CTexture> m_pTexture;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHyprNotificationOverlay> g_pHyprNotificationOverlay;
|
@@ -1,34 +1,73 @@
|
||||
#include "Log.hpp"
|
||||
#include "../defines.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "RollingLogFollow.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <fcntl.h>
|
||||
|
||||
void Debug::init(const std::string& IS) {
|
||||
logFile = "/tmp/hypr/" + IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log");
|
||||
logFile = IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log");
|
||||
logOfs.open(logFile, std::ios::out | std::ios::app);
|
||||
auto handle = logOfs.native_handle();
|
||||
fcntl(handle, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
|
||||
void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) {
|
||||
if (level > wlr_log_get_verbosity())
|
||||
void Debug::close() {
|
||||
logOfs.close();
|
||||
}
|
||||
|
||||
void Debug::log(LogLevel level, std::string str) {
|
||||
if (level == TRACE && !trace)
|
||||
return;
|
||||
|
||||
char* outputStr = nullptr;
|
||||
if (shuttingDown)
|
||||
return;
|
||||
|
||||
vasprintf(&outputStr, fmt, args);
|
||||
|
||||
std::string output = std::string(outputStr);
|
||||
free(outputStr);
|
||||
|
||||
rollingLog += output + "\n";
|
||||
|
||||
if (!disableLogs || !**disableLogs) {
|
||||
std::ofstream ofs;
|
||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||
ofs << "[wlr] " << output << "\n";
|
||||
ofs.close();
|
||||
std::string coloredStr = str;
|
||||
switch (level) {
|
||||
case LOG:
|
||||
str = "[LOG] " + str;
|
||||
coloredStr = str;
|
||||
break;
|
||||
case WARN:
|
||||
str = "[WARN] " + str;
|
||||
coloredStr = "\033[1;33m" + str + "\033[0m"; // yellow
|
||||
break;
|
||||
case ERR:
|
||||
str = "[ERR] " + str;
|
||||
coloredStr = "\033[1;31m" + str + "\033[0m"; // red
|
||||
break;
|
||||
case CRIT:
|
||||
str = "[CRITICAL] " + str;
|
||||
coloredStr = "\033[1;35m" + str + "\033[0m"; // magenta
|
||||
break;
|
||||
case INFO:
|
||||
str = "[INFO] " + str;
|
||||
coloredStr = "\033[1;32m" + str + "\033[0m"; // green
|
||||
break;
|
||||
case TRACE:
|
||||
str = "[TRACE] " + str;
|
||||
coloredStr = "\033[1;34m" + str + "\033[0m"; // blue
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
rollingLog += str + "\n";
|
||||
if (rollingLog.size() > ROLLING_LOG_SIZE)
|
||||
rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE);
|
||||
|
||||
if (RollingLogFollow::Get().IsRunning())
|
||||
RollingLogFollow::Get().AddLog(str);
|
||||
|
||||
if (!disableLogs || !**disableLogs) {
|
||||
// log to a file
|
||||
logOfs << str << "\n";
|
||||
logOfs.flush();
|
||||
}
|
||||
|
||||
// log it to the stdout too.
|
||||
if (!disableStdout)
|
||||
std::cout << output << "\n";
|
||||
std::cout << ((coloredLogs && !**coloredLogs) ? str : coloredStr) << "\n";
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include "../includes.hpp"
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
|
||||
@@ -22,17 +23,27 @@ enum LogLevel {
|
||||
|
||||
namespace Debug {
|
||||
inline std::string logFile;
|
||||
inline std::ofstream logOfs;
|
||||
inline int64_t* const* disableLogs = nullptr;
|
||||
inline int64_t* const* disableTime = nullptr;
|
||||
inline bool disableStdout = false;
|
||||
inline bool trace = false;
|
||||
inline bool shuttingDown = false;
|
||||
inline int64_t* const* coloredLogs = nullptr;
|
||||
|
||||
inline std::string rollingLog = ""; // rolling log contains the ROLLING_LOG_SIZE tail of the log
|
||||
inline std::mutex logMutex;
|
||||
|
||||
void init(const std::string& IS);
|
||||
void close();
|
||||
|
||||
//
|
||||
void log(LogLevel level, std::string str);
|
||||
|
||||
template <typename... Args>
|
||||
void log(LogLevel level, std::format_string<Args...> fmt, Args&&... args) {
|
||||
std::lock_guard<std::mutex> guard(logMutex);
|
||||
|
||||
if (level == TRACE && !trace)
|
||||
return;
|
||||
|
||||
@@ -41,25 +52,17 @@ namespace Debug {
|
||||
|
||||
std::string logMsg = "";
|
||||
|
||||
switch (level) {
|
||||
case LOG: logMsg += "[LOG] "; break;
|
||||
case WARN: logMsg += "[WARN] "; break;
|
||||
case ERR: logMsg += "[ERR] "; break;
|
||||
case CRIT: logMsg += "[CRITICAL] "; break;
|
||||
case INFO: logMsg += "[INFO] "; break;
|
||||
case TRACE: logMsg += "[TRACE] "; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// print date and time to the ofs
|
||||
if (disableTime && !**disableTime) {
|
||||
#ifndef _LIBCPP_VERSION
|
||||
logMsg += std::format("[{:%T}] ", std::chrono::hh_mm_ss{std::chrono::system_clock::now() - std::chrono::floor<std::chrono::days>(std::chrono::system_clock::now())});
|
||||
static auto current_zone = std::chrono::current_zone();
|
||||
const auto zt = std::chrono::zoned_time{current_zone, std::chrono::system_clock::now()};
|
||||
const auto hms = std::chrono::hh_mm_ss{zt.get_local_time() - std::chrono::floor<std::chrono::days>(zt.get_local_time())};
|
||||
#else
|
||||
auto c = std::chrono::hh_mm_ss{std::chrono::system_clock::now() - std::chrono::floor<std::chrono::days>(std::chrono::system_clock::now())};
|
||||
logMsg += std::format("{:%H}:{:%M}:{:%S}", c.hours(), c.minutes(), c.subseconds());
|
||||
|
||||
// TODO: current clang 17 does not support `zoned_time`, remove this once clang 19 is ready
|
||||
const auto hms = std::chrono::hh_mm_ss{std::chrono::system_clock::now() - std::chrono::floor<std::chrono::days>(std::chrono::system_clock::now())};
|
||||
#endif
|
||||
logMsg += std::format("[{}] ", hms);
|
||||
}
|
||||
|
||||
// no need for try {} catch {} because std::format_string<Args...> ensures that vformat never throw std::format_error
|
||||
@@ -69,23 +72,6 @@ namespace Debug {
|
||||
// 3. this is actually what std::format in stdlib does
|
||||
logMsg += std::vformat(fmt.get(), std::make_format_args(args...));
|
||||
|
||||
rollingLog += logMsg + "\n";
|
||||
if (rollingLog.size() > ROLLING_LOG_SIZE)
|
||||
rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE);
|
||||
|
||||
if (!disableLogs || !**disableLogs) {
|
||||
// log to a file
|
||||
std::ofstream ofs;
|
||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||
ofs << logMsg << "\n";
|
||||
|
||||
ofs.close();
|
||||
log(level, logMsg);
|
||||
}
|
||||
|
||||
// log it to the stdout too.
|
||||
if (!disableStdout)
|
||||
std::cout << logMsg << "\n";
|
||||
}
|
||||
|
||||
void wlrLog(wlr_log_importance level, const char* fmt, va_list args);
|
||||
};
|
||||
|
65
src/debug/RollingLogFollow.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include <shared_mutex>
|
||||
|
||||
namespace Debug {
|
||||
struct RollingLogFollow {
|
||||
std::unordered_map<int, std::string> socketToRollingLogFollowQueue;
|
||||
std::shared_mutex m;
|
||||
bool running = false;
|
||||
static constexpr size_t ROLLING_LOG_FOLLOW_TOO_BIG = 8192;
|
||||
|
||||
// Returns true if the queue is empty for the given socket
|
||||
bool isEmpty(int socket) {
|
||||
std::shared_lock<std::shared_mutex> r(m);
|
||||
return socketToRollingLogFollowQueue[socket].empty();
|
||||
}
|
||||
|
||||
std::string DebugInfo() {
|
||||
std::shared_lock<std::shared_mutex> r(m);
|
||||
return std::format("RollingLogFollow, got {} connections", socketToRollingLogFollowQueue.size());
|
||||
}
|
||||
|
||||
std::string GetLog(int socket) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
|
||||
const std::string ret = socketToRollingLogFollowQueue[socket];
|
||||
socketToRollingLogFollowQueue[socket] = "";
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
void AddLog(std::string log) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
running = true;
|
||||
std::vector<int> to_erase;
|
||||
for (const auto& p : socketToRollingLogFollowQueue)
|
||||
socketToRollingLogFollowQueue[p.first] += log + "\n";
|
||||
}
|
||||
|
||||
bool IsRunning() {
|
||||
std::shared_lock<std::shared_mutex> r(m);
|
||||
return running;
|
||||
}
|
||||
|
||||
void StopFor(int socket) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
socketToRollingLogFollowQueue.erase(socket);
|
||||
if (socketToRollingLogFollowQueue.empty())
|
||||
running = false;
|
||||
}
|
||||
|
||||
void StartFor(int socket) {
|
||||
std::unique_lock<std::shared_mutex> w(m);
|
||||
socketToRollingLogFollowQueue[socket] = std::format("[LOG] Following log to socket: {} started\n", socket);
|
||||
running = true;
|
||||
}
|
||||
|
||||
static RollingLogFollow& Get() {
|
||||
static RollingLogFollow instance;
|
||||
static std::mutex gm;
|
||||
std::lock_guard<std::mutex> lock(gm);
|
||||
return instance;
|
||||
};
|
||||
};
|
||||
}
|
@@ -3,3 +3,4 @@
|
||||
#include "helpers/WLListener.hpp"
|
||||
#include "helpers/Color.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "desktop/DesktopTypes.hpp"
|
||||
|
@@ -1,131 +0,0 @@
|
||||
#include "Constraint.hpp"
|
||||
#include "WLSurface.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
CConstraint::CConstraint(wlr_pointer_constraint_v1* constraint, CWLSurface* owner) : m_pOwner(owner), m_pConstraint(constraint) {
|
||||
RASSERT(!constraint->data, "CConstraint: attempted to duplicate ownership");
|
||||
|
||||
constraint->data = this;
|
||||
initSignals();
|
||||
|
||||
m_vCursorPosOnActivate = g_pInputManager->getMouseCoordsInternal();
|
||||
|
||||
g_pInputManager->m_vConstraints.push_back(this);
|
||||
|
||||
if (g_pCompositor->m_pLastFocus == m_pOwner->wlr())
|
||||
activate();
|
||||
}
|
||||
|
||||
CConstraint::~CConstraint() {
|
||||
std::erase(g_pInputManager->m_vConstraints, this);
|
||||
}
|
||||
|
||||
static void onConstraintDestroy(void* owner, void* data) {
|
||||
const auto CONSTRAINT = (CConstraint*)owner;
|
||||
CONSTRAINT->onDestroy();
|
||||
}
|
||||
|
||||
static void onConstraintSetRegion(void* owner, void* data) {
|
||||
const auto CONSTRAINT = (CConstraint*)owner;
|
||||
CONSTRAINT->onSetRegion();
|
||||
}
|
||||
|
||||
void CConstraint::initSignals() {
|
||||
hyprListener_setConstraintRegion.initCallback(&m_pConstraint->events.set_region, ::onConstraintSetRegion, this, "CConstraint");
|
||||
hyprListener_destroyConstraint.initCallback(&m_pConstraint->events.destroy, ::onConstraintDestroy, this, "CConstraint");
|
||||
}
|
||||
|
||||
void CConstraint::onDestroy() {
|
||||
hyprListener_setConstraintRegion.removeCallback();
|
||||
hyprListener_destroyConstraint.removeCallback();
|
||||
|
||||
if (active() && isLocked())
|
||||
g_pCompositor->warpCursorTo(logicPositionHint(), true);
|
||||
|
||||
// this is us
|
||||
m_pOwner->m_pConstraint.reset();
|
||||
}
|
||||
|
||||
void CConstraint::onSetRegion() {
|
||||
if (!m_bActive)
|
||||
return;
|
||||
|
||||
m_rRegion.set(&m_pConstraint->region);
|
||||
m_vPositionHint = m_rRegion.closestPoint(m_vPositionHint);
|
||||
g_pInputManager->simulateMouseMovement(); // to warp the cursor if anything's amiss
|
||||
}
|
||||
|
||||
void CConstraint::onCommit() {
|
||||
if (!m_bActive)
|
||||
return;
|
||||
|
||||
const auto COMMITTED = m_pConstraint->current.committed;
|
||||
|
||||
if (COMMITTED & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
|
||||
m_bHintSet = true;
|
||||
m_vPositionHint = {m_pConstraint->current.cursor_hint.x, m_pConstraint->current.cursor_hint.y};
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
}
|
||||
|
||||
if (COMMITTED & WLR_POINTER_CONSTRAINT_V1_STATE_REGION)
|
||||
onSetRegion();
|
||||
}
|
||||
|
||||
CRegion CConstraint::logicConstraintRegion() {
|
||||
CRegion rg = m_rRegion;
|
||||
const auto SURFBOX = m_pOwner->getSurfaceBoxGlobal();
|
||||
const auto CONSTRAINTPOS = SURFBOX.has_value() ? SURFBOX->pos() : Vector2D{};
|
||||
rg.translate(CONSTRAINTPOS);
|
||||
return rg;
|
||||
}
|
||||
|
||||
CWLSurface* CConstraint::owner() {
|
||||
return m_pOwner;
|
||||
}
|
||||
|
||||
bool CConstraint::isLocked() {
|
||||
return m_pConstraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED;
|
||||
}
|
||||
|
||||
Vector2D CConstraint::logicPositionHint() {
|
||||
const auto SURFBOX = m_pOwner->getSurfaceBoxGlobal();
|
||||
const auto CONSTRAINTPOS = SURFBOX.has_value() ? SURFBOX->pos() : Vector2D{};
|
||||
|
||||
return m_bHintSet ? CONSTRAINTPOS + m_vPositionHint : m_vCursorPosOnActivate;
|
||||
}
|
||||
|
||||
void CConstraint::deactivate() {
|
||||
if (!m_bActive)
|
||||
return;
|
||||
|
||||
m_bActive = false;
|
||||
|
||||
if (isLocked())
|
||||
g_pCompositor->warpCursorTo(logicPositionHint(), true);
|
||||
|
||||
if (m_pConstraint->lifetime == ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT)
|
||||
m_bDead = true;
|
||||
|
||||
wlr_pointer_constraint_v1_send_deactivated(m_pConstraint);
|
||||
}
|
||||
|
||||
void CConstraint::activate() {
|
||||
if (m_bActive || m_bDead)
|
||||
return;
|
||||
|
||||
m_bActive = true;
|
||||
|
||||
// TODO: hack, probably not a super duper great idea
|
||||
if (g_pCompositor->m_sSeat.seat->pointer_state.focused_surface != m_pOwner->wlr()) {
|
||||
const auto SURFBOX = m_pOwner->getSurfaceBoxGlobal();
|
||||
const auto LOCAL = SURFBOX.has_value() ? logicPositionHint() - SURFBOX->pos() : Vector2D{};
|
||||
wlr_seat_pointer_enter(g_pCompositor->m_sSeat.seat, m_pOwner->wlr(), LOCAL.x, LOCAL.y);
|
||||
}
|
||||
|
||||
g_pCompositor->warpCursorTo(logicPositionHint(), true);
|
||||
wlr_pointer_constraint_v1_send_activated(m_pConstraint);
|
||||
}
|
||||
|
||||
bool CConstraint::active() {
|
||||
return m_bActive;
|
||||
}
|