mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-19 14:03:47 -07:00
Compare commits
1047 Commits
v0.15.1bet
...
v0.25.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f27873a6f0 | ||
|
|
c3b9326ba1 | ||
|
|
fd3e6a3bfd | ||
|
|
0155b85950 | ||
|
|
a663823af2 | ||
|
|
5a3c144919 | ||
|
|
4fe5827598 | ||
|
|
2e28e88dfd | ||
|
|
72b118cd8f | ||
|
|
80b2ac1cc5 | ||
|
|
79791c9ed4 | ||
|
|
ac3edec14b | ||
|
|
cde7f79af0 | ||
|
|
609c7ab6b5 | ||
|
|
c949173bc9 | ||
|
|
250d5cf78c | ||
|
|
45b1e6dc5e | ||
|
|
d6b069458d | ||
|
|
3a631e40db | ||
|
|
dc469dc4c1 | ||
|
|
11b7ce14f8 | ||
|
|
ddfeebad3d | ||
|
|
11e87986a2 | ||
|
|
dbf0b92de7 | ||
|
|
02312cac59 | ||
|
|
6501bceb42 | ||
|
|
3580f845e6 | ||
|
|
b7e69be51e | ||
|
|
fdb772832f | ||
|
|
5c3684d0cc | ||
|
|
5a3e3deb33 | ||
|
|
2946221195 | ||
|
|
ce6c13f86b | ||
|
|
fbb938fcf2 | ||
|
|
093755d53f | ||
|
|
dbb6d9d174 | ||
|
|
f23455e592 | ||
|
|
5ce76cd0b0 | ||
|
|
49f9ca06c7 | ||
|
|
1a1656ddbf | ||
|
|
550700bed0 | ||
|
|
72d2f33b34 | ||
|
|
38bdbdb0f5 | ||
|
|
622132290f | ||
|
|
77223e1cad | ||
|
|
4a1fb3e903 | ||
|
|
28ca434fb5 | ||
|
|
1e526411b6 | ||
|
|
849d657595 | ||
|
|
bf27066fd7 | ||
|
|
1f80154823 | ||
|
|
f40272d509 | ||
|
|
e195a51cd4 | ||
|
|
247ff4e60d | ||
|
|
eb570c88e6 | ||
|
|
1a91c6ee60 | ||
|
|
67c73ec100 | ||
|
|
f7579fc923 | ||
|
|
fbcbe947da | ||
|
|
97b0368765 | ||
|
|
c0f4e9f52e | ||
|
|
4a92deec54 | ||
|
|
5bf1c32bc0 | ||
|
|
49fb4cd94d | ||
|
|
99079f7094 | ||
|
|
1911e4262b | ||
|
|
d366fc48b8 | ||
|
|
7b5b4a1049 | ||
|
|
458ea56b86 | ||
|
|
d03dcc3d99 | ||
|
|
2df0d034bc | ||
|
|
510db64860 | ||
|
|
b15803510c | ||
|
|
f914a5a06d | ||
|
|
6225591dbd | ||
|
|
e446db02f6 | ||
|
|
a4330fe378 | ||
|
|
716d713b04 | ||
|
|
1c50a11688 | ||
|
|
385fe4e301 | ||
|
|
412d46ff65 | ||
|
|
ae82c3a639 | ||
|
|
b4f75525d9 | ||
|
|
8b3d8dc792 | ||
|
|
5cb5b628b8 | ||
|
|
b0d86a7159 | ||
|
|
a6cfe70428 | ||
|
|
b6a7be7663 | ||
|
|
25f14294a8 | ||
|
|
7c36a3e167 | ||
|
|
785fc8d669 | ||
|
|
c62ab1bee7 | ||
|
|
f80f4f3194 | ||
|
|
6e58428336 | ||
|
|
b05ff89c76 | ||
|
|
28dfe21584 | ||
|
|
c86f06caa0 | ||
|
|
afc887d941 | ||
|
|
edad24c257 | ||
|
|
12604b7676 | ||
|
|
63841c8aac | ||
|
|
8944db49be | ||
|
|
4c4fcc128b | ||
|
|
d6c4ae71d0 | ||
|
|
a6d94eafba | ||
|
|
29fc410a8f | ||
|
|
83f1616a65 | ||
|
|
7ec23254fd | ||
|
|
c2b5dd1be6 | ||
|
|
727160f0a4 | ||
|
|
3f2a18a435 | ||
|
|
e329bc2c7b | ||
|
|
8dd0c4fe74 | ||
|
|
cf7c5e4dff | ||
|
|
287e6c4ede | ||
|
|
011600ac6e | ||
|
|
70eb74c356 | ||
|
|
260ef788f5 | ||
|
|
6131e0bef7 | ||
|
|
41c7d896e3 | ||
|
|
33d06fb0e5 | ||
|
|
4bc3f9adbe | ||
|
|
a22e1174ee | ||
|
|
985764c8db | ||
|
|
5f000306f5 | ||
|
|
efee6a1cda | ||
|
|
a68feb5aa0 | ||
|
|
293df75b97 | ||
|
|
f00e11d457 | ||
|
|
0fd09579a1 | ||
|
|
3ae33b951f | ||
|
|
92fecb8ad4 | ||
|
|
ac2cd0f0dc | ||
|
|
c2f29be9ba | ||
|
|
16a034a34a | ||
|
|
ea77622e04 | ||
|
|
a38b0e736d | ||
|
|
7b43f9f056 | ||
|
|
fa4aef4531 | ||
|
|
56a307d734 | ||
|
|
6a4bda60f2 | ||
|
|
16d05a5c8b | ||
|
|
7faead75bd | ||
|
|
a1b1480c21 | ||
|
|
f3909cf2bf | ||
|
|
4ae784dc53 | ||
|
|
dd2372d2e6 | ||
|
|
c03db1a1cd | ||
|
|
3ade6c4a96 | ||
|
|
046ad79d11 | ||
|
|
e4e653ada6 | ||
|
|
b32af6ebfb | ||
|
|
86852cdc78 | ||
|
|
31963f823b | ||
|
|
3ce19e67fe | ||
|
|
10b9e9bbe5 | ||
|
|
07e4ba9d80 | ||
|
|
5e2d4d644a | ||
|
|
50876f1b15 | ||
|
|
c2a85c9d36 | ||
|
|
41d1fdedf2 | ||
|
|
cd1b982b2a | ||
|
|
a35ea4d242 | ||
|
|
d8645cd148 | ||
|
|
c9f7afbf78 | ||
|
|
dfb78e0593 | ||
|
|
24ace03780 | ||
|
|
569eaff04c | ||
|
|
801a17194c | ||
|
|
1a5d5bf620 | ||
|
|
366ebc123b | ||
|
|
bc4a51dbbb | ||
|
|
80650b6722 | ||
|
|
a740e3e517 | ||
|
|
19809532df | ||
|
|
110f3fd658 | ||
|
|
a80ba54bbc | ||
|
|
00d199b477 | ||
|
|
eea99abc49 | ||
|
|
903d298381 | ||
|
|
49f0f53f51 | ||
|
|
2dc02bbb39 | ||
|
|
e7185b338f | ||
|
|
6519c0308c | ||
|
|
d154a8da20 | ||
|
|
7d9977d028 | ||
|
|
882be7765b | ||
|
|
99314fbe71 | ||
|
|
bab949599f | ||
|
|
f81b3eef4f | ||
|
|
c50df4c0c3 | ||
|
|
ee85dd6b61 | ||
|
|
bae19cb10e | ||
|
|
2f7fb2f553 | ||
|
|
23001f6144 | ||
|
|
55d585ce17 | ||
|
|
d3b0c90356 | ||
|
|
a43b18ae26 | ||
|
|
0a099ca2ab | ||
|
|
e6211eef00 | ||
|
|
b1426cad28 | ||
|
|
0fc145c52c | ||
|
|
c2b25f4701 | ||
|
|
88a96110b7 | ||
|
|
2b4d96e0ef | ||
|
|
16bc5997bb | ||
|
|
7680cd549c | ||
|
|
1df8b1957e | ||
|
|
430778293e | ||
|
|
de3b00b5ee | ||
|
|
24ef5d888c | ||
|
|
5688e24b8a | ||
|
|
3d9bf17f11 | ||
|
|
614ea53ad7 | ||
|
|
b88de63abb | ||
|
|
60527ab180 | ||
|
|
d6241a3086 | ||
|
|
df54ab40ce | ||
|
|
6fec5bfbeb | ||
|
|
e994b0c8b8 | ||
|
|
3343aac6bf | ||
|
|
41f7736c85 | ||
|
|
c418007c68 | ||
|
|
cc2c270dde | ||
|
|
70e3cb8151 | ||
|
|
a80f8f257f | ||
|
|
b3a70b565e | ||
|
|
e73c6fd3b0 | ||
|
|
a5a0434fff | ||
|
|
463690a27a | ||
|
|
471ac474a1 | ||
|
|
a3fda12ba1 | ||
|
|
0268bb9888 | ||
|
|
3a3a3f7bdb | ||
|
|
cf51a31807 | ||
|
|
5be42965ff | ||
|
|
a8b3be2c9c | ||
|
|
5ce91bb0fd | ||
|
|
adf5d8a114 | ||
|
|
cb229f6436 | ||
|
|
e80e93fcda | ||
|
|
37ced6aca4 | ||
|
|
5ffe5dd594 | ||
|
|
dc78c58c77 | ||
|
|
22721a37d5 | ||
|
|
dd4270eadf | ||
|
|
e2923a9385 | ||
|
|
316674fecf | ||
|
|
34da16b7e6 | ||
|
|
71a95a581f | ||
|
|
788a8f7c13 | ||
|
|
d23bbd1687 | ||
|
|
7a514f41a3 | ||
|
|
928de33447 | ||
|
|
0624455591 | ||
|
|
2ba5238b8e | ||
|
|
00c2ca4697 | ||
|
|
d544c30551 | ||
|
|
ef80a69399 | ||
|
|
6e6971606d | ||
|
|
e5ad53ac42 | ||
|
|
e98ee49aee | ||
|
|
d797d9905d | ||
|
|
e5870d47c7 | ||
|
|
91a565c7b0 | ||
|
|
5b924aaf60 | ||
|
|
606cb2832a | ||
|
|
4b52c1e68f | ||
|
|
e77ebec629 | ||
|
|
162f235972 | ||
|
|
e8adae65fe | ||
|
|
96718d8b09 | ||
|
|
5d44ea802a | ||
|
|
d9d57ce39a | ||
|
|
3e261b1fa7 | ||
|
|
cee7f11d8b | ||
|
|
1c67849bf1 | ||
|
|
595f2052c4 | ||
|
|
f5669a7d6b | ||
|
|
25d3d73dbf | ||
|
|
569ae86c90 | ||
|
|
8531d1d7a6 | ||
|
|
e4b6af41e5 | ||
|
|
d63e8c8f45 | ||
|
|
7e5a3eb045 | ||
|
|
f960f72785 | ||
|
|
0807b8b95f | ||
|
|
5dc1a5fec6 | ||
|
|
e749af7b60 | ||
|
|
17deeb07ad | ||
|
|
bcd8fe9573 | ||
|
|
146d231ec5 | ||
|
|
71ef1bde7e | ||
|
|
253286669a | ||
|
|
0ad2d9f0b5 | ||
|
|
c9167d9646 | ||
|
|
ca1c1438e3 | ||
|
|
878fe20409 | ||
|
|
5a5c41301d | ||
|
|
92d2331170 | ||
|
|
a85a6fa6c8 | ||
|
|
b11e2eaa3b | ||
|
|
0aeb61a95a | ||
|
|
4f647a8e8b | ||
|
|
7739b776cd | ||
|
|
0c8d1ba4a8 | ||
|
|
7ce92f93ad | ||
|
|
b03c8970e6 | ||
|
|
de5f1b2a83 | ||
|
|
dc7d783d14 | ||
|
|
8e5ee31f30 | ||
|
|
90c5715bc6 | ||
|
|
d5093f7af0 | ||
|
|
4abc608bc0 | ||
|
|
7bae0823c8 | ||
|
|
5184b542b1 | ||
|
|
fea2031bfe | ||
|
|
be22172a35 | ||
|
|
b69f40815f | ||
|
|
f678789dfd | ||
|
|
c386c52cf9 | ||
|
|
c444099325 | ||
|
|
31cd104286 | ||
|
|
1ead6c46f4 | ||
|
|
fb45f8f2f9 | ||
|
|
c1217066d1 | ||
|
|
3b41169395 | ||
|
|
8bfb2ad2b7 | ||
|
|
b602ac0970 | ||
|
|
a34b747661 | ||
|
|
fe007fd36a | ||
|
|
141365cbc1 | ||
|
|
51ce3ddd67 | ||
|
|
64f35c0e31 | ||
|
|
9c0e2bba54 | ||
|
|
62e0c9226e | ||
|
|
c5aa20f226 | ||
|
|
66b8629964 | ||
|
|
9e028d56c0 | ||
|
|
489ef7c51c | ||
|
|
34685a836a | ||
|
|
dea71875e4 | ||
|
|
76fc12869d | ||
|
|
556c7dd51f | ||
|
|
52878161e4 | ||
|
|
6c250df77e | ||
|
|
7c5c7ced91 | ||
|
|
3cef005fec | ||
|
|
71496a0a3c | ||
|
|
86acdcf8b6 | ||
|
|
ea717731a4 | ||
|
|
72f528cb52 | ||
|
|
0905515c40 | ||
|
|
50a4a74b4e | ||
|
|
7cbbf9a850 | ||
|
|
0e252d2c77 | ||
|
|
5c93f6947a | ||
|
|
07b98952bc | ||
|
|
cd2399715d | ||
|
|
2187c6cf43 | ||
|
|
984c2fdc68 | ||
|
|
a224d366ca | ||
|
|
5e48e6b075 | ||
|
|
72fc309fb1 | ||
|
|
7187ea443e | ||
|
|
91fd854e3b | ||
|
|
4b20d4f1ad | ||
|
|
7beb9fd606 | ||
|
|
4d3f2ca96b | ||
|
|
99b7d53817 | ||
|
|
7e523e4d5e | ||
|
|
89e7d812c8 | ||
|
|
ac251d7a66 | ||
|
|
49f423aa8f | ||
|
|
18229043fa | ||
|
|
03d7651916 | ||
|
|
c5d741fb39 | ||
|
|
3bceabe29b | ||
|
|
5da96132b9 | ||
|
|
15d108fbc1 | ||
|
|
8b81f41e52 | ||
|
|
74a10f26a4 | ||
|
|
492f36f7df | ||
|
|
2e21ad875b | ||
|
|
18ed73f091 | ||
|
|
55b412e0f4 | ||
|
|
3bfaeacf7d | ||
|
|
e302724847 | ||
|
|
edd0a141de | ||
|
|
cf566b59ce | ||
|
|
1089e858b4 | ||
|
|
60e37d727d | ||
|
|
14a2de0d0e | ||
|
|
2bf7f9e413 | ||
|
|
513bbb8047 | ||
|
|
f1c9077139 | ||
|
|
66e3679ba3 | ||
|
|
708bb014e9 | ||
|
|
ca3c8cdfae | ||
|
|
a66ef50469 | ||
|
|
431c74f111 | ||
|
|
f023126a73 | ||
|
|
474ada9267 | ||
|
|
784cdd7638 | ||
|
|
fc49a055c6 | ||
|
|
be8cf8ea1e | ||
|
|
0eee57aab9 | ||
|
|
ecd0156265 | ||
|
|
cd6640e890 | ||
|
|
40622a9e60 | ||
|
|
df2956b411 | ||
|
|
e5a4c0c986 | ||
|
|
2363cc2572 | ||
|
|
1b56cc4e99 | ||
|
|
6e16627cbc | ||
|
|
67e13fbb64 | ||
|
|
ad28321a8d | ||
|
|
0e5df91e3a | ||
|
|
38c25bb50d | ||
|
|
6548439f6c | ||
|
|
c92e0c05e4 | ||
|
|
b944386ca5 | ||
|
|
be2e4d9dd1 | ||
|
|
dbfa6eea7b | ||
|
|
f3d1ab55a2 | ||
|
|
ff95721ad9 | ||
|
|
d710e7347a | ||
|
|
3fbef25ffc | ||
|
|
ab6a092dbc | ||
|
|
1992f27a26 | ||
|
|
f37866eb7e | ||
|
|
87a4cc7654 | ||
|
|
fdc847706a | ||
|
|
61c817319f | ||
|
|
127e80692f | ||
|
|
98c95aa34d | ||
|
|
6b7e409f05 | ||
|
|
79ad93d536 | ||
|
|
7d914cd427 | ||
|
|
287f31329e | ||
|
|
97e0f02621 | ||
|
|
bda8208aaa | ||
|
|
42f4664022 | ||
|
|
d1a7f1dd36 | ||
|
|
1dde751da4 | ||
|
|
7b05133af0 | ||
|
|
68f56130ba | ||
|
|
4ea4efb871 | ||
|
|
48c86ad863 | ||
|
|
859d6b9b8a | ||
|
|
cb6c47098d | ||
|
|
5eb98c0072 | ||
|
|
863812a097 | ||
|
|
4a5c3c4861 | ||
|
|
15544c7544 | ||
|
|
53945cff31 | ||
|
|
760b37f71d | ||
|
|
a431c1b01c | ||
|
|
bd2245d642 | ||
|
|
be6325dd4b | ||
|
|
fcf1bafb09 | ||
|
|
6688421240 | ||
|
|
3e6601fa29 | ||
|
|
a0bc0e4998 | ||
|
|
d81f45e54a | ||
|
|
fd3a1cd086 | ||
|
|
494103b521 | ||
|
|
8e6950e200 | ||
|
|
9e40e47a2e | ||
|
|
a46abd8b1a | ||
|
|
129e99a6f6 | ||
|
|
32d56fec97 | ||
|
|
1a41f729a3 | ||
|
|
445f8c71c5 | ||
|
|
85c07c2fe0 | ||
|
|
eaf0fb14c9 | ||
|
|
11234529db | ||
|
|
f90ff8303b | ||
|
|
d4e2a0fd16 | ||
|
|
32381fe6c4 | ||
|
|
5d35c0432b | ||
|
|
4c4d3b3aa5 | ||
|
|
b2314aa33a | ||
|
|
ef12120270 | ||
|
|
3d83a0bc5f | ||
|
|
38011c50ab | ||
|
|
c3adc9ec56 | ||
|
|
ff9bcb19fa | ||
|
|
ce632b7a05 | ||
|
|
328e034472 | ||
|
|
1c1e688564 | ||
|
|
86f4772bd6 | ||
|
|
61c9e50bcd | ||
|
|
af37a3895f | ||
|
|
666c805101 | ||
|
|
94b7b6b584 | ||
|
|
06b17db227 | ||
|
|
fc89e70a1f | ||
|
|
8ae1fd0173 | ||
|
|
9813ba2f56 | ||
|
|
12e293e309 | ||
|
|
da23ec847e | ||
|
|
84954f376f | ||
|
|
5de659cc7a | ||
|
|
e273717a27 | ||
|
|
a2ae37396f | ||
|
|
eb9fa8460f | ||
|
|
e3d1743722 | ||
|
|
63babcba36 | ||
|
|
1cc7587789 | ||
|
|
70b5c1b119 | ||
|
|
7574b3db64 | ||
|
|
cb6e36d804 | ||
|
|
2a5ae435e1 | ||
|
|
c074f260a1 | ||
|
|
cb98242ea7 | ||
|
|
147be3e10b | ||
|
|
b963a6624e | ||
|
|
ef90a7ad13 | ||
|
|
eb7927d278 | ||
|
|
8f57db28f7 | ||
|
|
7d754b7c22 | ||
|
|
fcbfd19393 | ||
|
|
e811394603 | ||
|
|
434719611d | ||
|
|
5814d9b2a0 | ||
|
|
18330dec4e | ||
|
|
60b880d931 | ||
|
|
cee7bc6e74 | ||
|
|
d345804cd5 | ||
|
|
fb2679d5ef | ||
|
|
6f3548b184 | ||
|
|
d5913a23ac | ||
|
|
3436486575 | ||
|
|
5112056fdb | ||
|
|
d8ee624e35 | ||
|
|
428063ff23 | ||
|
|
32c11bb212 | ||
|
|
31ab2349f9 | ||
|
|
c31c627cf8 | ||
|
|
f14e808847 | ||
|
|
5c83976977 | ||
|
|
2ec7e241cd | ||
|
|
6a56d1e4d0 | ||
|
|
589046ecf7 | ||
|
|
040e99fd17 | ||
|
|
b5b436e01d | ||
|
|
668d90c700 | ||
|
|
b3012d97ab | ||
|
|
0b5a751e52 | ||
|
|
7729fa9ac9 | ||
|
|
9c77415cda | ||
|
|
cbd31ba481 | ||
|
|
8440aa3e9b | ||
|
|
11afb66010 | ||
|
|
c4e422644b | ||
|
|
df30f0519a | ||
|
|
8ba4f34a7c | ||
|
|
7afb7c85a7 | ||
|
|
b24f066c47 | ||
|
|
4ec034ad49 | ||
|
|
20a1a47e66 | ||
|
|
989ee6473f | ||
|
|
a572321f61 | ||
|
|
ff11883482 | ||
|
|
c0c7c12bb9 | ||
|
|
e5dcbf73d8 | ||
|
|
50e106f2e6 | ||
|
|
3173fbdc4a | ||
|
|
b1104b1ca7 | ||
|
|
809b7181a8 | ||
|
|
af4b9700b7 | ||
|
|
2858e08ce0 | ||
|
|
2b248b25c8 | ||
|
|
0d2e1e1270 | ||
|
|
464dd79246 | ||
|
|
85a71d15b6 | ||
|
|
f3551021e0 | ||
|
|
a54247125f | ||
|
|
98ce867104 | ||
|
|
461fab0f27 | ||
|
|
e9a6c3b498 | ||
|
|
c02ac5e08a | ||
|
|
c56b2b99f5 | ||
|
|
0d14fd9136 | ||
|
|
96198dae55 | ||
|
|
0e3547e0f6 | ||
|
|
3d1b255199 | ||
|
|
0b26b1eed6 | ||
|
|
a33ecec61e | ||
|
|
9ba93f4b0a | ||
|
|
85d1b06a79 | ||
|
|
cb4f748226 | ||
|
|
7525818097 | ||
|
|
ddcae74e09 | ||
|
|
228e630f40 | ||
|
|
7f595ed0ca | ||
|
|
a91d0a374a | ||
|
|
0baef17a02 | ||
|
|
5d095bb9e1 | ||
|
|
759490689c | ||
|
|
3e2200ed90 | ||
|
|
a55db95a3b | ||
|
|
b4ebc18367 | ||
|
|
a6699ef30c | ||
|
|
b5f5c26be3 | ||
|
|
d64fc7d336 | ||
|
|
659a5195d4 | ||
|
|
545e63d1dd | ||
|
|
fa79703b04 | ||
|
|
d39ed9254a | ||
|
|
17b4a2786d | ||
|
|
cd08fa22fd | ||
|
|
d87d2dac0b | ||
|
|
f7ce3c27ea | ||
|
|
5fe437da7e | ||
|
|
e6cbb6072b | ||
|
|
fbc7a9391a | ||
|
|
2b888d5106 | ||
|
|
4b8d417fca | ||
|
|
21cc6d7ae5 | ||
|
|
6749c8abd7 | ||
|
|
8c094b0eec | ||
|
|
eb9d063229 | ||
|
|
a1143521d3 | ||
|
|
8a23b66c39 | ||
|
|
de5e784e07 | ||
|
|
96cb47fc64 | ||
|
|
e9bd2ee996 | ||
|
|
41cdfb7420 | ||
|
|
fc37ce4a72 | ||
|
|
edcf4cd61d | ||
|
|
261fbb5b62 | ||
|
|
4fd90144d1 | ||
|
|
3e2785b970 | ||
|
|
ab7f2e847e | ||
|
|
781f0adad4 | ||
|
|
668cc93962 | ||
|
|
2f6b37e103 | ||
|
|
e2ee8b9f20 | ||
|
|
6424a1e398 | ||
|
|
a163ca9237 | ||
|
|
27b8561d25 | ||
|
|
974739457f | ||
|
|
563835404f | ||
|
|
2daabfa0e9 | ||
|
|
0f3214714f | ||
|
|
e7940569dd | ||
|
|
f59c9a805e | ||
|
|
85f50a4a13 | ||
|
|
a3b37b0191 | ||
|
|
11ba6afdd3 | ||
|
|
99ca1ad353 | ||
|
|
2076905d6e | ||
|
|
deb8d3d82e | ||
|
|
f72c237d85 | ||
|
|
98a4fa2b0d | ||
|
|
7c33c7fc64 | ||
|
|
20899b597e | ||
|
|
198b7cae12 | ||
|
|
121ea1fac2 | ||
|
|
3bd9ee0d32 | ||
|
|
95a042691a | ||
|
|
702c0a0fbf | ||
|
|
e405490593 | ||
|
|
ac07e447b8 | ||
|
|
9702b8ce75 | ||
|
|
efc686423a | ||
|
|
b89a07596e | ||
|
|
5a138bed6b | ||
|
|
a2ecca936e | ||
|
|
374571da96 | ||
|
|
f8188ed7f8 | ||
|
|
516949380d | ||
|
|
5d66122689 | ||
|
|
de9396d2a1 | ||
|
|
f8a6799d4e | ||
|
|
111d209bff | ||
|
|
b45a213413 | ||
|
|
1a9ee959dd | ||
|
|
46891b12cf | ||
|
|
0c1bec023f | ||
|
|
80f58bc93f | ||
|
|
06e6c6021e | ||
|
|
e8b99ae13a | ||
|
|
bb99f151da | ||
|
|
f97289a3c0 | ||
|
|
6381b6474f | ||
|
|
c3f1dc3f52 | ||
|
|
62f4503f07 | ||
|
|
bf78dcecf0 | ||
|
|
d5352a5d12 | ||
|
|
fd43d2bea7 | ||
|
|
b9812f8bc0 | ||
|
|
fba03540d5 | ||
|
|
11a1a6c271 | ||
|
|
ff12a41c40 | ||
|
|
629cca4816 | ||
|
|
9fc143cf3d | ||
|
|
726732244a | ||
|
|
be6e1a33b1 | ||
|
|
6e3bd440ba | ||
|
|
cba10ba5b7 | ||
|
|
050693be2e | ||
|
|
0803febac5 | ||
|
|
6259202c01 | ||
|
|
e1d7a13333 | ||
|
|
bf5844d607 | ||
|
|
5b7fec481b | ||
|
|
73b3bbe49b | ||
|
|
d8dcf670da | ||
|
|
87b9313034 | ||
|
|
993c382e74 | ||
|
|
3c9a7811b8 | ||
|
|
6c8d993477 | ||
|
|
dfa9277867 | ||
|
|
50e37419e9 | ||
|
|
22978aa31e | ||
|
|
7ed401e5e0 | ||
|
|
da76a1ed9e | ||
|
|
9c67e08dbd | ||
|
|
6cf716f182 | ||
|
|
9fb24ac1e9 | ||
|
|
66fb083003 | ||
|
|
20b91f58f8 | ||
|
|
ac0e675f3b | ||
|
|
f71f04db9e | ||
|
|
9e4e98acfb | ||
|
|
826e35f7a4 | ||
|
|
ffc580dda9 | ||
|
|
4557d13a32 | ||
|
|
215c7bd3cb | ||
|
|
ea2ef63de5 | ||
|
|
d9998f2ca5 | ||
|
|
686d6fc6d1 | ||
|
|
9e8df888eb | ||
|
|
409ac12f23 | ||
|
|
6aa26582f6 | ||
|
|
056a45d035 | ||
|
|
fbc839e8d9 | ||
|
|
cb85eea261 | ||
|
|
439b827a08 | ||
|
|
d39d6cc1e3 | ||
|
|
d6b3bfc48e | ||
|
|
70d4fadc39 | ||
|
|
a2a12018d9 | ||
|
|
10d34ef818 | ||
|
|
bf52545a91 | ||
|
|
c012e3d66b | ||
|
|
39a4f82460 | ||
|
|
7b020ffa84 | ||
|
|
b8ccf3dc3a | ||
|
|
869f0a0238 | ||
|
|
ff4ea1a13a | ||
|
|
51aebb2845 | ||
|
|
212f599412 | ||
|
|
55776df685 | ||
|
|
3dd06b674a | ||
|
|
12df799572 | ||
|
|
c341792092 | ||
|
|
afe12dc90b | ||
|
|
45d2d1e97d | ||
|
|
0a302901d2 | ||
|
|
49063f949d | ||
|
|
7699d657d9 | ||
|
|
b2cb3b8bf2 | ||
|
|
6cbaad896c | ||
|
|
9247f88d0c | ||
|
|
92f2e342a3 | ||
|
|
e2f3f5fe63 | ||
|
|
0db75852f3 | ||
|
|
afe688e6ab | ||
|
|
493fc00953 | ||
|
|
c709dc5e8e | ||
|
|
684c59e5bc | ||
|
|
0948b078e1 | ||
|
|
52c0356900 | ||
|
|
1c9a0be8c4 | ||
|
|
f45ec24977 | ||
|
|
75b7e661e7 | ||
|
|
381d7a4300 | ||
|
|
0e6e8461eb | ||
|
|
141456dd89 | ||
|
|
9616dc7bd8 | ||
|
|
379597e78f | ||
|
|
f6067816fb | ||
|
|
750eb76df3 | ||
|
|
79a9bc9076 | ||
|
|
dcb6a0425c | ||
|
|
e15a9f3d7d | ||
|
|
b0f95c63c9 | ||
|
|
5327565b33 | ||
|
|
95047fb083 | ||
|
|
f00b2fd509 | ||
|
|
eb86e7967f | ||
|
|
88874fcfe2 | ||
|
|
d504c1e5ab | ||
|
|
c78db1212b | ||
|
|
be03a6186c | ||
|
|
41a8975bd1 | ||
|
|
254c3d166f | ||
|
|
137cf9e582 | ||
|
|
11e841580f | ||
|
|
f8b9138383 | ||
|
|
c03e4c36b0 | ||
|
|
5530cf6e79 | ||
|
|
1f72237291 | ||
|
|
e427d9f622 | ||
|
|
f88feec02b | ||
|
|
df132e5ff3 | ||
|
|
0ffaa8d667 | ||
|
|
e887149f25 | ||
|
|
250d61e0b3 | ||
|
|
ba05c43ae3 | ||
|
|
82fe530045 | ||
|
|
f91f3d1c81 | ||
|
|
5d39223239 | ||
|
|
d2a7e22efd | ||
|
|
724e411ffc | ||
|
|
c02bfc3897 | ||
|
|
878a20741b | ||
|
|
d5eafe1926 | ||
|
|
e2da4ff257 | ||
|
|
dbb6732743 | ||
|
|
4034aa2c60 | ||
|
|
fcb5037a1d | ||
|
|
0634abf168 | ||
|
|
478fa7cafe | ||
|
|
549fdf63f6 | ||
|
|
1a14841a75 | ||
|
|
a7ed3a5e47 | ||
|
|
884fc4f89c | ||
|
|
1e5cab1ee7 | ||
|
|
5a00f0c657 | ||
|
|
2cbb10d850 | ||
|
|
23cd1b8c66 | ||
|
|
be6f5ce831 | ||
|
|
78a545112a | ||
|
|
2cdabf581e | ||
|
|
34a7f17956 | ||
|
|
dd11434e90 | ||
|
|
61995e3b4e | ||
|
|
13befbd266 | ||
|
|
a5ffd44caf | ||
|
|
0208dff574 | ||
|
|
3157bebed7 | ||
|
|
c0bb4db15c | ||
|
|
27cada2a02 | ||
|
|
153c99217d | ||
|
|
851df11eb5 | ||
|
|
5f2c741f49 | ||
|
|
9a9ecc25db | ||
|
|
34b145ee65 | ||
|
|
f41fe59cb6 | ||
|
|
7ff1fd9d69 | ||
|
|
d0b3cdc835 | ||
|
|
1cf829c889 | ||
|
|
17992b633d | ||
|
|
c545ab4993 | ||
|
|
1d2e4243dc | ||
|
|
aefc34b405 | ||
|
|
2a20cf5379 | ||
|
|
e3a3837164 | ||
|
|
c86ab4694c | ||
|
|
5d5066570c | ||
|
|
1a55fb4170 | ||
|
|
efbc3f8194 | ||
|
|
f755351511 | ||
|
|
57817f7252 | ||
|
|
b4c45aa2e3 | ||
|
|
5295244026 | ||
|
|
082f439db2 | ||
|
|
12697d2b72 | ||
|
|
976b44443a | ||
|
|
6553fb5a40 | ||
|
|
bee06f3507 | ||
|
|
5a750b485a | ||
|
|
a71f44baa5 | ||
|
|
65db3a7bd3 | ||
|
|
22384869a6 | ||
|
|
ff76fbe763 | ||
|
|
cfbab453e8 | ||
|
|
6a59b57ef8 | ||
|
|
f50c786640 | ||
|
|
70aece8522 | ||
|
|
c9eb0f3aab | ||
|
|
206360177f | ||
|
|
34ad837fd9 | ||
|
|
e796157672 | ||
|
|
b51222c004 | ||
|
|
9aad352789 | ||
|
|
ce8c20c1ed | ||
|
|
349afa0e7a | ||
|
|
748a6965ca | ||
|
|
97af7c416e | ||
|
|
47512dd6db | ||
|
|
653b9ed0e4 | ||
|
|
d0e47d9fe0 | ||
|
|
f978368a4e | ||
|
|
c47581fc5a | ||
|
|
31aa357c17 | ||
|
|
6ddfae0a07 | ||
|
|
0d7176792b | ||
|
|
c1542da18a | ||
|
|
5b548f5bc3 | ||
|
|
5ac2005318 | ||
|
|
a2b8e3b34e | ||
|
|
d78b53968f | ||
|
|
61b950d942 | ||
|
|
a16073a87b | ||
|
|
603a90886f | ||
|
|
95bbac8791 | ||
|
|
a69fd21a1a | ||
|
|
b6e33830af | ||
|
|
2c67c1c4f8 | ||
|
|
989deafd5e | ||
|
|
9f1d7f7fc7 | ||
|
|
6245c92bd0 | ||
|
|
2e32e202e9 | ||
|
|
d994ad75e8 | ||
|
|
2caebb3b10 | ||
|
|
05f3eebd96 | ||
|
|
74d05d0adc | ||
|
|
341a0616aa | ||
|
|
ea7f617df6 | ||
|
|
644c64d79d | ||
|
|
d193d70ecf | ||
|
|
9e227a52c0 | ||
|
|
1a767b021b | ||
|
|
83e4006b16 | ||
|
|
1759b0483c | ||
|
|
f7174acc48 | ||
|
|
c2cd718e89 | ||
|
|
c21808dd2d | ||
|
|
2c2e35eec1 | ||
|
|
c064711d2a | ||
|
|
7d6ccca695 | ||
|
|
28c81fc71e | ||
|
|
d5a0610ea2 | ||
|
|
4aebb73de0 | ||
|
|
46e51a81c4 | ||
|
|
83ad59fae7 | ||
|
|
f9a7b6bf26 | ||
|
|
cdb331076a | ||
|
|
ba9a8a9ded | ||
|
|
34bd2cf803 | ||
|
|
69f1d7b360 | ||
|
|
e0bc952c83 | ||
|
|
cf869d9636 | ||
|
|
077c1491a8 | ||
|
|
c04563734e | ||
|
|
1d0d350fc3 | ||
|
|
d55338a3f5 | ||
|
|
c6a3092b45 | ||
|
|
10303259f7 | ||
|
|
3dca2fd61e | ||
|
|
47eac4be1c | ||
|
|
2995867760 | ||
|
|
c132f5a91f | ||
|
|
24587492dd | ||
|
|
44cee0f5f8 | ||
|
|
2c714eace5 | ||
|
|
0d7d7a970d | ||
|
|
3a27ef5e12 | ||
|
|
6d273c8e44 | ||
|
|
c775153e01 | ||
|
|
b71d7c9007 | ||
|
|
ce5f025428 | ||
|
|
6df6aea1ba | ||
|
|
ca2d2db0ef | ||
|
|
1ccb0b5f96 | ||
|
|
c2545b3ae6 | ||
|
|
dada872981 | ||
|
|
1eec5161bd | ||
|
|
53c3644c29 | ||
|
|
6d66dde208 | ||
|
|
1b349f79ac | ||
|
|
da8be82c9a | ||
|
|
8ffd244ef6 | ||
|
|
bf9d31ce49 | ||
|
|
98a32f5e52 | ||
|
|
dc1737f128 | ||
|
|
48634d7e4a | ||
|
|
ecf0cdaba4 | ||
|
|
286cb90c48 | ||
|
|
3f77cde50e | ||
|
|
1145654987 | ||
|
|
da4cfb9c32 | ||
|
|
58375bc87a | ||
|
|
83d99ce5bd | ||
|
|
dca30815b0 | ||
|
|
edeb759bb1 | ||
|
|
610d4d9473 | ||
|
|
f30e572e00 | ||
|
|
34cd8b125a | ||
|
|
b0544dbfff | ||
|
|
a7bdfc06ca | ||
|
|
7e7cb40909 | ||
|
|
724fa4a7d4 | ||
|
|
cee0645fd1 | ||
|
|
df9409b8a2 | ||
|
|
f274a70edf | ||
|
|
ef24a27ade | ||
|
|
670d6ce8f4 | ||
|
|
f3917f2122 | ||
|
|
5d6e56b67c | ||
|
|
624303bfb9 | ||
|
|
eb3c132fc5 | ||
|
|
170def35d7 | ||
|
|
2ee9fb0675 | ||
|
|
1396d2a39b | ||
|
|
7ecc41db9c | ||
|
|
7ffe4eda12 | ||
|
|
25756afad5 | ||
|
|
8880298f50 | ||
|
|
d89355f0a6 | ||
|
|
ae91f6610f | ||
|
|
6e7143e0f5 | ||
|
|
f55f56f260 | ||
|
|
6287f2b71b | ||
|
|
7e781f24c5 | ||
|
|
3bf7c5aea1 | ||
|
|
092dbda88a | ||
|
|
cb687c208c | ||
|
|
945b4d7139 | ||
|
|
881f828250 | ||
|
|
0743dab3f0 | ||
|
|
496e37d044 | ||
|
|
1263bd5dcb | ||
|
|
9ee78b1a92 | ||
|
|
406b2fe6dc | ||
|
|
90f2259f5e | ||
|
|
948f4978e7 | ||
|
|
32ae0c51f0 | ||
|
|
fe4a97f245 | ||
|
|
2f3528c076 | ||
|
|
1964bcb13f | ||
|
|
4b779ac142 | ||
|
|
abc2d442dd | ||
|
|
b64f1fc5c4 | ||
|
|
33d264eaa7 | ||
|
|
5e3b8c3233 | ||
|
|
bbdfb7853d | ||
|
|
a19b152e4a | ||
|
|
1468001d3b | ||
|
|
7faa3c367d | ||
|
|
fd379db846 |
65
.clang-format
Normal file
65
.clang-format
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
|
||||||
|
AccessModifierOffset: -2
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveMacros: true
|
||||||
|
AlignConsecutiveAssignments: true
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: false
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllArgumentsOnNextLine: true
|
||||||
|
AllowAllConstructorInitializersOnNextLine: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: true
|
||||||
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AllowShortLambdasOnASingleLine: All
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeTernaryOperators: false
|
||||||
|
BreakConstructorInitializers: AfterColon
|
||||||
|
ColumnLimit: 180
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: false
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentWidth: 4
|
||||||
|
PointerAlignment: Left
|
||||||
|
ReflowComments: false
|
||||||
|
SortIncludes: false
|
||||||
|
SortUsingDeclarations: false
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInContainerLiterals: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Auto
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Never
|
||||||
|
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
|
|
||||||
|
BraceWrapping:
|
||||||
|
AfterEnum: false
|
||||||
|
|
||||||
|
AlignConsecutiveDeclarations: AcrossEmptyLines
|
||||||
|
|
||||||
|
NamespaceIndentation: All
|
||||||
55
.github/workflows/ci.yaml
vendored
55
.github/workflows/ci.yaml
vendored
@@ -12,15 +12,14 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
||||||
pacman --noconfirm --noprogressbar -Syyu
|
pacman --noconfirm --noprogressbar -Syyu
|
||||||
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd
|
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd python libliftoff
|
||||||
- name: Set up user
|
- name: Set up user
|
||||||
run: |
|
run: |
|
||||||
useradd -m githubuser
|
useradd -m githubuser
|
||||||
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
|
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
|
||||||
- name: Build wlroots
|
- name: Install libdisplay-info from the AUR
|
||||||
run: |
|
run: |
|
||||||
su githubuser -c "cd ~ && git clone https://gitlab.freedesktop.org/wlroots/wlroots"
|
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
|
||||||
su githubuser -c "cd ~/wlroots && meson build/ --prefix=/usr && ninja -C build/ && sudo ninja -C build/ install && cd .."
|
|
||||||
- name: Fix permissions for git
|
- name: Fix permissions for git
|
||||||
run: |
|
run: |
|
||||||
git config --global --add safe.directory /__w/Hyprland/Hyprland
|
git config --global --add safe.directory /__w/Hyprland/Hyprland
|
||||||
@@ -41,7 +40,7 @@ jobs:
|
|||||||
cp ./LICENSE hyprland/
|
cp ./LICENSE hyprland/
|
||||||
cp build/Hyprland hyprland/
|
cp build/Hyprland hyprland/
|
||||||
cp hyprctl/hyprctl hyprland/
|
cp hyprctl/hyprctl hyprland/
|
||||||
cp subprojects/wlroots/build/libwlroots.so.11032 hyprland/
|
cp subprojects/wlroots/build/libwlroots.so.12032 hyprland/
|
||||||
cp build/Hyprland hyprland/
|
cp build/Hyprland hyprland/
|
||||||
cp -r example/ hyprland/
|
cp -r example/ hyprland/
|
||||||
cp -r assets/ hyprland/
|
cp -r assets/ hyprland/
|
||||||
@@ -62,7 +61,14 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
||||||
pacman --noconfirm --noprogressbar -Syyu
|
pacman --noconfirm --noprogressbar -Syyu
|
||||||
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd
|
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd cmake jq python libliftoff
|
||||||
|
- name: Set up user
|
||||||
|
run: |
|
||||||
|
useradd -m githubuser
|
||||||
|
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
|
||||||
|
- name: Install libdisplay-info from the AUR
|
||||||
|
run: |
|
||||||
|
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
|
||||||
- name: Checkout Hyprland
|
- name: Checkout Hyprland
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
@@ -73,13 +79,30 @@ jobs:
|
|||||||
-Ddefault_library=static
|
-Ddefault_library=static
|
||||||
- name: Compile
|
- name: Compile
|
||||||
run: ninja -C obj-x86_64-pc-linux-gnu
|
run: ninja -C obj-x86_64-pc-linux-gnu
|
||||||
# - name: Compress artifacts
|
|
||||||
# run: |
|
noxwayland:
|
||||||
# mkdir x86_64-pc-linux-gnu
|
name: "Build Hyprland in pure Wayland (Arch)"
|
||||||
# DESTDIR=$PWD/x86_64-pc-linux-gnu meson install -C obj-x86_64-pc-linux-gnu --tags runtime
|
runs-on: ubuntu-latest
|
||||||
# tar -cvf x86_64-pc-linux-gnu.tar.xz x86_64-pc-linux-gnu
|
container:
|
||||||
# - name: Upload artifacts
|
image: archlinux
|
||||||
# uses: actions/upload-artifact@v3
|
steps:
|
||||||
# with:
|
- name: Download dependencies
|
||||||
# name: Build artifacts (x86_64-pc-linux-gnu)
|
run: |
|
||||||
# path: x86_64-pc-linux-gnu.tar.xz
|
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
||||||
|
pacman --noconfirm --noprogressbar -Syyu
|
||||||
|
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd libliftoff
|
||||||
|
- name: Set up user
|
||||||
|
run: |
|
||||||
|
useradd -m githubuser
|
||||||
|
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
|
||||||
|
- name: Install libdisplay-info from the AUR
|
||||||
|
run: |
|
||||||
|
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
|
||||||
|
- name: Checkout Hyprland
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
- name: Configure
|
||||||
|
run: mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DNO_XWAYLAND:STRING=true -H./ -B./build -G Ninja
|
||||||
|
- name: Compile
|
||||||
|
run: make config && make release
|
||||||
|
|||||||
30
.github/workflows/flawfinder.yml
vendored
30
.github/workflows/flawfinder.yml
vendored
@@ -1,30 +0,0 @@
|
|||||||
name: Flawfinder
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ main ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ main ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
flawfinder:
|
|
||||||
name: Flawfinder Checks
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Scan with Flawfinder
|
|
||||||
uses: david-a-wheeler/flawfinder@8e4a779ad59dbfaee5da586aa9210853b701959c
|
|
||||||
with:
|
|
||||||
arguments: '--sarif ./'
|
|
||||||
output: 'flawfinder_results.sarif'
|
|
||||||
|
|
||||||
- name: Upload analysis results to GitHub Security tab
|
|
||||||
uses: github/codeql-action/upload-sarif@v2
|
|
||||||
with:
|
|
||||||
sarif_file: ${{github.workspace}}/flawfinder_results.sarif
|
|
||||||
16
.github/workflows/nix-build.yaml
vendored
16
.github/workflows/nix-build.yaml
vendored
@@ -5,26 +5,22 @@ jobs:
|
|||||||
nix:
|
nix:
|
||||||
name: "Build Hyprland (Nix)"
|
name: "Build Hyprland (Nix)"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
package:
|
|
||||||
- default
|
|
||||||
- hyprland-no-hidpi
|
|
||||||
steps:
|
steps:
|
||||||
- name: Clone repository
|
- name: Clone repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Install nix
|
- name: Install nix
|
||||||
uses: cachix/install-nix-action@v17
|
uses: cachix/install-nix-action@v20
|
||||||
with:
|
with:
|
||||||
install_url: https://releases.nixos.org/nix/nix-2.10.3/install
|
install_url: https://nixos.org/nix/install
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
auto-optimise-store = true
|
auto-optimise-store = true
|
||||||
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
experimental-features = nix-command flakes
|
experimental-features = nix-command flakes
|
||||||
- uses: cachix/cachix-action@v10
|
- uses: cachix/cachix-action@v12
|
||||||
with:
|
with:
|
||||||
name: hyprland
|
name: hyprland
|
||||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||||
- name: Build Hyprland with default settings
|
- name: Build packages
|
||||||
run: nix build .#${{ matrix.package }} --print-build-logs
|
run: nix flake check --print-build-logs --accept-flake-config
|
||||||
|
|||||||
26
.github/workflows/nix-meson-ver-update.yaml
vendored
26
.github/workflows/nix-meson-ver-update.yaml
vendored
@@ -1,26 +0,0 @@
|
|||||||
name: "Nix & Meson: update version"
|
|
||||||
|
|
||||||
on: [workflow_dispatch]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Clone repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- name: Update flake and meson version
|
|
||||||
run: |
|
|
||||||
REGEX="([0-9]+(\.[0-9a-zA-Z]+)+)"
|
|
||||||
|
|
||||||
CRT_REV=$(git show-ref --tags --head --abbrev | head -n 1 | head -c 7)
|
|
||||||
TAG_REV=$(git show-ref --tags --abbrev | tail -n 1 | head -c 7)
|
|
||||||
CRT_VER=$(sed -nEe "/$REGEX/{p;q;}" meson.build | awk -F\' '{print $2}')
|
|
||||||
VERSION=$(git show-ref --tags --abbrev | tail -n 1 | tail -c +20)
|
|
||||||
|
|
||||||
if [[ $TAG_REV = $CRT_REV ]] || [[ $CRT_VER != $VERSION ]]; then
|
|
||||||
sed -Ei "s/$REGEX/$VERSION/g" meson.build
|
|
||||||
sed -Ei "s/$REGEX/$VERSION/g" flake.nix
|
|
||||||
fi
|
|
||||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
|
||||||
with:
|
|
||||||
commit_message: "[gha] bump flake and meson version"
|
|
||||||
11
.github/workflows/nix-update.yaml
vendored
11
.github/workflows/nix-update.yaml
vendored
@@ -9,14 +9,21 @@ jobs:
|
|||||||
- name: Clone repository
|
- name: Clone repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Install nix
|
- name: Install nix
|
||||||
uses: cachix/install-nix-action@v17
|
uses: cachix/install-nix-action@v20
|
||||||
with:
|
with:
|
||||||
install_url: https://releases.nixos.org/nix/nix-2.8.0/install
|
install_url: https://nixos.org/nix/install
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
auto-optimise-store = true
|
auto-optimise-store = true
|
||||||
|
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
||||||
experimental-features = nix-command flakes
|
experimental-features = nix-command flakes
|
||||||
- name: Update lockfile
|
- name: Update lockfile
|
||||||
run: nix/update-inputs.sh
|
run: nix/update-inputs.sh
|
||||||
|
- uses: cachix/cachix-action@v12
|
||||||
|
with:
|
||||||
|
name: hyprland
|
||||||
|
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||||
|
- name: Build Waybar-Hyprland
|
||||||
|
run: nix build .#waybar-hyprland --print-build-logs
|
||||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||||
with:
|
with:
|
||||||
commit_message: "[gha] bump flake inputs"
|
commit_message: "[gha] bump flake inputs"
|
||||||
|
|||||||
4
.github/workflows/release.yaml
vendored
4
.github/workflows/release.yaml
vendored
@@ -17,7 +17,9 @@ jobs:
|
|||||||
|
|
||||||
- name: Create tarball with submodules
|
- name: Create tarball with submodules
|
||||||
id: tar
|
id: tar
|
||||||
run: tar -czv --owner=0 --group=0 --no-same-owner --no-same-permissions -f source.tar.gz *
|
run: |
|
||||||
|
sed -i "1s/^/#define GIT_COMMIT_HASH $(git rev-parse HEAD)\n#define GIT_TAG \"$(git describe --tags)\"\n/" ./src/defines.hpp
|
||||||
|
mkdir hyprland-source; mv ./* ./hyprland-source || tar -czv --owner=0 --group=0 --no-same-owner --no-same-permissions -f source.tar.gz *
|
||||||
|
|
||||||
- id: whatrelease
|
- id: whatrelease
|
||||||
name: Get latest release
|
name: Get latest release
|
||||||
|
|||||||
76
.github/workflows/security-checks.yml
vendored
Normal file
76
.github/workflows/security-checks.yml
vendored
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
name: Security Checks
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
flawfinder:
|
||||||
|
name: Flawfinder Checks
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Scan with Flawfinder
|
||||||
|
uses: david-a-wheeler/flawfinder@8e4a779ad59dbfaee5da586aa9210853b701959c
|
||||||
|
with:
|
||||||
|
arguments: '--sarif ./'
|
||||||
|
output: 'flawfinder_results.sarif'
|
||||||
|
|
||||||
|
- name: Upload analysis results to GitHub Security tab
|
||||||
|
uses: github/codeql-action/upload-sarif@v2
|
||||||
|
with:
|
||||||
|
sarif_file: ${{github.workspace}}/flawfinder_results.sarif
|
||||||
|
|
||||||
|
codeql:
|
||||||
|
name: CodeQL
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: archlinux
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'cpp' ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
|
||||||
|
- name: Init Hyprland build
|
||||||
|
run: |
|
||||||
|
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
||||||
|
pacman --noconfirm --noprogressbar -Syyu
|
||||||
|
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd python libliftoff
|
||||||
|
useradd -m githubuser
|
||||||
|
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
|
||||||
|
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
|
||||||
|
git config --global --add safe.directory /__w/Hyprland/Hyprland
|
||||||
|
|
||||||
|
- name: Checkout Hyprland
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Build Hyprland
|
||||||
|
run: |
|
||||||
|
git submodule sync --recursive && git submodule update --init --force --recursive
|
||||||
|
make all
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
||||||
|
with:
|
||||||
|
category: "/language:${{matrix.language}}"
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -12,6 +12,7 @@ _deps
|
|||||||
build/
|
build/
|
||||||
result*
|
result*
|
||||||
/.vscode/
|
/.vscode/
|
||||||
|
/.idea/
|
||||||
.envrc
|
.envrc
|
||||||
.cache
|
.cache
|
||||||
|
|
||||||
@@ -19,9 +20,12 @@ result*
|
|||||||
*-protocol.c
|
*-protocol.c
|
||||||
*-protocol.h
|
*-protocol.h
|
||||||
.ccls-cache
|
.ccls-cache
|
||||||
|
*.so
|
||||||
|
|
||||||
hyprctl/hyprctl
|
hyprctl/hyprctl
|
||||||
|
|
||||||
gmon.out
|
gmon.out
|
||||||
*.out
|
*.out
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
|
|
||||||
|
PKGBUILD
|
||||||
|
|||||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,3 +1,9 @@
|
|||||||
[submodule "wlroots"]
|
[submodule "wlroots"]
|
||||||
path = subprojects/wlroots
|
path = subprojects/wlroots
|
||||||
url = https://gitlab.freedesktop.org/wlroots/wlroots.git
|
url = https://gitlab.freedesktop.org/wlroots/wlroots.git
|
||||||
|
[submodule "subprojects/hyprland-protocols"]
|
||||||
|
path = subprojects/hyprland-protocols
|
||||||
|
url = https://github.com/hyprwm/hyprland-protocols
|
||||||
|
[submodule "subprojects/udis86"]
|
||||||
|
path = subprojects/udis86
|
||||||
|
url = https://github.com/canihavesomecoffee/udis86
|
||||||
|
|||||||
182
CMakeLists.txt
182
CMakeLists.txt
@@ -1,11 +1,22 @@
|
|||||||
cmake_minimum_required(VERSION 3.4)
|
cmake_minimum_required(VERSION 3.19)
|
||||||
project(Hyprland
|
include(CheckIncludeFile)
|
||||||
|
|
||||||
|
# Get version
|
||||||
|
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/props.json PROPS)
|
||||||
|
string(JSON VER GET ${PROPS} version)
|
||||||
|
|
||||||
|
project(Hyprland
|
||||||
DESCRIPTION "A Modern C++ Wayland Compositor"
|
DESCRIPTION "A Modern C++ Wayland Compositor"
|
||||||
|
VERSION ${VER}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(HYPRLAND_VERSION ${VER})
|
||||||
|
set(PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||||
|
configure_file(hyprland.pc.in hyprland.pc @ONLY)
|
||||||
|
|
||||||
set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")
|
set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")
|
||||||
|
|
||||||
message(STATUS "Configuring Hyprland!")
|
message(STATUS "Gathering git info")
|
||||||
|
|
||||||
# Get git info
|
# Get git info
|
||||||
# hash and branch
|
# hash and branch
|
||||||
@@ -22,54 +33,116 @@ execute_process(
|
|||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND bash -c "git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1"
|
COMMAND sh -c "git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1 | sed -e 's/#//g' -e 's/\"//g'"
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
OUTPUT_VARIABLE GIT_COMMIT_MESSAGE
|
OUTPUT_VARIABLE GIT_COMMIT_MESSAGE
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND bash -c "git diff-index --quiet HEAD -- || echo \"dirty\""
|
COMMAND sh -c "git diff-index --quiet HEAD -- || echo \"dirty\""
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
OUTPUT_VARIABLE GIT_DIRTY
|
OUTPUT_VARIABLE GIT_DIRTY
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND sh -c "git describe --tags"
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE GIT_TAG
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
include_directories(. PRIVATE "subprojects/wlroots/include/")
|
find_program(WaylandScanner NAMES wayland-scanner)
|
||||||
include_directories(. PRIVATE "subprojects/wlroots/build/include/")
|
message(STATUS "Found WaylandScanner at ${WaylandScanner}")
|
||||||
add_compile_options(-std=c++23 -DWLR_USE_UNSTABLE )
|
execute_process(
|
||||||
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing)
|
COMMAND pkg-config --variable=pkgdatadir wayland-protocols
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE WAYLAND_PROTOCOLS_DIR
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
|
||||||
|
|
||||||
|
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||||
|
message(STATUS "Configuring Hyprland in Debug with CMake")
|
||||||
|
add_compile_definitions(HYPRLAND_DEBUG)
|
||||||
|
else()
|
||||||
|
add_compile_options(-O3)
|
||||||
|
message(STATUS "Configuring Hyprland in Release with CMake")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
.
|
||||||
|
"subprojects/wlroots/include/"
|
||||||
|
"subprojects/wlroots/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)
|
||||||
|
add_link_options(-rdynamic)
|
||||||
|
set(CMAKE_ENABLE_EXPORTS TRUE)
|
||||||
|
|
||||||
|
message(STATUS "Checking deps...")
|
||||||
|
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo libdrm egl xkbcommon libinput xcb) # we do not check for wlroots, as we provide it ourselves
|
find_package(OpenGL REQUIRED)
|
||||||
|
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1) # we do not check for wlroots, as we provide it ourselves
|
||||||
|
|
||||||
file(GLOB_RECURSE SRCFILES "src/*.cpp")
|
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||||
|
|
||||||
add_executable(Hyprland ${SRCFILES})
|
add_executable(Hyprland ${SRCFILES})
|
||||||
|
|
||||||
IF(LEGACY_RENDERER MATCHES true)
|
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||||
|
message(STATUS "Setting debug flags")
|
||||||
|
|
||||||
|
target_link_libraries(Hyprland asan)
|
||||||
|
|
||||||
|
add_compile_options(-pg -no-pie -fno-builtin -fsanitize=address)
|
||||||
|
add_link_options(-pg -no-pie -fno-builtin)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(CheckLibraryExists)
|
||||||
|
check_library_exists(execinfo backtrace "" HAVE_LIBEXECINFO)
|
||||||
|
if(HAVE_LIBEXECINFO)
|
||||||
|
target_link_libraries(Hyprland execinfo)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(LEGACY_RENDERER)
|
||||||
message(STATUS "Using the legacy GLES2 renderer!")
|
message(STATUS "Using the legacy GLES2 renderer!")
|
||||||
add_definitions( -DLEGACY_RENDERER )
|
add_compile_definitions(LEGACY_RENDERER)
|
||||||
ENDIF(LEGACY_RENDERER MATCHES true)
|
endif()
|
||||||
|
|
||||||
IF(NO_XWAYLAND MATCHES true)
|
if(NO_XWAYLAND)
|
||||||
message(STATUS "Using the NO_XWAYLAND flag, disabling XWayland!")
|
message(STATUS "Using the NO_XWAYLAND flag, disabling XWayland!")
|
||||||
add_definitions( -DNO_XWAYLAND )
|
add_compile_definitions(NO_XWAYLAND)
|
||||||
ENDIF(NO_XWAYLAND MATCHES true)
|
else()
|
||||||
|
message(STATUS "XWAYLAND Enabled (NO_XWAYLAND not defined) checking deps...")
|
||||||
|
pkg_check_modules(xcbdep REQUIRED IMPORTED_TARGET xcb)
|
||||||
|
target_link_libraries(Hyprland PkgConfig::xcbdep)
|
||||||
|
endif()
|
||||||
|
|
||||||
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
if(NO_SYSTEMD)
|
||||||
message(STATUS "Configuring Hyprland in Debug with CMake!")
|
message(STATUS "SYSTEMD support is disabled...")
|
||||||
add_definitions( -DHYPRLAND_DEBUG )
|
else()
|
||||||
ELSE()
|
message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined) checking deps...")
|
||||||
add_compile_options( -O3 )
|
pkg_check_modules(LIBSYSTEMD libsystemd)
|
||||||
message(STATUS "Configuring Hyprland in Release with CMake!")
|
check_include_file("systemd/sd-daemon.h" SYSTEMDH)
|
||||||
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
if(LIBSYSTEMD_FOUND AND SYSTEMDH)
|
||||||
|
add_compile_definitions(USES_SYSTEMD)
|
||||||
|
target_link_libraries(Hyprland "${LIBSYSTEMD_LIBRARIES}")
|
||||||
|
else()
|
||||||
|
message(WARNING "Systemd support requested but libsystemd or systemd headers were not found")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
target_compile_definitions(Hyprland PRIVATE "-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"")
|
target_compile_definitions(Hyprland
|
||||||
target_compile_definitions(Hyprland PRIVATE "-DGIT_BRANCH=\"${GIT_BRANCH}\"")
|
PRIVATE
|
||||||
target_compile_definitions(Hyprland PRIVATE "-DGIT_COMMIT_MESSAGE=\"${GIT_COMMIT_MESSAGE}\"")
|
"GIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\""
|
||||||
target_compile_definitions(Hyprland PRIVATE "-DGIT_DIRTY=\"${GIT_DIRTY}\"")
|
"GIT_BRANCH=\"${GIT_BRANCH}\""
|
||||||
|
"GIT_COMMIT_MESSAGE=\"${GIT_COMMIT_MESSAGE}\""
|
||||||
|
"GIT_DIRTY=\"${GIT_DIRTY}\""
|
||||||
|
"GIT_TAG=\"${GIT_TAG}\"")
|
||||||
|
|
||||||
target_link_libraries(Hyprland rt)
|
target_link_libraries(Hyprland rt)
|
||||||
|
|
||||||
@@ -77,20 +150,49 @@ set(CPACK_PROJECT_NAME ${PROJECT_NAME})
|
|||||||
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
|
||||||
|
message(STATUS "Setting link libraries")
|
||||||
|
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
target_link_libraries(Hyprland PkgConfig::deps)
|
target_link_libraries(Hyprland PkgConfig::deps)
|
||||||
|
|
||||||
target_link_libraries(Hyprland
|
target_link_libraries(Hyprland
|
||||||
${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.11032 # wlroots is provided by us
|
${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.12032 # wlroots is provided by us
|
||||||
pixman-1
|
OpenGL::EGL
|
||||||
OpenGL
|
OpenGL::GL
|
||||||
GLESv2
|
Threads::Threads
|
||||||
pthread
|
${CMAKE_SOURCE_DIR}/subprojects/udis86/build/libudis86/liblibudis86.a
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
|
||||||
${CMAKE_SOURCE_DIR}/ext-workspace-unstable-v1-protocol.o
|
|
||||||
)
|
)
|
||||||
|
|
||||||
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
protocol("protocols/ext-workspace-unstable-v1.xml" "ext-workspace-unstable-v1" true)
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg -no-pie -fno-builtin")
|
protocol("protocols/idle.xml" "idle" true)
|
||||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg -no-pie -fno-builtin")
|
protocol("protocols/pointer-constraints-unstable-v1.xml" "pointer-constraints-unstable-v1" true)
|
||||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg -no-pie -fno-builtin")
|
protocol("protocols/tablet-unstable-v2.xml" "tablet-unstable-v2" true)
|
||||||
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
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("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1" false)
|
||||||
|
protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false)
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
|||||||
BSD 3-Clause License
|
BSD 3-Clause License
|
||||||
|
|
||||||
Copyright (c) 2022, vaxerski
|
Copyright (c) 2022-2023, vaxerski
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|||||||
218
Makefile
218
Makefile
@@ -1,187 +1,123 @@
|
|||||||
include config.mk
|
PREFIX = /usr/local
|
||||||
|
|
||||||
CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99
|
|
||||||
|
|
||||||
WAYLAND_PROTOCOLS=$(shell pkg-config --variable=pkgdatadir wayland-protocols)
|
|
||||||
WAYLAND_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner)
|
|
||||||
|
|
||||||
PKGS = wlroots wayland-server xcb xkbcommon libinput
|
|
||||||
CFLAGS += $(foreach p,$(PKGS),$(shell pkg-config --cflags $(p)))
|
|
||||||
LDLIBS += $(foreach p,$(PKGS),$(shell pkg-config --libs $(p)))
|
|
||||||
|
|
||||||
DATE=$(shell date "+%d %b %Y")
|
|
||||||
|
|
||||||
xdg-shell-protocol.h:
|
|
||||||
$(WAYLAND_SCANNER) server-header \
|
|
||||||
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
|
|
||||||
|
|
||||||
xdg-shell-protocol.c:
|
|
||||||
$(WAYLAND_SCANNER) private-code \
|
|
||||||
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
|
|
||||||
|
|
||||||
xdg-shell-protocol.o: xdg-shell-protocol.h
|
|
||||||
|
|
||||||
wlr-layer-shell-unstable-v1-protocol.h:
|
|
||||||
$(WAYLAND_SCANNER) server-header \
|
|
||||||
protocols/wlr-layer-shell-unstable-v1.xml $@
|
|
||||||
|
|
||||||
wlr-layer-shell-unstable-v1-protocol.c:
|
|
||||||
$(WAYLAND_SCANNER) private-code \
|
|
||||||
protocols/wlr-layer-shell-unstable-v1.xml $@
|
|
||||||
|
|
||||||
wlr-layer-shell-unstable-v1-protocol.o: wlr-layer-shell-unstable-v1-protocol.h
|
|
||||||
|
|
||||||
wlr-screencopy-unstable-v1-protocol.h:
|
|
||||||
$(WAYLAND_SCANNER) server-header \
|
|
||||||
protocols/wlr-screencopy-unstable-v1.xml $@
|
|
||||||
|
|
||||||
wlr-screencopy-unstable-v1-protocol.c:
|
|
||||||
$(WAYLAND_SCANNER) private-code \
|
|
||||||
protocols/wlr-screencopy-unstable-v1.xml $@
|
|
||||||
|
|
||||||
wlr-screencopy-unstable-v1-protocol.o: wlr-screencopy-unstable-v1-protocol.h
|
|
||||||
|
|
||||||
ext-workspace-unstable-v1-protocol.h:
|
|
||||||
$(WAYLAND_SCANNER) server-header \
|
|
||||||
protocols/ext-workspace-unstable-v1.xml $@
|
|
||||||
|
|
||||||
ext-workspace-unstable-v1-protocol.c:
|
|
||||||
$(WAYLAND_SCANNER) private-code \
|
|
||||||
protocols/ext-workspace-unstable-v1.xml $@
|
|
||||||
|
|
||||||
ext-workspace-unstable-v1-protocol.o: ext-workspace-unstable-v1-protocol.h
|
|
||||||
|
|
||||||
pointer-constraints-unstable-v1-protocol.h:
|
|
||||||
$(WAYLAND_SCANNER) server-header \
|
|
||||||
protocols/pointer-constraints-unstable-v1.xml $@
|
|
||||||
|
|
||||||
pointer-constraints-unstable-v1-protocol.c:
|
|
||||||
$(WAYLAND_SCANNER) private-code \
|
|
||||||
protocols/pointer-constraints-unstable-v1.xml $@
|
|
||||||
|
|
||||||
pointer-constraints-unstable-v1-protocol.o: pointer-constraints-unstable-v1-protocol.h
|
|
||||||
|
|
||||||
tablet-unstable-v2-protocol.h:
|
|
||||||
$(WAYLAND_SCANNER) server-header \
|
|
||||||
protocols/tablet-unstable-v2.xml $@
|
|
||||||
|
|
||||||
tablet-unstable-v2-protocol.c:
|
|
||||||
$(WAYLAND_SCANNER) private-code \
|
|
||||||
protocols/tablet-unstable-v2.xml $@
|
|
||||||
|
|
||||||
tablet-unstable-v2-protocol.o: tablet-unstable-v2-protocol.h
|
|
||||||
|
|
||||||
idle-protocol.h:
|
|
||||||
$(WAYLAND_SCANNER) server-header \
|
|
||||||
protocols/idle.xml $@
|
|
||||||
|
|
||||||
idle-protocol.c:
|
|
||||||
$(WAYLAND_SCANNER) private-code \
|
|
||||||
protocols/idle.xml $@
|
|
||||||
|
|
||||||
idle-protocol.o: idle-protocol.h
|
|
||||||
|
|
||||||
wlr-output-power-management-unstable-v1-protocol.h:
|
|
||||||
$(WAYLAND_SCANNER) server-header \
|
|
||||||
protocols/wlr-output-power-management-unstable-v1.xml $@
|
|
||||||
|
|
||||||
wlr-output-power-management-unstable-v1-protocol.c:
|
|
||||||
$(WAYLAND_SCANNER) private-code \
|
|
||||||
protocols/wlr-output-power-management-unstable-v1.xml $@
|
|
||||||
|
|
||||||
wlr-output-power-management-unstable-v1-protocol.o: wlr-output-power-management-unstable-v1-protocol.h
|
|
||||||
|
|
||||||
legacyrenderer:
|
legacyrenderer:
|
||||||
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:STRING=true -H./ -B./build -G Ninja
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||||
cmake --build ./build --config Release --target all -j $(nproc)
|
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
|
|
||||||
legacyrendererdebug:
|
legacyrendererdebug:
|
||||||
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DLEGACY_RENDERER:STRING=true -H./ -B./build -G Ninja
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||||
cmake --build ./build --config Release --target all -j $(nproc)
|
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
|
|
||||||
release:
|
release:
|
||||||
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -H./ -B./build -G Ninja
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja
|
||||||
cmake --build ./build --config Release --target all -j $(nproc)
|
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -H./ -B./build -G Ninja
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -S . -B ./build -G Ninja
|
||||||
cmake --build ./build --config Debug --target all -j $(nproc)
|
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
|
|
||||||
clear:
|
clear:
|
||||||
rm -rf build
|
rm -rf build
|
||||||
rm -f *.o *-protocol.h *-protocol.c
|
rm -f ./protocols/*-protocol.h ./protocols/*-protocol.c
|
||||||
rm -f ./hyprctl/hyprctl
|
rm -f ./hyprctl/hyprctl
|
||||||
rm -rf ./subprojects/wlroots/build
|
rm -rf ./subprojects/wlroots/build
|
||||||
|
|
||||||
all:
|
all:
|
||||||
make config
|
$(MAKE) clear
|
||||||
make release
|
$(MAKE) fixwlr
|
||||||
cd ./hyprctl && make all && cd ..
|
cd ./subprojects/wlroots && meson setup build/ --buildtype=release && ninja -C build/ && mkdir -p ${PREFIX}/lib/ && cp ./build/libwlroots.so.12032 ${PREFIX}/lib/ || echo "Could not install libwlroots to ${PREFIX}/lib/libwlroots.so.12032"
|
||||||
|
cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
|
$(MAKE) release
|
||||||
|
$(MAKE) -C hyprctl all
|
||||||
|
|
||||||
install:
|
install:
|
||||||
make clear
|
$(MAKE) clear
|
||||||
make fixwlr
|
$(MAKE) fixwlr
|
||||||
cd ./subprojects/wlroots && meson build/ --buildtype=release && ninja -C build/ && cp ./build/libwlroots.so.11032 /usr/lib/ && cd ../..
|
cd ./subprojects/wlroots && meson setup build/ --buildtype=release && ninja -C build/ && mkdir -p ${PREFIX}/lib/ && cp ./build/libwlroots.so.12032 ${PREFIX}/lib/ || echo "Could not install libwlroots to ${PREFIX}/lib/libwlroots.so.12032"
|
||||||
make protocols
|
cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` && cd ../..
|
||||||
make release
|
$(MAKE) release
|
||||||
cd hyprctl && make all && cd ..
|
$(MAKE) -C hyprctl all
|
||||||
|
|
||||||
mkdir -p /usr/share/wayland-sessions
|
mkdir -p ${PREFIX}/share/wayland-sessions
|
||||||
cp ./example/hyprland.desktop /usr/share/wayland-sessions/
|
|
||||||
mkdir -p ${PREFIX}/bin
|
mkdir -p ${PREFIX}/bin
|
||||||
cp ./build/Hyprland ${PREFIX}/bin
|
cp -f ./build/Hyprland ${PREFIX}/bin
|
||||||
cp ./hyprctl/hyprctl ${PREFIX}/bin
|
cp -f ./hyprctl/hyprctl ${PREFIX}/bin
|
||||||
|
if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi
|
||||||
mkdir -p ${PREFIX}/share/hyprland
|
mkdir -p ${PREFIX}/share/hyprland
|
||||||
cp ./assets/wall_2K.png ${PREFIX}/share/hyprland
|
cp ./assets/wall_2K.png ${PREFIX}/share/hyprland
|
||||||
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
|
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
|
||||||
cp ./assets/wall_8K.png ${PREFIX}/share/hyprland
|
cp ./assets/wall_8K.png ${PREFIX}/share/hyprland
|
||||||
|
|
||||||
install -Dm644 -t ${PREFIX}/share/man/man1 ./docs/*.1
|
mkdir -p ${PREFIX}/share/man/man1
|
||||||
|
install -m644 ./docs/*.1 ${PREFIX}/share/man/man1
|
||||||
|
|
||||||
|
mkdir -p ${PREFIX}/include/hyprland
|
||||||
|
mkdir -p ${PREFIX}/include/hyprland/protocols
|
||||||
|
mkdir -p ${PREFIX}/include/hyprland/wlroots
|
||||||
|
mkdir -p ${PREFIX}/share/pkgconfig
|
||||||
|
|
||||||
|
find src -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland
|
||||||
|
cd subprojects/wlroots/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots && cd ../../..
|
||||||
|
cp ./protocols/*-protocol.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
|
||||||
|
|
||||||
cleaninstall:
|
cleaninstall:
|
||||||
make clear
|
echo -en "$(MAKE) cleaninstall has been DEPRECATED, you should avoid using it in the future.\nRunning $(MAKE) install instead...\n"
|
||||||
make fixwlr
|
$(MAKE) install
|
||||||
cd ./subprojects/wlroots && meson build/ --buildtype=release && ninja -C build/ && cp ./build/libwlroots.so.11032 /usr/lib/ && cd ../..
|
|
||||||
make protocols
|
|
||||||
make release
|
|
||||||
cd hyprctl && make all && cd ..
|
|
||||||
|
|
||||||
mkdir -p /usr/share/wayland-sessions
|
|
||||||
mkdir -p ${PREFIX}/bin
|
|
||||||
cp ./build/Hyprland ${PREFIX}/bin
|
|
||||||
cp ./hyprctl/hyprctl ${PREFIX}/bin
|
|
||||||
mkdir -p ${PREFIX}/share/hyprland
|
|
||||||
cp ./assets/wall_2K.png ${PREFIX}/share/hyprland
|
|
||||||
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
|
|
||||||
cp ./assets/wall_8K.png ${PREFIX}/share/hyprland
|
|
||||||
|
|
||||||
install -Dm644 -t ${PREFIX}/share/man/man1 ./docs/*.1
|
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
|
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/hyprctl
|
||||||
rm -f /usr/lib/libwlroots.so.11032
|
rm -f ${PREFIX}/lib/libwlroots.so.12032
|
||||||
rm -rf ${PREFIX}/share/hyprland
|
rm -rf ${PREFIX}/share/hyprland
|
||||||
rm -f ${PREFIX}/share/man/man1/Hyprland.1
|
rm -f ${PREFIX}/share/man/man1/Hyprland.1
|
||||||
rm -f ${PREFIX}/share/man/man1/hyprctl.1
|
rm -f ${PREFIX}/share/man/man1/hyprctl.1
|
||||||
|
|
||||||
protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o
|
|
||||||
|
|
||||||
fixwlr:
|
fixwlr:
|
||||||
sed -i -E 's/(soversion = 11)([^032]|$$)/soversion = 11032/g' subprojects/wlroots/meson.build
|
sed -E -i -e 's/(soversion = 12)([^032]|$$)/soversion = 12032/g' subprojects/wlroots/meson.build
|
||||||
|
|
||||||
rm -rf ./subprojects/wlroots/build
|
rm -rf ./subprojects/wlroots/build
|
||||||
|
|
||||||
config:
|
config:
|
||||||
make protocols
|
$(MAKE) fixwlr
|
||||||
|
|
||||||
make fixwlr
|
meson setup subprojects/wlroots/build subprojects/wlroots --prefix=${PREFIX} --buildtype=release -Dwerror=false -Dexamples=false
|
||||||
|
ninja -C subprojects/wlroots/build/
|
||||||
|
|
||||||
cd subprojects/wlroots && meson ./build --prefix=/usr --buildtype=release
|
ninja -C subprojects/wlroots/build/ install
|
||||||
cd subprojects/wlroots && ninja -C build/
|
|
||||||
|
|
||||||
cd subprojects/wlroots && ninja -C build/ install
|
cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
|
|
||||||
|
pluginenv:
|
||||||
|
cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
|
|
||||||
|
$(MAKE) fixwlr
|
||||||
|
|
||||||
|
meson setup subprojects/wlroots/build subprojects/wlroots --prefix=${PREFIX} --buildtype=release -Dwerror=false -Dexamples=false
|
||||||
|
ninja -C subprojects/wlroots/build/
|
||||||
|
|
||||||
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja
|
||||||
|
|
||||||
|
mkdir -p ${PREFIX}/include/hyprland
|
||||||
|
mkdir -p ${PREFIX}/include/hyprland/protocols
|
||||||
|
mkdir -p ${PREFIX}/include/hyprland/wlroots
|
||||||
|
mkdir -p ${PREFIX}/share/pkgconfig
|
||||||
|
|
||||||
|
find src -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland
|
||||||
|
cd subprojects/wlroots/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots && cd ../../..
|
||||||
|
cp ./protocols/*-protocol.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
|
||||||
|
|
||||||
|
configdebug:
|
||||||
|
$(MAKE) fixwlr
|
||||||
|
|
||||||
|
meson setup subprojects/wlroots/build subprojects/wlroots --prefix=${PREFIX} --buildtype=debug -Dwerror=false -Dexamples=false -Db_sanitize=address
|
||||||
|
ninja -C subprojects/wlroots/build/
|
||||||
|
|
||||||
|
ninja -C subprojects/wlroots/build/ install
|
||||||
|
|
||||||
man:
|
man:
|
||||||
pandoc ./docs/Hyprland.1.rst \
|
pandoc ./docs/Hyprland.1.rst \
|
||||||
|
|||||||
25
README.md
25
README.md
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
![Badge Workflow]
|
![Badge Workflow]
|
||||||
[![Badge License]][License]
|
[![Badge License]][License]
|
||||||
![Badge Lines]
|
|
||||||
![Badge Language]
|
![Badge Language]
|
||||||
[![Badge Pull Requests]][Pull Requests]
|
[![Badge Pull Requests]][Pull Requests]
|
||||||
[![Badge Issues]][Issues]
|
[![Badge Issues]][Issues]
|
||||||
@@ -17,7 +16,7 @@
|
|||||||
|
|
||||||
Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks.
|
Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks.
|
||||||
|
|
||||||
It supports multiple layouts, fancy effects, has a very flexible IPC model allowing for a lot of customization, and more.
|
It supports multiple layouts, fancy effects, has a very flexible IPC model allowing for a lot of customization, a powerful plugin system and more.
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
@@ -40,31 +39,29 @@ Hyprland is still in pretty early development compared to some other Wayland com
|
|||||||
|
|
||||||
Although Hyprland is pretty stable, it may have some bugs.
|
Although Hyprland is pretty stable, it may have some bugs.
|
||||||
|
|
||||||
### Help Wanted
|
|
||||||
|
|
||||||
Hyprland needs testers! <br/>
|
|
||||||
Try it out and report bugs / suggestions!
|
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
- Easily expandable and readable codebase
|
- Easily expandable and readable codebase
|
||||||
|
- Plugin support
|
||||||
- Config reloaded instantly upon saving
|
- Config reloaded instantly upon saving
|
||||||
- Custom bezier curve based animations
|
- Custom bezier curve based animations
|
||||||
- `wlr_ext` workspaces protocol support
|
|
||||||
- Dual Kawase blur
|
- Dual Kawase blur
|
||||||
- Drop shadows
|
- Drop shadows
|
||||||
|
- Rounded corners
|
||||||
|
- Gradient borders
|
||||||
- Fully dynamic workspaces
|
- Fully dynamic workspaces
|
||||||
- Closely follows `wlroots-git`
|
- Closely follows `wlroots-git`
|
||||||
- Global keybinds passed to your apps of choice
|
- Global keybinds passed to your apps of choice
|
||||||
|
- A lot of customization
|
||||||
- Bundled wlroots
|
- Bundled wlroots
|
||||||
- Window/layer fade in/out
|
- Window/layer fade in/out
|
||||||
- Tiling/pseudotiling/floating/fullscreen windows
|
- Tiling/pseudotiling/floating/fullscreen windows
|
||||||
- Switching workspaces between window modes on the fly
|
- Switching workspaces between window modes on the fly
|
||||||
- Special workspace (scratchpad)
|
- Special workspaces (scratchpads)
|
||||||
- Window/monitor rules
|
- Window/monitor rules
|
||||||
- Socket-based IPC
|
- Socket-based IPC
|
||||||
|
- `wlr_ext` workspaces protocol support
|
||||||
- Event system for bash scripts
|
- Event system for bash scripts
|
||||||
- Rounded corners
|
|
||||||
- Full damage tracking
|
- Full damage tracking
|
||||||
- Docks support
|
- Docks support
|
||||||
- Drawing tablet support
|
- Drawing tablet support
|
||||||
@@ -134,7 +131,7 @@ Try it out and report bugs / suggestions!
|
|||||||
|
|
||||||
[Contribute]: https://wiki.hyprland.org/Contributing-and-Debugging/
|
[Contribute]: https://wiki.hyprland.org/Contributing-and-Debugging/
|
||||||
[Install]: https://wiki.hyprland.org/Getting-Started/Installation/
|
[Install]: https://wiki.hyprland.org/Getting-Started/Installation/
|
||||||
[Quick Start]: https://wiki.hyprland.org/Getting-Started/Quick-start/
|
[Quick Start]: https://wiki.hyprland.org/Getting-Started/Master-Tutorial/
|
||||||
[License]: LICENSE
|
[License]: LICENSE
|
||||||
|
|
||||||
|
|
||||||
@@ -150,9 +147,9 @@ Try it out and report bugs / suggestions!
|
|||||||
<!----------------------------------{ Images }--------------------------------->
|
<!----------------------------------{ Images }--------------------------------->
|
||||||
|
|
||||||
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
|
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
|
||||||
[Preview A]: https://i.imgur.com/pC6YF1Y.png
|
[Preview A]: https://i.ibb.co/SX7GbYR/winter-rice.png
|
||||||
[Preview B]: https://i.imgur.com/NbrTnZH.png
|
[Preview B]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png
|
||||||
[Preview C]: https://i.imgur.com/sCafdKQ.png
|
[Preview C]: https://i.imgur.com/pC6YF1Y.png
|
||||||
|
|
||||||
|
|
||||||
<!----------------------------------{ Badges }--------------------------------->
|
<!----------------------------------{ Badges }--------------------------------->
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
PREFIX = /usr/local
|
|
||||||
CFLAGS ?= -g -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare -Wno-unused-function -Wno-unused-variable -Wno-unused-result -Wdeclaration-after-statement
|
|
||||||
CFLAGS += -DXWAYLAND
|
|
||||||
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
.\" Automatically generated by Pandoc 2.5
|
.\" Automatically generated by Pandoc 2.9.2.1
|
||||||
.\"
|
.\"
|
||||||
.TH "Hyprland" "1" "24 Aug 2022" "" "Hyprland User Manual"
|
.TH "Hyprland" "1" "03 Apr 2023" "" "Hyprland User Manual"
|
||||||
.hy
|
.hy
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
Hyprland \- Dynamic tiling Wayland compositor
|
Hyprland - Dynamic tiling Wayland compositor
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.PP
|
.PP
|
||||||
\f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]].
|
\f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]].
|
||||||
@@ -27,14 +27,14 @@ For configuration information please see
|
|||||||
<\f[I]https://github.com/hyprwm/Hyprland/wiki\f[R]>.
|
<\f[I]https://github.com/hyprwm/Hyprland/wiki\f[R]>.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.B \f[B]\-h\f[R], \f[B]\-\-help\f[R]
|
\f[B]-h\f[R], \f[B]--help\f[R]
|
||||||
Show command usage.
|
Show command usage.
|
||||||
.TP
|
.TP
|
||||||
.B \f[B]\-c\f[R], \f[B]\-\-config\f[R]
|
\f[B]-c\f[R], \f[B]--config\f[R]
|
||||||
Specify config file to use.
|
Specify config file to use.
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
.TP
|
.TP
|
||||||
.B Submit bug reports and request features online at:
|
Submit bug reports and request features online at:
|
||||||
<\f[I]https://github.com/hyprwm/Hyprland/issues\f[R]>
|
<\f[I]https://github.com/hyprwm/Hyprland/issues\f[R]>
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.PP
|
.PP
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
First of all, please remember to:
|
First of all, please remember to:
|
||||||
- Check that your issue is not a duplicate
|
- Check that your issue is not a duplicate
|
||||||
- Read the [FAQ](https://github.com/vaxerski/Hyprland/wiki/FAQ)
|
- Read the [FAQ](https://github.com/vaxerski/Hyprland/wiki/FAQ)
|
||||||
- Read the [Configuring Page](https://github.com/vaxerski/Hyprland/wiki/Configuring-Hyprland)
|
- Read the [Configuring Page](https://wiki.hyprland.org/Configuring/Configuring-Hyprland)
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
# Reporting suggestions
|
# Reporting suggestions
|
||||||
Suggestions are welcome.
|
Suggestions are welcome.
|
||||||
|
|
||||||
Many features can be implemented using bash scripts and Hyprland sockets, read up on those [Here](https://github.com/vaxerski/Hyprland/wiki/IPC). Please do not suggest features that can be implemented as such.
|
Many features can be implemented using bash scripts and Hyprland sockets, read up on those [Here](https://wiki.hyprland.org/IPC). Please do not suggest features that can be implemented as such.
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
@@ -25,8 +25,9 @@ If your bug is one that doesn't crash Hyprland, but feels like invalid behavior,
|
|||||||
|
|
||||||
If your bug crashes Hyprland, append additionally:
|
If your bug crashes Hyprland, append additionally:
|
||||||
- The Hyprland log
|
- The Hyprland log
|
||||||
- Coredump / Coredump analysis (with a stacktrace)
|
|
||||||
- Your config
|
- Your config
|
||||||
|
- (v0.22.0beta and up) The Hyprland Crash Report
|
||||||
|
- (v0.21.0beta and below) Coredump / Coredump analysis (with a stacktrace)
|
||||||
|
|
||||||
**Important**: Please do NOT use any package for reporting bugs! Clone and compile from source.
|
**Important**: Please do NOT use any package for reporting bugs! Clone and compile from source.
|
||||||
|
|
||||||
@@ -44,7 +45,14 @@ cat /tmp/hypr/$(ls -t /tmp/hypr/ | head -n 2 | tail -n 1)/hyprland.log
|
|||||||
|
|
||||||
basically, directories in /tmp/hypr are your sessions.
|
basically, directories in /tmp/hypr are your sessions.
|
||||||
|
|
||||||
## Obtaining the Hyprland coredump
|
## Obtaining the Hyprland Crash Report (v0.22.0beta and up)
|
||||||
|
|
||||||
|
If you have `$XDG_CACHE_HOME` set, the crash report directory is `$XDG_CACHE_HOME/hyprland`. If not, it's `~/.hyprland`
|
||||||
|
|
||||||
|
Go to the crash report directory and you should find a file named `hyprlandCrashReport[XXXX].txt` where `[XXXX]` is the PID of the process that crashed.
|
||||||
|
|
||||||
|
Attach that file to your issue.
|
||||||
|
## Obtaining the Hyprland coredump (v0.21.0beta and below)
|
||||||
If you are on systemd, you can simply use
|
If you are on systemd, you can simply use
|
||||||
```
|
```
|
||||||
coredumpctl
|
coredumpctl
|
||||||
@@ -57,3 +65,16 @@ coredumpctl info [PID]
|
|||||||
```
|
```
|
||||||
where `[PID]` is the PID you remembered.
|
where `[PID]` is the PID you remembered.
|
||||||
|
|
||||||
|
## Obtaining the debug Hyprland coredump
|
||||||
|
A debug coredump provides more information for debugging and may speed up the process of fixing the bug.
|
||||||
|
|
||||||
|
Make sure you're on latest git. Run `git pull --recurse-submodules` to sync everything.
|
||||||
|
|
||||||
|
1. [Compile Hyprland with debug mode](http://wiki.hyprland.org/Contributing-and-Debugging/#build-in-debug-mode)
|
||||||
|
> Note: The config file used will be `hyprlandd.conf` instead of `hyprland.conf`
|
||||||
|
|
||||||
|
2. `cd ~`
|
||||||
|
3. For your own convenience, launch Hyprland from a tty with the envvar `ASAN_OPTIONS="log_path=asan.log" ~/path/to/Hyprland`
|
||||||
|
4. Reproduce the crash. Hyprland should instantly close.
|
||||||
|
5. Check out your `~` and find a file called `asan.log.XXXXX` where `XXXXX` will be a number corresponding to the PID of the Hyprland instance that crashed.
|
||||||
|
6. That is your coredump. Attach it to your issue.
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
.\" Automatically generated by Pandoc 2.5
|
.\" Automatically generated by Pandoc 2.9.2.1
|
||||||
.\"
|
.\"
|
||||||
.TH "hyprctl" "1" "24 Aug 2022" "" "hyprctl User Manual"
|
.TH "hyprctl" "1" "03 Apr 2023" "" "hyprctl User Manual"
|
||||||
.hy
|
.hy
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
hyprctl \- Utility for controlling parts of Hyprland from a CLI or a
|
hyprctl - Utility for controlling parts of Hyprland from a CLI or a
|
||||||
script
|
script
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.PP
|
.PP
|
||||||
@@ -26,7 +26,7 @@ For dispatchers without parameters it can be anything.
|
|||||||
.PP
|
.PP
|
||||||
Returns: \f[I]ok\f[R] on success, and an error message on failure.
|
Returns: \f[I]ok\f[R] on success, and an error message on failure.
|
||||||
.TP
|
.TP
|
||||||
.B Examples:
|
Examples:
|
||||||
\f[B]hyprctl\f[R] \f[I]dispatch exec kitty\f[R]
|
\f[B]hyprctl\f[R] \f[I]dispatch exec kitty\f[R]
|
||||||
.RS
|
.RS
|
||||||
.PP
|
.PP
|
||||||
@@ -41,7 +41,7 @@ Set a config keyword dynamically.
|
|||||||
.PP
|
.PP
|
||||||
Returns: \f[I]ok\f[R] on success, and an error message on failure.
|
Returns: \f[I]ok\f[R] on success, and an error message on failure.
|
||||||
.TP
|
.TP
|
||||||
.B Examples:
|
Examples:
|
||||||
\f[B]hyprctl\f[R] \f[I]keyword bind SUPER,0,pseudo\f[R]
|
\f[B]hyprctl\f[R] \f[I]keyword bind SUPER,0,pseudo\f[R]
|
||||||
.RS
|
.RS
|
||||||
.PP
|
.PP
|
||||||
@@ -112,13 +112,13 @@ Returns the current random splash.
|
|||||||
.RE
|
.RE
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.PP
|
.PP
|
||||||
\f[B]\-\-batch\f[R]
|
\f[B]--batch\f[R]
|
||||||
.RS
|
.RS
|
||||||
.PP
|
.PP
|
||||||
Specify a batch of commands to execute.
|
Specify a batch of commands to execute.
|
||||||
.TP
|
.TP
|
||||||
.B Example:
|
Example:
|
||||||
\f[B]hyprctl\f[R] \f[I]\-\-batch \[dq]keyword general:border_size 2 ;
|
\f[B]hyprctl\f[R] \f[I]--batch \[dq]keyword general:border_size 2 ;
|
||||||
keyword general:gaps_out 20\[dq]\f[R]
|
keyword general:gaps_out 20\[dq]\f[R]
|
||||||
.RS
|
.RS
|
||||||
.PP
|
.PP
|
||||||
@@ -126,14 +126,14 @@ keyword general:gaps_out 20\[dq]\f[R]
|
|||||||
.RE
|
.RE
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
\f[B]\-j\f[R]
|
\f[B]-j\f[R]
|
||||||
.RS
|
.RS
|
||||||
.PP
|
.PP
|
||||||
Outputs information in JSON.
|
Outputs information in JSON.
|
||||||
.RE
|
.RE
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
.TP
|
.TP
|
||||||
.B Submit bug reports and request features online at:
|
Submit bug reports and request features online at:
|
||||||
<\f[I]https://github.com/hyprwm/Hyprland/issues\f[R]>
|
<\f[I]https://github.com/hyprwm/Hyprland/issues\f[R]>
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.PP
|
.PP
|
||||||
|
|||||||
8
example/examplePlugin/Makefile
Normal file
8
example/examplePlugin/Makefile
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# compile with HYPRLAND_HEADERS=<path_to_hl> make all
|
||||||
|
# make sure that the path above is to the root hl repo directory, NOT src/
|
||||||
|
# and that you have ran `make protocols` in the hl dir.
|
||||||
|
|
||||||
|
all:
|
||||||
|
g++ -shared -fPIC --no-gnu-unique main.cpp customLayout.cpp customDecoration.cpp -o examplePlugin.so -g -I "/usr/include/pixman-1" -I "/usr/include/libdrm" -I "${HYPRLAND_HEADERS}" -I "${HYPRLAND_HEADERS}/subprojects/wlroots/include" -I "${HYPRLAND_HEADERS}/subprojects/wlroots/include" -I "${HYPRLAND_HEADERS}/subprojects/wlroots/build/include" -std=c++23
|
||||||
|
clean:
|
||||||
|
rm ./examplePlugin.so
|
||||||
74
example/examplePlugin/customDecoration.cpp
Normal file
74
example/examplePlugin/customDecoration.cpp
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#include "customDecoration.hpp"
|
||||||
|
#include "../../src/Window.hpp"
|
||||||
|
#include "../../src/Compositor.hpp"
|
||||||
|
#include "globals.hpp"
|
||||||
|
|
||||||
|
CCustomDecoration::CCustomDecoration(CWindow* pWindow) {
|
||||||
|
m_pWindow = pWindow;
|
||||||
|
m_vLastWindowPos = pWindow->m_vRealPosition.vec();
|
||||||
|
m_vLastWindowSize = pWindow->m_vRealSize.vec();
|
||||||
|
}
|
||||||
|
|
||||||
|
CCustomDecoration::~CCustomDecoration() {
|
||||||
|
damageEntire();
|
||||||
|
}
|
||||||
|
|
||||||
|
SWindowDecorationExtents CCustomDecoration::getWindowDecorationExtents() {
|
||||||
|
return m_seExtents;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCustomDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset) {
|
||||||
|
if (!g_pCompositor->windowValidMapped(m_pWindow))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_pWindow->m_sSpecialRenderData.decorate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
static auto* const PCOLOR = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:example:border_color")->intValue;
|
||||||
|
static auto* const PROUNDING = &HyprlandAPI::getConfigValue(PHANDLE, "decoration:rounding")->intValue;
|
||||||
|
static auto* const PBORDERSIZE = &HyprlandAPI::getConfigValue(PHANDLE, "general:border_size")->intValue;
|
||||||
|
|
||||||
|
const auto ROUNDING = !m_pWindow->m_sSpecialRenderData.rounding ?
|
||||||
|
0 :
|
||||||
|
(m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying());
|
||||||
|
|
||||||
|
// draw the border
|
||||||
|
wlr_box fullBox = {(int)(m_vLastWindowPos.x - *PBORDERSIZE), (int)(m_vLastWindowPos.y - *PBORDERSIZE), (int)(m_vLastWindowSize.x + 2.0 * *PBORDERSIZE),
|
||||||
|
(int)(m_vLastWindowSize.y + 2.0 * *PBORDERSIZE)};
|
||||||
|
|
||||||
|
fullBox.x -= pMonitor->vecPosition.x;
|
||||||
|
fullBox.y -= pMonitor->vecPosition.y;
|
||||||
|
|
||||||
|
m_seExtents = {{m_vLastWindowPos.x - fullBox.x - pMonitor->vecPosition.x + 2, m_vLastWindowPos.y - fullBox.y - pMonitor->vecPosition.y + 2},
|
||||||
|
{fullBox.x + fullBox.width + pMonitor->vecPosition.x - m_vLastWindowPos.x - m_vLastWindowSize.x + 2,
|
||||||
|
fullBox.y + fullBox.height + pMonitor->vecPosition.y - m_vLastWindowPos.y - m_vLastWindowSize.y + 2}};
|
||||||
|
|
||||||
|
fullBox.x += offset.x;
|
||||||
|
fullBox.y += offset.y;
|
||||||
|
|
||||||
|
if (fullBox.width < 1 || fullBox.height < 1)
|
||||||
|
return; // don't draw invisible shadows
|
||||||
|
|
||||||
|
g_pHyprOpenGL->scissor((wlr_box*)nullptr);
|
||||||
|
|
||||||
|
scaleBox(&fullBox, pMonitor->scale);
|
||||||
|
g_pHyprOpenGL->renderBorder(&fullBox, CColor(*PCOLOR), *PROUNDING * pMonitor->scale + *PBORDERSIZE * 2, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
eDecorationType CCustomDecoration::getDecorationType() {
|
||||||
|
return DECORATION_CUSTOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCustomDecoration::updateWindow(CWindow* pWindow) {
|
||||||
|
|
||||||
|
m_vLastWindowPos = pWindow->m_vRealPosition.vec();
|
||||||
|
m_vLastWindowSize = pWindow->m_vRealSize.vec();
|
||||||
|
|
||||||
|
damageEntire();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCustomDecoration::damageEntire() {
|
||||||
|
wlr_box dm = {(int)(m_vLastWindowPos.x - m_seExtents.topLeft.x), (int)(m_vLastWindowPos.y - m_seExtents.topLeft.y),
|
||||||
|
(int)(m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x), (int)m_seExtents.topLeft.y};
|
||||||
|
g_pHyprRenderer->damageBox(&dm);
|
||||||
|
}
|
||||||
29
example/examplePlugin/customDecoration.hpp
Normal file
29
example/examplePlugin/customDecoration.hpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define WLR_USE_UNSTABLE
|
||||||
|
|
||||||
|
#include "../../src/render/decorations/IHyprWindowDecoration.hpp"
|
||||||
|
|
||||||
|
class CCustomDecoration : public IHyprWindowDecoration {
|
||||||
|
public:
|
||||||
|
CCustomDecoration(CWindow*);
|
||||||
|
virtual ~CCustomDecoration();
|
||||||
|
|
||||||
|
virtual SWindowDecorationExtents getWindowDecorationExtents();
|
||||||
|
|
||||||
|
virtual void draw(CMonitor*, float a, const Vector2D& offset);
|
||||||
|
|
||||||
|
virtual eDecorationType getDecorationType();
|
||||||
|
|
||||||
|
virtual void updateWindow(CWindow*);
|
||||||
|
|
||||||
|
virtual void damageEntire();
|
||||||
|
|
||||||
|
private:
|
||||||
|
SWindowDecorationExtents m_seExtents;
|
||||||
|
|
||||||
|
CWindow* m_pWindow = nullptr;
|
||||||
|
|
||||||
|
Vector2D m_vLastWindowPos;
|
||||||
|
Vector2D m_vLastWindowSize;
|
||||||
|
};
|
||||||
80
example/examplePlugin/customLayout.cpp
Normal file
80
example/examplePlugin/customLayout.cpp
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
#include "customLayout.hpp"
|
||||||
|
#include "../../src/Compositor.hpp"
|
||||||
|
#include "globals.hpp"
|
||||||
|
|
||||||
|
void CHyprCustomLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||||
|
const auto SIZE = PMONITOR->vecSize;
|
||||||
|
|
||||||
|
// these are used for focus and move calculations, and are *required* to touch for moving focus to work properly.
|
||||||
|
pWindow->m_vPosition = Vector2D{(SIZE.x / 2.0) * (m_vWindowData.size() % 2), (SIZE.y / 2.0) * (int)(m_vWindowData.size() > 1)};
|
||||||
|
pWindow->m_vSize = SIZE / 2.0;
|
||||||
|
|
||||||
|
// this is the actual pos and size of the window (where it's rendered)
|
||||||
|
pWindow->m_vRealPosition = pWindow->m_vPosition + Vector2D{10, 10};
|
||||||
|
pWindow->m_vRealSize = pWindow->m_vSize - Vector2D{20, 20};
|
||||||
|
|
||||||
|
const auto PDATA = &m_vWindowData.emplace_back();
|
||||||
|
PDATA->pWindow = pWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprCustomLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||||
|
std::erase_if(m_vWindowData, [&](const auto& other) { return other.pWindow == pWindow; });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CHyprCustomLayout::isWindowTiled(CWindow* pWindow) {
|
||||||
|
return std::find_if(m_vWindowData.begin(), m_vWindowData.end(), [&](const auto& other) { return other.pWindow == pWindow; }) != m_vWindowData.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprCustomLayout::recalculateMonitor(const int& eIdleInhibitMode) {
|
||||||
|
; // empty
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprCustomLayout::recalculateWindow(CWindow* pWindow) {
|
||||||
|
; // empty
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprCustomLayout::resizeActiveWindow(const Vector2D& delta, CWindow* pWindow) {
|
||||||
|
; // empty
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprCustomLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode mode, bool on) {
|
||||||
|
; // empty
|
||||||
|
}
|
||||||
|
|
||||||
|
std::any CHyprCustomLayout::layoutMessage(SLayoutMessageHeader header, std::string content) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
SWindowRenderLayoutHints CHyprCustomLayout::requestRenderHints(CWindow* pWindow) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprCustomLayout::switchWindows(CWindow* pWindowA, CWindow* pWindowB) {
|
||||||
|
; // empty
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprCustomLayout::alterSplitRatio(CWindow* pWindow, float delta, bool exact) {
|
||||||
|
; // empty
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CHyprCustomLayout::getLayoutName() {
|
||||||
|
return "custom";
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprCustomLayout::replaceWindowDataWith(CWindow* from, CWindow* to) {
|
||||||
|
; // empty
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprCustomLayout::onEnable() {
|
||||||
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
|
if (w->isHidden() || !w->m_bIsMapped || w->m_bFadingOut || w->m_bIsFloating)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
onWindowCreatedTiling(w.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprCustomLayout::onDisable() {
|
||||||
|
m_vWindowData.clear();
|
||||||
|
}
|
||||||
32
example/examplePlugin/customLayout.hpp
Normal file
32
example/examplePlugin/customLayout.hpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define WLR_USE_UNSTABLE
|
||||||
|
|
||||||
|
#include "../../src/layout/IHyprLayout.hpp"
|
||||||
|
|
||||||
|
struct SWindowData {
|
||||||
|
CWindow* pWindow = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CHyprCustomLayout : public IHyprLayout {
|
||||||
|
public:
|
||||||
|
virtual void onWindowCreatedTiling(CWindow*);
|
||||||
|
virtual void onWindowRemovedTiling(CWindow*);
|
||||||
|
virtual bool isWindowTiled(CWindow*);
|
||||||
|
virtual void recalculateMonitor(const int&);
|
||||||
|
virtual void recalculateWindow(CWindow*);
|
||||||
|
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
|
||||||
|
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
|
||||||
|
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
|
||||||
|
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
|
||||||
|
virtual void switchWindows(CWindow*, CWindow*);
|
||||||
|
virtual void alterSplitRatio(CWindow*, float, bool);
|
||||||
|
virtual std::string getLayoutName();
|
||||||
|
virtual void replaceWindowDataWith(CWindow* from, CWindow* to);
|
||||||
|
|
||||||
|
virtual void onEnable();
|
||||||
|
virtual void onDisable();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<SWindowData> m_vWindowData;
|
||||||
|
};
|
||||||
5
example/examplePlugin/globals.hpp
Normal file
5
example/examplePlugin/globals.hpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <src/plugins/PluginAPI.hpp>
|
||||||
|
|
||||||
|
inline HANDLE PHANDLE = nullptr;
|
||||||
95
example/examplePlugin/main.cpp
Normal file
95
example/examplePlugin/main.cpp
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#define WLR_USE_UNSTABLE
|
||||||
|
|
||||||
|
#include "globals.hpp"
|
||||||
|
|
||||||
|
#include <src/Window.hpp>
|
||||||
|
#include <src/Compositor.hpp>
|
||||||
|
#include "customLayout.hpp"
|
||||||
|
#include "customDecoration.hpp"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
inline std::unique_ptr<CHyprCustomLayout> g_pCustomLayout;
|
||||||
|
inline CFunctionHook* g_pFocusHook = nullptr;
|
||||||
|
inline CFunctionHook* g_pMotionHook = nullptr;
|
||||||
|
inline CFunctionHook* g_pMouseDownHook = nullptr;
|
||||||
|
typedef void (*origFocusWindow)(void*, CWindow*, wlr_surface*);
|
||||||
|
typedef void (*origMotion)(wlr_seat*, uint32_t, double, double);
|
||||||
|
typedef void (*origMouseDownNormal)(void*, wlr_pointer_button_event*);
|
||||||
|
|
||||||
|
// Do NOT change this function.
|
||||||
|
APICALL EXPORT std::string PLUGIN_API_VERSION() {
|
||||||
|
return HYPRLAND_API_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onActiveWindowChange(void* self, std::any data) {
|
||||||
|
try {
|
||||||
|
auto* const PWINDOW = std::any_cast<CWindow*>(data);
|
||||||
|
|
||||||
|
HyprlandAPI::addNotification(PHANDLE, "[ExamplePlugin] Active window: " + (PWINDOW ? PWINDOW->m_szTitle : "None"), CColor{0.f, 0.5f, 1.f, 1.f}, 5000);
|
||||||
|
} catch (std::bad_any_cast& e) { HyprlandAPI::addNotification(PHANDLE, "[ExamplePlugin] Active window: None", CColor{0.f, 0.5f, 1.f, 1.f}, 5000); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onNewWindow(void* self, std::any data) {
|
||||||
|
auto* const PWINDOW = std::any_cast<CWindow*>(data);
|
||||||
|
|
||||||
|
HyprlandAPI::addWindowDecoration(PHANDLE, PWINDOW, new CCustomDecoration(PWINDOW));
|
||||||
|
}
|
||||||
|
|
||||||
|
void hkFocusWindow(void* thisptr, CWindow* pWindow, wlr_surface* pSurface) {
|
||||||
|
// HyprlandAPI::addNotification(PHANDLE, getFormat("FocusWindow with %lx %lx", pWindow, pSurface), CColor{0.f, 1.f, 1.f, 1.f}, 5000);
|
||||||
|
(*(origFocusWindow)g_pFocusHook->m_pOriginal)(thisptr, pWindow, pSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hkNotifyMotion(wlr_seat* wlr_seat, uint32_t time_msec, double sx, double sy) {
|
||||||
|
// HyprlandAPI::addNotification(PHANDLE, getFormat("NotifyMotion with %lf %lf", sx, sy), CColor{0.f, 1.f, 1.f, 1.f}, 5000);
|
||||||
|
(*(origMotion)g_pMotionHook->m_pOriginal)(wlr_seat, time_msec, sx, sy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hkProcessMouseDownNormal(void* thisptr, wlr_pointer_button_event* e) {
|
||||||
|
// HyprlandAPI::addNotification(PHANDLE, "Mouse down normal!", CColor{0.8f, 0.2f, 0.5f, 1.0f}, 5000);
|
||||||
|
(*(origMouseDownNormal)g_pMouseDownHook->m_pOriginal)(thisptr, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
||||||
|
PHANDLE = handle;
|
||||||
|
|
||||||
|
HyprlandAPI::addNotification(PHANDLE, "Hello World from an example plugin!", CColor{0.f, 1.f, 1.f, 1.f}, 5000);
|
||||||
|
|
||||||
|
HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, std::any data) { onActiveWindowChange(self, data); });
|
||||||
|
HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, std::any data) { onNewWindow(self, data); });
|
||||||
|
|
||||||
|
g_pCustomLayout = std::make_unique<CHyprCustomLayout>();
|
||||||
|
|
||||||
|
HyprlandAPI::addLayout(PHANDLE, "custom", g_pCustomLayout.get());
|
||||||
|
|
||||||
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:example:border_color", SConfigValue{.intValue = configStringToInt("rgb(44ee44)")});
|
||||||
|
|
||||||
|
HyprlandAPI::addDispatcher(PHANDLE, "example", [](std::string arg) { HyprlandAPI::addNotification(PHANDLE, "Arg passed: " + arg, CColor{0.5f, 0.5f, 0.7f, 1.0f}, 5000); });
|
||||||
|
|
||||||
|
// Hook a public member
|
||||||
|
g_pFocusHook = HyprlandAPI::createFunctionHook(PHANDLE, (void*)&CCompositor::focusWindow, (void*)&hkFocusWindow);
|
||||||
|
// Hook a public non-member
|
||||||
|
g_pMotionHook = HyprlandAPI::createFunctionHook(PHANDLE, (void*)&wlr_seat_pointer_notify_motion, (void*)&hkNotifyMotion);
|
||||||
|
// Hook a private member
|
||||||
|
static const auto METHODS = HyprlandAPI::findFunctionsByName(PHANDLE, "processMouseDownNormal");
|
||||||
|
g_pMouseDownHook = HyprlandAPI::createFunctionHook(PHANDLE, METHODS[0].address, (void*)&hkProcessMouseDownNormal);
|
||||||
|
|
||||||
|
// fancy notifications
|
||||||
|
HyprlandAPI::addNotificationV2(PHANDLE, {{"text", "Example hint"}, {"time", (uint64_t)10000}, {"color", CColor(0.2, 0.2, 0.9, 1.0)}, {"icon", ICON_HINT}});
|
||||||
|
|
||||||
|
// Enable our hooks
|
||||||
|
g_pFocusHook->hook();
|
||||||
|
g_pMotionHook->hook();
|
||||||
|
g_pMouseDownHook->hook();
|
||||||
|
|
||||||
|
HyprlandAPI::reloadConfig();
|
||||||
|
|
||||||
|
return {"ExamplePlugin", "An example plugin", "Vaxry", "1.0"};
|
||||||
|
}
|
||||||
|
|
||||||
|
APICALL EXPORT void PLUGIN_EXIT() {
|
||||||
|
HyprlandAPI::invokeHyprctlCommand("seterror", "disable");
|
||||||
|
}
|
||||||
@@ -1,117 +1,162 @@
|
|||||||
# This is an example Hyprland config file.
|
# This is an example Hyprland config file.
|
||||||
# Syntax is the same as in Hypr, but settings might differ.
|
|
||||||
#
|
#
|
||||||
# Refer to the wiki for more information.
|
# Refer to the wiki for more information.
|
||||||
|
|
||||||
#
|
#
|
||||||
# Please note not all available settings / options are set here.
|
# Please note not all available settings / options are set here.
|
||||||
# For a full list, see the wiki (basic and advanced configuring)
|
# For a full list, see the wiki
|
||||||
#
|
#
|
||||||
|
|
||||||
monitor=,preferred,auto,1
|
# See https://wiki.hyprland.org/Configuring/Monitors/
|
||||||
workspace=DP-1,1
|
monitor=,preferred,auto,auto
|
||||||
|
|
||||||
|
|
||||||
|
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||||
|
|
||||||
|
# Execute your favorite apps at launch
|
||||||
|
# exec-once = waybar & hyprpaper & firefox
|
||||||
|
|
||||||
|
# Source a file (multi-file configs)
|
||||||
|
# source = ~/.config/hypr/myColors.conf
|
||||||
|
|
||||||
|
# Some default env vars.
|
||||||
|
env = XCURSOR_SIZE,24
|
||||||
|
|
||||||
|
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
|
||||||
input {
|
input {
|
||||||
kb_file=
|
kb_layout = us
|
||||||
kb_layout=
|
kb_variant =
|
||||||
kb_variant=
|
kb_model =
|
||||||
kb_model=
|
kb_options =
|
||||||
kb_options=
|
kb_rules =
|
||||||
kb_rules=
|
|
||||||
|
|
||||||
follow_mouse=1
|
follow_mouse = 1
|
||||||
|
|
||||||
touchpad {
|
touchpad {
|
||||||
natural_scroll=no
|
natural_scroll = false
|
||||||
}
|
}
|
||||||
|
|
||||||
sensitivity=0 # -1.0 - 1.0, 0 means no modification.
|
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
|
||||||
}
|
}
|
||||||
|
|
||||||
general {
|
general {
|
||||||
gaps_in=5
|
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||||
gaps_out=20
|
|
||||||
border_size=2
|
|
||||||
col.active_border=0x66ee1111
|
|
||||||
col.inactive_border=0x66333333
|
|
||||||
|
|
||||||
apply_sens_to_raw=0 # whether to apply the sensitivity to raw input (e.g. used by games where you aim using your mouse)
|
gaps_in = 5
|
||||||
|
gaps_out = 20
|
||||||
|
border_size = 2
|
||||||
|
col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
|
||||||
|
col.inactive_border = rgba(595959aa)
|
||||||
|
|
||||||
damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
|
layout = dwindle
|
||||||
}
|
}
|
||||||
|
|
||||||
decoration {
|
decoration {
|
||||||
rounding=10
|
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||||
blur=1
|
|
||||||
blur_size=3 # minimum 1
|
rounding = 10
|
||||||
blur_passes=1 # minimum 1
|
blur = true
|
||||||
blur_new_optimizations=1
|
blur_size = 3
|
||||||
|
blur_passes = 1
|
||||||
|
blur_new_optimizations = true
|
||||||
|
|
||||||
|
drop_shadow = true
|
||||||
|
shadow_range = 4
|
||||||
|
shadow_render_power = 3
|
||||||
|
col.shadow = rgba(1a1a1aee)
|
||||||
}
|
}
|
||||||
|
|
||||||
animations {
|
animations {
|
||||||
enabled=1
|
enabled = true
|
||||||
animation=windows,1,7,default
|
|
||||||
animation=border,1,10,default
|
# Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
|
||||||
animation=fade,1,10,default
|
|
||||||
animation=workspaces,1,6,default
|
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
|
||||||
|
|
||||||
|
animation = windows, 1, 7, myBezier
|
||||||
|
animation = windowsOut, 1, 7, default, popin 80%
|
||||||
|
animation = border, 1, 10, default
|
||||||
|
animation = borderangle, 1, 8, default
|
||||||
|
animation = fade, 1, 7, default
|
||||||
|
animation = workspaces, 1, 6, default
|
||||||
}
|
}
|
||||||
|
|
||||||
dwindle {
|
dwindle {
|
||||||
pseudotile=0 # enable pseudotiling on 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
|
||||||
|
}
|
||||||
|
|
||||||
|
master {
|
||||||
|
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
|
||||||
|
new_is_master = true
|
||||||
}
|
}
|
||||||
|
|
||||||
gestures {
|
gestures {
|
||||||
workspace_swipe=no
|
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||||
|
workspace_swipe = false
|
||||||
}
|
}
|
||||||
|
|
||||||
# example window rules
|
# Example per-device config
|
||||||
# for windows named/classed as abc and xyz
|
# See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
|
||||||
#windowrule=move 69 420,abc
|
device:epic-mouse-v1 {
|
||||||
#windowrule=size 420 69,abc
|
sensitivity = -0.5
|
||||||
#windowrule=tile,xyz
|
}
|
||||||
#windowrule=float,abc
|
|
||||||
#windowrule=pseudo,abc
|
|
||||||
#windowrule=monitor 0,xyz
|
|
||||||
|
|
||||||
# some nice mouse binds
|
# Example windowrule v1
|
||||||
bindm=SUPER,mouse:272,movewindow
|
# windowrule = float, ^(kitty)$
|
||||||
bindm=SUPER,mouse:273,resizewindow
|
# Example windowrule v2
|
||||||
|
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||||
|
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||||
|
|
||||||
# example binds
|
|
||||||
bind=SUPER,Q,exec,kitty
|
|
||||||
bind=SUPER,C,killactive,
|
|
||||||
bind=SUPER,M,exit,
|
|
||||||
bind=SUPER,E,exec,dolphin
|
|
||||||
bind=SUPER,V,togglefloating,
|
|
||||||
bind=SUPER,R,exec,wofi --show drun -o DP-3
|
|
||||||
bind=SUPER,P,pseudo,
|
|
||||||
|
|
||||||
bind=SUPER,left,movefocus,l
|
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||||
bind=SUPER,right,movefocus,r
|
$mainMod = SUPER
|
||||||
bind=SUPER,up,movefocus,u
|
|
||||||
bind=SUPER,down,movefocus,d
|
|
||||||
|
|
||||||
bind=SUPER,1,workspace,1
|
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
|
||||||
bind=SUPER,2,workspace,2
|
bind = $mainMod, Q, exec, kitty
|
||||||
bind=SUPER,3,workspace,3
|
bind = $mainMod, C, killactive,
|
||||||
bind=SUPER,4,workspace,4
|
bind = $mainMod, M, exit,
|
||||||
bind=SUPER,5,workspace,5
|
bind = $mainMod, E, exec, dolphin
|
||||||
bind=SUPER,6,workspace,6
|
bind = $mainMod, V, togglefloating,
|
||||||
bind=SUPER,7,workspace,7
|
bind = $mainMod, R, exec, wofi --show drun
|
||||||
bind=SUPER,8,workspace,8
|
bind = $mainMod, P, pseudo, # dwindle
|
||||||
bind=SUPER,9,workspace,9
|
bind = $mainMod, J, togglesplit, # dwindle
|
||||||
bind=SUPER,0,workspace,10
|
|
||||||
|
|
||||||
bind=ALT,1,movetoworkspace,1
|
# Move focus with mainMod + arrow keys
|
||||||
bind=ALT,2,movetoworkspace,2
|
bind = $mainMod, left, movefocus, l
|
||||||
bind=ALT,3,movetoworkspace,3
|
bind = $mainMod, right, movefocus, r
|
||||||
bind=ALT,4,movetoworkspace,4
|
bind = $mainMod, up, movefocus, u
|
||||||
bind=ALT,5,movetoworkspace,5
|
bind = $mainMod, down, movefocus, d
|
||||||
bind=ALT,6,movetoworkspace,6
|
|
||||||
bind=ALT,7,movetoworkspace,7
|
|
||||||
bind=ALT,8,movetoworkspace,8
|
|
||||||
bind=ALT,9,movetoworkspace,9
|
|
||||||
bind=ALT,0,movetoworkspace,10
|
|
||||||
|
|
||||||
bind=SUPER,mouse_down,workspace,e+1
|
# Switch workspaces with mainMod + [0-9]
|
||||||
bind=SUPER,mouse_up,workspace,e-1
|
bind = $mainMod, 1, workspace, 1
|
||||||
|
bind = $mainMod, 2, workspace, 2
|
||||||
|
bind = $mainMod, 3, workspace, 3
|
||||||
|
bind = $mainMod, 4, workspace, 4
|
||||||
|
bind = $mainMod, 5, workspace, 5
|
||||||
|
bind = $mainMod, 6, workspace, 6
|
||||||
|
bind = $mainMod, 7, workspace, 7
|
||||||
|
bind = $mainMod, 8, workspace, 8
|
||||||
|
bind = $mainMod, 9, workspace, 9
|
||||||
|
bind = $mainMod, 0, workspace, 10
|
||||||
|
|
||||||
|
# Move active window to a workspace with mainMod + SHIFT + [0-9]
|
||||||
|
bind = $mainMod SHIFT, 1, movetoworkspace, 1
|
||||||
|
bind = $mainMod SHIFT, 2, movetoworkspace, 2
|
||||||
|
bind = $mainMod SHIFT, 3, movetoworkspace, 3
|
||||||
|
bind = $mainMod SHIFT, 4, movetoworkspace, 4
|
||||||
|
bind = $mainMod SHIFT, 5, movetoworkspace, 5
|
||||||
|
bind = $mainMod SHIFT, 6, movetoworkspace, 6
|
||||||
|
bind = $mainMod SHIFT, 7, movetoworkspace, 7
|
||||||
|
bind = $mainMod SHIFT, 8, movetoworkspace, 8
|
||||||
|
bind = $mainMod SHIFT, 9, movetoworkspace, 9
|
||||||
|
bind = $mainMod SHIFT, 0, movetoworkspace, 10
|
||||||
|
|
||||||
|
# Scroll through existing workspaces with mainMod + scroll
|
||||||
|
bind = $mainMod, mouse_down, workspace, e+1
|
||||||
|
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
|
||||||
|
|||||||
12
example/hyprland.service
Normal file
12
example/hyprland.service
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
; a primitive systemd --user example
|
||||||
|
[Unit]
|
||||||
|
Description = %p
|
||||||
|
BindsTo = graphical-session.target
|
||||||
|
Upholds = swaybg@333333.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type = notify
|
||||||
|
ExecStart = /usr/bin/Hyprland
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy = default.target
|
||||||
16
example/screenShader.frag
Normal file
16
example/screenShader.frag
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// Example blue light filter shader.
|
||||||
|
//
|
||||||
|
|
||||||
|
precision mediump float;
|
||||||
|
varying vec2 v_texcoord;
|
||||||
|
uniform sampler2D tex;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
vec4 pixColor = texture2D(tex, v_texcoord);
|
||||||
|
|
||||||
|
pixColor[2] *= 0.8;
|
||||||
|
|
||||||
|
gl_FragColor = pixColor;
|
||||||
|
}
|
||||||
13
example/swaybg@.service
Normal file
13
example/swaybg@.service
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
; a primitive systemd --user example
|
||||||
|
; see example/hyprland.service for more details
|
||||||
|
[Unit]
|
||||||
|
Description = %p
|
||||||
|
BindsTo = hyprland.service
|
||||||
|
Wants = hyprland.service
|
||||||
|
After = hyprland.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart = /usr/bin/swaybg --color #%i
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy = default.target
|
||||||
59
flake.lock
generated
59
flake.lock
generated
@@ -1,12 +1,32 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"hyprland-protocols": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681065697,
|
||||||
|
"narHash": "sha256-QPzwwlGKX95tl6ZEshboZbEwwAXww6lNLdVYd6T9Mrc=",
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprland-protocols",
|
||||||
|
"rev": "4d29e48433270a2af06b8bc711ca1fe5109746cd",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprland-protocols",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1664989420,
|
"lastModified": 1683014792,
|
||||||
"narHash": "sha256-Q8IxomUjjmewsoJgO3htkXLfCckQ7HkDJ/ZhdYVf/fA=",
|
"narHash": "sha256-6Va9iVtmmsw4raBc3QKvQT2KT/NGRWlvUlJj46zN8B8=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "37bd39839acf99c5b738319f42478296f827f274",
|
"rev": "1a411f23ba299db155a5b45d5e145b85a7aafc42",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -18,19 +38,21 @@
|
|||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"hyprland-protocols": "hyprland-protocols",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"wlroots": "wlroots"
|
"wlroots": "wlroots",
|
||||||
|
"xdph": "xdph"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"wlroots": {
|
"wlroots": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"host": "gitlab.freedesktop.org",
|
"host": "gitlab.freedesktop.org",
|
||||||
"lastModified": 1663507239,
|
"lastModified": 1682436395,
|
||||||
"narHash": "sha256-LISZtkPVe8lQ2N8YwVe+KxCkXWLP9mdw6Q2kG93wE8A=",
|
"narHash": "sha256-GGEjkQO9m7YLYIXIXM76HWdhjg4Ye+oafOtyaFAYKI4=",
|
||||||
"owner": "wlroots",
|
"owner": "wlroots",
|
||||||
"repo": "wlroots",
|
"repo": "wlroots",
|
||||||
"rev": "2ad25b1460400e66ea26bd6489b04072be7d9dbb",
|
"rev": "6830bfc17fd94709e2cdd4da0af989f102a26e59",
|
||||||
"type": "gitlab"
|
"type": "gitlab"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -39,6 +61,29 @@
|
|||||||
"repo": "wlroots",
|
"repo": "wlroots",
|
||||||
"type": "gitlab"
|
"type": "gitlab"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"xdph": {
|
||||||
|
"inputs": {
|
||||||
|
"hyprland-protocols": [
|
||||||
|
"hyprland-protocols"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1682439384,
|
||||||
|
"narHash": "sha256-zHDa8LCZs05TZHQSIZ3ucwyMPglBGHcqTBzfkLjYXTM=",
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "xdg-desktop-portal-hyprland",
|
||||||
|
"rev": "c0e233955568fbea4e859336f6d3d14d51294d7c",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "xdg-desktop-portal-hyprland",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
|||||||
80
flake.nix
80
flake.nix
@@ -3,10 +3,22 @@
|
|||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
wlroots = {
|
wlroots = {
|
||||||
url = "gitlab:wlroots/wlroots?host=gitlab.freedesktop.org";
|
url = "gitlab:wlroots/wlroots?host=gitlab.freedesktop.org";
|
||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
hyprland-protocols = {
|
||||||
|
url = "github:hyprwm/hyprland-protocols";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
xdph = {
|
||||||
|
url = "github:hyprwm/xdg-desktop-portal-hyprland";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.hyprland-protocols.follows = "hyprland-protocols";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs @ {
|
outputs = inputs @ {
|
||||||
@@ -14,70 +26,54 @@
|
|||||||
nixpkgs,
|
nixpkgs,
|
||||||
...
|
...
|
||||||
}: let
|
}: let
|
||||||
inherit (nixpkgs) lib;
|
lib = nixpkgs.lib.extend (import ./nix/lib.nix);
|
||||||
genSystems = lib.genAttrs [
|
genSystems = lib.genAttrs [
|
||||||
# Add more systems if they are supported
|
# Add more systems if they are supported
|
||||||
"aarch64-linux"
|
"aarch64-linux"
|
||||||
"x86_64-linux"
|
"x86_64-linux"
|
||||||
];
|
];
|
||||||
|
|
||||||
pkgsFor = genSystems (system:
|
pkgsFor = genSystems (system:
|
||||||
import nixpkgs {
|
import nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
overlays = [
|
overlays = [
|
||||||
(_: prev: {
|
self.overlays.hyprland-packages
|
||||||
libdrm = prev.libdrm.overrideAttrs (old: rec {
|
self.overlays.wlroots-hyprland
|
||||||
version = "2.4.113";
|
inputs.hyprland-protocols.overlays.default
|
||||||
src = prev.fetchurl {
|
|
||||||
url = "https://dri.freedesktop.org/${old.pname}/${old.pname}-${version}.tar.xz";
|
|
||||||
sha256 = "sha256-f9frKWf2O+tGBvItUOJ32ZNIDQXvdd2Iqb2OZ3Mj5eE=";
|
|
||||||
};
|
|
||||||
mesonFlags =
|
|
||||||
[
|
|
||||||
"-Dinstall-test-programs=true"
|
|
||||||
"-Domap=enabled"
|
|
||||||
"-Dcairo-tests=disabled"
|
|
||||||
]
|
|
||||||
++ lib.optionals prev.stdenv.hostPlatform.isAarch [
|
|
||||||
"-Dtegra=enabled"
|
|
||||||
"-Detnaviv=enabled"
|
|
||||||
];
|
|
||||||
});
|
|
||||||
})
|
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
mkDate = longDate: (lib.concatStringsSep "-" [
|
|
||||||
(__substring 0 4 longDate)
|
|
||||||
(__substring 4 2 longDate)
|
|
||||||
(__substring 6 2 longDate)
|
|
||||||
]);
|
|
||||||
in {
|
in {
|
||||||
overlays.default = _: prev: rec {
|
overlays =
|
||||||
wlroots-hyprland = prev.callPackage ./nix/wlroots.nix {
|
(import ./nix/overlays.nix {inherit self lib inputs;})
|
||||||
version = mkDate (inputs.wlroots.lastModifiedDate or "19700101") + "_" + (inputs.wlroots.shortRev or "dirty");
|
// {
|
||||||
src = inputs.wlroots;
|
default =
|
||||||
|
lib.mkJoinedOverlays
|
||||||
|
(with self.overlays; [
|
||||||
|
hyprland-packages
|
||||||
|
hyprland-extras
|
||||||
|
wlroots-hyprland
|
||||||
|
]);
|
||||||
};
|
};
|
||||||
hyprland = prev.callPackage ./nix/default.nix {
|
|
||||||
stdenv = prev.gcc12Stdenv;
|
|
||||||
version = "0.15.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
|
|
||||||
wlroots = wlroots-hyprland;
|
|
||||||
};
|
|
||||||
hyprland-debug = hyprland.override {debug = true;};
|
|
||||||
hyprland-no-hidpi = hyprland.override {hidpiXWayland = false;};
|
|
||||||
|
|
||||||
waybar-hyprland = prev.waybar.overrideAttrs (oldAttrs: {
|
checks = genSystems (system:
|
||||||
mesonFlags = oldAttrs.mesonFlags ++ ["-Dexperimental=true"];
|
(lib.filterAttrs
|
||||||
|
(n: _: (lib.hasPrefix "hyprland" n) && !(lib.hasSuffix "debug" n))
|
||||||
|
self.packages.${system})
|
||||||
|
// {
|
||||||
|
inherit (self.packages.${system}) xdg-desktop-portal-hyprland;
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
packages = genSystems (system:
|
packages = genSystems (system:
|
||||||
(self.overlays.default null pkgsFor.${system})
|
(self.overlays.default pkgsFor.${system} pkgsFor.${system})
|
||||||
// {
|
// {
|
||||||
default = self.packages.${system}.hyprland;
|
default = self.packages.${system}.hyprland;
|
||||||
});
|
});
|
||||||
|
|
||||||
devShells = genSystems (system: {
|
devShells = genSystems (system: {
|
||||||
default = pkgsFor.${system}.mkShell.override {stdenv = pkgsFor.${system}.gcc12Stdenv;} {
|
default = pkgsFor.${system}.mkShell {
|
||||||
name = "hyprland-shell";
|
name = "hyprland-shell";
|
||||||
|
nativeBuildInputs = with pkgsFor.${system}; [cmake];
|
||||||
|
buildInputs = [self.packages.${system}.wlroots-hyprland];
|
||||||
inputsFrom = [
|
inputsFrom = [
|
||||||
self.packages.${system}.wlroots-hyprland
|
self.packages.${system}.wlroots-hyprland
|
||||||
self.packages.${system}.hyprland
|
self.packages.${system}.hyprland
|
||||||
@@ -87,7 +83,7 @@
|
|||||||
|
|
||||||
formatter = genSystems (system: pkgsFor.${system}.alejandra);
|
formatter = genSystems (system: pkgsFor.${system}.alejandra);
|
||||||
|
|
||||||
nixosModules.default = import ./nix/module.nix self;
|
nixosModules.default = import ./nix/module.nix inputs;
|
||||||
homeManagerModules.default = import ./nix/hm-module.nix self;
|
homeManagerModules.default = import ./nix/hm-module.nix self;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
all:
|
all:
|
||||||
g++ -std=c++23 ./main.cpp -o ./hyprctl
|
$(CXX) -std=c++2b ./main.cpp -o ./hyprctl
|
||||||
clean:
|
clean:
|
||||||
rm ./hyprctl
|
rm ./hyprctl
|
||||||
|
|||||||
199
hyprctl/main.cpp
199
hyprctl/main.cpp
@@ -23,10 +23,12 @@ const std::string USAGE = R"#(usage: hyprctl [(opt)flags] [command] [(opt)args]
|
|||||||
commands:
|
commands:
|
||||||
monitors
|
monitors
|
||||||
workspaces
|
workspaces
|
||||||
|
activeworkspace
|
||||||
clients
|
clients
|
||||||
activewindow
|
activewindow
|
||||||
layers
|
layers
|
||||||
devices
|
devices
|
||||||
|
binds
|
||||||
dispatch
|
dispatch
|
||||||
keyword
|
keyword
|
||||||
version
|
version
|
||||||
@@ -36,21 +38,36 @@ commands:
|
|||||||
reload
|
reload
|
||||||
setcursor
|
setcursor
|
||||||
getoption
|
getoption
|
||||||
|
cursorpos
|
||||||
|
switchxkblayout
|
||||||
|
seterror
|
||||||
|
setprop
|
||||||
|
plugin
|
||||||
|
notify
|
||||||
|
globalshortcuts
|
||||||
|
|
||||||
flags:
|
flags:
|
||||||
-j -> output in JSON
|
-j -> output in JSON
|
||||||
--batch -> execute a batch of commands, separated by ';'
|
--batch -> execute a batch of commands, separated by ';'
|
||||||
)#";
|
)#";
|
||||||
|
|
||||||
void request(std::string arg) {
|
#define PAD
|
||||||
|
|
||||||
|
void request(std::string arg, int minArgs = 0) {
|
||||||
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
const auto ARGS = std::count(arg.begin(), arg.end(), ' ');
|
||||||
|
|
||||||
|
if (ARGS < minArgs) {
|
||||||
|
std::cout << "Not enough arguments, expected at least " << minArgs;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (SERVERSOCKET < 0) {
|
if (SERVERSOCKET < 0) {
|
||||||
std::cout << "Couldn't open a socket (1)";
|
std::cout << "Couldn't open a socket (1)";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// get the instance signature
|
// get the instance signature
|
||||||
auto instanceSig = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
auto instanceSig = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
||||||
|
|
||||||
@@ -62,11 +79,11 @@ void request(std::string arg) {
|
|||||||
std::string instanceSigStr = std::string(instanceSig);
|
std::string instanceSigStr = std::string(instanceSig);
|
||||||
|
|
||||||
sockaddr_un serverAddress = {0};
|
sockaddr_un serverAddress = {0};
|
||||||
serverAddress.sun_family = AF_UNIX;
|
serverAddress.sun_family = AF_UNIX;
|
||||||
|
|
||||||
std::string socketPath = "/tmp/hypr/" + instanceSigStr + "/.socket.sock";
|
std::string socketPath = "/tmp/hypr/" + instanceSigStr + "/.socket.sock";
|
||||||
|
|
||||||
strcpy(serverAddress.sun_path, socketPath.c_str());
|
strncpy(serverAddress.sun_path, socketPath.c_str(), sizeof(serverAddress.sun_path) - 1);
|
||||||
|
|
||||||
if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN(&serverAddress)) < 0) {
|
if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN(&serverAddress)) < 0) {
|
||||||
std::cout << "Couldn't connect to " << socketPath << ". (3)";
|
std::cout << "Couldn't connect to " << socketPath << ". (3)";
|
||||||
@@ -80,7 +97,8 @@ void request(std::string arg) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buffer[8192] = {0};
|
std::string reply = "";
|
||||||
|
char buffer[8192] = {0};
|
||||||
|
|
||||||
sizeWritten = read(SERVERSOCKET, buffer, 8192);
|
sizeWritten = read(SERVERSOCKET, buffer, 8192);
|
||||||
|
|
||||||
@@ -89,9 +107,20 @@ void request(std::string arg) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reply += std::string(buffer, sizeWritten);
|
||||||
|
|
||||||
|
while (sizeWritten == 8192) {
|
||||||
|
sizeWritten = read(SERVERSOCKET, buffer, 8192);
|
||||||
|
if (sizeWritten < 0) {
|
||||||
|
std::cout << "Couldn't read (5)";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
reply += std::string(buffer, sizeWritten);
|
||||||
|
}
|
||||||
|
|
||||||
close(SERVERSOCKET);
|
close(SERVERSOCKET);
|
||||||
|
|
||||||
std::cout << std::string(buffer);
|
std::cout << reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
void requestHyprpaper(std::string arg) {
|
void requestHyprpaper(std::string arg) {
|
||||||
@@ -113,11 +142,11 @@ void requestHyprpaper(std::string arg) {
|
|||||||
std::string instanceSigStr = std::string(instanceSig);
|
std::string instanceSigStr = std::string(instanceSig);
|
||||||
|
|
||||||
sockaddr_un serverAddress = {0};
|
sockaddr_un serverAddress = {0};
|
||||||
serverAddress.sun_family = AF_UNIX;
|
serverAddress.sun_family = AF_UNIX;
|
||||||
|
|
||||||
std::string socketPath = "/tmp/hypr/" + instanceSigStr + "/.hyprpaper.sock";
|
std::string socketPath = "/tmp/hypr/" + instanceSigStr + "/.hyprpaper.sock";
|
||||||
|
|
||||||
strcpy(serverAddress.sun_path, socketPath.c_str());
|
strncpy(serverAddress.sun_path, socketPath.c_str(), sizeof(serverAddress.sun_path) - 1);
|
||||||
|
|
||||||
if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN(&serverAddress)) < 0) {
|
if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN(&serverAddress)) < 0) {
|
||||||
std::cout << "Couldn't connect to " << socketPath << ". (3)";
|
std::cout << "Couldn't connect to " << socketPath << ". (3)";
|
||||||
@@ -145,55 +174,84 @@ void requestHyprpaper(std::string arg) {
|
|||||||
std::cout << std::string(buffer);
|
std::cout << std::string(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatchRequest(int argc, char** argv) {
|
int dispatchRequest(int argc, char** argv) {
|
||||||
|
|
||||||
if (argc < 4) {
|
if (argc < 3) {
|
||||||
std::cout << "dispatch requires 2 params";
|
std::cout << "Usage: hyprctl dispatch <dispatcher> <arg>\n\
|
||||||
return;
|
Execute a hyprland keybind dispatcher with the given argument";
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string rq = "/dispatch";
|
std::string rq = "/dispatch";
|
||||||
|
|
||||||
for(int i = 2; i < argc; i++)
|
for (int i = 2; i < argc; i++) {
|
||||||
|
if (!strcmp(argv[i], "--"))
|
||||||
|
continue;
|
||||||
rq += " " + std::string(argv[i]);
|
rq += " " + std::string(argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
request(rq);
|
request(rq);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void keywordRequest(int argc, char** argv) {
|
int keywordRequest(int argc, char** argv) {
|
||||||
if (argc < 4) {
|
if (argc < 4) {
|
||||||
std::cout << "keyword requires 2 params";
|
std::cout << "Usage: hyprctl keyword <keyword> <arg>\n\
|
||||||
return;
|
Execute a hyprland keyword with the given argument";
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string rq = "/keyword";
|
std::string rq = "/keyword";
|
||||||
|
|
||||||
for(int i = 2; i < argc; i++)
|
for (int i = 2; i < argc; i++)
|
||||||
rq += " " + std::string(argv[i]);
|
rq += " " + std::string(argv[i]);
|
||||||
|
|
||||||
request(rq);
|
request(rq);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hyprpaperRequest(int argc, char** argv) {
|
int hyprpaperRequest(int argc, char** argv) {
|
||||||
if (argc < 4) {
|
if (argc < 4) {
|
||||||
std::cout << "hyprpaper requires 2 params";
|
std::cout << "Usage: hyprctl hyprpaper <command> <arg>\n\
|
||||||
return;
|
Execute a hyprpaper command with the given argument";
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string rq = std::string(argv[2]) + " " + std::string(argv[3]);
|
std::string rq = std::string(argv[2]) + " " + std::string(argv[3]);
|
||||||
|
|
||||||
requestHyprpaper(rq);
|
requestHyprpaper(rq);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setcursorRequest(int argc, char** argv) {
|
int setcursorRequest(int argc, char** argv) {
|
||||||
if (argc < 4) {
|
if (argc < 4) {
|
||||||
std::cout << "setcursor requires 2 params";
|
std::cout << "Usage: hyprctl setcursor <theme> <size>\n\
|
||||||
return;
|
Sets the cursor theme for everything except GTK and reloads the cursor";
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string rq = "setcursor " + std::string(argv[2]) + " " + std::string(argv[3]);
|
std::string rq = "setcursor ";
|
||||||
|
for (size_t i = 2; i < argc; ++i)
|
||||||
|
rq += std::string(argv[i]) + " ";
|
||||||
|
rq.pop_back();
|
||||||
|
|
||||||
request(rq);
|
request(rq);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int outputRequest(int argc, char** argv) {
|
||||||
|
if (argc < 4) {
|
||||||
|
std::cout << "Usage: hyprctl output <mode> <name>\n\
|
||||||
|
creates / destroys a fake output\n\
|
||||||
|
with create, name is the backend name to use (available: auto, x11, wayland, headless)\n\
|
||||||
|
with destroy, name is the output name to destroy";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rq = "output " + std::string(argv[2]) + " " + std::string(argv[3]);
|
||||||
|
|
||||||
|
request(rq);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void batchRequest(std::string arg) {
|
void batchRequest(std::string arg) {
|
||||||
@@ -212,11 +270,14 @@ std::deque<std::string> splitArgs(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isNumber(const std::string& str, bool allowfloat) {
|
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 == '.'); });
|
return std::ranges::all_of(str.begin(), str.end(), [&](char c) { return isdigit(c) != 0 || c == '-' || (allowfloat && c == '.'); });
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
int bflag = 0, sflag = 0, index, c;
|
int bflag = 0, sflag = 0, index, c;
|
||||||
|
bool parseArgs = true;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
printf("%s\n", USAGE.c_str());
|
printf("%s\n", USAGE.c_str());
|
||||||
@@ -224,11 +285,16 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string fullRequest = "";
|
std::string fullRequest = "";
|
||||||
std::string fullArgs = "";
|
std::string fullArgs = "";
|
||||||
const auto ARGS = splitArgs(argc, argv);
|
const auto ARGS = splitArgs(argc, argv);
|
||||||
|
|
||||||
for (auto i = 0; i < ARGS.size(); ++i) {
|
for (auto i = 0; i < ARGS.size(); ++i) {
|
||||||
if (ARGS[i][0] == '-' && !isNumber(ARGS[i], true) /* For stuff like -2 */) {
|
if (ARGS[i] == "--") {
|
||||||
|
// Stop parsing arguments after --
|
||||||
|
parseArgs = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (parseArgs && (ARGS[i][0] == '-') && !isNumber(ARGS[i], true) /* For stuff like -2 */) {
|
||||||
// parse
|
// parse
|
||||||
if (ARGS[i] == "-j" && !fullArgs.contains("j")) {
|
if (ARGS[i] == "-j" && !fullArgs.contains("j")) {
|
||||||
fullArgs += "j";
|
fullArgs += "j";
|
||||||
@@ -254,28 +320,69 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
fullRequest = fullArgs + "/" + fullRequest;
|
fullRequest = fullArgs + "/" + fullRequest;
|
||||||
|
|
||||||
if (fullRequest.contains("/--batch")) batchRequest(fullRequest);
|
int exitStatus = 0;
|
||||||
else if (fullRequest.contains("/monitors")) request(fullRequest);
|
|
||||||
else if (fullRequest.contains("/clients")) request(fullRequest);
|
if (fullRequest.contains("/--batch"))
|
||||||
else if (fullRequest.contains("/workspaces")) request(fullRequest);
|
batchRequest(fullRequest);
|
||||||
else if (fullRequest.contains("/activewindow")) request(fullRequest);
|
else if (fullRequest.contains("/monitors"))
|
||||||
else if (fullRequest.contains("/layers")) request(fullRequest);
|
request(fullRequest);
|
||||||
else if (fullRequest.contains("/version")) request(fullRequest);
|
else if (fullRequest.contains("/clients"))
|
||||||
else if (fullRequest.contains("/kill")) request(fullRequest);
|
request(fullRequest);
|
||||||
else if (fullRequest.contains("/splash")) request(fullRequest);
|
else if (fullRequest.contains("/workspaces"))
|
||||||
else if (fullRequest.contains("/devices")) request(fullRequest);
|
request(fullRequest);
|
||||||
else if (fullRequest.contains("/reload")) request(fullRequest);
|
else if (fullRequest.contains("/activeworkspace"))
|
||||||
else if (fullRequest.contains("/getoption")) request(fullRequest);
|
request(fullRequest);
|
||||||
else if (fullRequest.contains("/setcursor")) setcursorRequest(argc, argv);
|
else if (fullRequest.contains("/activewindow"))
|
||||||
else if (fullRequest.contains("/dispatch")) dispatchRequest(argc, argv);
|
request(fullRequest);
|
||||||
else if (fullRequest.contains("/keyword")) keywordRequest(argc, argv);
|
else if (fullRequest.contains("/layers"))
|
||||||
else if (fullRequest.contains("/hyprpaper")) hyprpaperRequest(argc, argv);
|
request(fullRequest);
|
||||||
else if (fullRequest.contains("/--help")) printf("%s", USAGE.c_str());
|
else if (fullRequest.contains("/version"))
|
||||||
|
request(fullRequest);
|
||||||
|
else if (fullRequest.contains("/kill"))
|
||||||
|
request(fullRequest);
|
||||||
|
else if (fullRequest.contains("/splash"))
|
||||||
|
request(fullRequest);
|
||||||
|
else if (fullRequest.contains("/devices"))
|
||||||
|
request(fullRequest);
|
||||||
|
else if (fullRequest.contains("/reload"))
|
||||||
|
request(fullRequest);
|
||||||
|
else if (fullRequest.contains("/getoption"))
|
||||||
|
request(fullRequest);
|
||||||
|
else if (fullRequest.contains("/binds"))
|
||||||
|
request(fullRequest);
|
||||||
|
else if (fullRequest.contains("/cursorpos"))
|
||||||
|
request(fullRequest);
|
||||||
|
else if (fullRequest.contains("/animations"))
|
||||||
|
request(fullRequest);
|
||||||
|
else if (fullRequest.contains("/globalshortcuts"))
|
||||||
|
request(fullRequest);
|
||||||
|
else if (fullRequest.contains("/switchxkblayout"))
|
||||||
|
request(fullRequest, 2);
|
||||||
|
else if (fullRequest.contains("/seterror"))
|
||||||
|
request(fullRequest, 1);
|
||||||
|
else if (fullRequest.contains("/setprop"))
|
||||||
|
request(fullRequest, 3);
|
||||||
|
else if (fullRequest.contains("/plugin"))
|
||||||
|
request(fullRequest, 1);
|
||||||
|
else if (fullRequest.contains("/notify"))
|
||||||
|
request(fullRequest, 2);
|
||||||
|
else if (fullRequest.contains("/output"))
|
||||||
|
exitStatus = outputRequest(argc, argv);
|
||||||
|
else if (fullRequest.contains("/setcursor"))
|
||||||
|
exitStatus = setcursorRequest(argc, argv);
|
||||||
|
else if (fullRequest.contains("/dispatch"))
|
||||||
|
exitStatus = dispatchRequest(argc, argv);
|
||||||
|
else if (fullRequest.contains("/keyword"))
|
||||||
|
exitStatus = keywordRequest(argc, argv);
|
||||||
|
else if (fullRequest.contains("/hyprpaper"))
|
||||||
|
exitStatus = hyprpaperRequest(argc, argv);
|
||||||
|
else if (fullRequest.contains("/--help"))
|
||||||
|
printf("%s", USAGE.c_str());
|
||||||
else {
|
else {
|
||||||
printf("%s\n", USAGE.c_str());
|
printf("%s\n", USAGE.c_str());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
return 0;
|
return exitStatus;
|
||||||
}
|
}
|
||||||
|
|||||||
8
hyprland.pc.in
Normal file
8
hyprland.pc.in
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
prefix="@PREFIX@"
|
||||||
|
includedir="${prefix}/include"
|
||||||
|
|
||||||
|
Name: Hyprland
|
||||||
|
URL: https://github.com/hyprwm/Hyprland
|
||||||
|
Description: Hyprland header files
|
||||||
|
Version: @HYPRLAND_VERSION@
|
||||||
|
Cflags: -I"${includedir}/hyprland/protocols" -I"${includedir}/hyprland/wlroots" -I"${includedir}"
|
||||||
46
meson.build
46
meson.build
@@ -1,9 +1,11 @@
|
|||||||
project('Hyprland', 'cpp', 'c',
|
project('Hyprland', 'cpp', 'c',
|
||||||
version : '0.15.0beta',
|
version : run_command('jq', '-r', '.version', join_paths(meson.source_root(), 'props.json'), check: true).stdout().strip(),
|
||||||
default_options : [
|
default_options : [
|
||||||
'warning_level=2',
|
'warning_level=2',
|
||||||
'default_library=static',
|
'default_library=static',
|
||||||
'optimization=3',
|
'optimization=3',
|
||||||
|
'buildtype=release',
|
||||||
|
'debug=false'
|
||||||
# 'cpp_std=c++23' # not yet supported by meson, as of version 0.63.0
|
# 'cpp_std=c++23' # not yet supported by meson, as of version 0.63.0
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -20,8 +22,8 @@ endif
|
|||||||
|
|
||||||
GIT_BRANCH = run_command('git', 'rev-parse', '--abbrev-ref', 'HEAD', check: false).stdout().strip()
|
GIT_BRANCH = run_command('git', 'rev-parse', '--abbrev-ref', 'HEAD', check: false).stdout().strip()
|
||||||
GIT_COMMIT_HASH = run_command('git', 'rev-parse', 'HEAD', check: false).stdout().strip()
|
GIT_COMMIT_HASH = run_command('git', 'rev-parse', 'HEAD', check: false).stdout().strip()
|
||||||
GIT_COMMIT_MESSAGE = run_command('bash', '-c', 'git show | head -n 5 | tail -n 1', check: false).stdout().strip()
|
GIT_COMMIT_MESSAGE = run_command('sh', '-c', 'git show | head -n 5 | tail -n 1', check: false).stdout().strip()
|
||||||
GIT_DIRTY = run_command('bash', '-c', 'git diff-index --quiet HEAD -- || echo "dirty"', check: false).stdout().strip()
|
GIT_DIRTY = run_command('sh', '-c', 'git diff-index --quiet HEAD -- || echo "dirty"', check: false).stdout().strip()
|
||||||
|
|
||||||
add_project_arguments(
|
add_project_arguments(
|
||||||
[
|
[
|
||||||
@@ -41,22 +43,58 @@ wlroots = subproject('wlroots', default_options: ['examples=false'])
|
|||||||
have_xwlr = wlroots.get_variable('features').get('xwayland')
|
have_xwlr = wlroots.get_variable('features').get('xwayland')
|
||||||
xcb_dep = dependency('xcb', required: get_option('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
|
if get_option('xwayland').enabled() and not have_xwlr
|
||||||
error('Cannot enable Xwayland in Hyprland: wlroots has been built without Xwayland support')
|
error('Cannot enable Xwayland in Hyprland: wlroots has been built without Xwayland support')
|
||||||
endif
|
endif
|
||||||
have_xwayland = xcb_dep.found() and have_xwlr
|
have_xwayland = xcb_dep.found() and have_xwlr
|
||||||
|
|
||||||
if not have_xwayland
|
if not have_xwayland
|
||||||
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
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'))
|
||||||
|
|
||||||
|
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()
|
||||||
|
add_project_arguments('-DLEGACY_RENDERER', language: 'cpp')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if get_option('buildtype') == 'debug'
|
if get_option('buildtype') == 'debug'
|
||||||
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
|
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
globber = run_command('find', 'src', '-name', '*.h*', check: true)
|
||||||
|
headers = globber.stdout().strip().split('\n')
|
||||||
|
foreach file : headers
|
||||||
|
install_headers(file, subdir: 'hyprland', preserve_path: true)
|
||||||
|
endforeach
|
||||||
|
|
||||||
subdir('protocols')
|
subdir('protocols')
|
||||||
subdir('src')
|
subdir('src')
|
||||||
subdir('hyprctl')
|
subdir('hyprctl')
|
||||||
subdir('assets')
|
subdir('assets')
|
||||||
subdir('example')
|
subdir('example')
|
||||||
subdir('docs')
|
subdir('docs')
|
||||||
|
|
||||||
|
pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig')
|
||||||
|
|
||||||
|
import('pkgconfig').generate(
|
||||||
|
name: 'Hyprland',
|
||||||
|
filebase: 'hyprland',
|
||||||
|
url: 'https://github.com/hyprwm/Hyprland',
|
||||||
|
description: 'Hyprland header files',
|
||||||
|
install_dir: pkg_install_dir,
|
||||||
|
subdirs: ['', 'hyprland/protocols'],
|
||||||
|
)
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
|
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
|
||||||
|
option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration')
|
||||||
|
option('legacy_renderer', type: 'feature', value: 'disabled', description: 'Enable legacy renderer')
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
{
|
{
|
||||||
lib,
|
lib,
|
||||||
stdenv,
|
stdenv,
|
||||||
fetchFromGitHub,
|
|
||||||
fetchpatch,
|
|
||||||
pkg-config,
|
pkg-config,
|
||||||
meson,
|
meson,
|
||||||
ninja,
|
ninja,
|
||||||
|
cairo,
|
||||||
git,
|
git,
|
||||||
|
hyprland-protocols,
|
||||||
|
jq,
|
||||||
libdrm,
|
libdrm,
|
||||||
libinput,
|
libinput,
|
||||||
libxcb,
|
libxcb,
|
||||||
libxkbcommon,
|
libxkbcommon,
|
||||||
mesa,
|
mesa,
|
||||||
mount,
|
|
||||||
pango,
|
pango,
|
||||||
|
pciutils,
|
||||||
|
systemd,
|
||||||
|
udis86,
|
||||||
wayland,
|
wayland,
|
||||||
wayland-protocols,
|
wayland-protocols,
|
||||||
wayland-scanner,
|
wayland-scanner,
|
||||||
@@ -22,10 +25,12 @@
|
|||||||
xwayland,
|
xwayland,
|
||||||
debug ? false,
|
debug ? false,
|
||||||
enableXWayland ? true,
|
enableXWayland ? true,
|
||||||
hidpiXWayland ? true,
|
hidpiXWayland ? false,
|
||||||
legacyRenderer ? false,
|
legacyRenderer ? false,
|
||||||
nvidiaPatches ? false,
|
nvidiaPatches ? false,
|
||||||
|
withSystemd ? true,
|
||||||
version ? "git",
|
version ? "git",
|
||||||
|
commit,
|
||||||
}: let
|
}: let
|
||||||
assertXWayland = lib.assertMsg (hidpiXWayland -> enableXWayland) ''
|
assertXWayland = lib.assertMsg (hidpiXWayland -> enableXWayland) ''
|
||||||
Hyprland: cannot have hidpiXWayland when enableXWayland is false.
|
Hyprland: cannot have hidpiXWayland when enableXWayland is false.
|
||||||
@@ -47,6 +52,7 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
|
jq
|
||||||
meson
|
meson
|
||||||
ninja
|
ninja
|
||||||
pkg-config
|
pkg-config
|
||||||
@@ -55,24 +61,28 @@ in
|
|||||||
outputs = [
|
outputs = [
|
||||||
"out"
|
"out"
|
||||||
"man"
|
"man"
|
||||||
|
"dev"
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs =
|
buildInputs =
|
||||||
[
|
[
|
||||||
git
|
git
|
||||||
|
cairo
|
||||||
|
hyprland-protocols
|
||||||
libdrm
|
libdrm
|
||||||
libinput
|
libinput
|
||||||
libxcb
|
|
||||||
libxkbcommon
|
libxkbcommon
|
||||||
mesa
|
mesa
|
||||||
pango
|
pango
|
||||||
|
udis86
|
||||||
wayland
|
wayland
|
||||||
wayland-protocols
|
wayland-protocols
|
||||||
wayland-scanner
|
wayland-scanner
|
||||||
|
pciutils
|
||||||
(wlroots.override {inherit enableXWayland hidpiXWayland nvidiaPatches;})
|
(wlroots.override {inherit enableXWayland hidpiXWayland nvidiaPatches;})
|
||||||
xcbutilwm
|
|
||||||
]
|
]
|
||||||
++ lib.optional enableXWayland xwayland;
|
++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland]
|
||||||
|
++ lib.optionals withSystemd [systemd];
|
||||||
|
|
||||||
mesonBuildType =
|
mesonBuildType =
|
||||||
if debug
|
if debug
|
||||||
@@ -80,8 +90,10 @@ in
|
|||||||
else "release";
|
else "release";
|
||||||
|
|
||||||
mesonFlags = builtins.concatLists [
|
mesonFlags = builtins.concatLists [
|
||||||
(lib.optional (!enableXWayland) "-Dxwayland=disabled")
|
["-Dauto_features=disabled"]
|
||||||
(lib.optional legacyRenderer "-DLEGACY_RENDERER:STRING=true")
|
(lib.optional enableXWayland "-Dxwayland=enabled")
|
||||||
|
(lib.optional legacyRenderer "-Dlegacy_renderer=enabled")
|
||||||
|
(lib.optional withSystemd "-Dsystemd=enabled")
|
||||||
];
|
];
|
||||||
|
|
||||||
patches = [
|
patches = [
|
||||||
@@ -89,9 +101,16 @@ in
|
|||||||
./meson-build.patch
|
./meson-build.patch
|
||||||
];
|
];
|
||||||
|
|
||||||
# Fix hardcoded paths to /usr installation
|
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
|
# Fix hardcoded paths to /usr installation
|
||||||
sed -i "s#/usr#$out#" src/render/OpenGL.cpp
|
sed -i "s#/usr#$out#" src/render/OpenGL.cpp
|
||||||
|
substituteInPlace meson.build \
|
||||||
|
--replace "@GIT_COMMIT_HASH@" '${commit}' \
|
||||||
|
--replace "@GIT_DIRTY@" '${
|
||||||
|
if commit == ""
|
||||||
|
then "dirty"
|
||||||
|
else ""
|
||||||
|
}'
|
||||||
'';
|
'';
|
||||||
|
|
||||||
passthru.providedSessions = ["hyprland"];
|
passthru.providedSessions = ["hyprland"];
|
||||||
|
|||||||
@@ -5,114 +5,156 @@ self: {
|
|||||||
...
|
...
|
||||||
}: let
|
}: let
|
||||||
cfg = config.wayland.windowManager.hyprland;
|
cfg = config.wayland.windowManager.hyprland;
|
||||||
defaultHyprlandPackage = self.packages.${pkgs.system}.default.override {
|
defaultHyprlandPackage = self.packages.${pkgs.stdenv.hostPlatform.system}.default.override {
|
||||||
enableXWayland = cfg.xwayland.enable;
|
enableXWayland = cfg.xwayland.enable;
|
||||||
hidpiXWayland = cfg.xwayland.hidpi;
|
hidpiXWayland = cfg.xwayland.hidpi;
|
||||||
|
inherit (cfg) nvidiaPatches;
|
||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
|
meta.maintainers = [lib.maintainers.fufexan];
|
||||||
|
|
||||||
options.wayland.windowManager.hyprland = {
|
options.wayland.windowManager.hyprland = {
|
||||||
enable = lib.mkEnableOption "hyprland wayland compositor";
|
enable =
|
||||||
|
lib.mkEnableOption null
|
||||||
|
// {
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
Whether to enable Hyprland, the dynamic tiling Wayland compositor
|
||||||
|
that doesn't sacrifice on its looks.
|
||||||
|
|
||||||
|
You can manually launch Hyprland by executing {command}`Hyprland` on
|
||||||
|
a TTY.
|
||||||
|
|
||||||
|
See <https://wiki.hyprland.org> for more information.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
package = lib.mkOption {
|
package = lib.mkOption {
|
||||||
type = with lib.types; nullOr package;
|
type = with lib.types; nullOr package;
|
||||||
default = defaultHyprlandPackage;
|
default = defaultHyprlandPackage;
|
||||||
description = ''
|
defaultText = lib.literalExpression ''
|
||||||
Hyprland package to use. Will override the 'xwayland' option.
|
hyprland.packages.''${pkgs.stdenv.hostPlatform.system}.default.override {
|
||||||
|
enableXWayland = config.wayland.windowManager.hyprland.xwayland.enable;
|
||||||
|
hidpiXWayland = config.wayland.windowManager.hyprland.xwayland.hidpi;
|
||||||
|
inherit (config.wayland.windowManager.hyprland) nvidiaPatches;
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
Hyprland package to use. Will override the 'xwayland' and
|
||||||
|
'nvidiaPatches' options.
|
||||||
|
|
||||||
Defaults to the one provided by the flake. Set it to
|
Defaults to the one provided by the flake. Set it to
|
||||||
<literal>pkgs.hyprland</literal> to use the one provided by nixpkgs or
|
{package}`pkgs.hyprland` to use the one provided by nixpkgs or
|
||||||
if you have an overlay.
|
if you have an overlay.
|
||||||
|
|
||||||
Set to null to not add any Hyprland package to your path. This should
|
Set to null to not add any Hyprland package to your path. This should
|
||||||
be done if you want to use the NixOS module to install Hyprland.
|
be done if you want to use the NixOS module to install Hyprland.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
plugins = lib.mkOption {
|
||||||
|
type = with lib.types; listOf (either package path);
|
||||||
|
default = [];
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
List of hyprlad plugins to use. Can either be packages or
|
||||||
|
absolute plugin paths.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
systemdIntegration = lib.mkOption {
|
systemdIntegration = lib.mkOption {
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
default = pkgs.stdenv.isLinux;
|
default = pkgs.stdenv.isLinux;
|
||||||
description = ''
|
description = lib.mdDoc ''
|
||||||
Whether to enable <filename>hyprland-session.target</filename> on
|
Whether to enable {file}`hyprland-session.target` on
|
||||||
hyprland startup. This links to <filename>graphical-session.target</filename>.
|
hyprland startup. This links to {file}`graphical-session.target`.
|
||||||
Some important environment variables will be imported to systemd
|
Some important environment variables will be imported to systemd
|
||||||
and dbus user environment before reaching the target, including
|
and dbus user environment before reaching the target, including
|
||||||
<itemizedlist>
|
- {env}`DISPLAY`
|
||||||
<listitem><para><literal>DISPLAY</literal></para></listitem>
|
- {env}`HYPRLAND_INSTANCE_SIGNATURE`
|
||||||
<listitem><para><literal>WAYLAND_DISPLAY</literal></para></listitem>
|
- {env}`WAYLAND_DISPLAY`
|
||||||
<listitem><para><literal>HYPRLAND_INSTANCE_SIGNATURE</literal></para></listitem>
|
- {env}`XDG_CURRENT_DESKTOP`
|
||||||
<listitem><para><literal>XDG_CURRENT_DESKTOP</literal></para></listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
disableAutoreload =
|
||||||
|
lib.mkEnableOption null
|
||||||
|
// {
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
Whether to disable automatically reloading Hyprland's configuration when
|
||||||
|
rebuilding the Home Manager profile.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
xwayland = {
|
xwayland = {
|
||||||
enable = lib.mkOption {
|
enable = lib.mkEnableOption (lib.mdDoc "XWayland") // {default = true;};
|
||||||
type = lib.types.bool;
|
hidpi =
|
||||||
default = true;
|
lib.mkEnableOption null
|
||||||
description = ''
|
// {
|
||||||
Enable XWayland.
|
description = lib.mdDoc ''
|
||||||
'';
|
Enable HiDPI XWayland, based on [XWayland MR 733](https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/733).
|
||||||
};
|
See <https://wiki.hyprland.org/Nix/Options-Overrides/#xwayland-hidpi> for more info.
|
||||||
hidpi = lib.mkOption {
|
'';
|
||||||
type = lib.types.bool;
|
};
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
Enable HiDPI XWayland.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
nvidiaPatches = lib.mkEnableOption (lib.mdDoc "patching wlroots for better Nvidia support.");
|
||||||
|
|
||||||
extraConfig = lib.mkOption {
|
extraConfig = lib.mkOption {
|
||||||
type = lib.types.lines;
|
type = lib.types.nullOr lib.types.lines;
|
||||||
default = "";
|
default = "";
|
||||||
description = ''
|
description = lib.mdDoc ''
|
||||||
Extra configuration lines to add to ~/.config/hypr/hyprland.conf.
|
Extra configuration lines to add to {file}`~/.config/hypr/hyprland.conf`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
recommendedEnvironment = lib.mkOption {
|
recommendedEnvironment =
|
||||||
type = lib.types.bool;
|
lib.mkEnableOption null
|
||||||
default = true;
|
// {
|
||||||
defaultText = lib.literalExpression "true";
|
description = lib.mdDoc ''
|
||||||
example = lib.literalExpression "false";
|
Whether to set the recommended environment variables.
|
||||||
description = ''
|
'';
|
||||||
Whether to set the recommended environment variables.
|
};
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
imports = [
|
|
||||||
(
|
|
||||||
lib.mkRenamedOptionModule
|
|
||||||
["wayland" "windowManager" "hyprland" "xwayland"]
|
|
||||||
["wayland" "windowManager" "hyprland" "xwayland" "enable"]
|
|
||||||
)
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
|
warnings =
|
||||||
|
if (cfg.systemdIntegration || cfg.plugins != []) && cfg.extraConfig == null then
|
||||||
|
[ ''You have enabled hyprland.systemdIntegration or listed plugins in hyprland.plugins.
|
||||||
|
Your hyprland config will be linked by home manager.
|
||||||
|
Set hyprland.extraConfig or unset hyprland.systemdIntegration and hyprland.plugins to remove this warning.'' ]
|
||||||
|
else [];
|
||||||
|
|
||||||
home.packages =
|
home.packages =
|
||||||
lib.optional (cfg.package != null) cfg.package
|
lib.optional (cfg.package != null) cfg.package
|
||||||
++ lib.optional cfg.xwayland.enable pkgs.xwayland;
|
++ lib.optional cfg.xwayland.enable pkgs.xwayland;
|
||||||
|
|
||||||
home.sessionVariables = lib.mkIf cfg.recommendedEnvironment {
|
home.sessionVariables =
|
||||||
GDK_BACKEND = "wayland";
|
lib.mkIf cfg.recommendedEnvironment {NIXOS_OZONE_WL = "1";};
|
||||||
_JAVA_AWT_WM_NONREPARENTING = "1";
|
|
||||||
NIXOS_OZONE_WL = "1";
|
|
||||||
XCURSOR_SIZE = toString config.home.pointerCursor.size or "24";
|
|
||||||
XDG_SESSION_TYPE = "wayland";
|
|
||||||
};
|
|
||||||
|
|
||||||
xdg.configFile."hypr/hyprland.conf" = {
|
xdg.configFile."hypr/hyprland.conf" = lib.mkIf (cfg.systemdIntegration || cfg.extraConfig != null || cfg.plugins != []) {
|
||||||
text =
|
text =
|
||||||
(lib.optionalString cfg.systemdIntegration ''
|
(lib.optionalString cfg.systemdIntegration ''
|
||||||
exec-once=${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP
|
exec-once=${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP && systemctl --user start hyprland-session.target
|
||||||
exec-once=systemctl --user start hyprland-session.target
|
|
||||||
'')
|
'')
|
||||||
+ cfg.extraConfig;
|
+ lib.concatStrings (builtins.map (entry: let
|
||||||
|
plugin = if lib.types.package.check entry then "${entry}/lib/lib${entry.pname}.so" else entry;
|
||||||
|
in "plugin = ${plugin}\n") cfg.plugins)
|
||||||
|
+ (if cfg.extraConfig != null then cfg.extraConfig else "");
|
||||||
|
|
||||||
onChange = let
|
onChange = let
|
||||||
hyprlandPackage =
|
hyprlandPackage =
|
||||||
if cfg.package == null
|
if cfg.package == null
|
||||||
then defaultHyprlandPackage
|
then defaultHyprlandPackage
|
||||||
else cfg.package;
|
else cfg.package;
|
||||||
in "HYPRLAND_INSTANCE_SIGNATURE=$(ls -w 1 /tmp/hypr | tail -1) ${hyprlandPackage}/bin/hyprctl reload config-only";
|
in
|
||||||
|
lib.mkIf (!cfg.disableAutoreload) ''
|
||||||
|
( # execute in subshell so that `shopt` won't affect other scripts
|
||||||
|
shopt -s nullglob # so that nothing is done if /tmp/hypr/ does not exist or is empty
|
||||||
|
for instance in /tmp/hypr/*; do
|
||||||
|
HYPRLAND_INSTANCE_SIGNATURE=''${instance##*/} ${hyprlandPackage}/bin/hyprctl reload config-only \
|
||||||
|
|| true # ignore dead instance(s)
|
||||||
|
done
|
||||||
|
)
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.user.targets.hyprland-session = lib.mkIf cfg.systemdIntegration {
|
systemd.user.targets.hyprland-session = lib.mkIf cfg.systemdIntegration {
|
||||||
@@ -124,12 +166,5 @@ in {
|
|||||||
After = ["graphical-session-pre.target"];
|
After = ["graphical-session-pre.target"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.user.targets.tray = {
|
|
||||||
Unit = {
|
|
||||||
Description = "Home Manager System Tray";
|
|
||||||
Requires = ["graphical-session-pre.target"];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
8
nix/lib.nix
Normal file
8
nix/lib.nix
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
final: prev: let
|
||||||
|
lib = final;
|
||||||
|
|
||||||
|
mkJoinedOverlays = overlays: final: prev:
|
||||||
|
lib.foldl' (attrs: overlay: attrs // (overlay final prev)) {} overlays;
|
||||||
|
in prev // {
|
||||||
|
inherit mkJoinedOverlays;
|
||||||
|
}
|
||||||
@@ -1,36 +1,64 @@
|
|||||||
diff --git a/meson.build b/meson.build
|
diff --git a/meson.build b/meson.build
|
||||||
index 22ee4bf..5528613 100644
|
index f3802553..6a924a79 100644
|
||||||
--- a/meson.build
|
--- a/meson.build
|
||||||
+++ b/meson.build
|
+++ b/meson.build
|
||||||
@@ -2,16 +2,10 @@ project('Hyprland', 'cpp', 'c',
|
@@ -21,9 +21,9 @@ else
|
||||||
version : '0.1',
|
endif
|
||||||
default_options : ['warning_level=3', 'cpp_std=c++20', 'default_library=static'])
|
|
||||||
|
GIT_BRANCH = run_command('git', 'rev-parse', '--abbrev-ref', 'HEAD', check: false).stdout().strip()
|
||||||
|
-GIT_COMMIT_HASH = run_command('git', 'rev-parse', 'HEAD', check: false).stdout().strip()
|
||||||
|
+GIT_COMMIT_HASH = '@GIT_COMMIT_HASH@'
|
||||||
|
GIT_COMMIT_MESSAGE = run_command('sh', '-c', 'git show | head -n 5 | tail -n 1', check: false).stdout().strip()
|
||||||
|
-GIT_DIRTY = run_command('sh', '-c', 'git diff-index --quiet HEAD -- || echo "dirty"', check: false).stdout().strip()
|
||||||
|
+GIT_DIRTY = '@GIT_DIRTY@'
|
||||||
|
|
||||||
|
add_project_arguments(
|
||||||
|
[
|
||||||
|
@@ -39,21 +39,8 @@ add_project_arguments(
|
||||||
|
],
|
||||||
|
language: 'cpp')
|
||||||
|
|
||||||
-wlroots = subproject('wlroots', default_options: ['examples=false'])
|
-wlroots = subproject('wlroots', default_options: ['examples=false'])
|
||||||
-have_xwlr = wlroots.get_variable('features').get('xwayland')
|
-have_xwlr = wlroots.get_variable('features').get('xwayland')
|
||||||
+wlroots = dependency('wlroots', version: '>=0.16.0')
|
-xcb_dep = dependency('xcb', required: get_option('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
|
-if get_option('xwayland').enabled() and not have_xwlr
|
||||||
- error('Cannot enable Xwayland in Hyprland: wlroots has been built without Xwayland support')
|
- error('Cannot enable Xwayland in Hyprland: wlroots has been built without Xwayland support')
|
||||||
-endif
|
-endif
|
||||||
-have_xwayland = xcb_dep.found() and have_xwlr
|
-have_xwayland = xcb_dep.found() and have_xwlr
|
||||||
-
|
-
|
||||||
-if not have_xwayland
|
-if not have_xwayland
|
||||||
+if not xcb_dep.found()
|
- add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
||||||
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
+if get_option('xwayland').disabled()
|
||||||
|
+ add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
backtrace_dep = cpp_compiler.find_library('execinfo', required: false)
|
||||||
diff --git a/src/meson.build b/src/meson.build
|
diff --git a/src/meson.build b/src/meson.build
|
||||||
index 5d64188..a676333 100644
|
index 7b658d31..60aa4057 100644
|
||||||
--- a/src/meson.build
|
--- a/src/meson.build
|
||||||
+++ b/src/meson.build
|
+++ b/src/meson.build
|
||||||
@@ -7,7 +7,7 @@ executable('Hyprland', src,
|
@@ -7,16 +7,16 @@ executable('Hyprland', src,
|
||||||
server_protos,
|
server_protos,
|
||||||
dependency('wayland-server'),
|
dependency('wayland-server'),
|
||||||
dependency('wayland-client'),
|
dependency('wayland-client'),
|
||||||
- wlroots.get_variable('wlroots'),
|
- wlroots.get_variable('wlroots'),
|
||||||
+ wlroots,
|
+ dependency('wlroots'),
|
||||||
dependency('cairo'),
|
dependency('cairo'),
|
||||||
dependency('pango'),
|
dependency('libdrm'),
|
||||||
dependency('pangocairo'),
|
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'),
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
# Copied from https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/programs/sway.nix
|
inputs: {
|
||||||
self: {
|
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
@@ -7,64 +6,93 @@ self: {
|
|||||||
}:
|
}:
|
||||||
with lib; let
|
with lib; let
|
||||||
cfg = config.programs.hyprland;
|
cfg = config.programs.hyprland;
|
||||||
|
|
||||||
|
defaultHyprlandPackage = inputs.self.packages.${pkgs.stdenv.hostPlatform.system}.default.override {
|
||||||
|
enableXWayland = cfg.xwayland.enable;
|
||||||
|
hidpiXWayland = cfg.xwayland.hidpi;
|
||||||
|
inherit (cfg) nvidiaPatches;
|
||||||
|
};
|
||||||
in {
|
in {
|
||||||
imports = [
|
# disables Nixpkgs Hyprland module to avoid conflicts
|
||||||
(mkRemovedOptionModule ["programs" "hyprland" "extraPackages"] "extraPackages has been removed. Use environment.systemPackages instead.")
|
disabledModules = ["programs/hyprland.nix"];
|
||||||
];
|
|
||||||
|
|
||||||
options.programs.hyprland = {
|
options.programs.hyprland = {
|
||||||
enable = mkEnableOption ''
|
enable =
|
||||||
Hyprland, the dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
|
mkEnableOption null
|
||||||
You can manually launch Hyprland by executing "exec Hyprland" on a TTY.
|
// {
|
||||||
A configuration file will be generated in ~/.config/hypr/hyprland.conf.
|
description = mdDoc ''
|
||||||
See <link xlink:href="https://github.com/vaxerski/Hyprland/wiki" /> for
|
Hyprland, the dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
|
||||||
more information.
|
|
||||||
'';
|
You can manually launch Hyprland by executing {command}`Hyprland` on a TTY.
|
||||||
|
|
||||||
|
A configuration file will be generated in {file}`~/.config/hypr/hyprland.conf`.
|
||||||
|
See <https://wiki.hyprland.org> for more information.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
package = mkOption {
|
package = mkOption {
|
||||||
type = types.nullOr types.package;
|
type = types.path;
|
||||||
default = self.packages.${pkgs.system}.default;
|
default = defaultHyprlandPackage;
|
||||||
defaultText = literalExpression "<Hyprland flake>.packages.<system>.default";
|
defaultText = literalExpression ''
|
||||||
example = literalExpression "<Hyprland flake>.packages.<system>.default.override { }";
|
hyprland.packages.''${pkgs.stdenv.hostPlatform.system}.default.override {
|
||||||
description = ''
|
enableXWayland = config.programs.hyprland.xwayland.enable;
|
||||||
Hyprland package to use.
|
hidpiXWayland = config.programs.hyprland.xwayland.hidpi;
|
||||||
|
inherit (config.programs.hyprland) nvidiaPatches;
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
example = literalExpression "pkgs.hyprland";
|
||||||
|
description = mdDoc ''
|
||||||
|
The Hyprland package to use.
|
||||||
|
Setting this option will make {option}`programs.hyprland.xwayland` and
|
||||||
|
{option}`programs.hyprland.nvidiaPatches` not work.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
recommendedEnvironment = mkOption {
|
xwayland = {
|
||||||
type = types.bool;
|
enable = mkEnableOption (mdDoc "XWayland") // {default = true;};
|
||||||
default = true;
|
hidpi =
|
||||||
defaultText = literalExpression "true";
|
mkEnableOption null
|
||||||
example = literalExpression "false";
|
// {
|
||||||
description = ''
|
description = mdDoc ''
|
||||||
Whether to set the recommended environment variables.
|
Enable HiDPI XWayland, based on [XWayland MR 733](https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/733).
|
||||||
'';
|
See <https://wiki.hyprland.org/Nix/Options-Overrides/#xwayland-hidpi> for more info.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
nvidiaPatches = mkEnableOption (mdDoc "patching wlroots for better Nvidia support");
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
environment = {
|
environment = {
|
||||||
systemPackages = lib.optional (cfg.package != null) cfg.package;
|
systemPackages = [cfg.package];
|
||||||
|
|
||||||
sessionVariables = mkIf cfg.recommendedEnvironment {
|
sessionVariables = {
|
||||||
GDK_BACKEND = "wayland";
|
NIXOS_OZONE_WL = mkDefault "1";
|
||||||
_JAVA_AWT_WM_NONREPARENTING = "1";
|
|
||||||
NIXOS_OZONE_WL = "1";
|
|
||||||
XCURSOR_SIZE = "24";
|
|
||||||
XDG_SESSION_TYPE = "wayland";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
fonts.enableDefaultFonts = mkDefault true;
|
fonts.enableDefaultFonts = mkDefault true;
|
||||||
hardware.opengl.enable = mkDefault true;
|
hardware.opengl.enable = mkDefault true;
|
||||||
|
|
||||||
programs = {
|
programs = {
|
||||||
dconf.enable = mkDefault true;
|
dconf.enable = mkDefault true;
|
||||||
xwayland.enable = mkDefault true;
|
xwayland.enable = mkDefault true;
|
||||||
};
|
};
|
||||||
|
|
||||||
security.polkit.enable = true;
|
security.polkit.enable = true;
|
||||||
services.xserver.displayManager.sessionPackages = lib.optional (cfg.package != null) cfg.package;
|
|
||||||
|
services.xserver.displayManager.sessionPackages = [cfg.package];
|
||||||
|
|
||||||
xdg.portal = {
|
xdg.portal = {
|
||||||
enable = mkDefault true;
|
enable = mkDefault true;
|
||||||
extraPortals = [pkgs.xdg-desktop-portal-wlr];
|
extraPortals = lib.mkIf (cfg.package != null) [
|
||||||
|
(inputs.xdph.packages.${pkgs.stdenv.hostPlatform.system}.xdg-desktop-portal-hyprland.override {
|
||||||
|
hyprland-share-picker = inputs.xdph.packages.${pkgs.stdenv.hostPlatform.system}.hyprland-share-picker.override {
|
||||||
|
hyprland = cfg.package;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
97
nix/overlays.nix
Normal file
97
nix/overlays.nix
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
{
|
||||||
|
self,
|
||||||
|
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)
|
||||||
|
]);
|
||||||
|
in {
|
||||||
|
# Packages for variations of Hyprland, and its dependencies.
|
||||||
|
hyprland-packages = final: prev: {
|
||||||
|
hyprland = final.callPackage ./default.nix {
|
||||||
|
version =
|
||||||
|
props.version
|
||||||
|
+ "+date="
|
||||||
|
+ (mkDate (self.lastModifiedDate or "19700101"))
|
||||||
|
+ "_"
|
||||||
|
+ (self.shortRev or "dirty");
|
||||||
|
wlroots = final.wlroots-hyprland;
|
||||||
|
commit = self.rev or "";
|
||||||
|
inherit (final) udis86 hyprland-protocols;
|
||||||
|
};
|
||||||
|
|
||||||
|
hyprland-debug = final.hyprland.override {debug = true;};
|
||||||
|
hyprland-hidpi = final.hyprland.override {hidpiXWayland = true;};
|
||||||
|
hyprland-nvidia = final.hyprland.override {nvidiaPatches = true;};
|
||||||
|
hyprland-no-hidpi =
|
||||||
|
builtins.trace
|
||||||
|
"hyprland-no-hidpi was removed. Please use the default package."
|
||||||
|
final.hyprland;
|
||||||
|
|
||||||
|
udis86 = final.callPackage ./udis86.nix {};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Packages for extra software recommended for usage with Hyprland,
|
||||||
|
# including forked or patched packages for compatibility.
|
||||||
|
hyprland-extras = lib.mkJoinedOverlays [
|
||||||
|
# Include any inputs' specific overlays whose attributes should
|
||||||
|
# be re-exported by the Hyprland flake.
|
||||||
|
#
|
||||||
|
inputs.xdph.overlays.default
|
||||||
|
# Provides:
|
||||||
|
# - xdg-desktop-portal-hyprland
|
||||||
|
# - hyprland-share-picker
|
||||||
|
#
|
||||||
|
# Attributes for `hyprland-extras` defined by this flake can
|
||||||
|
# go in the oberlay below.
|
||||||
|
(final: prev: {
|
||||||
|
waybar-hyprland = prev.waybar.overrideAttrs (old: {
|
||||||
|
postPatch = ''
|
||||||
|
# use hyprctl to switch workspaces
|
||||||
|
sed -i 's/zext_workspace_handle_v1_activate(workspace_handle_);/const std::string command = "hyprctl dispatch workspace " + name_;\n\tsystem(command.c_str());/g' src/modules/wlr/workspace_manager.cpp
|
||||||
|
'';
|
||||||
|
mesonFlags = old.mesonFlags ++ ["-Dexperimental=true"];
|
||||||
|
});
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
# 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;
|
||||||
|
libdisplay-info = prev.libdisplay-info.overrideAttrs (old: {
|
||||||
|
version = "0.1.1+date=2023-03-02";
|
||||||
|
src = final.fetchFromGitLab {
|
||||||
|
domain = "gitlab.freedesktop.org";
|
||||||
|
owner = "emersion";
|
||||||
|
repo = old.pname;
|
||||||
|
rev = "147d6611a64a6ab04611b923e30efacaca6fc678";
|
||||||
|
sha256 = "sha256-/q79o13Zvu7x02SBGu0W5yQznQ+p7ltZ9L6cMW5t/o4=";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
libliftoff = prev.libliftoff.overrideAttrs (old: {
|
||||||
|
version = "0.5.0-dev";
|
||||||
|
src = final.fetchFromGitLab {
|
||||||
|
domain = "gitlab.freedesktop.org";
|
||||||
|
owner = "emersion";
|
||||||
|
repo = old.pname;
|
||||||
|
rev = "d98ae243280074b0ba44bff92215ae8d785658c0";
|
||||||
|
sha256 = "sha256-DjwlS8rXE7srs7A8+tHqXyUsFGtucYSeq6X0T/pVOc8=";
|
||||||
|
};
|
||||||
|
|
||||||
|
NIX_CFLAGS_COMPILE = toString ["-Wno-error=sign-conversion"];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
32
nix/udis86.nix
Normal file
32
nix/udis86.nix
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
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,19 +1,21 @@
|
|||||||
#!/usr/bin/env -S nix shell nixpkgs#gawk nixpkgs#git nixpkgs#moreutils nixpkgs#jq -c bash
|
#!/usr/bin/env -S nix shell nixpkgs#gawk nixpkgs#git nixpkgs#moreutils nixpkgs#jq nixpkgs#ripgrep -c bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
# get wlroots revision from submodule
|
# get wlroots revision from submodule
|
||||||
SUB_REV=$(git submodule status | awk '{ print substr($1,2)}')
|
SUB_REV=$(git submodule status | rg wlroots | awk '{ print substr($1,2)}')
|
||||||
# and from lockfile
|
# and from lockfile
|
||||||
CRT_REV=$(jq < flake.lock '.nodes.wlroots.locked.rev' -r)
|
CRT_REV=$(jq <flake.lock '.nodes.wlroots.locked.rev' -r)
|
||||||
|
|
||||||
if [ $SUB_REV != $CRT_REV ]; then
|
if [ "$SUB_REV" != "$CRT_REV" ]; then
|
||||||
# update nixpkgs to latest version
|
# update inputs to latest versions
|
||||||
nix flake lock --update-input nixpkgs
|
nix flake update
|
||||||
|
|
||||||
# update wlroots to submodule revision
|
# update wlroots to submodule revision
|
||||||
nix flake lock --override-input wlroots "gitlab:wlroots/wlroots/$SUB_REV?host=gitlab.freedesktop.org"
|
nix flake lock --override-input wlroots "gitlab:wlroots/wlroots/$SUB_REV?host=gitlab.freedesktop.org"
|
||||||
|
|
||||||
# remove "dirty" mark from lockfile
|
# remove "dirty" mark from lockfile
|
||||||
jq < flake.lock 'del(.nodes.wlroots.original.rev)' | sponge flake.lock
|
jq <flake.lock 'del(.nodes.wlroots.original.rev)' | sponge flake.lock
|
||||||
else
|
else
|
||||||
echo "wlroots is up to date!"
|
echo "wlroots is up to date!"
|
||||||
fi
|
fi
|
||||||
|
|||||||
164
nix/wlroots-hidpi.patch
Normal file
164
nix/wlroots-hidpi.patch
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h
|
||||||
|
index 3d540522..1c5a2e37 100644
|
||||||
|
--- a/include/xwayland/xwm.h
|
||||||
|
+++ b/include/xwayland/xwm.h
|
||||||
|
@@ -88,6 +88,7 @@ enum atom_name {
|
||||||
|
DND_ACTION_PRIVATE,
|
||||||
|
NET_CLIENT_LIST,
|
||||||
|
NET_CLIENT_LIST_STACKING,
|
||||||
|
+ XWAYLAND_GLOBAL_OUTPUT_SCALE,
|
||||||
|
ATOM_LAST // keep last
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -96,6 +97,7 @@ struct wlr_xwm {
|
||||||
|
struct wl_event_source *event_source;
|
||||||
|
struct wlr_seat *seat;
|
||||||
|
uint32_t ping_timeout;
|
||||||
|
+ uint32_t scale;
|
||||||
|
|
||||||
|
xcb_atom_t atoms[ATOM_LAST];
|
||||||
|
xcb_connection_t *xcb_conn;
|
||||||
|
diff --git a/xwayland/xwm.c b/xwayland/xwm.c
|
||||||
|
index 5f857f24..21584ebd 100644
|
||||||
|
--- a/xwayland/xwm.c
|
||||||
|
+++ b/xwayland/xwm.c
|
||||||
|
@@ -19,6 +19,14 @@
|
||||||
|
#include <xcb/xfixes.h>
|
||||||
|
#include "xwayland/xwm.h"
|
||||||
|
|
||||||
|
+static int32_t scale(struct wlr_xwm *xwm, uint32_t val) {
|
||||||
|
+ return val * xwm->scale;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int32_t unscale(struct wlr_xwm *xwm, uint32_t val) {
|
||||||
|
+ return (val + xwm->scale/2) / xwm->scale;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static const char *const atom_map[ATOM_LAST] = {
|
||||||
|
[WL_SURFACE_ID] = "WL_SURFACE_ID",
|
||||||
|
[WL_SURFACE_SERIAL] = "WL_SURFACE_SERIAL",
|
||||||
|
@@ -90,6 +98,7 @@ static const char *const atom_map[ATOM_LAST] = {
|
||||||
|
[DND_ACTION_PRIVATE] = "XdndActionPrivate",
|
||||||
|
[NET_CLIENT_LIST] = "_NET_CLIENT_LIST",
|
||||||
|
[NET_CLIENT_LIST_STACKING] = "_NET_CLIENT_LIST_STACKING",
|
||||||
|
+ [XWAYLAND_GLOBAL_OUTPUT_SCALE] = "_XWAYLAND_GLOBAL_OUTPUT_SCALE",
|
||||||
|
};
|
||||||
|
|
||||||
|
#define STARTUP_INFO_REMOVE_PREFIX "remove: ID="
|
||||||
|
@@ -965,8 +974,8 @@ static void xwm_handle_create_notify(struct wlr_xwm *xwm,
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- xwayland_surface_create(xwm, ev->window, ev->x, ev->y,
|
||||||
|
- ev->width, ev->height, ev->override_redirect);
|
||||||
|
+ xwayland_surface_create(xwm, ev->window, unscale(xwm, ev->x), unscale(xwm, ev->y),
|
||||||
|
+ unscale(xwm, ev->width), unscale(xwm, ev->height), ev->override_redirect);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xwm_handle_destroy_notify(struct wlr_xwm *xwm,
|
||||||
|
@@ -997,10 +1006,10 @@ static void xwm_handle_configure_request(struct wlr_xwm *xwm,
|
||||||
|
|
||||||
|
struct wlr_xwayland_surface_configure_event wlr_event = {
|
||||||
|
.surface = surface,
|
||||||
|
- .x = mask & XCB_CONFIG_WINDOW_X ? ev->x : surface->x,
|
||||||
|
- .y = mask & XCB_CONFIG_WINDOW_Y ? ev->y : surface->y,
|
||||||
|
- .width = mask & XCB_CONFIG_WINDOW_WIDTH ? ev->width : surface->width,
|
||||||
|
- .height = mask & XCB_CONFIG_WINDOW_HEIGHT ? ev->height : surface->height,
|
||||||
|
+ .x = mask & XCB_CONFIG_WINDOW_X ? unscale(xwm, ev->x) : surface->x,
|
||||||
|
+ .y = mask & XCB_CONFIG_WINDOW_Y ? unscale(xwm, ev->y) : surface->y,
|
||||||
|
+ .width = mask & XCB_CONFIG_WINDOW_WIDTH ? unscale(xwm, ev->width) : surface->width,
|
||||||
|
+ .height = mask & XCB_CONFIG_WINDOW_HEIGHT ? unscale(xwm, ev->height) : surface->height,
|
||||||
|
.mask = mask,
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -1015,14 +1024,14 @@ static void xwm_handle_configure_notify(struct wlr_xwm *xwm,
|
||||||
|
}
|
||||||
|
|
||||||
|
bool geometry_changed =
|
||||||
|
- (xsurface->x != ev->x || xsurface->y != ev->y ||
|
||||||
|
- xsurface->width != ev->width || xsurface->height != ev->height);
|
||||||
|
+ (xsurface->x != unscale(xwm, ev->x) || xsurface->y != unscale(xwm, ev->y) ||
|
||||||
|
+ xsurface->width != unscale(xwm, ev->width) || xsurface->height != unscale(xwm, ev->height));
|
||||||
|
|
||||||
|
if (geometry_changed) {
|
||||||
|
- xsurface->x = ev->x;
|
||||||
|
- xsurface->y = ev->y;
|
||||||
|
- xsurface->width = ev->width;
|
||||||
|
- xsurface->height = ev->height;
|
||||||
|
+ xsurface->x = unscale(xwm, ev->x);
|
||||||
|
+ xsurface->y = unscale(xwm, ev->y);
|
||||||
|
+ xsurface->width = unscale(xwm, ev->width);
|
||||||
|
+ xsurface->height = unscale(xwm, ev->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xsurface->override_redirect != ev->override_redirect) {
|
||||||
|
@@ -1133,6 +1142,20 @@ static void xwm_handle_property_notify(struct wlr_xwm *xwm,
|
||||||
|
xcb_property_notify_event_t *ev) {
|
||||||
|
struct wlr_xwayland_surface *xsurface = lookup_surface(xwm, ev->window);
|
||||||
|
if (xsurface == NULL) {
|
||||||
|
+ if (ev->atom == xwm->atoms[XWAYLAND_GLOBAL_OUTPUT_SCALE]) {
|
||||||
|
+ xcb_get_property_cookie_t cookie = xcb_get_property(xwm->xcb_conn, 0,
|
||||||
|
+ ev->window, ev->atom, XCB_ATOM_ANY, 0, 2048);
|
||||||
|
+ xcb_get_property_reply_t *reply = xcb_get_property_reply(xwm->xcb_conn,
|
||||||
|
+ cookie, NULL);
|
||||||
|
+ if (reply == NULL) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ if (reply->type == XCB_ATOM_CARDINAL) {
|
||||||
|
+ xwm->scale = *(uint32_t*)xcb_get_property_value(reply);
|
||||||
|
+ }
|
||||||
|
+ free(reply);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1760,16 +1783,17 @@ void wlr_xwayland_surface_configure(struct wlr_xwayland_surface *xsurface,
|
||||||
|
int old_w = xsurface->width;
|
||||||
|
int old_h = xsurface->height;
|
||||||
|
|
||||||
|
+ struct wlr_xwm *xwm = xsurface->xwm;
|
||||||
|
+
|
||||||
|
xsurface->x = x;
|
||||||
|
xsurface->y = y;
|
||||||
|
xsurface->width = width;
|
||||||
|
xsurface->height = height;
|
||||||
|
|
||||||
|
- struct wlr_xwm *xwm = xsurface->xwm;
|
||||||
|
uint32_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
|
||||||
|
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT |
|
||||||
|
XCB_CONFIG_WINDOW_BORDER_WIDTH;
|
||||||
|
- uint32_t values[] = {x, y, width, height, 0};
|
||||||
|
+ uint32_t values[] = {scale(xwm, x), scale(xwm, y), scale(xwm, width), scale(xwm, height), 0};
|
||||||
|
xcb_configure_window(xwm->xcb_conn, xsurface->window_id, mask, values);
|
||||||
|
|
||||||
|
// If the window size did not change, then we cannot rely on
|
||||||
|
@@ -1777,15 +1801,15 @@ void wlr_xwayland_surface_configure(struct wlr_xwayland_surface *xsurface,
|
||||||
|
// we are supposed to send a synthetic event. See ICCCM part
|
||||||
|
// 4.1.5. But we ignore override-redirect windows as ICCCM does
|
||||||
|
// not apply to them.
|
||||||
|
- if (width == old_w && height == old_h && !xsurface->override_redirect) {
|
||||||
|
+ if (scale(xwm, width) == scale(xwm, old_w) && scale(xwm, height) == scale(xwm, old_h) && !xsurface->override_redirect) {
|
||||||
|
xcb_configure_notify_event_t configure_notify = {
|
||||||
|
.response_type = XCB_CONFIGURE_NOTIFY,
|
||||||
|
.event = xsurface->window_id,
|
||||||
|
.window = xsurface->window_id,
|
||||||
|
- .x = x,
|
||||||
|
- .y = y,
|
||||||
|
- .width = width,
|
||||||
|
- .height = height,
|
||||||
|
+ .x = scale(xwm, x),
|
||||||
|
+ .y = scale(xwm, y),
|
||||||
|
+ .width = scale(xwm, width),
|
||||||
|
+ .height = scale(xwm, height),
|
||||||
|
};
|
||||||
|
|
||||||
|
xcb_send_event(xwm->xcb_conn, 0, xsurface->window_id,
|
||||||
|
@@ -2122,6 +2146,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
|
||||||
|
wl_list_init(&xwm->pending_startup_ids);
|
||||||
|
xwm->ping_timeout = 10000;
|
||||||
|
|
||||||
|
+ xwm->scale = 1;
|
||||||
|
xwm->xcb_conn = xcb_connect_to_fd(wm_fd, NULL);
|
||||||
|
|
||||||
|
int rc = xcb_connection_has_error(xwm->xcb_conn);
|
||||||
@@ -6,6 +6,9 @@
|
|||||||
xwayland,
|
xwayland,
|
||||||
fetchpatch,
|
fetchpatch,
|
||||||
lib,
|
lib,
|
||||||
|
hwdata,
|
||||||
|
libliftoff,
|
||||||
|
libdisplay-info,
|
||||||
hidpiXWayland ? true,
|
hidpiXWayland ? true,
|
||||||
enableXWayland ? true,
|
enableXWayland ? true,
|
||||||
nvidiaPatches ? false,
|
nvidiaPatches ? false,
|
||||||
@@ -32,15 +35,19 @@ assert (lib.assertMsg (hidpiXWayland -> enableXWayland) ''
|
|||||||
patches =
|
patches =
|
||||||
(old.patches or [])
|
(old.patches or [])
|
||||||
++ (lib.optionals (enableXWayland && hidpiXWayland) [
|
++ (lib.optionals (enableXWayland && hidpiXWayland) [
|
||||||
(fetchpatch {
|
# adapted from https://gitlab.freedesktop.org/lilydjwg/wlroots/-/commit/6c5ffcd1fee9e44780a6a8792f74ecfbe24a1ca7
|
||||||
url = "https://gitlab.freedesktop.org/lilydjwg/wlroots/-/commit/6c5ffcd1fee9e44780a6a8792f74ecfbe24a1ca7.diff";
|
./wlroots-hidpi.patch
|
||||||
sha256 = "sha256-Eo1pTa/PIiJsRZwIUnHGTIFFIedzODVf0ZeuXb0a3TQ=";
|
|
||||||
})
|
|
||||||
(fetchpatch {
|
(fetchpatch {
|
||||||
url = "https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/18595000f3a21502fd60bf213122859cc348f9af.diff";
|
url = "https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/18595000f3a21502fd60bf213122859cc348f9af.diff";
|
||||||
sha256 = "sha256-jvfkAMh3gzkfuoRhB4E9T5X1Hu62wgUjj4tZkJm0mrI=";
|
sha256 = "sha256-jvfkAMh3gzkfuoRhB4E9T5X1Hu62wgUjj4tZkJm0mrI=";
|
||||||
revert = true;
|
revert = true;
|
||||||
})
|
})
|
||||||
|
])
|
||||||
|
++ (lib.optionals nvidiaPatches [
|
||||||
|
(fetchpatch {
|
||||||
|
url = "https://aur.archlinux.org/cgit/aur.git/plain/0001-nvidia-format-workaround.patch?h=hyprland-nvidia-screenshare-git";
|
||||||
|
sha256 = "A9f1p5EW++mGCaNq8w7ZJfeWmvTfUm4iO+1KDcnqYX8=";
|
||||||
|
})
|
||||||
]);
|
]);
|
||||||
postPatch =
|
postPatch =
|
||||||
(old.postPatch or "")
|
(old.postPatch or "")
|
||||||
@@ -51,6 +58,11 @@ assert (lib.assertMsg (hidpiXWayland -> enableXWayland) ''
|
|||||||
''
|
''
|
||||||
else ""
|
else ""
|
||||||
);
|
);
|
||||||
|
buildInputs = old.buildInputs ++ [hwdata libliftoff libdisplay-info];
|
||||||
|
|
||||||
|
NIX_CFLAGS_COMPILE = toString [
|
||||||
|
"-Wno-error=maybe-uninitialized"
|
||||||
|
];
|
||||||
}))
|
}))
|
||||||
.override {
|
.override {
|
||||||
xwayland = xwayland.overrideAttrs (old: {
|
xwayland = xwayland.overrideAttrs (old: {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c
|
diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c
|
||||||
index c4457cc2a61b2103b47f996b51dbbe9eb87bd715..4a33e1f33e73c35c1691564ef4852e7501b02245 100644
|
index e3c1aaa50..eba29b5ba 100644
|
||||||
--- a/hw/xwayland/xwayland-cursor.c
|
--- a/hw/xwayland/xwayland-cursor.c
|
||||||
+++ b/hw/xwayland/xwayland-cursor.c
|
+++ b/hw/xwayland/xwayland-cursor.c
|
||||||
@@ -171,6 +171,8 @@ xwl_cursor_attach_pixmap(struct xwl_seat *xwl_seat,
|
@@ -164,6 +164,8 @@ xwl_cursor_attach_pixmap(struct xwl_seat *xwl_seat,
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_surface_attach(xwl_cursor->surface, buffer, 0, 0);
|
wl_surface_attach(xwl_cursor->surface, buffer, 0, 0);
|
||||||
@@ -11,7 +11,7 @@ index c4457cc2a61b2103b47f996b51dbbe9eb87bd715..4a33e1f33e73c35c1691564ef4852e75
|
|||||||
xwl_surface_damage(xwl_seat->xwl_screen, xwl_cursor->surface, 0, 0,
|
xwl_surface_damage(xwl_seat->xwl_screen, xwl_cursor->surface, 0, 0,
|
||||||
xwl_seat->x_cursor->bits->width,
|
xwl_seat->x_cursor->bits->width,
|
||||||
xwl_seat->x_cursor->bits->height);
|
xwl_seat->x_cursor->bits->height);
|
||||||
@@ -190,6 +192,7 @@ xwl_cursor_attach_pixmap(struct xwl_seat *xwl_seat,
|
@@ -195,6 +197,7 @@ xwl_cursor_clear_frame_cb(struct xwl_cursor *xwl_cursor)
|
||||||
void
|
void
|
||||||
xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
|
xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
|
||||||
{
|
{
|
||||||
@@ -19,7 +19,7 @@ index c4457cc2a61b2103b47f996b51dbbe9eb87bd715..4a33e1f33e73c35c1691564ef4852e75
|
|||||||
struct xwl_cursor *xwl_cursor = &xwl_seat->cursor;
|
struct xwl_cursor *xwl_cursor = &xwl_seat->cursor;
|
||||||
PixmapPtr pixmap;
|
PixmapPtr pixmap;
|
||||||
CursorPtr cursor;
|
CursorPtr cursor;
|
||||||
@@ -220,8 +223,8 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
|
@@ -225,8 +228,8 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
|
||||||
wl_pointer_set_cursor(xwl_seat->wl_pointer,
|
wl_pointer_set_cursor(xwl_seat->wl_pointer,
|
||||||
xwl_seat->pointer_enter_serial,
|
xwl_seat->pointer_enter_serial,
|
||||||
xwl_cursor->surface,
|
xwl_cursor->surface,
|
||||||
@@ -30,7 +30,7 @@ index c4457cc2a61b2103b47f996b51dbbe9eb87bd715..4a33e1f33e73c35c1691564ef4852e75
|
|||||||
|
|
||||||
xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap);
|
xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap);
|
||||||
}
|
}
|
||||||
@@ -230,6 +233,7 @@ void
|
@@ -235,6 +238,7 @@ void
|
||||||
xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
|
xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
|
||||||
{
|
{
|
||||||
struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
|
struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
|
||||||
@@ -38,24 +38,23 @@ index c4457cc2a61b2103b47f996b51dbbe9eb87bd715..4a33e1f33e73c35c1691564ef4852e75
|
|||||||
struct xwl_cursor *xwl_cursor = &xwl_tablet_tool->cursor;
|
struct xwl_cursor *xwl_cursor = &xwl_tablet_tool->cursor;
|
||||||
PixmapPtr pixmap;
|
PixmapPtr pixmap;
|
||||||
CursorPtr cursor;
|
CursorPtr cursor;
|
||||||
@@ -258,9 +262,9 @@ xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
|
@@ -263,8 +267,9 @@ xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
|
||||||
zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool,
|
zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool,
|
||||||
xwl_tablet_tool->proximity_in_serial,
|
xwl_tablet_tool->proximity_in_serial,
|
||||||
xwl_cursor->surface,
|
xwl_cursor->surface,
|
||||||
- xwl_seat->x_cursor->bits->xhot,
|
- xwl_seat->x_cursor->bits->xhot,
|
||||||
- xwl_seat->x_cursor->bits->yhot);
|
- xwl_seat->x_cursor->bits->yhot);
|
||||||
-
|
|
||||||
+ xwl_scale_to(xwl_screen, xwl_seat->x_cursor->bits->xhot),
|
+ xwl_scale_to(xwl_screen, xwl_seat->x_cursor->bits->xhot),
|
||||||
+ xwl_scale_to(xwl_screen, xwl_seat->x_cursor->bits->yhot));
|
+ xwl_scale_to(xwl_screen, xwl_seat->x_cursor->bits->yhot));
|
||||||
+ wl_surface_set_buffer_scale(xwl_cursor->surface, xwl_screen->global_output_scale);
|
+ wl_surface_set_buffer_scale(xwl_cursor->surface, xwl_screen->global_output_scale);
|
||||||
|
|
||||||
xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap);
|
xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
|
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
|
||||||
index 26b3630c73b62514fe3ba7824371f79868e953f3..55cd8d466a55db03948abe93ffa03bf129b5e17a 100644
|
index 6e0600e4e..4a22ebff0 100644
|
||||||
--- a/hw/xwayland/xwayland-input.c
|
--- a/hw/xwayland/xwayland-input.c
|
||||||
+++ b/hw/xwayland/xwayland-input.c
|
+++ b/hw/xwayland/xwayland-input.c
|
||||||
@@ -412,8 +412,8 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer,
|
@@ -507,8 +507,8 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer,
|
||||||
DeviceIntPtr dev = get_pointer_device(xwl_seat);
|
DeviceIntPtr dev = get_pointer_device(xwl_seat);
|
||||||
DeviceIntPtr master;
|
DeviceIntPtr master;
|
||||||
int i;
|
int i;
|
||||||
@@ -66,7 +65,7 @@ index 26b3630c73b62514fe3ba7824371f79868e953f3..55cd8d466a55db03948abe93ffa03bf1
|
|||||||
int dx, dy;
|
int dx, dy;
|
||||||
ScreenPtr pScreen = xwl_seat->xwl_screen->screen;
|
ScreenPtr pScreen = xwl_seat->xwl_screen->screen;
|
||||||
ValuatorMask mask;
|
ValuatorMask mask;
|
||||||
@@ -592,13 +592,14 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer,
|
@@ -731,13 +731,14 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer,
|
||||||
uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
|
uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
|
||||||
{
|
{
|
||||||
struct xwl_seat *xwl_seat = data;
|
struct xwl_seat *xwl_seat = data;
|
||||||
@@ -83,17 +82,7 @@ index 26b3630c73b62514fe3ba7824371f79868e953f3..55cd8d466a55db03948abe93ffa03bf1
|
|||||||
|
|
||||||
if (wl_proxy_get_version((struct wl_proxy *) xwl_seat->wl_pointer) < 5)
|
if (wl_proxy_get_version((struct wl_proxy *) xwl_seat->wl_pointer) < 5)
|
||||||
dispatch_pointer_motion_event(xwl_seat);
|
dispatch_pointer_motion_event(xwl_seat);
|
||||||
@@ -672,7 +673,8 @@ pointer_handle_axis(void *data, struct wl_pointer *pointer,
|
@@ -887,12 +888,13 @@ relative_pointer_handle_relative_motion(void *data,
|
||||||
xorg_list_del(&pending->l);
|
|
||||||
free(pending);
|
|
||||||
} else {
|
|
||||||
- valuator_mask_set_double(&mask, index, wl_fixed_to_double(value) / divisor);
|
|
||||||
+ double scaled_value = wl_fixed_to_double(value);
|
|
||||||
+ valuator_mask_set_double(&mask, index, scaled_value / divisor);
|
|
||||||
}
|
|
||||||
|
|
||||||
QueuePointerEvents(get_pointer_device(xwl_seat),
|
|
||||||
@@ -740,12 +742,13 @@ relative_pointer_handle_relative_motion(void *data,
|
|
||||||
wl_fixed_t dy_unaccelf)
|
wl_fixed_t dy_unaccelf)
|
||||||
{
|
{
|
||||||
struct xwl_seat *xwl_seat = data;
|
struct xwl_seat *xwl_seat = data;
|
||||||
@@ -111,7 +100,7 @@ index 26b3630c73b62514fe3ba7824371f79868e953f3..55cd8d466a55db03948abe93ffa03bf1
|
|||||||
|
|
||||||
if (!xwl_seat->focus_window)
|
if (!xwl_seat->focus_window)
|
||||||
return;
|
return;
|
||||||
@@ -1057,8 +1060,8 @@ touch_handle_down(void *data, struct wl_touch *wl_touch,
|
@@ -1382,8 +1384,8 @@ touch_handle_down(void *data, struct wl_touch *wl_touch,
|
||||||
|
|
||||||
xwl_touch->window = wl_surface_get_user_data(surface);
|
xwl_touch->window = wl_surface_get_user_data(surface);
|
||||||
xwl_touch->id = id;
|
xwl_touch->id = id;
|
||||||
@@ -122,18 +111,18 @@ index 26b3630c73b62514fe3ba7824371f79868e953f3..55cd8d466a55db03948abe93ffa03bf1
|
|||||||
xorg_list_add(&xwl_touch->link_touch, &xwl_seat->touches);
|
xorg_list_add(&xwl_touch->link_touch, &xwl_seat->touches);
|
||||||
|
|
||||||
xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchBegin);
|
xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchBegin);
|
||||||
@@ -1094,8 +1097,8 @@ touch_handle_motion(void *data, struct wl_touch *wl_touch,
|
@@ -1419,8 +1421,8 @@ touch_handle_motion(void *data, struct wl_touch *wl_touch,
|
||||||
if (!xwl_touch)
|
if (!xwl_touch)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
- xwl_touch->x = wl_fixed_to_int(sx_w);
|
- xwl_touch->x = wl_fixed_to_int(sx_w);
|
||||||
- xwl_touch->y = wl_fixed_to_int(sy_w);
|
- xwl_touch->y = wl_fixed_to_int(sy_w);
|
||||||
+ xwl_touch->x = wl_fixed_to_int(sx_w) * xwl_seat->xwl_screen->global_output_scale;;
|
+ xwl_touch->x = wl_fixed_to_int(sx_w) * xwl_seat->xwl_screen->global_output_scale;
|
||||||
+ xwl_touch->y = wl_fixed_to_int(sy_w) * xwl_seat->xwl_screen->global_output_scale;;
|
+ xwl_touch->y = wl_fixed_to_int(sy_w) * xwl_seat->xwl_screen->global_output_scale;
|
||||||
xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchUpdate);
|
xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1726,8 +1729,8 @@ tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *tool,
|
@@ -2110,8 +2112,8 @@ tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *tool,
|
||||||
struct xwl_tablet_tool *xwl_tablet_tool = data;
|
struct xwl_tablet_tool *xwl_tablet_tool = data;
|
||||||
struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
|
struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
|
||||||
int32_t dx, dy;
|
int32_t dx, dy;
|
||||||
@@ -144,7 +133,7 @@ index 26b3630c73b62514fe3ba7824371f79868e953f3..55cd8d466a55db03948abe93ffa03bf1
|
|||||||
|
|
||||||
if (!xwl_seat->tablet_focus_window)
|
if (!xwl_seat->tablet_focus_window)
|
||||||
return;
|
return;
|
||||||
@@ -2714,6 +2717,7 @@ xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_em
|
@@ -3152,6 +3154,7 @@ xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_em
|
||||||
int x,
|
int x,
|
||||||
int y)
|
int y)
|
||||||
{
|
{
|
||||||
@@ -152,7 +141,7 @@ index 26b3630c73b62514fe3ba7824371f79868e953f3..55cd8d466a55db03948abe93ffa03bf1
|
|||||||
struct zwp_locked_pointer_v1 *locked_pointer =
|
struct zwp_locked_pointer_v1 *locked_pointer =
|
||||||
warp_emulator->locked_pointer;
|
warp_emulator->locked_pointer;
|
||||||
WindowPtr window;
|
WindowPtr window;
|
||||||
@@ -2725,6 +2729,7 @@ xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_em
|
@@ -3163,6 +3166,7 @@ xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_em
|
||||||
if (!warp_emulator->xwl_seat->focus_window)
|
if (!warp_emulator->xwl_seat->focus_window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -160,7 +149,7 @@ index 26b3630c73b62514fe3ba7824371f79868e953f3..55cd8d466a55db03948abe93ffa03bf1
|
|||||||
window = warp_emulator->xwl_seat->focus_window->window;
|
window = warp_emulator->xwl_seat->focus_window->window;
|
||||||
if (x >= window->drawable.x ||
|
if (x >= window->drawable.x ||
|
||||||
y >= window->drawable.y ||
|
y >= window->drawable.y ||
|
||||||
@@ -2733,8 +2738,8 @@ xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_em
|
@@ -3171,8 +3175,8 @@ xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_em
|
||||||
sx = x - window->drawable.x;
|
sx = x - window->drawable.x;
|
||||||
sy = y - window->drawable.y;
|
sy = y - window->drawable.y;
|
||||||
zwp_locked_pointer_v1_set_cursor_position_hint(locked_pointer,
|
zwp_locked_pointer_v1_set_cursor_position_hint(locked_pointer,
|
||||||
@@ -172,21 +161,21 @@ index 26b3630c73b62514fe3ba7824371f79868e953f3..55cd8d466a55db03948abe93ffa03bf1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
|
diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
|
||||||
index ef705bc01bf8c2d2f170cda9ba21ed8293f50559..b8f6cd51bd240ed5e16271eb4749db18868bea7b 100644
|
index 661e1828d..6c60aba34 100644
|
||||||
--- a/hw/xwayland/xwayland-output.c
|
--- a/hw/xwayland/xwayland-output.c
|
||||||
+++ b/hw/xwayland/xwayland-output.c
|
+++ b/hw/xwayland/xwayland-output.c
|
||||||
@@ -191,6 +191,9 @@ update_screen_size(struct xwl_output *xwl_output, int width, int height)
|
@@ -186,6 +186,9 @@ update_backing_pixmaps(struct xwl_screen *xwl_screen, int width, int height)
|
||||||
|
static void
|
||||||
|
update_screen_size(struct xwl_screen *xwl_screen, int width, int height)
|
||||||
{
|
{
|
||||||
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
|
|
||||||
|
|
||||||
+ width *= xwl_screen->global_output_scale;
|
+ width *= xwl_screen->global_output_scale;
|
||||||
+ height *= xwl_screen->global_output_scale;
|
+ height *= xwl_screen->global_output_scale;
|
||||||
+
|
+
|
||||||
if (xwl_screen->root_clip_mode == ROOT_CLIP_FULL)
|
xwl_screen->width = width;
|
||||||
SetRootClip(xwl_screen->screen, ROOT_CLIP_NONE);
|
xwl_screen->height = height;
|
||||||
|
|
||||||
@@ -497,14 +500,15 @@ xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client,
|
@@ -597,14 +600,15 @@ xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client,
|
||||||
xwl_output_set_randr_emu_props(xwl_output->xwl_screen, client);
|
new_emulated_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
-static void
|
-static void
|
||||||
@@ -203,20 +192,20 @@ index ef705bc01bf8c2d2f170cda9ba21ed8293f50559..b8f6cd51bd240ed5e16271eb4749db18
|
|||||||
|
|
||||||
/* Clear out the "done" received flags */
|
/* Clear out the "done" received flags */
|
||||||
xwl_output->wl_output_done = FALSE;
|
xwl_output->wl_output_done = FALSE;
|
||||||
@@ -523,10 +527,10 @@ apply_output_change(struct xwl_output *xwl_output)
|
@@ -623,10 +627,10 @@ apply_output_change(struct xwl_output *xwl_output)
|
||||||
}
|
}
|
||||||
|
if (xwl_output->randr_output) {
|
||||||
/* Build a fresh modes array using the current refresh rate */
|
/* Build a fresh modes array using the current refresh rate */
|
||||||
- randr_modes = output_get_rr_modes(xwl_output, mode_width, mode_height, &count);
|
- randr_modes = output_get_rr_modes(xwl_output, mode_width, mode_height, &count);
|
||||||
+ randr_modes = output_get_rr_modes(xwl_output, mode_width * scale, mode_height * scale, &count);
|
+ randr_modes = output_get_rr_modes(xwl_output, mode_width * scale, mode_height * scale, &count);
|
||||||
RROutputSetModes(xwl_output->randr_output, randr_modes, count, 1);
|
RROutputSetModes(xwl_output->randr_output, randr_modes, count, 1);
|
||||||
RRCrtcNotify(xwl_output->randr_crtc, randr_modes[0],
|
RRCrtcNotify(xwl_output->randr_crtc, randr_modes[0],
|
||||||
- xwl_output->x, xwl_output->y,
|
- xwl_output->x, xwl_output->y,
|
||||||
+ xwl_output->x * scale, xwl_output->y * scale,
|
+ xwl_output->x * scale, xwl_output->y * scale,
|
||||||
xwl_output->rotation, NULL, 1, &xwl_output->randr_output);
|
xwl_output->rotation, NULL, 1, &xwl_output->randr_output);
|
||||||
/* RROutputSetModes takes ownership of the passed in modes, so we only
|
/* RROutputSetModes takes ownership of the passed in modes, so we only
|
||||||
* have to free the pointer array.
|
* have to free the pointer array.
|
||||||
@@ -567,7 +571,7 @@ output_handle_done(void *data, struct wl_output *wl_output)
|
@@ -686,7 +690,7 @@ output_handle_done(void *data, struct wl_output *wl_output)
|
||||||
*/
|
*/
|
||||||
if (xwl_output->xdg_output_done || !xwl_output->xdg_output ||
|
if (xwl_output->xdg_output_done || !xwl_output->xdg_output ||
|
||||||
zxdg_output_v1_get_version(xwl_output->xdg_output) >= 3)
|
zxdg_output_v1_get_version(xwl_output->xdg_output) >= 3)
|
||||||
@@ -225,7 +214,7 @@ index ef705bc01bf8c2d2f170cda9ba21ed8293f50559..b8f6cd51bd240ed5e16271eb4749db18
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -610,7 +614,7 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
|
@@ -746,7 +750,7 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
|
||||||
xwl_output->xdg_output_done = TRUE;
|
xwl_output->xdg_output_done = TRUE;
|
||||||
if (xwl_output->wl_output_done &&
|
if (xwl_output->wl_output_done &&
|
||||||
zxdg_output_v1_get_version(xdg_output) < 3)
|
zxdg_output_v1_get_version(xdg_output) < 3)
|
||||||
@@ -234,17 +223,17 @@ index ef705bc01bf8c2d2f170cda9ba21ed8293f50559..b8f6cd51bd240ed5e16271eb4749db18
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -678,6 +682,8 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
|
@@ -857,6 +861,8 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id,
|
||||||
RROutputSetConnection(xwl_output->randr_output, RR_Connected);
|
RRCrtcGammaSetSize(xwl_output->randr_crtc, 256);
|
||||||
RRTellChanged(xwl_screen->screen);
|
RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1);
|
||||||
|
RROutputSetConnection(xwl_output->randr_output, RR_Connected);
|
||||||
+ xwl_output->scale = 1;
|
|
||||||
+
|
+
|
||||||
|
+ xwl_output->scale = 1;
|
||||||
|
}
|
||||||
/* We want the output to be in the list as soon as created so we can
|
/* We want the output to be in the list as soon as created so we can
|
||||||
* use it when binding to the xdg-output protocol...
|
* use it when binding to the xdg-output protocol...
|
||||||
*/
|
|
||||||
diff --git a/hw/xwayland/xwayland-output.h b/hw/xwayland/xwayland-output.h
|
diff --git a/hw/xwayland/xwayland-output.h b/hw/xwayland/xwayland-output.h
|
||||||
index 02b9831083e82a33d85d4404e39d00f06f6c56fd..ec089757f44178dcd7f9c48907f790ce1b2a2729 100644
|
index a95288e4f..46d1ead2a 100644
|
||||||
--- a/hw/xwayland/xwayland-output.h
|
--- a/hw/xwayland/xwayland-output.h
|
||||||
+++ b/hw/xwayland/xwayland-output.h
|
+++ b/hw/xwayland/xwayland-output.h
|
||||||
@@ -53,7 +53,7 @@ struct xwl_output {
|
@@ -53,7 +53,7 @@ struct xwl_output {
|
||||||
@@ -256,7 +245,7 @@ index 02b9831083e82a33d85d4404e39d00f06f6c56fd..ec089757f44178dcd7f9c48907f790ce
|
|||||||
Rotation rotation;
|
Rotation rotation;
|
||||||
Bool wl_output_done;
|
Bool wl_output_done;
|
||||||
Bool xdg_output_done;
|
Bool xdg_output_done;
|
||||||
@@ -100,6 +100,8 @@ void xwl_output_set_emulated_mode(struct xwl_output *xwl_output,
|
@@ -102,6 +102,8 @@ void xwl_output_set_emulated_mode(struct xwl_output *xwl_output,
|
||||||
void xwl_output_set_window_randr_emu_props(struct xwl_screen *xwl_screen,
|
void xwl_output_set_window_randr_emu_props(struct xwl_screen *xwl_screen,
|
||||||
WindowPtr window);
|
WindowPtr window);
|
||||||
|
|
||||||
@@ -266,20 +255,20 @@ index 02b9831083e82a33d85d4404e39d00f06f6c56fd..ec089757f44178dcd7f9c48907f790ce
|
|||||||
|
|
||||||
#endif /* XWAYLAND_OUTPUT_H */
|
#endif /* XWAYLAND_OUTPUT_H */
|
||||||
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
|
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
|
||||||
index c9cf8c2f569a319034e0789e7587414e50237065..5be0c208ca46b1a53a136885fdc8ab44251fe7ff 100644
|
index 189e7cfd6..555434031 100644
|
||||||
--- a/hw/xwayland/xwayland-present.c
|
--- a/hw/xwayland/xwayland-present.c
|
||||||
+++ b/hw/xwayland/xwayland-present.c
|
+++ b/hw/xwayland/xwayland-present.c
|
||||||
@@ -680,6 +680,8 @@ xwl_present_flip(WindowPtr present_window,
|
@@ -764,6 +764,8 @@ xwl_present_flip(WindowPtr present_window,
|
||||||
|
|
||||||
/* We can flip directly to the main surface (full screen window without clips) */
|
/* We can flip directly to the main surface (full screen window without clips) */
|
||||||
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
|
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
|
||||||
+ wl_surface_set_buffer_scale(xwl_window->surface,
|
+ wl_surface_set_buffer_scale(xwl_window->surface,
|
||||||
+ xwl_window->xwl_screen->global_output_scale);
|
+ xwl_window->xwl_screen->global_output_scale);
|
||||||
|
|
||||||
if (!xwl_window->frame_callback)
|
if (xorg_list_is_empty(&xwl_present_window->frame_callback_list)) {
|
||||||
xwl_window_create_frame_callback(xwl_window);
|
xorg_list_add(&xwl_present_window->frame_callback_list,
|
||||||
diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c
|
diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c
|
||||||
index bb18e5c94fbc7134c801e4e1979e8184079d352e..4ec2de7d123dd36315df07a1e95b1f417925f0f8 100644
|
index 46ab4fed7..b2d7022e6 100644
|
||||||
--- a/hw/xwayland/xwayland-screen.c
|
--- a/hw/xwayland/xwayland-screen.c
|
||||||
+++ b/hw/xwayland/xwayland-screen.c
|
+++ b/hw/xwayland/xwayland-screen.c
|
||||||
@@ -51,6 +51,7 @@
|
@@ -51,6 +51,7 @@
|
||||||
@@ -290,7 +279,7 @@ index bb18e5c94fbc7134c801e4e1979e8184079d352e..4ec2de7d123dd36315df07a1e95b1f41
|
|||||||
|
|
||||||
#ifdef MITSHM
|
#ifdef MITSHM
|
||||||
#include "shmint.h"
|
#include "shmint.h"
|
||||||
@@ -110,6 +111,12 @@ xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen)
|
@@ -111,6 +112,12 @@ xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen)
|
||||||
return xwl_screen->rootless && xwl_screen_has_viewport_support(xwl_screen);
|
return xwl_screen->rootless && xwl_screen_has_viewport_support(xwl_screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,7 +292,7 @@ index bb18e5c94fbc7134c801e4e1979e8184079d352e..4ec2de7d123dd36315df07a1e95b1f41
|
|||||||
/* Return the output @ 0x0, falling back to the first output in the list */
|
/* Return the output @ 0x0, falling back to the first output in the list */
|
||||||
struct xwl_output *
|
struct xwl_output *
|
||||||
xwl_screen_get_first_output(struct xwl_screen *xwl_screen)
|
xwl_screen_get_first_output(struct xwl_screen *xwl_screen)
|
||||||
@@ -127,6 +134,37 @@ xwl_screen_get_first_output(struct xwl_screen *xwl_screen)
|
@@ -128,6 +135,38 @@ xwl_screen_get_first_output(struct xwl_screen *xwl_screen)
|
||||||
return xorg_list_first_entry(&xwl_screen->output_list, struct xwl_output, link);
|
return xorg_list_first_entry(&xwl_screen->output_list, struct xwl_output, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,10 +327,11 @@ index bb18e5c94fbc7134c801e4e1979e8184079d352e..4ec2de7d123dd36315df07a1e95b1f41
|
|||||||
+ }
|
+ }
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
static void
|
+
|
||||||
xwl_property_callback(CallbackListPtr *pcbl, void *closure,
|
struct xwl_output *
|
||||||
void *calldata)
|
xwl_screen_get_fixed_or_first_output(struct xwl_screen *xwl_screen)
|
||||||
@@ -134,19 +172,24 @@ xwl_property_callback(CallbackListPtr *pcbl, void *closure,
|
{
|
||||||
|
@@ -144,19 +183,24 @@ xwl_property_callback(CallbackListPtr *pcbl, void *closure,
|
||||||
ScreenPtr screen = closure;
|
ScreenPtr screen = closure;
|
||||||
PropertyStateRec *rec = calldata;
|
PropertyStateRec *rec = calldata;
|
||||||
struct xwl_screen *xwl_screen;
|
struct xwl_screen *xwl_screen;
|
||||||
@@ -357,6 +347,7 @@ index bb18e5c94fbc7134c801e4e1979e8184079d352e..4ec2de7d123dd36315df07a1e95b1f41
|
|||||||
xwl_screen = xwl_screen_get(screen);
|
xwl_screen = xwl_screen_get(screen);
|
||||||
|
|
||||||
- if (rec->prop->propertyName == xwl_screen->allow_commits_prop)
|
- if (rec->prop->propertyName == xwl_screen->allow_commits_prop)
|
||||||
|
- xwl_window_update_property(xwl_window, rec);
|
||||||
+ if (rec->prop->propertyName == xwl_screen->allow_commits_prop) {
|
+ if (rec->prop->propertyName == xwl_screen->allow_commits_prop) {
|
||||||
+ struct xwl_window *xwl_window;
|
+ struct xwl_window *xwl_window;
|
||||||
+
|
+
|
||||||
@@ -364,15 +355,15 @@ index bb18e5c94fbc7134c801e4e1979e8184079d352e..4ec2de7d123dd36315df07a1e95b1f41
|
|||||||
+ if (!xwl_window)
|
+ if (!xwl_window)
|
||||||
+ return;
|
+ return;
|
||||||
+
|
+
|
||||||
xwl_window_update_property(xwl_window, rec);
|
+ xwl_window_update_property(xwl_window, rec);
|
||||||
+ }
|
+ }
|
||||||
+ else if (rec->prop->propertyName == xwl_screen->global_output_scale_prop) {
|
+ else if (rec->prop->propertyName == xwl_screen->global_output_scale_prop) {
|
||||||
+ xwl_screen_update_property(xwl_screen, rec);
|
+ xwl_screen_update_property(xwl_screen, rec);
|
||||||
+ }
|
+ }
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool
|
static void
|
||||||
@@ -521,8 +564,14 @@ void xwl_surface_damage(struct xwl_screen *xwl_screen,
|
@@ -638,8 +682,14 @@ void xwl_surface_damage(struct xwl_screen *xwl_screen,
|
||||||
{
|
{
|
||||||
if (wl_surface_get_version(surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)
|
if (wl_surface_get_version(surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)
|
||||||
wl_surface_damage_buffer(surface, x, y, width, height);
|
wl_surface_damage_buffer(surface, x, y, width, height);
|
||||||
@@ -388,7 +379,7 @@ index bb18e5c94fbc7134c801e4e1979e8184079d352e..4ec2de7d123dd36315df07a1e95b1f41
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -538,10 +587,34 @@ xwl_screen_roundtrip(struct xwl_screen *xwl_screen)
|
@@ -655,6 +705,30 @@ xwl_screen_roundtrip(struct xwl_screen *xwl_screen)
|
||||||
xwl_give_up("could not connect to wayland server\n");
|
xwl_give_up("could not connect to wayland server\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,7 +406,11 @@ index bb18e5c94fbc7134c801e4e1979e8184079d352e..4ec2de7d123dd36315df07a1e95b1f41
|
|||||||
+ }
|
+ }
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
Bool
|
+
|
||||||
|
static int
|
||||||
|
xwl_server_grab(ClientPtr client)
|
||||||
|
{
|
||||||
|
@@ -712,6 +786,7 @@ Bool
|
||||||
xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
||||||
{
|
{
|
||||||
static const char allow_commits[] = "_XWAYLAND_ALLOW_COMMITS";
|
static const char allow_commits[] = "_XWAYLAND_ALLOW_COMMITS";
|
||||||
@@ -423,7 +418,7 @@ index bb18e5c94fbc7134c801e4e1979e8184079d352e..4ec2de7d123dd36315df07a1e95b1f41
|
|||||||
struct xwl_screen *xwl_screen;
|
struct xwl_screen *xwl_screen;
|
||||||
Pixel red_mask, blue_mask, green_mask;
|
Pixel red_mask, blue_mask, green_mask;
|
||||||
int ret, bpc, green_bpc, i;
|
int ret, bpc, green_bpc, i;
|
||||||
@@ -573,6 +646,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
@@ -746,6 +821,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
||||||
#ifdef XWL_HAS_GLAMOR
|
#ifdef XWL_HAS_GLAMOR
|
||||||
xwl_screen->glamor = 1;
|
xwl_screen->glamor = 1;
|
||||||
#endif
|
#endif
|
||||||
@@ -431,7 +426,7 @@ index bb18e5c94fbc7134c801e4e1979e8184079d352e..4ec2de7d123dd36315df07a1e95b1f41
|
|||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
if (strcmp(argv[i], "-rootless") == 0) {
|
if (strcmp(argv[i], "-rootless") == 0) {
|
||||||
@@ -743,6 +817,12 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
@@ -988,6 +1064,13 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
||||||
if (xwl_screen->allow_commits_prop == BAD_RESOURCE)
|
if (xwl_screen->allow_commits_prop == BAD_RESOURCE)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@@ -440,24 +435,24 @@ index bb18e5c94fbc7134c801e4e1979e8184079d352e..4ec2de7d123dd36315df07a1e95b1f41
|
|||||||
+ TRUE);
|
+ TRUE);
|
||||||
+ if (xwl_screen->global_output_scale_prop == BAD_RESOURCE)
|
+ if (xwl_screen->global_output_scale_prop == BAD_RESOURCE)
|
||||||
+ return FALSE;
|
+ return FALSE;
|
||||||
|
+
|
||||||
+
|
+
|
||||||
AddCallback(&PropertyStateCallback, xwl_property_callback, pScreen);
|
AddCallback(&PropertyStateCallback, xwl_property_callback, pScreen);
|
||||||
|
AddCallback(&RootWindowFinalizeCallback, xwl_root_window_finalized_callback, pScreen);
|
||||||
|
|
||||||
xwl_screen_roundtrip(xwl_screen);
|
|
||||||
diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h
|
diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h
|
||||||
index b965dddd7f964b1d100bbb9d10da1c35ab39810e..7446829d098fbe235e605084a016daff1a8eaea2 100644
|
index fadd0526e..2ce6ce5ab 100644
|
||||||
--- a/hw/xwayland/xwayland-screen.h
|
--- a/hw/xwayland/xwayland-screen.h
|
||||||
+++ b/hw/xwayland/xwayland-screen.h
|
+++ b/hw/xwayland/xwayland-screen.h
|
||||||
@@ -72,6 +72,8 @@ struct xwl_screen {
|
@@ -87,6 +87,7 @@ struct xwl_screen {
|
||||||
struct xorg_list damage_window_list;
|
struct xorg_list damage_window_list;
|
||||||
struct xorg_list window_list;
|
struct xorg_list window_list;
|
||||||
|
|
||||||
+ int32_t global_output_scale;
|
+ int32_t global_output_scale;
|
||||||
+
|
|
||||||
int wayland_fd;
|
int wayland_fd;
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
@@ -107,6 +109,7 @@ struct xwl_screen {
|
@@ -134,6 +135,7 @@ struct xwl_screen {
|
||||||
struct glamor_context *glamor_ctx;
|
struct glamor_context *glamor_ctx;
|
||||||
|
|
||||||
Atom allow_commits_prop;
|
Atom allow_commits_prop;
|
||||||
@@ -465,29 +460,30 @@ index b965dddd7f964b1d100bbb9d10da1c35ab39810e..7446829d098fbe235e605084a016daff
|
|||||||
|
|
||||||
/* The preferred GLVND vendor. If NULL, "mesa" is assumed. */
|
/* The preferred GLVND vendor. If NULL, "mesa" is assumed. */
|
||||||
const char *glvnd_vendor;
|
const char *glvnd_vendor;
|
||||||
@@ -134,5 +137,7 @@ void xwl_screen_roundtrip (struct xwl_screen *xwl_screen);
|
@@ -166,6 +168,8 @@ void xwl_screen_roundtrip (struct xwl_screen *xwl_screen);
|
||||||
void xwl_surface_damage(struct xwl_screen *xwl_screen,
|
void xwl_surface_damage(struct xwl_screen *xwl_screen,
|
||||||
struct wl_surface *surface,
|
struct wl_surface *surface,
|
||||||
int32_t x, int32_t y, int32_t width, int32_t height);
|
int32_t x, int32_t y, int32_t width, int32_t height);
|
||||||
+int xwl_scale_to(struct xwl_screen *xwl_screen, int value);
|
+int xwl_scale_to(struct xwl_screen *xwl_screen, int value);
|
||||||
+void xwl_screen_set_global_scale(struct xwl_screen *xwl_screen, int32_t scale);
|
+void xwl_screen_set_global_scale(struct xwl_screen *xwl_screen, int32_t scale);
|
||||||
|
int xwl_screen_get_next_output_serial(struct xwl_screen * xwl_screen);
|
||||||
|
|
||||||
#endif /* XWAYLAND_SCREEN_H */
|
#endif /* XWAYLAND_SCREEN_H */
|
||||||
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
|
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
|
||||||
index 00f161eda084e335ac07471a2198176d75d9fcf0..ed3903853f0dab1dad390cd8429639541546157d 100644
|
index 6b7f38605..2f1e0dee1 100644
|
||||||
--- a/hw/xwayland/xwayland-window.c
|
--- a/hw/xwayland/xwayland-window.c
|
||||||
+++ b/hw/xwayland/xwayland-window.c
|
+++ b/hw/xwayland/xwayland-window.c
|
||||||
@@ -470,7 +470,8 @@ ensure_surface_for_window(WindowPtr window)
|
@@ -788,7 +788,8 @@ xwl_create_root_surface(struct xwl_window *xwl_window)
|
||||||
}
|
|
||||||
|
|
||||||
wl_region_add(region, 0, 0,
|
|
||||||
- window->drawable.width, window->drawable.height);
|
|
||||||
+ xwl_scale_to(xwl_screen, window->drawable.width),
|
|
||||||
+ xwl_scale_to(xwl_screen, window->drawable.height));
|
|
||||||
wl_surface_set_opaque_region(xwl_window->surface, region);
|
|
||||||
wl_region_destroy(region);
|
|
||||||
}
|
}
|
||||||
@@ -820,6 +821,7 @@ xwl_window_post_damage(struct xwl_window *xwl_window)
|
|
||||||
|
wl_region_add(region, 0, 0,
|
||||||
|
- window->drawable.width, window->drawable.height);
|
||||||
|
+ xwl_scale_to(xwl_screen, window->drawable.width),
|
||||||
|
+ xwl_scale_to(xwl_screen, window->drawable.height));
|
||||||
|
wl_surface_set_opaque_region(xwl_window->surface, region);
|
||||||
|
wl_region_destroy(region);
|
||||||
|
|
||||||
|
@@ -1322,6 +1323,7 @@ xwl_window_post_damage(struct xwl_window *xwl_window)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
|
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
|
||||||
@@ -495,4 +491,3 @@ index 00f161eda084e335ac07471a2198176d75d9fcf0..ed3903853f0dab1dad390cd842963954
|
|||||||
|
|
||||||
/* Arbitrary limit to try to avoid flooding the Wayland
|
/* Arbitrary limit to try to avoid flooding the Wayland
|
||||||
* connection. If we flood it too much anyway, this could
|
* connection. If we flood it too much anyway, this could
|
||||||
|
|
||||||
|
|||||||
3
props.json
Normal file
3
props.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"version": "0.25.0"
|
||||||
|
}
|
||||||
@@ -3,7 +3,14 @@ wayland_protos = dependency('wayland-protocols',
|
|||||||
fallback: 'wayland-protocols',
|
fallback: 'wayland-protocols',
|
||||||
default_options: ['tests=false'],
|
default_options: ['tests=false'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
hyprland_protos = dependency('hyprland-protocols',
|
||||||
|
version: '>=0.2',
|
||||||
|
fallback: 'hyprland-protocols',
|
||||||
|
)
|
||||||
|
|
||||||
wl_protocol_dir = wayland_protos.get_variable('pkgdatadir')
|
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_dep = dependency('wayland-scanner', native: true)
|
||||||
wayland_scanner = find_program(
|
wayland_scanner = find_program(
|
||||||
@@ -13,12 +20,19 @@ wayland_scanner = find_program(
|
|||||||
|
|
||||||
protocols = [
|
protocols = [
|
||||||
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
|
[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, 'staging/fractional-scale/fractional-scale-v1.xml'],
|
||||||
|
['wlr-foreign-toplevel-management-unstable-v1.xml'],
|
||||||
['wlr-layer-shell-unstable-v1.xml'],
|
['wlr-layer-shell-unstable-v1.xml'],
|
||||||
['wlr-output-power-management-unstable-v1.xml'],
|
['wlr-output-power-management-unstable-v1.xml'],
|
||||||
|
['wlr-screencopy-unstable-v1.xml'],
|
||||||
['ext-workspace-unstable-v1.xml'],
|
['ext-workspace-unstable-v1.xml'],
|
||||||
['pointer-constraints-unstable-v1.xml'],
|
['pointer-constraints-unstable-v1.xml'],
|
||||||
['tablet-unstable-v2.xml'],
|
['tablet-unstable-v2.xml'],
|
||||||
['idle.xml']
|
['idle.xml'],
|
||||||
|
[hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml'],
|
||||||
|
[hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml']
|
||||||
]
|
]
|
||||||
wl_protos_src = []
|
wl_protos_src = []
|
||||||
wl_protos_headers = []
|
wl_protos_headers = []
|
||||||
@@ -33,6 +47,8 @@ foreach p : protocols
|
|||||||
wl_protos_headers += custom_target(
|
wl_protos_headers += custom_target(
|
||||||
xml.underscorify() + '_server_h',
|
xml.underscorify() + '_server_h',
|
||||||
input: xml,
|
input: xml,
|
||||||
|
install: true,
|
||||||
|
install_dir: join_paths(get_option('includedir'), 'hyprland/protocols'),
|
||||||
output: '@BASENAME@-protocol.h',
|
output: '@BASENAME@-protocol.h',
|
||||||
command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'],
|
command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'],
|
||||||
)
|
)
|
||||||
|
|||||||
270
protocols/wlr-foreign-toplevel-management-unstable-v1.xml
Normal file
270
protocols/wlr-foreign-toplevel-management-unstable-v1.xml
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="wlr_foreign_toplevel_management_unstable_v1">
|
||||||
|
<copyright>
|
||||||
|
Copyright © 2018 Ilia Bozhinov
|
||||||
|
|
||||||
|
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>
|
||||||
|
|
||||||
|
<interface name="zwlr_foreign_toplevel_manager_v1" version="3">
|
||||||
|
<description summary="list and control opened apps">
|
||||||
|
The purpose of this protocol is to enable the creation of taskbars
|
||||||
|
and docks by providing them with a list of opened applications and
|
||||||
|
letting them request certain actions on them, like maximizing, etc.
|
||||||
|
|
||||||
|
After a client binds the zwlr_foreign_toplevel_manager_v1, each opened
|
||||||
|
toplevel window will be sent via the toplevel event
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<event name="toplevel">
|
||||||
|
<description summary="a toplevel has been created">
|
||||||
|
This event is emitted whenever a new toplevel window is created. It
|
||||||
|
is emitted for all toplevels, regardless of the app that has created
|
||||||
|
them.
|
||||||
|
|
||||||
|
All initial details of the toplevel(title, app_id, states, etc.) will
|
||||||
|
be sent immediately after this event via the corresponding events in
|
||||||
|
zwlr_foreign_toplevel_handle_v1.
|
||||||
|
</description>
|
||||||
|
<arg name="toplevel" type="new_id" interface="zwlr_foreign_toplevel_handle_v1"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="stop">
|
||||||
|
<description summary="stop sending events">
|
||||||
|
Indicates the client no longer wishes to receive events for new toplevels.
|
||||||
|
However the compositor may emit further toplevel_created 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 toplevel manager">
|
||||||
|
This event indicates that the compositor is done sending events to the
|
||||||
|
zwlr_foreign_toplevel_manager_v1. The server will destroy the object
|
||||||
|
immediately after sending this request, so it will become invalid and
|
||||||
|
the client should free any resources associated with it.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zwlr_foreign_toplevel_handle_v1" version="3">
|
||||||
|
<description summary="an opened toplevel">
|
||||||
|
A zwlr_foreign_toplevel_handle_v1 object represents an opened toplevel
|
||||||
|
window. Each app may have multiple opened toplevels.
|
||||||
|
|
||||||
|
Each toplevel has a list of outputs it is visible on, conveyed to the
|
||||||
|
client with the output_enter and output_leave events.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<event name="title">
|
||||||
|
<description summary="title change">
|
||||||
|
This event is emitted whenever the title of the toplevel changes.
|
||||||
|
</description>
|
||||||
|
<arg name="title" type="string"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="app_id">
|
||||||
|
<description summary="app-id change">
|
||||||
|
This event is emitted whenever the app-id of the toplevel changes.
|
||||||
|
</description>
|
||||||
|
<arg name="app_id" type="string"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="output_enter">
|
||||||
|
<description summary="toplevel entered an output">
|
||||||
|
This event is emitted whenever the toplevel becomes visible on
|
||||||
|
the given output. A toplevel may be visible on multiple outputs.
|
||||||
|
</description>
|
||||||
|
<arg name="output" type="object" interface="wl_output"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="output_leave">
|
||||||
|
<description summary="toplevel left an output">
|
||||||
|
This event is emitted whenever the toplevel stops being visible on
|
||||||
|
the given output. It is guaranteed that an entered-output event
|
||||||
|
with the same output has been emitted before this event.
|
||||||
|
</description>
|
||||||
|
<arg name="output" type="object" interface="wl_output"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="set_maximized">
|
||||||
|
<description summary="requests that the toplevel be maximized">
|
||||||
|
Requests that the toplevel be maximized. If the maximized state actually
|
||||||
|
changes, this will be indicated by the state event.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="unset_maximized">
|
||||||
|
<description summary="requests that the toplevel be unmaximized">
|
||||||
|
Requests that the toplevel be unmaximized. If the maximized state actually
|
||||||
|
changes, this will be indicated by the state event.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_minimized">
|
||||||
|
<description summary="requests that the toplevel be minimized">
|
||||||
|
Requests that the toplevel be minimized. If the minimized state actually
|
||||||
|
changes, this will be indicated by the state event.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="unset_minimized">
|
||||||
|
<description summary="requests that the toplevel be unminimized">
|
||||||
|
Requests that the toplevel be unminimized. If the minimized state actually
|
||||||
|
changes, this will be indicated by the state event.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="activate">
|
||||||
|
<description summary="activate the toplevel">
|
||||||
|
Request that this toplevel be activated on the given seat.
|
||||||
|
There is no guarantee the toplevel will be actually activated.
|
||||||
|
</description>
|
||||||
|
<arg name="seat" type="object" interface="wl_seat"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<enum name="state">
|
||||||
|
<description summary="types of states on the toplevel">
|
||||||
|
The different states that a toplevel can have. These have the same meaning
|
||||||
|
as the states with the same names defined in xdg-toplevel
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<entry name="maximized" value="0" summary="the toplevel is maximized"/>
|
||||||
|
<entry name="minimized" value="1" summary="the toplevel is minimized"/>
|
||||||
|
<entry name="activated" value="2" summary="the toplevel is active"/>
|
||||||
|
<entry name="fullscreen" value="3" summary="the toplevel is fullscreen" since="2"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<event name="state">
|
||||||
|
<description summary="the toplevel state changed">
|
||||||
|
This event is emitted immediately after the zlw_foreign_toplevel_handle_v1
|
||||||
|
is created and each time the toplevel state changes, either because of a
|
||||||
|
compositor action or because of a request in this protocol.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<arg name="state" type="array"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="done">
|
||||||
|
<description summary="all information about the toplevel has been sent">
|
||||||
|
This event is sent after all changes in the toplevel state have been
|
||||||
|
sent.
|
||||||
|
|
||||||
|
This allows changes to the zwlr_foreign_toplevel_handle_v1 properties
|
||||||
|
to be seen as atomic, even if they happen via multiple events.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="close">
|
||||||
|
<description summary="request that the toplevel be closed">
|
||||||
|
Send a request to the toplevel to close itself. The compositor would
|
||||||
|
typically use a shell-specific method to carry out this request, for
|
||||||
|
example by sending the xdg_toplevel.close event. However, this gives
|
||||||
|
no guarantees the toplevel will actually be destroyed. If and when
|
||||||
|
this happens, the zwlr_foreign_toplevel_handle_v1.closed event will
|
||||||
|
be emitted.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_rectangle">
|
||||||
|
<description summary="the rectangle which represents the toplevel">
|
||||||
|
The rectangle of the surface specified in this request corresponds to
|
||||||
|
the place where the app using this protocol represents the given toplevel.
|
||||||
|
It can be used by the compositor as a hint for some operations, e.g
|
||||||
|
minimizing. The client is however not required to set this, in which
|
||||||
|
case the compositor is free to decide some default value.
|
||||||
|
|
||||||
|
If the client specifies more than one rectangle, only the last one is
|
||||||
|
considered.
|
||||||
|
|
||||||
|
The dimensions are given in surface-local coordinates.
|
||||||
|
Setting width=height=0 removes the already-set rectangle.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<arg name="surface" type="object" interface="wl_surface"/>
|
||||||
|
<arg name="x" type="int"/>
|
||||||
|
<arg name="y" type="int"/>
|
||||||
|
<arg name="width" type="int"/>
|
||||||
|
<arg name="height" type="int"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="invalid_rectangle" value="0"
|
||||||
|
summary="the provided rectangle is invalid"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<event name="closed">
|
||||||
|
<description summary="this toplevel has been destroyed">
|
||||||
|
This event means the toplevel has been destroyed. It is guaranteed there
|
||||||
|
won't be any more events for this zwlr_foreign_toplevel_handle_v1. The
|
||||||
|
toplevel itself becomes inert so any requests will be ignored except the
|
||||||
|
destroy request.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroy the zwlr_foreign_toplevel_handle_v1 object">
|
||||||
|
Destroys the zwlr_foreign_toplevel_handle_v1 object.
|
||||||
|
|
||||||
|
This request should be called either when the client does not want to
|
||||||
|
use the toplevel anymore or after the closed event to finalize the
|
||||||
|
destruction of the object.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<!-- Version 2 additions -->
|
||||||
|
|
||||||
|
<request name="set_fullscreen" since="2">
|
||||||
|
<description summary="request that the toplevel be fullscreened">
|
||||||
|
Requests that the toplevel be fullscreened on the given output. If the
|
||||||
|
fullscreen state and/or the outputs the toplevel is visible on actually
|
||||||
|
change, this will be indicated by the state and output_enter/leave
|
||||||
|
events.
|
||||||
|
|
||||||
|
The output parameter is only a hint to the compositor. Also, if output
|
||||||
|
is NULL, the compositor should decide which output the toplevel will be
|
||||||
|
fullscreened on, if at all.
|
||||||
|
</description>
|
||||||
|
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="unset_fullscreen" since="2">
|
||||||
|
<description summary="request that the toplevel be unfullscreened">
|
||||||
|
Requests that the toplevel be unfullscreened. If the fullscreen state
|
||||||
|
actually changes, this will be indicated by the state event.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<!-- Version 3 additions -->
|
||||||
|
|
||||||
|
<event name="parent" since="3">
|
||||||
|
<description summary="parent change">
|
||||||
|
This event is emitted whenever the parent of the toplevel changes.
|
||||||
|
|
||||||
|
No event is emitted when the parent handle is destroyed by the client.
|
||||||
|
</description>
|
||||||
|
<arg name="parent" type="object" interface="zwlr_foreign_toplevel_handle_v1" allow-null="true"/>
|
||||||
|
</event>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
||||||
1381
src/Compositor.cpp
1381
src/Compositor.cpp
File diff suppressed because it is too large
Load Diff
@@ -15,180 +15,206 @@
|
|||||||
#include "managers/KeybindManager.hpp"
|
#include "managers/KeybindManager.hpp"
|
||||||
#include "managers/AnimationManager.hpp"
|
#include "managers/AnimationManager.hpp"
|
||||||
#include "managers/EventManager.hpp"
|
#include "managers/EventManager.hpp"
|
||||||
|
#include "managers/ProtocolManager.hpp"
|
||||||
|
#include "managers/SessionLockManager.hpp"
|
||||||
|
#include "managers/HookSystemManager.hpp"
|
||||||
#include "debug/HyprDebugOverlay.hpp"
|
#include "debug/HyprDebugOverlay.hpp"
|
||||||
|
#include "debug/HyprNotificationOverlay.hpp"
|
||||||
#include "helpers/Monitor.hpp"
|
#include "helpers/Monitor.hpp"
|
||||||
#include "helpers/Workspace.hpp"
|
#include "helpers/Workspace.hpp"
|
||||||
#include "Window.hpp"
|
#include "Window.hpp"
|
||||||
#include "render/Renderer.hpp"
|
#include "render/Renderer.hpp"
|
||||||
#include "render/OpenGL.hpp"
|
#include "render/OpenGL.hpp"
|
||||||
#include "hyprerror/HyprError.hpp"
|
#include "hyprerror/HyprError.hpp"
|
||||||
|
#include "plugins/PluginSystem.hpp"
|
||||||
|
|
||||||
|
enum eManagersInitStage
|
||||||
|
{
|
||||||
|
STAGE_PRIORITY = 0,
|
||||||
|
STAGE_LATE
|
||||||
|
};
|
||||||
|
|
||||||
class CCompositor {
|
class CCompositor {
|
||||||
public:
|
public:
|
||||||
CCompositor();
|
CCompositor();
|
||||||
~CCompositor();
|
~CCompositor();
|
||||||
|
|
||||||
// ------------------ WLR BASICS ------------------ //
|
// ------------------ WLR BASICS ------------------ //
|
||||||
wl_display* m_sWLDisplay;
|
wl_display* m_sWLDisplay;
|
||||||
wl_event_loop* m_sWLEventLoop;
|
wl_event_loop* m_sWLEventLoop;
|
||||||
wlr_backend* m_sWLRBackend;
|
wlr_backend* m_sWLRBackend;
|
||||||
wlr_session* m_sWLRSession;
|
wlr_session* m_sWLRSession;
|
||||||
wlr_renderer* m_sWLRRenderer;
|
wlr_renderer* m_sWLRRenderer;
|
||||||
wlr_allocator* m_sWLRAllocator;
|
wlr_allocator* m_sWLRAllocator;
|
||||||
wlr_compositor* m_sWLRCompositor;
|
wlr_compositor* m_sWLRCompositor;
|
||||||
wlr_subcompositor* m_sWLRSubCompositor;
|
wlr_subcompositor* m_sWLRSubCompositor;
|
||||||
wlr_data_device_manager* m_sWLRDataDevMgr;
|
wlr_data_device_manager* m_sWLRDataDevMgr;
|
||||||
wlr_drm* m_sWRLDRM;
|
wlr_drm* m_sWRLDRM;
|
||||||
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
|
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
|
||||||
wlr_xdg_activation_v1* m_sWLRXDGActivation;
|
wlr_xdg_activation_v1* m_sWLRXDGActivation;
|
||||||
wlr_output_layout* m_sWLROutputLayout;
|
wlr_output_layout* m_sWLROutputLayout;
|
||||||
wlr_idle* m_sWLRIdle;
|
wlr_idle* m_sWLRIdle;
|
||||||
wlr_layer_shell_v1* m_sWLRLayerShell;
|
wlr_layer_shell_v1* m_sWLRLayerShell;
|
||||||
wlr_xdg_shell* m_sWLRXDGShell;
|
wlr_xdg_shell* m_sWLRXDGShell;
|
||||||
wlr_cursor* m_sWLRCursor;
|
wlr_cursor* m_sWLRCursor;
|
||||||
wlr_xcursor_manager* m_sWLRXCursorMgr;
|
wlr_xcursor_manager* m_sWLRXCursorMgr;
|
||||||
wlr_virtual_keyboard_manager_v1* m_sWLRVKeyboardMgr;
|
wlr_virtual_keyboard_manager_v1* m_sWLRVKeyboardMgr;
|
||||||
wlr_output_manager_v1* m_sWLROutputMgr;
|
wlr_output_manager_v1* m_sWLROutputMgr;
|
||||||
wlr_presentation* m_sWLRPresentation;
|
wlr_presentation* m_sWLRPresentation;
|
||||||
wlr_scene* m_sWLRScene;
|
wlr_scene* m_sWLRScene;
|
||||||
wlr_input_inhibit_manager* m_sWLRInhibitMgr;
|
wlr_input_inhibit_manager* m_sWLRInhibitMgr;
|
||||||
wlr_keyboard_shortcuts_inhibit_manager_v1* m_sWLRKbShInhibitMgr;
|
wlr_keyboard_shortcuts_inhibit_manager_v1* m_sWLRKbShInhibitMgr;
|
||||||
wlr_egl* m_sWLREGL;
|
wlr_egl* m_sWLREGL;
|
||||||
int m_iDRMFD;
|
int m_iDRMFD;
|
||||||
wlr_ext_workspace_manager_v1* m_sWLREXTWorkspaceMgr;
|
wlr_ext_workspace_manager_v1* m_sWLREXTWorkspaceMgr;
|
||||||
wlr_pointer_constraints_v1* m_sWLRPointerConstraints;
|
wlr_pointer_constraints_v1* m_sWLRPointerConstraints;
|
||||||
wlr_relative_pointer_manager_v1* m_sWLRRelPointerMgr;
|
wlr_relative_pointer_manager_v1* m_sWLRRelPointerMgr;
|
||||||
wlr_server_decoration_manager* m_sWLRServerDecoMgr;
|
wlr_server_decoration_manager* m_sWLRServerDecoMgr;
|
||||||
wlr_xdg_decoration_manager_v1* m_sWLRXDGDecoMgr;
|
wlr_xdg_decoration_manager_v1* m_sWLRXDGDecoMgr;
|
||||||
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
|
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
|
||||||
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
|
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
|
||||||
wlr_tablet_manager_v2* m_sWLRTabletManager;
|
wlr_tablet_manager_v2* m_sWLRTabletManager;
|
||||||
wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
|
wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
|
||||||
wlr_idle_inhibit_manager_v1* m_sWLRIdleInhibitMgr;
|
wlr_idle_inhibit_manager_v1* m_sWLRIdleInhibitMgr;
|
||||||
wlr_pointer_gestures_v1* m_sWLRPointerGestures;
|
wlr_pointer_gestures_v1* m_sWLRPointerGestures;
|
||||||
wlr_output_power_manager_v1* m_sWLROutputPowerMgr;
|
wlr_output_power_manager_v1* m_sWLROutputPowerMgr;
|
||||||
wlr_input_method_manager_v2* m_sWLRIMEMgr;
|
wlr_input_method_manager_v2* m_sWLRIMEMgr;
|
||||||
wlr_text_input_manager_v3* m_sWLRTextInputMgr;
|
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;
|
||||||
// ------------------------------------------------- //
|
// ------------------------------------------------- //
|
||||||
|
|
||||||
|
std::string m_szWLDisplaySocket = "";
|
||||||
|
std::string m_szInstanceSignature = "";
|
||||||
|
std::string m_szCurrentSplash = "error";
|
||||||
|
|
||||||
const char* m_szWLDisplaySocket;
|
std::vector<std::shared_ptr<CMonitor>> m_vMonitors;
|
||||||
std::string m_szInstanceSignature = "";
|
std::vector<std::shared_ptr<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
|
||||||
std::string m_szCurrentSplash = "error";
|
std::vector<std::unique_ptr<CWindow>> m_vWindows;
|
||||||
|
std::vector<std::unique_ptr<SXDGPopup>> m_vXDGPopups;
|
||||||
|
std::vector<std::unique_ptr<CWorkspace>> m_vWorkspaces;
|
||||||
|
std::vector<std::unique_ptr<SSubsurface>> m_vSubsurfaces;
|
||||||
|
std::vector<CWindow*> m_vWindowsFadingOut;
|
||||||
|
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<CMonitor>> m_vMonitors;
|
void initServer();
|
||||||
std::vector<std::shared_ptr<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
|
void startCompositor();
|
||||||
std::vector<std::unique_ptr<CWindow>> m_vWindows;
|
void cleanup();
|
||||||
std::deque<std::unique_ptr<CWindow>> m_dUnmanagedX11Windows;
|
|
||||||
std::vector<std::unique_ptr<SXDGPopup>> m_vXDGPopups;
|
|
||||||
std::vector<std::unique_ptr<CWorkspace>> m_vWorkspaces;
|
|
||||||
std::vector<std::unique_ptr<SSubsurface>> m_vSubsurfaces;
|
|
||||||
std::vector<CWindow*> m_vWindowsFadingOut;
|
|
||||||
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
|
|
||||||
|
|
||||||
void startCompositor();
|
wlr_surface* m_pLastFocus = nullptr;
|
||||||
void cleanup();
|
CWindow* m_pLastWindow = nullptr;
|
||||||
|
CMonitor* m_pLastMonitor = nullptr;
|
||||||
|
|
||||||
wlr_surface* m_pLastFocus = nullptr;
|
std::vector<CWindow*> m_vWindowFocusHistory; // first element is the most recently focused.
|
||||||
CWindow* m_pLastWindow = nullptr;
|
|
||||||
CMonitor* m_pLastMonitor = nullptr;
|
|
||||||
|
|
||||||
SSeat m_sSeat;
|
SSeat m_sSeat;
|
||||||
|
|
||||||
bool m_bReadyToProcess = false;
|
bool m_bReadyToProcess = false;
|
||||||
bool m_bSessionActive = true;
|
bool m_bSessionActive = true;
|
||||||
bool m_bDPMSStateON = true;
|
bool m_bDPMSStateON = true;
|
||||||
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
|
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
|
||||||
bool m_bIsShuttingDown = false;
|
bool m_bIsShuttingDown = false;
|
||||||
std::deque<uint64_t> m_dProcessPIDsOnShutdown; // stores PIDs of apps to kill later when shutting down
|
|
||||||
|
|
||||||
// ------------------------------------------------- //
|
// ------------------------------------------------- //
|
||||||
|
|
||||||
CMonitor* getMonitorFromID(const int&);
|
CMonitor* getMonitorFromID(const int&);
|
||||||
CMonitor* getMonitorFromName(const std::string&);
|
CMonitor* getMonitorFromName(const std::string&);
|
||||||
CMonitor* getMonitorFromCursor();
|
CMonitor* getMonitorFromCursor();
|
||||||
CMonitor* getMonitorFromVector(const Vector2D&);
|
CMonitor* getMonitorFromVector(const Vector2D&);
|
||||||
void removeWindowFromVectorSafe(CWindow*);
|
void removeWindowFromVectorSafe(CWindow*);
|
||||||
void focusWindow(CWindow*, wlr_surface* pSurface = nullptr);
|
void focusWindow(CWindow*, wlr_surface* pSurface = nullptr);
|
||||||
void focusSurface(wlr_surface*, CWindow* pWindowOwner = nullptr);
|
void focusSurface(wlr_surface*, CWindow* pWindowOwner = nullptr);
|
||||||
bool windowExists(CWindow*);
|
bool windowExists(CWindow*);
|
||||||
bool windowValidMapped(CWindow*);
|
bool windowValidMapped(CWindow*);
|
||||||
CWindow* vectorToWindow(const Vector2D&);
|
CWindow* vectorToWindow(const Vector2D&);
|
||||||
CWindow* vectorToWindowIdeal(const Vector2D&); // used only for finding a window to focus on, basically a "findFocusableWindow"
|
CWindow* vectorToWindowIdeal(const Vector2D&); // used only for finding a window to focus on, basically a "findFocusableWindow"
|
||||||
CWindow* vectorToWindowTiled(const Vector2D&);
|
CWindow* vectorToWindowTiled(const Vector2D&);
|
||||||
wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector<std::unique_ptr<SLayerSurface>>*, Vector2D*, SLayerSurface**);
|
wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector<std::unique_ptr<SLayerSurface>>*, Vector2D*, SLayerSurface**);
|
||||||
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
|
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
|
||||||
CWindow* windowFromCursor();
|
CWindow* windowFromCursor();
|
||||||
CWindow* windowFloatingFromCursor();
|
CWindow* windowFloatingFromCursor();
|
||||||
CMonitor* getMonitorFromOutput(wlr_output*);
|
CMonitor* getMonitorFromOutput(wlr_output*);
|
||||||
CWindow* getWindowForPopup(wlr_xdg_popup*);
|
CWindow* getWindowForPopup(wlr_xdg_popup*);
|
||||||
CWindow* getWindowFromSurface(wlr_surface*);
|
CWindow* getWindowFromSurface(wlr_surface*);
|
||||||
bool isWorkspaceVisible(const int&);
|
CWindow* getWindowFromHandle(uint32_t);
|
||||||
CWorkspace* getWorkspaceByID(const int&);
|
CWindow* getWindowFromZWLRHandle(wl_resource*);
|
||||||
CWorkspace* getWorkspaceByName(const std::string&);
|
bool isWorkspaceVisible(const int&);
|
||||||
CWorkspace* getWorkspaceByString(const std::string&);
|
CWorkspace* getWorkspaceByID(const int&);
|
||||||
void sanityCheckWorkspaces();
|
CWorkspace* getWorkspaceByName(const std::string&);
|
||||||
void updateWorkspaceWindowDecos(const int&);
|
CWorkspace* getWorkspaceByString(const std::string&);
|
||||||
int getWindowsOnWorkspace(const int&);
|
void sanityCheckWorkspaces();
|
||||||
CWindow* getFirstWindowOnWorkspace(const int&);
|
void updateWorkspaceWindowDecos(const int&);
|
||||||
CWindow* getFullscreenWindowOnWorkspace(const int&);
|
int getWindowsOnWorkspace(const int&);
|
||||||
bool doesSeatAcceptInput(wlr_surface*);
|
CWindow* getUrgentWindow();
|
||||||
bool isWindowActive(CWindow*);
|
bool hasUrgentWindowOnWorkspace(const int&);
|
||||||
void moveWindowToTop(CWindow*);
|
CWindow* getFirstWindowOnWorkspace(const int&);
|
||||||
void cleanupFadingOut(const int& monid);
|
CWindow* getFullscreenWindowOnWorkspace(const int&);
|
||||||
CWindow* getWindowInDirection(CWindow*, char);
|
bool doesSeatAcceptInput(wlr_surface*);
|
||||||
void deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude = nullptr);
|
bool isWindowActive(CWindow*);
|
||||||
CWindow* getNextWindowOnWorkspace(CWindow*, bool focusableOnly = false);
|
void moveWindowToTop(CWindow*);
|
||||||
CWindow* getPrevWindowOnWorkspace(CWindow*, bool focusableOnly = false);
|
void cleanupFadingOut(const int& monid);
|
||||||
int getNextAvailableNamedWorkspace();
|
CWindow* getWindowInDirection(CWindow*, char);
|
||||||
bool isPointOnAnyMonitor(const Vector2D&);
|
void deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude = nullptr);
|
||||||
CWindow* getConstraintWindow(SMouse*);
|
CWindow* getNextWindowOnWorkspace(CWindow*, bool focusableOnly = false);
|
||||||
CMonitor* getMonitorInDirection(const char&);
|
CWindow* getPrevWindowOnWorkspace(CWindow*, bool focusableOnly = false);
|
||||||
void updateAllWindowsAnimatedDecorationValues();
|
int getNextAvailableNamedWorkspace();
|
||||||
void updateWindowAnimatedDecorationValues(CWindow*);
|
bool isPointOnAnyMonitor(const Vector2D&);
|
||||||
int getNextAvailableMonitorID();
|
CWindow* getConstraintWindow(SMouse*);
|
||||||
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*);
|
CMonitor* getMonitorInDirection(const char&);
|
||||||
void swapActiveWorkspaces(CMonitor*, CMonitor*);
|
void updateAllWindowsAnimatedDecorationValues();
|
||||||
CMonitor* getMonitorFromString(const std::string&);
|
void updateWindowAnimatedDecorationValues(CWindow*);
|
||||||
bool workspaceIDOutOfBounds(const int&);
|
int getNextAvailableMonitorID();
|
||||||
void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
|
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*);
|
||||||
void moveUnmanagedX11ToWindows(CWindow*);
|
void swapActiveWorkspaces(CMonitor*, CMonitor*);
|
||||||
CWindow* getX11Parent(CWindow*);
|
CMonitor* getMonitorFromString(const std::string&);
|
||||||
void scheduleFrameForMonitor(CMonitor*);
|
bool workspaceIDOutOfBounds(const int&);
|
||||||
void addToFadingOutSafe(SLayerSurface*);
|
void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
|
||||||
void addToFadingOutSafe(CWindow*);
|
void updateFullscreenFadeOnWorkspace(CWorkspace*);
|
||||||
CWindow* getWindowByRegex(const std::string&);
|
CWindow* getX11Parent(CWindow*);
|
||||||
void warpCursorTo(const Vector2D&);
|
void scheduleFrameForMonitor(CMonitor*);
|
||||||
SLayerSurface* getLayerSurfaceFromWlr(wlr_layer_surface_v1*);
|
void addToFadingOutSafe(SLayerSurface*);
|
||||||
SLayerSurface* getLayerSurfaceFromSurface(wlr_surface*);
|
void addToFadingOutSafe(CWindow*);
|
||||||
void closeWindow(CWindow*);
|
CWindow* getWindowByRegex(const std::string&);
|
||||||
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
|
void warpCursorTo(const Vector2D&, bool force = false);
|
||||||
void forceReportSizesToWindowsOnWorkspace(const int&);
|
SLayerSurface* getLayerSurfaceFromWlr(wlr_layer_surface_v1*);
|
||||||
bool cursorOnReservedArea();
|
SLayerSurface* getLayerSurfaceFromSurface(wlr_surface*);
|
||||||
|
void closeWindow(CWindow*);
|
||||||
|
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
|
||||||
|
void forceReportSizesToWindowsOnWorkspace(const int&);
|
||||||
|
bool cursorOnReservedArea();
|
||||||
|
CWorkspace* 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 setActiveMonitor(CMonitor*);
|
||||||
|
bool isWorkspaceSpecial(const int&);
|
||||||
|
int getNewSpecialID();
|
||||||
|
void performUserChecks();
|
||||||
|
void moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorkspace);
|
||||||
|
|
||||||
std::string explicitConfigPath;
|
std::string explicitConfigPath;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initAllSignals();
|
void initAllSignals();
|
||||||
void setRandomSplash();
|
void setRandomSplash();
|
||||||
|
void initManagers(eManagersInitStage stage);
|
||||||
|
|
||||||
uint64_t m_iHyprlandPID = 0;
|
uint64_t m_iHyprlandPID = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline std::unique_ptr<CCompositor> g_pCompositor;
|
inline std::unique_ptr<CCompositor> g_pCompositor;
|
||||||
|
|
||||||
// For XWayland
|
// For XWayland
|
||||||
inline std::map<std::string, xcb_atom_t> HYPRATOMS = {
|
inline std::map<std::string, xcb_atom_t> HYPRATOMS = {HYPRATOM("_NET_WM_WINDOW_TYPE"),
|
||||||
HYPRATOM("_NET_WM_WINDOW_TYPE"),
|
HYPRATOM("_NET_WM_WINDOW_TYPE_NORMAL"),
|
||||||
HYPRATOM("_NET_WM_WINDOW_TYPE_NORMAL"),
|
HYPRATOM("_NET_WM_WINDOW_TYPE_DOCK"),
|
||||||
HYPRATOM("_NET_WM_WINDOW_TYPE_DOCK"),
|
HYPRATOM("_NET_WM_WINDOW_TYPE_DIALOG"),
|
||||||
HYPRATOM("_NET_WM_WINDOW_TYPE_DIALOG"),
|
HYPRATOM("_NET_WM_WINDOW_TYPE_UTILITY"),
|
||||||
HYPRATOM("_NET_WM_WINDOW_TYPE_UTILITY"),
|
HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLBAR"),
|
||||||
HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLBAR"),
|
HYPRATOM("_NET_WM_WINDOW_TYPE_SPLASH"),
|
||||||
HYPRATOM("_NET_WM_WINDOW_TYPE_SPLASH"),
|
HYPRATOM("_NET_WM_WINDOW_TYPE_MENU"),
|
||||||
HYPRATOM("_NET_WM_WINDOW_TYPE_MENU"),
|
HYPRATOM("_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"),
|
||||||
HYPRATOM("_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"),
|
HYPRATOM("_NET_WM_WINDOW_TYPE_POPUP_MENU"),
|
||||||
HYPRATOM("_NET_WM_WINDOW_TYPE_POPUP_MENU"),
|
HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLTIP"),
|
||||||
HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLTIP"),
|
HYPRATOM("_NET_WM_WINDOW_TYPE_NOTIFICATION"),
|
||||||
HYPRATOM("_NET_WM_WINDOW_TYPE_NOTIFICATION")};
|
HYPRATOM("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE")};
|
||||||
|
|||||||
23
src/SharedDefs.hpp
Normal file
23
src/SharedDefs.hpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum eIcons
|
||||||
|
{
|
||||||
|
ICON_WARNING = 0,
|
||||||
|
ICON_INFO,
|
||||||
|
ICON_HINT,
|
||||||
|
ICON_ERROR,
|
||||||
|
ICON_CONFUSED,
|
||||||
|
ICON_OK,
|
||||||
|
ICON_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum eRenderStage
|
||||||
|
{
|
||||||
|
RENDER_PRE = 0, /* Before binding the gl context */
|
||||||
|
RENDER_BEGIN, /* Just when the rendering begins, nothing has been rendered yet. Damage, current render data in opengl valid. */
|
||||||
|
RENDER_PRE_WINDOWS, /* Pre windows, post bottom and overlay layers */
|
||||||
|
RENDER_POST_WINDOWS, /* Post windows, pre top/overlay layers, etc */
|
||||||
|
RENDER_LAST_MOMENT, /* Last moment to render with the gl context */
|
||||||
|
RENDER_POST, /* After rendering is finished, gl context not available anymore */
|
||||||
|
RENDER_POST_MIRROR, /* After rendering a mirror */
|
||||||
|
};
|
||||||
505
src/Window.cpp
505
src/Window.cpp
@@ -3,9 +3,10 @@
|
|||||||
#include "render/decorations/CHyprDropShadowDecoration.hpp"
|
#include "render/decorations/CHyprDropShadowDecoration.hpp"
|
||||||
|
|
||||||
CWindow::CWindow() {
|
CWindow::CWindow() {
|
||||||
m_vRealPosition.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*) this, AVARDAMAGE_ENTIRE);
|
m_vRealPosition.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||||
m_vRealSize.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
m_vRealSize.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||||
m_cRealBorderColor.create(AVARTYPE_COLOR, g_pConfigManager->getAnimationPropertyConfig("border"), (void*)this, AVARDAMAGE_BORDER);
|
m_fBorderFadeAnimationProgress.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("border"), (void*)this, AVARDAMAGE_BORDER);
|
||||||
|
m_fBorderAngleAnimationProgress.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("borderangle"), (void*)this, AVARDAMAGE_BORDER);
|
||||||
m_fAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
m_fAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||||
m_fActiveInactiveAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), (void*)this, AVARDAMAGE_ENTIRE);
|
m_fActiveInactiveAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||||
m_cRealShadowColor.create(AVARTYPE_COLOR, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), (void*)this, AVARDAMAGE_SHADOW);
|
m_cRealShadowColor.create(AVARTYPE_COLOR, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), (void*)this, AVARDAMAGE_SHADOW);
|
||||||
@@ -16,13 +17,18 @@ CWindow::CWindow() {
|
|||||||
|
|
||||||
CWindow::~CWindow() {
|
CWindow::~CWindow() {
|
||||||
if (g_pCompositor->isWindowActive(this)) {
|
if (g_pCompositor->isWindowActive(this)) {
|
||||||
g_pCompositor->m_pLastFocus = nullptr;
|
g_pCompositor->m_pLastFocus = nullptr;
|
||||||
g_pCompositor->m_pLastWindow = nullptr;
|
g_pCompositor->m_pLastWindow = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_box CWindow::getFullWindowBoundingBox() {
|
wlr_box CWindow::getFullWindowBoundingBox() {
|
||||||
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||||
|
|
||||||
|
if (m_sAdditionalConfigData.dimAround) {
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
|
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||||
|
}
|
||||||
|
|
||||||
SWindowDecorationExtents maxExtents = {{*PBORDERSIZE + 2, *PBORDERSIZE + 2}, {*PBORDERSIZE + 2, *PBORDERSIZE + 2}};
|
SWindowDecorationExtents maxExtents = {{*PBORDERSIZE + 2, *PBORDERSIZE + 2}, {*PBORDERSIZE + 2, *PBORDERSIZE + 2}};
|
||||||
|
|
||||||
@@ -44,10 +50,8 @@ wlr_box CWindow::getFullWindowBoundingBox() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add extents to the real base BB and return
|
// Add extents to the real base BB and return
|
||||||
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x,
|
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
||||||
m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||||
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x,
|
|
||||||
m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
|
||||||
|
|
||||||
return finalBox;
|
return finalBox;
|
||||||
}
|
}
|
||||||
@@ -56,8 +60,15 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
|||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
|
|
||||||
auto POS = m_vPosition;
|
auto POS = m_vPosition;
|
||||||
auto SIZE = m_vSize;
|
auto SIZE = m_vSize;
|
||||||
|
|
||||||
|
if (m_bIsFullscreen) {
|
||||||
|
POS = PMONITOR->vecPosition;
|
||||||
|
SIZE = PMONITOR->vecSize;
|
||||||
|
|
||||||
|
return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||||
|
}
|
||||||
|
|
||||||
if (DELTALESSTHAN(POS.y - PMONITOR->vecPosition.y, PMONITOR->vecReservedTopLeft.y, 1)) {
|
if (DELTALESSTHAN(POS.y - PMONITOR->vecPosition.y, PMONITOR->vecReservedTopLeft.y, 1)) {
|
||||||
POS.y = PMONITOR->vecPosition.y;
|
POS.y = PMONITOR->vecPosition.y;
|
||||||
@@ -77,6 +88,59 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
|||||||
return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wlr_box CWindow::getWindowInputBox() {
|
||||||
|
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||||
|
|
||||||
|
if (m_sAdditionalConfigData.dimAround) {
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
|
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||||
|
}
|
||||||
|
|
||||||
|
SWindowDecorationExtents maxExtents = {{*PBORDERSIZE + 2, *PBORDERSIZE + 2}, {*PBORDERSIZE + 2, *PBORDERSIZE + 2}};
|
||||||
|
|
||||||
|
for (auto& wd : m_dWindowDecorations) {
|
||||||
|
|
||||||
|
if (!wd->allowsInput())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto EXTENTS = wd->getWindowDecorationExtents();
|
||||||
|
|
||||||
|
if (EXTENTS.topLeft.x > maxExtents.topLeft.x)
|
||||||
|
maxExtents.topLeft.x = EXTENTS.topLeft.x;
|
||||||
|
|
||||||
|
if (EXTENTS.topLeft.y > maxExtents.topLeft.y)
|
||||||
|
maxExtents.topLeft.y = EXTENTS.topLeft.y;
|
||||||
|
|
||||||
|
if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x)
|
||||||
|
maxExtents.bottomRight.x = EXTENTS.bottomRight.x;
|
||||||
|
|
||||||
|
if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y)
|
||||||
|
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add extents to the real base BB and return
|
||||||
|
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
||||||
|
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||||
|
|
||||||
|
return finalBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWindowDecorationExtents CWindow::getFullWindowReservedArea() {
|
||||||
|
SWindowDecorationExtents extents;
|
||||||
|
|
||||||
|
for (auto& wd : m_dWindowDecorations) {
|
||||||
|
const auto RESERVED = wd->getWindowDecorationReservedArea();
|
||||||
|
|
||||||
|
if (RESERVED.bottomRight == Vector2D{} && RESERVED.topLeft == Vector2D{})
|
||||||
|
continue;
|
||||||
|
|
||||||
|
extents.topLeft = extents.topLeft + RESERVED.topLeft;
|
||||||
|
extents.bottomRight = extents.bottomRight + RESERVED.bottomRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return extents;
|
||||||
|
}
|
||||||
|
|
||||||
void CWindow::updateWindowDecos() {
|
void CWindow::updateWindowDecos() {
|
||||||
for (auto& wd : m_dWindowDecorations)
|
for (auto& wd : m_dWindowDecorations)
|
||||||
wd->updateWindow(this);
|
wd->updateWindow(this);
|
||||||
@@ -97,6 +161,10 @@ void CWindow::updateWindowDecos() {
|
|||||||
pid_t CWindow::getPID() {
|
pid_t CWindow::getPID() {
|
||||||
pid_t PID = -1;
|
pid_t PID = -1;
|
||||||
if (!m_bIsX11) {
|
if (!m_bIsX11) {
|
||||||
|
|
||||||
|
if (!m_bIsMapped)
|
||||||
|
return -1;
|
||||||
|
|
||||||
wl_client_get_credentials(wl_resource_get_client(m_uSurface.xdg->resource), &PID, nullptr, nullptr);
|
wl_client_get_credentials(wl_resource_get_client(m_uSurface.xdg->resource), &PID, nullptr, nullptr);
|
||||||
} else {
|
} else {
|
||||||
PID = m_uSurface.xwayland->pid;
|
PID = m_uSurface.xwayland->pid;
|
||||||
@@ -128,25 +196,20 @@ void CWindow::createToplevelHandle() {
|
|||||||
wlr_foreign_toplevel_handle_v1_set_fullscreen(m_phForeignToplevel, false);
|
wlr_foreign_toplevel_handle_v1_set_fullscreen(m_phForeignToplevel, false);
|
||||||
|
|
||||||
// handle events
|
// handle events
|
||||||
hyprListener_toplevelActivate.initCallback(&m_phForeignToplevel->events.request_activate, [&](void* owner, void* data) {
|
hyprListener_toplevelActivate.initCallback(
|
||||||
|
&m_phForeignToplevel->events.request_activate, [&](void* owner, void* data) { g_pCompositor->focusWindow(this); }, this, "Toplevel");
|
||||||
|
|
||||||
g_pCompositor->focusWindow(this);
|
hyprListener_toplevelFullscreen.initCallback(
|
||||||
|
&m_phForeignToplevel->events.request_fullscreen,
|
||||||
|
[&](void* owner, void* data) {
|
||||||
|
const auto EV = (wlr_foreign_toplevel_handle_v1_fullscreen_event*)data;
|
||||||
|
|
||||||
}, this, "Toplevel");
|
g_pCompositor->setWindowFullscreen(this, EV->fullscreen, FULLSCREEN_FULL);
|
||||||
|
},
|
||||||
|
this, "Toplevel");
|
||||||
|
|
||||||
hyprListener_toplevelFullscreen.initCallback(&m_phForeignToplevel->events.request_fullscreen, [&](void* owner, void* data) {
|
hyprListener_toplevelClose.initCallback(
|
||||||
|
&m_phForeignToplevel->events.request_close, [&](void* owner, void* data) { g_pCompositor->closeWindow(this); }, this, "Toplevel");
|
||||||
const auto EV = (wlr_foreign_toplevel_handle_v1_fullscreen_event*)data;
|
|
||||||
|
|
||||||
g_pCompositor->setWindowFullscreen(this, EV->fullscreen, FULLSCREEN_FULL);
|
|
||||||
|
|
||||||
}, this, "Toplevel");
|
|
||||||
|
|
||||||
hyprListener_toplevelClose.initCallback(&m_phForeignToplevel->events.request_close, [&](void* owner, void* data) {
|
|
||||||
|
|
||||||
g_pCompositor->closeWindow(this);
|
|
||||||
|
|
||||||
}, this, "Toplevel");
|
|
||||||
|
|
||||||
m_iLastToplevelMonitorID = m_iMonitorID;
|
m_iLastToplevelMonitorID = m_iMonitorID;
|
||||||
}
|
}
|
||||||
@@ -202,19 +265,43 @@ void CWindow::updateSurfaceOutputs() {
|
|||||||
const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
|
|
||||||
if (PLASTMONITOR && PLASTMONITOR->m_bEnabled)
|
if (PLASTMONITOR && PLASTMONITOR->m_bEnabled)
|
||||||
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(this), sendLeaveIter, PLASTMONITOR->output);
|
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendLeaveIter, PLASTMONITOR->output);
|
||||||
|
|
||||||
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(this), sendEnterIter, PNEWMONITOR->output);
|
wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendEnterIter, PNEWMONITOR->output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::moveToWorkspace(int workspaceID) {
|
void CWindow::moveToWorkspace(int workspaceID) {
|
||||||
if (m_iWorkspaceID != workspaceID) {
|
if (m_iWorkspaceID == workspaceID)
|
||||||
m_iWorkspaceID = workspaceID;
|
return;
|
||||||
|
|
||||||
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); PWORKSPACE) {
|
m_iWorkspaceID = workspaceID;
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%x,%s", this, PWORKSPACE->m_szName.c_str())});
|
|
||||||
}
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
||||||
|
|
||||||
|
if (PWORKSPACE) {
|
||||||
|
g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%lx,%s", this, PWORKSPACE->m_szName.c_str())});
|
||||||
|
EMIT_HOOK_EVENT("moveWindow", (std::vector<void*>{this, PWORKSPACE}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_pSwallowed) {
|
||||||
|
m_pSwallowed->moveToWorkspace(workspaceID);
|
||||||
|
m_pSwallowed->m_iMonitorID = m_iMonitorID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PMONITOR)
|
||||||
|
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(m_pWLSurface.wlr(), PMONITOR->scale);
|
||||||
|
|
||||||
|
if (!m_bIsMapped)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wlr_surface_for_each_surface(
|
||||||
|
m_pWLSurface.wlr(),
|
||||||
|
[](wlr_surface* surf, int x, int y, void* data) {
|
||||||
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(((CWindow*)data)->m_iMonitorID);
|
||||||
|
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(surf, PMONITOR ? PMONITOR->scale : 1.f);
|
||||||
|
},
|
||||||
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CWindow* CWindow::X11TransientFor() {
|
CWindow* CWindow::X11TransientFor() {
|
||||||
@@ -244,3 +331,355 @@ void CWindow::removeDecorationByType(eDecorationType type) {
|
|||||||
|
|
||||||
updateWindowDecos();
|
updateWindowDecos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void unregisterVar(void* ptr) {
|
||||||
|
((CAnimatedVariable*)ptr)->unregister();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::onUnmap() {
|
||||||
|
if (g_pCompositor->m_pLastWindow == this)
|
||||||
|
g_pCompositor->m_pLastWindow = nullptr;
|
||||||
|
|
||||||
|
m_vRealPosition.setCallbackOnEnd(unregisterVar);
|
||||||
|
m_vRealSize.setCallbackOnEnd(unregisterVar);
|
||||||
|
m_fBorderFadeAnimationProgress.setCallbackOnEnd(unregisterVar);
|
||||||
|
m_fBorderAngleAnimationProgress.setCallbackOnEnd(unregisterVar);
|
||||||
|
m_fActiveInactiveAlpha.setCallbackOnEnd(unregisterVar);
|
||||||
|
m_fAlpha.setCallbackOnEnd(unregisterVar);
|
||||||
|
m_cRealShadowColor.setCallbackOnEnd(unregisterVar);
|
||||||
|
m_fDimPercent.setCallbackOnEnd(unregisterVar);
|
||||||
|
|
||||||
|
m_vRealSize.setCallbackOnBegin(nullptr);
|
||||||
|
|
||||||
|
std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other == this; });
|
||||||
|
|
||||||
|
m_pWLSurface.unassign();
|
||||||
|
|
||||||
|
hyprListener_unmapWindow.removeCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::onMap() {
|
||||||
|
|
||||||
|
m_pWLSurface.assign(g_pXWaylandManager->getWindowSurface(this));
|
||||||
|
|
||||||
|
// JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped)
|
||||||
|
m_vRealPosition.resetAllCallbacks();
|
||||||
|
m_vRealSize.resetAllCallbacks();
|
||||||
|
m_fBorderFadeAnimationProgress.resetAllCallbacks();
|
||||||
|
m_fBorderAngleAnimationProgress.resetAllCallbacks();
|
||||||
|
m_fActiveInactiveAlpha.resetAllCallbacks();
|
||||||
|
m_fAlpha.resetAllCallbacks();
|
||||||
|
m_cRealShadowColor.resetAllCallbacks();
|
||||||
|
m_fDimPercent.resetAllCallbacks();
|
||||||
|
|
||||||
|
m_vRealPosition.registerVar();
|
||||||
|
m_vRealSize.registerVar();
|
||||||
|
m_fBorderFadeAnimationProgress.registerVar();
|
||||||
|
m_fBorderAngleAnimationProgress.registerVar();
|
||||||
|
m_fActiveInactiveAlpha.registerVar();
|
||||||
|
m_fAlpha.registerVar();
|
||||||
|
m_cRealShadowColor.registerVar();
|
||||||
|
m_fDimPercent.registerVar();
|
||||||
|
|
||||||
|
m_fBorderAngleAnimationProgress.setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false);
|
||||||
|
|
||||||
|
m_fBorderAngleAnimationProgress.setValueAndWarp(0.f);
|
||||||
|
m_fBorderAngleAnimationProgress = 1.f;
|
||||||
|
|
||||||
|
g_pCompositor->m_vWindowFocusHistory.push_back(this);
|
||||||
|
|
||||||
|
hyprListener_unmapWindow.initCallback(m_bIsX11 ? &m_uSurface.xwayland->events.unmap : &m_uSurface.xdg->events.unmap, &Events::listener_unmapWindow, this, "CWindow");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::onBorderAngleAnimEnd(void* ptr) {
|
||||||
|
const auto PANIMVAR = (CAnimatedVariable*)ptr;
|
||||||
|
|
||||||
|
const std::string STYLE = PANIMVAR->getConfig()->pValues->internalStyle;
|
||||||
|
|
||||||
|
if (STYLE != "loop" || !PANIMVAR->getConfig()->pValues->internalEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PANIMVAR->setCallbackOnEnd(nullptr); // we remove the callback here because otherwise setvalueandwarp will recurse this
|
||||||
|
|
||||||
|
PANIMVAR->setValueAndWarp(0);
|
||||||
|
*PANIMVAR = 1.f;
|
||||||
|
|
||||||
|
PANIMVAR->setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::setHidden(bool hidden) {
|
||||||
|
m_bHidden = hidden;
|
||||||
|
|
||||||
|
if (hidden && g_pCompositor->m_pLastWindow == this) {
|
||||||
|
g_pCompositor->m_pLastWindow = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWindow::isHidden() {
|
||||||
|
return m_bHidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||||
|
if (r.szRule == "noblur") {
|
||||||
|
m_sAdditionalConfigData.forceNoBlur = true;
|
||||||
|
} else if (r.szRule == "noborder") {
|
||||||
|
m_sAdditionalConfigData.forceNoBorder = true;
|
||||||
|
} else if (r.szRule == "noshadow") {
|
||||||
|
m_sAdditionalConfigData.forceNoShadow = true;
|
||||||
|
} else if (r.szRule == "forcergbx") {
|
||||||
|
m_sAdditionalConfigData.forceRGBX = true;
|
||||||
|
} else if (r.szRule == "opaque") {
|
||||||
|
if (!m_sAdditionalConfigData.forceOpaqueOverridden)
|
||||||
|
m_sAdditionalConfigData.forceOpaque = true;
|
||||||
|
} else if (r.szRule.find("rounding") == 0) {
|
||||||
|
try {
|
||||||
|
m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||||
|
} catch (std::exception& e) { Debug::log(ERR, "Rounding rule \"%s\" failed with: %s", r.szRule.c_str(), e.what()); }
|
||||||
|
} else if (r.szRule.find("opacity") == 0) {
|
||||||
|
try {
|
||||||
|
CVarList vars(r.szRule, 0, ' ');
|
||||||
|
|
||||||
|
for (size_t i = 1 /* first item is "opacity" */; i < vars.size(); ++i) {
|
||||||
|
if (i == 1) {
|
||||||
|
// first arg, alpha
|
||||||
|
m_sSpecialRenderData.alpha = std::stof(vars[i]);
|
||||||
|
} else {
|
||||||
|
if (vars[i] == "override") {
|
||||||
|
if (i == 2) {
|
||||||
|
m_sSpecialRenderData.alphaOverride = true;
|
||||||
|
} else {
|
||||||
|
m_sSpecialRenderData.alphaInactiveOverride = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_sSpecialRenderData.alphaInactive = std::stof(vars[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (std::exception& e) { Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what()); }
|
||||||
|
} else if (r.szRule == "noanim") {
|
||||||
|
m_sAdditionalConfigData.forceNoAnims = true;
|
||||||
|
} else if (r.szRule.find("animation") == 0) {
|
||||||
|
auto STYLE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||||
|
m_sAdditionalConfigData.animationStyle = STYLE;
|
||||||
|
} else if (r.szRule.find("bordercolor") == 0) {
|
||||||
|
try {
|
||||||
|
std::string colorPart = removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||||
|
|
||||||
|
if (colorPart.contains(' ')) {
|
||||||
|
// we have a space, 2 values
|
||||||
|
m_sSpecialRenderData.activeBorderColor = configStringToInt(colorPart.substr(0, colorPart.find_first_of(' ')));
|
||||||
|
m_sSpecialRenderData.inactiveBorderColor = configStringToInt(colorPart.substr(colorPart.find_first_of(' ') + 1));
|
||||||
|
} else {
|
||||||
|
m_sSpecialRenderData.activeBorderColor = configStringToInt(colorPart);
|
||||||
|
}
|
||||||
|
} catch (std::exception& e) { Debug::log(ERR, "BorderColor rule \"%s\" failed with: %s", r.szRule.c_str(), e.what()); }
|
||||||
|
} else if (r.szRule == "dimaround") {
|
||||||
|
m_sAdditionalConfigData.dimAround = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::updateDynamicRules() {
|
||||||
|
m_sSpecialRenderData.activeBorderColor = -1;
|
||||||
|
m_sSpecialRenderData.inactiveBorderColor = -1;
|
||||||
|
m_sSpecialRenderData.alpha = 1.f;
|
||||||
|
m_sSpecialRenderData.alphaInactive = -1.f;
|
||||||
|
m_sAdditionalConfigData.forceNoBlur = false;
|
||||||
|
m_sAdditionalConfigData.forceNoBorder = false;
|
||||||
|
m_sAdditionalConfigData.forceNoShadow = false;
|
||||||
|
if (!m_sAdditionalConfigData.forceOpaqueOverridden)
|
||||||
|
m_sAdditionalConfigData.forceOpaque = false;
|
||||||
|
m_sAdditionalConfigData.forceNoAnims = false;
|
||||||
|
m_sAdditionalConfigData.animationStyle = std::string("");
|
||||||
|
m_sAdditionalConfigData.rounding = -1;
|
||||||
|
m_sAdditionalConfigData.dimAround = false;
|
||||||
|
m_sAdditionalConfigData.forceRGBX = false;
|
||||||
|
|
||||||
|
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(this);
|
||||||
|
for (auto& r : WINDOWRULES) {
|
||||||
|
applyDynamicRule(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the point is "hidden" under a rounded corner of the window
|
||||||
|
// it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize)
|
||||||
|
// otherwise behaviour is undefined
|
||||||
|
bool CWindow::isInCurvedCorner(double x, double y) {
|
||||||
|
static auto* const ROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||||
|
static auto* const BORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||||
|
|
||||||
|
if (BORDERSIZE >= ROUNDING || ROUNDING == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// (x0, y0), (x0, y1), ... are the center point of rounding at each corner
|
||||||
|
double x0 = m_vRealPosition.vec().x + *ROUNDING;
|
||||||
|
double y0 = m_vRealPosition.vec().y + *ROUNDING;
|
||||||
|
double x1 = m_vRealPosition.vec().x + m_vRealSize.vec().x - *ROUNDING;
|
||||||
|
double y1 = m_vRealPosition.vec().y + m_vRealSize.vec().y - *ROUNDING;
|
||||||
|
|
||||||
|
if (x < x0 && y < y0) {
|
||||||
|
return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)*ROUNDING;
|
||||||
|
}
|
||||||
|
if (x > x1 && y < y0) {
|
||||||
|
return Vector2D{x1, y0}.distance(Vector2D{x, y}) > (double)*ROUNDING;
|
||||||
|
}
|
||||||
|
if (x < x0 && y > y1) {
|
||||||
|
return Vector2D{x0, y1}.distance(Vector2D{x, y}) > (double)*ROUNDING;
|
||||||
|
}
|
||||||
|
if (x > x1 && y > y1) {
|
||||||
|
return Vector2D{x1, y1}.distance(Vector2D{x, y}) > (double)*ROUNDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void findExtensionForVector2D(wlr_surface* surface, int x, int y, void* data) {
|
||||||
|
const auto DATA = (SExtensionFindingData*)data;
|
||||||
|
|
||||||
|
wlr_box box = {DATA->origin.x + x, DATA->origin.y + y, surface->current.width, surface->current.height};
|
||||||
|
|
||||||
|
if (wlr_box_contains_point(&box, DATA->vec.x, DATA->vec.y))
|
||||||
|
*DATA->found = surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks if the wayland window has a popup at pos
|
||||||
|
bool CWindow::hasPopupAt(const Vector2D& pos) {
|
||||||
|
if (m_bIsX11)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wlr_surface* resultSurf = nullptr;
|
||||||
|
Vector2D origin = m_vRealPosition.vec();
|
||||||
|
SExtensionFindingData data = {origin, pos, &resultSurf};
|
||||||
|
wlr_xdg_surface_for_each_popup_surface(m_uSurface.xdg, findExtensionForVector2D, &data);
|
||||||
|
|
||||||
|
return resultSurf;
|
||||||
|
}
|
||||||
|
|
||||||
|
CWindow* CWindow::getGroupHead() {
|
||||||
|
CWindow* curr = this;
|
||||||
|
while (!curr->m_sGroupData.head)
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CWindow* CWindow::getGroupTail() {
|
||||||
|
CWindow* curr = this;
|
||||||
|
while (!curr->m_sGroupData.pNextWindow->m_sGroupData.head)
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CWindow* CWindow::getGroupCurrent() {
|
||||||
|
CWindow* curr = this;
|
||||||
|
while (curr->isHidden())
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::setGroupCurrent(CWindow* pWindow) {
|
||||||
|
CWindow* curr = this->m_sGroupData.pNextWindow;
|
||||||
|
bool isMember = false;
|
||||||
|
while (curr != this) {
|
||||||
|
if (curr == pWindow) {
|
||||||
|
isMember = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isMember && pWindow != this)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto PCURRENT = getGroupCurrent();
|
||||||
|
const bool FULLSCREEN = PCURRENT->m_bIsFullscreen;
|
||||||
|
const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PCURRENT->m_iWorkspaceID);
|
||||||
|
|
||||||
|
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goalv();
|
||||||
|
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goalv();
|
||||||
|
|
||||||
|
const auto CURRENTISFOCUS = PCURRENT == g_pCompositor->m_pLastWindow;
|
||||||
|
|
||||||
|
if (FULLSCREEN)
|
||||||
|
g_pCompositor->setWindowFullscreen(PCURRENT, false, WORKSPACE->m_efFullscreenMode);
|
||||||
|
|
||||||
|
PCURRENT->setHidden(true);
|
||||||
|
pWindow->setHidden(false);
|
||||||
|
|
||||||
|
g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow);
|
||||||
|
|
||||||
|
if (PCURRENT->m_bIsFloating) {
|
||||||
|
pWindow->m_vRealPosition.setValueAndWarp(PWINDOWPOS);
|
||||||
|
pWindow->m_vRealSize.setValueAndWarp(PWINDOWSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||||
|
|
||||||
|
if (CURRENTISFOCUS)
|
||||||
|
g_pCompositor->focusWindow(pWindow);
|
||||||
|
|
||||||
|
if (FULLSCREEN)
|
||||||
|
g_pCompositor->setWindowFullscreen(pWindow, true, WORKSPACE->m_efFullscreenMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::insertWindowToGroup(CWindow* pWindow) {
|
||||||
|
const auto PHEAD = getGroupHead();
|
||||||
|
const auto PTAIL = getGroupTail();
|
||||||
|
|
||||||
|
if (pWindow->m_sGroupData.pNextWindow) {
|
||||||
|
std::vector<CWindow*> members;
|
||||||
|
CWindow* curr = pWindow;
|
||||||
|
do {
|
||||||
|
const auto PLAST = curr;
|
||||||
|
members.push_back(curr);
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
PLAST->m_sGroupData.pNextWindow = nullptr;
|
||||||
|
PLAST->m_sGroupData.head = false;
|
||||||
|
} while (curr != pWindow);
|
||||||
|
|
||||||
|
for (auto& w : members) {
|
||||||
|
insertWindowToGroup(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PTAIL->m_sGroupData.pNextWindow = pWindow;
|
||||||
|
pWindow->m_sGroupData.pNextWindow = PHEAD;
|
||||||
|
|
||||||
|
setGroupCurrent(pWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::updateGroupOutputs() {
|
||||||
|
if (!m_sGroupData.pNextWindow)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CWindow* curr = m_sGroupData.pNextWindow;
|
||||||
|
|
||||||
|
while (curr != this) {
|
||||||
|
curr->m_iMonitorID = m_iMonitorID;
|
||||||
|
curr->moveToWorkspace(m_iWorkspaceID);
|
||||||
|
|
||||||
|
curr->m_vRealPosition = m_vRealPosition.goalv();
|
||||||
|
curr->m_vRealSize = m_vRealSize.goalv();
|
||||||
|
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D CWindow::middle() {
|
||||||
|
return m_vRealPosition.goalv() + m_vRealSize.goalv() / 2.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWindow::opaque() {
|
||||||
|
if (m_bIsX11)
|
||||||
|
return !m_uSurface.xwayland->has_alpha;
|
||||||
|
|
||||||
|
if (m_uSurface.xdg->surface->opaque)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
const auto EXTENTS = pixman_region32_extents(&m_uSurface.xdg->surface->opaque_region);
|
||||||
|
if (EXTENTS->x2 - EXTENTS->x1 >= m_uSurface.xdg->surface->current.buffer_width
|
||||||
|
&& EXTENTS->y2 - EXTENTS->y1 >= m_uSurface.xdg->surface->current.buffer_height)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
299
src/Window.hpp
299
src/Window.hpp
@@ -6,28 +6,137 @@
|
|||||||
#include "helpers/AnimatedVariable.hpp"
|
#include "helpers/AnimatedVariable.hpp"
|
||||||
#include "render/decorations/IHyprWindowDecoration.hpp"
|
#include "render/decorations/IHyprWindowDecoration.hpp"
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include "config/ConfigDataValues.hpp"
|
||||||
|
#include "helpers/Vector2D.hpp"
|
||||||
|
#include "helpers/WLSurface.hpp"
|
||||||
|
|
||||||
|
enum eIdleInhibitMode {
|
||||||
|
IDLEINHIBIT_NONE = 0,
|
||||||
|
IDLEINHIBIT_ALWAYS,
|
||||||
|
IDLEINHIBIT_FULLSCREEN,
|
||||||
|
IDLEINHIBIT_FOCUS
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class CWindowOverridableVar {
|
||||||
|
public:
|
||||||
|
CWindowOverridableVar(T val) {
|
||||||
|
value = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
~CWindowOverridableVar() = default;
|
||||||
|
|
||||||
|
CWindowOverridableVar<T>& operator=(CWindowOverridableVar<T> other) {
|
||||||
|
if (locked)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
locked = other.locked;
|
||||||
|
value = other.value;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator=(T& other) {
|
||||||
|
if (locked)
|
||||||
|
return value;
|
||||||
|
value = other;
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
|
void forceSetIgnoreLocked(T val, bool lock = false) {
|
||||||
|
value = val;
|
||||||
|
locked = lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator*(T& other) {
|
||||||
|
return value * other;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator+(T& other) {
|
||||||
|
return value + other;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(T& other) {
|
||||||
|
return other == value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>=(T& other) {
|
||||||
|
return value >= other;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<=(T& other) {
|
||||||
|
return value <= other;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>(T& other) {
|
||||||
|
return value > other;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(T& other) {
|
||||||
|
return value < other;
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit operator bool() {
|
||||||
|
return static_cast<bool>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
T toUnderlying() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool locked = false;
|
||||||
|
|
||||||
|
private:
|
||||||
|
T value;
|
||||||
|
};
|
||||||
|
|
||||||
struct SWindowSpecialRenderData {
|
struct SWindowSpecialRenderData {
|
||||||
float alpha = 1.f;
|
CWindowOverridableVar<bool> alphaOverride = false;
|
||||||
float alphaInactive = -1.f; // -1 means unset
|
CWindowOverridableVar<float> alpha = 1.f;
|
||||||
|
CWindowOverridableVar<bool> alphaInactiveOverride = false;
|
||||||
|
CWindowOverridableVar<float> alphaInactive = -1.f; // -1 means unset
|
||||||
|
|
||||||
|
CWindowOverridableVar<int64_t> activeBorderColor = -1; // -1 means unset
|
||||||
|
CWindowOverridableVar<int64_t> inactiveBorderColor = -1; // -1 means unset
|
||||||
|
|
||||||
// set by the layout
|
// set by the layout
|
||||||
bool rounding = true;
|
int borderSize = -1;
|
||||||
bool border = true;
|
bool rounding = true;
|
||||||
bool decorate = true;
|
bool border = true;
|
||||||
|
bool decorate = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SWindowAdditionalConfigData {
|
struct SWindowAdditionalConfigData {
|
||||||
std::string animationStyle = "";
|
std::string animationStyle = std::string("");
|
||||||
int rounding = -1; // -1 means no
|
CWindowOverridableVar<int> rounding = -1; // -1 means no
|
||||||
bool forceNoBlur = false;
|
CWindowOverridableVar<bool> forceNoBlur = false;
|
||||||
bool forceOpaque = false;
|
CWindowOverridableVar<bool> forceOpaque = false;
|
||||||
bool forceAllowsInput = false;
|
CWindowOverridableVar<bool> forceOpaqueOverridden = false; // if true, a rule will not change the forceOpaque state. This is for the force opaque dispatcher.
|
||||||
bool forceNoAnims = false;
|
CWindowOverridableVar<bool> forceAllowsInput = false;
|
||||||
|
CWindowOverridableVar<bool> forceNoAnims = false;
|
||||||
|
CWindowOverridableVar<bool> forceNoBorder = false;
|
||||||
|
CWindowOverridableVar<bool> forceNoShadow = false;
|
||||||
|
CWindowOverridableVar<bool> windowDanceCompat = false;
|
||||||
|
CWindowOverridableVar<bool> noMaxSize = false;
|
||||||
|
CWindowOverridableVar<bool> dimAround = false;
|
||||||
|
CWindowOverridableVar<bool> forceRGBX = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SWindowRule {
|
||||||
|
std::string szRule;
|
||||||
|
std::string szValue;
|
||||||
|
|
||||||
|
bool v2 = false;
|
||||||
|
std::string szTitle;
|
||||||
|
std::string szClass;
|
||||||
|
int bX11 = -1; // -1 means "ANY"
|
||||||
|
int bFloating = -1;
|
||||||
|
int bFullscreen = -1;
|
||||||
|
int bPinned = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CWindow {
|
class CWindow {
|
||||||
public:
|
public:
|
||||||
CWindow();
|
CWindow();
|
||||||
~CWindow();
|
~CWindow();
|
||||||
|
|
||||||
@@ -48,94 +157,109 @@ public:
|
|||||||
DYNLISTENER(toplevelClose);
|
DYNLISTENER(toplevelClose);
|
||||||
DYNLISTENER(toplevelActivate);
|
DYNLISTENER(toplevelActivate);
|
||||||
DYNLISTENER(toplevelFullscreen);
|
DYNLISTENER(toplevelFullscreen);
|
||||||
// DYNLISTENER(newSubsurfaceWindow);
|
DYNLISTENER(setOverrideRedirect);
|
||||||
|
// DYNLISTENER(newSubsurfaceWindow);
|
||||||
|
|
||||||
|
CWLSurface m_pWLSurface;
|
||||||
|
std::list<CWLSurface> m_lPopupSurfaces;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
wlr_xdg_surface* xdg;
|
wlr_xdg_surface* xdg;
|
||||||
wlr_xwayland_surface* xwayland;
|
wlr_xwayland_surface* xwayland;
|
||||||
} m_uSurface;
|
} m_uSurface;
|
||||||
|
|
||||||
// this is the position and size of the "bounding box"
|
// this is the position and size of the "bounding box"
|
||||||
Vector2D m_vPosition = Vector2D(0,0);
|
Vector2D m_vPosition = Vector2D(0, 0);
|
||||||
Vector2D m_vSize = Vector2D(0,0);
|
Vector2D m_vSize = Vector2D(0, 0);
|
||||||
|
|
||||||
// this is the real position and size used to draw the thing
|
// this is the real position and size used to draw the thing
|
||||||
CAnimatedVariable m_vRealPosition;
|
CAnimatedVariable m_vRealPosition;
|
||||||
CAnimatedVariable m_vRealSize;
|
CAnimatedVariable m_vRealSize;
|
||||||
|
|
||||||
// for not spamming the protocols
|
// for not spamming the protocols
|
||||||
Vector2D m_vReportedPosition;
|
Vector2D m_vReportedPosition;
|
||||||
Vector2D m_vReportedSize;
|
Vector2D m_vReportedSize;
|
||||||
|
|
||||||
// for restoring floating statuses
|
// for restoring floating statuses
|
||||||
Vector2D m_vLastFloatingSize;
|
Vector2D m_vLastFloatingSize;
|
||||||
|
Vector2D m_vLastFloatingPosition;
|
||||||
|
|
||||||
// this is used for pseudotiling
|
// this is used for pseudotiling
|
||||||
bool m_bIsPseudotiled = false;
|
bool m_bIsPseudotiled = false;
|
||||||
Vector2D m_vPseudoSize = Vector2D(0,0);
|
Vector2D m_vPseudoSize = Vector2D(0, 0);
|
||||||
|
|
||||||
uint64_t m_iTags = 0;
|
uint64_t m_iTags = 0;
|
||||||
bool m_bIsFloating = false;
|
bool m_bIsFloating = false;
|
||||||
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
bool m_bDraggingTiled = false; // for dragging around tiled windows
|
||||||
bool m_bIsFullscreen = false;
|
bool m_bIsFullscreen = false;
|
||||||
uint64_t m_iMonitorID = -1;
|
bool m_bWasMaximized = false;
|
||||||
std::string m_szTitle = "";
|
uint64_t m_iMonitorID = -1;
|
||||||
int m_iWorkspaceID = -1;
|
std::string m_szTitle = "";
|
||||||
|
std::string m_szInitialTitle = "";
|
||||||
|
std::string m_szInitialClass = "";
|
||||||
|
int m_iWorkspaceID = -1;
|
||||||
|
|
||||||
bool m_bIsMapped = false;
|
bool m_bIsMapped = false;
|
||||||
|
|
||||||
bool m_bRequestsFloat = false;
|
bool m_bRequestsFloat = false;
|
||||||
|
|
||||||
// This is for fullscreen apps
|
// This is for fullscreen apps
|
||||||
bool m_bCreatedOverFullscreen = false;
|
bool m_bCreatedOverFullscreen = false;
|
||||||
|
|
||||||
// XWayland stuff
|
// XWayland stuff
|
||||||
bool m_bIsX11 = false;
|
bool m_bIsX11 = false;
|
||||||
bool m_bMappedX11 = false;
|
bool m_bMappedX11 = false;
|
||||||
CWindow* m_pX11Parent = nullptr;
|
CWindow* m_pX11Parent = nullptr;
|
||||||
uint64_t m_iX11Type = 0;
|
uint64_t m_iX11Type = 0;
|
||||||
bool m_bIsModal = false;
|
bool m_bIsModal = false;
|
||||||
bool m_bX11DoesntWantBorders = false;
|
bool m_bX11DoesntWantBorders = false;
|
||||||
bool m_bX11ShouldntFocus = false;
|
bool m_bX11ShouldntFocus = false;
|
||||||
//
|
//
|
||||||
|
|
||||||
// For nofocus
|
// For nofocus
|
||||||
bool m_bNoFocus = false;
|
bool m_bNoFocus = false;
|
||||||
bool m_bNoInitialFocus = false;
|
bool m_bNoInitialFocus = false;
|
||||||
|
|
||||||
// initial fullscreen
|
// initial fullscreen and fullscreen disabled
|
||||||
bool m_bWantsInitialFullscreen = false;
|
bool m_bWantsInitialFullscreen = false;
|
||||||
|
bool m_bNoFullscreenRequest = false;
|
||||||
|
|
||||||
SSurfaceTreeNode* m_pSurfaceTree = nullptr;
|
SSurfaceTreeNode* m_pSurfaceTree = nullptr;
|
||||||
|
|
||||||
// Animated border
|
// Animated border
|
||||||
CAnimatedVariable m_cRealBorderColor;
|
CGradientValueData m_cRealBorderColor = {0};
|
||||||
|
CGradientValueData m_cRealBorderColorPrevious = {0};
|
||||||
|
CAnimatedVariable m_fBorderFadeAnimationProgress;
|
||||||
|
CAnimatedVariable m_fBorderAngleAnimationProgress;
|
||||||
|
|
||||||
// Fade in-out
|
// Fade in-out
|
||||||
CAnimatedVariable m_fAlpha;
|
CAnimatedVariable m_fAlpha;
|
||||||
bool m_bFadingOut = false;
|
bool m_bFadingOut = false;
|
||||||
bool m_bReadyToDelete = false;
|
bool m_bReadyToDelete = false;
|
||||||
Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in
|
Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in
|
||||||
Vector2D m_vOriginalClosedSize; // drawing the closing animations
|
Vector2D m_vOriginalClosedSize; // drawing the closing animations
|
||||||
|
|
||||||
// For hidden windows and stuff
|
|
||||||
bool m_bHidden = false;
|
|
||||||
|
|
||||||
// For pinned (sticky) windows
|
// For pinned (sticky) windows
|
||||||
bool m_bPinned = false;
|
bool m_bPinned = false;
|
||||||
|
|
||||||
|
// urgency hint
|
||||||
|
bool m_bIsUrgent = false;
|
||||||
|
|
||||||
|
// fakefullscreen
|
||||||
|
bool m_bFakeFullscreenState = false;
|
||||||
|
|
||||||
// for proper cycling. While cycling we can't just move the pointers, so we need to keep track of the last cycled window.
|
// for proper cycling. While cycling we can't just move the pointers, so we need to keep track of the last cycled window.
|
||||||
CWindow* m_pLastCycledWindow = nullptr;
|
CWindow* m_pLastCycledWindow = nullptr;
|
||||||
|
|
||||||
// Foreign Toplevel proto
|
// Foreign Toplevel proto
|
||||||
wlr_foreign_toplevel_handle_v1* m_phForeignToplevel = nullptr;
|
wlr_foreign_toplevel_handle_v1* m_phForeignToplevel = nullptr;
|
||||||
|
|
||||||
// Window decorations
|
// Window decorations
|
||||||
std::deque<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
|
std::deque<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
|
||||||
std::vector<IHyprWindowDecoration*> m_vDecosToRemove;
|
std::vector<IHyprWindowDecoration*> m_vDecosToRemove;
|
||||||
|
|
||||||
// Special render data, rules, etc
|
// Special render data, rules, etc
|
||||||
SWindowSpecialRenderData m_sSpecialRenderData;
|
SWindowSpecialRenderData m_sSpecialRenderData;
|
||||||
SWindowAdditionalConfigData m_sAdditionalConfigData;
|
SWindowAdditionalConfigData m_sAdditionalConfigData;
|
||||||
|
|
||||||
// for alpha
|
// for alpha
|
||||||
@@ -148,28 +272,63 @@ public:
|
|||||||
CAnimatedVariable m_fDimPercent;
|
CAnimatedVariable m_fDimPercent;
|
||||||
|
|
||||||
// swallowing
|
// swallowing
|
||||||
CWindow* m_pSwallowed = nullptr;
|
CWindow* m_pSwallowed = nullptr;
|
||||||
|
|
||||||
// for toplevel monitor events
|
// for toplevel monitor events
|
||||||
uint64_t m_iLastToplevelMonitorID = -1;
|
uint64_t m_iLastToplevelMonitorID = -1;
|
||||||
uint64_t m_iLastSurfaceMonitorID = -1;
|
uint64_t m_iLastSurfaceMonitorID = -1;
|
||||||
|
|
||||||
|
// for idle inhibiting windows
|
||||||
|
eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
||||||
|
|
||||||
|
// for groups
|
||||||
|
struct SGroupData {
|
||||||
|
CWindow* pNextWindow = nullptr; // nullptr means no grouping. Self means single group.
|
||||||
|
bool head = false;
|
||||||
|
} m_sGroupData;
|
||||||
|
|
||||||
// For the list lookup
|
// For the list lookup
|
||||||
bool operator==(const CWindow& rhs) {
|
bool operator==(const CWindow& rhs) {
|
||||||
return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && m_bFadingOut == rhs.m_bFadingOut;
|
return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize &&
|
||||||
|
m_bFadingOut == rhs.m_bFadingOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
wlr_box getFullWindowBoundingBox();
|
wlr_box getFullWindowBoundingBox();
|
||||||
wlr_box getWindowIdealBoundingBoxIgnoreReserved();
|
wlr_box getWindowInputBox();
|
||||||
void updateWindowDecos();
|
wlr_box getWindowIdealBoundingBoxIgnoreReserved();
|
||||||
pid_t getPID();
|
void updateWindowDecos();
|
||||||
IHyprWindowDecoration* getDecorationByType(eDecorationType);
|
pid_t getPID();
|
||||||
void removeDecorationByType(eDecorationType);
|
IHyprWindowDecoration* getDecorationByType(eDecorationType);
|
||||||
void createToplevelHandle();
|
void removeDecorationByType(eDecorationType);
|
||||||
void destroyToplevelHandle();
|
void createToplevelHandle();
|
||||||
void updateToplevel();
|
void destroyToplevelHandle();
|
||||||
void updateSurfaceOutputs();
|
void updateToplevel();
|
||||||
void moveToWorkspace(int);
|
void updateSurfaceOutputs();
|
||||||
CWindow* X11TransientFor();
|
void moveToWorkspace(int);
|
||||||
|
CWindow* X11TransientFor();
|
||||||
|
void onUnmap();
|
||||||
|
void onMap();
|
||||||
|
void setHidden(bool hidden);
|
||||||
|
bool isHidden();
|
||||||
|
void applyDynamicRule(const SWindowRule& r);
|
||||||
|
void updateDynamicRules();
|
||||||
|
SWindowDecorationExtents getFullWindowReservedArea();
|
||||||
|
Vector2D middle();
|
||||||
|
bool opaque();
|
||||||
|
|
||||||
|
void onBorderAngleAnimEnd(void* ptr);
|
||||||
|
bool isInCurvedCorner(double x, double y);
|
||||||
|
bool hasPopupAt(const Vector2D& pos);
|
||||||
|
|
||||||
|
CWindow* getGroupHead();
|
||||||
|
CWindow* getGroupTail();
|
||||||
|
CWindow* getGroupCurrent();
|
||||||
|
void setGroupCurrent(CWindow* pWindow);
|
||||||
|
void insertWindowToGroup(CWindow* pWindow);
|
||||||
|
void updateGroupOutputs();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// For hidden windows and stuff
|
||||||
|
bool m_bHidden = false;
|
||||||
};
|
};
|
||||||
|
|||||||
51
src/config/ConfigDataValues.hpp
Normal file
51
src/config/ConfigDataValues.hpp
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../defines.hpp"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
enum eConfigValueDataTypes
|
||||||
|
{
|
||||||
|
CVD_TYPE_INVALID = -1,
|
||||||
|
CVD_TYPE_GRADIENT = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
interface ICustomConfigValueData {
|
||||||
|
public:
|
||||||
|
virtual ~ICustomConfigValueData() = 0;
|
||||||
|
|
||||||
|
virtual eConfigValueDataTypes getDataType() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CGradientValueData : public ICustomConfigValueData {
|
||||||
|
public:
|
||||||
|
CGradientValueData(CColor col) {
|
||||||
|
m_vColors.push_back(col);
|
||||||
|
};
|
||||||
|
virtual ~CGradientValueData(){};
|
||||||
|
|
||||||
|
virtual eConfigValueDataTypes getDataType() {
|
||||||
|
return CVD_TYPE_GRADIENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(CColor col) {
|
||||||
|
m_vColors.clear();
|
||||||
|
m_vColors.emplace_back(col);
|
||||||
|
m_fAngle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Vector containing the colors */
|
||||||
|
std::vector<CColor> m_vColors;
|
||||||
|
|
||||||
|
/* Float corresponding to the angle (rad) */
|
||||||
|
float m_fAngle = 0;
|
||||||
|
|
||||||
|
bool operator==(const CGradientValueData& other) {
|
||||||
|
if (other.m_vColors.size() != m_vColors.size() || m_fAngle != other.m_fAngle)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < m_vColors.size(); ++i)
|
||||||
|
if (m_vColors[i] != other.m_vColors[i])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -10,81 +10,94 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
#include <optional>
|
||||||
#include "../Window.hpp"
|
#include "../Window.hpp"
|
||||||
|
#include "../helpers/WLClasses.hpp"
|
||||||
|
|
||||||
#include "defaultConfig.hpp"
|
#include "defaultConfig.hpp"
|
||||||
|
#include "ConfigDataValues.hpp"
|
||||||
|
|
||||||
#define STRVAL_EMPTY "[[EMPTY]]"
|
#define STRVAL_EMPTY "[[EMPTY]]"
|
||||||
|
|
||||||
#define INITANIMCFG(name) animationConfig[name] = {}
|
#define INITANIMCFG(name) animationConfig[name] = {}
|
||||||
#define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]}
|
#define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]}
|
||||||
|
|
||||||
struct SConfigValue {
|
#define HANDLE void*
|
||||||
int64_t intValue = -INT64_MAX;
|
|
||||||
float floatValue = -__FLT_MAX__;
|
|
||||||
std::string strValue = "";
|
|
||||||
Vector2D vecValue = Vector2D(-__FLT_MAX__, -__FLT_MAX__);
|
|
||||||
|
|
||||||
bool set = false; // used for device configs
|
struct SConfigValue {
|
||||||
|
int64_t intValue = -INT64_MAX;
|
||||||
|
float floatValue = -__FLT_MAX__;
|
||||||
|
std::string strValue = "";
|
||||||
|
Vector2D vecValue = Vector2D(-__FLT_MAX__, -__FLT_MAX__);
|
||||||
|
std::shared_ptr<ICustomConfigValueData> data;
|
||||||
|
|
||||||
|
bool set = false; // used for device configs
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SMonitorRule {
|
struct SMonitorRule {
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
Vector2D resolution = Vector2D(1280,720);
|
Vector2D resolution = Vector2D(1280, 720);
|
||||||
Vector2D offset = Vector2D(0,0);
|
Vector2D offset = Vector2D(0, 0);
|
||||||
float scale = 1;
|
float scale = 1;
|
||||||
float refreshRate = 60;
|
float refreshRate = 60;
|
||||||
std::string defaultWorkspace = "";
|
bool disabled = false;
|
||||||
bool disabled = false;
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
std::string mirrorOf = "";
|
||||||
std::string mirrorOf = "";
|
bool enable10bit = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SWorkspaceRule {
|
||||||
|
std::string monitor = "";
|
||||||
|
std::string workspaceString = "";
|
||||||
|
std::string workspaceName = "";
|
||||||
|
int workspaceId = -1;
|
||||||
|
std::optional<int64_t> gapsIn;
|
||||||
|
std::optional<int64_t> gapsOut;
|
||||||
|
std::optional<int64_t> borderSize;
|
||||||
|
std::optional<int> border;
|
||||||
|
std::optional<int> rounding;
|
||||||
|
std::optional<int> decorate;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SMonitorAdditionalReservedArea {
|
struct SMonitorAdditionalReservedArea {
|
||||||
int top = 0;
|
int top = 0;
|
||||||
int bottom = 0;
|
int bottom = 0;
|
||||||
int left = 0;
|
int left = 0;
|
||||||
int right = 0;
|
int right = 0;
|
||||||
};
|
|
||||||
|
|
||||||
struct SWindowRule {
|
|
||||||
std::string szRule;
|
|
||||||
std::string szValue;
|
|
||||||
|
|
||||||
bool v2 = false;
|
|
||||||
std::string szTitle;
|
|
||||||
std::string szClass;
|
|
||||||
int bX11 = -1; // -1 means "ANY"
|
|
||||||
int bFloating = -1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SAnimationPropertyConfig {
|
struct SAnimationPropertyConfig {
|
||||||
bool overriden = true;
|
bool overridden = true;
|
||||||
|
|
||||||
std::string internalBezier = "";
|
std::string internalBezier = "";
|
||||||
std::string internalStyle = "";
|
std::string internalStyle = "";
|
||||||
float internalSpeed = 0.f;
|
float internalSpeed = 0.f;
|
||||||
int internalEnabled = -1;
|
int internalEnabled = -1;
|
||||||
|
|
||||||
SAnimationPropertyConfig* pValues = nullptr;
|
SAnimationPropertyConfig* pValues = nullptr;
|
||||||
SAnimationPropertyConfig* pParentAnimation = nullptr;
|
SAnimationPropertyConfig* pParentAnimation = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CVarList {
|
struct SExecRequestedRule {
|
||||||
public:
|
std::string szRule = "";
|
||||||
CVarList(const std::string& in, long unsigned int lastArgNo = 0) {
|
uint64_t iPid = 0;
|
||||||
std::string curitem = "";
|
};
|
||||||
std::string argZ = in;
|
|
||||||
|
|
||||||
auto nextItem = [&]() {
|
class CVarList {
|
||||||
auto idx = lastArgNo != 0 && m_vArgs.size() >= lastArgNo - 1 ? std::string::npos : argZ.find_first_of(',');
|
public:
|
||||||
|
CVarList(const std::string& in, long unsigned int lastArgNo = 0, const char separator = ',') {
|
||||||
|
std::string curitem = "";
|
||||||
|
std::string argZ = in;
|
||||||
|
|
||||||
|
auto nextItem = [&]() {
|
||||||
|
auto idx = lastArgNo != 0 && m_vArgs.size() >= lastArgNo - 1 ? std::string::npos : argZ.find_first_of(separator);
|
||||||
|
|
||||||
if (idx != std::string::npos) {
|
if (idx != std::string::npos) {
|
||||||
curitem = argZ.substr(0, idx);
|
curitem = argZ.substr(0, idx);
|
||||||
argZ = argZ.substr(idx + 1);
|
argZ = argZ.substr(idx + 1);
|
||||||
} else {
|
} else {
|
||||||
curitem = argZ;
|
curitem = argZ;
|
||||||
argZ = STRVAL_EMPTY;
|
argZ = STRVAL_EMPTY;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -98,7 +111,7 @@ public:
|
|||||||
|
|
||||||
~CVarList() = default;
|
~CVarList() = default;
|
||||||
|
|
||||||
int size() const {
|
size_t size() const {
|
||||||
return m_vArgs.size();
|
return m_vArgs.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,111 +121,154 @@ public:
|
|||||||
return m_vArgs[idx];
|
return m_vArgs[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
// for range-based loops
|
||||||
|
std::vector<std::string>::iterator begin() {
|
||||||
|
return m_vArgs.begin();
|
||||||
|
}
|
||||||
|
std::vector<std::string>::const_iterator begin() const {
|
||||||
|
return m_vArgs.begin();
|
||||||
|
}
|
||||||
|
std::vector<std::string>::iterator end() {
|
||||||
|
return m_vArgs.end();
|
||||||
|
}
|
||||||
|
std::vector<std::string>::const_iterator end() const {
|
||||||
|
return m_vArgs.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
std::vector<std::string> m_vArgs;
|
std::vector<std::string> m_vArgs;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CConfigManager {
|
class CConfigManager {
|
||||||
public:
|
public:
|
||||||
CConfigManager();
|
CConfigManager();
|
||||||
|
|
||||||
void tick();
|
void tick();
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
int getInt(const std::string&);
|
int getInt(const std::string&);
|
||||||
float getFloat(const std::string&);
|
float getFloat(const std::string&);
|
||||||
std::string getString(const std::string&);
|
std::string getString(const std::string&);
|
||||||
void setFloat(std::string, float);
|
void setFloat(const std::string&, float);
|
||||||
void setInt(std::string, int);
|
void setInt(const std::string&, int);
|
||||||
void setString(std::string, std::string);
|
void setString(const std::string&, const std::string&);
|
||||||
|
|
||||||
int getDeviceInt(const std::string&, const std::string&);
|
int getDeviceInt(const std::string&, const std::string&);
|
||||||
float getDeviceFloat(const std::string&, const std::string&);
|
float getDeviceFloat(const std::string&, const std::string&);
|
||||||
std::string getDeviceString(const std::string&, const std::string&);
|
std::string getDeviceString(const std::string&, const std::string&);
|
||||||
bool deviceConfigExists(const std::string&);
|
bool deviceConfigExists(const std::string&);
|
||||||
bool shouldBlurLS(const std::string&);
|
bool shouldBlurLS(const std::string&);
|
||||||
|
|
||||||
SConfigValue* getConfigValuePtr(std::string);
|
SConfigValue* getConfigValuePtr(const std::string&);
|
||||||
SConfigValue* getConfigValuePtrSafe(std::string);
|
SConfigValue* getConfigValuePtrSafe(const std::string&);
|
||||||
|
|
||||||
SMonitorRule getMonitorRuleFor(std::string, std::string displayName = "");
|
SMonitorRule getMonitorRuleFor(const std::string&, const std::string& displayName = "");
|
||||||
|
SWorkspaceRule getWorkspaceRuleFor(CWorkspace*);
|
||||||
|
std::string getDefaultWorkspaceFor(const std::string&);
|
||||||
|
|
||||||
CMonitor* getBoundMonitorForWS(std::string);
|
CMonitor* getBoundMonitorForWS(const std::string&);
|
||||||
|
std::string getBoundMonitorStringForWS(const std::string&);
|
||||||
|
|
||||||
std::vector<SWindowRule> getMatchingRules(CWindow*);
|
std::vector<SWindowRule> getMatchingRules(CWindow*);
|
||||||
|
std::vector<SLayerRule> getMatchingRules(SLayerSurface*);
|
||||||
|
|
||||||
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
|
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, SAnimationPropertyConfig> getAnimationConfig();
|
||||||
|
|
||||||
|
void addPluginConfigVar(HANDLE handle, const std::string& name, const SConfigValue& value);
|
||||||
|
void removePluginConfig(HANDLE handle);
|
||||||
|
|
||||||
// no-op when done.
|
// no-op when done.
|
||||||
void dispatchExecOnce();
|
void dispatchExecOnce();
|
||||||
|
|
||||||
void performMonitorReload();
|
void performMonitorReload();
|
||||||
bool m_bWantsMonitorReload = false;
|
bool m_bWantsMonitorReload = false;
|
||||||
bool m_bForceReload = false;
|
bool m_bForceReload = false;
|
||||||
bool m_bNoMonitorReload = false;
|
bool m_bNoMonitorReload = false;
|
||||||
void ensureDPMS();
|
void ensureMonitorStatus();
|
||||||
|
void ensureVRR(CMonitor* pMonitor = nullptr);
|
||||||
|
|
||||||
std::string parseKeyword(const std::string&, const std::string&, bool dynamic = false);
|
std::string parseKeyword(const std::string&, const std::string&, bool dynamic = false);
|
||||||
|
|
||||||
void addParseError(const std::string&);
|
void addParseError(const std::string&);
|
||||||
|
|
||||||
SAnimationPropertyConfig* getAnimationPropertyConfig(const std::string&);
|
SAnimationPropertyConfig* getAnimationPropertyConfig(const std::string&);
|
||||||
|
|
||||||
std::string configCurrentPath;
|
void addExecRule(const SExecRequestedRule&);
|
||||||
|
|
||||||
private:
|
void handlePluginLoads();
|
||||||
std::deque<std::string> configPaths; // stores all the config paths
|
|
||||||
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
|
|
||||||
std::unordered_map<std::string, std::string> configDynamicVars; // stores dynamic vars declared by the user
|
|
||||||
std::unordered_map<std::string, SConfigValue> configValues;
|
|
||||||
std::unordered_map<std::string, std::unordered_map<std::string, SConfigValue>> deviceConfigs; // stores device configs
|
|
||||||
|
|
||||||
std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values
|
std::string configCurrentPath;
|
||||||
|
|
||||||
std::string currentCategory = ""; // For storing the category of the current item
|
private:
|
||||||
|
std::deque<std::string> configPaths; // stores all the config paths
|
||||||
|
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
|
||||||
|
std::vector<std::pair<std::string, std::string>> configDynamicVars; // stores dynamic vars declared by the user
|
||||||
|
std::unordered_map<std::string, SConfigValue> configValues;
|
||||||
|
std::unordered_map<std::string, std::unordered_map<std::string, SConfigValue>> deviceConfigs; // stores device configs
|
||||||
|
|
||||||
std::string parseError = ""; // For storing a parse error to display later
|
std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values
|
||||||
|
|
||||||
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
|
std::string currentCategory = ""; // For storing the category of the current item
|
||||||
|
|
||||||
std::vector<std::pair<std::string, std::string>> boundWorkspaces;
|
std::string parseError = ""; // For storing a parse error to display later
|
||||||
|
|
||||||
bool isFirstLaunch = true; // For exec-once
|
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
|
||||||
|
|
||||||
std::deque<SMonitorRule> m_dMonitorRules;
|
std::vector<std::pair<std::string, std::string>> boundWorkspaces;
|
||||||
std::deque<SWindowRule> m_dWindowRules;
|
|
||||||
std::deque<std::string> m_dBlurLSNamespaces;
|
|
||||||
|
|
||||||
bool firstExecDispatched = false;
|
std::vector<SExecRequestedRule> execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty
|
||||||
std::deque<std::string> firstExecRequests;
|
|
||||||
|
std::vector<std::string> m_vDeclaredPlugins;
|
||||||
|
std::unordered_map<HANDLE, std::unique_ptr<std::unordered_map<std::string, SConfigValue>>> pluginConfigs; // stores plugin configs
|
||||||
|
|
||||||
|
bool isFirstLaunch = true; // For exec-once
|
||||||
|
|
||||||
|
std::deque<SMonitorRule> m_dMonitorRules;
|
||||||
|
std::unordered_map<int, SWorkspaceRule> m_mWorkspaceRules;
|
||||||
|
std::deque<SWindowRule> m_dWindowRules;
|
||||||
|
std::deque<SLayerRule> m_dLayerRules;
|
||||||
|
std::deque<std::string> m_dBlurLSNamespaces;
|
||||||
|
|
||||||
|
bool firstExecDispatched = false;
|
||||||
|
bool m_bManualCrashInitiated = false;
|
||||||
|
std::deque<std::string> firstExecRequests;
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> environmentVariables;
|
||||||
|
|
||||||
// internal methods
|
// internal methods
|
||||||
void setDefaultVars();
|
void setDefaultVars();
|
||||||
void setDefaultAnimationVars();
|
void setDefaultAnimationVars();
|
||||||
void setDeviceDefaultVars(const std::string&);
|
void setDeviceDefaultVars(const std::string&);
|
||||||
|
void populateEnvironment();
|
||||||
|
|
||||||
void setAnimForChildren(SAnimationPropertyConfig *const);
|
void setAnimForChildren(SAnimationPropertyConfig* const);
|
||||||
|
void updateBlurredLS(const std::string&, const bool);
|
||||||
|
|
||||||
void applyUserDefinedVars(std::string&, const size_t);
|
void applyUserDefinedVars(std::string&, const size_t);
|
||||||
void loadConfigLoadVars();
|
void loadConfigLoadVars();
|
||||||
SConfigValue getConfigValueSafe(const std::string&);
|
SConfigValue getConfigValueSafe(const std::string&);
|
||||||
SConfigValue getConfigValueSafeDevice(const std::string&, const std::string&);
|
SConfigValue getConfigValueSafeDevice(const std::string&, const std::string&);
|
||||||
void parseLine(std::string&);
|
void parseLine(std::string&);
|
||||||
void configSetValueSafe(const std::string&, const std::string&);
|
void configSetValueSafe(const std::string&, const std::string&);
|
||||||
void handleDeviceConfig(const std::string&, const std::string&);
|
void handleDeviceConfig(const std::string&, const std::string&);
|
||||||
void handleRawExec(const std::string&, const std::string&);
|
void handleRawExec(const std::string&, const std::string&);
|
||||||
void handleMonitor(const std::string&, const std::string&);
|
void handleMonitor(const std::string&, const std::string&);
|
||||||
void handleBind(const std::string&, const std::string&);
|
void handleBind(const std::string&, const std::string&);
|
||||||
void handleUnbind(const std::string&, const std::string&);
|
void handleUnbind(const std::string&, const std::string&);
|
||||||
void handleWindowRule(const std::string&, const std::string&);
|
void handleWindowRule(const std::string&, const std::string&);
|
||||||
void handleWindowRuleV2(const std::string&, const std::string&);
|
void handleLayerRule(const std::string&, const std::string&);
|
||||||
void handleDefaultWorkspace(const std::string&, const std::string&);
|
void handleWindowRuleV2(const std::string&, const std::string&);
|
||||||
void handleBezier(const std::string&, const std::string&);
|
void handleWorkspaceRules(const std::string&, const std::string&);
|
||||||
void handleAnimation(const std::string&, const std::string&);
|
void handleBezier(const std::string&, const std::string&);
|
||||||
void handleSource(const std::string&, const std::string&);
|
void handleAnimation(const std::string&, const std::string&);
|
||||||
void handleSubmap(const std::string&, const std::string&);
|
void handleSource(const std::string&, const std::string&);
|
||||||
void handleBlurLS(const std::string&, const std::string&);
|
void handleSubmap(const std::string&, const std::string&);
|
||||||
void handleBindWS(const std::string&, const std::string&);
|
void handleBlurLS(const std::string&, const std::string&);
|
||||||
|
void handleBindWS(const std::string&, const std::string&);
|
||||||
|
void handleEnv(const std::string&, const std::string&);
|
||||||
|
void handlePlugin(const std::string&, const std::string&);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
||||||
|
|||||||
@@ -9,121 +9,164 @@ PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
|
|||||||
OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
|
OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
|
||||||
########################################################################################
|
########################################################################################
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Please note not all available settings / options are set here.
|
# Please note not all available settings / options are set here.
|
||||||
# For a full list, see the wiki (basic and advanced configuring)
|
# For a full list, see the wiki
|
||||||
#
|
#
|
||||||
|
|
||||||
autogenerated=1 # remove this line to get rid of the warning on top.
|
autogenerated = 1 # remove this line to remove the warning
|
||||||
|
|
||||||
monitor=,preferred,auto,1
|
# See https://wiki.hyprland.org/Configuring/Monitors/
|
||||||
|
monitor=,preferred,auto,auto
|
||||||
|
|
||||||
|
|
||||||
|
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||||
|
|
||||||
|
# Execute your favorite apps at launch
|
||||||
|
# exec-once = waybar & hyprpaper & firefox
|
||||||
|
|
||||||
|
# Source a file (multi-file configs)
|
||||||
|
# source = ~/.config/hypr/myColors.conf
|
||||||
|
|
||||||
|
# Some default env vars.
|
||||||
|
env = XCURSOR_SIZE,24
|
||||||
|
|
||||||
|
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
|
||||||
input {
|
input {
|
||||||
kb_file=
|
kb_layout = us
|
||||||
kb_layout=
|
kb_variant =
|
||||||
kb_variant=
|
kb_model =
|
||||||
kb_model=
|
kb_options =
|
||||||
kb_options=
|
kb_rules =
|
||||||
kb_rules=
|
|
||||||
|
|
||||||
follow_mouse=1
|
follow_mouse = 1
|
||||||
|
|
||||||
touchpad {
|
touchpad {
|
||||||
natural_scroll=no
|
natural_scroll = no
|
||||||
}
|
}
|
||||||
|
|
||||||
sensitivity=0 # -1.0 - 1.0, 0 means no modification.
|
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
|
||||||
}
|
}
|
||||||
|
|
||||||
general {
|
general {
|
||||||
main_mod=SUPER
|
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||||
|
|
||||||
gaps_in=5
|
gaps_in = 5
|
||||||
gaps_out=20
|
gaps_out = 20
|
||||||
border_size=2
|
border_size = 2
|
||||||
col.active_border=0x66ee1111
|
col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
|
||||||
col.inactive_border=0x66333333
|
col.inactive_border = rgba(595959aa)
|
||||||
|
|
||||||
apply_sens_to_raw=0 # whether to apply the sensitivity to raw input (e.g. used by games where you aim using your mouse)
|
layout = dwindle
|
||||||
|
|
||||||
damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
decoration {
|
decoration {
|
||||||
rounding=10
|
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||||
blur=1
|
|
||||||
blur_size=3 # minimum 1
|
rounding = 10
|
||||||
blur_passes=1 # minimum 1
|
blur = yes
|
||||||
blur_new_optimizations=1
|
blur_size = 3
|
||||||
|
blur_passes = 1
|
||||||
|
blur_new_optimizations = on
|
||||||
|
|
||||||
|
drop_shadow = yes
|
||||||
|
shadow_range = 4
|
||||||
|
shadow_render_power = 3
|
||||||
|
col.shadow = rgba(1a1a1aee)
|
||||||
}
|
}
|
||||||
|
|
||||||
animations {
|
animations {
|
||||||
enabled=1
|
enabled = yes
|
||||||
animation=windows,1,7,default
|
|
||||||
animation=border,1,10,default
|
# Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
|
||||||
animation=fade,1,10,default
|
|
||||||
animation=workspaces,1,6,default
|
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
|
||||||
|
|
||||||
|
animation = windows, 1, 7, myBezier
|
||||||
|
animation = windowsOut, 1, 7, default, popin 80%
|
||||||
|
animation = border, 1, 10, default
|
||||||
|
animation = borderangle, 1, 8, default
|
||||||
|
animation = fade, 1, 7, default
|
||||||
|
animation = workspaces, 1, 6, default
|
||||||
}
|
}
|
||||||
|
|
||||||
dwindle {
|
dwindle {
|
||||||
pseudotile=0 # enable pseudotiling on 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
|
||||||
|
}
|
||||||
|
|
||||||
|
master {
|
||||||
|
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
|
||||||
|
new_is_master = true
|
||||||
}
|
}
|
||||||
|
|
||||||
gestures {
|
gestures {
|
||||||
workspace_swipe=no
|
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||||
|
workspace_swipe = off
|
||||||
}
|
}
|
||||||
|
|
||||||
# example window rules
|
# Example per-device config
|
||||||
# for windows named/classed as abc and xyz
|
# See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
|
||||||
#windowrule=move 69 420,abc
|
device:epic-mouse-v1 {
|
||||||
#windowrule=size 420 69,abc
|
sensitivity = -0.5
|
||||||
#windowrule=tile,xyz
|
}
|
||||||
#windowrule=float,abc
|
|
||||||
#windowrule=pseudo,abc
|
|
||||||
#windowrule=monitor 0,xyz
|
|
||||||
|
|
||||||
# some nice mouse binds
|
# Example windowrule v1
|
||||||
bindm=SUPER,mouse:272,movewindow
|
# windowrule = float, ^(kitty)$
|
||||||
bindm=SUPER,mouse:273,resizewindow
|
# Example windowrule v2
|
||||||
|
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||||
|
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||||
|
|
||||||
# example binds
|
|
||||||
bind=SUPER,Q,exec,kitty
|
|
||||||
bind=SUPER,RETURN,exec,alacritty
|
|
||||||
bind=SUPER,C,killactive,
|
|
||||||
bind=SUPER,M,exit,
|
|
||||||
bind=SUPER,E,exec,dolphin
|
|
||||||
bind=SUPER,V,togglefloating,
|
|
||||||
bind=SUPER,R,exec,wofi --show drun -o DP-3
|
|
||||||
bind=SUPER,P,pseudo,
|
|
||||||
|
|
||||||
bind=SUPER,left,movefocus,l
|
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||||
bind=SUPER,right,movefocus,r
|
$mainMod = SUPER
|
||||||
bind=SUPER,up,movefocus,u
|
|
||||||
bind=SUPER,down,movefocus,d
|
|
||||||
|
|
||||||
bind=SUPER,1,workspace,1
|
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
|
||||||
bind=SUPER,2,workspace,2
|
bind = $mainMod, Q, exec, kitty
|
||||||
bind=SUPER,3,workspace,3
|
bind = $mainMod, C, killactive,
|
||||||
bind=SUPER,4,workspace,4
|
bind = $mainMod, M, exit,
|
||||||
bind=SUPER,5,workspace,5
|
bind = $mainMod, E, exec, dolphin
|
||||||
bind=SUPER,6,workspace,6
|
bind = $mainMod, V, togglefloating,
|
||||||
bind=SUPER,7,workspace,7
|
bind = $mainMod, R, exec, wofi --show drun
|
||||||
bind=SUPER,8,workspace,8
|
bind = $mainMod, P, pseudo, # dwindle
|
||||||
bind=SUPER,9,workspace,9
|
bind = $mainMod, J, togglesplit, # dwindle
|
||||||
bind=SUPER,0,workspace,10
|
|
||||||
|
|
||||||
bind=ALT,1,movetoworkspace,1
|
# Move focus with mainMod + arrow keys
|
||||||
bind=ALT,2,movetoworkspace,2
|
bind = $mainMod, left, movefocus, l
|
||||||
bind=ALT,3,movetoworkspace,3
|
bind = $mainMod, right, movefocus, r
|
||||||
bind=ALT,4,movetoworkspace,4
|
bind = $mainMod, up, movefocus, u
|
||||||
bind=ALT,5,movetoworkspace,5
|
bind = $mainMod, down, movefocus, d
|
||||||
bind=ALT,6,movetoworkspace,6
|
|
||||||
bind=ALT,7,movetoworkspace,7
|
|
||||||
bind=ALT,8,movetoworkspace,8
|
|
||||||
bind=ALT,9,movetoworkspace,9
|
|
||||||
bind=ALT,0,movetoworkspace,10
|
|
||||||
|
|
||||||
bind=SUPER,mouse_down,workspace,e+1
|
# Switch workspaces with mainMod + [0-9]
|
||||||
bind=SUPER,mouse_up,workspace,e-1
|
bind = $mainMod, 1, workspace, 1
|
||||||
|
bind = $mainMod, 2, workspace, 2
|
||||||
|
bind = $mainMod, 3, workspace, 3
|
||||||
|
bind = $mainMod, 4, workspace, 4
|
||||||
|
bind = $mainMod, 5, workspace, 5
|
||||||
|
bind = $mainMod, 6, workspace, 6
|
||||||
|
bind = $mainMod, 7, workspace, 7
|
||||||
|
bind = $mainMod, 8, workspace, 8
|
||||||
|
bind = $mainMod, 9, workspace, 9
|
||||||
|
bind = $mainMod, 0, workspace, 10
|
||||||
|
|
||||||
|
# Move active window to a workspace with mainMod + SHIFT + [0-9]
|
||||||
|
bind = $mainMod SHIFT, 1, movetoworkspace, 1
|
||||||
|
bind = $mainMod SHIFT, 2, movetoworkspace, 2
|
||||||
|
bind = $mainMod SHIFT, 3, movetoworkspace, 3
|
||||||
|
bind = $mainMod SHIFT, 4, movetoworkspace, 4
|
||||||
|
bind = $mainMod SHIFT, 5, movetoworkspace, 5
|
||||||
|
bind = $mainMod SHIFT, 6, movetoworkspace, 6
|
||||||
|
bind = $mainMod SHIFT, 7, movetoworkspace, 7
|
||||||
|
bind = $mainMod SHIFT, 8, movetoworkspace, 8
|
||||||
|
bind = $mainMod SHIFT, 9, movetoworkspace, 9
|
||||||
|
bind = $mainMod SHIFT, 0, movetoworkspace, 10
|
||||||
|
|
||||||
|
# Scroll through existing workspaces with mainMod + scroll
|
||||||
|
bind = $mainMod, mouse_down, workspace, e+1
|
||||||
|
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
|
||||||
)#";
|
)#";
|
||||||
|
|||||||
166
src/debug/CrashReporter.cpp
Normal file
166
src/debug/CrashReporter.cpp
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
#include "CrashReporter.hpp"
|
||||||
|
#include <random>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <execinfo.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "../plugins/PluginSystem.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...",
|
||||||
|
"This was an accident, I swear!",
|
||||||
|
"Calm down, it was a misinput! MISINPUT!",
|
||||||
|
"Oops",
|
||||||
|
"Vaxry is going to be upset.",
|
||||||
|
"Who tried dividing by zero?!",
|
||||||
|
"Maybe you should try dusting your PC in the meantime?",
|
||||||
|
"I tried so hard, and got so far...",
|
||||||
|
"I don't feel so good...",
|
||||||
|
"*thud*",
|
||||||
|
"Well this is awkward.",
|
||||||
|
"\"stable\"",
|
||||||
|
"I hope you didn't have any unsaved progress."};
|
||||||
|
|
||||||
|
std::random_device dev;
|
||||||
|
std::mt19937 engine(dev());
|
||||||
|
std::uniform_int_distribution<> distribution(0, MESSAGES.size() - 1);
|
||||||
|
|
||||||
|
return MESSAGES[distribution(engine)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CrashReporter::createAndSaveCrash(int sig) {
|
||||||
|
|
||||||
|
// get the backtrace
|
||||||
|
const int PID = getpid();
|
||||||
|
|
||||||
|
std::string finalCrashReport = "";
|
||||||
|
|
||||||
|
finalCrashReport += "--------------------------------------------\n Hyprland Crash Report\n--------------------------------------------\n";
|
||||||
|
finalCrashReport += getRandomMessage() + "\n\n";
|
||||||
|
|
||||||
|
finalCrashReport += getFormat("Hyprland received signal %d (%s)\n\n", sig, strsignal(sig));
|
||||||
|
|
||||||
|
finalCrashReport += getFormat("Version: %s\n\n", GIT_COMMIT_HASH);
|
||||||
|
|
||||||
|
if (g_pPluginSystem && !g_pPluginSystem->getAllPlugins().empty()) {
|
||||||
|
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 += getFormat("\t%s (%s) %s\n", p->name.c_str(), p->author.c_str(), p->version.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
finalCrashReport += "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
finalCrashReport += "System info:\n";
|
||||||
|
|
||||||
|
struct utsname unameInfo;
|
||||||
|
uname(&unameInfo);
|
||||||
|
|
||||||
|
finalCrashReport +=
|
||||||
|
getFormat("\tSystem name: %s\n\tNode name: %s\n\tRelease: %s\n\tVersion: %s\n\n", unameInfo.sysname, unameInfo.nodename, unameInfo.release, unameInfo.version);
|
||||||
|
|
||||||
|
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
||||||
|
const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga");
|
||||||
|
#else
|
||||||
|
const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
finalCrashReport += "GPU:\n\t" + GPUINFO;
|
||||||
|
|
||||||
|
finalCrashReport += getFormat("\n\nos-release:\n\t%s\n\n\n", replaceInString(execAndGet("cat /etc/os-release"), "\n", "\n\t").c_str());
|
||||||
|
|
||||||
|
finalCrashReport += "Backtrace:\n";
|
||||||
|
|
||||||
|
void* bt[1024];
|
||||||
|
size_t btSize;
|
||||||
|
char** btSymbols;
|
||||||
|
|
||||||
|
btSize = backtrace(bt, 1024);
|
||||||
|
btSymbols = backtrace_symbols(bt, btSize);
|
||||||
|
|
||||||
|
#if defined(KERN_PROC_PATHNAME)
|
||||||
|
int mib[] = {
|
||||||
|
CTL_KERN,
|
||||||
|
#if defined(__NetBSD__)
|
||||||
|
KERN_PROC_ARGS,
|
||||||
|
-1,
|
||||||
|
KERN_PROC_PATHNAME,
|
||||||
|
#else
|
||||||
|
KERN_PROC,
|
||||||
|
KERN_PROC_PATHNAME,
|
||||||
|
-1,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
u_int miblen = sizeof(mib) / sizeof(mib[0]);
|
||||||
|
char exe[PATH_MAX] = "";
|
||||||
|
size_t sz = sizeof(exe);
|
||||||
|
sysctl(mib, miblen, &exe, &sz, NULL, 0);
|
||||||
|
const auto FPATH = std::filesystem::canonical(exe);
|
||||||
|
#elif defined(__OpenBSD__)
|
||||||
|
// Neither KERN_PROC_PATHNAME nor /proc are supported
|
||||||
|
const auto FPATH = std::filesystem::canonical("/usr/local/bin/Hyprland");
|
||||||
|
#else
|
||||||
|
const auto FPATH = std::filesystem::canonical("/proc/self/exe");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (size_t i = 0; i < btSize; ++i) {
|
||||||
|
finalCrashReport += getFormat("\t#%lu | %s\n", i, btSymbols[i]);
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
const auto CMD = getFormat("llvm-addr2line -e %s -f 0x%lx", FPATH.c_str(), (uint64_t)bt[i]);
|
||||||
|
#else
|
||||||
|
const auto CMD = getFormat("addr2line -e %s -f 0x%lx", FPATH.c_str(), (uint64_t)bt[i]);
|
||||||
|
#endif
|
||||||
|
const auto ADDR2LINE = replaceInString(execAndGet(CMD.c_str()), "\n", "\n\t\t");
|
||||||
|
finalCrashReport += "\t\t" + ADDR2LINE.substr(0, ADDR2LINE.length() - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(btSymbols);
|
||||||
|
|
||||||
|
finalCrashReport += "\n\nLog tail:\n";
|
||||||
|
|
||||||
|
finalCrashReport += execAndGet(("cat \"" + Debug::logFile + "\" | tail -n 50").c_str());
|
||||||
|
|
||||||
|
const auto HOME = getenv("HOME");
|
||||||
|
const auto CACHE_HOME = getenv("XDG_CACHE_HOME");
|
||||||
|
|
||||||
|
if (!HOME)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::ofstream ofs;
|
||||||
|
std::string path;
|
||||||
|
if (!CACHE_HOME) {
|
||||||
|
if (!std::filesystem::exists(std::string(HOME) + "/.hyprland")) {
|
||||||
|
std::filesystem::create_directory(std::string(HOME) + "/.hyprland");
|
||||||
|
std::filesystem::permissions(std::string(HOME) + "/.hyprland", std::filesystem::perms::all, std::filesystem::perm_options::replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
path = std::string(HOME) + "/.hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt";
|
||||||
|
ofs.open(path, std::ios::trunc);
|
||||||
|
|
||||||
|
} else if (CACHE_HOME) {
|
||||||
|
if (!std::filesystem::exists(std::string(CACHE_HOME) + "/hyprland")) {
|
||||||
|
std::filesystem::create_directory(std::string(CACHE_HOME) + "/hyprland");
|
||||||
|
std::filesystem::permissions(std::string(CACHE_HOME) + "/hyprland", std::filesystem::perms::all, std::filesystem::perm_options::replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
path = std::string(CACHE_HOME) + "/hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt";
|
||||||
|
ofs.open(path, std::ios::trunc);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ofs << finalCrashReport;
|
||||||
|
|
||||||
|
ofs.close();
|
||||||
|
|
||||||
|
Debug::disableStdout = false;
|
||||||
|
Debug::log(CRIT, "Hyprland has crashed :( Consult the crash report at %s for more information.", path.c_str());
|
||||||
|
}
|
||||||
7
src/debug/CrashReporter.hpp
Normal file
7
src/debug/CrashReporter.hpp
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../defines.hpp"
|
||||||
|
|
||||||
|
namespace CrashReporter {
|
||||||
|
void createAndSaveCrash(int sig);
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -5,18 +5,19 @@
|
|||||||
#include "../helpers/MiscFunctions.hpp"
|
#include "../helpers/MiscFunctions.hpp"
|
||||||
|
|
||||||
namespace HyprCtl {
|
namespace HyprCtl {
|
||||||
void startHyprCtlSocket();
|
void startHyprCtlSocket();
|
||||||
|
std::string makeDynamicCall(const std::string& input);
|
||||||
|
|
||||||
// very simple thread-safe request method
|
// very simple thread-safe request method
|
||||||
inline bool requestMade = false;
|
inline bool requestMade = false;
|
||||||
inline bool requestReady = false;
|
inline bool requestReady = false;
|
||||||
inline std::string request = "";
|
inline std::string request = "";
|
||||||
|
|
||||||
inline std::ifstream requestStream;
|
inline std::ifstream requestStream;
|
||||||
|
|
||||||
inline wl_event_source* hyprCtlTickSource = nullptr;
|
inline wl_event_source* hyprCtlTickSource = nullptr;
|
||||||
|
|
||||||
inline int iSocketFD = -1;
|
inline int iSocketFD = -1;
|
||||||
|
|
||||||
enum eHyprCtlOutputFormat {
|
enum eHyprCtlOutputFormat {
|
||||||
FORMAT_NORMAL = 0,
|
FORMAT_NORMAL = 0,
|
||||||
|
|||||||
@@ -31,6 +31,15 @@ void CHyprMonitorDebugOverlay::frameData(CMonitor* pMonitor) {
|
|||||||
|
|
||||||
if (!m_pMonitor)
|
if (!m_pMonitor)
|
||||||
m_pMonitor = pMonitor;
|
m_pMonitor = pMonitor;
|
||||||
|
|
||||||
|
// anim data too
|
||||||
|
const auto PMONITORFORTICKS = g_pHyprRenderer->m_pMostHzMonitor ? g_pHyprRenderer->m_pMostHzMonitor : g_pCompositor->m_pLastMonitor;
|
||||||
|
if (PMONITORFORTICKS) {
|
||||||
|
if (m_dLastAnimationTicks.size() > (long unsigned int)PMONITORFORTICKS->refreshRate)
|
||||||
|
m_dLastAnimationTicks.pop_front();
|
||||||
|
|
||||||
|
m_dLastAnimationTicks.push_back(g_pAnimationManager->m_fLastTickTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CHyprMonitorDebugOverlay::draw(int offset) {
|
int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||||
@@ -38,34 +47,68 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
|||||||
if (!m_pMonitor)
|
if (!m_pMonitor)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int yOffset = offset;
|
int yOffset = offset;
|
||||||
cairo_text_extents_t cairoExtents;
|
cairo_text_extents_t cairoExtents;
|
||||||
float maxX = 0;
|
float maxX = 0;
|
||||||
std::string text = "";
|
std::string text = "";
|
||||||
|
|
||||||
// get avg fps
|
// get avg fps
|
||||||
float avgFrametime = 0;
|
float avgFrametime = 0;
|
||||||
|
float maxFrametime = 0;
|
||||||
|
float minFrametime = 9999;
|
||||||
for (auto& ft : m_dLastFrametimes) {
|
for (auto& ft : m_dLastFrametimes) {
|
||||||
|
if (ft > maxFrametime)
|
||||||
|
maxFrametime = ft;
|
||||||
|
if (ft < minFrametime)
|
||||||
|
minFrametime = ft;
|
||||||
avgFrametime += ft;
|
avgFrametime += ft;
|
||||||
}
|
}
|
||||||
|
float varFrametime = maxFrametime - minFrametime;
|
||||||
avgFrametime /= m_dLastFrametimes.size() == 0 ? 1 : m_dLastFrametimes.size();
|
avgFrametime /= m_dLastFrametimes.size() == 0 ? 1 : m_dLastFrametimes.size();
|
||||||
|
|
||||||
float avgRenderTime = 0;
|
float avgRenderTime = 0;
|
||||||
|
float maxRenderTime = 0;
|
||||||
|
float minRenderTime = 9999;
|
||||||
for (auto& rt : m_dLastRenderTimes) {
|
for (auto& rt : m_dLastRenderTimes) {
|
||||||
|
if (rt > maxRenderTime)
|
||||||
|
maxRenderTime = rt;
|
||||||
|
if (rt < minRenderTime)
|
||||||
|
minRenderTime = rt;
|
||||||
avgRenderTime += rt;
|
avgRenderTime += rt;
|
||||||
}
|
}
|
||||||
|
float varRenderTime = maxRenderTime - minRenderTime;
|
||||||
avgRenderTime /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
|
avgRenderTime /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
|
||||||
|
|
||||||
float avgRenderTimeNoOverlay = 0;
|
float avgRenderTimeNoOverlay = 0;
|
||||||
|
float maxRenderTimeNoOverlay = 0;
|
||||||
|
float minRenderTimeNoOverlay = 9999;
|
||||||
for (auto& rt : m_dLastRenderTimesNoOverlay) {
|
for (auto& rt : m_dLastRenderTimesNoOverlay) {
|
||||||
|
if (rt > maxRenderTimeNoOverlay)
|
||||||
|
maxRenderTimeNoOverlay = rt;
|
||||||
|
if (rt < minRenderTimeNoOverlay)
|
||||||
|
minRenderTimeNoOverlay = rt;
|
||||||
avgRenderTimeNoOverlay += rt;
|
avgRenderTimeNoOverlay += rt;
|
||||||
}
|
}
|
||||||
|
float varRenderTimeNoOverlay = maxRenderTimeNoOverlay - minRenderTimeNoOverlay;
|
||||||
avgRenderTimeNoOverlay /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
|
avgRenderTimeNoOverlay /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
|
||||||
|
|
||||||
const float FPS = 1.f / (avgFrametime / 1000.f); // frametimes are in ms
|
float avgAnimMgrTick = 0;
|
||||||
|
float maxAnimMgrTick = 0;
|
||||||
|
float minAnimMgrTick = 9999;
|
||||||
|
for (auto& at : m_dLastAnimationTicks) {
|
||||||
|
if (at > maxAnimMgrTick)
|
||||||
|
maxAnimMgrTick = at;
|
||||||
|
if (at < minAnimMgrTick)
|
||||||
|
minAnimMgrTick = at;
|
||||||
|
avgAnimMgrTick += at;
|
||||||
|
}
|
||||||
|
float varAnimMgrTick = maxAnimMgrTick - minAnimMgrTick;
|
||||||
|
avgAnimMgrTick /= m_dLastAnimationTicks.size() == 0 ? 1 : m_dLastAnimationTicks.size();
|
||||||
|
|
||||||
|
const float FPS = 1.f / (avgFrametime / 1000.f); // frametimes are in ms
|
||||||
const float idealFPS = m_dLastFrametimes.size();
|
const float idealFPS = m_dLastFrametimes.size();
|
||||||
|
|
||||||
cairo_select_font_face(g_pDebugOverlay->m_pCairo, "Noto Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
cairo_select_font_face(g_pDebugOverlay->m_pCairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||||
|
|
||||||
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
|
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);
|
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
|
||||||
@@ -75,7 +118,8 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
|||||||
text = m_pMonitor->szName;
|
text = m_pMonitor->szName;
|
||||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||||
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
if (cairoExtents.width > maxX)
|
||||||
|
maxX = cairoExtents.width;
|
||||||
|
|
||||||
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 16);
|
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 16);
|
||||||
|
|
||||||
@@ -88,39 +132,52 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
|||||||
|
|
||||||
yOffset += 17;
|
yOffset += 17;
|
||||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||||
text = std::string(std::to_string((int)FPS) + " FPS");
|
text = std::string(getFormat("%i FPS", (int)FPS));
|
||||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||||
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
if (cairoExtents.width > maxX)
|
||||||
|
maxX = cairoExtents.width;
|
||||||
|
|
||||||
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
|
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);
|
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
|
||||||
|
|
||||||
yOffset += 11;
|
yOffset += 11;
|
||||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||||
text = std::string("Avg Frametime: " + std::to_string((int)avgFrametime) + "." + std::to_string((int)(avgFrametime * 10.f) % 10) + "ms");
|
text = std::string(getFormat("Avg Frametime: %.2fms (var %.2fms)", avgFrametime, varFrametime));
|
||||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||||
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
if (cairoExtents.width > maxX)
|
||||||
|
maxX = cairoExtents.width;
|
||||||
|
|
||||||
yOffset += 11;
|
yOffset += 11;
|
||||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||||
text = std::string("Avg Rendertime: " + std::to_string((int)avgRenderTime) + "." + std::to_string((int)(avgRenderTime * 10.f) % 10) + "ms");
|
text = std::string(getFormat("Avg Rendertime: %.2fms (var %.2fms)", avgRenderTime, varRenderTime));
|
||||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||||
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
if (cairoExtents.width > maxX)
|
||||||
|
maxX = cairoExtents.width;
|
||||||
|
|
||||||
yOffset += 11;
|
yOffset += 11;
|
||||||
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||||
text = std::string("Avg Rendertime (no overlay): " + std::to_string((int)avgRenderTimeNoOverlay) + "." + std::to_string((int)(avgRenderTimeNoOverlay * 10.f) % 10) + "ms");
|
text = std::string(getFormat("Avg Rendertime (No Overlay): %.2fms (var %.2fms)", avgRenderTimeNoOverlay, varRenderTimeNoOverlay));
|
||||||
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
|
||||||
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
|
||||||
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
|
if (cairoExtents.width > maxX)
|
||||||
|
maxX = cairoExtents.width;
|
||||||
|
|
||||||
|
yOffset += 11;
|
||||||
|
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
|
||||||
|
text = std::string(getFormat("Avg Anim Tick: %.2fms (var %.2fms) (%.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;
|
||||||
|
|
||||||
yOffset += 11;
|
yOffset += 11;
|
||||||
|
|
||||||
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
|
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, (int)g_pCompositor->m_vMonitors.front()->vecPosition.y + offset - 1, (int)maxX + 2,
|
||||||
|
yOffset - offset + 2};
|
||||||
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
|
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
|
||||||
|
|
||||||
return yOffset - offset;
|
return yOffset - offset;
|
||||||
@@ -143,8 +200,8 @@ void CHyprDebugOverlay::draw() {
|
|||||||
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
|
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
|
||||||
|
|
||||||
if (!m_pCairoSurface || !m_pCairo) {
|
if (!m_pCairoSurface || !m_pCairo) {
|
||||||
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
|
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||||
m_pCairo = cairo_create(m_pCairoSurface);
|
m_pCairo = cairo_create(m_pCairoSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear the pixmap
|
// clear the pixmap
|
||||||
@@ -174,8 +231,8 @@ void CHyprDebugOverlay::draw() {
|
|||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecSize.x, PMONITOR->vecSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||||
|
|
||||||
wlr_box pMonBox = {0,0,PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
wlr_box pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||||
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 255.f);
|
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,41 +7,45 @@
|
|||||||
#include <cairo/cairo.h>
|
#include <cairo/cairo.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class CHyprRenderer;
|
||||||
|
|
||||||
class CHyprMonitorDebugOverlay {
|
class CHyprMonitorDebugOverlay {
|
||||||
public:
|
public:
|
||||||
int draw(int offset);
|
int draw(int offset);
|
||||||
|
|
||||||
void renderData(CMonitor* pMonitor, float µs);
|
void renderData(CMonitor* pMonitor, float µs);
|
||||||
void renderDataNoOverlay(CMonitor* pMonitor, float µs);
|
void renderDataNoOverlay(CMonitor* pMonitor, float µs);
|
||||||
void frameData(CMonitor* pMonitor);
|
void frameData(CMonitor* pMonitor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::deque<float> m_dLastFrametimes;
|
std::deque<float> m_dLastFrametimes;
|
||||||
std::deque<float> m_dLastRenderTimes;
|
std::deque<float> m_dLastRenderTimes;
|
||||||
std::deque<float> m_dLastRenderTimesNoOverlay;
|
std::deque<float> m_dLastRenderTimesNoOverlay;
|
||||||
|
std::deque<float> m_dLastAnimationTicks;
|
||||||
std::chrono::high_resolution_clock::time_point m_tpLastFrame;
|
std::chrono::high_resolution_clock::time_point m_tpLastFrame;
|
||||||
CMonitor* m_pMonitor = nullptr;
|
CMonitor* m_pMonitor = nullptr;
|
||||||
wlr_box m_wbLastDrawnBox;
|
wlr_box m_wbLastDrawnBox;
|
||||||
|
|
||||||
|
friend class CHyprRenderer;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CHyprDebugOverlay {
|
class CHyprDebugOverlay {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void draw();
|
void draw();
|
||||||
void renderData(CMonitor*, float µs);
|
void renderData(CMonitor*, float µs);
|
||||||
void renderDataNoOverlay(CMonitor*, float µs);
|
void renderDataNoOverlay(CMonitor*, float µs);
|
||||||
void frameData(CMonitor*);
|
void frameData(CMonitor*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::unordered_map<CMonitor*, CHyprMonitorDebugOverlay> m_mMonitorOverlays;
|
std::unordered_map<CMonitor*, CHyprMonitorDebugOverlay> m_mMonitorOverlays;
|
||||||
|
|
||||||
cairo_surface_t* m_pCairoSurface = nullptr;
|
cairo_surface_t* m_pCairoSurface = nullptr;
|
||||||
cairo_t* m_pCairo = nullptr;
|
cairo_t* m_pCairo = nullptr;
|
||||||
|
|
||||||
CTexture m_tTexture;
|
CTexture m_tTexture;
|
||||||
|
|
||||||
friend class CHyprMonitorDebugOverlay;
|
friend class CHyprMonitorDebugOverlay;
|
||||||
|
friend class CHyprRenderer;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CHyprDebugOverlay> g_pDebugOverlay;
|
inline std::unique_ptr<CHyprDebugOverlay> g_pDebugOverlay;
|
||||||
225
src/debug/HyprNotificationOverlay.cpp
Normal file
225
src/debug/HyprNotificationOverlay.cpp
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
#include "HyprNotificationOverlay.hpp"
|
||||||
|
#include "../Compositor.hpp"
|
||||||
|
#include <pango/pangocairo.h>
|
||||||
|
|
||||||
|
CHyprNotificationOverlay::CHyprNotificationOverlay() {
|
||||||
|
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, 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); });
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprNotificationOverlay::addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon) {
|
||||||
|
const auto PNOTIF = m_dNotifications.emplace_back(std::make_unique<SNotification>()).get();
|
||||||
|
|
||||||
|
PNOTIF->text = text;
|
||||||
|
PNOTIF->color = color == CColor(0) ? ICONS_COLORS[icon] : color;
|
||||||
|
PNOTIF->started.reset();
|
||||||
|
PNOTIF->timeMs = timeMs;
|
||||||
|
PNOTIF->icon = icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_box CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||||
|
static constexpr auto ANIM_DURATION_MS = 600.0;
|
||||||
|
static constexpr auto ANIM_LAG_MS = 100.0;
|
||||||
|
static constexpr auto NOTIF_LEFTBAR_SIZE = 5.0;
|
||||||
|
static constexpr auto ICON_PAD = 3.0;
|
||||||
|
static constexpr auto ICON_SCALE = 0.9;
|
||||||
|
static constexpr auto GRADIENT_SIZE = 60.0;
|
||||||
|
|
||||||
|
float offsetY = 10;
|
||||||
|
float maxWidth = 0;
|
||||||
|
|
||||||
|
const auto SCALE = pMonitor->scale;
|
||||||
|
const auto FONTSIZE = std::clamp((int)(13.f * ((pMonitor->vecPixelSize.x * SCALE) / 1920.f)), 8, 40);
|
||||||
|
|
||||||
|
const auto MONSIZE = pMonitor->vecPixelSize;
|
||||||
|
|
||||||
|
cairo_text_extents_t cairoExtents;
|
||||||
|
int iconW = 0, iconH = 0;
|
||||||
|
|
||||||
|
PangoLayout* pangoLayout;
|
||||||
|
PangoFontDescription* pangoFD;
|
||||||
|
|
||||||
|
pangoLayout = pango_cairo_create_layout(m_pCairo);
|
||||||
|
pangoFD = pango_font_description_from_string(("Sans " + std::to_string(FONTSIZE * ICON_SCALE)).c_str());
|
||||||
|
pango_layout_set_font_description(pangoLayout, pangoFD);
|
||||||
|
|
||||||
|
cairo_select_font_face(m_pCairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||||
|
cairo_set_font_size(m_pCairo, FONTSIZE);
|
||||||
|
|
||||||
|
const auto PBEZIER = g_pAnimationManager->getBezier("default");
|
||||||
|
|
||||||
|
for (auto& notif : m_dNotifications) {
|
||||||
|
const auto ICONPADFORNOTIF = notif->icon == ICON_NONE ? 0 : ICON_PAD;
|
||||||
|
|
||||||
|
// first rect (bg, col)
|
||||||
|
const float FIRSTRECTANIMP =
|
||||||
|
(notif->started.getMillis() > (ANIM_DURATION_MS - ANIM_LAG_MS) ?
|
||||||
|
(notif->started.getMillis() > notif->timeMs - (ANIM_DURATION_MS - ANIM_LAG_MS) ? notif->timeMs - notif->started.getMillis() : (ANIM_DURATION_MS - ANIM_LAG_MS)) :
|
||||||
|
notif->started.getMillis()) /
|
||||||
|
(ANIM_DURATION_MS - ANIM_LAG_MS);
|
||||||
|
|
||||||
|
const float FIRSTRECTPERC = FIRSTRECTANIMP >= 0.99f ? 1.f : PBEZIER->getYForPoint(FIRSTRECTANIMP);
|
||||||
|
|
||||||
|
// second rect (fg, black)
|
||||||
|
const float SECONDRECTANIMP = (notif->started.getMillis() > ANIM_DURATION_MS ?
|
||||||
|
(notif->started.getMillis() > notif->timeMs - ANIM_DURATION_MS ? notif->timeMs - notif->started.getMillis() : ANIM_DURATION_MS) :
|
||||||
|
notif->started.getMillis()) /
|
||||||
|
ANIM_DURATION_MS;
|
||||||
|
|
||||||
|
const float SECONDRECTPERC = SECONDRECTANIMP >= 0.99f ? 1.f : PBEZIER->getYForPoint(SECONDRECTANIMP);
|
||||||
|
|
||||||
|
// third rect (horiz, col)
|
||||||
|
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 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);
|
||||||
|
iconW /= PANGO_SCALE;
|
||||||
|
iconH /= PANGO_SCALE;
|
||||||
|
|
||||||
|
cairo_set_source_rgba(m_pCairo, notif->color.r, notif->color.g, notif->color.b, notif->color.a);
|
||||||
|
|
||||||
|
const auto NOTIFSIZE = Vector2D{cairoExtents.width + 20 + iconW + 2 * ICONPADFORNOTIF, cairoExtents.height + 10};
|
||||||
|
|
||||||
|
// draw rects
|
||||||
|
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);
|
||||||
|
|
||||||
|
// draw gradient
|
||||||
|
if (notif->icon != ICON_NONE) {
|
||||||
|
cairo_pattern_t* pattern;
|
||||||
|
pattern = cairo_pattern_create_linear(MONSIZE.x - (NOTIFSIZE.x + NOTIF_LEFTBAR_SIZE) * FIRSTRECTPERC, offsetY,
|
||||||
|
MONSIZE.x - (NOTIFSIZE.x + NOTIF_LEFTBAR_SIZE) * FIRSTRECTPERC + GRADIENT_SIZE, offsetY);
|
||||||
|
cairo_pattern_add_color_stop_rgba(pattern, 0, ICONCOLOR.r, ICONCOLOR.g, ICONCOLOR.b, ICONCOLOR.a / 3.0);
|
||||||
|
cairo_pattern_add_color_stop_rgba(pattern, 1, ICONCOLOR.r, ICONCOLOR.g, ICONCOLOR.b, 0);
|
||||||
|
cairo_rectangle(m_pCairo, MONSIZE.x - (NOTIFSIZE.x + NOTIF_LEFTBAR_SIZE) * FIRSTRECTPERC, offsetY, GRADIENT_SIZE, NOTIFSIZE.y);
|
||||||
|
cairo_set_source(m_pCairo, pattern);
|
||||||
|
cairo_fill(m_pCairo);
|
||||||
|
cairo_pattern_destroy(pattern);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// cleanup notifs
|
||||||
|
std::erase_if(m_dNotifications, [](const auto& notif) { return notif->started.getMillis() > notif->timeMs; });
|
||||||
|
|
||||||
|
return wlr_box{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||||
|
|
||||||
|
if (m_pLastMonitor != pMonitor || !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_pCairo = cairo_create(m_pCairoSurface);
|
||||||
|
m_pLastMonitor = pMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the notifications
|
||||||
|
if (m_dNotifications.size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Render to the monitor
|
||||||
|
|
||||||
|
// clear the pixmap
|
||||||
|
cairo_save(m_pCairo);
|
||||||
|
cairo_set_operator(m_pCairo, CAIRO_OPERATOR_CLEAR);
|
||||||
|
cairo_paint(m_pCairo);
|
||||||
|
cairo_restore(m_pCairo);
|
||||||
|
|
||||||
|
cairo_surface_flush(m_pCairoSurface);
|
||||||
|
|
||||||
|
wlr_box damage = drawNotifications(pMonitor);
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageBox(&damage);
|
||||||
|
g_pHyprRenderer->damageBox(&m_bLastDamage);
|
||||||
|
|
||||||
|
g_pCompositor->scheduleFrameForMonitor(pMonitor);
|
||||||
|
|
||||||
|
m_bLastDamage = damage;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
#ifndef GLES2
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||||
|
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);
|
||||||
|
|
||||||
|
wlr_box pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||||
|
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
|
||||||
|
}
|
||||||
63
src/debug/HyprNotificationOverlay.hpp
Normal file
63
src/debug/HyprNotificationOverlay.hpp
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../defines.hpp"
|
||||||
|
#include "../helpers/Timer.hpp"
|
||||||
|
#include "../helpers/Monitor.hpp"
|
||||||
|
#include "../render/Texture.hpp"
|
||||||
|
#include "../SharedDefs.hpp"
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
#include <cairo/cairo.h>
|
||||||
|
|
||||||
|
enum eIconBackend
|
||||||
|
{
|
||||||
|
ICONS_BACKEND_NONE = 0,
|
||||||
|
ICONS_BACKEND_NF,
|
||||||
|
ICONS_BACKEND_FA
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::array<std::array<std::string, ICON_NONE + 1>, 3 /* backends */> ICONS_ARRAY = {
|
||||||
|
std::array<std::string, ICON_NONE + 1>{"[!]", "[i]", "[Hint]", "[Err]", "[?]", "[ok]", ""}, std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", "", ""},
|
||||||
|
std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", ""}};
|
||||||
|
static const std::array<CColor, ICON_NONE + 1> ICONS_COLORS = {CColor{255.0 / 255.0, 204 / 255.0, 102 / 255.0, 1.0},
|
||||||
|
CColor{128 / 255.0, 255 / 255.0, 255 / 255.0, 1.0},
|
||||||
|
CColor{179 / 255.0, 255 / 255.0, 204 / 255.0, 1.0},
|
||||||
|
CColor{255 / 255.0, 77 / 255.0, 77 / 255.0, 1.0},
|
||||||
|
CColor{255 / 255.0, 204 / 255.0, 153 / 255.0, 1.0},
|
||||||
|
CColor{128 / 255.0, 255 / 255.0, 128 / 255.0, 1.0},
|
||||||
|
CColor{0, 0, 0, 1.0}};
|
||||||
|
|
||||||
|
struct SNotification {
|
||||||
|
std::string text = "";
|
||||||
|
CColor color;
|
||||||
|
CTimer started;
|
||||||
|
float timeMs = 0;
|
||||||
|
eIcons icon = ICON_NONE;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CHyprNotificationOverlay {
|
||||||
|
public:
|
||||||
|
CHyprNotificationOverlay();
|
||||||
|
|
||||||
|
void draw(CMonitor* pMonitor);
|
||||||
|
void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE);
|
||||||
|
|
||||||
|
private:
|
||||||
|
wlr_box drawNotifications(CMonitor* pMonitor);
|
||||||
|
wlr_box m_bLastDamage;
|
||||||
|
|
||||||
|
std::deque<std::unique_ptr<SNotification>> m_dNotifications;
|
||||||
|
|
||||||
|
cairo_surface_t* m_pCairoSurface = nullptr;
|
||||||
|
cairo_t* m_pCairo = nullptr;
|
||||||
|
|
||||||
|
CMonitor* m_pLastMonitor = nullptr;
|
||||||
|
|
||||||
|
CTexture m_tTexture;
|
||||||
|
|
||||||
|
eIconBackend m_eIconBackend = ICONS_BACKEND_NONE;
|
||||||
|
std::string m_szIconFontName = "Sans";
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::unique_ptr<CHyprNotificationOverlay> g_pHyprNotificationOverlay;
|
||||||
@@ -5,12 +5,12 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
void Debug::init(std::string IS) {
|
void Debug::init(const std::string& IS) {
|
||||||
logFile = "/tmp/hypr/" + IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log");
|
logFile = "/tmp/hypr/" + IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) {
|
void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) {
|
||||||
char* outputStr = nullptr;
|
char* outputStr = nullptr;
|
||||||
|
|
||||||
std::ofstream ofs;
|
std::ofstream ofs;
|
||||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||||
@@ -23,6 +23,9 @@ void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) {
|
|||||||
ofs << "[wlr] " << output << "\n";
|
ofs << "[wlr] " << output << "\n";
|
||||||
|
|
||||||
ofs.close();
|
ofs.close();
|
||||||
|
|
||||||
|
if (!disableStdout)
|
||||||
|
std::cout << output << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debug::log(LogLevel level, const char* fmt, ...) {
|
void Debug::log(LogLevel level, const char* fmt, ...) {
|
||||||
@@ -35,28 +38,17 @@ void Debug::log(LogLevel level, const char* fmt, ...) {
|
|||||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||||
|
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case LOG:
|
case LOG: ofs << "[LOG] "; break;
|
||||||
ofs << "[LOG] ";
|
case WARN: ofs << "[WARN] "; break;
|
||||||
break;
|
case ERR: ofs << "[ERR] "; break;
|
||||||
case WARN:
|
case CRIT: ofs << "[CRITICAL] "; break;
|
||||||
ofs << "[WARN] ";
|
case INFO: ofs << "[INFO] "; break;
|
||||||
break;
|
default: break;
|
||||||
case ERR:
|
|
||||||
ofs << "[ERR] ";
|
|
||||||
break;
|
|
||||||
case CRIT:
|
|
||||||
ofs << "[CRITICAL] ";
|
|
||||||
break;
|
|
||||||
case INFO:
|
|
||||||
ofs << "[INFO] ";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// print date and time to the ofs
|
// print date and time to the ofs
|
||||||
if (disableTime && !*disableTime) {
|
if (disableTime && !*disableTime) {
|
||||||
auto timet = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
auto timet = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||||
const auto MILLIS = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() % 1000;
|
const auto MILLIS = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() % 1000;
|
||||||
|
|
||||||
ofs << std::put_time(std::localtime(&timet), "[%H:%M:%S:");
|
ofs << std::put_time(std::localtime(&timet), "[%H:%M:%S:");
|
||||||
@@ -71,7 +63,7 @@ void Debug::log(LogLevel level, const char* fmt, ...) {
|
|||||||
ofs << "] ";
|
ofs << "] ";
|
||||||
}
|
}
|
||||||
|
|
||||||
char* outputStr = nullptr;
|
char* outputStr = nullptr;
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
@@ -86,5 +78,6 @@ void Debug::log(LogLevel level, const char* fmt, ...) {
|
|||||||
ofs.close();
|
ofs.close();
|
||||||
|
|
||||||
// log it to the stdout too.
|
// log it to the stdout too.
|
||||||
std::cout << output << "\n";
|
if (!disableStdout)
|
||||||
|
std::cout << output << "\n";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,10 @@
|
|||||||
|
|
||||||
#define LOGMESSAGESIZE 1024
|
#define LOGMESSAGESIZE 1024
|
||||||
|
|
||||||
enum LogLevel {
|
enum LogLevel
|
||||||
|
{
|
||||||
NONE = -1,
|
NONE = -1,
|
||||||
LOG = 0,
|
LOG = 0,
|
||||||
WARN,
|
WARN,
|
||||||
ERR,
|
ERR,
|
||||||
CRIT,
|
CRIT,
|
||||||
@@ -14,11 +15,12 @@ enum LogLevel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace Debug {
|
namespace Debug {
|
||||||
void init(std::string IS);
|
void init(const std::string& IS);
|
||||||
void log(LogLevel level, const char* fmt, ...);
|
void log(LogLevel level, const char* fmt, ...);
|
||||||
void wlrLog(wlr_log_importance level, const char* fmt, va_list args);
|
void wlrLog(wlr_log_importance level, const char* fmt, va_list args);
|
||||||
|
|
||||||
inline std::string logFile;
|
inline std::string logFile;
|
||||||
inline int64_t* disableLogs = nullptr;
|
inline int64_t* disableLogs = nullptr;
|
||||||
inline int64_t* disableTime = nullptr;
|
inline int64_t* disableTime = nullptr;
|
||||||
|
inline bool disableStdout = false;
|
||||||
};
|
};
|
||||||
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "wlrunstable/wlr_ext_workspace_v1.hpp"
|
#include "wlrunstable/wlr_ext_workspace_v1.hpp"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#ifdef HYPRLAND_DEBUG
|
#ifdef HYPRLAND_DEBUG
|
||||||
#define ISDEBUG true
|
#define ISDEBUG true
|
||||||
@@ -16,37 +18,44 @@
|
|||||||
#define ISDEBUG false
|
#define ISDEBUG false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LISTENER(name) void listener_##name(wl_listener*, void*); inline wl_listener listen_##name = { .notify = listener_##name };
|
#define LISTENER(name) \
|
||||||
#define DYNLISTENFUNC(name) void listener_##name(void*, void*);
|
void listener_##name(wl_listener*, void*); \
|
||||||
#define DYNLISTENER(name) CHyprWLListener hyprListener_##name;
|
inline wl_listener listen_##name = {.notify = listener_##name}
|
||||||
#define DYNMULTILISTENER(name) wl_listener listen_##name;
|
#define DYNLISTENFUNC(name) void listener_##name(void*, void*)
|
||||||
|
#define DYNLISTENER(name) CHyprWLListener hyprListener_##name
|
||||||
|
#define DYNMULTILISTENER(name) wl_listener listen_##name
|
||||||
|
|
||||||
#define VECINRECT(vec, x1, y1, x2, y2) (vec.x >= (x1) && vec.x <= (x2) && vec.y >= (y1) && vec.y <= (y2))
|
#define VECINRECT(vec, x1, y1, x2, y2) ((vec).x >= (x1) && (vec).x <= (x2) && (vec).y >= (y1) && (vec).y <= (y2))
|
||||||
|
|
||||||
#define DELTALESSTHAN(a, b, delta) (abs((a) - (b)) < delta)
|
#define DELTALESSTHAN(a, b, delta) (abs((a) - (b)) < (delta))
|
||||||
|
|
||||||
#define PIXMAN_DAMAGE_FOREACH(region) int rectsNum = 0; \
|
#define PIXMAN_DAMAGE_FOREACH(region) \
|
||||||
const auto RECTSARR = pixman_region32_rectangles(region, &rectsNum); \
|
int rectsNum = 0; \
|
||||||
|
const auto RECTSARR = pixman_region32_rectangles(region, &rectsNum); \
|
||||||
for (int i = 0; i < rectsNum; ++i)
|
for (int i = 0; i < rectsNum; ++i)
|
||||||
|
|
||||||
|
#define PIXMAN_REGION_FOREACH(region) PIXMAN_DAMAGE_FOREACH(region)
|
||||||
|
|
||||||
#define interface class
|
#define interface class
|
||||||
|
|
||||||
#define STICKS(a, b) abs((a) - (b)) < 2
|
#define STICKS(a, b) abs((a) - (b)) < 2
|
||||||
|
|
||||||
#define ALPHA(c) ((double)(((c) >> 24) & 0xff) / 255.0)
|
#define ALPHA(c) ((double)(((c) >> 24) & 0xff) / 255.0)
|
||||||
#define RED(c) ((double)(((c) >> 16) & 0xff) / 255.0)
|
#define RED(c) ((double)(((c) >> 16) & 0xff) / 255.0)
|
||||||
#define GREEN(c) ((double)(((c) >> 8) & 0xff) / 255.0)
|
#define GREEN(c) ((double)(((c) >> 8) & 0xff) / 255.0)
|
||||||
#define BLUE(c) ((double)(((c)) & 0xff) / 255.0)
|
#define BLUE(c) ((double)(((c)) & 0xff) / 255.0)
|
||||||
|
|
||||||
#define HYPRATOM(name) {name, 0}
|
#define HYPRATOM(name) \
|
||||||
|
{ name, 0 }
|
||||||
|
|
||||||
#ifndef __INTELLISENSE__
|
#ifndef __INTELLISENSE__
|
||||||
#define RASSERT(expr, reason, ...) \
|
#define RASSERT(expr, reason, ...) \
|
||||||
if (!(expr)) { \
|
if (!(expr)) { \
|
||||||
Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n%s\n\nat: line %d in %s", getFormat(reason, ##__VA_ARGS__).c_str(), __LINE__, ([]() constexpr->std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })().c_str()); \
|
Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n%s\n\nat: line %d in %s", \
|
||||||
printf("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info."); \
|
getFormat(reason, ##__VA_ARGS__).c_str(), __LINE__, \
|
||||||
*((int*)nullptr) = 1; /* so that we crash and get a coredump */ \
|
([]() constexpr->std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })().c_str()); \
|
||||||
|
printf("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info."); \
|
||||||
|
*((int*)nullptr) = 1; /* so that we crash and get a coredump */ \
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define RASSERT(expr, reason, ...)
|
#define RASSERT(expr, reason, ...)
|
||||||
@@ -55,7 +64,11 @@
|
|||||||
#define ASSERT(expr) RASSERT(expr, "?")
|
#define ASSERT(expr) RASSERT(expr, "?")
|
||||||
|
|
||||||
#if ISDEBUG
|
#if ISDEBUG
|
||||||
#define UNREACHABLE() { Debug::log(CRIT, "\n\nMEMORY CORRUPTED: Unreachable failed! (Reached an unreachable position, memory corruption!!!)"); *((int*)nullptr) = 1; }
|
#define UNREACHABLE() \
|
||||||
|
{ \
|
||||||
|
Debug::log(CRIT, "\n\nMEMORY CORRUPTED: Unreachable failed! (Reached an unreachable position, memory corruption!!!)"); \
|
||||||
|
*((int*)nullptr) = 1; \
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
#define UNREACHABLE() std::unreachable();
|
#define UNREACHABLE() std::unreachable();
|
||||||
#endif
|
#endif
|
||||||
@@ -73,5 +86,10 @@
|
|||||||
#ifndef GIT_DIRTY
|
#ifndef GIT_DIRTY
|
||||||
#define GIT_DIRTY "?"
|
#define GIT_DIRTY "?"
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef GIT_TAG
|
||||||
|
#define GIT_TAG "?"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SPECIAL_WORKSPACE_ID -99
|
#define SPECIAL_WORKSPACE_START (-99)
|
||||||
|
|
||||||
|
#define PI 3.14159265358979
|
||||||
@@ -19,7 +19,7 @@ void Events::listener_keyboardDestroy(void* owner, void* data) {
|
|||||||
SKeyboard* PKEYBOARD = (SKeyboard*)owner;
|
SKeyboard* PKEYBOARD = (SKeyboard*)owner;
|
||||||
g_pInputManager->destroyKeyboard(PKEYBOARD);
|
g_pInputManager->destroyKeyboard(PKEYBOARD);
|
||||||
|
|
||||||
Debug::log(LOG, "Destroyed keyboard %x", PKEYBOARD);
|
Debug::log(LOG, "Destroyed keyboard %lx", PKEYBOARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_keyboardKey(void* owner, void* data) {
|
void Events::listener_keyboardKey(void* owner, void* data) {
|
||||||
@@ -61,7 +61,7 @@ void Events::listener_requestMouse(wl_listener* listener, void* data) {
|
|||||||
void Events::listener_newInput(wl_listener* listener, void* data) {
|
void Events::listener_newInput(wl_listener* listener, void* data) {
|
||||||
const auto DEVICE = (wlr_input_device*)data;
|
const auto DEVICE = (wlr_input_device*)data;
|
||||||
|
|
||||||
switch(DEVICE->type) {
|
switch (DEVICE->type) {
|
||||||
case WLR_INPUT_DEVICE_KEYBOARD:
|
case WLR_INPUT_DEVICE_KEYBOARD:
|
||||||
Debug::log(LOG, "Attached a keyboard with name %s", DEVICE->name);
|
Debug::log(LOG, "Attached a keyboard with name %s", DEVICE->name);
|
||||||
g_pInputManager->newKeyboard(DEVICE);
|
g_pInputManager->newKeyboard(DEVICE);
|
||||||
@@ -86,23 +86,21 @@ void Events::listener_newInput(wl_listener* listener, void* data) {
|
|||||||
Debug::log(LOG, "Attached a switch device with name %s", DEVICE->name);
|
Debug::log(LOG, "Attached a switch device with name %s", DEVICE->name);
|
||||||
g_pInputManager->newSwitch(DEVICE);
|
g_pInputManager->newSwitch(DEVICE);
|
||||||
break;
|
break;
|
||||||
default:
|
default: Debug::log(WARN, "Unrecognized input device plugged in: %s", DEVICE->name); break;
|
||||||
Debug::log(WARN, "Unrecognized input device plugged in: %s", DEVICE->name);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pInputManager->updateCapabilities(DEVICE);
|
g_pInputManager->updateCapabilities();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_newConstraint(wl_listener* listener, void* data) {
|
void Events::listener_newConstraint(wl_listener* listener, void* data) {
|
||||||
const auto PCONSTRAINT = (wlr_pointer_constraint_v1*)data;
|
const auto PCONSTRAINT = (wlr_pointer_constraint_v1*)data;
|
||||||
|
|
||||||
Debug::log(LOG, "New mouse constraint at %x", PCONSTRAINT);
|
Debug::log(LOG, "New mouse constraint at %lx", PCONSTRAINT);
|
||||||
|
|
||||||
g_pInputManager->m_lConstraints.emplace_back();
|
g_pInputManager->m_lConstraints.emplace_back();
|
||||||
const auto CONSTRAINT = &g_pInputManager->m_lConstraints.back();
|
const auto CONSTRAINT = &g_pInputManager->m_lConstraints.back();
|
||||||
|
|
||||||
CONSTRAINT->pMouse = g_pCompositor->m_sSeat.mouse;
|
CONSTRAINT->pMouse = g_pCompositor->m_sSeat.mouse;
|
||||||
CONSTRAINT->constraint = PCONSTRAINT;
|
CONSTRAINT->constraint = PCONSTRAINT;
|
||||||
|
|
||||||
CONSTRAINT->hyprListener_destroyConstraint.initCallback(&PCONSTRAINT->events.destroy, &Events::listener_destroyConstraint, CONSTRAINT, "Constraint");
|
CONSTRAINT->hyprListener_destroyConstraint.initCallback(&PCONSTRAINT->events.destroy, &Events::listener_destroyConstraint, CONSTRAINT, "Constraint");
|
||||||
@@ -110,6 +108,9 @@ void Events::listener_newConstraint(wl_listener* listener, void* data) {
|
|||||||
|
|
||||||
if (g_pCompositor->m_pLastFocus == PCONSTRAINT->surface) {
|
if (g_pCompositor->m_pLastFocus == PCONSTRAINT->surface) {
|
||||||
g_pInputManager->constrainMouse(CONSTRAINT->pMouse, PCONSTRAINT);
|
g_pInputManager->constrainMouse(CONSTRAINT->pMouse, PCONSTRAINT);
|
||||||
|
|
||||||
|
if (!CONSTRAINT->hintSet)
|
||||||
|
CONSTRAINT->positionHint = Vector2D{-1, -1};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,24 +122,24 @@ void Events::listener_destroyConstraint(void* owner, void* data) {
|
|||||||
|
|
||||||
const auto PWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
|
const auto PWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
|
||||||
|
|
||||||
if (PWINDOW) {
|
if (PWINDOW && PCONSTRAINT->positionHint != Vector2D{-1, -1}) {
|
||||||
if (PWINDOW->m_bIsX11) {
|
if (PWINDOW->m_bIsX11) {
|
||||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr,
|
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PCONSTRAINT->positionHint.x + PWINDOW->m_uSurface.xwayland->x,
|
||||||
PCONSTRAINT->constraint->current.cursor_hint.x + PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y + PCONSTRAINT->constraint->current.cursor_hint.y);
|
PWINDOW->m_uSurface.xwayland->y + PCONSTRAINT->positionHint.y);
|
||||||
|
|
||||||
wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->constraint->current.cursor_hint.x, PCONSTRAINT->constraint->current.cursor_hint.y);
|
wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->positionHint.x, PCONSTRAINT->positionHint.y);
|
||||||
} else {
|
} else {
|
||||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr,
|
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PCONSTRAINT->positionHint.x + PWINDOW->m_vRealPosition.vec().x,
|
||||||
PCONSTRAINT->constraint->current.cursor_hint.x + PWINDOW->m_vRealPosition.vec().x, PCONSTRAINT->constraint->current.cursor_hint.y + PWINDOW->m_vRealPosition.vec().y);
|
PCONSTRAINT->positionHint.y + PWINDOW->m_vRealPosition.vec().y);
|
||||||
|
|
||||||
wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->constraint->current.cursor_hint.x, PCONSTRAINT->constraint->current.cursor_hint.y);
|
wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->positionHint.x, PCONSTRAINT->positionHint.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PCONSTRAINT->pMouse->currentConstraint = nullptr;
|
PCONSTRAINT->pMouse->currentConstraint = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Unconstrained mouse from %x", PCONSTRAINT->constraint);
|
Debug::log(LOG, "Unconstrained mouse from %lx", PCONSTRAINT->constraint);
|
||||||
|
|
||||||
g_pInputManager->m_lConstraints.remove(*PCONSTRAINT);
|
g_pInputManager->m_lConstraints.remove(*PCONSTRAINT);
|
||||||
}
|
}
|
||||||
@@ -148,9 +149,9 @@ void Events::listener_setConstraintRegion(void* owner, void* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_newVirtPtr(wl_listener* listener, void* data) {
|
void Events::listener_newVirtPtr(wl_listener* listener, void* data) {
|
||||||
const auto EV = (wlr_virtual_pointer_v1_new_pointer_event*)data;
|
const auto EV = (wlr_virtual_pointer_v1_new_pointer_event*)data;
|
||||||
const auto POINTER = EV->new_pointer;
|
const auto POINTER = EV->new_pointer;
|
||||||
const auto DEVICE = &POINTER->pointer.base;
|
const auto DEVICE = &POINTER->pointer.base;
|
||||||
|
|
||||||
g_pInputManager->newMouse(DEVICE, true);
|
g_pInputManager->newMouse(DEVICE, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace Events {
|
|||||||
DYNLISTENFUNC(commitSubsurface);
|
DYNLISTENFUNC(commitSubsurface);
|
||||||
|
|
||||||
// Popups
|
// Popups
|
||||||
DYNLISTENFUNC(newPopup); // LayerSurface
|
DYNLISTENFUNC(newPopup); // LayerSurface
|
||||||
|
|
||||||
DYNLISTENFUNC(newPopupXDG);
|
DYNLISTENFUNC(newPopupXDG);
|
||||||
DYNLISTENFUNC(mapPopupXDG);
|
DYNLISTENFUNC(mapPopupXDG);
|
||||||
@@ -42,6 +42,7 @@ namespace Events {
|
|||||||
|
|
||||||
// Surface XDG (window)
|
// Surface XDG (window)
|
||||||
LISTENER(newXDGSurface);
|
LISTENER(newXDGSurface);
|
||||||
|
LISTENER(activateXDG);
|
||||||
|
|
||||||
// Window events
|
// Window events
|
||||||
DYNLISTENFUNC(commitWindow);
|
DYNLISTENFUNC(commitWindow);
|
||||||
@@ -57,9 +58,10 @@ namespace Events {
|
|||||||
DYNLISTENFUNC(requestResize);
|
DYNLISTENFUNC(requestResize);
|
||||||
DYNLISTENFUNC(requestMinimize);
|
DYNLISTENFUNC(requestMinimize);
|
||||||
DYNLISTENFUNC(requestMaximize);
|
DYNLISTENFUNC(requestMaximize);
|
||||||
|
DYNLISTENFUNC(setOverrideRedirect);
|
||||||
|
|
||||||
// Window subsurfaces
|
// Window subsurfaces
|
||||||
// LISTENER(newSubsurfaceWindow);
|
// LISTENER(newSubsurfaceWindow);
|
||||||
|
|
||||||
// Input events
|
// Input events
|
||||||
LISTENER(mouseMove);
|
LISTENER(mouseMove);
|
||||||
@@ -87,7 +89,6 @@ namespace Events {
|
|||||||
LISTENER(requestMouse);
|
LISTENER(requestMouse);
|
||||||
LISTENER(requestSetSel);
|
LISTENER(requestSetSel);
|
||||||
LISTENER(requestSetPrimarySel);
|
LISTENER(requestSetPrimarySel);
|
||||||
DYNLISTENFUNC(activate);
|
|
||||||
|
|
||||||
// outputMgr
|
// outputMgr
|
||||||
LISTENER(outputMgrApply);
|
LISTENER(outputMgrApply);
|
||||||
@@ -96,6 +97,10 @@ namespace Events {
|
|||||||
// Monitor part 2 the sequel
|
// Monitor part 2 the sequel
|
||||||
DYNLISTENFUNC(monitorFrame);
|
DYNLISTENFUNC(monitorFrame);
|
||||||
DYNLISTENFUNC(monitorDestroy);
|
DYNLISTENFUNC(monitorDestroy);
|
||||||
|
DYNLISTENFUNC(monitorStateRequest);
|
||||||
|
DYNLISTENFUNC(monitorDamage);
|
||||||
|
DYNLISTENFUNC(monitorNeedsFrame);
|
||||||
|
DYNLISTENFUNC(monitorCommit);
|
||||||
|
|
||||||
// XWayland
|
// XWayland
|
||||||
LISTENER(readyXWayland);
|
LISTENER(readyXWayland);
|
||||||
@@ -156,4 +161,7 @@ namespace Events {
|
|||||||
|
|
||||||
LISTENER(holdBegin);
|
LISTENER(holdBegin);
|
||||||
LISTENER(holdEnd);
|
LISTENER(holdEnd);
|
||||||
|
|
||||||
|
// Session Lock
|
||||||
|
LISTENER(newSessionLock);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,15 +31,17 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
|
|||||||
WLRLAYERSURFACE->output = PMONITOR->output;
|
WLRLAYERSURFACE->output = PMONITOR->output;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto PMONITOR = (CMonitor*)g_pCompositor->getMonitorFromOutput(WLRLAYERSURFACE->output);
|
auto PMONITOR = (CMonitor*)g_pCompositor->getMonitorFromOutput(WLRLAYERSURFACE->output);
|
||||||
SLayerSurface* layerSurface = PMONITOR->m_aLayerSurfaceLists[WLRLAYERSURFACE->pending.layer].emplace_back(std::make_unique<SLayerSurface>()).get();
|
|
||||||
|
if (!WLRLAYERSURFACE->output || !PMONITOR || PMONITOR->pMirrorOf) {
|
||||||
|
PMONITOR = g_pCompositor->m_vMonitors.front().get();
|
||||||
|
WLRLAYERSURFACE->output = PMONITOR->output; // TODO: current mon
|
||||||
|
}
|
||||||
|
|
||||||
|
SLayerSurface* layerSurface = PMONITOR->m_aLayerSurfaceLayers[WLRLAYERSURFACE->pending.layer].emplace_back(std::make_unique<SLayerSurface>()).get();
|
||||||
|
|
||||||
layerSurface->szNamespace = WLRLAYERSURFACE->_namespace;
|
layerSurface->szNamespace = WLRLAYERSURFACE->_namespace;
|
||||||
|
|
||||||
if (!WLRLAYERSURFACE->output) {
|
|
||||||
WLRLAYERSURFACE->output = g_pCompositor->m_vMonitors.front()->output; // TODO: current mon
|
|
||||||
}
|
|
||||||
|
|
||||||
layerSurface->hyprListener_commitLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.commit, &Events::listener_commitLayerSurface, layerSurface, "layerSurface");
|
layerSurface->hyprListener_commitLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.commit, &Events::listener_commitLayerSurface, layerSurface, "layerSurface");
|
||||||
layerSurface->hyprListener_destroyLayerSurface.initCallback(&WLRLAYERSURFACE->events.destroy, &Events::listener_destroyLayerSurface, layerSurface, "layerSurface");
|
layerSurface->hyprListener_destroyLayerSurface.initCallback(&WLRLAYERSURFACE->events.destroy, &Events::listener_destroyLayerSurface, layerSurface, "layerSurface");
|
||||||
layerSurface->hyprListener_mapLayerSurface.initCallback(&WLRLAYERSURFACE->events.map, &Events::listener_mapLayerSurface, layerSurface, "layerSurface");
|
layerSurface->hyprListener_mapLayerSurface.initCallback(&WLRLAYERSURFACE->events.map, &Events::listener_mapLayerSurface, layerSurface, "layerSurface");
|
||||||
@@ -47,19 +49,20 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
|
|||||||
layerSurface->hyprListener_newPopup.initCallback(&WLRLAYERSURFACE->events.new_popup, &Events::listener_newPopup, layerSurface, "layerSurface");
|
layerSurface->hyprListener_newPopup.initCallback(&WLRLAYERSURFACE->events.new_popup, &Events::listener_newPopup, layerSurface, "layerSurface");
|
||||||
|
|
||||||
layerSurface->layerSurface = WLRLAYERSURFACE;
|
layerSurface->layerSurface = WLRLAYERSURFACE;
|
||||||
layerSurface->layer = WLRLAYERSURFACE->current.layer;
|
layerSurface->layer = WLRLAYERSURFACE->current.layer;
|
||||||
WLRLAYERSURFACE->data = layerSurface;
|
WLRLAYERSURFACE->data = layerSurface;
|
||||||
layerSurface->monitorID = PMONITOR->ID;
|
layerSurface->monitorID = PMONITOR->ID;
|
||||||
|
|
||||||
layerSurface->forceBlur = g_pConfigManager->shouldBlurLS(layerSurface->szNamespace);
|
layerSurface->forceBlur = g_pConfigManager->shouldBlurLS(layerSurface->szNamespace);
|
||||||
|
|
||||||
Debug::log(LOG, "LayerSurface %x (namespace %s layer %d) created on monitor %s", layerSurface->layerSurface, layerSurface->layerSurface->_namespace, layerSurface->layer, PMONITOR->szName.c_str());
|
Debug::log(LOG, "LayerSurface %lx (namespace %s layer %d) created on monitor %s", layerSurface->layerSurface, layerSurface->layerSurface->_namespace, layerSurface->layer,
|
||||||
|
PMONITOR->szName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_destroyLayerSurface(void* owner, void* data) {
|
void Events::listener_destroyLayerSurface(void* owner, void* data) {
|
||||||
SLayerSurface* layersurface = (SLayerSurface*)owner;
|
SLayerSurface* layersurface = (SLayerSurface*)owner;
|
||||||
|
|
||||||
Debug::log(LOG, "LayerSurface %x destroyed", layersurface->layerSurface);
|
Debug::log(LOG, "LayerSurface %lx destroyed", layersurface->layerSurface);
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
||||||
|
|
||||||
@@ -92,21 +95,24 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
|
|||||||
PMONITOR->scheduledRecalc = true;
|
PMONITOR->scheduledRecalc = true;
|
||||||
|
|
||||||
// and damage
|
// and damage
|
||||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
|
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||||
|
layersurface->geometry.height};
|
||||||
g_pHyprRenderer->damageBox(&geomFixed);
|
g_pHyprRenderer->damageBox(&geomFixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
layersurface->readyToDelete = true;
|
layersurface->readyToDelete = true;
|
||||||
layersurface->layerSurface = nullptr;
|
layersurface->layerSurface = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_mapLayerSurface(void* owner, void* data) {
|
void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||||
SLayerSurface* layersurface = (SLayerSurface*)owner;
|
SLayerSurface* layersurface = (SLayerSurface*)owner;
|
||||||
|
|
||||||
Debug::log(LOG, "LayerSurface %x mapped", layersurface->layerSurface);
|
Debug::log(LOG, "LayerSurface %lx mapped", layersurface->layerSurface);
|
||||||
|
|
||||||
layersurface->layerSurface->mapped = true;
|
layersurface->layerSurface->mapped = true;
|
||||||
layersurface->mapped = true;
|
layersurface->mapped = true;
|
||||||
|
|
||||||
|
layersurface->surface = layersurface->layerSurface->surface;
|
||||||
|
|
||||||
// anim
|
// anim
|
||||||
layersurface->alpha.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn"));
|
layersurface->alpha.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn"));
|
||||||
@@ -117,16 +123,18 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
|||||||
if (!PMONITOR)
|
if (!PMONITOR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
layersurface->applyRules();
|
||||||
|
|
||||||
if ((uint64_t)layersurface->monitorID != PMONITOR->ID) {
|
if ((uint64_t)layersurface->monitorID != PMONITOR->ID) {
|
||||||
const auto POLDMON = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
const auto POLDMON = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
||||||
for (auto it = POLDMON->m_aLayerSurfaceLists[layersurface->layer].begin(); it != POLDMON->m_aLayerSurfaceLists[layersurface->layer].end(); it++) {
|
for (auto it = POLDMON->m_aLayerSurfaceLayers[layersurface->layer].begin(); it != POLDMON->m_aLayerSurfaceLayers[layersurface->layer].end(); it++) {
|
||||||
if (it->get() == layersurface) {
|
if (it->get() == layersurface) {
|
||||||
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].emplace_back(std::move(*it));
|
PMONITOR->m_aLayerSurfaceLayers[layersurface->layer].emplace_back(std::move(*it));
|
||||||
POLDMON->m_aLayerSurfaceLists[layersurface->layer].erase(it);
|
POLDMON->m_aLayerSurfaceLayers[layersurface->layer].erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
layersurface->monitorID = PMONITOR->ID;
|
layersurface->monitorID = PMONITOR->ID;
|
||||||
PMONITOR->scheduledRecalc = true;
|
PMONITOR->scheduledRecalc = true;
|
||||||
g_pHyprRenderer->arrangeLayersForMonitor(POLDMON->ID);
|
g_pHyprRenderer->arrangeLayersForMonitor(POLDMON->ID);
|
||||||
}
|
}
|
||||||
@@ -135,29 +143,40 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
|||||||
|
|
||||||
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
|
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
|
||||||
|
|
||||||
if (layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)) { // don't focus if constrained
|
if (layersurface->layerSurface->current.keyboard_interactive &&
|
||||||
|
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)) { // don't focus if constrained
|
||||||
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
|
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
|
||||||
|
|
||||||
const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y);
|
const auto LOCAL =
|
||||||
|
g_pInputManager->getMouseCoordsInternal() - Vector2D(layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y);
|
||||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, layersurface->layerSurface->surface, LOCAL.x, LOCAL.y);
|
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, layersurface->layerSurface->surface, LOCAL.x, LOCAL.y);
|
||||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, 0, LOCAL.x, LOCAL.y);
|
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, 0, LOCAL.x, LOCAL.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
|
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
|
||||||
|
|
||||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
|
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||||
|
layersurface->geometry.height};
|
||||||
g_pHyprRenderer->damageBox(&geomFixed);
|
g_pHyprRenderer->damageBox(&geomFixed);
|
||||||
|
|
||||||
layersurface->alpha.setValue(0);
|
layersurface->alpha.setValue(0);
|
||||||
layersurface->alpha = 255.f;
|
layersurface->alpha = 1.f;
|
||||||
layersurface->readyToDelete = false;
|
layersurface->readyToDelete = false;
|
||||||
layersurface->fadingOut = false;
|
layersurface->fadingOut = false;
|
||||||
|
|
||||||
|
g_pEventManager->postEvent(SHyprIPCEvent{"openlayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")});
|
||||||
|
EMIT_HOOK_EVENT("openLayer", layersurface);
|
||||||
|
|
||||||
|
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||||
SLayerSurface* layersurface = (SLayerSurface*)owner;
|
SLayerSurface* layersurface = (SLayerSurface*)owner;
|
||||||
|
|
||||||
Debug::log(LOG, "LayerSurface %x unmapped", layersurface->layerSurface);
|
Debug::log(LOG, "LayerSurface %lx unmapped", layersurface->layerSurface);
|
||||||
|
|
||||||
|
g_pEventManager->postEvent(SHyprIPCEvent{"closelayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")});
|
||||||
|
EMIT_HOOK_EVENT("closeLayer", layersurface);
|
||||||
|
|
||||||
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID) || g_pCompositor->m_bUnsafeState) {
|
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID) || g_pCompositor->m_bUnsafeState) {
|
||||||
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
|
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
|
||||||
@@ -190,23 +209,49 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
|||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
|
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
|
||||||
|
|
||||||
|
const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == layersurface->layerSurface->surface;
|
||||||
|
|
||||||
|
layersurface->surface = nullptr;
|
||||||
|
|
||||||
if (!PMONITOR)
|
if (!PMONITOR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// refocus if needed
|
// refocus if needed
|
||||||
if (layersurface->layerSurface->surface == g_pCompositor->m_pLastFocus) {
|
if (WASLASTFOCUS) {
|
||||||
|
g_pInputManager->releaseAllMouseButtons();
|
||||||
|
|
||||||
|
Vector2D surfaceCoords;
|
||||||
|
SLayerSurface* pFoundLayerSurface = nullptr;
|
||||||
|
wlr_surface* foundSurface = nullptr;
|
||||||
|
|
||||||
g_pCompositor->m_pLastFocus = nullptr;
|
g_pCompositor->m_pLastFocus = nullptr;
|
||||||
g_pInputManager->refocus();
|
|
||||||
|
// find LS-es to focus
|
||||||
|
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
|
||||||
|
&surfaceCoords, &pFoundLayerSurface);
|
||||||
|
|
||||||
|
if (!foundSurface)
|
||||||
|
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
|
||||||
|
&surfaceCoords, &pFoundLayerSurface);
|
||||||
|
|
||||||
|
if (!foundSurface) {
|
||||||
|
// if there isn't any, focus the last window
|
||||||
|
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow;
|
||||||
|
g_pCompositor->focusWindow(nullptr);
|
||||||
|
g_pCompositor->focusWindow(PLASTWINDOW);
|
||||||
|
} else {
|
||||||
|
// otherwise, full refocus
|
||||||
|
g_pInputManager->refocus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
|
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||||
|
layersurface->geometry.height};
|
||||||
g_pHyprRenderer->damageBox(&geomFixed);
|
g_pHyprRenderer->damageBox(&geomFixed);
|
||||||
|
|
||||||
geomFixed = {layersurface->geometry.x + (int)PMONITOR->vecPosition.x, layersurface->geometry.y + (int)PMONITOR->vecPosition.y, (int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
|
geomFixed = {layersurface->geometry.x + (int)PMONITOR->vecPosition.x, layersurface->geometry.y + (int)PMONITOR->vecPosition.y,
|
||||||
|
(int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
|
||||||
g_pHyprRenderer->damageBox(&geomFixed);
|
g_pHyprRenderer->damageBox(&geomFixed);
|
||||||
|
|
||||||
geomFixed = {layersurface->geometry.x, layersurface->geometry.y, (int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
|
|
||||||
layersurface->geometry = geomFixed; // because the surface can overflow... for some reason?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_commitLayerSurface(void* owner, void* data) {
|
void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||||
@@ -221,7 +266,7 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
|
if (layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
|
||||||
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
|
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
|
||||||
|
|
||||||
wlr_box geomFixed = {layersurface->geometry.x, layersurface->geometry.y, layersurface->geometry.width, layersurface->geometry.height};
|
wlr_box geomFixed = {layersurface->geometry.x, layersurface->geometry.y, layersurface->geometry.width, layersurface->geometry.height};
|
||||||
g_pHyprRenderer->damageBox(&geomFixed);
|
g_pHyprRenderer->damageBox(&geomFixed);
|
||||||
@@ -230,15 +275,15 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
|||||||
if ((uint64_t)layersurface->monitorID != PMONITOR->ID) {
|
if ((uint64_t)layersurface->monitorID != PMONITOR->ID) {
|
||||||
const auto POLDMON = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
const auto POLDMON = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
||||||
|
|
||||||
for (auto it = POLDMON->m_aLayerSurfaceLists[layersurface->layer].begin(); it != POLDMON->m_aLayerSurfaceLists[layersurface->layer].end(); it++) {
|
for (auto it = POLDMON->m_aLayerSurfaceLayers[layersurface->layer].begin(); it != POLDMON->m_aLayerSurfaceLayers[layersurface->layer].end(); it++) {
|
||||||
if (it->get() == layersurface) {
|
if (it->get() == layersurface) {
|
||||||
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].emplace_back(std::move(*it));
|
PMONITOR->m_aLayerSurfaceLayers[layersurface->layer].emplace_back(std::move(*it));
|
||||||
POLDMON->m_aLayerSurfaceLists[layersurface->layer].erase(it);
|
POLDMON->m_aLayerSurfaceLayers[layersurface->layer].erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layersurface->monitorID = PMONITOR->ID;
|
layersurface->monitorID = PMONITOR->ID;
|
||||||
PMONITOR->scheduledRecalc = true;
|
PMONITOR->scheduledRecalc = true;
|
||||||
g_pHyprRenderer->arrangeLayersForMonitor(POLDMON->ID);
|
g_pHyprRenderer->arrangeLayersForMonitor(POLDMON->ID);
|
||||||
}
|
}
|
||||||
@@ -246,10 +291,10 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
|||||||
if (layersurface->layerSurface->current.committed != 0) {
|
if (layersurface->layerSurface->current.committed != 0) {
|
||||||
if (layersurface->layer != layersurface->layerSurface->current.layer) {
|
if (layersurface->layer != layersurface->layerSurface->current.layer) {
|
||||||
|
|
||||||
for (auto it = PMONITOR->m_aLayerSurfaceLists[layersurface->layer].begin(); it != PMONITOR->m_aLayerSurfaceLists[layersurface->layer].end(); it++) {
|
for (auto it = PMONITOR->m_aLayerSurfaceLayers[layersurface->layer].begin(); it != PMONITOR->m_aLayerSurfaceLayers[layersurface->layer].end(); it++) {
|
||||||
if (it->get() == layersurface) {
|
if (it->get() == layersurface) {
|
||||||
PMONITOR->m_aLayerSurfaceLists[layersurface->layerSurface->current.layer].emplace_back(std::move(*it));
|
PMONITOR->m_aLayerSurfaceLayers[layersurface->layerSurface->current.layer].emplace_back(std::move(*it));
|
||||||
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].erase(it);
|
PMONITOR->m_aLayerSurfaceLayers[layersurface->layer].erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,18 +302,28 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
|||||||
layersurface->layer = layersurface->layerSurface->current.layer;
|
layersurface->layer = layersurface->layerSurface->current.layer;
|
||||||
|
|
||||||
if (layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
|
if (layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
|
||||||
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
|
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
|
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
|
||||||
|
|
||||||
PMONITOR->scheduledRecalc = true;
|
PMONITOR->scheduledRecalc = true;
|
||||||
|
} else {
|
||||||
|
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
|
||||||
|
|
||||||
|
// update geom if it changed
|
||||||
|
if (layersurface->layerSurface->surface->current.scale == 1 && PMONITOR->scale != 1.f && layersurface->layerSurface->surface->current.viewport.has_dst) {
|
||||||
|
// fractional scaling. Dirty hack.
|
||||||
|
layersurface->geometry = {layersurface->geometry.x, layersurface->geometry.y, (int)(layersurface->layerSurface->surface->current.viewport.dst_width),
|
||||||
|
(int)(layersurface->layerSurface->surface->current.viewport.dst_height)};
|
||||||
|
} else {
|
||||||
|
// this is because some apps like e.g. rofi-lbonn can't fucking use the protocol correctly.
|
||||||
|
layersurface->geometry = {layersurface->geometry.x, layersurface->geometry.y, (int)layersurface->layerSurface->surface->current.width,
|
||||||
|
(int)layersurface->layerSurface->surface->current.height};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
|
|
||||||
|
|
||||||
// update geom if it changed
|
|
||||||
layersurface->geometry = {layersurface->geometry.x, layersurface->geometry.y, layersurface->layerSurface->surface->current.width, layersurface->layerSurface->surface->current.height};
|
|
||||||
|
|
||||||
g_pHyprRenderer->damageSurface(layersurface->layerSurface->surface, layersurface->position.x, layersurface->position.y);
|
g_pHyprRenderer->damageSurface(layersurface->layerSurface->surface, layersurface->position.x, layersurface->position.y);
|
||||||
|
|
||||||
|
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ void Events::listener_outputMgrTest(wl_listener* listener, void* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_leaseRequest(wl_listener* listener, void* data) {
|
void Events::listener_leaseRequest(wl_listener* listener, void* data) {
|
||||||
const auto REQUEST = (wlr_drm_lease_request_v1*)data;
|
const auto REQUEST = (wlr_drm_lease_request_v1*)data;
|
||||||
struct wlr_drm_lease_v1* lease = wlr_drm_lease_request_v1_grant(REQUEST);
|
struct wlr_drm_lease_v1* lease = wlr_drm_lease_request_v1_grant(REQUEST);
|
||||||
if (!lease) {
|
if (!lease) {
|
||||||
Debug::log(ERR, "Failed to grant lease request!");
|
Debug::log(ERR, "Failed to grant lease request!");
|
||||||
wlr_drm_lease_request_v1_reject(REQUEST);
|
wlr_drm_lease_request_v1_reject(REQUEST);
|
||||||
@@ -45,8 +45,9 @@ void Events::listener_requestSetSel(wl_listener* listener, void* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_readyXWayland(wl_listener* listener, void* data) {
|
void Events::listener_readyXWayland(wl_listener* listener, void* data) {
|
||||||
|
#ifndef NO_XWAYLAND
|
||||||
const auto XCBCONNECTION = xcb_connect(g_pXWaylandManager->m_sWLRXWayland->display_name, NULL);
|
const auto XCBCONNECTION = xcb_connect(g_pXWaylandManager->m_sWLRXWayland->display_name, NULL);
|
||||||
const auto ERR = xcb_connection_has_error(XCBCONNECTION);
|
const auto ERR = xcb_connection_has_error(XCBCONNECTION);
|
||||||
if (ERR) {
|
if (ERR) {
|
||||||
Debug::log(LogLevel::ERR, "XWayland -> xcb_connection_has_error failed with %i", ERR);
|
Debug::log(LogLevel::ERR, "XWayland -> xcb_connection_has_error failed with %i", ERR);
|
||||||
return;
|
return;
|
||||||
@@ -54,7 +55,7 @@ void Events::listener_readyXWayland(wl_listener* listener, void* data) {
|
|||||||
|
|
||||||
for (auto& ATOM : HYPRATOMS) {
|
for (auto& ATOM : HYPRATOMS) {
|
||||||
xcb_intern_atom_cookie_t cookie = xcb_intern_atom(XCBCONNECTION, 0, ATOM.first.length(), ATOM.first.c_str());
|
xcb_intern_atom_cookie_t cookie = xcb_intern_atom(XCBCONNECTION, 0, ATOM.first.length(), ATOM.first.c_str());
|
||||||
xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(XCBCONNECTION, cookie, NULL);
|
xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(XCBCONNECTION, cookie, NULL);
|
||||||
|
|
||||||
if (!reply) {
|
if (!reply) {
|
||||||
Debug::log(LogLevel::ERR, "XWayland -> Atom failed: %s", ATOM.first.c_str());
|
Debug::log(LogLevel::ERR, "XWayland -> Atom failed: %s", ATOM.first.c_str());
|
||||||
@@ -68,10 +69,12 @@ void Events::listener_readyXWayland(wl_listener* listener, void* data) {
|
|||||||
|
|
||||||
const auto XCURSOR = wlr_xcursor_manager_get_xcursor(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", 1);
|
const auto XCURSOR = wlr_xcursor_manager_get_xcursor(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", 1);
|
||||||
if (XCURSOR) {
|
if (XCURSOR) {
|
||||||
wlr_xwayland_set_cursor(g_pXWaylandManager->m_sWLRXWayland, XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, XCURSOR->images[0]->width, XCURSOR->images[0]->height, XCURSOR->images[0]->hotspot_x, XCURSOR->images[0]->hotspot_y);
|
wlr_xwayland_set_cursor(g_pXWaylandManager->m_sWLRXWayland, XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, XCURSOR->images[0]->width,
|
||||||
|
XCURSOR->images[0]->height, XCURSOR->images[0]->hotspot_x, XCURSOR->images[0]->hotspot_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_disconnect(XCBCONNECTION);
|
xcb_disconnect(XCBCONNECTION);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_requestDrag(wl_listener* listener, void* data) {
|
void Events::listener_requestDrag(wl_listener* listener, void* data) {
|
||||||
@@ -95,48 +98,36 @@ void Events::listener_startDrag(wl_listener* listener, void* data) {
|
|||||||
|
|
||||||
wlr_drag* wlrDrag = (wlr_drag*)data;
|
wlr_drag* wlrDrag = (wlr_drag*)data;
|
||||||
|
|
||||||
Debug::log(LOG, "Started drag %x", wlrDrag);
|
Debug::log(LOG, "Started drag %lx", wlrDrag);
|
||||||
|
|
||||||
wlrDrag->data = data;
|
wlrDrag->data = data;
|
||||||
|
|
||||||
g_pInputManager->m_sDrag.hyprListener_destroy.initCallback(&wlrDrag->events.destroy, &Events::listener_destroyDrag, &g_pInputManager->m_sDrag, "Drag");
|
g_pInputManager->m_sDrag.hyprListener_destroy.initCallback(&wlrDrag->events.destroy, &Events::listener_destroyDrag, &g_pInputManager->m_sDrag, "Drag");
|
||||||
|
|
||||||
if (wlrDrag->icon) {
|
if (wlrDrag->icon) {
|
||||||
Debug::log(LOG, "Drag started with an icon %x", wlrDrag->icon);
|
Debug::log(LOG, "Drag started with an icon %lx", wlrDrag->icon);
|
||||||
|
|
||||||
g_pInputManager->m_sDrag.dragIcon = wlrDrag->icon;
|
g_pInputManager->m_sDrag.dragIcon = wlrDrag->icon;
|
||||||
wlrDrag->icon->data = g_pInputManager->m_sDrag.dragIcon;
|
wlrDrag->icon->data = g_pInputManager->m_sDrag.dragIcon;
|
||||||
|
|
||||||
g_pInputManager->m_sDrag.hyprListener_mapIcon.initCallback(&wlrDrag->icon->events.map, &Events::listener_mapDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
|
g_pInputManager->m_sDrag.hyprListener_mapIcon.initCallback(&wlrDrag->icon->events.map, &Events::listener_mapDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
|
||||||
g_pInputManager->m_sDrag.hyprListener_unmapIcon.initCallback(&wlrDrag->icon->events.unmap, &Events::listener_unmapDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
|
g_pInputManager->m_sDrag.hyprListener_unmapIcon.initCallback(&wlrDrag->icon->events.unmap, &Events::listener_unmapDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
|
||||||
g_pInputManager->m_sDrag.hyprListener_destroyIcon.initCallback(&wlrDrag->icon->events.destroy, &Events::listener_destroyDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
|
g_pInputManager->m_sDrag.hyprListener_destroyIcon.initCallback(&wlrDrag->icon->events.destroy, &Events::listener_destroyDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
|
||||||
g_pInputManager->m_sDrag.hyprListener_commitIcon.initCallback(&wlrDrag->icon->surface->events.commit, &Events::listener_commitDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
|
g_pInputManager->m_sDrag.hyprListener_commitIcon.initCallback(&wlrDrag->icon->surface->events.commit, &Events::listener_commitDragIcon, &g_pInputManager->m_sDrag,
|
||||||
|
"DragIcon");
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto *const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue;
|
|
||||||
|
|
||||||
if (*PFOLLOWONDND)
|
|
||||||
g_pInputManager->m_pFollowOnDnDBegin = g_pCompositor->m_pLastWindow;
|
|
||||||
else
|
|
||||||
g_pInputManager->m_pFollowOnDnDBegin = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_destroyDrag(void* owner, void* data) {
|
void Events::listener_destroyDrag(void* owner, void* data) {
|
||||||
Debug::log(LOG, "Drag destroyed.");
|
Debug::log(LOG, "Drag destroyed.");
|
||||||
|
|
||||||
if (g_pInputManager->m_sDrag.drag && g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.dragIcon->surface)
|
if (g_pInputManager->m_sDrag.drag && g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.dragIcon->surface)
|
||||||
g_pHyprRenderer->damageBox(g_pInputManager->m_sDrag.pos.x - 2, g_pInputManager->m_sDrag.pos.y - 2, g_pInputManager->m_sDrag.dragIcon->surface->current.width + 4, g_pInputManager->m_sDrag.dragIcon->surface->current.height + 4);
|
g_pHyprRenderer->damageBox(g_pInputManager->m_sDrag.pos.x - 2, g_pInputManager->m_sDrag.pos.y - 2, g_pInputManager->m_sDrag.dragIcon->surface->current.width + 4,
|
||||||
|
g_pInputManager->m_sDrag.dragIcon->surface->current.height + 4);
|
||||||
|
|
||||||
g_pInputManager->m_sDrag.drag = nullptr;
|
g_pInputManager->m_sDrag.drag = nullptr;
|
||||||
g_pInputManager->m_sDrag.dragIcon = nullptr;
|
g_pInputManager->m_sDrag.dragIcon = nullptr;
|
||||||
g_pInputManager->m_sDrag.hyprListener_destroy.removeCallback();
|
g_pInputManager->m_sDrag.hyprListener_destroy.removeCallback();
|
||||||
|
|
||||||
g_pInputManager->refocus();
|
|
||||||
|
|
||||||
if (g_pInputManager->m_pFollowOnDnDBegin)
|
|
||||||
g_pCompositor->focusWindow(g_pInputManager->m_pFollowOnDnDBegin);
|
|
||||||
|
|
||||||
g_pInputManager->m_pFollowOnDnDBegin = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_mapDragIcon(void* owner, void* data) {
|
void Events::listener_mapDragIcon(void* owner, void* data) {
|
||||||
@@ -166,7 +157,7 @@ void Events::listener_commitDragIcon(void* owner, void* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_InhibitActivate(wl_listener* listener, void* data) {
|
void Events::listener_InhibitActivate(wl_listener* listener, void* data) {
|
||||||
Debug::log(LOG, "Activated exclusive for %x.", g_pCompositor->m_sSeat.exclusiveClient);
|
Debug::log(LOG, "Activated exclusive for %lx.", g_pCompositor->m_sSeat.exclusiveClient);
|
||||||
|
|
||||||
g_pInputManager->refocus();
|
g_pInputManager->refocus();
|
||||||
g_pCompositor->m_sSeat.exclusiveClient = g_pCompositor->m_sWLRInhibitMgr->active_client;
|
g_pCompositor->m_sSeat.exclusiveClient = g_pCompositor->m_sWLRInhibitMgr->active_client;
|
||||||
@@ -187,6 +178,12 @@ void Events::listener_sessionActive(wl_listener* listener, void* data) {
|
|||||||
Debug::log(LOG, "Session got activated!");
|
Debug::log(LOG, "Session got activated!");
|
||||||
|
|
||||||
g_pCompositor->m_bSessionActive = true;
|
g_pCompositor->m_bSessionActive = true;
|
||||||
|
|
||||||
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||||
|
g_pCompositor->scheduleFrameForMonitor(m.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_powerMgrSetMode(wl_listener* listener, void* data) {
|
void Events::listener_powerMgrSetMode(wl_listener* listener, void* data) {
|
||||||
@@ -211,3 +208,9 @@ void Events::listener_newTextInput(wl_listener* listener, void* data) {
|
|||||||
|
|
||||||
g_pInputManager->m_sIMERelay.onNewTextInput((wlr_text_input_v3*)data);
|
g_pInputManager->m_sIMERelay.onNewTextInput((wlr_text_input_v3*)data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Events::listener_newSessionLock(wl_listener* listener, void* data) {
|
||||||
|
Debug::log(LOG, "New session lock!");
|
||||||
|
|
||||||
|
g_pSessionLockManager->onNewSessionLock((wlr_session_lock_v1*)data);
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,13 +15,17 @@
|
|||||||
// //
|
// //
|
||||||
// --------------------------------------------------------- //
|
// --------------------------------------------------------- //
|
||||||
|
|
||||||
CMonitor* pMostHzMonitor = nullptr;
|
|
||||||
|
|
||||||
void Events::listener_change(wl_listener* listener, void* data) {
|
void Events::listener_change(wl_listener* listener, void* data) {
|
||||||
// layout got changed, let's update monitors.
|
// layout got changed, let's update monitors.
|
||||||
const auto CONFIG = wlr_output_configuration_v1_create();
|
const auto CONFIG = wlr_output_configuration_v1_create();
|
||||||
|
|
||||||
|
if (!CONFIG)
|
||||||
|
return;
|
||||||
|
|
||||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||||
|
if (!m->output)
|
||||||
|
continue;
|
||||||
|
|
||||||
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m->output);
|
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m->output);
|
||||||
|
|
||||||
// TODO: clients off of disabled
|
// TODO: clients off of disabled
|
||||||
@@ -29,25 +33,26 @@ void Events::listener_change(wl_listener* listener, void* data) {
|
|||||||
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, &BOX);
|
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, &BOX);
|
||||||
|
|
||||||
//m->vecSize.x = BOX.width;
|
//m->vecSize.x = BOX.width;
|
||||||
// m->vecSize.y = BOX.height;
|
// m->vecSize.y = BOX.height;
|
||||||
m->vecPosition.x = BOX.x;
|
m->vecPosition.x = BOX.x;
|
||||||
m->vecPosition.y = BOX.y;
|
m->vecPosition.y = BOX.y;
|
||||||
|
|
||||||
CONFIGHEAD->state.enabled = m->output->enabled;
|
CONFIGHEAD->state.enabled = m->output->enabled;
|
||||||
CONFIGHEAD->state.mode = m->output->current_mode;
|
CONFIGHEAD->state.mode = m->output->current_mode;
|
||||||
CONFIGHEAD->state.x = m->vecPosition.x;
|
CONFIGHEAD->state.x = m->vecPosition.x;
|
||||||
CONFIGHEAD->state.y = m->vecPosition.y;
|
CONFIGHEAD->state.y = m->vecPosition.y;
|
||||||
|
|
||||||
wlr_output_set_custom_mode(m->output, m->vecPixelSize.x, m->vecPixelSize.y, (int)(round(m->refreshRate * 1000)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_output_manager_v1_set_configuration(g_pCompositor->m_sWLROutputMgr, CONFIG);
|
wlr_output_manager_v1_set_configuration(g_pCompositor->m_sWLROutputMgr, CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_newOutput(wl_listener* listener, void* data) {
|
void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||||
// new monitor added, let's accomodate for that.
|
// new monitor added, let's accommodate for that.
|
||||||
const auto OUTPUT = (wlr_output*)data;
|
const auto OUTPUT = (wlr_output*)data;
|
||||||
|
|
||||||
|
// for warping the cursor on launch
|
||||||
|
static bool firstLaunch = true;
|
||||||
|
|
||||||
if (!OUTPUT->name) {
|
if (!OUTPUT->name) {
|
||||||
Debug::log(ERR, "New monitor has no name?? Ignoring");
|
Debug::log(ERR, "New monitor has no name?? Ignoring");
|
||||||
return;
|
return;
|
||||||
@@ -77,18 +82,35 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
|||||||
|
|
||||||
const auto PNEWMONITOR = PNEWMONITORWRAP->get();
|
const auto PNEWMONITOR = PNEWMONITORWRAP->get();
|
||||||
|
|
||||||
PNEWMONITOR->output = OUTPUT;
|
PNEWMONITOR->output = OUTPUT;
|
||||||
PNEWMONITOR->m_pThisWrap = PNEWMONITORWRAP;
|
PNEWMONITOR->m_pThisWrap = PNEWMONITORWRAP;
|
||||||
|
|
||||||
PNEWMONITOR->onConnect(false);
|
PNEWMONITOR->onConnect(false);
|
||||||
|
|
||||||
if ((!pMostHzMonitor || PNEWMONITOR->refreshRate > pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled)
|
if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled)
|
||||||
pMostHzMonitor = PNEWMONITOR;
|
g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR;
|
||||||
|
|
||||||
// ready to process cuz we have a monitor
|
// ready to process cuz we have a monitor
|
||||||
if (PNEWMONITOR->m_bEnabled) {
|
if (PNEWMONITOR->m_bEnabled) {
|
||||||
g_pCompositor->m_bReadyToProcess = true;
|
g_pCompositor->m_bReadyToProcess = true;
|
||||||
g_pCompositor->m_bUnsafeState = false;
|
g_pCompositor->m_bUnsafeState = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||||
|
g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR);
|
||||||
|
|
||||||
|
if (firstLaunch) {
|
||||||
|
firstLaunch = false;
|
||||||
|
const auto POS = PNEWMONITOR->vecPosition + PNEWMONITOR->vecSize / 2.f;
|
||||||
|
if (g_pCompositor->m_sSeat.mouse)
|
||||||
|
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, POS.x, POS.y);
|
||||||
|
} else {
|
||||||
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
|
if (w->m_iMonitorID == PNEWMONITOR->ID) {
|
||||||
|
w->m_iLastSurfaceMonitorID = -1;
|
||||||
|
w->updateSurfaceOutputs();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,220 +119,57 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
|||||||
|
|
||||||
if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) {
|
if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) {
|
||||||
Debug::log(WARN, "Attempted to render frame on inactive session!");
|
Debug::log(WARN, "Attempted to render frame on inactive session!");
|
||||||
|
|
||||||
|
if (g_pCompositor->m_bUnsafeState)
|
||||||
|
g_pConfigManager->performMonitorReload();
|
||||||
|
|
||||||
return; // cannot draw on session inactive (different tty)
|
return; // cannot draw on session inactive (different tty)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PMONITOR->m_bEnabled)
|
if (!PMONITOR->m_bEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now();
|
static auto* const PENABLERAT = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_of_time")->intValue;
|
||||||
static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now();
|
static auto* const PRATSAFE = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_safezone")->intValue;
|
||||||
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
|
|
||||||
|
|
||||||
static auto *const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
|
PMONITOR->lastPresentationTimer.reset();
|
||||||
static auto *const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("general:damage_tracking_internal")->intValue;
|
|
||||||
static auto *const PDAMAGEBLINK = &g_pConfigManager->getConfigValuePtr("debug:damage_blink")->intValue;
|
|
||||||
static auto *const PNOVFR = &g_pConfigManager->getConfigValuePtr("misc:no_vfr")->intValue;
|
|
||||||
|
|
||||||
static int damageBlinkCleanup = 0; // because double-buffered
|
if (*PENABLERAT) {
|
||||||
|
if (!PMONITOR->RATScheduled) {
|
||||||
if (!*PDAMAGEBLINK)
|
// render
|
||||||
damageBlinkCleanup = 0;
|
g_pHyprRenderer->renderMonitor(PMONITOR);
|
||||||
|
|
||||||
if (*PDEBUGOVERLAY == 1) {
|
|
||||||
startRender = std::chrono::high_resolution_clock::now();
|
|
||||||
g_pDebugOverlay->frameData(PMONITOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PMONITOR->framesToSkip > 0) {
|
|
||||||
PMONITOR->framesToSkip -= 1;
|
|
||||||
|
|
||||||
if (!PMONITOR->noFrameSchedule)
|
|
||||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
|
||||||
else {
|
|
||||||
Debug::log(LOG, "NoFrameSchedule hit for %s.", PMONITOR->szName.c_str());
|
|
||||||
}
|
}
|
||||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
|
|
||||||
|
|
||||||
if (PMONITOR->framesToSkip > 10)
|
PMONITOR->RATScheduled = false;
|
||||||
PMONITOR->framesToSkip = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// checks //
|
const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(PMONITOR);
|
||||||
if (PMONITOR->ID == pMostHzMonitor->ID || !*PNOVFR) { // unfortunately with VFR we don't have the guarantee mostHz is going to be updated all the time, so we have to ignore that
|
|
||||||
g_pCompositor->sanityCheckWorkspaces();
|
|
||||||
g_pAnimationManager->tick();
|
|
||||||
|
|
||||||
g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
|
if (max + *PRATSAFE > 1000.0 / PMONITOR->refreshRate)
|
||||||
|
return;
|
||||||
|
|
||||||
if (g_pConfigManager->m_bWantsMonitorReload)
|
const auto MSLEFT = 1000.0 / PMONITOR->refreshRate - PMONITOR->lastPresentationTimer.getMillis();
|
||||||
g_pConfigManager->performMonitorReload();
|
|
||||||
|
|
||||||
g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
|
PMONITOR->RATScheduled = true;
|
||||||
}
|
|
||||||
// //
|
|
||||||
|
|
||||||
if (PMONITOR->scheduledRecalc) {
|
const auto ESTRENDERTIME = std::ceil(avg + *PRATSAFE);
|
||||||
PMONITOR->scheduledRecalc = false;
|
const auto TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME);
|
||||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
timespec now;
|
if (MSLEFT < 1 || MSLEFT < ESTRENDERTIME || TIMETOSLEEP < 1)
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
g_pHyprRenderer->renderMonitor(PMONITOR);
|
||||||
|
else
|
||||||
// check the damage
|
wl_event_source_timer_update(PMONITOR->renderTimer, TIMETOSLEEP);
|
||||||
pixman_region32_t damage;
|
|
||||||
bool hasChanged;
|
|
||||||
pixman_region32_init(&damage);
|
|
||||||
|
|
||||||
if (*PDAMAGETRACKINGMODE == -1) {
|
|
||||||
Debug::log(CRIT, "Damage tracking mode -1 ????");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_pHyprOpenGL->preRender(PMONITOR);
|
|
||||||
|
|
||||||
if (!wlr_output_damage_attach_render(PMONITOR->damage, &hasChanged, &damage)){
|
|
||||||
Debug::log(ERR, "Couldn't attach render to display %s ???", PMONITOR->szName.c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we need to cleanup fading out when rendering the appropriate context
|
|
||||||
g_pCompositor->cleanupFadingOut(PMONITOR->ID);
|
|
||||||
|
|
||||||
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && PMONITOR->forceFullFrames == 0 && damageBlinkCleanup == 0) {
|
|
||||||
pixman_region32_fini(&damage);
|
|
||||||
wlr_output_rollback(PMONITOR->output);
|
|
||||||
|
|
||||||
if (*PDAMAGEBLINK || *PNOVFR)
|
|
||||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we have no tracking or full tracking, invalidate the entire monitor
|
|
||||||
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0 || PMONITOR->isMirror() /* why??? */) {
|
|
||||||
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x * 10, (int)PMONITOR->vecTransformedSize.y * 10); // wot?
|
|
||||||
|
|
||||||
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
|
|
||||||
} else {
|
} else {
|
||||||
static auto *const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
|
g_pHyprRenderer->renderMonitor(PMONITOR);
|
||||||
|
|
||||||
// if we use blur we need to expand the damage for proper blurring
|
|
||||||
if (*PBLURENABLED == 1) {
|
|
||||||
// TODO: can this be optimized?
|
|
||||||
static auto *const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_size")->intValue;
|
|
||||||
static auto *const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur_passes")->intValue;
|
|
||||||
const auto BLURRADIUS = *PBLURSIZE * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think.
|
|
||||||
|
|
||||||
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
|
|
||||||
|
|
||||||
// now, prep the damage, get the extended damage region
|
|
||||||
wlr_region_expand(&damage, &damage, BLURRADIUS); // expand for proper blurring
|
|
||||||
} else {
|
|
||||||
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PMONITOR->forceFullFrames > 0) {
|
|
||||||
PMONITOR->forceFullFrames -= 1;
|
|
||||||
if (PMONITOR->forceFullFrames > 10)
|
|
||||||
PMONITOR->forceFullFrames = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: this is getting called with extents being 0,0,0,0 should it be?
|
|
||||||
// potentially can save on resources.
|
|
||||||
|
|
||||||
g_pHyprOpenGL->begin(PMONITOR, &damage);
|
|
||||||
|
|
||||||
if (PMONITOR->isMirror()) {
|
|
||||||
g_pHyprOpenGL->renderMirrored();
|
|
||||||
|
|
||||||
Debug::log(LOG, "Mirror frame");
|
|
||||||
} else {
|
|
||||||
g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
|
|
||||||
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
|
|
||||||
|
|
||||||
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
|
|
||||||
|
|
||||||
// if correct monitor draw hyprerror
|
|
||||||
if (PMONITOR->ID == 0)
|
|
||||||
g_pHyprError->draw();
|
|
||||||
|
|
||||||
// for drawing the debug overlay
|
|
||||||
if (PMONITOR->ID == 0 && *PDEBUGOVERLAY == 1) {
|
|
||||||
startRenderOverlay = std::chrono::high_resolution_clock::now();
|
|
||||||
g_pDebugOverlay->draw();
|
|
||||||
endRenderOverlay = std::chrono::high_resolution_clock::now();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
|
|
||||||
wlr_box monrect = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
|
|
||||||
g_pHyprOpenGL->renderRect(&monrect, CColor(255, 0, 255, 100), 0);
|
|
||||||
damageBlinkCleanup = 1;
|
|
||||||
} else if (*PDAMAGEBLINK) {
|
|
||||||
damageBlinkCleanup++;
|
|
||||||
if (damageBlinkCleanup > 3)
|
|
||||||
damageBlinkCleanup = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
|
||||||
|
|
||||||
wlr_output_render_software_cursors(PMONITOR->output, NULL);
|
|
||||||
|
|
||||||
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_pHyprOpenGL->end();
|
|
||||||
|
|
||||||
// calc frame damage
|
|
||||||
pixman_region32_t frameDamage;
|
|
||||||
pixman_region32_init(&frameDamage);
|
|
||||||
|
|
||||||
const auto TRANSFORM = wlr_output_transform_invert(PMONITOR->output->transform);
|
|
||||||
wlr_region_transform(&frameDamage, &PMONITOR->damage->current, TRANSFORM, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
|
|
||||||
|
|
||||||
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR)
|
|
||||||
pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
|
|
||||||
|
|
||||||
if (*PDAMAGEBLINK)
|
|
||||||
pixman_region32_union(&frameDamage, &frameDamage, &damage);
|
|
||||||
|
|
||||||
wlr_output_set_damage(PMONITOR->output, &frameDamage);
|
|
||||||
|
|
||||||
if (!PMONITOR->mirrors.empty())
|
|
||||||
g_pHyprRenderer->damageMirrorsWith(PMONITOR, &frameDamage);
|
|
||||||
|
|
||||||
pixman_region32_fini(&frameDamage);
|
|
||||||
pixman_region32_fini(&damage);
|
|
||||||
|
|
||||||
if (!wlr_output_commit(PMONITOR->output))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (*PDAMAGEBLINK || *PNOVFR)
|
|
||||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
|
||||||
|
|
||||||
if (*PDEBUGOVERLAY == 1) {
|
|
||||||
const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f;
|
|
||||||
g_pDebugOverlay->renderData(PMONITOR, µs);
|
|
||||||
if (PMONITOR->ID == 0) {
|
|
||||||
const float µsNoOverlay = µs - std::chrono::duration_cast<std::chrono::nanoseconds>(endRenderOverlay - startRenderOverlay).count() / 1000.f;
|
|
||||||
g_pDebugOverlay->renderDataNoOverlay(PMONITOR, µsNoOverlay);
|
|
||||||
} else {
|
|
||||||
g_pDebugOverlay->renderDataNoOverlay(PMONITOR, µs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_monitorDestroy(void* owner, void* data) {
|
void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||||
const auto OUTPUT = (wlr_output*)data;
|
const auto OUTPUT = (wlr_output*)data;
|
||||||
|
|
||||||
CMonitor* pMonitor = nullptr;
|
CMonitor* pMonitor = nullptr;
|
||||||
|
|
||||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||||
if (m->szName == OUTPUT->name) {
|
if (m->output == OUTPUT) {
|
||||||
pMonitor = m.get();
|
pMonitor = m.get();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -319,25 +178,45 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
|||||||
if (!pMonitor)
|
if (!pMonitor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Debug::log(LOG, "Destroy called for monitor %s", pMonitor->output->name);
|
||||||
|
|
||||||
pMonitor->onDisconnect();
|
pMonitor->onDisconnect();
|
||||||
|
|
||||||
|
pMonitor->output = nullptr;
|
||||||
|
pMonitor->m_bRenderingInitPassed = false;
|
||||||
|
|
||||||
// cleanup if not unsafe
|
// cleanup if not unsafe
|
||||||
|
|
||||||
if (!g_pCompositor->m_bUnsafeState) {
|
if (!g_pCompositor->m_bUnsafeState) {
|
||||||
g_pCompositor->m_vRealMonitors.erase(std::remove_if(g_pCompositor->m_vRealMonitors.begin(), g_pCompositor->m_vRealMonitors.end(), [&](std::shared_ptr<CMonitor>& el) { return el.get() == pMonitor; }));
|
Debug::log(LOG, "Removing monitor %s from realMonitors", pMonitor->szName.c_str());
|
||||||
|
|
||||||
if (pMostHzMonitor == pMonitor) {
|
std::erase_if(g_pCompositor->m_vRealMonitors, [&](std::shared_ptr<CMonitor>& el) { return el.get() == pMonitor; });
|
||||||
int mostHz = 0;
|
|
||||||
CMonitor* pMonitorMostHz = nullptr;
|
|
||||||
|
|
||||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
|
||||||
if (m->refreshRate > mostHz) {
|
|
||||||
pMonitorMostHz = m.get();
|
|
||||||
mostHz = m->refreshRate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pMostHzMonitor = pMonitorMostHz;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Events::listener_monitorStateRequest(void* owner, void* data) {
|
||||||
|
const auto PMONITOR = (CMonitor*)owner;
|
||||||
|
const auto E = (wlr_output_event_request_state*)data;
|
||||||
|
|
||||||
|
wlr_output_commit_state(PMONITOR->output, E->state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Events::listener_monitorDamage(void* owner, void* data) {
|
||||||
|
const auto PMONITOR = (CMonitor*)owner;
|
||||||
|
const auto E = (wlr_output_event_damage*)data;
|
||||||
|
|
||||||
|
PMONITOR->addDamage(E->damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Events::listener_monitorNeedsFrame(void* owner, void* data) {
|
||||||
|
const auto PMONITOR = (CMonitor*)owner;
|
||||||
|
|
||||||
|
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Events::listener_monitorCommit(void* owner, void* data) {
|
||||||
|
const auto PMONITOR = (CMonitor*)owner;
|
||||||
|
|
||||||
|
const auto E = (wlr_output_event_commit*)data;
|
||||||
|
|
||||||
|
g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR, E);
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,12 +16,12 @@
|
|||||||
// --------------------------------------------- //
|
// --------------------------------------------- //
|
||||||
|
|
||||||
void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
|
void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
|
||||||
SXDGPopup *const PPOPUP = (SXDGPopup*)pPopup;
|
SXDGPopup* const PPOPUP = (SXDGPopup*)pPopup;
|
||||||
|
|
||||||
auto curPopup = PPOPUP;
|
auto curPopup = PPOPUP;
|
||||||
|
|
||||||
int px = 0;
|
int px = 0;
|
||||||
int py = 0;
|
int py = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
px += curPopup->popup->current.geometry.x;
|
px += curPopup->popup->current.geometry.x;
|
||||||
@@ -32,8 +32,8 @@ void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
|
|||||||
py -= curPopup->popup->base->current.geometry.y;
|
py -= curPopup->popup->base->current.geometry.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curPopup->pSurfaceTree && curPopup->pSurfaceTree->pSurface && !curPopup->parentPopup && !curPopup->parentWindow) {
|
if (curPopup->popup && !curPopup->parentPopup && !curPopup->parentWindow) {
|
||||||
const auto EXTENTSSURFACE = pixman_region32_extents(&curPopup->pSurfaceTree->pSurface->input_region);
|
const auto EXTENTSSURFACE = pixman_region32_extents(&curPopup->popup->base->surface->input_region);
|
||||||
px -= EXTENTSSURFACE->x1;
|
px -= EXTENTSSURFACE->x1;
|
||||||
py -= EXTENTSSURFACE->y1;
|
py -= EXTENTSSURFACE->y1;
|
||||||
}
|
}
|
||||||
@@ -63,13 +63,14 @@ void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) {
|
|||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||||
|
|
||||||
wlr_box box = {.x = PMONITOR->vecPosition.x - pHyprPopup->lx, .y = PMONITOR->vecPosition.y - pHyprPopup->ly, .width = PMONITOR->vecSize.x, .height = PMONITOR->vecSize.y};
|
wlr_box box = {.x = PMONITOR->vecPosition.x - pHyprPopup->lx, .y = PMONITOR->vecPosition.y - pHyprPopup->ly, .width = PMONITOR->vecSize.x, .height = PMONITOR->vecSize.y};
|
||||||
|
|
||||||
wlr_xdg_popup_unconstrain_from_box(popup, &box);
|
wlr_xdg_popup_unconstrain_from_box(popup, &box);
|
||||||
|
|
||||||
pHyprPopup->monitor = PMONITOR;
|
pHyprPopup->monitor = PMONITOR;
|
||||||
|
|
||||||
Debug::log(LOG, "Popup: Unconstrained from lx ly: %f %f, pHyprPopup lx ly: %f %f", (float)PMONITOR->vecPosition.x, (float)PMONITOR->vecPosition.y, (float)pHyprPopup->lx, (float)pHyprPopup->ly);
|
Debug::log(LOG, "Popup: Unconstrained from lx ly: %f %f, pHyprPopup lx ly: %f %f", (float)PMONITOR->vecPosition.x, (float)PMONITOR->vecPosition.y, (float)pHyprPopup->lx,
|
||||||
|
(float)pHyprPopup->ly);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_newPopup(void* owner, void* data) {
|
void Events::listener_newPopup(void* owner, void* data) {
|
||||||
@@ -77,7 +78,7 @@ void Events::listener_newPopup(void* owner, void* data) {
|
|||||||
|
|
||||||
ASSERT(layersurface);
|
ASSERT(layersurface);
|
||||||
|
|
||||||
Debug::log(LOG, "New layer popup created from surface %x", layersurface);
|
Debug::log(LOG, "New layer popup created from surface %lx", layersurface);
|
||||||
|
|
||||||
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
||||||
|
|
||||||
@@ -85,10 +86,11 @@ void Events::listener_newPopup(void* owner, void* data) {
|
|||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
||||||
|
|
||||||
PNEWPOPUP->popup = WLRPOPUP;
|
PNEWPOPUP->popup = WLRPOPUP;
|
||||||
PNEWPOPUP->lx = layersurface->position.x;
|
PNEWPOPUP->lx = layersurface->position.x;
|
||||||
PNEWPOPUP->ly = layersurface->position.y;
|
PNEWPOPUP->ly = layersurface->position.y;
|
||||||
PNEWPOPUP->monitor = PMONITOR;
|
PNEWPOPUP->monitor = PMONITOR;
|
||||||
|
PNEWPOPUP->parentLS = layersurface;
|
||||||
createNewPopup(WLRPOPUP, PNEWPOPUP);
|
createNewPopup(WLRPOPUP, PNEWPOPUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +102,7 @@ void Events::listener_newPopupXDG(void* owner, void* data) {
|
|||||||
if (!PWINDOW->m_bIsMapped)
|
if (!PWINDOW->m_bIsMapped)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug::log(LOG, "New layer popup created from XDG window %x -> %s", PWINDOW, PWINDOW->m_szTitle.c_str());
|
Debug::log(LOG, "New layer popup created from XDG window %lx -> %s", PWINDOW, PWINDOW->m_szTitle.c_str());
|
||||||
|
|
||||||
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
||||||
|
|
||||||
@@ -108,11 +110,11 @@ void Events::listener_newPopupXDG(void* owner, void* data) {
|
|||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||||
|
|
||||||
PNEWPOPUP->popup = WLRPOPUP;
|
PNEWPOPUP->popup = WLRPOPUP;
|
||||||
PNEWPOPUP->lx = PWINDOW->m_vRealPosition.goalv().x;
|
PNEWPOPUP->lx = PWINDOW->m_vRealPosition.goalv().x;
|
||||||
PNEWPOPUP->ly = PWINDOW->m_vRealPosition.goalv().y;
|
PNEWPOPUP->ly = PWINDOW->m_vRealPosition.goalv().y;
|
||||||
PNEWPOPUP->parentWindow = PWINDOW;
|
PNEWPOPUP->parentWindow = PWINDOW;
|
||||||
PNEWPOPUP->monitor = PMONITOR;
|
PNEWPOPUP->monitor = PMONITOR;
|
||||||
createNewPopup(WLRPOPUP, PNEWPOPUP);
|
createNewPopup(WLRPOPUP, PNEWPOPUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,20 +124,20 @@ void Events::listener_newPopupFromPopupXDG(void* owner, void* data) {
|
|||||||
ASSERT(PPOPUP);
|
ASSERT(PPOPUP);
|
||||||
|
|
||||||
if (PPOPUP->parentWindow)
|
if (PPOPUP->parentWindow)
|
||||||
Debug::log(LOG, "New popup created from XDG Window popup %x -> %s", PPOPUP, PPOPUP->parentWindow->m_szTitle.c_str());
|
Debug::log(LOG, "New popup created from XDG Window popup %lx -> %s", PPOPUP, PPOPUP->parentWindow->m_szTitle.c_str());
|
||||||
else
|
else
|
||||||
Debug::log(LOG, "New popup created from Non-Window popup %x", PPOPUP);
|
Debug::log(LOG, "New popup created from Non-Window popup %lx", PPOPUP);
|
||||||
|
|
||||||
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
||||||
|
|
||||||
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
|
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
|
||||||
|
|
||||||
PNEWPOPUP->popup = WLRPOPUP;
|
PNEWPOPUP->popup = WLRPOPUP;
|
||||||
PNEWPOPUP->parentPopup = PPOPUP;
|
PNEWPOPUP->parentPopup = PPOPUP;
|
||||||
PNEWPOPUP->lx = PPOPUP->lx;
|
PNEWPOPUP->lx = PPOPUP->lx;
|
||||||
PNEWPOPUP->ly = PPOPUP->ly;
|
PNEWPOPUP->ly = PPOPUP->ly;
|
||||||
PNEWPOPUP->parentWindow = PPOPUP->parentWindow;
|
PNEWPOPUP->parentWindow = PPOPUP->parentWindow;
|
||||||
PNEWPOPUP->monitor = PPOPUP->monitor;
|
PNEWPOPUP->monitor = PPOPUP->monitor;
|
||||||
|
|
||||||
createNewPopup(WLRPOPUP, PNEWPOPUP);
|
createNewPopup(WLRPOPUP, PNEWPOPUP);
|
||||||
}
|
}
|
||||||
@@ -147,6 +149,11 @@ void Events::listener_mapPopupXDG(void* owner, void* data) {
|
|||||||
|
|
||||||
Debug::log(LOG, "New XDG Popup mapped at %d %d", (int)PPOPUP->lx, (int)PPOPUP->ly);
|
Debug::log(LOG, "New XDG Popup mapped at %d %d", (int)PPOPUP->lx, (int)PPOPUP->ly);
|
||||||
|
|
||||||
|
if (PPOPUP->parentWindow)
|
||||||
|
PPOPUP->parentWindow->m_lPopupSurfaces.emplace_back(PPOPUP->popup->base->surface);
|
||||||
|
else if (PPOPUP->parentLS)
|
||||||
|
PPOPUP->parentLS->popupSurfaces.emplace_back(PPOPUP->popup->base->surface);
|
||||||
|
|
||||||
PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP, PPOPUP->parentWindow);
|
PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP, PPOPUP->parentWindow);
|
||||||
|
|
||||||
int lx = 0, ly = 0;
|
int lx = 0, ly = 0;
|
||||||
@@ -157,7 +164,10 @@ void Events::listener_mapPopupXDG(void* owner, void* data) {
|
|||||||
|
|
||||||
g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2);
|
g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2);
|
||||||
|
|
||||||
Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode %x", PPOPUP->pSurfaceTree);
|
if (PPOPUP->monitor)
|
||||||
|
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->scale);
|
||||||
|
|
||||||
|
Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode %lx", PPOPUP->pSurfaceTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_unmapPopupXDG(void* owner, void* data) {
|
void Events::listener_unmapPopupXDG(void* owner, void* data) {
|
||||||
@@ -166,6 +176,9 @@ void Events::listener_unmapPopupXDG(void* owner, void* data) {
|
|||||||
|
|
||||||
ASSERT(PPOPUP);
|
ASSERT(PPOPUP);
|
||||||
|
|
||||||
|
if (PPOPUP->popup->base->surface == g_pCompositor->m_pLastFocus)
|
||||||
|
g_pInputManager->releaseAllMouseButtons();
|
||||||
|
|
||||||
SubsurfaceTree::destroySurfaceTree(PPOPUP->pSurfaceTree);
|
SubsurfaceTree::destroySurfaceTree(PPOPUP->pSurfaceTree);
|
||||||
|
|
||||||
int lx = 0, ly = 0;
|
int lx = 0, ly = 0;
|
||||||
@@ -176,13 +189,20 @@ void Events::listener_unmapPopupXDG(void* owner, void* data) {
|
|||||||
|
|
||||||
g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2);
|
g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2);
|
||||||
|
|
||||||
|
if (PPOPUP->parentWindow)
|
||||||
|
std::erase(PPOPUP->parentWindow->m_lPopupSurfaces, PPOPUP->popup->base->surface);
|
||||||
|
else if (PPOPUP->parentLS)
|
||||||
|
std::erase(PPOPUP->parentLS->popupSurfaces, PPOPUP->popup->base->surface);
|
||||||
|
|
||||||
PPOPUP->pSurfaceTree = nullptr;
|
PPOPUP->pSurfaceTree = nullptr;
|
||||||
|
|
||||||
|
g_pInputManager->simulateMouseMovement(); // to focus and return back to an appropriate surface
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_commitPopupXDG(void* owner, void* data) {
|
void Events::listener_commitPopupXDG(void* owner, void* data) {
|
||||||
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
|
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
|
||||||
|
|
||||||
int lx = 0, ly = 0;
|
int lx = 0, ly = 0;
|
||||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
||||||
|
|
||||||
g_pHyprRenderer->damageSurface(PPOPUP->popup->base->surface, lx, ly);
|
g_pHyprRenderer->damageSurface(PPOPUP->popup->base->surface, lx, ly);
|
||||||
@@ -193,12 +213,12 @@ void Events::listener_destroyPopupXDG(void* owner, void* data) {
|
|||||||
|
|
||||||
ASSERT(PPOPUP);
|
ASSERT(PPOPUP);
|
||||||
|
|
||||||
Debug::log(LOG, "Destroyed popup XDG %x", PPOPUP);
|
Debug::log(LOG, "Destroyed popup XDG %lx", PPOPUP);
|
||||||
|
|
||||||
if (PPOPUP->pSurfaceTree) {
|
if (PPOPUP->pSurfaceTree) {
|
||||||
SubsurfaceTree::destroySurfaceTree(PPOPUP->pSurfaceTree);
|
SubsurfaceTree::destroySurfaceTree(PPOPUP->pSurfaceTree);
|
||||||
PPOPUP->pSurfaceTree = nullptr;
|
PPOPUP->pSurfaceTree = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pCompositor->m_vXDGPopups.erase(std::remove_if(g_pCompositor->m_vXDGPopups.begin(), g_pCompositor->m_vXDGPopups.end(), [&](std::unique_ptr<SXDGPopup>& el) { return el.get() == PPOPUP; }));
|
std::erase_if(g_pCompositor->m_vXDGPopups, [&](std::unique_ptr<SXDGPopup>& el) { return el.get() == PPOPUP; });
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -7,12 +7,10 @@ CAnimatedVariable::CAnimatedVariable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CAnimatedVariable::create(ANIMATEDVARTYPE type, SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy) {
|
void CAnimatedVariable::create(ANIMATEDVARTYPE type, SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy) {
|
||||||
m_eVarType = type;
|
m_eVarType = type;
|
||||||
m_eDamagePolicy = policy;
|
m_eDamagePolicy = policy;
|
||||||
m_pConfig = pAnimConfig;
|
m_pConfig = pAnimConfig;
|
||||||
m_pWindow = pWindow;
|
m_pWindow = pWindow;
|
||||||
|
|
||||||
g_pAnimationManager->m_lAnimatedVariables.push_back(this);
|
|
||||||
|
|
||||||
m_bDummy = false;
|
m_bDummy = false;
|
||||||
}
|
}
|
||||||
@@ -24,25 +22,23 @@ void CAnimatedVariable::create(ANIMATEDVARTYPE type, std::any val, SAnimationPro
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case AVARTYPE_FLOAT: {
|
case AVARTYPE_FLOAT: {
|
||||||
const auto V = std::any_cast<float>(val);
|
const auto V = std::any_cast<float>(val);
|
||||||
m_fValue = V;
|
m_fValue = V;
|
||||||
m_fGoal = V;
|
m_fGoal = V;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AVARTYPE_VECTOR: {
|
case AVARTYPE_VECTOR: {
|
||||||
const auto V = std::any_cast<Vector2D>(val);
|
const auto V = std::any_cast<Vector2D>(val);
|
||||||
m_vValue = V;
|
m_vValue = V;
|
||||||
m_vGoal = V;
|
m_vGoal = V;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AVARTYPE_COLOR: {
|
case AVARTYPE_COLOR: {
|
||||||
const auto V = std::any_cast<CColor>(val);
|
const auto V = std::any_cast<CColor>(val);
|
||||||
m_cValue = V;
|
m_cValue = V;
|
||||||
m_cGoal = V;
|
m_cGoal = V;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default: ASSERT(false); break;
|
||||||
ASSERT(false);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
Debug::log(ERR, "CAnimatedVariable create error: %s", e.what());
|
Debug::log(ERR, "CAnimatedVariable create error: %s", e.what());
|
||||||
@@ -56,8 +52,30 @@ CAnimatedVariable::~CAnimatedVariable() {
|
|||||||
|
|
||||||
void CAnimatedVariable::unregister() {
|
void CAnimatedVariable::unregister() {
|
||||||
g_pAnimationManager->m_lAnimatedVariables.remove(this);
|
g_pAnimationManager->m_lAnimatedVariables.remove(this);
|
||||||
|
m_bIsRegistered = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAnimatedVariable::registerVar() {
|
||||||
|
if (!m_bIsRegistered)
|
||||||
|
g_pAnimationManager->m_lAnimatedVariables.push_back(this);
|
||||||
|
m_bIsRegistered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CAnimatedVariable::getDurationLeftMs() {
|
int CAnimatedVariable::getDurationLeftMs() {
|
||||||
return std::max((int)(m_pConfig->pValues->internalSpeed * 100) - (int)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - animationBegin).count(), 0);
|
return std::max(
|
||||||
|
(int)(m_pConfig->pValues->internalSpeed * 100) - (int)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - animationBegin).count(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float CAnimatedVariable::getPercent() {
|
||||||
|
const auto DURATIONPASSED = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - animationBegin).count();
|
||||||
|
return std::clamp((DURATIONPASSED / 100.f) / m_pConfig->pValues->internalSpeed, 0.f, 1.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float CAnimatedVariable::getCurveValue() {
|
||||||
|
const auto SPENT = getPercent();
|
||||||
|
|
||||||
|
if (SPENT >= 1.f)
|
||||||
|
return 1.f;
|
||||||
|
|
||||||
|
return g_pAnimationManager->getBezier(m_pConfig->pValues->internalBezier)->getYForPoint(SPENT);
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ enum ANIMATEDVARTYPE {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum AVARDAMAGEPOLICY {
|
enum AVARDAMAGEPOLICY {
|
||||||
AVARDAMAGE_INVALID = -1,
|
AVARDAMAGE_NONE = -1,
|
||||||
AVARDAMAGE_ENTIRE = 0,
|
AVARDAMAGE_ENTIRE = 0,
|
||||||
AVARDAMAGE_BORDER,
|
AVARDAMAGE_BORDER,
|
||||||
AVARDAMAGE_SHADOW
|
AVARDAMAGE_SHADOW
|
||||||
@@ -21,9 +21,10 @@ class CAnimationManager;
|
|||||||
class CWorkspace;
|
class CWorkspace;
|
||||||
struct SLayerSurface;
|
struct SLayerSurface;
|
||||||
struct SAnimationPropertyConfig;
|
struct SAnimationPropertyConfig;
|
||||||
|
class CHyprRenderer;
|
||||||
|
|
||||||
class CAnimatedVariable {
|
class CAnimatedVariable {
|
||||||
public:
|
public:
|
||||||
CAnimatedVariable(); // dummy var
|
CAnimatedVariable(); // dummy var
|
||||||
|
|
||||||
void create(ANIMATEDVARTYPE, SAnimationPropertyConfig*, void* pWindow, AVARDAMAGEPOLICY);
|
void create(ANIMATEDVARTYPE, SAnimationPropertyConfig*, void* pWindow, AVARDAMAGEPOLICY);
|
||||||
@@ -32,6 +33,7 @@ public:
|
|||||||
~CAnimatedVariable();
|
~CAnimatedVariable();
|
||||||
|
|
||||||
void unregister();
|
void unregister();
|
||||||
|
void registerVar();
|
||||||
|
|
||||||
// gets the current vector value (real time)
|
// gets the current vector value (real time)
|
||||||
const Vector2D& vec() const {
|
const Vector2D& vec() const {
|
||||||
@@ -63,43 +65,61 @@ public:
|
|||||||
return m_cGoal;
|
return m_cGoal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator=(const Vector2D& v) {
|
CAnimatedVariable& operator=(const Vector2D& v) {
|
||||||
m_vGoal = v;
|
m_vGoal = v;
|
||||||
animationBegin = std::chrono::system_clock::now();
|
animationBegin = std::chrono::system_clock::now();
|
||||||
m_vBegun = m_vValue;
|
m_vBegun = m_vValue;
|
||||||
|
|
||||||
|
onAnimationBegin();
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator=(const float& v) {
|
CAnimatedVariable& operator=(const float& v) {
|
||||||
m_fGoal = v;
|
m_fGoal = v;
|
||||||
animationBegin = std::chrono::system_clock::now();
|
animationBegin = std::chrono::system_clock::now();
|
||||||
m_fBegun = m_fValue;
|
m_fBegun = m_fValue;
|
||||||
|
|
||||||
|
onAnimationBegin();
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator=(const CColor& v) {
|
CAnimatedVariable& operator=(const CColor& v) {
|
||||||
m_cGoal = v;
|
m_cGoal = v;
|
||||||
animationBegin = std::chrono::system_clock::now();
|
animationBegin = std::chrono::system_clock::now();
|
||||||
m_cBegun = m_cValue;
|
m_cBegun = m_cValue;
|
||||||
|
|
||||||
|
onAnimationBegin();
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the actual stored value, without affecting the goal, but resets the timer
|
// Sets the actual stored value, without affecting the goal, but resets the timer
|
||||||
void setValue(const Vector2D& v) {
|
void setValue(const Vector2D& v) {
|
||||||
m_vValue = v;
|
m_vValue = v;
|
||||||
animationBegin = std::chrono::system_clock::now();
|
animationBegin = std::chrono::system_clock::now();
|
||||||
m_vBegun = m_vValue;
|
m_vBegun = m_vValue;
|
||||||
|
|
||||||
|
onAnimationBegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the actual stored value, without affecting the goal, but resets the timer
|
// Sets the actual stored value, without affecting the goal, but resets the timer
|
||||||
void setValue(const float& v) {
|
void setValue(const float& v) {
|
||||||
m_fValue = v;
|
m_fValue = v;
|
||||||
animationBegin = std::chrono::system_clock::now();
|
animationBegin = std::chrono::system_clock::now();
|
||||||
m_vBegun = m_vValue;
|
m_vBegun = m_vValue;
|
||||||
|
|
||||||
|
onAnimationBegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the actual stored value, without affecting the goal, but resets the timer
|
// Sets the actual stored value, without affecting the goal, but resets the timer
|
||||||
void setValue(const CColor& v) {
|
void setValue(const CColor& v) {
|
||||||
m_cValue = v;
|
m_cValue = v;
|
||||||
animationBegin = std::chrono::system_clock::now();
|
animationBegin = std::chrono::system_clock::now();
|
||||||
m_vBegun = m_vValue;
|
m_vBegun = m_vValue;
|
||||||
|
|
||||||
|
onAnimationBegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the actual value and goal
|
// Sets the actual value and goal
|
||||||
@@ -123,14 +143,10 @@ public:
|
|||||||
// checks if an animation is in progress
|
// checks if an animation is in progress
|
||||||
bool isBeingAnimated() {
|
bool isBeingAnimated() {
|
||||||
switch (m_eVarType) {
|
switch (m_eVarType) {
|
||||||
case AVARTYPE_FLOAT:
|
case AVARTYPE_FLOAT: return m_fValue != m_fGoal;
|
||||||
return m_fValue != m_fGoal;
|
case AVARTYPE_VECTOR: return m_vValue != m_vGoal;
|
||||||
case AVARTYPE_VECTOR:
|
case AVARTYPE_COLOR: return m_cValue != m_cGoal;
|
||||||
return m_vValue != m_vGoal;
|
default: UNREACHABLE();
|
||||||
case AVARTYPE_COLOR:
|
|
||||||
return m_cValue != m_cGoal;
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@@ -138,7 +154,7 @@ public:
|
|||||||
return false; // just so that the warning is suppressed
|
return false; // just so that the warning is suppressed
|
||||||
}
|
}
|
||||||
|
|
||||||
void warp() {
|
void warp(bool endCallback = true) {
|
||||||
switch (m_eVarType) {
|
switch (m_eVarType) {
|
||||||
case AVARTYPE_FLOAT: {
|
case AVARTYPE_FLOAT: {
|
||||||
m_fValue = m_fGoal;
|
m_fValue = m_fGoal;
|
||||||
@@ -152,9 +168,11 @@ public:
|
|||||||
m_cValue = m_cGoal;
|
m_cValue = m_cGoal;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default: UNREACHABLE();
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (endCallback)
|
||||||
|
onAnimationEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setConfig(SAnimationPropertyConfig* pConfig) {
|
void setConfig(SAnimationPropertyConfig* pConfig) {
|
||||||
@@ -167,35 +185,90 @@ public:
|
|||||||
|
|
||||||
int getDurationLeftMs();
|
int getDurationLeftMs();
|
||||||
|
|
||||||
private:
|
/* returns the spent (completion) % */
|
||||||
|
float getPercent();
|
||||||
|
|
||||||
Vector2D m_vValue = Vector2D(0,0);
|
/* returns the current curve value */
|
||||||
float m_fValue = 0;
|
float getCurveValue();
|
||||||
CColor m_cValue;
|
|
||||||
|
|
||||||
Vector2D m_vGoal = Vector2D(0,0);
|
/* sets a function to be ran when the animation finishes.
|
||||||
float m_fGoal = 0;
|
if an animation is not running, runs instantly.
|
||||||
CColor m_cGoal;
|
if "remove" is set to true, will remove the callback when ran. */
|
||||||
|
void setCallbackOnEnd(std::function<void(void* thisptr)> func, bool remove = true) {
|
||||||
|
m_fEndCallback = func;
|
||||||
|
m_bRemoveEndAfterRan = remove;
|
||||||
|
|
||||||
Vector2D m_vBegun = Vector2D(0,0);
|
if (!isBeingAnimated())
|
||||||
float m_fBegun = 0;
|
onAnimationEnd();
|
||||||
CColor m_cBegun;
|
}
|
||||||
|
|
||||||
|
/* sets a function to be ran when an animation is started.
|
||||||
|
if "remove" is set to true, will remove the callback when ran. */
|
||||||
|
void setCallbackOnBegin(std::function<void(void* thisptr)> func, bool remove = true) {
|
||||||
|
m_fBeginCallback = func;
|
||||||
|
m_bRemoveBeginAfterRan = remove;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* resets all callbacks. Does not call any. */
|
||||||
|
void resetAllCallbacks() {
|
||||||
|
m_fBeginCallback = nullptr;
|
||||||
|
m_fEndCallback = nullptr;
|
||||||
|
m_bRemoveBeginAfterRan = false;
|
||||||
|
m_bRemoveEndAfterRan = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector2D m_vValue = Vector2D(0, 0);
|
||||||
|
float m_fValue = 0;
|
||||||
|
CColor m_cValue;
|
||||||
|
|
||||||
|
Vector2D m_vGoal = Vector2D(0, 0);
|
||||||
|
float m_fGoal = 0;
|
||||||
|
CColor m_cGoal;
|
||||||
|
|
||||||
|
Vector2D m_vBegun = Vector2D(0, 0);
|
||||||
|
float m_fBegun = 0;
|
||||||
|
CColor m_cBegun;
|
||||||
|
|
||||||
// owners
|
// owners
|
||||||
void* m_pWindow = nullptr;
|
void* m_pWindow = nullptr;
|
||||||
void* m_pWorkspace = nullptr;
|
void* m_pWorkspace = nullptr;
|
||||||
void* m_pLayer = nullptr;
|
void* m_pLayer = nullptr;
|
||||||
|
|
||||||
SAnimationPropertyConfig* m_pConfig = nullptr;
|
SAnimationPropertyConfig* m_pConfig = nullptr;
|
||||||
|
|
||||||
bool m_bDummy = true;
|
bool m_bDummy = true;
|
||||||
|
bool m_bIsRegistered = false;
|
||||||
|
|
||||||
std::chrono::system_clock::time_point animationBegin;
|
std::chrono::system_clock::time_point animationBegin;
|
||||||
|
|
||||||
ANIMATEDVARTYPE m_eVarType = AVARTYPE_INVALID;
|
ANIMATEDVARTYPE m_eVarType = AVARTYPE_INVALID;
|
||||||
AVARDAMAGEPOLICY m_eDamagePolicy = AVARDAMAGE_INVALID;
|
AVARDAMAGEPOLICY m_eDamagePolicy = AVARDAMAGE_NONE;
|
||||||
|
|
||||||
|
bool m_bRemoveEndAfterRan = true;
|
||||||
|
bool m_bRemoveBeginAfterRan = true;
|
||||||
|
std::function<void(void* thisptr)> m_fEndCallback;
|
||||||
|
std::function<void(void* thisptr)> m_fBeginCallback;
|
||||||
|
|
||||||
|
// methods
|
||||||
|
void onAnimationEnd() {
|
||||||
|
if (m_fEndCallback) {
|
||||||
|
m_fEndCallback(this);
|
||||||
|
if (m_bRemoveEndAfterRan)
|
||||||
|
m_fEndCallback = nullptr; // reset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onAnimationBegin() {
|
||||||
|
if (m_fBeginCallback) {
|
||||||
|
m_fBeginCallback(this);
|
||||||
|
if (m_bRemoveBeginAfterRan)
|
||||||
|
m_fBeginCallback = nullptr; // reset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
friend class CAnimationManager;
|
friend class CAnimationManager;
|
||||||
friend class CWorkspace;
|
friend class CWorkspace;
|
||||||
friend struct SLayerSurface;
|
friend struct SLayerSurface;
|
||||||
|
friend class CHyprRenderer;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
#include "BezierCurve.hpp"
|
#include "BezierCurve.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
|
void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
|
||||||
m_dPoints.clear();
|
m_dPoints.clear();
|
||||||
|
|
||||||
const auto BEGIN = std::chrono::high_resolution_clock::now();
|
const auto BEGIN = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
m_dPoints.emplace_back(Vector2D(0,0));
|
m_dPoints.emplace_back(Vector2D(0, 0));
|
||||||
|
|
||||||
for (auto& p : *pVec) {
|
for (auto& p : *pVec) {
|
||||||
m_dPoints.push_back(p);
|
m_dPoints.push_back(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_dPoints.emplace_back(Vector2D(1,1));
|
m_dPoints.emplace_back(Vector2D(1, 1));
|
||||||
|
|
||||||
RASSERT(m_dPoints.size() == 4, "CBezierCurve only supports cubic beziers! (points num: %i)", m_dPoints.size());
|
RASSERT(m_dPoints.size() == 4, "CBezierCurve only supports cubic beziers! (points num: %i)", m_dPoints.size());
|
||||||
|
|
||||||
@@ -21,7 +23,7 @@ void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
|
|||||||
m_aPointsBaked[i] = Vector2D(getXForT((i + 1) / (float)BAKEDPOINTS), getYForT((i + 1) / (float)BAKEDPOINTS));
|
m_aPointsBaked[i] = Vector2D(getXForT((i + 1) / (float)BAKEDPOINTS), getYForT((i + 1) / (float)BAKEDPOINTS));
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ELAPSEDUS = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGIN).count() / 1000.f;
|
const auto ELAPSEDUS = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGIN).count() / 1000.f;
|
||||||
const auto POINTSSIZE = m_aPointsBaked.size() * sizeof(m_aPointsBaked[0]) / 1000.f;
|
const auto POINTSSIZE = m_aPointsBaked.size() * sizeof(m_aPointsBaked[0]) / 1000.f;
|
||||||
|
|
||||||
const auto BEGINCALC = std::chrono::high_resolution_clock::now();
|
const auto BEGINCALC = std::chrono::high_resolution_clock::now();
|
||||||
@@ -29,9 +31,8 @@ void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
|
|||||||
getYForPoint(i);
|
getYForPoint(i);
|
||||||
const auto ELAPSEDCALCAVG = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGINCALC).count() / 1000.f / 10.f;
|
const auto ELAPSEDCALCAVG = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGINCALC).count() / 1000.f / 10.f;
|
||||||
|
|
||||||
Debug::log(LOG, "Created a bezier curve, baked %i points, mem usage: %.2fkB, time to bake: %.2fµs. Estimated average calc time: %.2fµs.",
|
Debug::log(LOG, "Created a bezier curve, baked %i points, mem usage: %.2fkB, time to bake: %.2fµs. Estimated average calc time: %.2fµs.", BAKEDPOINTS, POINTSSIZE, ELAPSEDUS,
|
||||||
BAKEDPOINTS, POINTSSIZE, ELAPSEDUS, ELAPSEDCALCAVG);
|
ELAPSEDCALCAVG);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float CBezierCurve::getYForT(float t) {
|
float CBezierCurve::getYForT(float t) {
|
||||||
@@ -44,29 +45,32 @@ float CBezierCurve::getXForT(float t) {
|
|||||||
|
|
||||||
// Todo: this probably can be done better and faster
|
// Todo: this probably can be done better and faster
|
||||||
float CBezierCurve::getYForPoint(float x) {
|
float CBezierCurve::getYForPoint(float x) {
|
||||||
// binary search for the range UPDOWN X
|
if (x >= 1.0)
|
||||||
float upperT = 1;
|
return 1.0;
|
||||||
float lowerT = 0;
|
|
||||||
float mid = 0.5;
|
|
||||||
|
|
||||||
while(std::abs(upperT - lowerT) > INVBAKEDPOINTS) {
|
// binary search for the range UPDOWN X
|
||||||
if (m_aPointsBaked[((int)(mid * (float)BAKEDPOINTS))].x > x) {
|
int upperT = BAKEDPOINTS - 1;
|
||||||
|
int lowerT = 0;
|
||||||
|
int mid = upperT / 2;
|
||||||
|
|
||||||
|
while (std::abs(upperT - lowerT) > 1) {
|
||||||
|
if (m_aPointsBaked[mid].x > x) {
|
||||||
upperT = mid;
|
upperT = mid;
|
||||||
} else {
|
} else {
|
||||||
lowerT = mid;
|
lowerT = mid;
|
||||||
}
|
}
|
||||||
|
|
||||||
mid = (upperT + lowerT) / 2.f;
|
mid = (upperT + lowerT) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// in the name of performance i shall make a hack
|
// in the name of performance i shall make a hack
|
||||||
const auto LOWERPOINT = &m_aPointsBaked[std::clamp((int)((float)BAKEDPOINTS * lowerT), 0, 199)];
|
const auto LOWERPOINT = &m_aPointsBaked[std::clamp(lowerT, 0, BAKEDPOINTS - 1)];
|
||||||
const auto UPPERPOINT = &m_aPointsBaked[std::clamp((int)((float)BAKEDPOINTS * upperT), 0, 199)];
|
const auto UPPERPOINT = &m_aPointsBaked[std::clamp(upperT, 0, BAKEDPOINTS - 1)];
|
||||||
|
|
||||||
const auto PERCINDELTA = (x - LOWERPOINT->x) / (UPPERPOINT->x - LOWERPOINT->x);
|
const auto PERCINDELTA = (x - LOWERPOINT->x) / (UPPERPOINT->x - LOWERPOINT->x);
|
||||||
|
|
||||||
if (std::isnan(PERCINDELTA) || std::isinf(PERCINDELTA)) // can sometimes happen for VERY small x
|
if (std::isnan(PERCINDELTA) || std::isinf(PERCINDELTA)) // can sometimes happen for VERY small x
|
||||||
return 0.f;
|
return 0.f;
|
||||||
|
|
||||||
return LOWERPOINT->y + (UPPERPOINT->y - UPPERPOINT->y) * PERCINDELTA;
|
return LOWERPOINT->y + (UPPERPOINT->y - LOWERPOINT->y) * PERCINDELTA;
|
||||||
}
|
}
|
||||||
@@ -3,25 +3,25 @@
|
|||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
constexpr int BAKEDPOINTS = 200;
|
constexpr int BAKEDPOINTS = 255;
|
||||||
constexpr float INVBAKEDPOINTS = 1.f / BAKEDPOINTS;
|
constexpr float INVBAKEDPOINTS = 1.f / BAKEDPOINTS;
|
||||||
|
|
||||||
// an implementation of a cubic bezier curve
|
// an implementation of a cubic bezier curve
|
||||||
// might do better later
|
// might do better later
|
||||||
// TODO: n-point curves
|
// TODO: n-point curves
|
||||||
class CBezierCurve {
|
class CBezierCurve {
|
||||||
public:
|
public:
|
||||||
// sets up the bezier curve.
|
// sets up the bezier curve.
|
||||||
// this EXCLUDES the 0,0 and 1,1 points,
|
// this EXCLUDES the 0,0 and 1,1 points,
|
||||||
void setup(std::vector<Vector2D>* points);
|
void setup(std::vector<Vector2D>* points);
|
||||||
|
|
||||||
float getYForT(float t);
|
float getYForT(float t);
|
||||||
float getXForT(float t);
|
float getXForT(float t);
|
||||||
float getYForPoint(float x);
|
float getYForPoint(float x);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// this INCLUDES the 0,0 and 1,1 points.
|
// this INCLUDES the 0,0 and 1,1 points.
|
||||||
std::deque<Vector2D> m_dPoints;
|
std::deque<Vector2D> m_dPoints;
|
||||||
|
|
||||||
std::array<Vector2D, BAKEDPOINTS> m_aPointsBaked;
|
std::array<Vector2D, BAKEDPOINTS> m_aPointsBaked;
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "Color.hpp"
|
#include "Color.hpp"
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
|
|
||||||
CColor::CColor() { }
|
CColor::CColor() {}
|
||||||
|
|
||||||
CColor::CColor(float r, float g, float b, float a) {
|
CColor::CColor(float r, float g, float b, float a) {
|
||||||
this->r = r;
|
this->r = r;
|
||||||
@@ -11,10 +11,10 @@ CColor::CColor(float r, float g, float b, float a) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CColor::CColor(uint64_t hex) {
|
CColor::CColor(uint64_t hex) {
|
||||||
this->r = RED(hex) * 255.f;
|
this->r = RED(hex);
|
||||||
this->g = GREEN(hex) * 255.f;
|
this->g = GREEN(hex);
|
||||||
this->b = BLUE(hex) * 255.f;
|
this->b = BLUE(hex);
|
||||||
this->a = ALPHA(hex) * 255.f;
|
this->a = ALPHA(hex);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t CColor::getAsHex() {
|
uint64_t CColor::getAsHex() {
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../includes.hpp"
|
#include <cstdint>
|
||||||
|
|
||||||
class CColor {
|
class CColor {
|
||||||
public:
|
public:
|
||||||
CColor();
|
CColor();
|
||||||
CColor(float, float, float, float);
|
CColor(float, float, float, float);
|
||||||
CColor(uint64_t);
|
CColor(uint64_t);
|
||||||
|
|
||||||
float r = 0, g = 0, b = 0, a = 255;
|
float r = 0, g = 0, b = 0, a = 1.f;
|
||||||
|
|
||||||
uint64_t getAsHex();
|
uint64_t getAsHex();
|
||||||
|
|
||||||
CColor operator- (const CColor& c2) const {
|
CColor operator-(const CColor& c2) const {
|
||||||
return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a);
|
return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
CColor operator+ (const CColor& c2) const {
|
CColor operator+(const CColor& c2) const {
|
||||||
return CColor(r + c2.r, g + c2.g, b + c2.b, a + c2.a);
|
return CColor(r + c2.r, g + c2.g, b + c2.b, a + c2.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
CColor operator* (const float& v) const {
|
CColor operator*(const float& v) const {
|
||||||
return CColor(r * v, g * v, b * v, a * v);
|
return CColor(r * v, g * v, b * v, a * v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,40 +4,121 @@
|
|||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
static const float transforms[][9] = {{
|
#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
1.0f, 0.0f, 0.0f,
|
#include <sys/sysctl.h>
|
||||||
0.0f, 1.0f, 0.0f,
|
#if defined(__DragonFly__)
|
||||||
0.0f, 0.0f, 1.0f,
|
#include <sys/kinfo.h> // struct kinfo_proc
|
||||||
},{
|
#elif defined(__FreeBSD__)
|
||||||
0.0f, 1.0f, 0.0f,
|
#include <sys/user.h> // struct kinfo_proc
|
||||||
-1.0f, 0.0f, 0.0f,
|
#endif
|
||||||
0.0f, 0.0f, 1.0f,
|
|
||||||
},{
|
#if defined(__NetBSD__)
|
||||||
-1.0f, 0.0f, 0.0f,
|
#undef KERN_PROC
|
||||||
0.0f, -1.0f, 0.0f,
|
#define KERN_PROC KERN_PROC2
|
||||||
0.0f, 0.0f, 1.0f,
|
#define KINFO_PROC struct kinfo_proc2
|
||||||
},{
|
#else
|
||||||
0.0f, -1.0f, 0.0f,
|
#define KINFO_PROC struct kinfo_proc
|
||||||
1.0f, 0.0f, 0.0f,
|
#endif
|
||||||
0.0f, 0.0f, 1.0f,
|
#if defined(__DragonFly__)
|
||||||
},{
|
#define KP_PPID(kp) kp.kp_ppid
|
||||||
-1.0f, 0.0f, 0.0f,
|
#elif defined(__FreeBSD__)
|
||||||
0.0f, 1.0f, 0.0f,
|
#define KP_PPID(kp) kp.ki_ppid
|
||||||
0.0f, 0.0f, 1.0f,
|
#else
|
||||||
},{
|
#define KP_PPID(kp) kp.p_ppid
|
||||||
0.0f, 1.0f, 0.0f,
|
#endif
|
||||||
1.0f, 0.0f, 0.0f,
|
#endif
|
||||||
0.0f, 0.0f, 1.0f,
|
|
||||||
},{
|
static const float transforms[][9] = {
|
||||||
1.0f, 0.0f, 0.0f,
|
{
|
||||||
0.0f, -1.0f, 0.0f,
|
1.0f,
|
||||||
0.0f, 0.0f, 1.0f,
|
0.0f,
|
||||||
},{
|
0.0f,
|
||||||
0.0f, -1.0f, 0.0f,
|
0.0f,
|
||||||
-1.0f, 0.0f, 0.0f,
|
1.0f,
|
||||||
0.0f, 0.0f, 1.0f,
|
0.0f,
|
||||||
},
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
0.0f,
|
||||||
|
-1.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
-1.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
-1.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0.0f,
|
||||||
|
-1.0f,
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
-1.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
1.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
-1.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0.0f,
|
||||||
|
-1.0f,
|
||||||
|
0.0f,
|
||||||
|
-1.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
0.0f,
|
||||||
|
1.0f,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string absolutePath(const std::string& rawpath, const std::string& currentPath) {
|
std::string absolutePath(const std::string& rawpath, const std::string& currentPath) {
|
||||||
@@ -62,21 +143,21 @@ std::string absolutePath(const std::string& rawpath, const std::string& currentP
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::string ownerString) {
|
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, const std::string& ownerString) {
|
||||||
ASSERT(pSignal);
|
ASSERT(pSignal);
|
||||||
ASSERT(pListener);
|
ASSERT(pListener);
|
||||||
|
|
||||||
wl_signal_add(pSignal, pListener);
|
wl_signal_add(pSignal, pListener);
|
||||||
|
|
||||||
Debug::log(LOG, "Registered signal for owner %x: %x -> %x (owner: %s)", pOwner, pSignal, pListener, ownerString.c_str());
|
Debug::log(LOG, "Registered signal for owner %lx: %lx -> %lx (owner: %s)", pOwner, pSignal, pListener, ownerString.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleNoop(struct wl_listener *listener, void *data) {
|
void handleNoop(struct wl_listener* listener, void* data) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getFormat(const char *fmt, ...) {
|
std::string getFormat(const char* fmt, ...) {
|
||||||
char* outputStr = nullptr;
|
char* outputStr = nullptr;
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
@@ -91,42 +172,44 @@ std::string getFormat(const char *fmt, ...) {
|
|||||||
|
|
||||||
std::string escapeJSONStrings(const std::string& str) {
|
std::string escapeJSONStrings(const std::string& str) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
for (auto &c : str) {
|
for (auto& c : str) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '"': oss << "\\\""; break;
|
case '"': oss << "\\\""; break;
|
||||||
case '\\': oss << "\\\\"; break;
|
case '\\': oss << "\\\\"; break;
|
||||||
case '\b': oss << "\\b"; break;
|
case '\b': oss << "\\b"; break;
|
||||||
case '\f': oss << "\\f"; break;
|
case '\f': oss << "\\f"; break;
|
||||||
case '\n': oss << "\\n"; break;
|
case '\n': oss << "\\n"; break;
|
||||||
case '\r': oss << "\\r"; break;
|
case '\r': oss << "\\r"; break;
|
||||||
case '\t': oss << "\\t"; break;
|
case '\t': oss << "\\t"; break;
|
||||||
default:
|
default:
|
||||||
if ('\x00' <= c && c <= '\x1f') {
|
if ('\x00' <= c && c <= '\x1f') {
|
||||||
oss << "\\u"
|
oss << "\\u" << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
|
||||||
<< std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
|
} else {
|
||||||
} else {
|
oss << c;
|
||||||
oss << c;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void scaleBox(wlr_box* box, float scale) {
|
void scaleBox(wlr_box* box, float scale) {
|
||||||
box->width = std::round(box->width * scale);
|
box->width = std::round(box->width * scale);
|
||||||
box->height = std::round(box->height * scale);
|
box->height = std::round(box->height * scale);
|
||||||
box->x = std::round(box->x * scale);
|
box->x = std::round(box->x * scale);
|
||||||
box->y = std::round(box->y * scale);
|
box->y = std::round(box->y * scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string removeBeginEndSpacesTabs(std::string str) {
|
std::string removeBeginEndSpacesTabs(std::string str) {
|
||||||
|
if (str.empty())
|
||||||
|
return str;
|
||||||
|
|
||||||
int countBefore = 0;
|
int countBefore = 0;
|
||||||
while (str[countBefore] == ' ' || str[countBefore] == '\t') {
|
while (str[countBefore] == ' ' || str[countBefore] == '\t') {
|
||||||
countBefore++;
|
countBefore++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int countAfter = 0;
|
int countAfter = 0;
|
||||||
while (str.length() != 0 && (str[str.length() - countAfter - 1] == ' ' || str[str.length() - 1 - countAfter] == '\t')) {
|
while ((int)str.length() - countAfter - 1 >= 0 && (str[str.length() - countAfter - 1] == ' ' || str[str.length() - 1 - countAfter] == '\t')) {
|
||||||
countAfter++;
|
countAfter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,41 +219,12 @@ std::string removeBeginEndSpacesTabs(std::string str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float getPlusMinusKeywordResult(std::string source, float relative) {
|
float getPlusMinusKeywordResult(std::string source, float relative) {
|
||||||
float result = INT_MAX;
|
try {
|
||||||
|
return relative + stof(source);
|
||||||
if (source.find_first_of("+") == 0) {
|
} catch (...) {
|
||||||
try {
|
Debug::log(ERR, "Invalid arg \"%s\" in getPlusMinusKeywordResult!", source.c_str());
|
||||||
if (source.contains("."))
|
return INT_MAX;
|
||||||
result = relative + std::stof(source.substr(1));
|
|
||||||
else
|
|
||||||
result = relative + std::stoi(source.substr(1));
|
|
||||||
} catch (...) {
|
|
||||||
Debug::log(ERR, "Invalid arg \"%s\" in getPlusMinusKeywordResult!", source.c_str());
|
|
||||||
return INT_MAX;
|
|
||||||
}
|
|
||||||
} else if (source.find_first_of("-") == 0) {
|
|
||||||
try {
|
|
||||||
if (source.contains("."))
|
|
||||||
result = relative - std::stof(source.substr(1));
|
|
||||||
else
|
|
||||||
result = relative - std::stoi(source.substr(1));
|
|
||||||
} catch (...) {
|
|
||||||
Debug::log(ERR, "Invalid arg \"%s\" in getPlusMinusKeywordResult!", source.c_str());
|
|
||||||
return INT_MAX;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
if (source.contains("."))
|
|
||||||
result = stof(source);
|
|
||||||
else
|
|
||||||
result = stoi(source);
|
|
||||||
} catch (...) {
|
|
||||||
Debug::log(ERR, "Invalid arg \"%s\" in getPlusMinusKeywordResult!", source.c_str());
|
|
||||||
return INT_MAX;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNumber(const std::string& str, bool allowfloat) {
|
bool isNumber(const std::string& str, bool allowfloat) {
|
||||||
@@ -178,7 +232,7 @@ bool isNumber(const std::string& str, bool allowfloat) {
|
|||||||
std::string copy = str;
|
std::string copy = str;
|
||||||
if (*copy.begin() == '-')
|
if (*copy.begin() == '-')
|
||||||
copy = copy.substr(1);
|
copy = copy.substr(1);
|
||||||
|
|
||||||
if (copy.empty())
|
if (copy.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -206,16 +260,50 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
|||||||
int result = INT_MAX;
|
int result = INT_MAX;
|
||||||
if (in.find("special") == 0) {
|
if (in.find("special") == 0) {
|
||||||
outName = "special";
|
outName = "special";
|
||||||
return SPECIAL_WORKSPACE_ID;
|
|
||||||
|
if (in.length() > 8) {
|
||||||
|
const auto NAME = in.substr(8);
|
||||||
|
|
||||||
|
const auto WS = g_pCompositor->getWorkspaceByName("special:" + NAME);
|
||||||
|
|
||||||
|
outName = "special:" + NAME;
|
||||||
|
|
||||||
|
return WS ? WS->m_iID : g_pCompositor->getNewSpecialID();
|
||||||
|
}
|
||||||
|
|
||||||
|
return SPECIAL_WORKSPACE_START;
|
||||||
} else if (in.find("name:") == 0) {
|
} else if (in.find("name:") == 0) {
|
||||||
const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1);
|
const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1);
|
||||||
const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME);
|
const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME);
|
||||||
if (!WORKSPACE) {
|
if (!WORKSPACE) {
|
||||||
result = g_pCompositor->getNextAvailableNamedWorkspace();
|
result = g_pCompositor->getNextAvailableNamedWorkspace();
|
||||||
} else {
|
} else {
|
||||||
result = WORKSPACE->m_iID;
|
result = WORKSPACE->m_iID;
|
||||||
}
|
}
|
||||||
outName = WORKSPACENAME;
|
outName = WORKSPACENAME;
|
||||||
|
} else if (in.find("empty") == 0) {
|
||||||
|
int id = 0;
|
||||||
|
while (++id < INT_MAX) {
|
||||||
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id);
|
||||||
|
if (!PWORKSPACE || (g_pCompositor->getWindowsOnWorkspace(id) == 0))
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
} else if (in.find("prev") == 0) {
|
||||||
|
if (!g_pCompositor->m_pLastMonitor)
|
||||||
|
return INT_MAX;
|
||||||
|
|
||||||
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
|
||||||
|
|
||||||
|
if (!PWORKSPACE)
|
||||||
|
return INT_MAX;
|
||||||
|
|
||||||
|
const auto PLASTWORKSPACE = g_pCompositor->getWorkspaceByID(PWORKSPACE->m_sPrevWorkspace.iID);
|
||||||
|
|
||||||
|
if (!PLASTWORKSPACE)
|
||||||
|
return INT_MAX;
|
||||||
|
|
||||||
|
outName = PLASTWORKSPACE->m_szName;
|
||||||
|
return PLASTWORKSPACE->m_iID;
|
||||||
} else {
|
} else {
|
||||||
if ((in[0] == 'm' || in[0] == 'e') && (in[1] == '-' || in[1] == '+') && isNumber(in.substr(2))) {
|
if ((in[0] == 'm' || in[0] == 'e') && (in[1] == '-' || in[1] == '+') && isNumber(in.substr(2))) {
|
||||||
bool onAllMonitors = in[0] == 'e';
|
bool onAllMonitors = in[0] == 'e';
|
||||||
@@ -230,52 +318,42 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
|||||||
result = (int)getPlusMinusKeywordResult(in.substr(1), 0);
|
result = (int)getPlusMinusKeywordResult(in.substr(1), 0);
|
||||||
|
|
||||||
// result now has +/- what we should move on mon
|
// result now has +/- what we should move on mon
|
||||||
int remains = (int)result;
|
int remains = (int)result;
|
||||||
int currentID = g_pCompositor->m_pLastMonitor->activeWorkspace;
|
|
||||||
int searchID = currentID;
|
|
||||||
|
|
||||||
while (remains != 0) {
|
std::vector<int> validWSes;
|
||||||
if (remains < 0)
|
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||||
searchID--;
|
if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID && !onAllMonitors))
|
||||||
else
|
continue;
|
||||||
searchID++;
|
|
||||||
|
|
||||||
if (g_pCompositor->workspaceIDOutOfBounds(searchID)){
|
validWSes.push_back(ws->m_iID);
|
||||||
// means we need to wrap around
|
}
|
||||||
int lowestID = 99999;
|
|
||||||
int highestID = -99999;
|
|
||||||
|
|
||||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
std::sort(validWSes.begin(), validWSes.end());
|
||||||
if (w->m_iID == SPECIAL_WORKSPACE_ID)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (w->m_iID < lowestID)
|
// get the offset
|
||||||
lowestID = w->m_iID;
|
remains = remains < 0 ? -((-remains) % validWSes.size()) : remains % validWSes.size();
|
||||||
|
|
||||||
if (w->m_iID > highestID)
|
// get the current item
|
||||||
highestID = w->m_iID;
|
int currentItem = -1;
|
||||||
}
|
for (size_t i = 0; i < validWSes.size(); i++) {
|
||||||
|
if (validWSes[i] == g_pCompositor->m_pLastMonitor->activeWorkspace) {
|
||||||
if (remains < 0)
|
currentItem = i;
|
||||||
searchID = highestID;
|
break;
|
||||||
else
|
|
||||||
searchID = lowestID;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(searchID); PWORKSPACE && PWORKSPACE->m_iID != SPECIAL_WORKSPACE_ID) {
|
|
||||||
if (onAllMonitors || PWORKSPACE->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
|
|
||||||
currentID = PWORKSPACE->m_iID;
|
|
||||||
|
|
||||||
if (remains < 0)
|
|
||||||
remains++;
|
|
||||||
else
|
|
||||||
remains--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = currentID;
|
// apply
|
||||||
outName = g_pCompositor->getWorkspaceByID(currentID)->m_szName;
|
currentItem += remains;
|
||||||
|
|
||||||
|
// sanitize
|
||||||
|
if (currentItem >= (int)validWSes.size()) {
|
||||||
|
currentItem = currentItem % validWSes.size();
|
||||||
|
} else if (currentItem < 0) {
|
||||||
|
currentItem = validWSes.size() + currentItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = validWSes[currentItem];
|
||||||
|
outName = g_pCompositor->getWorkspaceByID(validWSes[currentItem])->m_szName;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (in[0] == '+' || in[0] == '-') {
|
if (in[0] == '+' || in[0] == '-') {
|
||||||
@@ -309,8 +387,8 @@ float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Ve
|
|||||||
|
|
||||||
// Execute a shell command and get the output
|
// Execute a shell command and get the output
|
||||||
std::string execAndGet(const char* cmd) {
|
std::string execAndGet(const char* cmd) {
|
||||||
std::array<char, 128> buffer;
|
std::array<char, 128> buffer;
|
||||||
std::string result;
|
std::string result;
|
||||||
const std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
|
const std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
|
||||||
if (!pipe) {
|
if (!pipe) {
|
||||||
Debug::log(ERR, "execAndGet: failed in pipe");
|
Debug::log(ERR, "execAndGet: failed in pipe");
|
||||||
@@ -331,10 +409,14 @@ void logSystemInfo() {
|
|||||||
Debug::log(LOG, "Node name: %s", unameInfo.nodename);
|
Debug::log(LOG, "Node name: %s", unameInfo.nodename);
|
||||||
Debug::log(LOG, "Release: %s", unameInfo.release);
|
Debug::log(LOG, "Release: %s", unameInfo.release);
|
||||||
Debug::log(LOG, "Version: %s", unameInfo.version);
|
Debug::log(LOG, "Version: %s", unameInfo.version);
|
||||||
|
|
||||||
Debug::log(NONE, "\n");
|
Debug::log(NONE, "\n");
|
||||||
|
|
||||||
|
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
||||||
|
const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga");
|
||||||
|
#else
|
||||||
const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA");
|
const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA");
|
||||||
|
#endif
|
||||||
Debug::log(LOG, "GPU information:\n%s\n", GPUINFO.c_str());
|
Debug::log(LOG, "GPU information:\n%s\n", GPUINFO.c_str());
|
||||||
|
|
||||||
if (GPUINFO.contains("NVIDIA")) {
|
if (GPUINFO.contains("NVIDIA")) {
|
||||||
@@ -351,14 +433,14 @@ void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) {
|
|||||||
memset(mat, 0, sizeof(*mat) * 9);
|
memset(mat, 0, sizeof(*mat) * 9);
|
||||||
|
|
||||||
const float* t = transforms[tr];
|
const float* t = transforms[tr];
|
||||||
float x = 2.0f / w;
|
float x = 2.0f / w;
|
||||||
float y = 2.0f / h;
|
float y = 2.0f / h;
|
||||||
|
|
||||||
// Rotation + reflection
|
// Rotation + reflection
|
||||||
mat[0] = x * t[0];
|
mat[0] = x * t[0];
|
||||||
mat[1] = x * t[1];
|
mat[1] = x * t[1];
|
||||||
mat[3] = y * -t[3];
|
mat[3] = y * t[3];
|
||||||
mat[4] = y * -t[4];
|
mat[4] = y * t[4];
|
||||||
|
|
||||||
// Translation
|
// Translation
|
||||||
mat[2] = -copysign(1.0f, mat[0] + mat[1]);
|
mat[2] = -copysign(1.0f, mat[0] + mat[1]);
|
||||||
@@ -369,22 +451,41 @@ void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int64_t getPPIDof(int64_t pid) {
|
int64_t getPPIDof(int64_t pid) {
|
||||||
std::string dir = "/proc/" + std::to_string(pid) + "/status";
|
#if defined(KERN_PROC_PID)
|
||||||
FILE* infile;
|
int mib[] = {
|
||||||
|
CTL_KERN,
|
||||||
|
KERN_PROC,
|
||||||
|
KERN_PROC_PID,
|
||||||
|
(int)pid,
|
||||||
|
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
|
sizeof(KINFO_PROC),
|
||||||
|
1,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
u_int miblen = sizeof(mib) / sizeof(mib[0]);
|
||||||
|
KINFO_PROC kp;
|
||||||
|
size_t sz = sizeof(KINFO_PROC);
|
||||||
|
if (sysctl(mib, miblen, &kp, &sz, NULL, 0) != -1)
|
||||||
|
return KP_PPID(kp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
std::string dir = "/proc/" + std::to_string(pid) + "/status";
|
||||||
|
FILE* infile;
|
||||||
|
|
||||||
infile = fopen(dir.c_str(), "r");
|
infile = fopen(dir.c_str(), "r");
|
||||||
if (!infile)
|
if (!infile)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
char* line = nullptr;
|
char* line = nullptr;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
ssize_t len2 = 0;
|
ssize_t len2 = 0;
|
||||||
|
|
||||||
std::string pidstr;
|
std::string pidstr;
|
||||||
|
|
||||||
while ((len2 = getline(&line, &len, infile)) != -1) {
|
while ((len2 = getline(&line, &len, infile)) != -1) {
|
||||||
if (strstr(line, "PPid:")) {
|
if (strstr(line, "PPid:")) {
|
||||||
pidstr = std::string(line, len2);
|
pidstr = std::string(line, len2);
|
||||||
const auto tabpos = pidstr.find_last_of('\t');
|
const auto tabpos = pidstr.find_last_of('\t');
|
||||||
if (tabpos != std::string::npos)
|
if (tabpos != std::string::npos)
|
||||||
pidstr = pidstr.substr(tabpos);
|
pidstr = pidstr.substr(tabpos);
|
||||||
@@ -398,7 +499,67 @@ int64_t getPPIDof(int64_t pid) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
return std::stoll(pidstr);
|
return std::stoll(pidstr);
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) { return 0; }
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t configStringToInt(const std::string& VALUE) {
|
||||||
|
if (VALUE.find("0x") == 0) {
|
||||||
|
// Values with 0x are hex
|
||||||
|
const auto VALUEWITHOUTHEX = VALUE.substr(2);
|
||||||
|
return stol(VALUEWITHOUTHEX, nullptr, 16);
|
||||||
|
} else if (VALUE.find("rgba(") == 0 && VALUE.find(')') == VALUE.length() - 1) {
|
||||||
|
const auto VALUEWITHOUTFUNC = VALUE.substr(5, VALUE.length() - 6);
|
||||||
|
|
||||||
|
if (removeBeginEndSpacesTabs(VALUEWITHOUTFUNC).length() != 8) {
|
||||||
|
Debug::log(WARN, "invalid length %i for rgba", VALUEWITHOUTFUNC.length());
|
||||||
|
throw std::invalid_argument("rgba() expects length of 8 characters (4 bytes)");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto RGBA = std::stol(VALUEWITHOUTFUNC, nullptr, 16);
|
||||||
|
|
||||||
|
// now we need to RGBA -> ARGB. The config holds ARGB only.
|
||||||
|
return (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF);
|
||||||
|
} else if (VALUE.find("rgb(") == 0 && VALUE.find(')') == VALUE.length() - 1) {
|
||||||
|
const auto VALUEWITHOUTFUNC = VALUE.substr(4, VALUE.length() - 5);
|
||||||
|
|
||||||
|
if (removeBeginEndSpacesTabs(VALUEWITHOUTFUNC).length() != 6) {
|
||||||
|
Debug::log(WARN, "invalid length %i for rgb", VALUEWITHOUTFUNC.length());
|
||||||
|
throw std::invalid_argument("rgb() expects length of 6 characters (3 bytes)");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto RGB = std::stol(VALUEWITHOUTFUNC, nullptr, 16);
|
||||||
|
|
||||||
|
return RGB + 0xFF000000; // 0xFF for opaque
|
||||||
|
} else if (VALUE.find("true") == 0 || VALUE.find("on") == 0 || VALUE.find("yes") == 0) {
|
||||||
|
return 1;
|
||||||
|
} else if (VALUE.find("false") == 0 || VALUE.find("off") == 0 || VALUE.find("no") == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
return std::stoll(VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
double normalizeAngleRad(double ang) {
|
||||||
|
if (ang > M_PI * 2) {
|
||||||
|
while (ang > M_PI * 2)
|
||||||
|
ang -= M_PI * 2;
|
||||||
|
return ang;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ang < 0.0) {
|
||||||
|
while (ang < 0.0)
|
||||||
|
ang += M_PI * 2;
|
||||||
|
return ang;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ang;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string replaceInString(std::string subject, const std::string& search, const std::string& replace) {
|
||||||
|
size_t pos = 0;
|
||||||
|
while ((pos = subject.find(search, pos)) != std::string::npos) {
|
||||||
|
subject.replace(pos, search.length(), replace);
|
||||||
|
pos += replace.length();
|
||||||
|
}
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,19 +3,20 @@
|
|||||||
#include "../includes.hpp"
|
#include "../includes.hpp"
|
||||||
|
|
||||||
std::string absolutePath(const std::string&, const std::string&);
|
std::string absolutePath(const std::string&, const std::string&);
|
||||||
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, std::string ownerString);
|
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString);
|
||||||
std::string getFormat(const char *fmt, ...); // Basically Debug::log to a string
|
std::string getFormat(const char* fmt, ...); // Basically Debug::log to a string
|
||||||
std::string escapeJSONStrings(const std::string& str);
|
std::string escapeJSONStrings(const std::string& str);
|
||||||
void scaleBox(wlr_box*, float);
|
void scaleBox(wlr_box*, float);
|
||||||
std::string removeBeginEndSpacesTabs(std::string);
|
std::string removeBeginEndSpacesTabs(std::string);
|
||||||
bool isNumber(const std::string&, bool allowfloat = false);
|
bool isNumber(const std::string&, bool allowfloat = false);
|
||||||
bool isDirection(const std::string&);
|
bool isDirection(const std::string&);
|
||||||
int getWorkspaceIDFromString(const std::string&, std::string&);
|
int getWorkspaceIDFromString(const std::string&, std::string&);
|
||||||
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
|
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
|
||||||
void logSystemInfo();
|
void logSystemInfo();
|
||||||
std::string execAndGet(const char*);
|
std::string execAndGet(const char*);
|
||||||
int64_t getPPIDof(int64_t pid);
|
int64_t getPPIDof(int64_t pid);
|
||||||
|
int64_t configStringToInt(const std::string&);
|
||||||
float getPlusMinusKeywordResult(std::string in, float relative);
|
float getPlusMinusKeywordResult(std::string in, float relative);
|
||||||
|
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);
|
||||||
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);
|
double normalizeAngleRad(double ang);
|
||||||
|
std::string replaceInString(std::string subject, const std::string& search, const std::string& replace);
|
||||||
@@ -2,22 +2,51 @@
|
|||||||
|
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
|
int ratHandler(void* data) {
|
||||||
|
g_pHyprRenderer->renderMonitor((CMonitor*)data);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMonitor::CMonitor() {
|
||||||
|
wlr_damage_ring_init(&damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
CMonitor::~CMonitor() {
|
||||||
|
wlr_damage_ring_finish(&damage);
|
||||||
|
}
|
||||||
|
|
||||||
void CMonitor::onConnect(bool noRule) {
|
void CMonitor::onConnect(bool noRule) {
|
||||||
if (m_bEnabled)
|
hyprListener_monitorDestroy.removeCallback();
|
||||||
|
hyprListener_monitorFrame.removeCallback();
|
||||||
|
hyprListener_monitorStateRequest.removeCallback();
|
||||||
|
hyprListener_monitorDamage.removeCallback();
|
||||||
|
hyprListener_monitorNeedsFrame.removeCallback();
|
||||||
|
hyprListener_monitorCommit.removeCallback();
|
||||||
|
hyprListener_monitorFrame.initCallback(&output->events.frame, &Events::listener_monitorFrame, this);
|
||||||
|
hyprListener_monitorDestroy.initCallback(&output->events.destroy, &Events::listener_monitorDestroy, this);
|
||||||
|
hyprListener_monitorStateRequest.initCallback(&output->events.request_state, &Events::listener_monitorStateRequest, this);
|
||||||
|
hyprListener_monitorDamage.initCallback(&output->events.damage, &Events::listener_monitorDamage, this);
|
||||||
|
hyprListener_monitorNeedsFrame.initCallback(&output->events.needs_frame, &Events::listener_monitorNeedsFrame, this);
|
||||||
|
hyprListener_monitorCommit.initCallback(&output->events.commit, &Events::listener_monitorCommit, this);
|
||||||
|
|
||||||
|
if (m_bEnabled) {
|
||||||
|
wlr_output_enable(output, 1);
|
||||||
|
wlr_output_commit(output);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
szName = output->name;
|
szName = output->name;
|
||||||
|
|
||||||
|
if (!wlr_backend_is_drm(output->backend))
|
||||||
|
createdByUser = true; // should be true. WL, X11 and Headless backends should be addable / removable
|
||||||
|
|
||||||
// get monitor rule that matches
|
// get monitor rule that matches
|
||||||
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(output->name, output->description ? output->description : "");
|
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(output->name, output->description ? output->description : "");
|
||||||
|
|
||||||
hyprListener_monitorFrame.initCallback(&output->events.frame, &Events::listener_monitorFrame, this);
|
|
||||||
hyprListener_monitorDestroy.initCallback(&output->events.destroy, &Events::listener_monitorDestroy, this);
|
|
||||||
|
|
||||||
// if it's disabled, disable and ignore
|
// if it's disabled, disable and ignore
|
||||||
if (monitorRule.disabled) {
|
if (monitorRule.disabled) {
|
||||||
|
|
||||||
wlr_output_enable_adaptive_sync(output, 1);
|
|
||||||
wlr_output_set_scale(output, 1);
|
wlr_output_set_scale(output, 1);
|
||||||
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
|
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
|
||||||
|
|
||||||
@@ -58,15 +87,15 @@ void CMonitor::onConnect(bool noRule) {
|
|||||||
|
|
||||||
if (output->non_desktop) {
|
if (output->non_desktop) {
|
||||||
Debug::log(LOG, "Not configuring non-desktop output");
|
Debug::log(LOG, "Not configuring non-desktop output");
|
||||||
if (g_pCompositor->m_sWRLDRMLeaseMgr) {
|
if (g_pCompositor->m_sWRLDRMLeaseMgr) {
|
||||||
wlr_drm_lease_v1_manager_offer_output(g_pCompositor->m_sWRLDRMLeaseMgr, output);
|
wlr_drm_lease_v1_manager_offer_output(g_pCompositor->m_sWRLDRMLeaseMgr, output);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_bRenderingInitPassed) {
|
if (!m_bRenderingInitPassed) {
|
||||||
output->allocator = nullptr;
|
output->allocator = nullptr;
|
||||||
output->renderer = nullptr;
|
output->renderer = nullptr;
|
||||||
wlr_output_init_render(output, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
|
wlr_output_init_render(output, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
|
||||||
m_bRenderingInitPassed = true;
|
m_bRenderingInitPassed = true;
|
||||||
}
|
}
|
||||||
@@ -82,34 +111,29 @@ void CMonitor::onConnect(bool noRule) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()){
|
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()) {
|
||||||
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
|
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_bEnabled = true;
|
m_bEnabled = true;
|
||||||
|
|
||||||
wlr_output_set_scale(output, monitorRule.scale);
|
|
||||||
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, monitorRule.scale);
|
|
||||||
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL); // TODO: support other transforms
|
|
||||||
|
|
||||||
// create it in the arr
|
// create it in the arr
|
||||||
vecPosition = monitorRule.offset;
|
vecPosition = monitorRule.offset;
|
||||||
vecSize = monitorRule.resolution;
|
vecSize = monitorRule.resolution;
|
||||||
refreshRate = monitorRule.refreshRate;
|
refreshRate = monitorRule.refreshRate;
|
||||||
|
|
||||||
wlr_output_enable(output, 1);
|
wlr_output_enable(output, 1);
|
||||||
|
|
||||||
// TODO: this doesn't seem to set the X and Y correctly,
|
|
||||||
// wlr_output_layout_output_coords returns invalid values, I think...
|
|
||||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, output, monitorRule.offset.x, monitorRule.offset.y);
|
|
||||||
|
|
||||||
// set mode, also applies
|
// set mode, also applies
|
||||||
if (!noRule)
|
if (!noRule)
|
||||||
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
|
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
|
||||||
|
|
||||||
Debug::log(LOG, "Added new monitor with name %s at %i,%i with size %ix%i, pointer %x", output->name, (int)vecPosition.x, (int)vecPosition.y, (int)vecPixelSize.x, (int)vecPixelSize.y, output);
|
wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y);
|
||||||
|
|
||||||
damage = wlr_output_damage_create(output);
|
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale);
|
||||||
|
|
||||||
|
Debug::log(LOG, "Added new monitor with name %s at %i,%i with size %ix%i, pointer %lx", output->name, (int)vecPosition.x, (int)vecPosition.y, (int)vecPixelSize.x,
|
||||||
|
(int)vecPixelSize.y, output);
|
||||||
|
|
||||||
// add a WLR workspace group
|
// add a WLR workspace group
|
||||||
if (!pWLRWorkspaceGroupHandle) {
|
if (!pWLRWorkspaceGroupHandle) {
|
||||||
@@ -120,29 +144,64 @@ void CMonitor::onConnect(bool noRule) {
|
|||||||
|
|
||||||
setupDefaultWS(monitorRule);
|
setupDefaultWS(monitorRule);
|
||||||
|
|
||||||
|
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||||
|
if (ws->m_szLastMonitor == szName) {
|
||||||
|
g_pCompositor->moveWorkspaceToMonitor(ws.get(), this);
|
||||||
|
ws->startAnim(true, true, true);
|
||||||
|
ws->m_szLastMonitor = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
scale = monitorRule.scale;
|
scale = monitorRule.scale;
|
||||||
|
if (scale < 0.1)
|
||||||
|
scale = getDefaultScale();
|
||||||
|
|
||||||
m_pThisWrap = nullptr;
|
m_pThisWrap = nullptr;
|
||||||
|
|
||||||
forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
|
forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
|
||||||
//
|
//
|
||||||
|
|
||||||
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
|
||||||
g_pCompositor->m_pLastMonitor = this;
|
EMIT_HOOK_EVENT("monitorAdded", this);
|
||||||
|
|
||||||
|
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
||||||
|
g_pCompositor->setActiveMonitor(this);
|
||||||
|
|
||||||
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale);
|
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale);
|
||||||
|
|
||||||
g_pHyprRenderer->arrangeLayersForMonitor(ID);
|
g_pHyprRenderer->arrangeLayersForMonitor(ID);
|
||||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
||||||
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
|
// ensure VRR (will enable if necessary)
|
||||||
|
g_pConfigManager->ensureVRR(this);
|
||||||
|
|
||||||
|
// verify last mon valid
|
||||||
|
bool found = false;
|
||||||
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||||
|
if (m.get() == g_pCompositor->m_pLastMonitor) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
g_pCompositor->setActiveMonitor(this);
|
||||||
|
|
||||||
|
renderTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ratHandler, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMonitor::onDisconnect() {
|
void CMonitor::onDisconnect() {
|
||||||
|
|
||||||
|
if (renderTimer) {
|
||||||
|
wl_event_source_remove(renderTimer);
|
||||||
|
renderTimer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_bEnabled || g_pCompositor->m_bIsShuttingDown)
|
if (!m_bEnabled || g_pCompositor->m_bIsShuttingDown)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Debug::log(LOG, "onDisconnect called for %s", output->name);
|
||||||
|
|
||||||
// Cleanup everything. Move windows back, snap cursor, shit.
|
// Cleanup everything. Move windows back, snap cursor, shit.
|
||||||
CMonitor* BACKUPMON = nullptr;
|
CMonitor* BACKUPMON = nullptr;
|
||||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||||
@@ -166,26 +225,43 @@ void CMonitor::onDisconnect() {
|
|||||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_bEnabled = false;
|
m_bEnabled = false;
|
||||||
m_bRenderingInitPassed = false;
|
m_bRenderingInitPassed = false;
|
||||||
|
|
||||||
hyprListener_monitorFrame.removeCallback();
|
hyprListener_monitorFrame.removeCallback();
|
||||||
|
hyprListener_monitorDamage.removeCallback();
|
||||||
|
hyprListener_monitorNeedsFrame.removeCallback();
|
||||||
|
hyprListener_monitorCommit.removeCallback();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 4; ++i) {
|
||||||
|
for (auto& ls : m_aLayerSurfaceLayers[i]) {
|
||||||
|
if (ls->layerSurface && !ls->fadingOut)
|
||||||
|
wlr_layer_surface_v1_destroy(ls->layerSurface);
|
||||||
|
}
|
||||||
|
m_aLayerSurfaceLayers[i].clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug::log(LOG, "Removed monitor %s!", szName.c_str());
|
||||||
|
|
||||||
|
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName});
|
||||||
|
EMIT_HOOK_EVENT("monitorRemoved", this);
|
||||||
|
|
||||||
if (!BACKUPMON) {
|
if (!BACKUPMON) {
|
||||||
Debug::log(WARN, "Unplugged last monitor, entering an unsafe state. Good luck my friend.");
|
Debug::log(WARN, "Unplugged last monitor, entering an unsafe state. Good luck my friend.");
|
||||||
|
|
||||||
hyprListener_monitorMode.removeCallback();
|
hyprListener_monitorStateRequest.removeCallback();
|
||||||
hyprListener_monitorDestroy.removeCallback();
|
hyprListener_monitorDestroy.removeCallback();
|
||||||
|
|
||||||
g_pCompositor->m_bUnsafeState = true;
|
g_pCompositor->m_bUnsafeState = true;
|
||||||
|
|
||||||
|
std::erase_if(g_pCompositor->m_vMonitors, [&](std::shared_ptr<CMonitor>& el) { return el.get() == this; });
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto BACKUPWORKSPACE = BACKUPMON->activeWorkspace > 0 ? std::to_string(BACKUPMON->activeWorkspace) : "name:" + g_pCompositor->getWorkspaceByID(BACKUPMON->activeWorkspace)->m_szName;
|
|
||||||
|
|
||||||
// snap cursor
|
// snap cursor
|
||||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f, BACKUPMON->vecPosition.y + BACKUPMON->vecTransformedSize.y / 2.f);
|
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f,
|
||||||
|
BACKUPMON->vecPosition.y + BACKUPMON->vecTransformedSize.y / 2.f);
|
||||||
|
|
||||||
// move workspaces
|
// move workspaces
|
||||||
std::deque<CWorkspace*> wspToMove;
|
std::deque<CWorkspace*> wspToMove;
|
||||||
@@ -196,51 +272,93 @@ void CMonitor::onDisconnect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto& w : wspToMove) {
|
for (auto& w : wspToMove) {
|
||||||
|
w->m_szLastMonitor = szName;
|
||||||
g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON);
|
g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON);
|
||||||
w->startAnim(true, true, true);
|
w->startAnim(true, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
activeWorkspace = -1;
|
activeWorkspace = -1;
|
||||||
|
|
||||||
wlr_output_damage_destroy(damage);
|
|
||||||
|
|
||||||
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
|
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
|
||||||
|
|
||||||
wlr_output_enable(output, false);
|
wlr_output_enable(output, false);
|
||||||
|
|
||||||
wlr_output_commit(output);
|
wlr_output_commit(output);
|
||||||
|
|
||||||
g_pCompositor->m_vWorkspaces.erase(std::remove_if(g_pCompositor->m_vWorkspaces.begin(), g_pCompositor->m_vWorkspaces.end(), [&](std::unique_ptr<CWorkspace>& el) { return el->m_iMonitorID == ID; }));
|
std::erase_if(g_pCompositor->m_vWorkspaces, [&](std::unique_ptr<CWorkspace>& el) { return el->m_iMonitorID == ID; });
|
||||||
|
|
||||||
Debug::log(LOG, "Removed monitor %s!", szName.c_str());
|
if (g_pCompositor->m_pLastMonitor == this)
|
||||||
|
g_pCompositor->setActiveMonitor(BACKUPMON);
|
||||||
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName});
|
if (g_pHyprRenderer->m_pMostHzMonitor == this) {
|
||||||
|
int mostHz = 0;
|
||||||
|
CMonitor* pMonitorMostHz = nullptr;
|
||||||
|
|
||||||
g_pCompositor->m_vMonitors.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](std::shared_ptr<CMonitor>& el) { return el.get() == this; }));
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||||
|
if (m->refreshRate > mostHz && m.get() != this) {
|
||||||
|
pMonitorMostHz = m.get();
|
||||||
|
mostHz = m->refreshRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pHyprRenderer->m_pMostHzMonitor = pMonitorMostHz;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::erase_if(g_pCompositor->m_vMonitors, [&](std::shared_ptr<CMonitor>& el) { return el.get() == this; });
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMonitor::addDamage(pixman_region32_t* rg) {
|
void CMonitor::addDamage(const pixman_region32_t* rg) {
|
||||||
wlr_output_damage_add(damage, rg);
|
static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue;
|
||||||
|
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
||||||
|
wlr_damage_ring_add_whole(&damage);
|
||||||
|
g_pCompositor->scheduleFrameForMonitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wlr_damage_ring_add(&damage, rg))
|
||||||
|
g_pCompositor->scheduleFrameForMonitor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMonitor::addDamage(wlr_box* box) {
|
void CMonitor::addDamage(const wlr_box* box) {
|
||||||
wlr_output_damage_add_box(damage, box);
|
static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue;
|
||||||
|
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
||||||
|
wlr_damage_ring_add_whole(&damage);
|
||||||
|
g_pCompositor->scheduleFrameForMonitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wlr_damage_ring_add_box(&damage, box))
|
||||||
|
g_pCompositor->scheduleFrameForMonitor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMonitor::isMirror() {
|
bool CMonitor::isMirror() {
|
||||||
return pMirrorOf != nullptr;
|
return pMirrorOf != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CMonitor::findAvailableDefaultWS() {
|
||||||
|
for (size_t i = 1; i < INT32_MAX; ++i) {
|
||||||
|
if (g_pCompositor->getWorkspaceByID(i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (const auto BOUND = g_pConfigManager->getBoundMonitorStringForWS(std::to_string(i)); !BOUND.empty() && BOUND != szName)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return INT32_MAX; // shouldn't be reachable
|
||||||
|
}
|
||||||
|
|
||||||
void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
|
void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
|
||||||
// Workspace
|
// Workspace
|
||||||
std::string newDefaultWorkspaceName = "";
|
std::string newDefaultWorkspaceName = "";
|
||||||
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_vWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
|
int64_t WORKSPACEID = g_pConfigManager->getDefaultWorkspaceFor(szName).empty() ?
|
||||||
|
findAvailableDefaultWS() :
|
||||||
|
getWorkspaceIDFromString(g_pConfigManager->getDefaultWorkspaceFor(szName), newDefaultWorkspaceName);
|
||||||
|
|
||||||
if (WORKSPACEID == INT_MAX || WORKSPACEID == (long unsigned int)SPECIAL_WORKSPACE_ID) {
|
if (WORKSPACEID == INT_MAX || (WORKSPACEID >= SPECIAL_WORKSPACE_START && WORKSPACEID <= -2)) {
|
||||||
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
|
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
|
||||||
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
||||||
|
|
||||||
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace.c_str());
|
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", g_pConfigManager->getDefaultWorkspaceFor(szName).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||||
@@ -269,6 +387,7 @@ void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
|
|||||||
|
|
||||||
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
||||||
PNEWWORKSPACE->setActive(true);
|
PNEWWORKSPACE->setActive(true);
|
||||||
|
PNEWWORKSPACE->m_szLastMonitor = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMonitor::setMirror(const std::string& mirrorOf) {
|
void CMonitor::setMirror(const std::string& mirrorOf) {
|
||||||
@@ -312,13 +431,14 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()) {
|
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) ==
|
||||||
|
g_pCompositor->m_vMonitors.end()) {
|
||||||
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
|
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
setupDefaultWS(RULE);
|
setupDefaultWS(RULE);
|
||||||
|
|
||||||
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, output, (int)vecPosition.x, (int)vecPosition.y);
|
g_pHyprRenderer->applyMonitorRule(this, (SMonitorRule*)&RULE, true); // will apply the offset and stuff
|
||||||
} else {
|
} else {
|
||||||
CMonitor* BACKUPMON = nullptr;
|
CMonitor* BACKUPMON = nullptr;
|
||||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||||
@@ -345,17 +465,130 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
|
|||||||
|
|
||||||
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
|
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
|
||||||
|
|
||||||
vecPosition = Vector2D(-1337420, -1337420);
|
vecPosition = PMIRRORMON->vecPosition;
|
||||||
|
|
||||||
pMirrorOf = PMIRRORMON;
|
pMirrorOf = PMIRRORMON;
|
||||||
|
|
||||||
pMirrorOf->mirrors.push_back(this);
|
pMirrorOf->mirrors.push_back(this);
|
||||||
|
|
||||||
// remove from mvmonitors
|
// remove from mvmonitors
|
||||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) != g_pCompositor->m_vMonitors.end()) {
|
std::erase_if(g_pCompositor->m_vMonitors, [&](const auto& other) { return other.get() == this; });
|
||||||
g_pCompositor->m_vMonitors.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](const auto& other) { return other.get() == this; }));
|
|
||||||
}
|
|
||||||
|
|
||||||
g_pCompositor->m_pLastMonitor = g_pCompositor->m_vMonitors.front().get();
|
g_pCompositor->setActiveMonitor(g_pCompositor->m_vMonitors.front().get());
|
||||||
|
|
||||||
|
g_pCompositor->sanityCheckWorkspaces();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float CMonitor::getDefaultScale() {
|
||||||
|
if (!m_bEnabled)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
static constexpr double MMPERINCH = 25.4;
|
||||||
|
|
||||||
|
const auto DIAGONALPX = sqrt(pow(vecPixelSize.x, 2) + pow(vecPixelSize.y, 2));
|
||||||
|
const auto DIAGONALIN = sqrt(pow(output->phys_width / MMPERINCH, 2) + pow(output->phys_height / MMPERINCH, 2));
|
||||||
|
|
||||||
|
const auto PPI = DIAGONALPX / DIAGONALIN;
|
||||||
|
|
||||||
|
if (PPI > 200 /* High PPI, 2x*/)
|
||||||
|
return 2;
|
||||||
|
else if (PPI > 140 /* Medium PPI, 1.5x*/)
|
||||||
|
return 1.5;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal) {
|
||||||
|
if (!pWorkspace)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pWorkspace->m_bIsSpecialWorkspace) {
|
||||||
|
Debug::log(ERR, "BUG THIS: Attempted to changeWorkspace to special!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pWorkspace->m_iID == activeWorkspace) {
|
||||||
|
// in some cases (e.g. workspace from one monitor to another)
|
||||||
|
// we need to send this
|
||||||
|
g_pCompositor->deactivateAllWLRWorkspaces(pWorkspace->m_pWlrHandle);
|
||||||
|
pWorkspace->setActive(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto POLDWORKSPACE = g_pCompositor->getWorkspaceByID(activeWorkspace);
|
||||||
|
|
||||||
|
activeWorkspace = pWorkspace->m_iID;
|
||||||
|
|
||||||
|
if (!internal) {
|
||||||
|
const auto ANIMTOLEFT = pWorkspace->m_iID > POLDWORKSPACE->m_iID;
|
||||||
|
POLDWORKSPACE->startAnim(false, ANIMTOLEFT);
|
||||||
|
pWorkspace->startAnim(true, ANIMTOLEFT);
|
||||||
|
|
||||||
|
// move pinned windows
|
||||||
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
|
if (w->m_iWorkspaceID == POLDWORKSPACE->m_iID && w->m_bPinned) {
|
||||||
|
w->m_iWorkspaceID = pWorkspace->m_iID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto PLASTWINDOW = pWorkspace->getLastFocusedWindow(); PLASTWINDOW)
|
||||||
|
g_pCompositor->focusWindow(PLASTWINDOW);
|
||||||
|
else {
|
||||||
|
g_pCompositor->focusWindow(nullptr);
|
||||||
|
g_pInputManager->refocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
||||||
|
|
||||||
|
// set some flags and fire event
|
||||||
|
g_pCompositor->deactivateAllWLRWorkspaces(pWorkspace->m_pWlrHandle);
|
||||||
|
pWorkspace->setActive(true);
|
||||||
|
g_pEventManager->postEvent(SHyprIPCEvent{"workspace", pWorkspace->m_szName});
|
||||||
|
EMIT_HOOK_EVENT("workspace", pWorkspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageMonitor(this);
|
||||||
|
|
||||||
|
g_pCompositor->updateFullscreenFadeOnWorkspace(pWorkspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMonitor::changeWorkspace(const int& id, bool internal) {
|
||||||
|
changeWorkspace(g_pCompositor->getWorkspaceByID(id), internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) {
|
||||||
|
g_pHyprRenderer->damageMonitor(this);
|
||||||
|
|
||||||
|
if (!pWorkspace) {
|
||||||
|
// remove special if exists
|
||||||
|
if (const auto EXISTINGSPECIAL = g_pCompositor->getWorkspaceByID(specialWorkspaceID); EXISTINGSPECIAL)
|
||||||
|
EXISTINGSPECIAL->startAnim(false, false);
|
||||||
|
specialWorkspaceID = 0;
|
||||||
|
|
||||||
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
||||||
|
|
||||||
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(activeWorkspace);
|
||||||
|
if (const auto PLAST = PWORKSPACE->getLastFocusedWindow(); PLAST)
|
||||||
|
g_pCompositor->focusWindow(PLAST);
|
||||||
|
else
|
||||||
|
g_pInputManager->refocus();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open special
|
||||||
|
pWorkspace->m_iMonitorID = ID;
|
||||||
|
specialWorkspaceID = pWorkspace->m_iID;
|
||||||
|
pWorkspace->startAnim(true, true);
|
||||||
|
|
||||||
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
||||||
|
|
||||||
|
if (const auto PLAST = pWorkspace->getLastFocusedWindow(); PLAST)
|
||||||
|
g_pCompositor->focusWindow(PLAST);
|
||||||
|
else
|
||||||
|
g_pInputManager->refocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMonitor::setSpecialWorkspace(const int& id) {
|
||||||
|
setSpecialWorkspace(g_pCompositor->getWorkspaceByID(id));
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,71 +6,89 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include "Timer.hpp"
|
||||||
|
|
||||||
struct SMonitorRule;
|
struct SMonitorRule;
|
||||||
|
|
||||||
class CMonitor {
|
class CMonitor {
|
||||||
public:
|
public:
|
||||||
Vector2D vecPosition = Vector2D(0,0);
|
CMonitor();
|
||||||
Vector2D vecSize = Vector2D(0,0);
|
~CMonitor();
|
||||||
Vector2D vecPixelSize = Vector2D(0,0);
|
|
||||||
Vector2D vecTransformedSize = Vector2D(0,0);
|
|
||||||
|
|
||||||
bool primary = false;
|
Vector2D vecPosition = Vector2D(-1, -1); // means unset
|
||||||
|
Vector2D vecSize = Vector2D(0, 0);
|
||||||
|
Vector2D vecPixelSize = Vector2D(0, 0);
|
||||||
|
Vector2D vecTransformedSize = Vector2D(0, 0);
|
||||||
|
|
||||||
|
bool primary = false;
|
||||||
|
|
||||||
uint64_t ID = -1;
|
uint64_t ID = -1;
|
||||||
int activeWorkspace = -1;
|
int activeWorkspace = -1;
|
||||||
float scale = 1;
|
float scale = 1;
|
||||||
|
|
||||||
std::string szName = "";
|
std::string szName = "";
|
||||||
|
|
||||||
Vector2D vecReservedTopLeft = Vector2D(0,0);
|
Vector2D vecReservedTopLeft = Vector2D(0, 0);
|
||||||
Vector2D vecReservedBottomRight = Vector2D(0,0);
|
Vector2D vecReservedBottomRight = Vector2D(0, 0);
|
||||||
|
|
||||||
// WLR stuff
|
// WLR stuff
|
||||||
wlr_output* output = nullptr;
|
wlr_damage_ring damage;
|
||||||
float refreshRate = 60;
|
wlr_output* output = nullptr;
|
||||||
wlr_output_damage* damage = nullptr;
|
float refreshRate = 60;
|
||||||
int framesToSkip = 0;
|
int framesToSkip = 0;
|
||||||
int forceFullFrames = 0;
|
int forceFullFrames = 0;
|
||||||
bool noFrameSchedule = false;
|
bool noFrameSchedule = false;
|
||||||
bool scheduledRecalc = false;
|
bool scheduledRecalc = false;
|
||||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
|
|
||||||
bool dpmsStatus = true;
|
bool dpmsStatus = true;
|
||||||
|
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
||||||
|
bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
||||||
|
bool createdByUser = false;
|
||||||
|
|
||||||
|
bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
|
||||||
|
bool renderingActive = false;
|
||||||
|
|
||||||
|
wl_event_source* renderTimer = nullptr; // for RAT
|
||||||
|
bool RATScheduled = false;
|
||||||
|
CTimer lastPresentationTimer;
|
||||||
|
|
||||||
// mirroring
|
// mirroring
|
||||||
CMonitor* pMirrorOf = nullptr;
|
CMonitor* pMirrorOf = nullptr;
|
||||||
std::vector<CMonitor*> mirrors;
|
std::vector<CMonitor*> mirrors;
|
||||||
|
|
||||||
// for the special workspace
|
// for the special workspace. 0 means not open.
|
||||||
bool specialWorkspaceOpen = false;
|
int specialWorkspaceID = 0;
|
||||||
|
|
||||||
// Double-linked list because we need to have constant mem addresses for signals
|
std::array<std::vector<std::unique_ptr<SLayerSurface>>, 4> m_aLayerSurfaceLayers;
|
||||||
// We have to store pointers and use raw new/delete because they might be moved between them
|
|
||||||
// and I am lazy
|
|
||||||
std::array<std::vector<std::unique_ptr<SLayerSurface>>, 4> m_aLayerSurfaceLists;
|
|
||||||
|
|
||||||
DYNLISTENER(monitorFrame);
|
DYNLISTENER(monitorFrame);
|
||||||
DYNLISTENER(monitorDestroy);
|
DYNLISTENER(monitorDestroy);
|
||||||
DYNLISTENER(monitorMode);
|
DYNLISTENER(monitorStateRequest);
|
||||||
|
DYNLISTENER(monitorDamage);
|
||||||
|
DYNLISTENER(monitorNeedsFrame);
|
||||||
|
DYNLISTENER(monitorCommit);
|
||||||
|
|
||||||
// hack: a group = workspaces on a monitor.
|
// hack: a group = workspaces on a monitor.
|
||||||
// I don't really care lol :P
|
// I don't really care lol :P
|
||||||
wlr_ext_workspace_group_handle_v1* pWLRWorkspaceGroupHandle = nullptr;
|
wlr_ext_workspace_group_handle_v1* pWLRWorkspaceGroupHandle = nullptr;
|
||||||
|
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
void onConnect(bool noRule);
|
void onConnect(bool noRule);
|
||||||
void onDisconnect();
|
void onDisconnect();
|
||||||
void addDamage(pixman_region32_t* rg);
|
void addDamage(const pixman_region32_t* rg);
|
||||||
void addDamage(wlr_box* box);
|
void addDamage(const wlr_box* box);
|
||||||
void setMirror(const std::string&);
|
void setMirror(const std::string&);
|
||||||
bool isMirror();
|
bool isMirror();
|
||||||
|
float getDefaultScale();
|
||||||
|
void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false);
|
||||||
|
void changeWorkspace(const int& id, bool internal = false);
|
||||||
|
void setSpecialWorkspace(CWorkspace* const pWorkspace);
|
||||||
|
void setSpecialWorkspace(const int& id);
|
||||||
|
|
||||||
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
|
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
|
||||||
bool m_bEnabled = false;
|
bool m_bEnabled = false;
|
||||||
bool m_bRenderingInitPassed = false;
|
bool m_bRenderingInitPassed = false;
|
||||||
|
|
||||||
// For the list lookup
|
// For the list lookup
|
||||||
|
|
||||||
@@ -78,6 +96,7 @@ public:
|
|||||||
return vecPosition == rhs.vecPosition && vecSize == rhs.vecSize && szName == rhs.szName;
|
return vecPosition == rhs.vecPosition && vecSize == rhs.vecSize && szName == rhs.szName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupDefaultWS(const SMonitorRule&);
|
void setupDefaultWS(const SMonitorRule&);
|
||||||
|
int findAvailableDefaultWS();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -48,6 +48,13 @@ inline const std::vector<std::string> SPLASHES = {
|
|||||||
"Ding ding pch n daa, bam-ba-ba-re-bam baram bom bom baba-bam-bam-bommm",
|
"Ding ding pch n daa, bam-ba-ba-re-bam baram bom bom baba-bam-bam-bommm",
|
||||||
"Súbeme la radio que esta es mi canción",
|
"Súbeme la radio que esta es mi canción",
|
||||||
"I'm beggin', beggin' you",
|
"I'm beggin', beggin' you",
|
||||||
|
"Never gonna let you down (I am trying!)",
|
||||||
|
"\"I use Arch, btw\" - John Cena",
|
||||||
|
"\"Hyper\".replace(\"e\", \"\")",
|
||||||
|
"\"my win11 install runs hyprland that is true\" - raf",
|
||||||
|
"\"stop playing league loser\" - hyprBot",
|
||||||
|
"\"If it ain't broke, don't fix it\" - Lucascito_03",
|
||||||
|
"\"@vaxry how do i learn c++\" - flicko",
|
||||||
//
|
//
|
||||||
"Join the discord server!",
|
"Join the discord server!",
|
||||||
"Thanks ThatOneCalculator!",
|
"Thanks ThatOneCalculator!",
|
||||||
|
|||||||
@@ -3,8 +3,11 @@
|
|||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
|
void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
|
||||||
*lx += node->pSurface->sx;
|
if (!node->pSurface || !node->pSurface->exists())
|
||||||
*ly += node->pSurface->sy;
|
return;
|
||||||
|
|
||||||
|
*lx += node->pSurface->wlr()->current.dx;
|
||||||
|
*ly += node->pSurface->wlr()->current.dy;
|
||||||
|
|
||||||
if (node->offsetfn) {
|
if (node->offsetfn) {
|
||||||
// This is the root node
|
// This is the root node
|
||||||
@@ -23,7 +26,13 @@ void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
|
|||||||
SSurfaceTreeNode* createTree(wlr_surface* pSurface, CWindow* pWindow) {
|
SSurfaceTreeNode* createTree(wlr_surface* pSurface, CWindow* pWindow) {
|
||||||
const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.emplace_back();
|
const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.emplace_back();
|
||||||
|
|
||||||
PNODE->pSurface = pSurface;
|
if (pSurface->data)
|
||||||
|
PNODE->pSurface = (CWLSurface*)pSurface->data;
|
||||||
|
else {
|
||||||
|
PNODE->pInternalSurface = pSurface;
|
||||||
|
PNODE->pSurface = &PNODE->pInternalSurface;
|
||||||
|
}
|
||||||
|
|
||||||
PNODE->pWindowOwner = pWindow;
|
PNODE->pWindowOwner = pWindow;
|
||||||
|
|
||||||
PNODE->hyprListener_newSubsurface.initCallback(&pSurface->events.new_subsurface, &Events::listener_newSubsurfaceNode, PNODE, "SurfaceTreeNode");
|
PNODE->hyprListener_newSubsurface.initCallback(&pSurface->events.new_subsurface, &Events::listener_newSubsurfaceNode, PNODE, "SurfaceTreeNode");
|
||||||
@@ -42,11 +51,11 @@ SSurfaceTreeNode* createTree(wlr_surface* pSurface, CWindow* pWindow) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface, CWindow* pWindow) {
|
SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface, CWindow* pWindow) {
|
||||||
const auto PNODE = createTree(surface, pWindow);
|
const auto PNODE = createTree(surface, pWindow);
|
||||||
PNODE->pParent = pParent;
|
PNODE->pParent = pParent;
|
||||||
PNODE->pSubsurface = pSubsurface;
|
PNODE->pSubsurface = pSubsurface;
|
||||||
|
|
||||||
Debug::log(LOG, "Creating a subsurface Node! (pWindow: %x)", pWindow);
|
Debug::log(LOG, "Creating a subsurface Node! (pWindow: %lx)", pWindow);
|
||||||
|
|
||||||
return PNODE;
|
return PNODE;
|
||||||
}
|
}
|
||||||
@@ -54,9 +63,9 @@ SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* p
|
|||||||
SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlobalOffsetFn fn, void* data, CWindow* pWindow) {
|
SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlobalOffsetFn fn, void* data, CWindow* pWindow) {
|
||||||
const auto PNODE = createTree(pSurface, pWindow);
|
const auto PNODE = createTree(pSurface, pWindow);
|
||||||
|
|
||||||
Debug::log(LOG, "Creating a surfaceTree Root! (pWindow: %x)", pWindow);
|
Debug::log(LOG, "Creating a surfaceTree Root! (pWindow: %lx)", pWindow);
|
||||||
|
|
||||||
PNODE->offsetfn = fn;
|
PNODE->offsetfn = fn;
|
||||||
PNODE->globalOffsetData = data;
|
PNODE->globalOffsetData = data;
|
||||||
|
|
||||||
return PNODE;
|
return PNODE;
|
||||||
@@ -74,8 +83,8 @@ void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
Debug::log(ERR, "Tried to remove a SurfaceTreeNode that doesn't exist?? (Node %x)", pNode);
|
Debug::log(ERR, "Tried to remove a SurfaceTreeNode that doesn't exist?? (Node %lx)", pNode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& c : pNode->childSubsurfaces)
|
for (auto& c : pNode->childSubsurfaces)
|
||||||
@@ -88,9 +97,9 @@ void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) {
|
|||||||
pNode->hyprListener_newSubsurface.removeCallback();
|
pNode->hyprListener_newSubsurface.removeCallback();
|
||||||
|
|
||||||
// damage
|
// damage
|
||||||
if (pNode->pSurface) {
|
if (pNode->pSurface && pNode->pSurface->exists()) {
|
||||||
wlr_box extents = {};
|
wlr_box extents = {};
|
||||||
wlr_surface_get_extends(pNode->pSurface, &extents);
|
wlr_surface_get_extends(pNode->pSurface->wlr(), &extents);
|
||||||
|
|
||||||
int lx = 0, ly = 0;
|
int lx = 0, ly = 0;
|
||||||
addSurfaceGlobalOffset(pNode, &lx, &ly);
|
addSurfaceGlobalOffset(pNode, &lx, &ly);
|
||||||
@@ -132,14 +141,14 @@ void destroySubsurface(SSubsurface* pSubsurface) {
|
|||||||
void Events::listener_newSubsurfaceNode(void* owner, void* data) {
|
void Events::listener_newSubsurfaceNode(void* owner, void* data) {
|
||||||
SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner;
|
SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner;
|
||||||
|
|
||||||
const auto PSUBSURFACE = (wlr_subsurface*)data;
|
const auto PSUBSURFACE = (wlr_subsurface*)data;
|
||||||
|
|
||||||
const auto PNEWSUBSURFACE = &pNode->childSubsurfaces.emplace_back();
|
const auto PNEWSUBSURFACE = &pNode->childSubsurfaces.emplace_back();
|
||||||
|
|
||||||
Debug::log(LOG, "Added a new subsurface %x", PSUBSURFACE);
|
Debug::log(LOG, "Added a new subsurface %lx", PSUBSURFACE);
|
||||||
|
|
||||||
PNEWSUBSURFACE->pSubsurface = PSUBSURFACE;
|
PNEWSUBSURFACE->pSubsurface = PSUBSURFACE;
|
||||||
PNEWSUBSURFACE->pParent = pNode;
|
PNEWSUBSURFACE->pParent = pNode;
|
||||||
|
|
||||||
PNEWSUBSURFACE->hyprListener_map.initCallback(&PSUBSURFACE->events.map, &Events::listener_mapSubsurface, PNEWSUBSURFACE, "Subsurface");
|
PNEWSUBSURFACE->hyprListener_map.initCallback(&PSUBSURFACE->events.map, &Events::listener_mapSubsurface, PNEWSUBSURFACE, "Subsurface");
|
||||||
PNEWSUBSURFACE->hyprListener_unmap.initCallback(&PSUBSURFACE->events.unmap, &Events::listener_unmapSubsurface, PNEWSUBSURFACE, "Subsurface");
|
PNEWSUBSURFACE->hyprListener_unmap.initCallback(&PSUBSURFACE->events.unmap, &Events::listener_unmapSubsurface, PNEWSUBSURFACE, "Subsurface");
|
||||||
@@ -165,7 +174,7 @@ void Events::listener_mapSubsurface(void* owner, void* data) {
|
|||||||
if (subsurface->pChild)
|
if (subsurface->pChild)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug::log(LOG, "Subsurface %x mapped", subsurface->pSubsurface);
|
Debug::log(LOG, "Subsurface %lx mapped", subsurface->pSubsurface);
|
||||||
|
|
||||||
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner);
|
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner);
|
||||||
}
|
}
|
||||||
@@ -173,25 +182,36 @@ void Events::listener_mapSubsurface(void* owner, void* data) {
|
|||||||
void Events::listener_unmapSubsurface(void* owner, void* data) {
|
void Events::listener_unmapSubsurface(void* owner, void* data) {
|
||||||
SSubsurface* subsurface = (SSubsurface*)owner;
|
SSubsurface* subsurface = (SSubsurface*)owner;
|
||||||
|
|
||||||
Debug::log(LOG, "Subsurface %x unmapped", subsurface);
|
Debug::log(LOG, "Subsurface %lx unmapped", subsurface);
|
||||||
|
|
||||||
|
if (subsurface->pSubsurface->surface == g_pCompositor->m_pLastFocus)
|
||||||
|
g_pInputManager->releaseAllMouseButtons();
|
||||||
|
|
||||||
if (subsurface->pChild) {
|
if (subsurface->pChild) {
|
||||||
const auto PNODE = subsurface->pChild;
|
const auto PNODE = subsurface->pChild;
|
||||||
|
|
||||||
int lx = 0, ly = 0;
|
const auto IT =
|
||||||
addSurfaceGlobalOffset(PNODE, &lx, &ly);
|
std::find_if(SubsurfaceTree::surfaceTreeNodes.begin(), SubsurfaceTree::surfaceTreeNodes.end(), [&](const SSurfaceTreeNode& other) { return &other == PNODE; });
|
||||||
|
|
||||||
wlr_box extents = {lx, ly, 0, 0};
|
if (IT != SubsurfaceTree::surfaceTreeNodes.end()) {
|
||||||
if (PNODE->pSurface) {
|
if (PNODE->pSurface && PNODE->pSurface->exists()) {
|
||||||
extents.width = PNODE->pSurface->current.width;
|
int lx = 0, ly = 0;
|
||||||
extents.height = PNODE->pSurface->current.height;
|
addSurfaceGlobalOffset(PNODE, &lx, &ly);
|
||||||
|
|
||||||
g_pHyprRenderer->damageBox(&extents);
|
wlr_box extents = {lx, ly, 0, 0};
|
||||||
|
|
||||||
|
extents.width = PNODE->pSurface->wlr()->current.width;
|
||||||
|
extents.height = PNODE->pSurface->wlr()->current.height;
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageBox(&extents);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
||||||
|
// subsurface->pChild = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
|
||||||
//subsurface->pChild = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_pInputManager->simulateMouseMovement(); // to focus and return back to an appropriate surface
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_commitSubsurface(void* owner, void* data) {
|
void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||||
@@ -199,9 +219,9 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
|||||||
|
|
||||||
// no damaging if it's not visible
|
// no damaging if it's not visible
|
||||||
if (!g_pHyprRenderer->shouldRenderWindow(pNode->pWindowOwner)) {
|
if (!g_pHyprRenderer->shouldRenderWindow(pNode->pWindowOwner)) {
|
||||||
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
||||||
if (*PLOGDAMAGE)
|
if (*PLOGDAMAGE)
|
||||||
Debug::log(LOG, "Refusing to commit damage from %x because it's invisible.", pNode->pWindowOwner);
|
Debug::log(LOG, "Refusing to commit damage from %lx because it's invisible.", pNode->pWindowOwner);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,15 +232,17 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
|||||||
// I do not think this is correct, but it solves a lot of issues with some apps (e.g. firefox)
|
// I do not think this is correct, but it solves a lot of issues with some apps (e.g. firefox)
|
||||||
// What this does is that basically, if the pNode is a child of some other node, on commit,
|
// What this does is that basically, if the pNode is a child of some other node, on commit,
|
||||||
// it will also damage (check & damage if needed) all its siblings.
|
// it will also damage (check & damage if needed) all its siblings.
|
||||||
if (pNode->pParent) for (auto& cs : pNode->pParent->childSubsurfaces) {
|
if (pNode->pParent)
|
||||||
const auto NODECOORDS = pNode->pSubsurface ? Vector2D(pNode->pSubsurface->pSubsurface->current.x, pNode->pSubsurface->pSubsurface->current.y) : Vector2D();
|
for (auto& cs : pNode->pParent->childSubsurfaces) {
|
||||||
|
const auto NODECOORDS = pNode->pSubsurface ? Vector2D(pNode->pSubsurface->pSubsurface->current.x, pNode->pSubsurface->pSubsurface->current.y) : Vector2D();
|
||||||
|
|
||||||
if (&cs != pNode->pSubsurface && cs.pSubsurface) {
|
if (&cs != pNode->pSubsurface && cs.pSubsurface) {
|
||||||
g_pHyprRenderer->damageSurface(cs.pSubsurface->surface, lx - NODECOORDS.x + cs.pSubsurface->current.x, ly - NODECOORDS.y + cs.pSubsurface->current.y);
|
g_pHyprRenderer->damageSurface(cs.pSubsurface->surface, lx - NODECOORDS.x + cs.pSubsurface->current.x, ly - NODECOORDS.y + cs.pSubsurface->current.y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
g_pHyprRenderer->damageSurface(pNode->pSurface, lx, ly);
|
if (pNode->pSurface && pNode->pSurface->exists())
|
||||||
|
g_pHyprRenderer->damageSurface(pNode->pSurface->wlr(), lx, ly);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_destroySubsurface(void* owner, void* data) {
|
void Events::listener_destroySubsurface(void* owner, void* data) {
|
||||||
@@ -230,7 +252,7 @@ void Events::listener_destroySubsurface(void* owner, void* data) {
|
|||||||
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "Subsurface %x destroyed", subsurface);
|
Debug::log(LOG, "Subsurface %lx destroyed", subsurface);
|
||||||
|
|
||||||
subsurface->hyprListener_destroy.removeCallback();
|
subsurface->hyprListener_destroy.removeCallback();
|
||||||
subsurface->hyprListener_map.removeCallback();
|
subsurface->hyprListener_map.removeCallback();
|
||||||
@@ -242,7 +264,7 @@ void Events::listener_destroySubsurface(void* owner, void* data) {
|
|||||||
void Events::listener_destroySubsurfaceNode(void* owner, void* data) {
|
void Events::listener_destroySubsurfaceNode(void* owner, void* data) {
|
||||||
SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner;
|
SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner;
|
||||||
|
|
||||||
Debug::log(LOG, "Subsurface Node %x destroyed", pNode);
|
Debug::log(LOG, "Subsurface Node %lx destroyed", pNode);
|
||||||
|
|
||||||
for (auto& c : pNode->childSubsurfaces)
|
for (auto& c : pNode->childSubsurfaces)
|
||||||
destroySubsurface(&c);
|
destroySubsurface(&c);
|
||||||
|
|||||||
@@ -2,53 +2,55 @@
|
|||||||
|
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include "WLSurface.hpp"
|
||||||
|
|
||||||
struct SSubsurface;
|
struct SSubsurface;
|
||||||
class CWindow;
|
class CWindow;
|
||||||
|
|
||||||
typedef void (*applyGlobalOffsetFn)(void *, int *, int *);
|
typedef void (*applyGlobalOffsetFn)(void*, int*, int*);
|
||||||
|
|
||||||
struct SSurfaceTreeNode {
|
struct SSurfaceTreeNode {
|
||||||
wlr_surface* pSurface = nullptr;
|
CWLSurface* pSurface = nullptr; // actual surface
|
||||||
|
CWLSurface pInternalSurface; // not present for head nodes to not dupe wlr_surface ownership
|
||||||
|
|
||||||
DYNLISTENER(newSubsurface);
|
DYNLISTENER(newSubsurface);
|
||||||
DYNLISTENER(commit);
|
DYNLISTENER(commit);
|
||||||
DYNLISTENER(destroy);
|
DYNLISTENER(destroy);
|
||||||
|
|
||||||
SSurfaceTreeNode* pParent = nullptr;
|
SSurfaceTreeNode* pParent = nullptr;
|
||||||
SSubsurface* pSubsurface = nullptr;
|
SSubsurface* pSubsurface = nullptr;
|
||||||
|
|
||||||
std::list<SSubsurface> childSubsurfaces;
|
std::list<SSubsurface> childSubsurfaces;
|
||||||
|
|
||||||
applyGlobalOffsetFn offsetfn;
|
applyGlobalOffsetFn offsetfn;
|
||||||
void *globalOffsetData;
|
void* globalOffsetData;
|
||||||
CWindow* pWindowOwner = nullptr;
|
CWindow* pWindowOwner = nullptr;
|
||||||
|
|
||||||
bool operator==(const SSurfaceTreeNode& rhs) {
|
bool operator==(const SSurfaceTreeNode& rhs) const {
|
||||||
return pSurface == rhs.pSurface;
|
return pSurface == rhs.pSurface;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SSubsurface {
|
struct SSubsurface {
|
||||||
wlr_subsurface* pSubsurface = nullptr;
|
wlr_subsurface* pSubsurface = nullptr;
|
||||||
|
|
||||||
SSurfaceTreeNode* pParent = nullptr;
|
SSurfaceTreeNode* pParent = nullptr;
|
||||||
SSurfaceTreeNode* pChild = nullptr;
|
SSurfaceTreeNode* pChild = nullptr;
|
||||||
|
|
||||||
DYNLISTENER(map);
|
DYNLISTENER(map);
|
||||||
DYNLISTENER(unmap);
|
DYNLISTENER(unmap);
|
||||||
DYNLISTENER(destroy);
|
DYNLISTENER(destroy);
|
||||||
|
|
||||||
CWindow* pWindowOwner = nullptr;
|
CWindow* pWindowOwner = nullptr;
|
||||||
|
|
||||||
bool operator==(const SSubsurface& rhs) {
|
bool operator==(const SSubsurface& rhs) const {
|
||||||
return pSubsurface == rhs.pSubsurface;
|
return pSubsurface == rhs.pSubsurface;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace SubsurfaceTree {
|
namespace SubsurfaceTree {
|
||||||
SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*, CWindow* pWindow = nullptr);
|
SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*, CWindow* pWindow = nullptr);
|
||||||
void destroySurfaceTree(SSurfaceTreeNode*);
|
void destroySurfaceTree(SSurfaceTreeNode*);
|
||||||
|
|
||||||
inline std::list<SSurfaceTreeNode> surfaceTreeNodes;
|
inline std::list<SSurfaceTreeNode> surfaceTreeNodes;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
|
|
||||||
class CTimer {
|
class CTimer {
|
||||||
public:
|
public:
|
||||||
void reset();
|
void reset();
|
||||||
float getSeconds();
|
float getSeconds();
|
||||||
int getMillis();
|
int getMillis();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::chrono::system_clock::time_point m_tpLastReset;
|
std::chrono::system_clock::time_point m_tpLastReset;
|
||||||
|
|
||||||
std::chrono::system_clock::duration getDuration();
|
std::chrono::system_clock::duration getDuration();
|
||||||
};
|
};
|
||||||
@@ -1,12 +1,17 @@
|
|||||||
#include "Vector2D.hpp"
|
#include "Vector2D.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
Vector2D::Vector2D(double xx, double yy) {
|
Vector2D::Vector2D(double xx, double yy) {
|
||||||
x = xx;
|
x = xx;
|
||||||
y = yy;
|
y = yy;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2D::Vector2D() { x = 0; y = 0; }
|
Vector2D::Vector2D() {
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
Vector2D::~Vector2D() {}
|
Vector2D::~Vector2D() {}
|
||||||
|
|
||||||
double Vector2D::normalize() {
|
double Vector2D::normalize() {
|
||||||
@@ -24,8 +29,11 @@ Vector2D Vector2D::floor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) {
|
Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) {
|
||||||
return Vector2D(
|
return Vector2D(std::clamp(this->x, min.x, max.x < min.x ? INFINITY : max.x), std::clamp(this->y, min.y, max.y < min.y ? INFINITY : max.y));
|
||||||
std::clamp(this->x, min.x, max.x == 0 ? INFINITY : max.x),
|
}
|
||||||
std::clamp(this->y, min.y, max.y == 0 ? INFINITY : max.y)
|
|
||||||
);
|
double Vector2D::distance(const Vector2D& other) {
|
||||||
}
|
double dx = x - other.x;
|
||||||
|
double dy = y - other.y;
|
||||||
|
return std::sqrt(dx * dx + dy * dy);
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
class Vector2D {
|
class Vector2D {
|
||||||
public:
|
public:
|
||||||
Vector2D(double, double);
|
Vector2D(double, double);
|
||||||
Vector2D();
|
Vector2D();
|
||||||
~Vector2D();
|
~Vector2D();
|
||||||
@@ -12,18 +12,18 @@ class Vector2D {
|
|||||||
double y = 0;
|
double y = 0;
|
||||||
|
|
||||||
// returns the scale
|
// returns the scale
|
||||||
double normalize();
|
double normalize();
|
||||||
|
|
||||||
Vector2D operator+(const Vector2D a) const {
|
Vector2D operator+(const Vector2D& a) const {
|
||||||
return Vector2D(this->x + a.x, this->y + a.y);
|
return Vector2D(this->x + a.x, this->y + a.y);
|
||||||
}
|
}
|
||||||
Vector2D operator-(const Vector2D a) const {
|
Vector2D operator-(const Vector2D& a) const {
|
||||||
return Vector2D(this->x - a.x, this->y - a.y);
|
return Vector2D(this->x - a.x, this->y - a.y);
|
||||||
}
|
}
|
||||||
Vector2D operator*(const float a) const {
|
Vector2D operator*(const float& a) const {
|
||||||
return Vector2D(this->x * a, this->y * a);
|
return Vector2D(this->x * a, this->y * a);
|
||||||
}
|
}
|
||||||
Vector2D operator/(const float a) const {
|
Vector2D operator/(const float& a) const {
|
||||||
return Vector2D(this->x / a, this->y / a);
|
return Vector2D(this->x / a, this->y / a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +39,13 @@ class Vector2D {
|
|||||||
return Vector2D(this->x * a.x, this->y * a.y);
|
return Vector2D(this->x * a.x, this->y * a.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2D operator/(const Vector2D& a) const {
|
||||||
|
return Vector2D(this->x / a.x, this->y / a.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
double distance(const Vector2D& other);
|
||||||
|
|
||||||
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D());
|
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D());
|
||||||
|
|
||||||
Vector2D floor();
|
Vector2D floor();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,4 +4,20 @@
|
|||||||
SLayerSurface::SLayerSurface() {
|
SLayerSurface::SLayerSurface() {
|
||||||
alpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), nullptr, AVARDAMAGE_ENTIRE);
|
alpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), nullptr, AVARDAMAGE_ENTIRE);
|
||||||
alpha.m_pLayer = this;
|
alpha.m_pLayer = this;
|
||||||
|
alpha.registerVar();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SLayerSurface::applyRules() {
|
||||||
|
noAnimations = false;
|
||||||
|
forceBlur = false;
|
||||||
|
ignoreZero = false;
|
||||||
|
|
||||||
|
for (auto& rule : g_pConfigManager->getMatchingRules(this)) {
|
||||||
|
if (rule.rule == "noanim")
|
||||||
|
noAnimations = true;
|
||||||
|
else if (rule.rule == "blur")
|
||||||
|
forceBlur = true;
|
||||||
|
else if (rule.rule == "ignorezero")
|
||||||
|
ignoreZero = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -6,12 +6,23 @@
|
|||||||
#include "../Window.hpp"
|
#include "../Window.hpp"
|
||||||
#include "SubsurfaceTree.hpp"
|
#include "SubsurfaceTree.hpp"
|
||||||
#include "AnimatedVariable.hpp"
|
#include "AnimatedVariable.hpp"
|
||||||
|
#include "WLSurface.hpp"
|
||||||
|
|
||||||
|
struct SLayerRule {
|
||||||
|
std::string targetNamespace = "";
|
||||||
|
std::string rule = "";
|
||||||
|
};
|
||||||
|
|
||||||
struct SLayerSurface {
|
struct SLayerSurface {
|
||||||
SLayerSurface();
|
SLayerSurface();
|
||||||
|
|
||||||
wlr_layer_surface_v1* layerSurface;
|
void applyRules();
|
||||||
wl_list link;
|
|
||||||
|
wlr_layer_surface_v1* layerSurface;
|
||||||
|
wl_list link;
|
||||||
|
|
||||||
|
CWLSurface surface;
|
||||||
|
std::list<CWLSurface> popupSurfaces;
|
||||||
|
|
||||||
DYNLISTENER(destroyLayerSurface);
|
DYNLISTENER(destroyLayerSurface);
|
||||||
DYNLISTENER(mapLayerSurface);
|
DYNLISTENER(mapLayerSurface);
|
||||||
@@ -19,45 +30,48 @@ struct SLayerSurface {
|
|||||||
DYNLISTENER(commitLayerSurface);
|
DYNLISTENER(commitLayerSurface);
|
||||||
DYNLISTENER(newPopup);
|
DYNLISTENER(newPopup);
|
||||||
|
|
||||||
wlr_box geometry = {0,0,0,0};
|
wlr_box geometry = {0, 0, 0, 0};
|
||||||
Vector2D position;
|
Vector2D position;
|
||||||
zwlr_layer_shell_v1_layer layer;
|
zwlr_layer_shell_v1_layer layer;
|
||||||
|
|
||||||
bool mapped = false;
|
bool mapped = false;
|
||||||
|
|
||||||
int monitorID = -1;
|
int monitorID = -1;
|
||||||
|
|
||||||
std::string szNamespace = "";
|
std::string szNamespace = "";
|
||||||
|
|
||||||
CAnimatedVariable alpha;
|
CAnimatedVariable alpha;
|
||||||
bool fadingOut = false;
|
bool fadingOut = false;
|
||||||
bool readyToDelete = false;
|
bool readyToDelete = false;
|
||||||
bool noProcess = false;
|
bool noProcess = false;
|
||||||
|
bool noAnimations = false;
|
||||||
|
|
||||||
bool forceBlur = false;
|
bool forceBlur = false;
|
||||||
|
bool ignoreZero = false;
|
||||||
|
|
||||||
// For the list lookup
|
// For the list lookup
|
||||||
bool operator==(const SLayerSurface& rhs) {
|
bool operator==(const SLayerSurface& rhs) const {
|
||||||
return layerSurface == rhs.layerSurface && monitorID == rhs.monitorID;
|
return layerSurface == rhs.layerSurface && monitorID == rhs.monitorID;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CMonitor;
|
||||||
|
|
||||||
struct SRenderData {
|
struct SRenderData {
|
||||||
wlr_output* output;
|
CMonitor* pMonitor;
|
||||||
timespec* when;
|
timespec* when;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
// for iters
|
// for iters
|
||||||
void* data = nullptr;
|
void* data = nullptr;
|
||||||
wlr_surface* surface = nullptr;
|
wlr_surface* surface = nullptr;
|
||||||
int w, h;
|
int w, h;
|
||||||
void* pMonitor = nullptr;
|
|
||||||
|
|
||||||
// for rounding
|
// for rounding
|
||||||
bool dontRound = true;
|
bool dontRound = true;
|
||||||
|
|
||||||
// for fade
|
// for fade
|
||||||
float fadeAlpha = 255.f;
|
float fadeAlpha = 1.f;
|
||||||
|
|
||||||
// for alpha settings
|
// for alpha settings
|
||||||
float alpha = 1.f;
|
float alpha = 1.f;
|
||||||
@@ -69,7 +83,8 @@ struct SRenderData {
|
|||||||
int rounding = -1; // -1 means not set
|
int rounding = -1; // -1 means not set
|
||||||
|
|
||||||
// for blurring
|
// for blurring
|
||||||
bool blur = false;
|
bool blur = false;
|
||||||
|
bool blockBlurOptimization = false;
|
||||||
|
|
||||||
// only for windows, not popups
|
// only for windows, not popups
|
||||||
bool squishOversized = true;
|
bool squishOversized = true;
|
||||||
@@ -79,17 +94,17 @@ struct SRenderData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct SExtensionFindingData {
|
struct SExtensionFindingData {
|
||||||
Vector2D origin;
|
Vector2D origin;
|
||||||
Vector2D vec;
|
Vector2D vec;
|
||||||
wlr_surface** found;
|
wlr_surface** found;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SStringRuleNames {
|
struct SStringRuleNames {
|
||||||
std::string layout = "";
|
std::string layout = "";
|
||||||
std::string model = "";
|
std::string model = "";
|
||||||
std::string variant = "";
|
std::string variant = "";
|
||||||
std::string options = "";
|
std::string options = "";
|
||||||
std::string rules = "";
|
std::string rules = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SKeyboard {
|
struct SKeyboard {
|
||||||
@@ -100,53 +115,59 @@ struct SKeyboard {
|
|||||||
DYNLISTENER(keyboardKeymap);
|
DYNLISTENER(keyboardKeymap);
|
||||||
DYNLISTENER(keyboardDestroy);
|
DYNLISTENER(keyboardDestroy);
|
||||||
|
|
||||||
bool isVirtual = false;
|
bool isVirtual = false;
|
||||||
bool active = false;
|
bool active = false;
|
||||||
|
bool enabled = true;
|
||||||
|
|
||||||
xkb_layout_index_t activeLayout = 0;
|
xkb_layout_index_t activeLayout = 0;
|
||||||
|
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
std::string xkbFilePath = "";
|
std::string xkbFilePath = "";
|
||||||
|
|
||||||
SStringRuleNames currentRules;
|
SStringRuleNames currentRules;
|
||||||
int repeatRate = 0;
|
int repeatRate = 0;
|
||||||
int repeatDelay = 0;
|
int repeatDelay = 0;
|
||||||
int numlockOn = -1;
|
int numlockOn = -1;
|
||||||
|
|
||||||
// For the list lookup
|
// For the list lookup
|
||||||
bool operator==(const SKeyboard& rhs) {
|
bool operator==(const SKeyboard& rhs) const {
|
||||||
return keyboard == rhs.keyboard;
|
return keyboard == rhs.keyboard;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SMouse {
|
struct SMouse {
|
||||||
wlr_input_device* mouse = nullptr;
|
wlr_input_device* mouse = nullptr;
|
||||||
|
|
||||||
wlr_pointer_constraint_v1* currentConstraint = nullptr;
|
wlr_pointer_constraint_v1* currentConstraint = nullptr;
|
||||||
bool constraintActive = false;
|
bool constraintActive = false;
|
||||||
|
|
||||||
pixman_region32_t confinedTo;
|
pixman_region32_t confinedTo;
|
||||||
|
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
|
|
||||||
bool virt = false;
|
bool virt = false;
|
||||||
|
|
||||||
|
bool connected = false; // means connected to the cursor
|
||||||
|
|
||||||
DYNLISTENER(commitConstraint);
|
DYNLISTENER(commitConstraint);
|
||||||
DYNLISTENER(destroyMouse);
|
DYNLISTENER(destroyMouse);
|
||||||
|
|
||||||
bool operator==(const SMouse& b) {
|
bool operator==(const SMouse& b) const {
|
||||||
return mouse == b.mouse;
|
return mouse == b.mouse;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SConstraint {
|
struct SConstraint {
|
||||||
SMouse* pMouse = nullptr;
|
SMouse* pMouse = nullptr;
|
||||||
wlr_pointer_constraint_v1* constraint = nullptr;
|
wlr_pointer_constraint_v1* constraint = nullptr;
|
||||||
|
|
||||||
|
bool hintSet = false;
|
||||||
|
Vector2D positionHint; // the position hint, but will be set to the current cursor pos if not set.
|
||||||
|
|
||||||
DYNLISTENER(setConstraintRegion);
|
DYNLISTENER(setConstraintRegion);
|
||||||
DYNLISTENER(destroyConstraint);
|
DYNLISTENER(destroyConstraint);
|
||||||
|
|
||||||
bool operator==(const SConstraint& b) {
|
bool operator==(const SConstraint& b) const {
|
||||||
return constraint == b.constraint;
|
return constraint == b.constraint;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -154,10 +175,11 @@ struct SConstraint {
|
|||||||
class CMonitor;
|
class CMonitor;
|
||||||
|
|
||||||
struct SXDGPopup {
|
struct SXDGPopup {
|
||||||
CWindow* parentWindow = nullptr;
|
CWindow* parentWindow = nullptr;
|
||||||
SXDGPopup* parentPopup = nullptr;
|
SLayerSurface* parentLS = nullptr;
|
||||||
wlr_xdg_popup* popup = nullptr;
|
SXDGPopup* parentPopup = nullptr;
|
||||||
CMonitor* monitor = nullptr;
|
wlr_xdg_popup* popup = nullptr;
|
||||||
|
CMonitor* monitor = nullptr;
|
||||||
|
|
||||||
DYNLISTENER(newPopupFromPopupXDG);
|
DYNLISTENER(newPopupFromPopupXDG);
|
||||||
DYNLISTENER(destroyPopupXDG);
|
DYNLISTENER(destroyPopupXDG);
|
||||||
@@ -165,36 +187,36 @@ struct SXDGPopup {
|
|||||||
DYNLISTENER(unmapPopupXDG);
|
DYNLISTENER(unmapPopupXDG);
|
||||||
DYNLISTENER(commitPopupXDG);
|
DYNLISTENER(commitPopupXDG);
|
||||||
|
|
||||||
double lx;
|
double lx;
|
||||||
double ly;
|
double ly;
|
||||||
|
|
||||||
SSurfaceTreeNode* pSurfaceTree = nullptr;
|
SSurfaceTreeNode* pSurfaceTree = nullptr;
|
||||||
|
|
||||||
// For the list lookup
|
// For the list lookup
|
||||||
bool operator==(const SXDGPopup& rhs) {
|
bool operator==(const SXDGPopup& rhs) const {
|
||||||
return popup == rhs.popup;
|
return popup == rhs.popup;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SSeat {
|
struct SSeat {
|
||||||
wlr_seat* seat = nullptr;
|
wlr_seat* seat = nullptr;
|
||||||
wl_client* exclusiveClient = nullptr;
|
wl_client* exclusiveClient = nullptr;
|
||||||
|
|
||||||
SMouse* mouse = nullptr;
|
SMouse* mouse = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SDrag {
|
struct SDrag {
|
||||||
wlr_drag* drag = nullptr;
|
wlr_drag* drag = nullptr;
|
||||||
|
|
||||||
DYNLISTENER(destroy);
|
DYNLISTENER(destroy);
|
||||||
|
|
||||||
// Icon
|
// Icon
|
||||||
|
|
||||||
bool iconMapped = false;
|
bool iconMapped = false;
|
||||||
|
|
||||||
wlr_drag_icon* dragIcon = nullptr;
|
wlr_drag_icon* dragIcon = nullptr;
|
||||||
|
|
||||||
Vector2D pos;
|
Vector2D pos;
|
||||||
|
|
||||||
DYNLISTENER(destroyIcon);
|
DYNLISTENER(destroyIcon);
|
||||||
DYNLISTENER(mapIcon);
|
DYNLISTENER(mapIcon);
|
||||||
@@ -209,45 +231,46 @@ struct STablet {
|
|||||||
DYNLISTENER(Proximity);
|
DYNLISTENER(Proximity);
|
||||||
DYNLISTENER(Destroy);
|
DYNLISTENER(Destroy);
|
||||||
|
|
||||||
wlr_tablet* wlrTablet = nullptr;
|
wlr_tablet* wlrTablet = nullptr;
|
||||||
wlr_tablet_v2_tablet* wlrTabletV2 = nullptr;
|
wlr_tablet_v2_tablet* wlrTabletV2 = nullptr;
|
||||||
wlr_input_device* wlrDevice = nullptr;
|
wlr_input_device* wlrDevice = nullptr;
|
||||||
|
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
|
|
||||||
bool operator==(const STablet& b) {
|
bool operator==(const STablet& b) const {
|
||||||
return wlrDevice == b.wlrDevice;
|
return wlrDevice == b.wlrDevice;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct STabletTool {
|
struct STabletTool {
|
||||||
wlr_tablet_tool* wlrTabletTool = nullptr;
|
wlr_tablet_tool* wlrTabletTool = nullptr;
|
||||||
wlr_tablet_v2_tablet_tool* wlrTabletToolV2 = nullptr;
|
wlr_tablet_v2_tablet_tool* wlrTabletToolV2 = nullptr;
|
||||||
|
|
||||||
wlr_tablet_v2_tablet* wlrTabletOwnerV2 = nullptr;
|
wlr_tablet_v2_tablet* wlrTabletOwnerV2 = nullptr;
|
||||||
|
|
||||||
wlr_surface* pSurface = nullptr;
|
wlr_surface* pSurface = nullptr;
|
||||||
|
|
||||||
double tiltX = 0;
|
double tiltX = 0;
|
||||||
double tiltY = 0;
|
double tiltY = 0;
|
||||||
|
|
||||||
bool active = true;
|
bool active = true;
|
||||||
|
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
|
|
||||||
DYNLISTENER(TabletToolDestroy);
|
DYNLISTENER(TabletToolDestroy);
|
||||||
DYNLISTENER(TabletToolSetCursor);
|
DYNLISTENER(TabletToolSetCursor);
|
||||||
|
|
||||||
bool operator==(const STabletTool& b) {
|
bool operator==(const STabletTool& b) const {
|
||||||
return wlrTabletTool == b.wlrTabletTool;
|
return wlrTabletTool == b.wlrTabletTool;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct STabletPad {
|
struct STabletPad {
|
||||||
wlr_tablet_v2_tablet_pad* wlrTabletPadV2 = nullptr;
|
wlr_tablet_v2_tablet_pad* wlrTabletPadV2 = nullptr;
|
||||||
STablet* pTabletParent = nullptr;
|
STablet* pTabletParent = nullptr;
|
||||||
|
wlr_input_device* pWlrDevice = nullptr;
|
||||||
|
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
|
|
||||||
DYNLISTENER(Attach);
|
DYNLISTENER(Attach);
|
||||||
DYNLISTENER(Button);
|
DYNLISTENER(Button);
|
||||||
@@ -255,37 +278,40 @@ struct STabletPad {
|
|||||||
DYNLISTENER(Ring);
|
DYNLISTENER(Ring);
|
||||||
DYNLISTENER(Destroy);
|
DYNLISTENER(Destroy);
|
||||||
|
|
||||||
bool operator==(const STabletPad& b) {
|
bool operator==(const STabletPad& b) const {
|
||||||
return wlrTabletPadV2 == b.wlrTabletPadV2;
|
return wlrTabletPadV2 == b.wlrTabletPadV2;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SIdleInhibitor {
|
struct SIdleInhibitor {
|
||||||
wlr_idle_inhibitor_v1* pWlrInhibitor = nullptr;
|
wlr_idle_inhibitor_v1* pWlrInhibitor = nullptr;
|
||||||
CWindow* pWindow = nullptr;
|
CWindow* pWindow = nullptr;
|
||||||
|
|
||||||
DYNLISTENER(Destroy);
|
DYNLISTENER(Destroy);
|
||||||
|
|
||||||
bool operator==(const SIdleInhibitor& b) {
|
bool operator==(const SIdleInhibitor& b) const {
|
||||||
return pWlrInhibitor == b.pWlrInhibitor;
|
return pWlrInhibitor == b.pWlrInhibitor;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SSwipeGesture {
|
struct SSwipeGesture {
|
||||||
CWorkspace* pWorkspaceBegin = nullptr;
|
CWorkspace* pWorkspaceBegin = nullptr;
|
||||||
|
|
||||||
double delta = 0;
|
double delta = 0;
|
||||||
|
|
||||||
float avgSpeed = 0;
|
float avgSpeed = 0;
|
||||||
int speedPoints = 0;
|
int speedPoints = 0;
|
||||||
|
|
||||||
CMonitor* pMonitor = nullptr;
|
CMonitor* pMonitor = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct STextInputV1;
|
||||||
|
|
||||||
struct STextInput {
|
struct STextInput {
|
||||||
wlr_text_input_v3* pWlrInput = nullptr;
|
wlr_text_input_v3* pWlrInput = nullptr;
|
||||||
|
STextInputV1* pV1Input = nullptr;
|
||||||
|
|
||||||
wlr_surface* pPendingSurface = nullptr;
|
wlr_surface* pPendingSurface = nullptr;
|
||||||
|
|
||||||
DYNLISTENER(textInputEnable);
|
DYNLISTENER(textInputEnable);
|
||||||
DYNLISTENER(textInputDisable);
|
DYNLISTENER(textInputDisable);
|
||||||
@@ -298,7 +324,7 @@ struct STextInput {
|
|||||||
struct SIMEKbGrab {
|
struct SIMEKbGrab {
|
||||||
wlr_input_method_keyboard_grab_v2* pWlrKbGrab = nullptr;
|
wlr_input_method_keyboard_grab_v2* pWlrKbGrab = nullptr;
|
||||||
|
|
||||||
wlr_keyboard* pKeyboard = nullptr;
|
wlr_keyboard* pKeyboard = nullptr;
|
||||||
|
|
||||||
DYNLISTENER(grabDestroy);
|
DYNLISTENER(grabDestroy);
|
||||||
};
|
};
|
||||||
@@ -306,10 +332,10 @@ struct SIMEKbGrab {
|
|||||||
struct SIMEPopup {
|
struct SIMEPopup {
|
||||||
wlr_input_popup_surface_v2* pSurface = nullptr;
|
wlr_input_popup_surface_v2* pSurface = nullptr;
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
int realX, realY;
|
int realX, realY;
|
||||||
bool visible;
|
bool visible;
|
||||||
Vector2D lastSize;
|
Vector2D lastSize;
|
||||||
|
|
||||||
DYNLISTENER(mapPopup);
|
DYNLISTENER(mapPopup);
|
||||||
DYNLISTENER(unmapPopup);
|
DYNLISTENER(unmapPopup);
|
||||||
@@ -318,7 +344,7 @@ struct SIMEPopup {
|
|||||||
|
|
||||||
DYNLISTENER(focusedSurfaceUnmap);
|
DYNLISTENER(focusedSurfaceUnmap);
|
||||||
|
|
||||||
bool operator==(const SIMEPopup& other) {
|
bool operator==(const SIMEPopup& other) const {
|
||||||
return pSurface == other.pSurface;
|
return pSurface == other.pSurface;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -326,9 +352,13 @@ struct SIMEPopup {
|
|||||||
struct STouchDevice {
|
struct STouchDevice {
|
||||||
wlr_input_device* pWlrDevice = nullptr;
|
wlr_input_device* pWlrDevice = nullptr;
|
||||||
|
|
||||||
|
std::string name = "";
|
||||||
|
|
||||||
|
std::string boundOutput = "";
|
||||||
|
|
||||||
DYNLISTENER(destroy);
|
DYNLISTENER(destroy);
|
||||||
|
|
||||||
bool operator==(const STouchDevice& other) {
|
bool operator==(const STouchDevice& other) const {
|
||||||
return pWlrDevice == other.pWlrDevice;
|
return pWlrDevice == other.pWlrDevice;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -336,10 +366,12 @@ struct STouchDevice {
|
|||||||
struct SSwitchDevice {
|
struct SSwitchDevice {
|
||||||
wlr_input_device* pWlrDevice = nullptr;
|
wlr_input_device* pWlrDevice = nullptr;
|
||||||
|
|
||||||
|
int status = -1; // uninitialized
|
||||||
|
|
||||||
DYNLISTENER(destroy);
|
DYNLISTENER(destroy);
|
||||||
DYNLISTENER(toggle);
|
DYNLISTENER(toggle);
|
||||||
|
|
||||||
bool operator==(const SSwitchDevice& other) {
|
bool operator==(const SSwitchDevice& other) const {
|
||||||
return pWlrDevice == other.pWlrDevice;
|
return pWlrDevice == other.pWlrDevice;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, v
|
|||||||
}
|
}
|
||||||
|
|
||||||
CHyprWLListener::CHyprWLListener() {
|
CHyprWLListener::CHyprWLListener() {
|
||||||
m_swWrapper.m_pSelf = this;
|
m_swWrapper.m_pSelf = this;
|
||||||
m_swWrapper.m_sListener.notify = &handleWrapped;
|
m_swWrapper.m_sListener.notify = &handleWrapped;
|
||||||
wl_list_init(&m_swWrapper.m_sListener.link);
|
wl_list_init(&m_swWrapper.m_sListener.link);
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ CHyprWLListener::~CHyprWLListener() {
|
|||||||
|
|
||||||
void CHyprWLListener::removeCallback() {
|
void CHyprWLListener::removeCallback() {
|
||||||
if (isConnected()) {
|
if (isConnected()) {
|
||||||
Debug::log(LOG, "Callback %x -> %x, %s removed.", &m_pCallback, &m_pOwner, m_szAuthor.c_str());
|
Debug::log(LOG, "Callback %lx -> %lx, %s removed.", &m_pCallback, &m_pOwner, m_szAuthor.c_str());
|
||||||
wl_list_remove(&m_swWrapper.m_sListener.link);
|
wl_list_remove(&m_swWrapper.m_sListener.link);
|
||||||
wl_list_init(&m_swWrapper.m_sListener.link);
|
wl_list_init(&m_swWrapper.m_sListener.link);
|
||||||
}
|
}
|
||||||
@@ -41,9 +41,9 @@ void CHyprWLListener::initCallback(wl_signal* pSignal, std::function<void(void*,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pOwner = pOwner;
|
m_pOwner = pOwner;
|
||||||
m_pCallback = callback;
|
m_pCallback = callback;
|
||||||
m_szAuthor = author;
|
m_szAuthor = author;
|
||||||
|
|
||||||
addWLSignal(pSignal, &m_swWrapper.m_sListener, pOwner, m_szAuthor);
|
addWLSignal(pSignal, &m_swWrapper.m_sListener, pOwner, m_szAuthor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,35 +4,35 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
class CHyprWLListener {
|
class CHyprWLListener {
|
||||||
public:
|
public:
|
||||||
CHyprWLListener(wl_signal*, std::function<void(void*, void*)>, void* owner);
|
CHyprWLListener(wl_signal*, std::function<void(void*, void*)>, void* owner);
|
||||||
CHyprWLListener();
|
CHyprWLListener();
|
||||||
~CHyprWLListener();
|
~CHyprWLListener();
|
||||||
|
|
||||||
CHyprWLListener(const CHyprWLListener&) = delete;
|
CHyprWLListener(const CHyprWLListener&) = delete;
|
||||||
CHyprWLListener(CHyprWLListener&&) = delete;
|
CHyprWLListener(CHyprWLListener&&) = delete;
|
||||||
CHyprWLListener& operator=(const CHyprWLListener&) = delete;
|
CHyprWLListener& operator=(const CHyprWLListener&) = delete;
|
||||||
CHyprWLListener& operator=(CHyprWLListener&&) = delete;
|
CHyprWLListener& operator=(CHyprWLListener&&) = delete;
|
||||||
|
|
||||||
void initCallback(wl_signal*, std::function<void(void*, void*)>, void* owner, std::string author = "");
|
void initCallback(wl_signal*, std::function<void(void*, void*)>, void* owner, std::string author = "");
|
||||||
|
|
||||||
void removeCallback();
|
void removeCallback();
|
||||||
|
|
||||||
bool isConnected();
|
bool isConnected();
|
||||||
|
|
||||||
struct SWrapper {
|
struct SWrapper {
|
||||||
wl_listener m_sListener;
|
wl_listener m_sListener;
|
||||||
CHyprWLListener* m_pSelf;
|
CHyprWLListener* m_pSelf;
|
||||||
};
|
};
|
||||||
|
|
||||||
void emit(void*);
|
void emit(void*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SWrapper m_swWrapper;
|
SWrapper m_swWrapper;
|
||||||
|
|
||||||
void* m_pOwner = nullptr;
|
void* m_pOwner = nullptr;
|
||||||
|
|
||||||
std::function<void(void*, void*)> m_pCallback = nullptr;
|
std::function<void(void*, void*)> m_pCallback = nullptr;
|
||||||
|
|
||||||
std::string m_szAuthor = "";
|
std::string m_szAuthor = "";
|
||||||
};
|
};
|
||||||
57
src/helpers/WLSurface.cpp
Normal file
57
src/helpers/WLSurface.cpp
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#include "WLSurface.hpp"
|
||||||
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
|
CWLSurface::CWLSurface(wlr_surface* pSurface) {
|
||||||
|
m_pWLRSurface = pSurface;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWLSurface::assign(wlr_surface* pSurface) {
|
||||||
|
m_pWLRSurface = pSurface;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWLSurface::unassign() {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
CWLSurface::~CWLSurface() {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWLSurface::exists() const {
|
||||||
|
return m_pWLRSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_surface* CWLSurface::wlr() const {
|
||||||
|
return m_pWLRSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWLSurface::destroy() {
|
||||||
|
if (!m_pWLRSurface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hyprListener_destroy.removeCallback();
|
||||||
|
m_pWLRSurface->data = nullptr;
|
||||||
|
|
||||||
|
if (g_pCompositor->m_pLastFocus == m_pWLRSurface)
|
||||||
|
g_pCompositor->m_pLastFocus = nullptr;
|
||||||
|
|
||||||
|
m_pWLRSurface = nullptr;
|
||||||
|
|
||||||
|
Debug::log(LOG, "CWLSurface %lx called destroy()", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWLSurface::init() {
|
||||||
|
if (!m_pWLRSurface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RASSERT(!m_pWLRSurface->data, "Attempted to duplicate CWLSurface ownership!");
|
||||||
|
|
||||||
|
m_pWLRSurface->data = this;
|
||||||
|
|
||||||
|
hyprListener_destroy.initCallback(
|
||||||
|
&m_pWLRSurface->events.destroy, [&](void* owner, void* data) { destroy(); }, this, "CWLSurface");
|
||||||
|
|
||||||
|
Debug::log(LOG, "CWLSurface %lx called init()", this);
|
||||||
|
}
|
||||||
49
src/helpers/WLSurface.hpp
Normal file
49
src/helpers/WLSurface.hpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../defines.hpp"
|
||||||
|
|
||||||
|
class CWLSurface {
|
||||||
|
public:
|
||||||
|
CWLSurface() = default;
|
||||||
|
CWLSurface(wlr_surface* pSurface);
|
||||||
|
~CWLSurface();
|
||||||
|
|
||||||
|
void assign(wlr_surface* pSurface);
|
||||||
|
void unassign();
|
||||||
|
|
||||||
|
CWLSurface(const CWLSurface&) = delete;
|
||||||
|
CWLSurface(CWLSurface&&) = delete;
|
||||||
|
CWLSurface& operator=(const CWLSurface&) = delete;
|
||||||
|
CWLSurface& operator=(CWLSurface&&) = delete;
|
||||||
|
|
||||||
|
wlr_surface* wlr() const;
|
||||||
|
bool exists() const;
|
||||||
|
|
||||||
|
CWLSurface& operator=(wlr_surface* pSurface) {
|
||||||
|
destroy();
|
||||||
|
m_pWLRSurface = pSurface;
|
||||||
|
init();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const CWLSurface& other) const {
|
||||||
|
return other.wlr() == wlr();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const wlr_surface* other) const {
|
||||||
|
return other == wlr();
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit operator bool() const {
|
||||||
|
return exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
wlr_surface* m_pWLRSurface = nullptr;
|
||||||
|
|
||||||
|
void destroy();
|
||||||
|
void init();
|
||||||
|
|
||||||
|
DYNLISTENER(destroy);
|
||||||
|
};
|
||||||
@@ -9,8 +9,8 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_iMonitorID = monitorID;
|
m_iMonitorID = monitorID;
|
||||||
m_szName = name;
|
m_szName = name;
|
||||||
m_bIsSpecialWorkspace = special;
|
m_bIsSpecialWorkspace = special;
|
||||||
|
|
||||||
if (!special) {
|
if (!special) {
|
||||||
@@ -26,12 +26,18 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_vRenderOffset.m_pWorkspace = this;
|
m_vRenderOffset.m_pWorkspace = this;
|
||||||
m_vRenderOffset.create(AVARTYPE_VECTOR, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), nullptr, AVARDAMAGE_ENTIRE);
|
m_vRenderOffset.create(AVARTYPE_VECTOR, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"),
|
||||||
|
nullptr, AVARDAMAGE_ENTIRE);
|
||||||
m_fAlpha.m_pWorkspace = this;
|
m_fAlpha.m_pWorkspace = this;
|
||||||
m_fAlpha.create(AVARTYPE_FLOAT, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), nullptr, AVARDAMAGE_ENTIRE);
|
m_fAlpha.create(AVARTYPE_FLOAT, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"),
|
||||||
m_fAlpha.setValueAndWarp(255.f);
|
nullptr, AVARDAMAGE_ENTIRE);
|
||||||
|
m_fAlpha.setValueAndWarp(1.f);
|
||||||
|
|
||||||
|
m_vRenderOffset.registerVar();
|
||||||
|
m_fAlpha.registerVar();
|
||||||
|
|
||||||
g_pEventManager->postEvent({"createworkspace", m_szName}, true);
|
g_pEventManager->postEvent({"createworkspace", m_szName}, true);
|
||||||
|
EMIT_HOOK_EVENT("createWorkspace", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CWorkspace::~CWorkspace() {
|
CWorkspace::~CWorkspace() {
|
||||||
@@ -46,6 +52,7 @@ CWorkspace::~CWorkspace() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_pEventManager->postEvent({"destroyworkspace", m_szName}, true);
|
g_pEventManager->postEvent({"destroyworkspace", m_szName}, true);
|
||||||
|
EMIT_HOOK_EVENT("destroyWorkspace", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||||
@@ -56,16 +63,16 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
|||||||
|
|
||||||
if (in) {
|
if (in) {
|
||||||
m_fAlpha.setValueAndWarp(0.f);
|
m_fAlpha.setValueAndWarp(0.f);
|
||||||
m_fAlpha = 255.f;
|
m_fAlpha = 1.f;
|
||||||
} else {
|
} else {
|
||||||
m_fAlpha.setValueAndWarp(255.f);
|
m_fAlpha.setValueAndWarp(1.f);
|
||||||
m_fAlpha = 0.f;
|
m_fAlpha = 0.f;
|
||||||
}
|
}
|
||||||
} else if (ANIMSTYLE == "slidevert") {
|
} else if (ANIMSTYLE == "slidevert") {
|
||||||
// fallback is slide
|
// fallback is slide
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
|
|
||||||
m_fAlpha.setValueAndWarp(255.f); // fix a bug, if switching from fade -> slide.
|
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
|
||||||
|
|
||||||
if (in) {
|
if (in) {
|
||||||
m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y));
|
m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y));
|
||||||
@@ -77,7 +84,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
|||||||
// fallback is slide
|
// fallback is slide
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||||
|
|
||||||
m_fAlpha.setValueAndWarp(255.f); // fix a bug, if switching from fade -> slide.
|
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
|
||||||
|
|
||||||
if (in) {
|
if (in) {
|
||||||
m_vRenderOffset.setValueAndWarp(Vector2D(left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x, 0));
|
m_vRenderOffset.setValueAndWarp(Vector2D(left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x, 0));
|
||||||
@@ -91,15 +98,6 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
|||||||
m_vRenderOffset.warp();
|
m_vRenderOffset.warp();
|
||||||
m_fAlpha.warp();
|
m_fAlpha.warp();
|
||||||
}
|
}
|
||||||
|
|
||||||
// check LS-es
|
|
||||||
if (in) {
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
|
||||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
|
||||||
if (!ls->fadingOut)
|
|
||||||
ls->alpha = m_bHasFullscreenWindow && m_efFullscreenMode == FULLSCREEN_FULL ? 0.f : 255.f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorkspace::setActive(bool on) {
|
void CWorkspace::setActive(bool on) {
|
||||||
@@ -136,3 +134,30 @@ CWindow* CWorkspace::getLastFocusedWindow() {
|
|||||||
|
|
||||||
return m_pLastFocusedWindow;
|
return m_pLastFocusedWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWorkspace::rememberPrevWorkspace(const CWorkspace* prev) {
|
||||||
|
if (!prev) {
|
||||||
|
m_sPrevWorkspace.iID = -1;
|
||||||
|
m_sPrevWorkspace.name = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev->m_sPrevWorkspace.iID == m_sPrevWorkspace.iID) {
|
||||||
|
Debug::log(LOG, "Tried to set prev workspace to the same as current one");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sPrevWorkspace.iID = prev->m_iID;
|
||||||
|
m_sPrevWorkspace.name = prev->m_szName;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CWorkspace::getConfigName() {
|
||||||
|
if (m_bIsSpecialWorkspace) {
|
||||||
|
return "special:" + m_szName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_iID > 0)
|
||||||
|
return std::to_string(m_iID);
|
||||||
|
|
||||||
|
return "name:" + m_szName;
|
||||||
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user