Compare commits
1059 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
f1a867ea12 | |
![]() |
15589c9997 | |
![]() |
280594354c | |
![]() |
a9377db1a9 | |
![]() |
8f35a9ea8d | |
![]() |
cfe5bf2073 | |
![]() |
09b45a9937 | |
![]() |
d7ad0083a5 | |
![]() |
d2c648f6cc | |
![]() |
13b2c43b2b | |
![]() |
3fd9026a01 | |
![]() |
11d3f27e97 | |
![]() |
8314cdf89d | |
![]() |
6f2cab89d9 | |
![]() |
ad8c947134 | |
![]() |
e597a37429 | |
![]() |
240af64c82 | |
![]() |
585dd069f7 | |
![]() |
4c8544c44f | |
![]() |
a41fac2d75 | |
![]() |
02d43147b5 | |
![]() |
07dcede820 | |
![]() |
4c86653cd5 | |
![]() |
eb7b04e320 | |
![]() |
bdc24ff8c7 | |
![]() |
b35edf8d30 | |
![]() |
60a483471c | |
![]() |
0773db0710 | |
![]() |
9e57469c2f | |
![]() |
f0fad81963 | |
![]() |
7590c6d386 | |
![]() |
5a0ecdba33 | |
![]() |
c5fb21fd8b | |
![]() |
2601d06f5b | |
![]() |
a7470f4b4a | |
![]() |
44ea9ee959 | |
![]() |
059f66af9a | |
![]() |
c958a75e2b | |
![]() |
47ee47dcc8 | |
![]() |
a97c748d1c | |
![]() |
1384a8d3fd | |
![]() |
d6b3baec8f | |
![]() |
53221fd43f | |
![]() |
28b396f44c | |
![]() |
6a2bc79dae | |
![]() |
03eb688818 | |
![]() |
92ceb00b37 | |
![]() |
4453ce7eef | |
![]() |
3b3c75a8e9 | |
![]() |
ad4e27f5ef | |
![]() |
21a0ae31b7 | |
![]() |
a169114fee | |
![]() |
0eb02c8b2c | |
![]() |
b1bd3ff630 | |
![]() |
1dbef2d5ed | |
![]() |
1ee3062e45 | |
![]() |
944be3d55a | |
![]() |
c6ac6d3caa | |
![]() |
6540112bf3 | |
![]() |
7d486ddce7 | |
![]() |
85badd901d | |
![]() |
7eb9f75af2 | |
![]() |
b745f83339 | |
![]() |
9293df2681 | |
![]() |
2fb485d67d | |
![]() |
16f6473f56 | |
![]() |
9bcba5334c | |
![]() |
268d066f4f | |
![]() |
9276d28b3d | |
![]() |
2db79aaca8 | |
![]() |
1a916293dc | |
![]() |
92f1fabe5b | |
![]() |
b107295c03 | |
![]() |
e316694675 | |
![]() |
8a5bae0f86 | |
![]() |
ad31fd6b18 | |
![]() |
18e9adf5b7 | |
![]() |
1dee66a36c | |
![]() |
1b1af29de9 | |
![]() |
940215b624 | |
![]() |
559b0cccf5 | |
![]() |
7fca508619 | |
![]() |
0fc6c6800e | |
![]() |
c761571a43 | |
![]() |
e16069ae77 | |
![]() |
4f5fce8b7a | |
![]() |
170b138026 | |
![]() |
7e2d650c8f | |
![]() |
af16c9b243 | |
![]() |
1a7c94b692 | |
![]() |
ba599a2aa0 | |
![]() |
64bbbde249 | |
![]() |
f89a1f9766 | |
![]() |
a1443cb43e | |
![]() |
2d4bbe917c | |
![]() |
8c067c77f4 | |
![]() |
68b7448847 | |
![]() |
178d49093c | |
![]() |
979ac5bd50 | |
![]() |
29a5541ccf | |
![]() |
e1192a6934 | |
![]() |
d00d00c7fc | |
![]() |
6b4ef4170c | |
![]() |
d595b8f8aa | |
![]() |
55dc891190 | |
![]() |
5c6e51d75e | |
![]() |
927fb42abc | |
![]() |
3461d5bc3a | |
![]() |
e5528e9317 | |
![]() |
786b3ffbae | |
![]() |
07f266e7c7 | |
![]() |
5fe9e9c756 | |
![]() |
8256f8e14c | |
![]() |
5d03d58dc1 | |
![]() |
a7c4175099 | |
![]() |
fef2bfb93f | |
![]() |
ad98069618 | |
![]() |
ec86640f44 | |
![]() |
c2141dc4ef | |
![]() |
f46174453d | |
![]() |
21a45c2700 | |
![]() |
4db2742e96 | |
![]() |
312f88872b | |
![]() |
ad6700dd88 | |
![]() |
6543ab3caa | |
![]() |
c2ca1cc33d | |
![]() |
8fb3348600 | |
![]() |
877d220bfe | |
![]() |
f37c15b0a2 | |
![]() |
6be238e622 | |
![]() |
35a7e30952 | |
![]() |
131c5399b3 | |
![]() |
d65bc400e9 | |
![]() |
1c3b4cc548 | |
![]() |
d6360cc4ce | |
![]() |
64b02cf464 | |
![]() |
6c69f0a4d1 | |
![]() |
f9b9149ba4 | |
![]() |
b202ecf711 | |
![]() |
3c857a3375 | |
![]() |
68d1e2f42a | |
![]() |
70231f2431 | |
![]() |
cd2d5b07d5 | |
![]() |
cfbee55c2a | |
![]() |
61332caa20 | |
![]() |
0c5ee47892 | |
![]() |
4b58f6c207 | |
![]() |
57d8bd6856 | |
![]() |
57f862eb4d | |
![]() |
fa5b3e920b | |
![]() |
cfca23f9b3 | |
![]() |
65b4968c80 | |
![]() |
a6a85466cd | |
![]() |
f6540283d5 | |
![]() |
83502e29a9 | |
![]() |
b2ff465490 | |
![]() |
bffae41983 | |
![]() |
3bf97e87e5 | |
![]() |
0cd6f5cd06 | |
![]() |
6166060f9b | |
![]() |
76739f1f2f | |
![]() |
54473f03ba | |
![]() |
ecb6460277 | |
![]() |
a167657214 | |
![]() |
47d873db94 | |
![]() |
3f48b22f1a | |
![]() |
8c25784070 | |
![]() |
c9627dc60f | |
![]() |
a56b16e2ff | |
![]() |
eea79bddd8 | |
![]() |
7622921de6 | |
![]() |
b4822389c3 | |
![]() |
8c149bb6b7 | |
![]() |
fd746b46e5 | |
![]() |
cadf16b12e | |
![]() |
01a9eb2327 | |
![]() |
d048f9aad8 | |
![]() |
79238b06cf | |
![]() |
79ef1be57b | |
![]() |
8b843e647c | |
![]() |
ee4cf67371 | |
![]() |
1c3a987d74 | |
![]() |
26d9361695 | |
![]() |
31a3961c4c | |
![]() |
a1f30edaf6 | |
![]() |
e84ca82c9a | |
![]() |
f700de56f8 | |
![]() |
40839e3347 | |
![]() |
2ca81bbe32 | |
![]() |
d7772031b1 | |
![]() |
1195936a68 | |
![]() |
f4f0660dbb | |
![]() |
4ab679f2fd | |
![]() |
5d90f232bd | |
![]() |
0ce7a40850 | |
![]() |
2cf36e640f | |
![]() |
cefcdf7db5 | |
![]() |
64ddeff3bd | |
![]() |
ce57af62ec | |
![]() |
ba7b23c41d | |
![]() |
59f1f7ee9f | |
![]() |
c164ff467c | |
![]() |
ec1ebb6fb8 | |
![]() |
1d05f98e4b | |
![]() |
6a59c4defc | |
![]() |
804ecb0e22 | |
![]() |
97c1d335e5 | |
![]() |
09d4f3fda3 | |
![]() |
b0ccacc983 | |
![]() |
fa351403ef | |
![]() |
a76ae07ee1 | |
![]() |
447994581b | |
![]() |
5e122cb6c0 | |
![]() |
ae376766ef | |
![]() |
862dae455a | |
![]() |
d0e07ba3e8 | |
![]() |
669e90325c | |
![]() |
9e3db94718 | |
![]() |
2099409189 | |
![]() |
3f0627172d | |
![]() |
73425b13a4 | |
![]() |
cc031839db | |
![]() |
e678ebef29 | |
![]() |
586a775d5b | |
![]() |
d655b5a994 | |
![]() |
40a9f08dd3 | |
![]() |
1e3d50e3ff | |
![]() |
0c4f46739d | |
![]() |
df9b0bd8f0 | |
![]() |
3ebbe28b64 | |
![]() |
5362105f27 | |
![]() |
572e07b130 | |
![]() |
01d3f22633 | |
![]() |
5e79956933 | |
![]() |
1ab1a5f297 | |
![]() |
14bbe38b31 | |
![]() |
7b547bf61d | |
![]() |
e7e6dee79b | |
![]() |
dd36387c1f | |
![]() |
d737d1dbcb | |
![]() |
84633badc7 | |
![]() |
29122f1df6 | |
![]() |
0e934273bb | |
![]() |
b232e80319 | |
![]() |
1866e70fe3 | |
![]() |
c65f01e5dc | |
![]() |
7ba6c08fa7 | |
![]() |
2e9e6893bb | |
![]() |
0f41239515 | |
![]() |
3465ecac16 | |
![]() |
7bf40c3501 | |
![]() |
79357db409 | |
![]() |
dcd2f7b15a | |
![]() |
202356ba89 | |
![]() |
f4232bc391 | |
![]() |
1ca7524853 | |
![]() |
bc52189e20 | |
![]() |
1d9824d0a2 | |
![]() |
7880f879a3 | |
![]() |
bbf4f46b28 | |
![]() |
f5ac8968d8 | |
![]() |
aae9eb9c65 | |
![]() |
c919c91063 | |
![]() |
35ce8a6208 | |
![]() |
22dffa4714 | |
![]() |
ebe6f58d9a | |
![]() |
0b2596b604 | |
![]() |
b59ba5b9b7 | |
![]() |
de88370577 | |
![]() |
fa895828de | |
![]() |
9af15a979d | |
![]() |
df60eef0db | |
![]() |
856925bcc3 | |
![]() |
de15b87ea7 | |
![]() |
982a2e3a37 | |
![]() |
711c5bb43f | |
![]() |
7710b44f1d | |
![]() |
54f7079100 | |
![]() |
47484bb141 | |
![]() |
96c0d800b8 | |
![]() |
29a93a2e57 | |
![]() |
77794e1333 | |
![]() |
805435d157 | |
![]() |
4ebb21e8c3 | |
![]() |
886f0e852b | |
![]() |
0ce58c7cbf | |
![]() |
9fef6380d4 | |
![]() |
e04ec0ce29 | |
![]() |
b167d1f56a | |
![]() |
8d5ebb5e15 | |
![]() |
22d0631b1b | |
![]() |
589479c24a | |
![]() |
7a2e6bb58e | |
![]() |
d2d92cdfd2 | |
![]() |
a3c763b8ef | |
![]() |
dcda15e5e3 | |
![]() |
653938e456 | |
![]() |
26a0038d0c | |
![]() |
b1ed2bb3e7 | |
![]() |
200e46bec6 | |
![]() |
325daecace | |
![]() |
43c21c390b | |
![]() |
013e69988f | |
![]() |
ba8c52564e | |
![]() |
ef41fa8e8f | |
![]() |
4c144958c7 | |
![]() |
2dd71603dd | |
![]() |
b2e1ede6e5 | |
![]() |
ea5b79dbf6 | |
![]() |
01f3f185d8 | |
![]() |
c41315564c | |
![]() |
46f5951820 | |
![]() |
6ec7e919fb | |
![]() |
24807dfa50 | |
![]() |
d55fa39ebf | |
![]() |
0db46e3966 | |
![]() |
b3f7924539 | |
![]() |
cac430fdbb | |
![]() |
4e01d2c8b7 | |
![]() |
33fe211471 | |
![]() |
14c08422ca | |
![]() |
df9f8f8346 | |
![]() |
fb28d75ad8 | |
![]() |
6a44cce527 | |
![]() |
219f110093 | |
![]() |
4470e82baa | |
![]() |
c8de1aa677 | |
![]() |
11cd27c793 | |
![]() |
5980945ee4 | |
![]() |
38c4980b0d | |
![]() |
6acc652487 | |
![]() |
801fecf821 | |
![]() |
8f0425d91c | |
![]() |
93d810aaad | |
![]() |
a7e26a5770 | |
![]() |
b976c274fd | |
![]() |
aabadcee6d | |
![]() |
04643fa3d8 | |
![]() |
7916352f5b | |
![]() |
cdbe119789 | |
![]() |
b2193f370d | |
![]() |
e4e5c52300 | |
![]() |
55e5d50074 | |
![]() |
354a71855e | |
![]() |
336b2fd2f6 | |
![]() |
26b15feb61 | |
![]() |
20d5f9bc6e | |
![]() |
445567f54e | |
![]() |
3232a63ac1 | |
![]() |
06ba20cc2e | |
![]() |
6b5571b023 | |
![]() |
55cccf3779 | |
![]() |
ce9531d549 | |
![]() |
4e4186aa48 | |
![]() |
a2185d0836 | |
![]() |
5c93c4251b | |
![]() |
75ab5b8353 | |
![]() |
eb331a5df4 | |
![]() |
77cf49aa72 | |
![]() |
f5120e570b | |
![]() |
4037f093db | |
![]() |
e2611d710f | |
![]() |
31f80d18f2 | |
![]() |
2e92fca017 | |
![]() |
69b8c91655 | |
![]() |
351f613ef4 | |
![]() |
e804b45d86 | |
![]() |
4dffc09aaa | |
![]() |
4a70793e2b | |
![]() |
c404c76a8b | |
![]() |
5ff705a124 | |
![]() |
24f4e268a9 | |
![]() |
529ccbbd18 | |
![]() |
068f1c2b54 | |
![]() |
1470cfc790 | |
![]() |
bc29e09d88 | |
![]() |
98aa044508 | |
![]() |
7949032411 | |
![]() |
38694bbe1a | |
![]() |
c14c61f745 | |
![]() |
1f32171ac9 | |
![]() |
1da8b61864 | |
![]() |
fba948b39f | |
![]() |
48197a4f5b | |
![]() |
7bd6b92110 | |
![]() |
eed7943939 | |
![]() |
09b32a1e68 | |
![]() |
9ca7b9b1cf | |
![]() |
26afbfb6fa | |
![]() |
01d224fa22 | |
![]() |
98747246cd | |
![]() |
3ed535dd67 | |
![]() |
bca99d0b4c | |
![]() |
499d006e3a | |
![]() |
2120e18729 | |
![]() |
9ba95ecd5d | |
![]() |
52b92904de | |
![]() |
36001e5ee0 | |
![]() |
1ab5453a90 | |
![]() |
5e94f5429a | |
![]() |
f7a36a43d9 | |
![]() |
344e56dd77 | |
![]() |
99324c12fd | |
![]() |
64e0b693c7 | |
![]() |
b2f181fe80 | |
![]() |
89b6a67232 | |
![]() |
749b80ab49 | |
![]() |
881858f8dd | |
![]() |
1a4606d990 | |
![]() |
bf4c5241a0 | |
![]() |
ab1350b6a6 | |
![]() |
9ca69cf50c | |
![]() |
4c6000b3e1 | |
![]() |
32addf4d59 | |
![]() |
672b662dd2 | |
![]() |
1573d04b5a | |
![]() |
485769ddd9 | |
![]() |
cfe001df6f | |
![]() |
2014f9a382 | |
![]() |
00c1e9850b | |
![]() |
f9e746dff6 | |
![]() |
7d557784a1 | |
![]() |
15e23b825e | |
![]() |
17029cd54f | |
![]() |
d20d84cfa3 | |
![]() |
61ca42cd2c | |
![]() |
c26101a9fe | |
![]() |
786dc09704 | |
![]() |
d9d733924c | |
![]() |
9cd067e4fd | |
![]() |
b29b3db26d | |
![]() |
2dbf2dd995 | |
![]() |
c05a26f5c4 | |
![]() |
693603d87a | |
![]() |
17c857ce66 | |
![]() |
c3c3b903b1 | |
![]() |
608cc0e7f8 | |
![]() |
bd2728fac1 | |
![]() |
9a74d70ba4 | |
![]() |
d9ee6d98ae | |
![]() |
4448e23363 | |
![]() |
9c2035ca63 | |
![]() |
da34191115 | |
![]() |
2b0b04235c | |
![]() |
8c6ebee318 | |
![]() |
38e2bf34cf | |
![]() |
cbab4b46c1 | |
![]() |
baaa1db5d1 | |
![]() |
883acb1f58 | |
![]() |
fdd338f02b | |
![]() |
3d5e10e9bb | |
![]() |
7f20621b25 | |
![]() |
57a79608da | |
![]() |
7c3a27fb43 | |
![]() |
298a8ca8c5 | |
![]() |
7bb250826e | |
![]() |
28d6b5230a | |
![]() |
5272c24301 | |
![]() |
b4e15b28b6 | |
![]() |
4c384d1e9f | |
![]() |
0c49ae5360 | |
![]() |
a4be9859b7 | |
![]() |
4d72263b31 | |
![]() |
20960c2fea | |
![]() |
b5c127519f | |
![]() |
7ac61516b2 | |
![]() |
9165ba3b20 | |
![]() |
5c2314a6bd | |
![]() |
9e9da67fc0 | |
![]() |
c8e0568022 | |
![]() |
4be92db483 | |
![]() |
bd84f1606d | |
![]() |
8d3c06a178 | |
![]() |
d1fdb69946 | |
![]() |
cd2a4de82f | |
![]() |
7894db7504 | |
![]() |
9d3e87bd9d | |
![]() |
ea9691a2f5 | |
![]() |
0bcb9a0ddd | |
![]() |
399a955eb2 | |
![]() |
c310ba782a | |
![]() |
d59451adcf | |
![]() |
5101579eb8 | |
![]() |
8c8c5b9b0e | |
![]() |
8428b4603c | |
![]() |
c6c99c1740 | |
![]() |
686ea6374b | |
![]() |
866afcb94b | |
![]() |
d71243aa07 | |
![]() |
a2cccf0d75 | |
![]() |
9b5ee76683 | |
![]() |
0fef229587 | |
![]() |
6a4a68dea4 | |
![]() |
221c6aaf2b | |
![]() |
08439957d0 | |
![]() |
fb19774730 | |
![]() |
d0b69f3503 | |
![]() |
3c82d5a919 | |
![]() |
831ca28f93 | |
![]() |
5777b3c257 | |
![]() |
8bf1f9203b | |
![]() |
489cd31ee9 | |
![]() |
4f322e24d3 | |
![]() |
232984ebd5 | |
![]() |
111657ad04 | |
![]() |
5c16cdd4ed | |
![]() |
012c64b054 | |
![]() |
236baa63df | |
![]() |
8934a31dad | |
![]() |
442648edc0 | |
![]() |
44b72823c2 | |
![]() |
6412fd2c34 | |
![]() |
b4b9a28b6f | |
![]() |
a7e7923d6b | |
![]() |
630ba5fab4 | |
![]() |
246824aa61 | |
![]() |
60d36c0753 | |
![]() |
fb6ce3707a | |
![]() |
3ebe34bc3f | |
![]() |
75f94c7cd0 | |
![]() |
afbb878fca | |
![]() |
01fa6c0af0 | |
![]() |
7bfb4a93e2 | |
![]() |
701f914081 | |
![]() |
c1a2355d71 | |
![]() |
6b1e2f24f4 | |
![]() |
8892b16626 | |
![]() |
bf6727b384 | |
![]() |
b6d315705b | |
![]() |
29135f188f | |
![]() |
fb7dd07076 | |
![]() |
0897dbff75 | |
![]() |
e13a30f00f | |
![]() |
b2a48d09e7 | |
![]() |
22ef6d9ddf | |
![]() |
0bc3fc18aa | |
![]() |
5fd96620ed | |
![]() |
af3bf939c5 | |
![]() |
2a13a33040 | |
![]() |
e5805fbd62 | |
![]() |
6b25d95f77 | |
![]() |
8cae7f7186 | |
![]() |
e8ae03d799 | |
![]() |
f563bade46 | |
![]() |
0780c0d96b | |
![]() |
645db7fc90 | |
![]() |
2663756ebf | |
![]() |
7db47ac2fd | |
![]() |
78e2c123c3 | |
![]() |
11a5513e78 | |
![]() |
3e4c2b3ec8 | |
![]() |
5d313fdd7b | |
![]() |
2d5a69b1d2 | |
![]() |
aa465efa51 | |
![]() |
1655d6bbc7 | |
![]() |
e68ac506af | |
![]() |
ac9b9a6772 | |
![]() |
b8a59d0bd9 | |
![]() |
6c4551ff46 | |
![]() |
0b4c6f8b3b | |
![]() |
c7b9376ccc | |
![]() |
d6ad0bcc20 | |
![]() |
acb4945cd3 | |
![]() |
9ee6b57d69 | |
![]() |
9a0471a6d5 | |
![]() |
a28676666a | |
![]() |
fa4635e570 | |
![]() |
b2babac3d0 | |
![]() |
09049954b9 | |
![]() |
3a55351211 | |
![]() |
2c7301b3ee | |
![]() |
656313455b | |
![]() |
380795423d | |
![]() |
92d29ed7f0 | |
![]() |
681752ada1 | |
![]() |
609833e880 | |
![]() |
9302e84b95 | |
![]() |
044c9f0154 | |
![]() |
4d659998d4 | |
![]() |
46f3c8509c | |
![]() |
a887b737ef | |
![]() |
2922b8d0a7 | |
![]() |
b4e2241ded | |
![]() |
8a11dde6f2 | |
![]() |
98f0af0bc1 | |
![]() |
f723b11a9a | |
![]() |
ad747daf4f | |
![]() |
670c71f11e | |
![]() |
93326f3e50 | |
![]() |
af7388c8a3 | |
![]() |
3f6a4eb1ea | |
![]() |
47829e6ac3 | |
![]() |
6435adc9d8 | |
![]() |
0bfe7e150a | |
![]() |
422b6c4f0d | |
![]() |
0360ce38e2 | |
![]() |
277701e99f | |
![]() |
c1311abfc1 | |
![]() |
05dc255048 | |
![]() |
2e5d3253d4 | |
![]() |
ad13765348 | |
![]() |
ea4fa87bc6 | |
![]() |
b19426879f | |
![]() |
2f3b05e733 | |
![]() |
179af074eb | |
![]() |
493797ff31 | |
![]() |
7618be3697 | |
![]() |
605401dcfc | |
![]() |
c5cd8d1318 | |
![]() |
5aa2606f04 | |
![]() |
c41da588f6 | |
![]() |
568da29fbf | |
![]() |
a8b9e8d262 | |
![]() |
bb0d1fc45e | |
![]() |
f98477e05b | |
![]() |
1b4a9abbe3 | |
![]() |
feeacf37db | |
![]() |
e763cd9eec | |
![]() |
1b21b08130 | |
![]() |
7ff51ba47c | |
![]() |
f3d9e5c90c | |
![]() |
9bf7c294a8 | |
![]() |
a136a159f9 | |
![]() |
f5cb109a87 | |
![]() |
e2cbed7060 | |
![]() |
18e414443e | |
![]() |
40b8637ab8 | |
![]() |
7078f4e3af | |
![]() |
2103eb8d16 | |
![]() |
7992d01fbd | |
![]() |
b674b458df | |
![]() |
a489bfa12c | |
![]() |
9ca738ffec | |
![]() |
769c63c834 | |
![]() |
5401d6c213 | |
![]() |
34545553b2 | |
![]() |
e4349536a3 | |
![]() |
d1bc39a6ea | |
![]() |
568f9fb666 | |
![]() |
4a42829841 | |
![]() |
1d57c9a5af | |
![]() |
f82542790c | |
![]() |
dcd20922d9 | |
![]() |
0bc60023f5 | |
![]() |
2ad896c71d | |
![]() |
8736e44e1a | |
![]() |
bfd755aee9 | |
![]() |
0c8b3251e5 | |
![]() |
2b8b53a105 | |
![]() |
a33fe84f57 | |
![]() |
d0a6bd3404 | |
![]() |
43e5f17547 | |
![]() |
599020d8da | |
![]() |
1b10dde569 | |
![]() |
da80dd4c84 | |
![]() |
9e77e5038f | |
![]() |
3b28788592 | |
![]() |
918ac8b27e | |
![]() |
b650f55d60 | |
![]() |
2025bf4c6b | |
![]() |
53a61dfac0 | |
![]() |
956390005b | |
![]() |
282d221ee1 | |
![]() |
96139b8af5 | |
![]() |
fdb8d49946 | |
![]() |
2491fb1b2b | |
![]() |
47317a9fc7 | |
![]() |
f0b3964c1a | |
![]() |
181ce590a9 | |
![]() |
f6813258ce | |
![]() |
49852cc096 | |
![]() |
0dc3f4906f | |
![]() |
79b7545840 | |
![]() |
64dc01c640 | |
![]() |
86ede0ecf2 | |
![]() |
d377b5cdab | |
![]() |
bd88801de4 | |
![]() |
e89bd802a2 | |
![]() |
52349491af | |
![]() |
bf1ce85474 | |
![]() |
94121c2a42 | |
![]() |
26a7af5e5f | |
![]() |
e84d5bb666 | |
![]() |
38fae969a9 | |
![]() |
7d7344a983 | |
![]() |
494daab3d5 | |
![]() |
6004ffe228 | |
![]() |
d8e8f952a2 | |
![]() |
bc62e7e094 | |
![]() |
a8a53c651b | |
![]() |
5a32f012c3 | |
![]() |
2ed54ee10f | |
![]() |
6fb8eac890 | |
![]() |
0dd2012d4f | |
![]() |
e40f632c9b | |
![]() |
fe45c99e99 | |
![]() |
191b0e7b6d | |
![]() |
bcba59a7f5 | |
![]() |
916710ea01 | |
![]() |
207bc1d9e6 | |
![]() |
c153fc719a | |
![]() |
f6b605daf2 | |
![]() |
9e70c2a21c | |
![]() |
33e971cc09 | |
![]() |
693cd16b12 | |
![]() |
18628131df | |
![]() |
5f043f2d61 | |
![]() |
36f6f2fb2d | |
![]() |
c11eeabc86 | |
![]() |
765cd82613 | |
![]() |
dd53576fe2 | |
![]() |
af4e12c5fc | |
![]() |
d55f012537 | |
![]() |
183637502d | |
![]() |
d13b6db706 | |
![]() |
677ce4014a | |
![]() |
deb17ded8a | |
![]() |
4d6f6223bc | |
![]() |
329c5de451 | |
![]() |
13c092d671 | |
![]() |
192ec437df | |
![]() |
083318dddd | |
![]() |
32be54b19d | |
![]() |
024db60ccd | |
![]() |
fb36af09cd | |
![]() |
4d5195bf8b | |
![]() |
7468465393 | |
![]() |
d649eab88a | |
![]() |
a8af40ecf7 | |
![]() |
8029c5c7ac | |
![]() |
9cf424993f | |
![]() |
4449315e39 | |
![]() |
10e41fc948 | |
![]() |
56d3c797cc | |
![]() |
7c0a88f34b | |
![]() |
9da0b8543f | |
![]() |
493a4f7280 | |
![]() |
d51b69d6ac | |
![]() |
05a3e2bad9 | |
![]() |
4f008c0231 | |
![]() |
ff4cfe279a | |
![]() |
bb354de90e | |
![]() |
d33ab542db | |
![]() |
904c33556b | |
![]() |
648cfcd66c | |
![]() |
602095ec52 | |
![]() |
b7bdd4f3ff | |
![]() |
8c3332f619 | |
![]() |
564bfafb57 | |
![]() |
039fd39e34 | |
![]() |
080d28b3f9 | |
![]() |
5306823435 | |
![]() |
c5c25a66f7 | |
![]() |
2c445ebf3c | |
![]() |
ade5d72c3a | |
![]() |
c2c19fe91f | |
![]() |
0bd65de375 | |
![]() |
f77f5b2342 | |
![]() |
be3823e826 | |
![]() |
af7fa6a040 | |
![]() |
bb8b51a3ab | |
![]() |
b2450cfe14 | |
![]() |
86f0d9914e | |
![]() |
9e3e567592 | |
![]() |
79dd34b3f9 | |
![]() |
afa450b97a | |
![]() |
4045b3b389 | |
![]() |
6dc908908c | |
![]() |
8fa782f1a8 | |
![]() |
2c280b1bb0 | |
![]() |
86db3b4336 | |
![]() |
3ede995b27 | |
![]() |
64e701fdaf | |
![]() |
c3cda8b62a | |
![]() |
7732f0e56b | |
![]() |
f349d8e132 | |
![]() |
dfa1cbda4f | |
![]() |
86540cd344 | |
![]() |
b3b2bcb369 | |
![]() |
a1ae401240 | |
![]() |
742268bfa1 | |
![]() |
9ea6f311ea | |
![]() |
d69331d186 | |
![]() |
fc92544cb3 | |
![]() |
0991cded05 | |
![]() |
f364f3a923 | |
![]() |
ac9d470ab8 | |
![]() |
7297e62283 | |
![]() |
af12a103ae | |
![]() |
3388b7643c | |
![]() |
3a8ae60f87 | |
![]() |
5d787a4083 | |
![]() |
c6a3d76b92 | |
![]() |
b36894884e | |
![]() |
5244f9f406 | |
![]() |
1b14b7b2f1 | |
![]() |
46ca22f480 | |
![]() |
b7e5d3f232 | |
![]() |
f303ba4b59 | |
![]() |
f650ebe2fc | |
![]() |
1f1c54ca6c | |
![]() |
a917d1885e | |
![]() |
8c543dbe7c | |
![]() |
c5305820d4 | |
![]() |
5386360928 | |
![]() |
8a9cb06b41 | |
![]() |
eab90b6a0a | |
![]() |
b480297913 | |
![]() |
1230c5ef92 | |
![]() |
c6be2b51a9 | |
![]() |
2f4db693e3 | |
![]() |
55ef69645c | |
![]() |
f6447ad188 | |
![]() |
62b55d0463 | |
![]() |
77f3046ae0 | |
![]() |
8f27ee0cb8 | |
![]() |
9abf7a9d61 | |
![]() |
2ca1d3fd4c | |
![]() |
857766eb74 | |
![]() |
a0d437163d | |
![]() |
b02190bf23 | |
![]() |
956451111c | |
![]() |
4585cec7a1 | |
![]() |
daec969720 | |
![]() |
349f9c1fb6 | |
![]() |
9187fe80f4 | |
![]() |
ea8dd5f32c | |
![]() |
4e8f1bdfda | |
![]() |
13e7cac019 | |
![]() |
95d4671a10 | |
![]() |
914aeb32ec | |
![]() |
7c8b5be55a | |
![]() |
31ebdb73a0 | |
![]() |
06db626fc4 | |
![]() |
764f0102fd | |
![]() |
d78dcc6140 | |
![]() |
e974c07001 | |
![]() |
5ad63f21e0 | |
![]() |
a5726e19fd | |
![]() |
cd43199e70 | |
![]() |
540dff30e7 | |
![]() |
6b4018014c | |
![]() |
51fb56773b | |
![]() |
7c4bde3a32 | |
![]() |
6cd615e4df | |
![]() |
83fe158a16 | |
![]() |
4b7874391d | |
![]() |
d3a2e07002 | |
![]() |
1583b2c717 | |
![]() |
6d0f1fedc0 | |
![]() |
f75fb70ddc | |
![]() |
b1908949d0 | |
![]() |
a472c90327 | |
![]() |
c9c84b6859 | |
![]() |
7c2cf9c953 | |
![]() |
cb398ce6fe | |
![]() |
b432c22e76 | |
![]() |
b560ad56b6 | |
![]() |
3714dcc337 | |
![]() |
8086707d1c | |
![]() |
2556378dfa | |
![]() |
9c0947ae15 | |
![]() |
3d21e41bc9 | |
![]() |
14749e91e9 | |
![]() |
1c8bd1be62 | |
![]() |
3118ba5982 | |
![]() |
e7d6e8b217 | |
![]() |
8f7f97148c | |
![]() |
63c1363ca1 | |
![]() |
41aeecbb2a | |
![]() |
e97b6032c2 | |
![]() |
0c03e7ccfc | |
![]() |
69f344a439 | |
![]() |
50fae55821 | |
![]() |
6e4b5839ce | |
![]() |
68f1684031 | |
![]() |
fec39141b5 | |
![]() |
8b29f07dbe | |
![]() |
993f110d59 | |
![]() |
71ade59f4b | |
![]() |
aac5d562fb | |
![]() |
3f2b49be5d | |
![]() |
66a491bda6 | |
![]() |
ba37d18ab9 | |
![]() |
909d83419c | |
![]() |
94e1d6de3e | |
![]() |
7c9fb68b14 | |
![]() |
cc2e6fc96c | |
![]() |
ee782c8a91 | |
![]() |
4d0cd42aef | |
![]() |
79a61deb25 | |
![]() |
e58451fc01 | |
![]() |
92f4a95bb5 | |
![]() |
5896bab86f | |
![]() |
880ce92fb2 | |
![]() |
c733e7a7b6 | |
![]() |
c2749e3acf | |
![]() |
93b9fdd391 | |
![]() |
67b1a88466 | |
![]() |
cc72778d5e | |
![]() |
ae7fb3885b | |
![]() |
795b619704 | |
![]() |
19970bd639 | |
![]() |
5ae170f1d6 | |
![]() |
896a57d3be | |
![]() |
a649be64db | |
![]() |
6db05aaef1 | |
![]() |
9c0085f5a9 | |
![]() |
8d44ece874 | |
![]() |
3a1b9414ed | |
![]() |
120e36da2a | |
![]() |
788f42ddd4 | |
![]() |
def3a50558 | |
![]() |
98dcf82ada | |
![]() |
b1414033ef | |
![]() |
4dd1e91bda | |
![]() |
a64c86b73f | |
![]() |
e23cb52a16 | |
![]() |
b05fa94d32 | |
![]() |
91974b7794 | |
![]() |
d9e96223f4 | |
![]() |
341067d4d7 | |
![]() |
16aaf92782 | |
![]() |
2d399e93f0 | |
![]() |
aaa35d455c | |
![]() |
1eb95982dc | |
![]() |
b21229e59a | |
![]() |
35572904fc | |
![]() |
601d33f294 | |
![]() |
75b08a8fd9 | |
![]() |
ab631c2147 | |
![]() |
53fa2bfbd6 | |
![]() |
0300c17441 | |
![]() |
1b6aa65ee5 | |
![]() |
fe8fe42ea9 | |
![]() |
2d2ee710c8 | |
![]() |
5876269f66 | |
![]() |
91ae3d907e | |
![]() |
2505fd03f1 | |
![]() |
bbc833baa6 | |
![]() |
bb2391133d | |
![]() |
06230e43d6 | |
![]() |
957e73a889 | |
![]() |
daad3b9d7c | |
![]() |
9cdf19c657 | |
![]() |
296d3f31be | |
![]() |
25150633ed | |
![]() |
3bce89553c | |
![]() |
f44484137e | |
![]() |
e01116149b | |
![]() |
a1b47dfa08 | |
![]() |
f065ee6d06 | |
![]() |
3663e1ec13 | |
![]() |
bbb40a9a84 | |
![]() |
adc076322b | |
![]() |
d0a49a6b77 | |
![]() |
8db8dd24bf | |
![]() |
7e095412aa | |
![]() |
3cafc20981 | |
![]() |
7a2d95ddc8 | |
![]() |
575ff68e5b | |
![]() |
01818f683c | |
![]() |
8774a0114c | |
![]() |
acb0dc4c24 | |
![]() |
015a8452cd | |
![]() |
9fa5f7547f | |
![]() |
efde6c8e9e | |
![]() |
fd7a67d92e | |
![]() |
daa8785e34 | |
![]() |
2b684146c7 | |
![]() |
adbf69aab4 | |
![]() |
39a5489bde | |
![]() |
ab41bcf3ad | |
![]() |
9822e75fbf | |
![]() |
7ba7ddfee8 | |
![]() |
0284610eff | |
![]() |
7e8230a596 | |
![]() |
4cc94e9462 | |
![]() |
0ce01ac30f | |
![]() |
d563bc6c86 | |
![]() |
cffacc514d | |
![]() |
428758d33a | |
![]() |
0b36919b7c | |
![]() |
36bec2d941 | |
![]() |
788c186701 | |
![]() |
f6d9b8a0b4 | |
![]() |
f23e0ef05b | |
![]() |
69f8bee0b1 | |
![]() |
d5ca429627 | |
![]() |
da4f4d7e69 | |
![]() |
9f10d5d79f | |
![]() |
f79886765d | |
![]() |
176ae6e692 | |
![]() |
5c4acbdddd | |
![]() |
74a193d383 | |
![]() |
597753047d | |
![]() |
2dba3d30af | |
![]() |
e963ae09cc | |
![]() |
7007599b3f | |
![]() |
42c61dc6a3 | |
![]() |
9c2f12f98f | |
![]() |
e9db9cd7d3 | |
![]() |
1a1eaee13f | |
![]() |
fd2e77317f | |
![]() |
6ab8f179a7 | |
![]() |
ed339de953 | |
![]() |
203c4998bc | |
![]() |
3dd18a543b | |
![]() |
4433fb48dc | |
![]() |
c3d3d83b56 | |
![]() |
2e6619f3d0 | |
![]() |
f665dda192 | |
![]() |
af39179446 | |
![]() |
359f36d6ab | |
![]() |
3b67edf20d | |
![]() |
72c391ebc8 | |
![]() |
09f97c8037 | |
![]() |
b98607c689 | |
![]() |
4f8c941bff | |
![]() |
2d71d7cada | |
![]() |
0ddcc85f68 | |
![]() |
1f74e9a5c5 | |
![]() |
e00a26d72d | |
![]() |
1fd5a6555e | |
![]() |
4f512c6571 | |
![]() |
faab23e914 | |
![]() |
3353ed87ef | |
![]() |
3572e6f0e7 | |
![]() |
c1e09f65c9 | |
![]() |
20bee00681 | |
![]() |
7d1db53f6b | |
![]() |
d8012cf00c | |
![]() |
24168aebdb | |
![]() |
2a07aa238f | |
![]() |
b08a4a1896 | |
![]() |
427ce522a2 | |
![]() |
d4a3d6689e | |
![]() |
56fc8f83ac | |
![]() |
a89d1f8058 | |
![]() |
c59f385996 | |
![]() |
1c15a6dd88 | |
![]() |
260bc0a61d | |
![]() |
451b878bb9 | |
![]() |
36222adb25 | |
![]() |
571e4026ac | |
![]() |
c314705d53 | |
![]() |
bc58d13ee8 | |
![]() |
a879c59a08 | |
![]() |
bc30ca64dc | |
![]() |
4ab504c994 | |
![]() |
68f1570d45 | |
![]() |
3a5ba58a45 | |
![]() |
18ba622c40 | |
![]() |
e427ad73aa | |
![]() |
4d3779f061 | |
![]() |
a05a6d8727 | |
![]() |
66b1462cf8 | |
![]() |
61699e9ed3 | |
![]() |
3f1e57de1c |
|
@ -81,3 +81,6 @@ AllowShortLambdasOnASingleLine: Empty
|
|||
|
||||
# We do not want clang-format to put all arguments on a new line
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
|
||||
# Indent lambdas to the start of the line, not to the start of the lambda
|
||||
LambdaBodyIndentation: OuterScope
|
||||
|
|
|
@ -25,3 +25,4 @@ CMakeLists.txt.user*
|
|||
.idea
|
||||
/cmake-build*
|
||||
.cache
|
||||
.directory
|
||||
|
|
|
@ -7,8 +7,8 @@ include:
|
|||
- /gitlab-templates/linux-qt6.yml
|
||||
- /gitlab-templates/freebsd-qt6.yml
|
||||
|
||||
suse_tumbleweed_qt66_reduced_featureset:
|
||||
extends: suse_tumbleweed_qt66
|
||||
suse_tumbleweed_qt67_reduced_featureset:
|
||||
extends: suse_tumbleweed_qt67
|
||||
script:
|
||||
- git config --global --add safe.directory $CI_PROJECT_DIR
|
||||
- python3 -u ci-utilities/run-ci-build.py --project $CI_PROJECT_NAME --branch $CI_COMMIT_REF_NAME --platform Linux --extra-cmake-args="-DKWIN_BUILD_KCMS=OFF -DKWIN_BUILD_SCREENLOCKER=OFF -DKWIN_BUILD_TABBOX=OFF -DKWIN_BUILD_ACTIVITIES=OFF -DKWIN_BUILD_RUNNERS=OFF -DKWIN_BUILD_NOTIFICATIONS=OFF -DKWIN_BUILD_GLOBALSHORTCUTS=OFF" --skip-publishing
|
||||
- python3 -u ci-utilities/run-ci-build.py --project $CI_PROJECT_NAME --branch $CI_COMMIT_REF_NAME --platform Linux --extra-cmake-args="-DKWIN_BUILD_KCMS=OFF -DKWIN_BUILD_SCREENLOCKER=OFF -DKWIN_BUILD_TABBOX=OFF -DKWIN_BUILD_ACTIVITIES=OFF -DKWIN_BUILD_RUNNERS=OFF -DKWIN_BUILD_NOTIFICATIONS=OFF -DKWIN_BUILD_GLOBALSHORTCUTS=OFF -DKWIN_BUILD_X11=OFF -DKWIN_BUILD_EIS=OFF" --skip-publishing
|
||||
|
|
206
CMakeLists.txt
|
@ -1,14 +1,15 @@
|
|||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(PROJECT_VERSION "5.92.0") # Handled by release scripts
|
||||
set(PROJECT_VERSION "6.1.80") # Handled by release scripts
|
||||
project(KWin VERSION ${PROJECT_VERSION})
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(PROJECT_DEP_VERSION "6.1.1")
|
||||
set(QT_MIN_VERSION "6.6.0")
|
||||
set(KF6_MIN_VERSION "5.240.0")
|
||||
set(KF6_MIN_VERSION "6.2.0")
|
||||
set(KDE_COMPILERSETTINGS_LEVEL "5.82")
|
||||
|
||||
find_package(ECM ${KF6_MIN_VERSION} REQUIRED NO_MODULE)
|
||||
|
@ -47,6 +48,9 @@ option(KWIN_BUILD_KCMS "Enable building of KWin configuration modules." ON)
|
|||
option(KWIN_BUILD_NOTIFICATIONS "Enable building of KWin with knotifications support" ON)
|
||||
option(KWIN_BUILD_SCREENLOCKER "Enable building of KWin lockscreen functionality" ON)
|
||||
option(KWIN_BUILD_TABBOX "Enable building of KWin Tabbox functionality" ON)
|
||||
option(KWIN_BUILD_X11 "Enable building kwin_x11 and Xwayland support" ON)
|
||||
option(KWIN_BUILD_GLOBALSHORTCUTS "Enable building of KWin with global shortcuts support" ON)
|
||||
option(KWIN_BUILD_RUNNERS "Enable building of KWin with krunner support" ON)
|
||||
|
||||
find_package(Qt6 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
|
||||
Concurrent
|
||||
|
@ -77,6 +81,7 @@ endif()
|
|||
# required frameworks by Core
|
||||
find_package(KF6 ${KF6_MIN_VERSION} REQUIRED COMPONENTS
|
||||
Auth
|
||||
ColorScheme
|
||||
Config
|
||||
ConfigWidgets
|
||||
CoreAddons
|
||||
|
@ -109,14 +114,14 @@ set_package_properties(Threads PROPERTIES
|
|||
TYPE REQUIRED
|
||||
)
|
||||
|
||||
find_package(KWayland ${PROJECT_VERSION} CONFIG)
|
||||
find_package(KWayland ${PROJECT_DEP_VERSION} CONFIG)
|
||||
set_package_properties(KWayland PROPERTIES
|
||||
PURPOSE "Required to build wayland platform plugin and tests"
|
||||
TYPE REQUIRED
|
||||
)
|
||||
|
||||
# optional frameworks
|
||||
find_package(PlasmaActivities ${PROJECT_VERSION} CONFIG)
|
||||
find_package(PlasmaActivities ${PROJECT_DEP_VERSION} CONFIG)
|
||||
set_package_properties(PlasmaActivities PROPERTIES
|
||||
PURPOSE "Enable building of KWin with kactivities support"
|
||||
TYPE OPTIONAL
|
||||
|
@ -130,20 +135,20 @@ set_package_properties(KF6DocTools PROPERTIES
|
|||
)
|
||||
add_feature_info("KF6DocTools" KF6DocTools_FOUND "Enable building documentation")
|
||||
|
||||
find_package(KF6Kirigami2 ${KF6_MIN_VERSION} CONFIG)
|
||||
set_package_properties(KF6Kirigami2 PROPERTIES
|
||||
find_package(KF6Kirigami ${KF6_MIN_VERSION} CONFIG)
|
||||
set_package_properties(KF6Kirigami PROPERTIES
|
||||
DESCRIPTION "A QtQuick based components set"
|
||||
PURPOSE "Required at runtime for several QML effects"
|
||||
TYPE RUNTIME
|
||||
)
|
||||
find_package(Plasma ${PROJECT_VERSION} CONFIG)
|
||||
find_package(Plasma ${PROJECT_DEP_VERSION} CONFIG)
|
||||
set_package_properties(Plasma PROPERTIES
|
||||
DESCRIPTION "A QtQuick based components set"
|
||||
PURPOSE "Required at runtime for several QML effects"
|
||||
TYPE RUNTIME
|
||||
)
|
||||
|
||||
find_package(KDecoration2 ${PROJECT_VERSION} CONFIG)
|
||||
find_package(KDecoration2 ${PROJECT_DEP_VERSION} CONFIG)
|
||||
set_package_properties(KDecoration2 PROPERTIES
|
||||
TYPE REQUIRED
|
||||
PURPOSE "Required for server side decoration support"
|
||||
|
@ -187,33 +192,25 @@ if (epoxy_HAS_GLX)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main() {
|
||||
const int size = 10;
|
||||
int fd = memfd_create(\"test\", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
||||
ftruncate(fd, size);
|
||||
fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
|
||||
mmap(nullptr, size, PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
}" HAVE_MEMFD)
|
||||
|
||||
find_package(Wayland 1.22)
|
||||
set_package_properties(Wayland PROPERTIES
|
||||
TYPE REQUIRED
|
||||
PURPOSE "Required for building KWin with Wayland support"
|
||||
)
|
||||
if (Wayland_VERSION VERSION_GREATER_EQUAL 1.23)
|
||||
set(HAVE_WL_DISPLAY_SET_DEFAULT_MAX_BUFFER_SIZE 1)
|
||||
else()
|
||||
set(HAVE_WL_DISPLAY_SET_DEFAULT_MAX_BUFFER_SIZE 0)
|
||||
endif()
|
||||
|
||||
find_package(WaylandProtocols 1.32)
|
||||
find_package(WaylandProtocols 1.34)
|
||||
set_package_properties(WaylandProtocols PROPERTIES
|
||||
TYPE REQUIRED
|
||||
PURPOSE "Collection of Wayland protocols that add functionality not available in the Wayland core protocol"
|
||||
URL "https://gitlab.freedesktop.org/wayland/wayland-protocols/"
|
||||
)
|
||||
|
||||
find_package(PlasmaWaylandProtocols 1.9.0 CONFIG)
|
||||
find_package(PlasmaWaylandProtocols 1.13.0 CONFIG)
|
||||
set_package_properties(PlasmaWaylandProtocols PROPERTIES
|
||||
TYPE REQUIRED
|
||||
PURPOSE "Collection of Plasma-specific Wayland protocols"
|
||||
|
@ -231,12 +228,67 @@ else()
|
|||
set(HAVE_XKBCOMMON_NO_SECURE_GETENV 0)
|
||||
endif()
|
||||
|
||||
pkg_check_modules(XKBX11 IMPORTED_TARGET xkbcommon-x11 REQUIRED)
|
||||
add_feature_info(XKBX11 XKBX11_FOUND "Required for handling keyboard events in X11 backend")
|
||||
if (KWIN_BUILD_X11)
|
||||
pkg_check_modules(XKBX11 IMPORTED_TARGET xkbcommon-x11 REQUIRED)
|
||||
add_feature_info(XKBX11 XKBX11_FOUND "Required for handling keyboard events in X11 backend")
|
||||
|
||||
# All the required XCB components
|
||||
find_package(XCB 1.10 REQUIRED COMPONENTS
|
||||
COMPOSITE
|
||||
CURSOR
|
||||
DAMAGE
|
||||
DRI3
|
||||
GLX
|
||||
ICCCM
|
||||
IMAGE
|
||||
KEYSYMS
|
||||
PRESENT
|
||||
RANDR
|
||||
RENDER
|
||||
SHAPE
|
||||
SHM
|
||||
SYNC
|
||||
XCB
|
||||
XFIXES
|
||||
XKB
|
||||
XINERAMA
|
||||
XINPUT
|
||||
)
|
||||
set_package_properties(XCB PROPERTIES TYPE REQUIRED)
|
||||
|
||||
find_package(X11_XCB)
|
||||
set_package_properties(X11_XCB PROPERTIES
|
||||
PURPOSE "Required for building X11 windowed backend of kwin_wayland"
|
||||
TYPE OPTIONAL
|
||||
)
|
||||
|
||||
find_package(Xwayland)
|
||||
set_package_properties(Xwayland PROPERTIES
|
||||
URL "https://x.org"
|
||||
DESCRIPTION "Xwayland X server"
|
||||
TYPE RUNTIME
|
||||
PURPOSE "Needed for running kwin_wayland"
|
||||
)
|
||||
set(HAVE_XWAYLAND_LISTENFD ${Xwayland_HAVE_LISTENFD})
|
||||
set(HAVE_XWAYLAND_ENABLE_EI_PORTAL ${Xwayland_HAVE_ENABLE_EI_PORTAL})
|
||||
|
||||
set(HAVE_GLX ${epoxy_HAS_GLX})
|
||||
get_target_property(QT_DISABLED_FEATURES Qt6::Gui QT_DISABLED_PUBLIC_FEATURES)
|
||||
if("xcb_glx_plugin" IN_LIST QT_DISABLED_FEATURES)
|
||||
message(STATUS "Disable GLX because Qt6::Gui was built without xcb_glx_plugin")
|
||||
set(HAVE_GLX false)
|
||||
endif()
|
||||
|
||||
# for kwin internal things
|
||||
set(HAVE_X11_XCB ${X11_XCB_FOUND})
|
||||
endif()
|
||||
|
||||
find_package(Libinput 1.19)
|
||||
set_package_properties(Libinput PROPERTIES TYPE REQUIRED PURPOSE "Required for input handling on Wayland.")
|
||||
|
||||
find_package(Libeis-1.0)
|
||||
set_package_properties(Libeis PROPERTIES TYPE OPTIONAL PURPOSE "Required for emulated input handling.")
|
||||
|
||||
find_package(UDev)
|
||||
set_package_properties(UDev PROPERTIES
|
||||
URL "https://www.freedesktop.org/wiki/Software/systemd/"
|
||||
|
@ -245,7 +297,7 @@ set_package_properties(UDev PROPERTIES
|
|||
PURPOSE "Required for input handling on Wayland."
|
||||
)
|
||||
|
||||
find_package(Libdrm 2.4.112)
|
||||
find_package(Libdrm 2.4.116)
|
||||
set_package_properties(Libdrm PROPERTIES TYPE REQUIRED PURPOSE "Required for drm output on Wayland.")
|
||||
|
||||
find_package(gbm)
|
||||
|
@ -281,35 +333,6 @@ set_package_properties(lcms2 PROPERTIES
|
|||
PURPOSE "Required for the color management system"
|
||||
)
|
||||
|
||||
# All the required XCB components
|
||||
find_package(XCB 1.10 REQUIRED COMPONENTS
|
||||
COMPOSITE
|
||||
CURSOR
|
||||
DAMAGE
|
||||
DRI3
|
||||
GLX
|
||||
ICCCM
|
||||
IMAGE
|
||||
KEYSYMS
|
||||
PRESENT
|
||||
RANDR
|
||||
RENDER
|
||||
SHAPE
|
||||
SHM
|
||||
SYNC
|
||||
XCB
|
||||
XFIXES
|
||||
XKB
|
||||
XINERAMA
|
||||
)
|
||||
set_package_properties(XCB PROPERTIES TYPE REQUIRED)
|
||||
|
||||
find_package(X11_XCB)
|
||||
set_package_properties(X11_XCB PROPERTIES
|
||||
PURPOSE "Required for building X11 windowed backend of kwin_wayland"
|
||||
TYPE OPTIONAL
|
||||
)
|
||||
|
||||
find_package(Freetype)
|
||||
set_package_properties(Freetype PROPERTIES
|
||||
DESCRIPTION "A font rendering engine"
|
||||
|
@ -323,15 +346,6 @@ set_package_properties(Fontconfig PROPERTIES
|
|||
PURPOSE "Needed for KWin's QPA plugin."
|
||||
)
|
||||
|
||||
find_package(Xwayland)
|
||||
set_package_properties(Xwayland PROPERTIES
|
||||
URL "https://x.org"
|
||||
DESCRIPTION "Xwayland X server"
|
||||
TYPE RUNTIME
|
||||
PURPOSE "Needed for running kwin_wayland"
|
||||
)
|
||||
set(HAVE_XWAYLAND_LISTENFD ${Xwayland_HAVE_LISTENFD})
|
||||
|
||||
find_package(Libcap)
|
||||
set_package_properties(Libcap PROPERTIES
|
||||
TYPE OPTIONAL
|
||||
|
@ -355,45 +369,19 @@ set_package_properties(QAccessibilityClient6 PROPERTIES
|
|||
)
|
||||
set(HAVE_ACCESSIBILITY ${QAccessibilityClient6_FOUND})
|
||||
|
||||
option(KWIN_BUILD_GLOBALSHORTCUTS "Enable building of KWin with global shortcuts support" ON)
|
||||
pkg_check_modules(libsystemd IMPORTED_TARGET libsystemd)
|
||||
add_feature_info(libsystemd libsystemd_FOUND "Required for setting up the service watchdog")
|
||||
|
||||
if(KWIN_BUILD_GLOBALSHORTCUTS)
|
||||
find_package(KGlobalAccelD REQUIRED)
|
||||
endif()
|
||||
|
||||
pkg_check_modules(libdisplayinfo IMPORTED_TARGET display-info)
|
||||
if (NOT libdisplayinfo_FOUND)
|
||||
pkg_check_modules(libdisplayinfo REQUIRED IMPORTED_TARGET libdisplay-info)
|
||||
endif()
|
||||
add_feature_info(libdisplayinfo libdisplayinfo_FOUND "EDID and DisplayID library: https://gitlab.freedesktop.org/emersion/libdisplay-info")
|
||||
|
||||
ecm_find_qmlmodule(QtQuick 2.3)
|
||||
ecm_find_qmlmodule(QtQuick.Controls 2.15)
|
||||
ecm_find_qmlmodule(QtQuick.Layouts 1.3)
|
||||
ecm_find_qmlmodule(QtQuick.Window 2.1)
|
||||
ecm_find_qmlmodule(QtMultimedia 5.0)
|
||||
ecm_find_qmlmodule(org.kde.kquickcontrolsaddons 2.0)
|
||||
ecm_find_qmlmodule(org.kde.plasma.core 2.0)
|
||||
ecm_find_qmlmodule(org.kde.plasma.components 2.0)
|
||||
|
||||
########### configure tests ###############
|
||||
cmake_dependent_option(KWIN_BUILD_ACTIVITIES "Enable building of KWin with kactivities support" ON "PlasmaActivities_FOUND" OFF)
|
||||
option(KWIN_BUILD_RUNNERS "Enable building of KWin with krunner support" ON)
|
||||
|
||||
set(HAVE_GLX ${epoxy_HAS_GLX})
|
||||
get_target_property(QT_DISABLED_FEATURES Qt6::Gui QT_DISABLED_PUBLIC_FEATURES)
|
||||
if("xcb_glx_plugin" IN_LIST QT_DISABLED_FEATURES)
|
||||
message(STATUS "Disable GLX because Qt6::Gui was built without xcb_glx_plugin")
|
||||
set(HAVE_GLX false)
|
||||
endif()
|
||||
|
||||
# for kwin internal things
|
||||
set(HAVE_X11_XCB ${X11_XCB_FOUND})
|
||||
|
||||
check_symbol_exists(SCHED_RESET_ON_FORK "sched.h" HAVE_SCHED_RESET_ON_FORK)
|
||||
add_feature_info("SCHED_RESET_ON_FORK"
|
||||
HAVE_SCHED_RESET_ON_FORK
|
||||
"Required for running kwin_wayland with real-time scheduling")
|
||||
|
||||
|
||||
pkg_check_modules(PipeWire IMPORTED_TARGET libpipewire-0.3>=0.3.29)
|
||||
add_feature_info(PipeWire PipeWire_FOUND "Required for Wayland screencasting")
|
||||
|
||||
|
@ -409,7 +397,17 @@ if (KWIN_BUILD_SCREENLOCKER)
|
|||
)
|
||||
endif()
|
||||
|
||||
########### global ###############
|
||||
ecm_find_qmlmodule(QtQuick 2.3)
|
||||
ecm_find_qmlmodule(QtQuick.Controls 2.15)
|
||||
ecm_find_qmlmodule(QtQuick.Layouts 1.3)
|
||||
ecm_find_qmlmodule(QtQuick.Window 2.1)
|
||||
ecm_find_qmlmodule(QtMultimedia 5.0)
|
||||
ecm_find_qmlmodule(org.kde.kquickcontrolsaddons 2.0)
|
||||
ecm_find_qmlmodule(org.kde.plasma.core 2.0)
|
||||
ecm_find_qmlmodule(org.kde.plasma.components 2.0)
|
||||
|
||||
cmake_dependent_option(KWIN_BUILD_ACTIVITIES "Enable building of KWin with kactivities support" ON "PlasmaActivities_FOUND" OFF)
|
||||
cmake_dependent_option(KWIN_BUILD_EIS "Enable building KWin with libeis support" ON "Libeis-1.0_FOUND" OFF)
|
||||
|
||||
include_directories(BEFORE
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src/wayland
|
||||
|
@ -417,6 +415,24 @@ include_directories(BEFORE
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
check_symbol_exists(SCHED_RESET_ON_FORK "sched.h" HAVE_SCHED_RESET_ON_FORK)
|
||||
add_feature_info("SCHED_RESET_ON_FORK"
|
||||
HAVE_SCHED_RESET_ON_FORK
|
||||
"Required for running kwin_wayland with real-time scheduling")
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main() {
|
||||
const int size = 10;
|
||||
int fd = memfd_create(\"test\", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
||||
ftruncate(fd, size);
|
||||
fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
|
||||
mmap(nullptr, size, PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
}" HAVE_MEMFD)
|
||||
|
||||
check_cxx_compiler_flag(-Wno-unused-parameter COMPILER_UNUSED_PARAMETER_SUPPORTED)
|
||||
if (COMPILER_UNUSED_PARAMETER_SUPPORTED)
|
||||
add_compile_options(-Wno-unused-parameter)
|
||||
|
|
|
@ -27,9 +27,9 @@ The Breeze decorations theme is not located in the KWin repository, and is in fa
|
|||
|
||||
### Tab Switcher
|
||||
|
||||
The default visual appearance of the tab switcher is not located in the KWin repository, and is in fact part of [Plasma Workspace](https://invent.kde.org/plasma/plasma-workspace), located at `lookandfeel/contents/windowswitcher`.
|
||||
The default visual appearance of the tab switcher is located in `src/tabbox/switchers`.
|
||||
|
||||
Other window switchers usually shipped by default are located in [Plasma Addons](https://invent.kde.org/plasma/kdeplasma-addons), located in the `windowswitchers` directory.
|
||||
Other window switchers usually shipped by default are located in [Plasma Addons](https://invent.kde.org/plasma/kdeplasma-addons), located in the `kwin/windowswitchers` directory.
|
||||
|
||||
### Window Management
|
||||
|
||||
|
@ -53,7 +53,7 @@ Other scripting stuff is located in `src/scripting`.
|
|||
|
||||
KWin's coding conventions are located [here](doc/coding-conventions.md).
|
||||
|
||||
KWin additionally follows [KDE's Frameworks Coding Style]((https://techbase.kde.org/Policies/Frameworks_Coding_Style)).
|
||||
KWin additionally follows [KDE's Frameworks Coding Style](https://community.kde.org/Policies/Frameworks_Coding_Style).
|
||||
|
||||
### Commits
|
||||
|
||||
|
|
|
@ -6,5 +6,5 @@ set(KWIN_EFFECTS_INTERFACE "@PACKAGE_KDE_INSTALL_DBUSINTERFACEDIR@/org.kde.kwin.
|
|||
set(KWIN_VIRTUALKEYBOARD_INTERFACE "@PACKAGE_KDE_INSTALL_DBUSINTERFACEDIR@/org.kde.kwin.VirtualKeyboard.xml")
|
||||
set(KWIN_TABLETMODE_INTERFACE "@PACKAGE_KDE_INSTALL_DBUSINTERFACEDIR@/org.kde.KWin.TabletModeManager.xml")
|
||||
set(KWIN_INPUTDEVICE_INTERFACE "@PACKAGE_KDE_INSTALL_DBUSINTERFACEDIR@/org.kde.kwin.InputDevice.xml")
|
||||
set(KWIN_COLORCORRECT_INTERFACE "@PACKAGE_KDE_INSTALL_DBUSINTERFACEDIR@/org.kde.kwin.ColorCorrect.xml")
|
||||
set(KWIN_NIGHTLIGHT_INTERFACE "@PACKAGE_KDE_INSTALL_DBUSINTERFACEDIR@/org.kde.KWin.NightLight.xml")
|
||||
set(KWIN_WAYLAND_BIN_PATH "@CMAKE_INSTALL_FULL_BINDIR@/kwin_wayland")
|
||||
|
|
|
@ -45,82 +45,97 @@ ecm_mark_as_test(testVirtualDesktops)
|
|||
########################################################
|
||||
# Test ClientMachine
|
||||
########################################################
|
||||
set(testClientMachine_SRCS
|
||||
../src/client_machine.cpp
|
||||
test_client_machine.cpp
|
||||
xcb_scaling_mock.cpp
|
||||
)
|
||||
add_executable(testClientMachine ${testClientMachine_SRCS})
|
||||
set_target_properties(testClientMachine PROPERTIES COMPILE_DEFINITIONS "NO_NONE_WINDOW")
|
||||
if(KWIN_BUILD_X11)
|
||||
set(testClientMachine_SRCS
|
||||
../src/client_machine.cpp
|
||||
test_client_machine.cpp
|
||||
xcb_scaling_mock.cpp
|
||||
)
|
||||
add_executable(testClientMachine ${testClientMachine_SRCS})
|
||||
set_target_properties(testClientMachine PROPERTIES COMPILE_DEFINITIONS "NO_NONE_WINDOW")
|
||||
|
||||
target_link_libraries(testClientMachine
|
||||
Qt::Concurrent
|
||||
Qt::GuiPrivate
|
||||
Qt::Test
|
||||
Qt::Widgets
|
||||
target_link_libraries(testClientMachine
|
||||
Qt::Concurrent
|
||||
Qt::GuiPrivate
|
||||
Qt::Test
|
||||
Qt::Widgets
|
||||
|
||||
KF6::ConfigCore
|
||||
KF6::WindowSystem
|
||||
KF6::ConfigCore
|
||||
KF6::WindowSystem
|
||||
|
||||
XCB::XCB
|
||||
XCB::XFIXES
|
||||
XCB::XCB
|
||||
XCB::XFIXES
|
||||
|
||||
${X11_X11_LIB} # to make jenkins happy
|
||||
)
|
||||
add_test(NAME kwin-testClientMachine COMMAND testClientMachine)
|
||||
ecm_mark_as_test(testClientMachine)
|
||||
${X11_X11_LIB} # to make jenkins happy
|
||||
)
|
||||
add_test(NAME kwin-testClientMachine COMMAND testClientMachine)
|
||||
ecm_mark_as_test(testClientMachine)
|
||||
|
||||
########################################################
|
||||
# Test XcbWrapper
|
||||
########################################################
|
||||
add_executable(testXcbWrapper test_xcb_wrapper.cpp xcb_scaling_mock.cpp)
|
||||
########################################################
|
||||
# Test XcbWrapper
|
||||
########################################################
|
||||
add_executable(testXcbWrapper test_xcb_wrapper.cpp xcb_scaling_mock.cpp)
|
||||
|
||||
target_link_libraries(testXcbWrapper
|
||||
Qt::GuiPrivate
|
||||
Qt::Test
|
||||
Qt::Widgets
|
||||
target_link_libraries(testXcbWrapper
|
||||
Qt::GuiPrivate
|
||||
Qt::Test
|
||||
Qt::Widgets
|
||||
|
||||
KF6::ConfigCore
|
||||
KF6::WindowSystem
|
||||
KF6::ConfigCore
|
||||
KF6::WindowSystem
|
||||
|
||||
XCB::XCB
|
||||
)
|
||||
add_test(NAME kwin-testXcbWrapper COMMAND testXcbWrapper)
|
||||
ecm_mark_as_test(testXcbWrapper)
|
||||
XCB::XCB
|
||||
)
|
||||
add_test(NAME kwin-testXcbWrapper COMMAND testXcbWrapper)
|
||||
ecm_mark_as_test(testXcbWrapper)
|
||||
|
||||
add_executable(testXcbSizeHints test_xcb_size_hints.cpp xcb_scaling_mock.cpp)
|
||||
set_target_properties(testXcbSizeHints PROPERTIES COMPILE_DEFINITIONS "NO_NONE_WINDOW")
|
||||
target_link_libraries(testXcbSizeHints
|
||||
Qt::GuiPrivate
|
||||
Qt::Test
|
||||
Qt::Widgets
|
||||
add_executable(testXcbSizeHints test_xcb_size_hints.cpp xcb_scaling_mock.cpp)
|
||||
set_target_properties(testXcbSizeHints PROPERTIES COMPILE_DEFINITIONS "NO_NONE_WINDOW")
|
||||
target_link_libraries(testXcbSizeHints
|
||||
Qt::GuiPrivate
|
||||
Qt::Test
|
||||
Qt::Widgets
|
||||
|
||||
KF6::ConfigCore
|
||||
KF6::WindowSystem
|
||||
KF6::ConfigCore
|
||||
KF6::WindowSystem
|
||||
|
||||
XCB::ICCCM
|
||||
XCB::XCB
|
||||
)
|
||||
add_test(NAME kwin-testXcbSizeHints COMMAND testXcbSizeHints)
|
||||
ecm_mark_as_test(testXcbSizeHints)
|
||||
XCB::ICCCM
|
||||
XCB::XCB
|
||||
)
|
||||
add_test(NAME kwin-testXcbSizeHints COMMAND testXcbSizeHints)
|
||||
ecm_mark_as_test(testXcbSizeHints)
|
||||
|
||||
########################################################
|
||||
# Test XcbWindow
|
||||
########################################################
|
||||
add_executable(testXcbWindow test_xcb_window.cpp xcb_scaling_mock.cpp)
|
||||
########################################################
|
||||
# Test XcbWindow
|
||||
########################################################
|
||||
add_executable(testXcbWindow test_xcb_window.cpp xcb_scaling_mock.cpp)
|
||||
|
||||
target_link_libraries(testXcbWindow
|
||||
Qt::GuiPrivate
|
||||
Qt::Test
|
||||
Qt::Widgets
|
||||
target_link_libraries(testXcbWindow
|
||||
Qt::GuiPrivate
|
||||
Qt::Test
|
||||
Qt::Widgets
|
||||
|
||||
KF6::ConfigCore
|
||||
KF6::WindowSystem
|
||||
KF6::ConfigCore
|
||||
KF6::WindowSystem
|
||||
|
||||
XCB::XCB
|
||||
)
|
||||
add_test(NAME kwin-testXcbWindow COMMAND testXcbWindow)
|
||||
ecm_mark_as_test(testXcbWindow)
|
||||
XCB::XCB
|
||||
)
|
||||
add_test(NAME kwin-testXcbWindow COMMAND testXcbWindow)
|
||||
ecm_mark_as_test(testXcbWindow)
|
||||
|
||||
########################################################
|
||||
# Test X11 TimestampUpdate
|
||||
########################################################
|
||||
add_executable(testX11TimestampUpdate test_x11_timestamp_update.cpp)
|
||||
target_link_libraries(testX11TimestampUpdate
|
||||
KF6::CoreAddons
|
||||
Qt::Test
|
||||
Qt::GuiPrivate
|
||||
kwin
|
||||
)
|
||||
add_test(NAME kwin-testX11TimestampUpdate COMMAND testX11TimestampUpdate)
|
||||
ecm_mark_as_test(testX11TimestampUpdate)
|
||||
endif()
|
||||
|
||||
########################################################
|
||||
# Test OnScreenNotification
|
||||
|
@ -161,19 +176,6 @@ target_link_libraries(testGestures
|
|||
add_test(NAME kwin-testGestures COMMAND testGestures)
|
||||
ecm_mark_as_test(testGestures)
|
||||
|
||||
########################################################
|
||||
# Test X11 TimestampUpdate
|
||||
########################################################
|
||||
add_executable(testX11TimestampUpdate test_x11_timestamp_update.cpp)
|
||||
target_link_libraries(testX11TimestampUpdate
|
||||
KF6::CoreAddons
|
||||
Qt::Test
|
||||
Qt::GuiPrivate
|
||||
kwin
|
||||
)
|
||||
add_test(NAME kwin-testX11TimestampUpdate COMMAND testX11TimestampUpdate)
|
||||
ecm_mark_as_test(testX11TimestampUpdate)
|
||||
|
||||
set(testOpenGLContextAttributeBuilder_SRCS
|
||||
../src/opengl/abstract_opengl_context_attribute_builder.cpp
|
||||
../src/opengl/egl_context_attribute_builder.cpp
|
||||
|
|
|
@ -8,9 +8,7 @@ set(mockDRM_SRCS
|
|||
../../src/backends/drm/drm_commit_thread.cpp
|
||||
../../src/backends/drm/drm_connector.cpp
|
||||
../../src/backends/drm/drm_crtc.cpp
|
||||
../../src/backends/drm/drm_dmabuf_feedback.cpp
|
||||
../../src/backends/drm/drm_egl_backend.cpp
|
||||
../../src/backends/drm/drm_egl_cursor_layer.cpp
|
||||
../../src/backends/drm/drm_egl_layer.cpp
|
||||
../../src/backends/drm/drm_egl_layer_surface.cpp
|
||||
../../src/backends/drm/drm_gpu.cpp
|
||||
|
@ -39,7 +37,6 @@ target_link_libraries(LibDrmTest
|
|||
KF6::WindowSystem
|
||||
KF6::CoreAddons
|
||||
KF6::I18n
|
||||
XCB::XCB
|
||||
PkgConfig::Libxcvt
|
||||
gbm::gbm
|
||||
Libdrm::Libdrm
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <QSignalSpy>
|
||||
#include <QSize>
|
||||
#include <QTest>
|
||||
|
||||
|
@ -70,6 +71,7 @@ private Q_SLOTS:
|
|||
void testConnectorLifetime();
|
||||
void testModeset_data();
|
||||
void testModeset();
|
||||
void testVrrChange();
|
||||
};
|
||||
|
||||
static void verifyCleanup(MockGpu *mockGpu)
|
||||
|
@ -93,7 +95,7 @@ void DrmTest::testAmsDetection()
|
|||
// gpu without planes should use legacy mode
|
||||
{
|
||||
const auto mockGpu = findPrimaryDevice(0);
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->devNode, mockGpu->fd, 0);
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->fd, DrmDevice::open(mockGpu->devNode));
|
||||
QVERIFY(!gpu->atomicModeSetting());
|
||||
}
|
||||
|
||||
|
@ -101,8 +103,8 @@ void DrmTest::testAmsDetection()
|
|||
{
|
||||
const auto mockGpu = findPrimaryDevice(0);
|
||||
mockGpu->planes << std::make_shared<MockPlane>(mockGpu.get(), PlaneType::Primary, 0);
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->devNode, mockGpu->fd, 0);
|
||||
gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->devNode, mockGpu->fd, 0);
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->fd, DrmDevice::open(mockGpu->devNode));
|
||||
gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->fd, DrmDevice::open(mockGpu->devNode));
|
||||
QVERIFY(gpu->atomicModeSetting());
|
||||
}
|
||||
|
||||
|
@ -110,7 +112,7 @@ void DrmTest::testAmsDetection()
|
|||
{
|
||||
const auto mockGpu = findPrimaryDevice(0);
|
||||
mockGpu->deviceCaps[MOCKDRM_DEVICE_CAP_ATOMIC] = 0;
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->devNode, mockGpu->fd, 0);
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->fd, DrmDevice::open(mockGpu->devNode));
|
||||
QVERIFY(!gpu->atomicModeSetting());
|
||||
gpu.reset();
|
||||
verifyCleanup(mockGpu.get());
|
||||
|
@ -131,7 +133,7 @@ void DrmTest::testOutputDetection()
|
|||
const auto session = Session::create(Session::Type::Noop);
|
||||
const auto backend = std::make_unique<DrmBackend>(session.get());
|
||||
const auto renderBackend = backend->createQPainterBackend();
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->devNode, mockGpu->fd, 0);
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->fd, DrmDevice::open(mockGpu->devNode));
|
||||
QVERIFY(gpu->updateOutputs());
|
||||
|
||||
// 3 outputs should be detected, one of them non-desktop
|
||||
|
@ -178,7 +180,7 @@ void DrmTest::testZeroModesHandling()
|
|||
const auto session = Session::create(Session::Type::Noop);
|
||||
const auto backend = std::make_unique<DrmBackend>(session.get());
|
||||
const auto renderBackend = backend->createQPainterBackend();
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->devNode, mockGpu->fd, 0);
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->fd, DrmDevice::open(mockGpu->devNode));
|
||||
|
||||
// connector with zero modes should be ignored
|
||||
conn->modes.clear();
|
||||
|
@ -295,7 +297,7 @@ void DrmTest::testModeGeneration()
|
|||
const auto session = Session::create(Session::Type::Noop);
|
||||
const auto backend = std::make_unique<DrmBackend>(session.get());
|
||||
const auto renderBackend = backend->createQPainterBackend();
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->devNode, mockGpu->fd, 0);
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->fd, DrmDevice::open(mockGpu->devNode));
|
||||
|
||||
QFETCH(QSize, nativeMode);
|
||||
QFETCH(QList<QSize>, expectedModes);
|
||||
|
@ -338,7 +340,7 @@ void DrmTest::testConnectorLifetime()
|
|||
const auto session = Session::create(Session::Type::Noop);
|
||||
const auto backend = std::make_unique<DrmBackend>(session.get());
|
||||
const auto renderBackend = backend->createQPainterBackend();
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->devNode, mockGpu->fd, 0);
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->fd, DrmDevice::open(mockGpu->devNode));
|
||||
|
||||
QVERIFY(gpu->updateOutputs());
|
||||
QCOMPARE(gpu->drmOutputs().size(), 1);
|
||||
|
@ -364,6 +366,8 @@ void DrmTest::testModeset_data()
|
|||
|
||||
void DrmTest::testModeset()
|
||||
{
|
||||
// to reenable, make this part of an integration test, so that kwinApp() isn't nullptr
|
||||
QSKIP("this test needs output pipelines to be enabled by default, which is no longer the case");
|
||||
// test if doing a modeset would succeed
|
||||
QFETCH(int, AMS);
|
||||
const auto mockGpu = findPrimaryDevice(5);
|
||||
|
@ -375,7 +379,7 @@ void DrmTest::testModeset()
|
|||
const auto session = Session::create(Session::Type::Noop);
|
||||
const auto backend = std::make_unique<DrmBackend>(session.get());
|
||||
const auto renderBackend = backend->createQPainterBackend();
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->devNode, mockGpu->fd, 0);
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->fd, DrmDevice::open(mockGpu->devNode));
|
||||
|
||||
QVERIFY(gpu->updateOutputs());
|
||||
QCOMPARE(gpu->drmOutputs().size(), 1);
|
||||
|
@ -384,12 +388,40 @@ void DrmTest::testModeset()
|
|||
layer->beginFrame();
|
||||
output->renderLoop()->prepareNewFrame();
|
||||
output->renderLoop()->beginPaint();
|
||||
layer->endFrame(infiniteRegion(), infiniteRegion());
|
||||
QVERIFY(output->present(std::make_shared<OutputFrame>(output->renderLoop())));
|
||||
const auto frame = std::make_shared<OutputFrame>(output->renderLoop(), std::chrono::nanoseconds(1'000'000'000'000 / output->refreshRate()));
|
||||
layer->endFrame(infiniteRegion(), infiniteRegion(), frame.get());
|
||||
QVERIFY(output->present(frame));
|
||||
|
||||
gpu.reset();
|
||||
verifyCleanup(mockGpu.get());
|
||||
}
|
||||
|
||||
void DrmTest::testVrrChange()
|
||||
{
|
||||
const auto mockGpu = findPrimaryDevice(5);
|
||||
mockGpu->deviceCaps[MOCKDRM_DEVICE_CAP_ATOMIC] = 1;
|
||||
|
||||
const auto conn = std::make_shared<MockConnector>(mockGpu.get());
|
||||
conn->setVrrCapable(false);
|
||||
mockGpu->connectors.push_back(conn);
|
||||
|
||||
const auto session = Session::create(Session::Type::Noop);
|
||||
const auto backend = std::make_unique<DrmBackend>(session.get());
|
||||
const auto renderBackend = backend->createQPainterBackend();
|
||||
auto gpu = std::make_unique<DrmGpu>(backend.get(), mockGpu->fd, DrmDevice::open(mockGpu->devNode));
|
||||
|
||||
QVERIFY(gpu->updateOutputs());
|
||||
const auto output = gpu->drmOutputs().front();
|
||||
QVERIFY(!(output->capabilities() & Output::Capability::Vrr));
|
||||
|
||||
QSignalSpy capsChanged(output, &Output::capabilitiesChanged);
|
||||
|
||||
conn->setVrrCapable(true);
|
||||
QVERIFY(gpu->updateOutputs());
|
||||
QCOMPARE(gpu->drmOutputs().front(), output);
|
||||
QCOMPARE(capsChanged.count(), 1);
|
||||
QVERIFY(output->capabilities() & Output::Capability::Vrr);
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(DrmTest)
|
||||
#include "drmTest.moc"
|
||||
|
|
|
@ -212,6 +212,14 @@ void MockConnector::addMode(uint32_t width, uint32_t height, float refreshRate,
|
|||
free(modeInfo);
|
||||
}
|
||||
|
||||
void MockConnector::setVrrCapable(bool cap)
|
||||
{
|
||||
auto &prop = *std::ranges::find_if(props, [](const auto &prop) {
|
||||
return prop.name == "vrr_capable";
|
||||
});
|
||||
prop.value = cap ? 1 : 0;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
MockCrtc::MockCrtc(MockGpu *gpu, const std::shared_ptr<MockPlane> &legacyPlane, int pipeIndex, int gamma_size)
|
||||
|
|
|
@ -71,6 +71,7 @@ public:
|
|||
~MockConnector() = default;
|
||||
|
||||
void addMode(uint32_t width, uint32_t height, float refreshRate, bool preferred = false);
|
||||
void setVrrCapable(bool cap);
|
||||
|
||||
drmModeConnection connection;
|
||||
uint32_t type;
|
||||
|
|
|
@ -14,7 +14,7 @@ kwineffects_unit_tests(
|
|||
timelinetest
|
||||
)
|
||||
|
||||
add_executable(kwinglplatformtest kwinglplatformtest.cpp mock_gl.cpp ../../src/opengl/glplatform.cpp ../../src/opengl/openglcontext.cpp ../../src/utils/version.cpp)
|
||||
add_executable(kwinglplatformtest kwinglplatformtest.cpp ../../src/opengl/glplatform.cpp ../../src/utils/version.cpp)
|
||||
add_test(NAME kwineffects-kwinglplatformtest COMMAND kwinglplatformtest)
|
||||
target_link_libraries(kwinglplatformtest Qt::Test Qt::Gui KF6::ConfigCore XCB::XCB)
|
||||
target_link_libraries(kwinglplatformtest Qt::Test Qt::Gui KF6::ConfigCore)
|
||||
ecm_mark_as_test(kwinglplatformtest)
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "mock_gl.h"
|
||||
#include "opengl/glplatform.h"
|
||||
#include <QTest>
|
||||
|
||||
|
@ -18,33 +17,18 @@ Q_DECLARE_METATYPE(KWin::ChipClass)
|
|||
|
||||
using namespace KWin;
|
||||
|
||||
void KWin::cleanupGL()
|
||||
{
|
||||
GLPlatform::cleanup();
|
||||
}
|
||||
|
||||
class GLPlatformTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private Q_SLOTS:
|
||||
void cleanup();
|
||||
|
||||
void testDriverToString_data();
|
||||
void testDriverToString();
|
||||
void testChipClassToString_data();
|
||||
void testChipClassToString();
|
||||
void testPriorDetect();
|
||||
void testDetect_data();
|
||||
void testDetect();
|
||||
};
|
||||
|
||||
void GLPlatformTest::cleanup()
|
||||
{
|
||||
cleanupGL();
|
||||
delete s_gl;
|
||||
s_gl = nullptr;
|
||||
}
|
||||
|
||||
void GLPlatformTest::testDriverToString_data()
|
||||
{
|
||||
QTest::addColumn<Driver>("driver");
|
||||
|
@ -142,47 +126,6 @@ void GLPlatformTest::testChipClassToString()
|
|||
QTEST(GLPlatform::chipClassToString(chipClass), "expected");
|
||||
}
|
||||
|
||||
void GLPlatformTest::testPriorDetect()
|
||||
{
|
||||
auto *gl = GLPlatform::instance();
|
||||
QVERIFY(gl);
|
||||
QCOMPARE(gl->supports(GLFeature::LooseBinding), false);
|
||||
|
||||
QCOMPARE(gl->glVersion(), Version());
|
||||
QCOMPARE(gl->glslVersion(), Version());
|
||||
QCOMPARE(gl->mesaVersion(), Version());
|
||||
QCOMPARE(gl->driverVersion(), Version());
|
||||
|
||||
QCOMPARE(gl->driver(), Driver_Unknown);
|
||||
QCOMPARE(gl->chipClass(), UnknownChipClass);
|
||||
|
||||
QCOMPARE(gl->isMesaDriver(), false);
|
||||
QCOMPARE(gl->isRadeon(), false);
|
||||
QCOMPARE(gl->isNvidia(), false);
|
||||
QCOMPARE(gl->isIntel(), false);
|
||||
QCOMPARE(gl->isPanfrost(), false);
|
||||
QCOMPARE(gl->isLima(), false);
|
||||
QCOMPARE(gl->isVideoCore4(), false);
|
||||
QCOMPARE(gl->isVideoCore3D(), false);
|
||||
|
||||
QCOMPARE(gl->isVirtualBox(), false);
|
||||
QCOMPARE(gl->isVMware(), false);
|
||||
|
||||
QCOMPARE(gl->isSoftwareEmulation(), false);
|
||||
QCOMPARE(gl->isVirtualMachine(), false);
|
||||
|
||||
QCOMPARE(gl->glVersionString(), QByteArray());
|
||||
QCOMPARE(gl->glRendererString(), QByteArray());
|
||||
QCOMPARE(gl->glVendorString(), QByteArray());
|
||||
QCOMPARE(gl->glShadingLanguageVersionString(), QByteArray());
|
||||
|
||||
QCOMPARE(gl->isLooseBinding(), false);
|
||||
QCOMPARE(gl->isGLES(), false);
|
||||
QCOMPARE(gl->recommendedCompositor(), QPainterCompositing);
|
||||
QCOMPARE(gl->preferBufferSubData(), false);
|
||||
QCOMPARE(gl->platformInterface(), NoOpenGLPlatformInterface);
|
||||
}
|
||||
|
||||
void GLPlatformTest::testDetect_data()
|
||||
{
|
||||
QTest::addColumn<QString>("configFile");
|
||||
|
@ -222,60 +165,50 @@ void GLPlatformTest::testDetect()
|
|||
QFETCH(QString, configFile);
|
||||
KConfig config(configFile);
|
||||
const KConfigGroup driverGroup = config.group(QStringLiteral("Driver"));
|
||||
s_gl = new MockGL;
|
||||
s_gl->getString.vendor = driverGroup.readEntry("Vendor").toUtf8();
|
||||
s_gl->getString.renderer = driverGroup.readEntry("Renderer").toUtf8();
|
||||
s_gl->getString.version = driverGroup.readEntry("Version").toUtf8();
|
||||
s_gl->getString.shadingLanguageVersion = driverGroup.readEntry("ShadingLanguageVersion").toUtf8();
|
||||
s_gl->getString.extensions = QList<QByteArray>{QByteArrayLiteral("GL_ARB_shader_objects"),
|
||||
QByteArrayLiteral("GL_ARB_fragment_shader"),
|
||||
QByteArrayLiteral("GL_ARB_vertex_shader"),
|
||||
QByteArrayLiteral("GL_ARB_texture_non_power_of_two")};
|
||||
s_gl->getString.extensionsString = QByteArray();
|
||||
|
||||
auto *gl = GLPlatform::instance();
|
||||
QVERIFY(gl);
|
||||
gl->detect(EglPlatformInterface);
|
||||
QCOMPARE(gl->platformInterface(), EglPlatformInterface);
|
||||
const auto version = driverGroup.readEntry("Version").toUtf8();
|
||||
const auto glslVersion = driverGroup.readEntry("ShadingLanguageVersion").toUtf8();
|
||||
const auto renderer = driverGroup.readEntry("Renderer").toUtf8();
|
||||
const auto vendor = driverGroup.readEntry("Vendor").toUtf8();
|
||||
GLPlatform gl(EglPlatformInterface, version, glslVersion, renderer, vendor);
|
||||
QCOMPARE(gl.platformInterface(), EglPlatformInterface);
|
||||
|
||||
const KConfigGroup settingsGroup = config.group(QStringLiteral("Settings"));
|
||||
|
||||
QCOMPARE(gl->supports(GLFeature::LooseBinding), settingsGroup.readEntry("LooseBinding", false));
|
||||
QCOMPARE(gl.isLooseBinding(), settingsGroup.readEntry("LooseBinding", false));
|
||||
|
||||
QCOMPARE(gl->glVersion(), readVersion(settingsGroup, "GLVersion"));
|
||||
QCOMPARE(gl->glslVersion(), readVersion(settingsGroup, "GLSLVersion"));
|
||||
QCOMPARE(gl->mesaVersion(), readVersion(settingsGroup, "MesaVersion"));
|
||||
QCOMPARE(gl.glVersion(), readVersion(settingsGroup, "GLVersion"));
|
||||
QCOMPARE(gl.glslVersion(), readVersion(settingsGroup, "GLSLVersion"));
|
||||
QCOMPARE(gl.mesaVersion(), readVersion(settingsGroup, "MesaVersion"));
|
||||
QEXPECT_FAIL("amd-catalyst-radeonhd-7700M-3.1.13399", "Detects GL version instead of driver version", Continue);
|
||||
QCOMPARE(gl->driverVersion(), readVersion(settingsGroup, "DriverVersion"));
|
||||
QCOMPARE(gl.driverVersion(), readVersion(settingsGroup, "DriverVersion"));
|
||||
|
||||
QCOMPARE(gl->driver(), Driver(settingsGroup.readEntry("Driver", int(Driver_Unknown))));
|
||||
QCOMPARE(gl->chipClass(), ChipClass(settingsGroup.readEntry("ChipClass", int(UnknownChipClass))));
|
||||
QCOMPARE(gl.driver(), Driver(settingsGroup.readEntry("Driver", int(Driver_Unknown))));
|
||||
QCOMPARE(gl.chipClass(), ChipClass(settingsGroup.readEntry("ChipClass", int(UnknownChipClass))));
|
||||
|
||||
QCOMPARE(gl->isMesaDriver(), settingsGroup.readEntry("Mesa", false));
|
||||
QCOMPARE(gl->isRadeon(), settingsGroup.readEntry("Radeon", false));
|
||||
QCOMPARE(gl->isNvidia(), settingsGroup.readEntry("Nvidia", false));
|
||||
QCOMPARE(gl->isIntel(), settingsGroup.readEntry("Intel", false));
|
||||
QCOMPARE(gl->isVirtualBox(), settingsGroup.readEntry("VirtualBox", false));
|
||||
QCOMPARE(gl->isVMware(), settingsGroup.readEntry("VMware", false));
|
||||
QCOMPARE(gl->isAdreno(), settingsGroup.readEntry("Adreno", false));
|
||||
QCOMPARE(gl->isPanfrost(), settingsGroup.readEntry("Panfrost", false));
|
||||
QCOMPARE(gl->isLima(), settingsGroup.readEntry("Lima", false));
|
||||
QCOMPARE(gl->isVideoCore4(), settingsGroup.readEntry("VC4", false));
|
||||
QCOMPARE(gl->isVideoCore3D(), settingsGroup.readEntry("V3D", false));
|
||||
QCOMPARE(gl->isVirgl(), settingsGroup.readEntry("Virgl", false));
|
||||
QCOMPARE(gl.isMesaDriver(), settingsGroup.readEntry("Mesa", false));
|
||||
QCOMPARE(gl.isRadeon(), settingsGroup.readEntry("Radeon", false));
|
||||
QCOMPARE(gl.isNvidia(), settingsGroup.readEntry("Nvidia", false));
|
||||
QCOMPARE(gl.isIntel(), settingsGroup.readEntry("Intel", false));
|
||||
QCOMPARE(gl.isVirtualBox(), settingsGroup.readEntry("VirtualBox", false));
|
||||
QCOMPARE(gl.isVMware(), settingsGroup.readEntry("VMware", false));
|
||||
QCOMPARE(gl.isAdreno(), settingsGroup.readEntry("Adreno", false));
|
||||
QCOMPARE(gl.isPanfrost(), settingsGroup.readEntry("Panfrost", false));
|
||||
QCOMPARE(gl.isLima(), settingsGroup.readEntry("Lima", false));
|
||||
QCOMPARE(gl.isVideoCore4(), settingsGroup.readEntry("VC4", false));
|
||||
QCOMPARE(gl.isVideoCore3D(), settingsGroup.readEntry("V3D", false));
|
||||
QCOMPARE(gl.isVirgl(), settingsGroup.readEntry("Virgl", false));
|
||||
|
||||
QCOMPARE(gl->isSoftwareEmulation(), settingsGroup.readEntry("SoftwareEmulation", false));
|
||||
QCOMPARE(gl->isVirtualMachine(), settingsGroup.readEntry("VirtualMachine", false));
|
||||
QCOMPARE(gl.isVirtualMachine(), settingsGroup.readEntry("VirtualMachine", false));
|
||||
|
||||
QCOMPARE(gl->glVersionString(), s_gl->getString.version);
|
||||
QCOMPARE(gl->glRendererString(), s_gl->getString.renderer);
|
||||
QCOMPARE(gl->glVendorString(), s_gl->getString.vendor);
|
||||
QCOMPARE(gl->glShadingLanguageVersionString(), s_gl->getString.shadingLanguageVersion);
|
||||
QCOMPARE(gl.glVersionString(), version);
|
||||
QCOMPARE(gl.glRendererString(), renderer);
|
||||
QCOMPARE(gl.glVendorString(), vendor);
|
||||
QCOMPARE(gl.glShadingLanguageVersionString(), glslVersion);
|
||||
|
||||
QCOMPARE(gl->isLooseBinding(), settingsGroup.readEntry("LooseBinding", false));
|
||||
QCOMPARE(gl->isGLES(), settingsGroup.readEntry("GLES", false));
|
||||
QCOMPARE(gl->recommendedCompositor(), CompositingType(settingsGroup.readEntry("Compositor", int(NoCompositing))));
|
||||
QCOMPARE(gl->preferBufferSubData(), settingsGroup.readEntry("PreferBufferSubData", false));
|
||||
QCOMPARE(gl.isLooseBinding(), settingsGroup.readEntry("LooseBinding", false));
|
||||
QCOMPARE(gl.recommendedCompositor(), CompositingType(settingsGroup.readEntry("Compositor", int(NoCompositing))));
|
||||
QCOMPARE(gl.preferBufferSubData(), settingsGroup.readEntry("PreferBufferSubData", false));
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(GLPlatformTest)
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "mock_gl.h"
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
MockGL *s_gl = nullptr;
|
||||
|
||||
static const GLubyte *mock_glGetString(GLenum name)
|
||||
{
|
||||
if (!s_gl) {
|
||||
return nullptr;
|
||||
}
|
||||
switch (name) {
|
||||
case GL_VENDOR:
|
||||
return (const GLubyte *)s_gl->getString.vendor.constData();
|
||||
case GL_RENDERER:
|
||||
return (const GLubyte *)s_gl->getString.renderer.constData();
|
||||
case GL_VERSION:
|
||||
return (const GLubyte *)s_gl->getString.version.constData();
|
||||
case GL_EXTENSIONS:
|
||||
return (const GLubyte *)s_gl->getString.extensionsString.constData();
|
||||
case GL_SHADING_LANGUAGE_VERSION:
|
||||
return (const GLubyte *)s_gl->getString.shadingLanguageVersion.constData();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static const GLubyte *mock_glGetStringi(GLenum name, GLuint index)
|
||||
{
|
||||
if (!s_gl) {
|
||||
return nullptr;
|
||||
}
|
||||
if (name == GL_EXTENSIONS && index < uint(s_gl->getString.extensions.count())) {
|
||||
return (const GLubyte *)s_gl->getString.extensions.at(index).constData();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void mock_glGetIntegerv(GLenum pname, GLint *data)
|
||||
{
|
||||
if (pname == GL_NUM_EXTENSIONS) {
|
||||
if (data && s_gl) {
|
||||
*data = s_gl->getString.extensions.count();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PFNGLGETSTRINGPROC epoxy_glGetString = mock_glGetString;
|
||||
PFNGLGETSTRINGIPROC epoxy_glGetStringi = mock_glGetStringi;
|
||||
PFNGLGETINTEGERVPROC epoxy_glGetIntegerv = mock_glGetIntegerv;
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#ifndef MOCK_GL_H
|
||||
#define MOCK_GL_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
|
||||
struct MockGL
|
||||
{
|
||||
struct
|
||||
{
|
||||
QByteArray vendor;
|
||||
QByteArray renderer;
|
||||
QByteArray version;
|
||||
QList<QByteArray> extensions;
|
||||
QByteArray extensionsString;
|
||||
QByteArray shadingLanguageVersion;
|
||||
} getString;
|
||||
};
|
||||
|
||||
extern MockGL *s_gl;
|
||||
|
||||
#endif
|
|
@ -25,6 +25,36 @@ qt6_generate_wayland_protocol_client_sources(KWinIntegrationTestFramework
|
|||
${PLASMA_WAYLAND_PROTOCOLS_DIR}/fake-input.xml
|
||||
)
|
||||
|
||||
if (Qt6_VERSION VERSION_LESS "6.7.1")
|
||||
# the qtwaylandscanner macro cannot handle the mismatched file name and <protocol name=""
|
||||
find_package(QtWaylandScanner REQUIRED)
|
||||
if (WaylandProtocols_VERSION VERSION_LESS 1.36)
|
||||
ecm_add_qtwayland_client_protocol(KWinIntegrationTestFramework
|
||||
PROTOCOL ${WaylandProtocols_DATADIR}/staging/xdg-dialog/xdg-dialog-v1.xml
|
||||
BASENAME dialog-v1
|
||||
)
|
||||
target_compile_definitions(KWinIntegrationTestFramework PUBLIC
|
||||
-DHAVE_XDG_DIALOG_V1_HEADER=0
|
||||
)
|
||||
else()
|
||||
ecm_add_qtwayland_client_protocol(KWinIntegrationTestFramework
|
||||
PROTOCOL ${WaylandProtocols_DATADIR}/staging/xdg-dialog/xdg-dialog-v1.xml
|
||||
BASENAME xdg-dialog-v1
|
||||
)
|
||||
target_compile_definitions(KWinIntegrationTestFramework PUBLIC
|
||||
-DHAVE_XDG_DIALOG_V1_HEADER=1
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
qt6_generate_wayland_protocol_client_sources(KWinIntegrationTestFramework
|
||||
FILES
|
||||
${WaylandProtocols_DATADIR}/staging/xdg-dialog/xdg-dialog-v1.xml
|
||||
)
|
||||
target_compile_definitions(KWinIntegrationTestFramework PUBLIC
|
||||
-DHAVE_XDG_DIALOG_V1_HEADER=1
|
||||
)
|
||||
endif()
|
||||
|
||||
target_sources(KWinIntegrationTestFramework PRIVATE
|
||||
generic_scene_opengl_test.cpp
|
||||
kwin_wayland_test.cpp
|
||||
|
@ -33,20 +63,21 @@ target_sources(KWinIntegrationTestFramework PRIVATE
|
|||
target_link_libraries(KWinIntegrationTestFramework
|
||||
PUBLIC
|
||||
Qt::Test
|
||||
Qt::Concurrent
|
||||
Plasma::KWaylandClient
|
||||
Wayland::Client
|
||||
Libdrm::Libdrm
|
||||
kwin
|
||||
|
||||
PRIVATE
|
||||
# Own libraries
|
||||
KWinXwaylandServerModule
|
||||
|
||||
# Static plugins
|
||||
KWinQpaPlugin
|
||||
KF6WindowSystemKWinPlugin
|
||||
KF6IdleTimeKWinPlugin
|
||||
)
|
||||
if(KWIN_BUILD_X11)
|
||||
target_link_libraries(KWinIntegrationTestFramework PRIVATE KWinXwaylandServerModule)
|
||||
endif()
|
||||
if(TARGET KF6GlobalAccelKWinPlugin)
|
||||
target_link_libraries(KWinIntegrationTestFramework PUBLIC KF6GlobalAccelKWinPlugin)
|
||||
endif()
|
||||
|
@ -60,6 +91,9 @@ function(integrationTest)
|
|||
set(oneValueArgs NAME)
|
||||
set(multiValueArgs SRCS LIBS)
|
||||
cmake_parse_arguments(ARGS "${optionArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
if (NOT KWIN_BUILD_X11 AND ARGS_LIBS MATCHES XCB::)
|
||||
return()
|
||||
endif()
|
||||
add_executable(${ARGS_NAME} ${ARGS_SRCS})
|
||||
target_link_libraries(${ARGS_NAME} KWinIntegrationTestFramework Qt::Test ${ARGS_LIBS})
|
||||
if(${ARGS_BUILTIN_EFFECTS})
|
||||
|
@ -67,12 +101,14 @@ function(integrationTest)
|
|||
endif()
|
||||
add_test(NAME kwin-${ARGS_NAME} COMMAND dbus-run-session ${CMAKE_BINARY_DIR}/bin/${ARGS_NAME})
|
||||
endfunction()
|
||||
|
||||
integrationTest(NAME testDontCrashGlxgears SRCS dont_crash_glxgears.cpp LIBS KF6::I18n KDecoration2::KDecoration)
|
||||
if(KWIN_BUILD_X11)
|
||||
integrationTest(NAME testDontCrashGlxgears SRCS dont_crash_glxgears.cpp LIBS KF6::I18n KDecoration2::KDecoration)
|
||||
endif()
|
||||
if (KWIN_BUILD_SCREENLOCKER)
|
||||
integrationTest(NAME testLockScreen SRCS lockscreen.cpp LIBS KF6::GlobalAccel)
|
||||
endif()
|
||||
integrationTest(NAME testBounceKeys SRCS bounce_keys_test.cpp)
|
||||
integrationTest(NAME testButtonRebind SRCS buttonrebind_test.cpp)
|
||||
integrationTest(NAME testDecorationInput SRCS decoration_input_test.cpp LIBS KDecoration2::KDecoration KDecoration2::KDecoration2Private)
|
||||
integrationTest(NAME testInternalWindow SRCS internal_window.cpp)
|
||||
integrationTest(NAME testTouchInput SRCS touch_input_test.cpp)
|
||||
|
@ -82,15 +118,12 @@ integrationTest(NAME testPlatformCursor SRCS platformcursor.cpp)
|
|||
integrationTest(NAME testDontCrashCancelAnimation SRCS dont_crash_cancel_animation.cpp LIBS KDecoration2::KDecoration)
|
||||
integrationTest(NAME testTransientPlacement SRCS transient_placement.cpp)
|
||||
integrationTest(NAME testDebugConsole SRCS debug_console_test.cpp)
|
||||
integrationTest(NAME testDontCrashEmptyDeco SRCS dont_crash_empty_deco.cpp LIBS KDecoration2::KDecoration)
|
||||
integrationTest(NAME testPlasmaSurface SRCS plasma_surface_test.cpp)
|
||||
integrationTest(NAME testMaximized SRCS maximize_test.cpp LIBS KDecoration2::KDecoration KF6::Package)
|
||||
integrationTest(NAME testXdgShellWindow SRCS xdgshellwindow_test.cpp LIBS KDecoration2::KDecoration)
|
||||
integrationTest(NAME testXwaylandSelections SRCS xwayland_selections_test.cpp)
|
||||
integrationTest(NAME testSceneOpenGL SRCS scene_opengl_test.cpp )
|
||||
integrationTest(NAME testSceneOpenGLES SRCS scene_opengl_es_test.cpp )
|
||||
integrationTest(NAME testScreenChanges SRCS screen_changes_test.cpp)
|
||||
integrationTest(NAME testModiferOnlyShortcut SRCS modifier_only_shortcut_test.cpp LIBS XKB::XKB)
|
||||
if (KWIN_BUILD_TABBOX)
|
||||
integrationTest(NAME testTabBox SRCS tabbox_test.cpp)
|
||||
endif()
|
||||
|
@ -111,7 +144,7 @@ integrationTest(NAME testActivation SRCS activation_test.cpp)
|
|||
integrationTest(NAME testInputMethod SRCS inputmethod_test.cpp LIBS XKB::XKB)
|
||||
integrationTest(NAME testScreens SRCS screens_test.cpp)
|
||||
integrationTest(NAME testScreenEdges SRCS screenedges_test.cpp LIBS XCB::ICCCM)
|
||||
integrationTest(NAME testOutputChanges SRCS outputchanges_test.cpp)
|
||||
integrationTest(NAME testOutputChanges SRCS outputchanges_test.cpp LIBS XCB::ICCCM)
|
||||
integrationTest(NAME testTiles SRCS tiles_test.cpp)
|
||||
integrationTest(NAME testFractionalScaling SRCS fractional_scaling_test.cpp)
|
||||
integrationTest(NAME testMoveResize SRCS move_resize_window_test.cpp LIBS XCB::ICCCM)
|
||||
|
@ -131,6 +164,12 @@ integrationTest(NAME testXwaylandServerRestart SRCS xwaylandserver_restart_test.
|
|||
integrationTest(NAME testFakeInput SRCS fakeinput_test.cpp)
|
||||
integrationTest(NAME testSecurityContext SRCS security_context_test.cpp)
|
||||
integrationTest(NAME testStickyKeys SRCS sticky_keys_test.cpp)
|
||||
if(KWIN_BUILD_X11)
|
||||
integrationTest(NAME testDontCrashEmptyDeco SRCS dont_crash_empty_deco.cpp LIBS KDecoration2::KDecoration)
|
||||
integrationTest(NAME testXwaylandSelections SRCS xwayland_selections_test.cpp)
|
||||
integrationTest(NAME testXinerama SRCS xinerama_test.cpp)
|
||||
integrationTest(NAME testX11KeyRead SRCS x11keyread.cpp LIBS XCB::XINPUT)
|
||||
endif()
|
||||
|
||||
qt_add_dbus_interfaces(DBUS_SRCS ${CMAKE_BINARY_DIR}/src/org.kde.kwin.VirtualKeyboard.xml)
|
||||
integrationTest(NAME testVirtualKeyboardDBus SRCS test_virtualkeyboard_dbus.cpp ${DBUS_SRCS})
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2024 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "kwin_wayland_test.h"
|
||||
|
||||
#include "pointer_input.h"
|
||||
#include "wayland_server.h"
|
||||
#include "workspace.h"
|
||||
|
||||
#include <KWayland/Client/keyboard.h>
|
||||
#include <KWayland/Client/seat.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
|
||||
using namespace KWin;
|
||||
|
||||
static const QString s_socketName = QStringLiteral("wayland_test_kwin_buttonrebind-0");
|
||||
|
||||
class TestButtonRebind : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void init();
|
||||
void cleanup();
|
||||
void initTestCase();
|
||||
|
||||
void testKey_data();
|
||||
void testKey();
|
||||
|
||||
private:
|
||||
quint32 timestamp = 1;
|
||||
};
|
||||
|
||||
void TestButtonRebind::init()
|
||||
{
|
||||
QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::Seat));
|
||||
QVERIFY(Test::waitForWaylandKeyboard());
|
||||
}
|
||||
|
||||
void TestButtonRebind::cleanup()
|
||||
{
|
||||
Test::destroyWaylandConnection();
|
||||
QVERIFY(QFile::remove(QStandardPaths::locate(QStandardPaths::ConfigLocation, QStringLiteral("kcminputrc"))));
|
||||
}
|
||||
|
||||
void TestButtonRebind::initTestCase()
|
||||
{
|
||||
qRegisterMetaType<KWin::Window *>();
|
||||
QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
|
||||
QVERIFY(waylandServer()->init(s_socketName));
|
||||
Test::setOutputConfig({
|
||||
QRect(0, 0, 1280, 1024),
|
||||
QRect(1280, 0, 1280, 1024),
|
||||
});
|
||||
kwinApp()->start();
|
||||
QVERIFY(applicationStartedSpy.wait());
|
||||
}
|
||||
|
||||
void TestButtonRebind::testKey_data()
|
||||
{
|
||||
QTest::addColumn<QKeySequence>("boundKeys");
|
||||
QTest::addColumn<QList<quint32>>("expectedKeys");
|
||||
|
||||
QTest::newRow("single key") << QKeySequence(Qt::Key_A) << QList<quint32>{KEY_A};
|
||||
QTest::newRow("single modifier") << QKeySequence(Qt::Key_Control) << QList<quint32>{KEY_LEFTCTRL};
|
||||
QTest::newRow("single modifier plus key") << QKeySequence(Qt::ControlModifier | Qt::Key_N) << QList<quint32>{KEY_LEFTCTRL, KEY_N};
|
||||
QTest::newRow("multiple modifiers plus key") << QKeySequence(Qt::ControlModifier | Qt::MetaModifier | Qt::Key_Y) << QList<quint32>{KEY_LEFTCTRL, KEY_LEFTMETA, KEY_Y};
|
||||
QTest::newRow("delete") << QKeySequence(Qt::Key_Delete) << QList<quint32>{KEY_DELETE};
|
||||
QTest::newRow("keypad delete") << QKeySequence(Qt::KeypadModifier | Qt::Key_Delete) << QList<quint32>{KEY_KPDOT};
|
||||
QTest::newRow("keypad enter") << QKeySequence(Qt::KeypadModifier | Qt::Key_Enter) << QList<quint32>{KEY_KPENTER};
|
||||
}
|
||||
|
||||
void TestButtonRebind::testKey()
|
||||
{
|
||||
KConfigGroup buttonGroup = KSharedConfig::openConfig(QStringLiteral("kcminputrc"))->group(QStringLiteral("ButtonRebinds")).group(QStringLiteral("Mouse"));
|
||||
QFETCH(QKeySequence, boundKeys);
|
||||
buttonGroup.writeEntry("ExtraButton7", QStringList{"Key", boundKeys.toString(QKeySequence::PortableText)}, KConfig::Notify);
|
||||
buttonGroup.sync();
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
std::unique_ptr<KWayland::Client::Keyboard> keyboard(Test::waylandSeat()->createKeyboard());
|
||||
QSignalSpy enteredSpy(keyboard.get(), &KWayland::Client::Keyboard::entered);
|
||||
QSignalSpy keyChangedSpy(keyboard.get(), &KWayland::Client::Keyboard::keyChanged);
|
||||
QVERIFY(enteredSpy.wait());
|
||||
|
||||
// 0x119 is Qt::ExtraButton7
|
||||
Test::pointerButtonPressed(0x119, timestamp++);
|
||||
|
||||
QVERIFY(keyChangedSpy.wait());
|
||||
QFETCH(QList<quint32>, expectedKeys);
|
||||
QCOMPARE(keyChangedSpy.count(), expectedKeys.count());
|
||||
for (int i = 0; i < keyChangedSpy.count(); i++) {
|
||||
QCOMPARE(keyChangedSpy.at(i).at(0).value<quint32>(), expectedKeys.at(i));
|
||||
QCOMPARE(keyChangedSpy.at(i).at(1).value<KWayland::Client::Keyboard::KeyState>(), KWayland::Client::Keyboard::KeyState::Pressed);
|
||||
}
|
||||
Test::pointerButtonReleased(0x119, timestamp++);
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(TestButtonRebind)
|
||||
#include "buttonrebind_test.moc"
|
|
@ -140,6 +140,7 @@ void TestDbusInterface::testGetWindowInfoXdgShellClient()
|
|||
#if KWIN_BUILD_ACTIVITIES
|
||||
{QStringLiteral("activities"), QStringList()},
|
||||
#endif
|
||||
{QStringLiteral("layer"), NormalLayer},
|
||||
};
|
||||
|
||||
// let's get the window info
|
||||
|
@ -276,6 +277,7 @@ void TestDbusInterface::testGetWindowInfoX11Client()
|
|||
#if KWIN_BUILD_ACTIVITIES
|
||||
{QStringLiteral("activities"), QStringList()},
|
||||
#endif
|
||||
{QStringLiteral("layer"), NormalLayer},
|
||||
};
|
||||
|
||||
// let's get the window info
|
||||
|
|
|
@ -11,11 +11,14 @@
|
|||
#include "core/output.h"
|
||||
#include "debug_console.h"
|
||||
#include "internalwindow.h"
|
||||
#include "utils/xcbutils.h"
|
||||
#include "wayland_server.h"
|
||||
#include "window.h"
|
||||
#include "workspace.h"
|
||||
|
||||
#if KWIN_BUILD_X11
|
||||
#include "utils/xcbutils.h"
|
||||
#endif
|
||||
|
||||
#include <KWayland/Client/compositor.h>
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/shm_pool.h>
|
||||
|
@ -38,8 +41,10 @@ private Q_SLOTS:
|
|||
void cleanup();
|
||||
void topLevelTest_data();
|
||||
void topLevelTest();
|
||||
#if KWIN_BUILD_X11
|
||||
void testX11Window();
|
||||
void testX11Unmanaged();
|
||||
#endif
|
||||
void testWaylandClient();
|
||||
void testInternalWindow();
|
||||
void testClosingDebugConsole();
|
||||
|
@ -109,6 +114,7 @@ void DebugConsoleTest::topLevelTest()
|
|||
}
|
||||
}
|
||||
|
||||
#if KWIN_BUILD_X11
|
||||
void DebugConsoleTest::testX11Window()
|
||||
{
|
||||
DebugConsoleModel model;
|
||||
|
@ -281,6 +287,7 @@ void DebugConsoleTest::testX11Unmanaged()
|
|||
QVERIFY(!model.hasChildren(unmanagedTopLevelIndex));
|
||||
QVERIFY(!model2.hasChildren(model2.index(1, 0, QModelIndex())));
|
||||
}
|
||||
#endif
|
||||
|
||||
void DebugConsoleTest::testWaylandClient()
|
||||
{
|
||||
|
|
|
@ -52,10 +52,8 @@ private Q_SLOTS:
|
|||
void cleanup();
|
||||
void testAxis_data();
|
||||
void testAxis();
|
||||
void testDoubleClickOnAllDesktops_data();
|
||||
void testDoubleClickOnAllDesktops();
|
||||
void testDoubleClickClose();
|
||||
void testDoubleTap_data();
|
||||
void testDoubleTap();
|
||||
void testHover();
|
||||
void testPressToMove_data();
|
||||
|
@ -72,7 +70,7 @@ private Q_SLOTS:
|
|||
void testTooltipDoesntEatKeyEvents();
|
||||
|
||||
private:
|
||||
std::tuple<Window *, std::unique_ptr<KWayland::Client::Surface>, Test::XdgToplevel *> showWindow();
|
||||
std::tuple<Window *, std::unique_ptr<KWayland::Client::Surface>, std::unique_ptr<Test::XdgToplevel>, std::unique_ptr<Test::XdgToplevelDecorationV1>> showWindow();
|
||||
};
|
||||
|
||||
#define MOTION(target) Test::pointerMotion(target, timestamp++)
|
||||
|
@ -81,23 +79,23 @@ private:
|
|||
|
||||
#define RELEASE Test::pointerButtonReleased(BTN_LEFT, timestamp++)
|
||||
|
||||
std::tuple<Window *, std::unique_ptr<KWayland::Client::Surface>, Test::XdgToplevel *> DecorationInputTest::showWindow()
|
||||
std::tuple<Window *, std::unique_ptr<KWayland::Client::Surface>, std::unique_ptr<Test::XdgToplevel>, std::unique_ptr<Test::XdgToplevelDecorationV1>> DecorationInputTest::showWindow()
|
||||
{
|
||||
#define VERIFY(statement) \
|
||||
if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__)) \
|
||||
return {nullptr, nullptr, nullptr};
|
||||
return {nullptr, nullptr, nullptr, nullptr};
|
||||
#define COMPARE(actual, expected) \
|
||||
if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__, __LINE__)) \
|
||||
return {nullptr, nullptr, nullptr};
|
||||
return {nullptr, nullptr, nullptr, nullptr};
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface{Test::createSurface()};
|
||||
VERIFY(surface.get());
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), Test::CreationSetup::CreateOnly, surface.get());
|
||||
VERIFY(shellSurface);
|
||||
Test::XdgToplevelDecorationV1 *decoration = Test::createXdgToplevelDecorationV1(shellSurface, shellSurface);
|
||||
VERIFY(decoration);
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get(), Test::CreationSetup::CreateOnly);
|
||||
VERIFY(shellSurface.get());
|
||||
std::unique_ptr<Test::XdgToplevelDecorationV1> decoration = Test::createXdgToplevelDecorationV1(shellSurface.get());
|
||||
VERIFY(decoration.get());
|
||||
|
||||
QSignalSpy decorationConfigureRequestedSpy(decoration, &Test::XdgToplevelDecorationV1::configureRequested);
|
||||
QSignalSpy decorationConfigureRequestedSpy(decoration.get(), &Test::XdgToplevelDecorationV1::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
|
||||
decoration->set_mode(Test::XdgToplevelDecorationV1::mode_server_side);
|
||||
|
@ -114,7 +112,7 @@ std::tuple<Window *, std::unique_ptr<KWayland::Client::Surface>, Test::XdgToplev
|
|||
#undef VERIFY
|
||||
#undef COMPARE
|
||||
|
||||
return {window, std::move(surface), shellSurface};
|
||||
return {window, std::move(surface), std::move(shellSurface), std::move(decoration)};
|
||||
}
|
||||
|
||||
void DecorationInputTest::initTestCase()
|
||||
|
@ -174,7 +172,7 @@ void DecorationInputTest::testAxis()
|
|||
{
|
||||
static constexpr double oneTick = 15;
|
||||
|
||||
const auto [window, surface, shellSurface] = showWindow();
|
||||
const auto [window, surface, shellSurface, decoration] = showWindow();
|
||||
QVERIFY(window);
|
||||
QVERIFY(window->isDecorated());
|
||||
QVERIFY(!window->noBorder());
|
||||
|
@ -211,16 +209,6 @@ void DecorationInputTest::testAxis()
|
|||
QVERIFY(!window->keepAbove());
|
||||
}
|
||||
|
||||
void DecorationInputTest::testDoubleClickOnAllDesktops_data()
|
||||
{
|
||||
QTest::addColumn<QPoint>("decoPoint");
|
||||
QTest::addColumn<Qt::WindowFrameSection>("expectedSection");
|
||||
|
||||
QTest::newRow("topLeft") << QPoint(0, 0) << Qt::TopLeftSection;
|
||||
QTest::newRow("top") << QPoint(250, 0) << Qt::TopSection;
|
||||
QTest::newRow("topRight") << QPoint(499, 0) << Qt::TopRightSection;
|
||||
}
|
||||
|
||||
void KWin::DecorationInputTest::testDoubleClickOnAllDesktops()
|
||||
{
|
||||
KConfigGroup group = kwinApp()->config()->group(QStringLiteral("Windows"));
|
||||
|
@ -228,7 +216,7 @@ void KWin::DecorationInputTest::testDoubleClickOnAllDesktops()
|
|||
group.sync();
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
const auto [window, surface, shellSurface] = showWindow();
|
||||
const auto [window, surface, shellSurface, decoration] = showWindow();
|
||||
QVERIFY(window);
|
||||
QVERIFY(window->isDecorated());
|
||||
QVERIFY(!window->noBorder());
|
||||
|
@ -249,21 +237,6 @@ void KWin::DecorationInputTest::testDoubleClickOnAllDesktops()
|
|||
PRESS;
|
||||
RELEASE;
|
||||
QVERIFY(!window->isOnAllDesktops());
|
||||
|
||||
// test top most deco pixel, BUG: 362860
|
||||
window->move(QPoint(0, 0));
|
||||
QFETCH(QPoint, decoPoint);
|
||||
MOTION(decoPoint);
|
||||
QVERIFY(input()->pointer()->decoration());
|
||||
QCOMPARE(input()->pointer()->decoration()->window(), window);
|
||||
QTEST(input()->pointer()->decoration()->decoration()->sectionUnderMouse(), "expectedSection");
|
||||
// double click
|
||||
PRESS;
|
||||
RELEASE;
|
||||
QVERIFY(!window->isOnAllDesktops());
|
||||
PRESS;
|
||||
RELEASE;
|
||||
QVERIFY(window->isOnAllDesktops());
|
||||
}
|
||||
|
||||
void DecorationInputTest::testDoubleClickClose()
|
||||
|
@ -274,13 +247,13 @@ void DecorationInputTest::testDoubleClickClose()
|
|||
group.sync();
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
auto [window, surface, shellSurface] = showWindow();
|
||||
auto [window, surface, shellSurface, decoration] = showWindow();
|
||||
QVERIFY(window);
|
||||
QVERIFY(window->isDecorated());
|
||||
quint32 timestamp = 1;
|
||||
MOTION(QPoint(window->frameGeometry().center().x(), window->frameMargins().top() / 2.0));
|
||||
|
||||
connect(shellSurface, &Test::XdgToplevel::closeRequested, this, [&surface = surface]() {
|
||||
connect(shellSurface.get(), &Test::XdgToplevel::closeRequested, this, [&surface = surface]() {
|
||||
surface.reset();
|
||||
});
|
||||
|
||||
|
@ -297,16 +270,6 @@ void DecorationInputTest::testDoubleClickClose()
|
|||
window->unref();
|
||||
}
|
||||
|
||||
void DecorationInputTest::testDoubleTap_data()
|
||||
{
|
||||
QTest::addColumn<QPoint>("decoPoint");
|
||||
QTest::addColumn<Qt::WindowFrameSection>("expectedSection");
|
||||
|
||||
QTest::newRow("topLeft") << QPoint(10, 10) << Qt::TopLeftSection;
|
||||
QTest::newRow("top") << QPoint(260, 10) << Qt::TopSection;
|
||||
QTest::newRow("topRight") << QPoint(509, 10) << Qt::TopRightSection;
|
||||
}
|
||||
|
||||
void KWin::DecorationInputTest::testDoubleTap()
|
||||
{
|
||||
KConfigGroup group = kwinApp()->config()->group(QStringLiteral("Windows"));
|
||||
|
@ -314,7 +277,7 @@ void KWin::DecorationInputTest::testDoubleTap()
|
|||
group.sync();
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
const auto [window, surface, shellSurface] = showWindow();
|
||||
const auto [window, surface, shellSurface, decoration] = showWindow();
|
||||
QVERIFY(window);
|
||||
QVERIFY(window->isDecorated());
|
||||
QVERIFY(!window->noBorder());
|
||||
|
@ -335,28 +298,11 @@ void KWin::DecorationInputTest::testDoubleTap()
|
|||
Test::touchDown(0, tapPoint, timestamp++);
|
||||
Test::touchUp(0, timestamp++);
|
||||
QVERIFY(!window->isOnAllDesktops());
|
||||
|
||||
// test top most deco pixel, BUG: 362860
|
||||
//
|
||||
// Not directly at (0, 0), otherwise ScreenEdgeInputFilter catches
|
||||
// event before DecorationEventFilter.
|
||||
window->move(QPoint(10, 10));
|
||||
QFETCH(QPoint, decoPoint);
|
||||
// double click
|
||||
Test::touchDown(0, decoPoint, timestamp++);
|
||||
QVERIFY(input()->touch()->decoration());
|
||||
QCOMPARE(input()->touch()->decoration()->window(), window);
|
||||
QTEST(input()->touch()->decoration()->decoration()->sectionUnderMouse(), "expectedSection");
|
||||
Test::touchUp(0, timestamp++);
|
||||
QVERIFY(!window->isOnAllDesktops());
|
||||
Test::touchDown(0, decoPoint, timestamp++);
|
||||
Test::touchUp(0, timestamp++);
|
||||
QVERIFY(window->isOnAllDesktops());
|
||||
}
|
||||
|
||||
void DecorationInputTest::testHover()
|
||||
{
|
||||
const auto [window, surface, shellSurface] = showWindow();
|
||||
const auto [window, surface, shellSurface, decoration] = showWindow();
|
||||
QVERIFY(window);
|
||||
QVERIFY(window->isDecorated());
|
||||
QVERIFY(!window->noBorder());
|
||||
|
@ -415,7 +361,7 @@ void DecorationInputTest::testPressToMove_data()
|
|||
|
||||
void DecorationInputTest::testPressToMove()
|
||||
{
|
||||
const auto [window, surface, shellSurface] = showWindow();
|
||||
const auto [window, surface, shellSurface, decoration] = showWindow();
|
||||
QVERIFY(window);
|
||||
QVERIFY(window->isDecorated());
|
||||
QVERIFY(!window->noBorder());
|
||||
|
@ -472,7 +418,7 @@ void DecorationInputTest::testTapToMove_data()
|
|||
|
||||
void DecorationInputTest::testTapToMove()
|
||||
{
|
||||
const auto [window, surface, shellSurface] = showWindow();
|
||||
const auto [window, surface, shellSurface, decoration] = showWindow();
|
||||
QVERIFY(window);
|
||||
QVERIFY(window->isDecorated());
|
||||
QVERIFY(!window->noBorder());
|
||||
|
@ -536,7 +482,7 @@ void DecorationInputTest::testResizeOutsideWindow()
|
|||
workspace()->slotReconfigure();
|
||||
|
||||
// now create window
|
||||
const auto [window, surface, shellSurface] = showWindow();
|
||||
const auto [window, surface, shellSurface, decoration] = showWindow();
|
||||
QVERIFY(window);
|
||||
QVERIFY(window->isDecorated());
|
||||
QVERIFY(!window->noBorder());
|
||||
|
@ -630,7 +576,7 @@ void DecorationInputTest::testModifierClickUnrestrictedMove()
|
|||
QCOMPARE(options->commandAll3(), Options::MouseUnrestrictedMove);
|
||||
|
||||
// create a window
|
||||
const auto [window, surface, shellSurface] = showWindow();
|
||||
const auto [window, surface, shellSurface, decoration] = showWindow();
|
||||
QVERIFY(window);
|
||||
QVERIFY(window->isDecorated());
|
||||
QVERIFY(!window->noBorder());
|
||||
|
@ -692,7 +638,7 @@ void DecorationInputTest::testModifierScrollOpacity()
|
|||
group.sync();
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
const auto [window, surface, shellSurface] = showWindow();
|
||||
const auto [window, surface, shellSurface, decoration] = showWindow();
|
||||
QVERIFY(window);
|
||||
QVERIFY(window->isDecorated());
|
||||
QVERIFY(!window->noBorder());
|
||||
|
@ -750,7 +696,7 @@ void DecorationInputTest::testTouchEvents()
|
|||
{
|
||||
// this test verifies that the decoration gets a hover leave event on touch release
|
||||
// see BUG 386231
|
||||
const auto [window, surface, shellSurface] = showWindow();
|
||||
const auto [window, surface, shellSurface, decoration] = showWindow();
|
||||
QVERIFY(window);
|
||||
QVERIFY(window->isDecorated());
|
||||
QVERIFY(!window->noBorder());
|
||||
|
@ -796,7 +742,7 @@ void DecorationInputTest::testTooltipDoesntEatKeyEvents()
|
|||
QVERIFY(keyboard);
|
||||
QSignalSpy enteredSpy(keyboard, &KWayland::Client::Keyboard::entered);
|
||||
|
||||
const auto [window, surface, shellSurface] = showWindow();
|
||||
const auto [window, surface, shellSurface, decoration] = showWindow();
|
||||
QVERIFY(window);
|
||||
QVERIFY(window->isDecorated());
|
||||
QVERIFY(!window->noBorder());
|
||||
|
|
|
@ -131,7 +131,7 @@ void X11DesktopWindowTest::testDesktopWindow()
|
|||
QVERIFY(window);
|
||||
QCOMPARE(window->window(), windowId);
|
||||
QVERIFY(!window->isDecorated());
|
||||
QCOMPARE(window->windowType(), NET::Desktop);
|
||||
QCOMPARE(window->windowType(), WindowType::Desktop);
|
||||
QCOMPARE(window->frameGeometry(), windowGeometry);
|
||||
QVERIFY(window->isDesktop());
|
||||
QCOMPARE(window->depth(), 24);
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
#include "wayland_server.h"
|
||||
#include "window.h"
|
||||
#include "workspace.h"
|
||||
#if KWIN_BUILD_X11
|
||||
#include "x11window.h"
|
||||
#endif
|
||||
|
||||
#include <KDecoration2/Decoration>
|
||||
|
||||
|
@ -85,7 +87,7 @@ void DontCrashCancelAnimationFromAnimationEndedTest::testScript()
|
|||
// create a window
|
||||
std::unique_ptr<KWayland::Client::Surface> surface{Test::createSurface()};
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
// let's render
|
||||
Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
|
|
@ -182,7 +182,7 @@ void ScriptedEffectsTest::testEffectsHandler()
|
|||
// create a window
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
auto *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
shellSurface->set_title("WindowA");
|
||||
auto *c = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
@ -265,7 +265,7 @@ void ScriptedEffectsTest::testAnimations()
|
|||
// animated after window added connect
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
auto *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
shellSurface->set_title("Window 1");
|
||||
auto *c = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
@ -371,7 +371,7 @@ void ScriptedEffectsTest::testFullScreenEffect()
|
|||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
auto *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
shellSurface->set_title("Window 1");
|
||||
auto *c = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
@ -433,7 +433,7 @@ void ScriptedEffectsTest::testKeepAlive()
|
|||
// create a window
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
auto *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
auto *c = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(c);
|
||||
|
@ -479,7 +479,7 @@ void ScriptedEffectsTest::testGrab()
|
|||
// create test window
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(window);
|
||||
|
@ -509,7 +509,7 @@ void ScriptedEffectsTest::testGrabAlreadyGrabbedWindow()
|
|||
// create test window
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(window);
|
||||
|
@ -543,7 +543,7 @@ void ScriptedEffectsTest::testGrabAlreadyGrabbedWindowForced()
|
|||
// create test window
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(window);
|
||||
|
@ -572,7 +572,7 @@ void ScriptedEffectsTest::testUngrab()
|
|||
// create test window
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(window);
|
||||
|
@ -614,7 +614,7 @@ void ScriptedEffectsTest::testRedirect()
|
|||
// create test window
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(window);
|
||||
|
@ -690,7 +690,7 @@ void ScriptedEffectsTest::testComplete()
|
|||
// create test window
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(window);
|
||||
|
|
|
@ -119,8 +119,8 @@ void WobblyWindowsShadeTest::testShadeMove()
|
|||
QVERIFY(!window->isShade());
|
||||
QVERIFY(window->isActive());
|
||||
|
||||
QSignalSpy windowShownSpy(window, &Window::windowShown);
|
||||
QVERIFY(windowShownSpy.wait());
|
||||
QSignalSpy readyForPaintingChangedSpy(window, &Window::readyForPaintingChanged);
|
||||
QVERIFY(readyForPaintingChangedSpy.wait());
|
||||
|
||||
// now shade the window
|
||||
workspace()->slotWindowShade();
|
||||
|
|
|
@ -42,7 +42,8 @@ private Q_SLOTS:
|
|||
void init();
|
||||
void cleanup();
|
||||
|
||||
void testShow();
|
||||
void testToplevel();
|
||||
void testPopup();
|
||||
};
|
||||
|
||||
void TestFractionalScale::initTestCase()
|
||||
|
@ -87,20 +88,73 @@ void TestFractionalScale::cleanup()
|
|||
Test::destroyWaylandConnection();
|
||||
}
|
||||
|
||||
void TestFractionalScale::testShow()
|
||||
void TestFractionalScale::testToplevel()
|
||||
{
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::FractionalScaleV1> fractionalScale(Test::createFractionalScaleV1(surface.get()));
|
||||
QSignalSpy fractionalScaleChanged(fractionalScale.get(), &Test::FractionalScaleV1::preferredScaleChanged);
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
|
||||
// above call commits the surface and blocks for the configure event. We should have received the scale already
|
||||
// We are sent the value in 120ths
|
||||
QCOMPARE(fractionalScale->preferredScale(), 1.25 * 120);
|
||||
QCOMPARE(fractionalScaleChanged.count(), 1);
|
||||
QCOMPARE(fractionalScale->preferredScale(), std::round(1.25 * 120));
|
||||
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(window);
|
||||
QCOMPARE(fractionalScaleChanged.count(), 1);
|
||||
QCOMPARE(fractionalScale->preferredScale(), std::round(1.25 * 120));
|
||||
|
||||
QCOMPARE(fractionalScale->preferredScale(), 1.25 * 120);
|
||||
// move to screen 2
|
||||
window->move(QPoint(1280, 0));
|
||||
|
||||
QVERIFY(Test::waylandSync());
|
||||
QCOMPARE(fractionalScaleChanged.count(), 2);
|
||||
QCOMPARE(fractionalScale->preferredScale(), std::round(2.0 * 120));
|
||||
}
|
||||
|
||||
void TestFractionalScale::testPopup()
|
||||
{
|
||||
std::unique_ptr<KWayland::Client::Surface> toplevelSurface(Test::createSurface());
|
||||
std::unique_ptr<Test::FractionalScaleV1> toplevelFractionalScale(Test::createFractionalScaleV1(toplevelSurface.get()));
|
||||
QSignalSpy toplevelFractionalScaleChanged(toplevelFractionalScale.get(), &Test::FractionalScaleV1::preferredScaleChanged);
|
||||
std::unique_ptr<Test::XdgToplevel> toplevel(Test::createXdgToplevelSurface(toplevelSurface.get()));
|
||||
|
||||
// above call commits the surface and blocks for the configure event. We should have received the scale already
|
||||
// We are sent the value in 120ths
|
||||
QCOMPARE(toplevelFractionalScaleChanged.count(), 1);
|
||||
QCOMPARE(toplevelFractionalScale->preferredScale(), std::round(1.25 * 120));
|
||||
|
||||
auto toplevelWindow = Test::renderAndWaitForShown(toplevelSurface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(toplevelWindow);
|
||||
QCOMPARE(toplevelFractionalScaleChanged.count(), 1);
|
||||
QCOMPARE(toplevelFractionalScale->preferredScale(), std::round(1.25 * 120));
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> popupSurface(Test::createSurface());
|
||||
std::unique_ptr<Test::FractionalScaleV1> popupFractionalScale(Test::createFractionalScaleV1(popupSurface.get()));
|
||||
QSignalSpy popupFractionalScaleChanged(popupFractionalScale.get(), &Test::FractionalScaleV1::preferredScaleChanged);
|
||||
std::unique_ptr<Test::XdgPositioner> positioner(Test::createXdgPositioner());
|
||||
positioner->set_size(10, 10);
|
||||
positioner->set_anchor_rect(10, 10, 10, 10);
|
||||
std::unique_ptr<Test::XdgPopup> popup(Test::createXdgPopupSurface(popupSurface.get(), toplevel->xdgSurface(), positioner.get()));
|
||||
|
||||
// above call commits the surface and blocks for the configure event. We should have received the scale already
|
||||
// We are sent the value in 120ths
|
||||
QCOMPARE(popupFractionalScaleChanged.count(), 1);
|
||||
QCOMPARE(popupFractionalScale->preferredScale(), std::round(1.25 * 120));
|
||||
|
||||
auto popupWindow = Test::renderAndWaitForShown(popupSurface.get(), QSize(10, 10), Qt::cyan);
|
||||
QVERIFY(popupWindow);
|
||||
QCOMPARE(popupFractionalScaleChanged.count(), 1);
|
||||
QCOMPARE(popupFractionalScale->preferredScale(), std::round(1.25 * 120));
|
||||
|
||||
// move the parent to screen 2
|
||||
toplevelWindow->move(QPoint(1280, 0));
|
||||
|
||||
QVERIFY(Test::waylandSync());
|
||||
QCOMPARE(toplevelFractionalScaleChanged.count(), 2);
|
||||
QCOMPARE(toplevelFractionalScale->preferredScale(), std::round(2.0 * 120));
|
||||
QCOMPARE(popupFractionalScaleChanged.count(), 2);
|
||||
QCOMPARE(popupFractionalScale->preferredScale(), std::round(2.0 * 120));
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(TestFractionalScale)
|
||||
|
|
|
@ -49,6 +49,7 @@ private Q_SLOTS:
|
|||
void testUserActionsMenu();
|
||||
void testMetaShiftW();
|
||||
void testComponseKey();
|
||||
void testKeypad();
|
||||
void testX11WindowShortcut();
|
||||
void testWaylandWindowShortcut();
|
||||
void testSetupWindowShortcut();
|
||||
|
@ -275,6 +276,44 @@ void GlobalShortcutsTest::testComponseKey()
|
|||
QTRY_COMPARE(triggeredSpy.count(), 0);
|
||||
}
|
||||
|
||||
void GlobalShortcutsTest::testKeypad()
|
||||
{
|
||||
auto zeroAction = std::make_unique<QAction>();
|
||||
zeroAction->setProperty("componentName", QStringLiteral("kwin"));
|
||||
zeroAction->setObjectName(QStringLiteral("globalshortcuts-test-keypad-0"));
|
||||
QSignalSpy zeroActionTriggeredSpy(zeroAction.get(), &QAction::triggered);
|
||||
KGlobalAccel::self()->setShortcut(zeroAction.get(), QList<QKeySequence>{Qt::MetaModifier | Qt::KeypadModifier | Qt::Key_0}, KGlobalAccel::NoAutoloading);
|
||||
|
||||
auto insertAction = std::make_unique<QAction>();
|
||||
insertAction->setProperty("componentName", QStringLiteral("kwin"));
|
||||
insertAction->setObjectName(QStringLiteral("globalshortcuts-test-keypad-ins"));
|
||||
QSignalSpy insertActionTriggeredSpy(insertAction.get(), &QAction::triggered);
|
||||
KGlobalAccel::self()->setShortcut(insertAction.get(), QList<QKeySequence>{Qt::MetaModifier | Qt::KeypadModifier | Qt::Key_Insert}, KGlobalAccel::NoAutoloading);
|
||||
|
||||
// Turn on numlock
|
||||
quint32 timestamp = 0;
|
||||
Test::keyboardKeyPressed(KEY_NUMLOCK, timestamp++);
|
||||
Test::keyboardKeyReleased(KEY_NUMLOCK, timestamp++);
|
||||
|
||||
Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++);
|
||||
Test::keyboardKeyPressed(KEY_KP0, timestamp++);
|
||||
Test::keyboardKeyReleased(KEY_KP0, timestamp++);
|
||||
Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++);
|
||||
QTRY_COMPARE(zeroActionTriggeredSpy.count(), 1);
|
||||
QCOMPARE(insertActionTriggeredSpy.count(), 0);
|
||||
|
||||
// Turn off numlock
|
||||
Test::keyboardKeyPressed(KEY_NUMLOCK, timestamp++);
|
||||
Test::keyboardKeyReleased(KEY_NUMLOCK, timestamp++);
|
||||
|
||||
Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++);
|
||||
Test::keyboardKeyPressed(KEY_KP0, timestamp++);
|
||||
Test::keyboardKeyReleased(KEY_KP0, timestamp++);
|
||||
Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++);
|
||||
QTRY_COMPARE(insertActionTriggeredSpy.count(), 1);
|
||||
QCOMPARE(zeroActionTriggeredSpy.count(), 1);
|
||||
}
|
||||
|
||||
void GlobalShortcutsTest::testX11WindowShortcut()
|
||||
{
|
||||
// create an X11 window
|
||||
|
|
|
@ -101,7 +101,7 @@ void InputStackingOrderTest::testPointerFocusUpdatesOnStackingOrderChange()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface1 = Test::createSurface();
|
||||
QVERIFY(surface1);
|
||||
Test::XdgToplevel *shellSurface1 = Test::createXdgToplevelSurface(surface1.get(), surface1.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface1 = Test::createXdgToplevelSurface(surface1.get());
|
||||
QVERIFY(shellSurface1);
|
||||
render(surface1.get());
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -110,7 +110,7 @@ void InputStackingOrderTest::testPointerFocusUpdatesOnStackingOrderChange()
|
|||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface2 = Test::createSurface();
|
||||
QVERIFY(surface2);
|
||||
Test::XdgToplevel *shellSurface2 = Test::createXdgToplevelSurface(surface2.get(), surface2.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface2 = Test::createXdgToplevelSurface(surface2.get());
|
||||
QVERIFY(shellSurface2);
|
||||
render(surface2.get());
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "core/output.h"
|
||||
#include "inputmethod.h"
|
||||
#include "inputpanelv1window.h"
|
||||
#include "keyboard_input.h"
|
||||
#include "pointer_input.h"
|
||||
#include "qwayland-input-method-unstable-v1.h"
|
||||
|
@ -63,6 +64,8 @@ private Q_SLOTS:
|
|||
void testDisableShowInputPanel();
|
||||
void testModifierForwarding();
|
||||
void testFakeEventFallback();
|
||||
void testOverlayPositioning_data();
|
||||
void testOverlayPositioning();
|
||||
|
||||
private:
|
||||
void touchNow()
|
||||
|
@ -210,12 +213,12 @@ void InputMethodTest::testEnableDisableV3()
|
|||
kwinApp()->inputMethod()->hide();
|
||||
QVERIFY(!keyboardClient->isShown());
|
||||
|
||||
QSignalSpy windowShownSpy(keyboardClient, &Window::windowShown);
|
||||
QSignalSpy hiddenChangedSpy(keyboardClient, &Window::hiddenChanged);
|
||||
// Force enable the text input object. This is what's done by Gtk.
|
||||
textInputV3->enable();
|
||||
textInputV3->commit();
|
||||
|
||||
windowShownSpy.wait();
|
||||
hiddenChangedSpy.wait();
|
||||
QVERIFY(keyboardClient->isShown());
|
||||
|
||||
// disable text input and ensure that it is not hiding input panel without commit
|
||||
|
@ -358,7 +361,7 @@ void InputMethodTest::testSwitchFocusedSurfaces()
|
|||
|
||||
QList<Window *> windows;
|
||||
std::vector<std::unique_ptr<KWayland::Client::Surface>> surfaces;
|
||||
QList<Test::XdgToplevel *> toplevels;
|
||||
std::vector<std::unique_ptr<Test::XdgToplevel>> toplevels;
|
||||
// We create 3 surfaces
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
|
@ -366,7 +369,7 @@ void InputMethodTest::testSwitchFocusedSurfaces()
|
|||
windows += Test::renderAndWaitForShown(surface.get(), QSize(1280, 1024), Qt::red);
|
||||
QCOMPARE(workspace()->activeWindow(), windows.constLast());
|
||||
surfaces.push_back(std::move(surface));
|
||||
toplevels += shellSurface;
|
||||
toplevels.push_back(std::move(shellSurface));
|
||||
}
|
||||
QCOMPARE(windowAddedSpy.count(), 3);
|
||||
waylandServer()->seat()->setFocusedTextInputSurface(windows.constFirst()->surface());
|
||||
|
@ -385,12 +388,6 @@ void InputMethodTest::testSwitchFocusedSurfaces()
|
|||
waylandServer()->seat()->setFocusedTextInputSurface(windows.first()->surface());
|
||||
QVERIFY(activateSpy.count() || activateSpy.wait());
|
||||
QVERIFY(!kwinApp()->inputMethod()->isActive());
|
||||
|
||||
// Destroy the test window.
|
||||
for (int i = 0; i < windows.count(); ++i) {
|
||||
delete toplevels[i];
|
||||
QVERIFY(Test::waitForWindowClosed(windows[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void InputMethodTest::testV2V3SameClient()
|
||||
|
@ -552,6 +549,10 @@ void InputMethodTest::testV3Styling()
|
|||
// Merged range should be [1,6).
|
||||
QCOMPARE(textInputPreeditSpy.last().at(1), 1);
|
||||
QCOMPARE(textInputPreeditSpy.last().at(2), 6);
|
||||
|
||||
shellSurface.reset();
|
||||
QVERIFY(Test::waitForWindowClosed(window));
|
||||
QVERIFY(!kwinApp()->inputMethod()->isActive());
|
||||
}
|
||||
|
||||
void InputMethodTest::testDisableShowInputPanel()
|
||||
|
@ -584,6 +585,9 @@ void InputMethodTest::testDisableShowInputPanel()
|
|||
textInputV2->showInputPanel();
|
||||
QVERIFY(requestShowInputPanelSpy.count() || requestShowInputPanelSpy.wait());
|
||||
QVERIFY(!kwinApp()->inputMethod()->isActive());
|
||||
|
||||
shellSurface.reset();
|
||||
QVERIFY(Test::waitForWindowClosed(window));
|
||||
}
|
||||
|
||||
void InputMethodTest::testModifierForwarding()
|
||||
|
@ -655,6 +659,10 @@ void InputMethodTest::testModifierForwarding()
|
|||
QVERIFY(modifierSpy.count() == 3 || modifierSpy.wait());
|
||||
disconnect(keyChangedConnection);
|
||||
disconnect(modifiersChangedConnection);
|
||||
|
||||
shellSurface.reset();
|
||||
QVERIFY(Test::waitForWindowClosed(window));
|
||||
QVERIFY(!kwinApp()->inputMethod()->isActive());
|
||||
}
|
||||
|
||||
void InputMethodTest::testFakeEventFallback()
|
||||
|
@ -726,6 +734,71 @@ void InputMethodTest::testFakeEventFallback()
|
|||
|
||||
compare(keySpy.at(0), KEY_ENTER, KWayland::Client::Keyboard::KeyState::Pressed);
|
||||
compare(keySpy.at(1), KEY_ENTER, KWayland::Client::Keyboard::KeyState::Released);
|
||||
|
||||
shellSurface.reset();
|
||||
QVERIFY(Test::waitForWindowClosed(window));
|
||||
kwinApp()->inputMethod()->setActive(false);
|
||||
QVERIFY(!kwinApp()->inputMethod()->isActive());
|
||||
}
|
||||
|
||||
void InputMethodTest::testOverlayPositioning_data()
|
||||
{
|
||||
QTest::addColumn<QRect>("cursorRectangle");
|
||||
QTest::addColumn<QRect>("result");
|
||||
|
||||
QTest::newRow("regular") << QRect(10, 20, 30, 40) << QRect(60, 160, 200, 50);
|
||||
QTest::newRow("offscreen-left") << QRect(-200, 40, 30, 40) << QRect(0, 180, 200, 50);
|
||||
QTest::newRow("offscreen-right") << QRect(1200, 40, 30, 40) << QRect(1080, 180, 200, 50);
|
||||
QTest::newRow("offscreen-top") << QRect(1200, -400, 30, 40) << QRect(1080, 0, 200, 50);
|
||||
// Check it is flipped near the bottom of screen (anchor point 844 + 100 + 40 = 1024 - 40)
|
||||
QTest::newRow("offscreen-bottom-flip") << QRect(1200, 844, 30, 40) << QRect(1080, 894, 200, 50);
|
||||
// Top is (screen height 1024 - window height 50) = 984
|
||||
QTest::newRow("offscreen-bottom-slide") << QRect(1200, 1200, 30, 40) << QRect(1080, 974, 200, 50);
|
||||
}
|
||||
|
||||
void InputMethodTest::testOverlayPositioning()
|
||||
{
|
||||
QFETCH(QRect, cursorRectangle);
|
||||
QFETCH(QRect, result);
|
||||
Test::inputMethod()->setMode(Test::MockInputMethod::Mode::Overlay);
|
||||
QVERIFY(!kwinApp()->inputMethod()->isActive());
|
||||
|
||||
touchNow();
|
||||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
QSignalSpy windowRemovedSpy(workspace(), &Workspace::windowRemoved);
|
||||
|
||||
QSignalSpy activateSpy(kwinApp()->inputMethod(), &InputMethod::activeChanged);
|
||||
std::unique_ptr<KWayland::Client::TextInput> textInput(Test::waylandTextInputManager()->createTextInput(Test::waylandSeat()));
|
||||
|
||||
// Create an xdg_toplevel surface and wait for the compositor to catch up.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
// Make the window smaller than the screen and move it.
|
||||
Window *window = Test::renderAndWaitForShown(surface.get(), QSize(1080, 824), Qt::red);
|
||||
window->move(QPointF(50, 100));
|
||||
waylandServer()->seat()->setFocusedTextInputSurface(window->surface());
|
||||
|
||||
textInput->setCursorRectangle(cursorRectangle);
|
||||
textInput->enable(surface.get());
|
||||
// Overlay is shown upon activate
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
||||
QCOMPARE(workspace()->activeWindow(), window);
|
||||
|
||||
QCOMPARE(windowAddedSpy.count(), 2);
|
||||
QVERIFY(activateSpy.count() || activateSpy.wait());
|
||||
QVERIFY(kwinApp()->inputMethod()->isActive());
|
||||
|
||||
auto keyboardWindow = kwinApp()->inputMethod()->panel();
|
||||
QVERIFY(keyboardWindow);
|
||||
// Check the overlay window is placed with cursor rectangle + window position.
|
||||
QCOMPARE(keyboardWindow->frameGeometry(), result);
|
||||
|
||||
// Destroy the test window.
|
||||
shellSurface.reset();
|
||||
QVERIFY(Test::waitForWindowClosed(window));
|
||||
|
||||
Test::inputMethod()->setMode(Test::MockInputMethod::Mode::TopLevel);
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(InputMethodTest)
|
||||
|
|
|
@ -500,16 +500,6 @@ void InternalWindowTest::testMove()
|
|||
internalWindow->move(QPoint(10, 20));
|
||||
QCOMPARE(internalWindow->frameGeometry(), QRect(10, 20, 100, 100));
|
||||
QTRY_COMPARE(win.geometry(), QRect(10, 20, 100, 100));
|
||||
|
||||
// now move with a Geometry update blocker
|
||||
{
|
||||
GeometryUpdatesBlocker blocker(internalWindow);
|
||||
internalWindow->move(QPoint(5, 10));
|
||||
// not synced!
|
||||
QCOMPARE(win.geometry(), QRect(10, 20, 100, 100));
|
||||
}
|
||||
// after destroying the blocker it should be synced
|
||||
QTRY_COMPARE(win.geometry(), QRect(5, 10, 100, 100));
|
||||
}
|
||||
|
||||
void InternalWindowTest::testSkipCloseAnimation_data()
|
||||
|
|
|
@ -58,7 +58,6 @@ private Q_SLOTS:
|
|||
void testReconfigure();
|
||||
void testChangeLayoutThroughDBus();
|
||||
void testPerLayoutShortcut();
|
||||
void testDBusServiceExport();
|
||||
void testVirtualDesktopPolicy();
|
||||
void testWindowPolicy();
|
||||
void testApplicationPolicy();
|
||||
|
@ -307,36 +306,6 @@ void KeyboardLayoutTest::testPerLayoutShortcut()
|
|||
Test::keyboardKeyReleased(KEY_LEFTCTRL, timestamp++);
|
||||
}
|
||||
|
||||
void KeyboardLayoutTest::testDBusServiceExport()
|
||||
{
|
||||
// verifies that the dbus service is only exported if there are at least two layouts
|
||||
|
||||
// first configure layouts, with just one layout
|
||||
layoutGroup.writeEntry("LayoutList", QStringLiteral("us"));
|
||||
layoutGroup.sync();
|
||||
reconfigureLayouts();
|
||||
auto xkb = input()->keyboard()->xkb();
|
||||
QCOMPARE(xkb->numberOfLayouts(), 1u);
|
||||
// default layout is English
|
||||
QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
||||
// with one layout we should not have the dbus interface
|
||||
QVERIFY(!QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.keyboard")).value());
|
||||
|
||||
// reconfigure to two layouts
|
||||
layoutGroup.writeEntry("LayoutList", QStringLiteral("us,de"));
|
||||
layoutGroup.sync();
|
||||
reconfigureLayouts();
|
||||
QCOMPARE(xkb->numberOfLayouts(), 2u);
|
||||
QVERIFY(QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.keyboard")).value());
|
||||
|
||||
// and back to one layout
|
||||
layoutGroup.writeEntry("LayoutList", QStringLiteral("us"));
|
||||
layoutGroup.sync();
|
||||
reconfigureLayouts();
|
||||
QCOMPARE(xkb->numberOfLayouts(), 1u);
|
||||
QVERIFY(!QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.keyboard")).value());
|
||||
}
|
||||
|
||||
void KeyboardLayoutTest::testVirtualDesktopPolicy()
|
||||
{
|
||||
layoutGroup.writeEntry("LayoutList", QStringLiteral("us,de,de(neo)"));
|
||||
|
|
|
@ -15,11 +15,14 @@
|
|||
#include "inputmethod.h"
|
||||
#include "placement.h"
|
||||
#include "pluginmanager.h"
|
||||
#include "utils/xcbutils.h"
|
||||
#include "wayland_server.h"
|
||||
#include "workspace.h"
|
||||
|
||||
#if KWIN_BUILD_X11
|
||||
#include "utils/xcbutils.h"
|
||||
#include "xwayland/xwayland.h"
|
||||
#include "xwayland/xwaylandlauncher.h"
|
||||
#endif
|
||||
|
||||
#include <KPluginMetaData>
|
||||
|
||||
|
@ -52,6 +55,7 @@ WaylandTestApplication::WaylandTestApplication(OperationMode mode, int &argc, ch
|
|||
const QStringList configs{
|
||||
QStringLiteral("kaccessrc"),
|
||||
QStringLiteral("kglobalshortcutsrc"),
|
||||
QStringLiteral("kcminputrc"),
|
||||
};
|
||||
for (const QString &config : configs) {
|
||||
if (const QString &fileName = QStandardPaths::locate(QStandardPaths::ConfigLocation, config); !fileName.isEmpty()) {
|
||||
|
@ -71,10 +75,18 @@ WaylandTestApplication::WaylandTestApplication(OperationMode mode, int &argc, ch
|
|||
qunsetenv("XKB_DEFAULT_VARIANT");
|
||||
qunsetenv("XKB_DEFAULT_OPTIONS");
|
||||
|
||||
auto breezerc = KSharedConfig::openConfig(QStringLiteral("breezerc"));
|
||||
breezerc->group(QStringLiteral("Common")).writeEntry(QStringLiteral("OutlineIntensity"), QStringLiteral("OutlineOff"));
|
||||
breezerc->sync();
|
||||
|
||||
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
|
||||
KConfigGroup windowsGroup = config->group(QStringLiteral("Windows"));
|
||||
windowsGroup.writeEntry("Placement", Placement::policyToString(PlacementSmart));
|
||||
windowsGroup.sync();
|
||||
KConfigGroup edgeBarrierGroup = config->group(QStringLiteral("EdgeBarrier"));
|
||||
edgeBarrierGroup.writeEntry("EdgeBarrier", 0);
|
||||
edgeBarrierGroup.writeEntry("CornerBarrier", false);
|
||||
edgeBarrierGroup.sync();
|
||||
setConfig(config);
|
||||
|
||||
const auto ownPath = libraryPaths().last();
|
||||
|
@ -83,7 +95,7 @@ WaylandTestApplication::WaylandTestApplication(OperationMode mode, int &argc, ch
|
|||
|
||||
setSession(Session::create(Session::Type::Noop));
|
||||
setOutputBackend(std::make_unique<VirtualBackend>());
|
||||
WaylandServer::create(this);
|
||||
m_waylandServer.reset(WaylandServer::create());
|
||||
setProcessStartupEnvironment(QProcessEnvironment::systemEnvironment());
|
||||
}
|
||||
|
||||
|
@ -95,13 +107,16 @@ WaylandTestApplication::~WaylandTestApplication()
|
|||
if (effects) {
|
||||
effects->unloadAllEffects();
|
||||
}
|
||||
#if KWIN_BUILD_X11
|
||||
m_xwayland.reset();
|
||||
#endif
|
||||
destroyVirtualInputDevices();
|
||||
destroyColorManager();
|
||||
destroyWorkspace();
|
||||
destroyInputMethod();
|
||||
destroyCompositor();
|
||||
destroyInput();
|
||||
m_waylandServer.reset();
|
||||
}
|
||||
|
||||
void WaylandTestApplication::createVirtualInputDevices()
|
||||
|
@ -175,10 +190,12 @@ void WaylandTestApplication::continueStartupWithScene()
|
|||
qFatal("Failed to initialize the Wayland server, exiting now");
|
||||
}
|
||||
|
||||
#if KWIN_BUILD_X11
|
||||
if (operationMode() == OperationModeXwayland) {
|
||||
m_xwayland = std::make_unique<Xwl::Xwayland>(this);
|
||||
m_xwayland->init();
|
||||
}
|
||||
#endif
|
||||
|
||||
notifyStarted();
|
||||
}
|
||||
|
@ -198,10 +215,12 @@ Test::VirtualInputDevice *WaylandTestApplication::virtualTouch() const
|
|||
return m_virtualTouch.get();
|
||||
}
|
||||
|
||||
#if KWIN_BUILD_X11
|
||||
XwaylandInterface *WaylandTestApplication::xwayland() const
|
||||
{
|
||||
return m_xwayland.get();
|
||||
}
|
||||
#endif
|
||||
|
||||
Test::FractionalScaleManagerV1::~FractionalScaleManagerV1()
|
||||
{
|
||||
|
@ -220,7 +239,11 @@ int Test::FractionalScaleV1::preferredScale()
|
|||
|
||||
void Test::FractionalScaleV1::wp_fractional_scale_v1_preferred_scale(uint32_t scale)
|
||||
{
|
||||
if (m_preferredScale == scale) {
|
||||
return;
|
||||
}
|
||||
m_preferredScale = scale;
|
||||
Q_EMIT preferredScaleChanged();
|
||||
}
|
||||
|
||||
void Test::setOutputConfig(const QList<QRect> &geometries)
|
||||
|
|
|
@ -34,6 +34,11 @@
|
|||
#include "qwayland-xdg-decoration-unstable-v1.h"
|
||||
#include "qwayland-xdg-shell.h"
|
||||
#include "qwayland-zkde-screencast-unstable-v1.h"
|
||||
#if HAVE_XDG_DIALOG_V1_HEADER
|
||||
#include "qwayland-xdg-dialog-v1.h"
|
||||
#else
|
||||
#include "qwayland-dialog-v1.h"
|
||||
#endif
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
|
@ -68,10 +73,15 @@ class ScreencastingV1;
|
|||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class WaylandServer;
|
||||
|
||||
#if KWIN_BUILD_X11
|
||||
namespace Xwl
|
||||
{
|
||||
class Xwayland;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace Test
|
||||
{
|
||||
|
@ -93,7 +103,9 @@ public:
|
|||
Test::VirtualInputDevice *virtualPointer() const;
|
||||
Test::VirtualInputDevice *virtualKeyboard() const;
|
||||
Test::VirtualInputDevice *virtualTouch() const;
|
||||
#if KWIN_BUILD_X11
|
||||
XwaylandInterface *xwayland() const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void performStartup() override;
|
||||
|
@ -105,7 +117,10 @@ private:
|
|||
void createVirtualInputDevices();
|
||||
void destroyVirtualInputDevices();
|
||||
|
||||
std::unique_ptr<WaylandServer> m_waylandServer;
|
||||
#if KWIN_BUILD_X11
|
||||
std::unique_ptr<Xwl::Xwayland> m_xwayland;
|
||||
#endif
|
||||
QString m_inputMethodServerToStart;
|
||||
|
||||
std::unique_ptr<Test::VirtualInputDevice> m_virtualPointer;
|
||||
|
@ -446,6 +461,11 @@ class MockInputMethod : public QObject, QtWayland::zwp_input_method_v1
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum class Mode {
|
||||
TopLevel,
|
||||
Overlay,
|
||||
};
|
||||
|
||||
MockInputMethod(struct wl_registry *registry, int id, int version);
|
||||
~MockInputMethod();
|
||||
|
||||
|
@ -458,6 +478,8 @@ public:
|
|||
return m_context;
|
||||
}
|
||||
|
||||
void setMode(Mode mode);
|
||||
|
||||
Q_SIGNALS:
|
||||
void activate();
|
||||
|
||||
|
@ -467,8 +489,9 @@ protected:
|
|||
|
||||
private:
|
||||
std::unique_ptr<KWayland::Client::Surface> m_inputSurface;
|
||||
QtWayland::zwp_input_panel_surface_v1 *m_inputMethodSurface = nullptr;
|
||||
std::unique_ptr<QtWayland::zwp_input_panel_surface_v1> m_inputMethodSurface;
|
||||
struct ::zwp_input_method_context_v1 *m_context = nullptr;
|
||||
Mode m_mode = Mode::TopLevel;
|
||||
};
|
||||
|
||||
class FractionalScaleManagerV1 : public QObject, public QtWayland::wp_fractional_scale_manager_v1
|
||||
|
@ -488,8 +511,11 @@ public:
|
|||
protected:
|
||||
void wp_fractional_scale_v1_preferred_scale(uint32_t scale) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void preferredScaleChanged();
|
||||
|
||||
private:
|
||||
int m_preferredScale = 120;
|
||||
uint m_preferredScale = 120;
|
||||
};
|
||||
|
||||
class ScreenEdgeManagerV1 : public QObject, public QtWayland::kde_screen_edge_manager_v1
|
||||
|
@ -534,6 +560,19 @@ public:
|
|||
~SecurityContextManagerV1() override;
|
||||
};
|
||||
|
||||
class XdgWmDialogV1 : public QtWayland::xdg_wm_dialog_v1
|
||||
{
|
||||
public:
|
||||
~XdgWmDialogV1() override;
|
||||
};
|
||||
|
||||
class XdgDialogV1 : public QtWayland::xdg_dialog_v1
|
||||
{
|
||||
public:
|
||||
XdgDialogV1(XdgWmDialogV1 *wm, XdgToplevel *toplevel);
|
||||
~XdgDialogV1() override;
|
||||
};
|
||||
|
||||
enum class AdditionalWaylandInterface {
|
||||
Seat = 1 << 0,
|
||||
PlasmaShell = 1 << 2,
|
||||
|
@ -555,6 +594,7 @@ enum class AdditionalWaylandInterface {
|
|||
CursorShapeV1 = 1 << 18,
|
||||
FakeInput = 1 << 19,
|
||||
SecurityContextManagerV1 = 1 << 20,
|
||||
XdgDialogV1 = 1 << 21,
|
||||
};
|
||||
Q_DECLARE_FLAGS(AdditionalWaylandInterfaces, AdditionalWaylandInterface)
|
||||
|
||||
|
@ -581,7 +621,6 @@ public:
|
|||
void setLeds(LEDs leds) override;
|
||||
|
||||
bool isKeyboard() const override;
|
||||
bool isAlphaNumericKeyboard() const override;
|
||||
bool isPointer() const override;
|
||||
bool isTouchpad() const override;
|
||||
bool isTouch() const override;
|
||||
|
@ -667,13 +706,13 @@ void flushWaylandConnection();
|
|||
bool waylandSync();
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> createSurface();
|
||||
KWayland::Client::SubSurface *createSubSurface(KWayland::Client::Surface *surface,
|
||||
KWayland::Client::Surface *parentSurface, QObject *parent = nullptr);
|
||||
std::unique_ptr<KWayland::Client::SubSurface> createSubSurface(KWayland::Client::Surface *surface,
|
||||
KWayland::Client::Surface *parentSurface);
|
||||
|
||||
LayerSurfaceV1 *createLayerSurfaceV1(KWayland::Client::Surface *surface,
|
||||
const QString &scope,
|
||||
KWayland::Client::Output *output = nullptr,
|
||||
LayerShellV1::layer layer = LayerShellV1::layer_top);
|
||||
std::unique_ptr<LayerSurfaceV1> createLayerSurfaceV1(KWayland::Client::Surface *surface,
|
||||
const QString &scope,
|
||||
KWayland::Client::Output *output = nullptr,
|
||||
LayerShellV1::layer layer = LayerShellV1::layer_top);
|
||||
|
||||
TextInputManagerV3 *waylandTextInputManagerV3();
|
||||
|
||||
|
@ -682,27 +721,27 @@ enum class CreationSetup {
|
|||
CreateAndConfigure, /// commit and wait for the configure event, making this surface ready to commit buffers
|
||||
};
|
||||
|
||||
QtWayland::zwp_input_panel_surface_v1 *createInputPanelSurfaceV1(KWayland::Client::Surface *surface,
|
||||
KWayland::Client::Output *output);
|
||||
std::unique_ptr<QtWayland::zwp_input_panel_surface_v1> createInputPanelSurfaceV1(KWayland::Client::Surface *surface,
|
||||
KWayland::Client::Output *output,
|
||||
MockInputMethod::Mode mode);
|
||||
|
||||
FractionalScaleV1 *createFractionalScaleV1(KWayland::Client::Surface *surface);
|
||||
std::unique_ptr<FractionalScaleV1> createFractionalScaleV1(KWayland::Client::Surface *surface);
|
||||
|
||||
XdgToplevel *createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent = nullptr);
|
||||
XdgToplevel *createXdgToplevelSurface(KWayland::Client::Surface *surface,
|
||||
CreationSetup configureMode,
|
||||
QObject *parent = nullptr);
|
||||
std::unique_ptr<XdgToplevel> createXdgToplevelSurface(KWayland::Client::Surface *surface);
|
||||
std::unique_ptr<XdgToplevel> createXdgToplevelSurface(KWayland::Client::Surface *surface, CreationSetup configureMode);
|
||||
std::unique_ptr<XdgToplevel> createXdgToplevelSurface(KWayland::Client::Surface *surface, std::function<void(XdgToplevel *toplevel)> setup);
|
||||
|
||||
XdgPositioner *createXdgPositioner();
|
||||
std::unique_ptr<XdgPositioner> createXdgPositioner();
|
||||
|
||||
XdgPopup *createXdgPopupSurface(KWayland::Client::Surface *surface, XdgSurface *parentSurface,
|
||||
XdgPositioner *positioner,
|
||||
CreationSetup configureMode = CreationSetup::CreateAndConfigure,
|
||||
QObject *parent = nullptr);
|
||||
std::unique_ptr<XdgPopup> createXdgPopupSurface(KWayland::Client::Surface *surface, XdgSurface *parentSurface,
|
||||
XdgPositioner *positioner,
|
||||
CreationSetup configureMode = CreationSetup::CreateAndConfigure);
|
||||
|
||||
XdgToplevelDecorationV1 *createXdgToplevelDecorationV1(XdgToplevel *toplevel, QObject *parent = nullptr);
|
||||
IdleInhibitorV1 *createIdleInhibitorV1(KWayland::Client::Surface *surface);
|
||||
AutoHideScreenEdgeV1 *createAutoHideScreenEdgeV1(KWayland::Client::Surface *surface, uint32_t border);
|
||||
CursorShapeDeviceV1 *createCursorShapeDeviceV1(KWayland::Client::Pointer *pointer);
|
||||
std::unique_ptr<XdgToplevelDecorationV1> createXdgToplevelDecorationV1(XdgToplevel *toplevel);
|
||||
std::unique_ptr<IdleInhibitorV1> createIdleInhibitorV1(KWayland::Client::Surface *surface);
|
||||
std::unique_ptr<AutoHideScreenEdgeV1> createAutoHideScreenEdgeV1(KWayland::Client::Surface *surface, uint32_t border);
|
||||
std::unique_ptr<CursorShapeDeviceV1> createCursorShapeDeviceV1(KWayland::Client::Pointer *pointer);
|
||||
std::unique_ptr<XdgDialogV1> createXdgDialogV1(XdgToplevel *toplevel);
|
||||
|
||||
/**
|
||||
* Creates a shared memory buffer of @p size in @p color and attaches it to the @p surface.
|
||||
|
@ -758,13 +797,14 @@ bool renderNodeAvailable();
|
|||
* with X on demand
|
||||
*/
|
||||
|
||||
#if KWIN_BUILD_X11
|
||||
struct XcbConnectionDeleter
|
||||
{
|
||||
void operator()(xcb_connection_t *pointer);
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<xcb_connection_t, XcbConnectionDeleter> XcbConnectionPtr;
|
||||
XcbConnectionPtr createX11Connection();
|
||||
#endif
|
||||
|
||||
MockInputMethod *inputMethod();
|
||||
KWayland::Client::Surface *inputPanelSurface();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "kwin_wayland_test.h"
|
||||
|
||||
#include "core/output.h"
|
||||
#include "core/outputconfiguration.h"
|
||||
#include "main.h"
|
||||
#include "pointer_input.h"
|
||||
#include "screenedge.h"
|
||||
|
@ -44,6 +45,7 @@ private Q_SLOTS:
|
|||
void testChangeLayer();
|
||||
void testPlacementArea_data();
|
||||
void testPlacementArea();
|
||||
void testPlacementAreaAfterOutputLayoutChange();
|
||||
void testFill_data();
|
||||
void testFill();
|
||||
void testStack();
|
||||
|
@ -52,6 +54,7 @@ private Q_SLOTS:
|
|||
void testActivate_data();
|
||||
void testActivate();
|
||||
void testUnmap();
|
||||
void testScreenEdge_data();
|
||||
void testScreenEdge();
|
||||
};
|
||||
|
||||
|
@ -263,7 +266,7 @@ void LayerShellV1WindowTest::testLayer_data()
|
|||
QTest::addColumn<int>("protocolLayer");
|
||||
QTest::addColumn<Layer>("compositorLayer");
|
||||
|
||||
QTest::addRow("overlay") << int(Test::LayerShellV1::layer_overlay) << UnmanagedLayer;
|
||||
QTest::addRow("overlay") << int(Test::LayerShellV1::layer_overlay) << OverlayLayer;
|
||||
QTest::addRow("top") << int(Test::LayerShellV1::layer_top) << AboveLayer;
|
||||
QTest::addRow("bottom") << int(Test::LayerShellV1::layer_bottom) << BelowLayer;
|
||||
QTest::addRow("background") << int(Test::LayerShellV1::layer_background) << DesktopLayer;
|
||||
|
@ -356,22 +359,42 @@ void LayerShellV1WindowTest::testPlacementArea_data()
|
|||
QTest::addColumn<int>("anchor");
|
||||
QTest::addColumn<QMargins>("margins");
|
||||
QTest::addColumn<int>("exclusiveZone");
|
||||
QTest::addColumn<int>("exclusiveEdge");
|
||||
QTest::addColumn<QRectF>("placementArea");
|
||||
|
||||
QTest::addRow("left") << int(Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << QRectF(300, 0, 980, 1024);
|
||||
QTest::addRow("top") << int(Test::LayerSurfaceV1::anchor_top) << QMargins(0, 0, 0, 0) << 300 << QRectF(0, 300, 1280, 724);
|
||||
QTest::addRow("right") << int(Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << QRectF(0, 0, 980, 1024);
|
||||
QTest::addRow("bottom") << int(Test::LayerSurfaceV1::anchor_bottom) << QMargins(0, 0, 0, 0) << 300 << QRectF(0, 0, 1280, 724);
|
||||
QTest::addRow("left") << int(Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(300, 0, 980, 1024);
|
||||
QTest::addRow("top") << int(Test::LayerSurfaceV1::anchor_top) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(0, 300, 1280, 724);
|
||||
QTest::addRow("right") << int(Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(0, 0, 980, 1024);
|
||||
QTest::addRow("bottom") << int(Test::LayerSurfaceV1::anchor_bottom) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(0, 0, 1280, 724);
|
||||
|
||||
QTest::addRow("left, negative margin") << int(Test::LayerSurfaceV1::anchor_left) << QMargins(-5, 0, 0, 0) << 300 << QRectF(295, 0, 985, 1024);
|
||||
QTest::addRow("top, negative margin") << int(Test::LayerSurfaceV1::anchor_top) << QMargins(0, -5, 0, 0) << 300 << QRectF(0, 295, 1280, 729);
|
||||
QTest::addRow("right, negative margin") << int(Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, -5, 0) << 300 << QRectF(0, 0, 985, 1024);
|
||||
QTest::addRow("bottom, negative margin") << int(Test::LayerSurfaceV1::anchor_bottom) << QMargins(0, 0, 0, -5) << 300 << QRectF(0, 0, 1280, 729);
|
||||
QTest::addRow("top | left") << int(Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(0, 0, 1280, 1024);
|
||||
QTest::addRow("top | right") << int(Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(0, 0, 1280, 1024);
|
||||
QTest::addRow("bottom | left") << int(Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(0, 0, 1280, 1024);
|
||||
QTest::addRow("bottom | right") << int(Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(0, 0, 1280, 1024);
|
||||
|
||||
QTest::addRow("left, positive margin") << int(Test::LayerSurfaceV1::anchor_left) << QMargins(5, 0, 0, 0) << 300 << QRectF(305, 0, 975, 1024);
|
||||
QTest::addRow("top, positive margin") << int(Test::LayerSurfaceV1::anchor_top) << QMargins(0, 5, 0, 0) << 300 << QRectF(0, 305, 1280, 719);
|
||||
QTest::addRow("right, positive margin") << int(Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 5, 0) << 300 << QRectF(0, 0, 975, 1024);
|
||||
QTest::addRow("bottom, positive margin") << int(Test::LayerSurfaceV1::anchor_bottom) << QMargins(0, 0, 0, 5) << 300 << QRectF(0, 0, 1280, 719);
|
||||
QTest::addRow("left, negative margin") << int(Test::LayerSurfaceV1::anchor_left) << QMargins(-5, 0, 0, 0) << 300 << 0 << QRectF(295, 0, 985, 1024);
|
||||
QTest::addRow("top, negative margin") << int(Test::LayerSurfaceV1::anchor_top) << QMargins(0, -5, 0, 0) << 300 << 0 << QRectF(0, 295, 1280, 729);
|
||||
QTest::addRow("right, negative margin") << int(Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, -5, 0) << 300 << 0 << QRectF(0, 0, 985, 1024);
|
||||
QTest::addRow("bottom, negative margin") << int(Test::LayerSurfaceV1::anchor_bottom) << QMargins(0, 0, 0, -5) << 300 << 0 << QRectF(0, 0, 1280, 729);
|
||||
|
||||
QTest::addRow("left, positive margin") << int(Test::LayerSurfaceV1::anchor_left) << QMargins(5, 0, 0, 0) << 300 << 0 << QRectF(305, 0, 975, 1024);
|
||||
QTest::addRow("top, positive margin") << int(Test::LayerSurfaceV1::anchor_top) << QMargins(0, 5, 0, 0) << 300 << 0 << QRectF(0, 305, 1280, 719);
|
||||
QTest::addRow("right, positive margin") << int(Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 5, 0) << 300 << 0 << QRectF(0, 0, 975, 1024);
|
||||
QTest::addRow("bottom, positive margin") << int(Test::LayerSurfaceV1::anchor_bottom) << QMargins(0, 0, 0, 5) << 300 << 0 << QRectF(0, 0, 1280, 719);
|
||||
|
||||
QTest::addRow("left + left exclusive edge") << int(Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_left) << QRectF(300, 0, 980, 1024);
|
||||
QTest::addRow("top + top exclusive edge") << int(Test::LayerSurfaceV1::anchor_top) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_top) << QRectF(0, 300, 1280, 724);
|
||||
QTest::addRow("right + right exclusive edge") << int(Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_right) << QRectF(0, 0, 980, 1024);
|
||||
QTest::addRow("bottom + bottom exclusive edge") << int(Test::LayerSurfaceV1::anchor_bottom) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_bottom) << QRectF(0, 0, 1280, 724);
|
||||
|
||||
QTest::addRow("top | left + top exclusive edge") << int(Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_top) << QRectF(0, 300, 1280, 724);
|
||||
QTest::addRow("top | left + left exclusive edge") << int(Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_left) << QRectF(300, 0, 980, 1024);
|
||||
QTest::addRow("top | right + top exclusive edge") << int(Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_top) << QRectF(0, 300, 1280, 724);
|
||||
QTest::addRow("top | right + right exclusive edge") << int(Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_right) << QRectF(0, 0, 980, 1024);
|
||||
QTest::addRow("bottom | left + bottom exclusive edge") << int(Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_bottom) << QRectF(0, 0, 1280, 724);
|
||||
QTest::addRow("bottom | left + left exclusive edge") << int(Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_left) << QRectF(300, 0, 980, 1024);
|
||||
QTest::addRow("bottom | right + bottom exclusive edge") << int(Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_bottom) << QRectF(0, 0, 1280, 724);
|
||||
QTest::addRow("bottom | right + right exclusive edge") << int(Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_right) << QRectF(0, 0, 980, 1024);
|
||||
}
|
||||
|
||||
void LayerShellV1WindowTest::testPlacementArea()
|
||||
|
@ -384,9 +407,11 @@ void LayerShellV1WindowTest::testPlacementArea()
|
|||
QFETCH(int, anchor);
|
||||
QFETCH(QMargins, margins);
|
||||
QFETCH(int, exclusiveZone);
|
||||
QFETCH(int, exclusiveEdge);
|
||||
shellSurface->set_anchor(anchor);
|
||||
shellSurface->set_margin(margins.top(), margins.right(), margins.bottom(), margins.left());
|
||||
shellSurface->set_exclusive_zone(exclusiveZone);
|
||||
shellSurface->set_exclusive_edge(exclusiveEdge);
|
||||
shellSurface->set_size(280, 124);
|
||||
surface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
|
||||
|
@ -408,6 +433,54 @@ void LayerShellV1WindowTest::testPlacementArea()
|
|||
QVERIFY(Test::waitForWindowClosed(window));
|
||||
}
|
||||
|
||||
void LayerShellV1WindowTest::testPlacementAreaAfterOutputLayoutChange()
|
||||
{
|
||||
// This test verifies that layer shell windows correctly react to output layout changes.
|
||||
|
||||
// The output where the layer surface should be placed.
|
||||
Output *output = workspace()->activeOutput();
|
||||
|
||||
// Create a layer surface with an exclusive zone.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::LayerSurfaceV1> shellSurface(Test::createLayerSurfaceV1(surface.get(), QStringLiteral("dock"), Test::waylandOutput(output->name())));
|
||||
shellSurface->set_layer(Test::LayerShellV1::layer_top);
|
||||
shellSurface->set_anchor(Test::LayerSurfaceV1::anchor_bottom);
|
||||
shellSurface->set_size(100, 50);
|
||||
shellSurface->set_exclusive_edge(Test::LayerSurfaceV1::anchor_bottom);
|
||||
shellSurface->set_exclusive_zone(50);
|
||||
surface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
|
||||
// Wait for the compositor to position the layer surface.
|
||||
QSignalSpy configureRequestedSpy(shellSurface.get(), &Test::LayerSurfaceV1::configureRequested);
|
||||
QVERIFY(configureRequestedSpy.wait());
|
||||
shellSurface->ack_configure(configureRequestedSpy.last().at(0).toUInt());
|
||||
Window *window = Test::renderAndWaitForShown(surface.get(), configureRequestedSpy.last().at(1).toSize(), Qt::red);
|
||||
QVERIFY(window);
|
||||
QCOMPARE(workspace()->clientArea(PlacementArea, window), output->geometry().adjusted(0, 0, 0, -50));
|
||||
|
||||
// Move the output 100px down.
|
||||
OutputConfiguration config1;
|
||||
{
|
||||
auto changeSet = config1.changeSet(output);
|
||||
changeSet->pos = output->geometry().topLeft() + QPoint(0, 100);
|
||||
}
|
||||
workspace()->applyOutputConfiguration(config1);
|
||||
QCOMPARE(workspace()->clientArea(PlacementArea, window), output->geometry().adjusted(0, 0, 0, -50));
|
||||
|
||||
// Move the output back to its original position.
|
||||
OutputConfiguration config2;
|
||||
{
|
||||
auto changeSet = config2.changeSet(output);
|
||||
changeSet->pos = output->geometry().topLeft() - QPoint(0, 100);
|
||||
}
|
||||
workspace()->applyOutputConfiguration(config2);
|
||||
QCOMPARE(workspace()->clientArea(PlacementArea, window), output->geometry().adjusted(0, 0, 0, -50));
|
||||
|
||||
// Destroy the window.
|
||||
shellSurface.reset();
|
||||
QVERIFY(Test::waitForWindowClosed(window));
|
||||
}
|
||||
|
||||
void LayerShellV1WindowTest::testFill_data()
|
||||
{
|
||||
QTest::addColumn<int>("anchor");
|
||||
|
@ -672,10 +745,18 @@ void LayerShellV1WindowTest::testUnmap()
|
|||
QVERIFY(Test::waitForWindowClosed(window));
|
||||
}
|
||||
|
||||
void LayerShellV1WindowTest::testScreenEdge_data()
|
||||
{
|
||||
QTest::addColumn<QMargins>("margins");
|
||||
|
||||
QTest::addRow("normal") << QMargins(0, 0, 0, 0);
|
||||
QTest::addRow("with margin") << QMargins(0, 0, 0, 10);
|
||||
}
|
||||
|
||||
void LayerShellV1WindowTest::testScreenEdge()
|
||||
{
|
||||
auto config = kwinApp()->config();
|
||||
config->group(QStringLiteral("Windows")).writeEntry("ElectricBorderDelay", 150);
|
||||
config->group(QStringLiteral("Windows")).writeEntry("ElectricBorderDelay", 75);
|
||||
config->sync();
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
|
@ -685,9 +766,11 @@ void LayerShellV1WindowTest::testScreenEdge()
|
|||
std::unique_ptr<Test::AutoHideScreenEdgeV1> screenEdge(Test::createAutoHideScreenEdgeV1(surface.get(), Test::ScreenEdgeManagerV1::border_bottom));
|
||||
|
||||
// Set the initial state of the layer surface.
|
||||
QFETCH(QMargins, margins);
|
||||
shellSurface->set_layer(Test::LayerShellV1::layer_top);
|
||||
shellSurface->set_anchor(Test::LayerSurfaceV1::anchor_bottom);
|
||||
shellSurface->set_size(100, 50);
|
||||
shellSurface->set_margin(margins.top(), margins.right(), margins.bottom(), margins.left());
|
||||
surface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
|
||||
// Wait for the compositor to position the surface.
|
||||
|
@ -701,25 +784,24 @@ void LayerShellV1WindowTest::testScreenEdge()
|
|||
QVERIFY(window);
|
||||
QVERIFY(!window->isActive());
|
||||
|
||||
QSignalSpy windowShowSpy(window, &Window::windowShown);
|
||||
QSignalSpy windowHiddenSpy(window, &Window::windowHidden);
|
||||
QSignalSpy hiddenChangedSpy(window, &Window::hiddenChanged);
|
||||
quint32 timestamp = 0;
|
||||
|
||||
// The layer surface will be hidden and shown when the screen edge is activated or deactivated.
|
||||
{
|
||||
screenEdge->activate();
|
||||
QVERIFY(windowHiddenSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(!window->isShown());
|
||||
|
||||
screenEdge->deactivate();
|
||||
QVERIFY(windowShowSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(window->isShown());
|
||||
}
|
||||
|
||||
// The layer surface will be shown when the screen edge is triggered.
|
||||
{
|
||||
screenEdge->activate();
|
||||
QVERIFY(windowHiddenSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(!window->isShown());
|
||||
|
||||
Test::pointerMotion(QPointF(640, 1023), timestamp);
|
||||
|
@ -727,7 +809,7 @@ void LayerShellV1WindowTest::testScreenEdge()
|
|||
Test::pointerMotion(QPointF(640, 1023), timestamp);
|
||||
timestamp += 160;
|
||||
Test::pointerMotion(QPointF(640, 512), timestamp);
|
||||
QVERIFY(windowShowSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(window->isShown());
|
||||
}
|
||||
|
||||
|
@ -735,7 +817,7 @@ void LayerShellV1WindowTest::testScreenEdge()
|
|||
{
|
||||
QSignalSpy approachingSpy(workspace()->screenEdges(), &ScreenEdges::approaching);
|
||||
screenEdge->activate();
|
||||
QVERIFY(windowHiddenSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(!window->isShown());
|
||||
|
||||
Test::pointerMotion(QPointF(640, 1020), timestamp++);
|
||||
|
@ -744,7 +826,7 @@ void LayerShellV1WindowTest::testScreenEdge()
|
|||
QVERIFY(approachingSpy.last().at(1).toReal() != 0.0);
|
||||
|
||||
screenEdge->deactivate();
|
||||
QVERIFY(windowShowSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(window->isShown());
|
||||
QVERIFY(approachingSpy.last().at(1).toReal() == 0.0);
|
||||
|
||||
|
@ -754,11 +836,11 @@ void LayerShellV1WindowTest::testScreenEdge()
|
|||
// The layer surface will be shown when the screen edge is destroyed.
|
||||
{
|
||||
screenEdge->activate();
|
||||
QVERIFY(windowHiddenSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(!window->isShown());
|
||||
|
||||
screenEdge.reset();
|
||||
QVERIFY(windowShowSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(window->isShown());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,12 +67,19 @@ private Q_SLOTS:
|
|||
void testPointerShortcut();
|
||||
void testAxisShortcut_data();
|
||||
void testAxisShortcut();
|
||||
void testKeyboardShortcut();
|
||||
void testKeyboardLockShortcut();
|
||||
void testKeyboardShortcutsDisabledWhenLocked();
|
||||
void testTouch();
|
||||
|
||||
private:
|
||||
struct WindowHandle
|
||||
{
|
||||
Window *window;
|
||||
std::unique_ptr<KWayland::Client::Surface> surface;
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface;
|
||||
};
|
||||
void unlock();
|
||||
std::pair<Window *, std::unique_ptr<KWayland::Client::Surface>> showWindow();
|
||||
WindowHandle showWindow();
|
||||
KWayland::Client::ConnectionThread *m_connection = nullptr;
|
||||
KWayland::Client::Compositor *m_compositor = nullptr;
|
||||
KWayland::Client::Seat *m_seat = nullptr;
|
||||
|
@ -147,7 +154,7 @@ void LockScreenTest::unlock()
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<Window *, std::unique_ptr<KWayland::Client::Surface>> LockScreenTest::showWindow()
|
||||
LockScreenTest::WindowHandle LockScreenTest::showWindow()
|
||||
{
|
||||
#define VERIFY(statement) \
|
||||
if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__)) \
|
||||
|
@ -158,8 +165,8 @@ std::pair<Window *, std::unique_ptr<KWayland::Client::Surface>> LockScreenTest::
|
|||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
VERIFY(surface.get());
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
VERIFY(shellSurface);
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
VERIFY(shellSurface.get());
|
||||
// let's render
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
|
@ -169,7 +176,7 @@ std::pair<Window *, std::unique_ptr<KWayland::Client::Surface>> LockScreenTest::
|
|||
#undef VERIFY
|
||||
#undef COMPARE
|
||||
|
||||
return {window, std::move(surface)};
|
||||
return {window, std::move(surface), std::move(shellSurface)};
|
||||
}
|
||||
|
||||
void LockScreenTest::initTestCase()
|
||||
|
@ -223,7 +230,7 @@ void LockScreenTest::testStackingOrder()
|
|||
Window *window = windowAddedSpy.first().first().value<Window *>();
|
||||
QVERIFY(window);
|
||||
QVERIFY(window->isLockScreen());
|
||||
QCOMPARE(window->layer(), UnmanagedLayer);
|
||||
QCOMPARE(window->layer(), OverlayLayer);
|
||||
|
||||
UNLOCK;
|
||||
}
|
||||
|
@ -235,7 +242,7 @@ void LockScreenTest::testPointer()
|
|||
QSignalSpy enteredSpy(pointer.get(), &KWayland::Client::Pointer::entered);
|
||||
QSignalSpy leftSpy(pointer.get(), &KWayland::Client::Pointer::left);
|
||||
|
||||
auto [window, surface] = showWindow();
|
||||
auto [window, surface, shellSurface] = showWindow();
|
||||
QVERIFY(window);
|
||||
|
||||
// first move cursor into the center of the window
|
||||
|
@ -278,7 +285,7 @@ void LockScreenTest::testPointerButton()
|
|||
QSignalSpy enteredSpy(pointer.get(), &KWayland::Client::Pointer::entered);
|
||||
QSignalSpy buttonChangedSpy(pointer.get(), &KWayland::Client::Pointer::buttonStateChanged);
|
||||
|
||||
auto [window, surface] = showWindow();
|
||||
auto [window, surface, shellSurface] = showWindow();
|
||||
QVERIFY(window);
|
||||
|
||||
// first move cursor into the center of the window
|
||||
|
@ -317,7 +324,7 @@ void LockScreenTest::testPointerAxis()
|
|||
QSignalSpy axisChangedSpy(pointer.get(), &KWayland::Client::Pointer::axisChanged);
|
||||
QSignalSpy enteredSpy(pointer.get(), &KWayland::Client::Pointer::entered);
|
||||
|
||||
auto [window, surface] = showWindow();
|
||||
auto [window, surface, shellSurface] = showWindow();
|
||||
QVERIFY(window);
|
||||
|
||||
// first move cursor into the center of the window
|
||||
|
@ -356,7 +363,7 @@ void LockScreenTest::testKeyboard()
|
|||
QSignalSpy leftSpy(keyboard.get(), &KWayland::Client::Keyboard::left);
|
||||
QSignalSpy keyChangedSpy(keyboard.get(), &KWayland::Client::Keyboard::keyChanged);
|
||||
|
||||
auto [window, surface] = showWindow();
|
||||
auto [window, surface, shellSurface] = showWindow();
|
||||
QVERIFY(window);
|
||||
QVERIFY(enteredSpy.wait());
|
||||
QTRY_COMPARE(enteredSpy.count(), 1);
|
||||
|
@ -553,7 +560,7 @@ void LockScreenTest::testEffectsKeyboardAutorepeat()
|
|||
|
||||
void LockScreenTest::testMoveWindow()
|
||||
{
|
||||
auto [window, surface] = showWindow();
|
||||
auto [window, surface, shellSurface] = showWindow();
|
||||
QVERIFY(window);
|
||||
QSignalSpy interactiveMoveResizeSteppedSpy(window, &Window::interactiveMoveResizeStepped);
|
||||
quint32 timestamp = 1;
|
||||
|
@ -685,7 +692,10 @@ void LockScreenTest::testAxisShortcut()
|
|||
#undef PERFORM
|
||||
}
|
||||
|
||||
void LockScreenTest::testKeyboardShortcut()
|
||||
/**
|
||||
* This test verifies that keyboard shortcuts are disabled when the screen is locked
|
||||
*/
|
||||
void LockScreenTest::testKeyboardShortcutsDisabledWhenLocked()
|
||||
{
|
||||
#if !KWIN_BUILD_GLOBALSHORTCUTS
|
||||
QSKIP("Can't test shortcuts without shortcuts");
|
||||
|
@ -732,12 +742,49 @@ void LockScreenTest::testKeyboardShortcut()
|
|||
KEYRELEASE(KEY_LEFTALT);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test verifies that the global keyboard shortcut to lock the screen works
|
||||
*/
|
||||
void LockScreenTest::testKeyboardLockShortcut()
|
||||
{
|
||||
#if !KWIN_BUILD_GLOBALSHORTCUTS
|
||||
QSKIP("Can't test shortcuts without shortcuts");
|
||||
return;
|
||||
#endif
|
||||
|
||||
QList<QKeySequence> shortcuts = KGlobalAccel::self()->globalShortcut("ksmserver", "Lock Session");
|
||||
// Verify the shortcut is Meta + L, the default
|
||||
QCOMPARE(shortcuts.first().toString(), QString("Meta+L"));
|
||||
|
||||
// Verify the screen is not locked
|
||||
QVERIFY(!waylandServer()->isScreenLocked());
|
||||
|
||||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
|
||||
// Trigger the shortcut
|
||||
quint32 timestamp = 1;
|
||||
KEYPRESS(KEY_LEFTMETA);
|
||||
KEYPRESS(KEY_L);
|
||||
KEYRELEASE(KEY_L);
|
||||
KEYRELEASE(KEY_LEFTMETA);
|
||||
|
||||
// Verify the screen gets locked
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
Window *window = windowAddedSpy.first().first().value<Window *>();
|
||||
QVERIFY(window);
|
||||
QVERIFY(window->isLockScreen());
|
||||
QTRY_COMPARE(ScreenLocker::KSldApp::self()->lockState(), ScreenLocker::KSldApp::Locked);
|
||||
QVERIFY(waylandServer()->isScreenLocked());
|
||||
|
||||
UNLOCK;
|
||||
}
|
||||
|
||||
void LockScreenTest::testTouch()
|
||||
{
|
||||
auto touch = m_seat->createTouch(m_seat);
|
||||
QVERIFY(touch);
|
||||
QVERIFY(touch->isValid());
|
||||
auto [window, surface] = showWindow();
|
||||
auto [window, surface, shellSurface] = showWindow();
|
||||
QVERIFY(window);
|
||||
QSignalSpy sequenceStartedSpy(touch, &KWayland::Client::Touch::sequenceStarted);
|
||||
QSignalSpy cancelSpy(touch, &KWayland::Client::Touch::sequenceCanceled);
|
||||
|
|
|
@ -1,376 +0,0 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include <config-kwin.h>
|
||||
|
||||
#include "kwin_wayland_test.h"
|
||||
|
||||
#include "input.h"
|
||||
#include "keyboard_input.h"
|
||||
#include "pointer_input.h"
|
||||
#include "wayland_server.h"
|
||||
#include "workspace.h"
|
||||
#include "xkb.h"
|
||||
|
||||
#include <KConfigGroup>
|
||||
|
||||
#include <QDBusConnection>
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
using namespace KWin;
|
||||
|
||||
static const QString s_socketName = QStringLiteral("wayland_test_kwin_modifier_only_shortcut-0");
|
||||
static const QString s_serviceName = QStringLiteral("org.kde.KWin.Test.ModifierOnlyShortcut");
|
||||
static const QString s_path = QStringLiteral("/Test");
|
||||
|
||||
class ModifierOnlyShortcutTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
void testTrigger_data();
|
||||
void testTrigger();
|
||||
void testCapsLock();
|
||||
void testGlobalShortcutsDisabled_data();
|
||||
void testGlobalShortcutsDisabled();
|
||||
};
|
||||
|
||||
class Target : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.kde.KWin.Test.ModifierOnlyShortcut")
|
||||
|
||||
public:
|
||||
Target();
|
||||
~Target() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
Q_SCRIPTABLE void shortcut();
|
||||
|
||||
Q_SIGNALS:
|
||||
void shortcutTriggered();
|
||||
};
|
||||
|
||||
Target::Target()
|
||||
: QObject()
|
||||
{
|
||||
QDBusConnection::sessionBus().registerService(s_serviceName);
|
||||
QDBusConnection::sessionBus().registerObject(s_path, s_serviceName, this, QDBusConnection::ExportScriptableSlots);
|
||||
}
|
||||
|
||||
Target::~Target()
|
||||
{
|
||||
QDBusConnection::sessionBus().unregisterObject(s_path);
|
||||
QDBusConnection::sessionBus().unregisterService(s_serviceName);
|
||||
}
|
||||
|
||||
void Target::shortcut()
|
||||
{
|
||||
Q_EMIT shortcutTriggered();
|
||||
}
|
||||
|
||||
void ModifierOnlyShortcutTest::initTestCase()
|
||||
{
|
||||
QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
|
||||
QVERIFY(waylandServer()->init(s_socketName));
|
||||
Test::setOutputConfig({
|
||||
QRect(0, 0, 1280, 1024),
|
||||
QRect(1280, 0, 1280, 1024),
|
||||
});
|
||||
|
||||
kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
|
||||
qputenv("KWIN_XKB_DEFAULT_KEYMAP", "1");
|
||||
qputenv("XKB_DEFAULT_RULES", "evdev");
|
||||
|
||||
kwinApp()->start();
|
||||
QVERIFY(applicationStartedSpy.wait());
|
||||
}
|
||||
|
||||
void ModifierOnlyShortcutTest::init()
|
||||
{
|
||||
workspace()->setActiveOutput(QPoint(640, 512));
|
||||
KWin::input()->pointer()->warp(QPoint(640, 512));
|
||||
}
|
||||
|
||||
void ModifierOnlyShortcutTest::cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
void ModifierOnlyShortcutTest::testTrigger_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("metaConfig");
|
||||
QTest::addColumn<QStringList>("altConfig");
|
||||
QTest::addColumn<QStringList>("controlConfig");
|
||||
QTest::addColumn<QStringList>("shiftConfig");
|
||||
QTest::addColumn<int>("modifier");
|
||||
QTest::addColumn<QList<int>>("nonTriggeringMods");
|
||||
|
||||
const QStringList trigger = QStringList{s_serviceName, s_path, s_serviceName, QStringLiteral("shortcut")};
|
||||
const QStringList e = QStringList();
|
||||
|
||||
QTest::newRow("leftMeta") << trigger << e << e << e << KEY_LEFTMETA << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
||||
QTest::newRow("rightMeta") << trigger << e << e << e << KEY_RIGHTMETA << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
||||
QTest::newRow("leftAlt") << e << trigger << e << e << KEY_LEFTALT << QList<int>{KEY_LEFTMETA, KEY_RIGHTMETA, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
||||
QTest::newRow("rightAlt") << e << trigger << e << e << KEY_RIGHTALT << QList<int>{KEY_LEFTMETA, KEY_RIGHTMETA, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
||||
QTest::newRow("leftControl") << e << e << trigger << e << KEY_LEFTCTRL << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTMETA, KEY_RIGHTMETA, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
||||
QTest::newRow("rightControl") << e << e << trigger << e << KEY_RIGHTCTRL << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTMETA, KEY_RIGHTMETA, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
||||
QTest::newRow("leftShift") << e << e << e << trigger << KEY_LEFTSHIFT << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTMETA, KEY_RIGHTMETA};
|
||||
QTest::newRow("rightShift") << e << e << e << trigger << KEY_RIGHTSHIFT << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTMETA, KEY_RIGHTMETA};
|
||||
}
|
||||
|
||||
void ModifierOnlyShortcutTest::testTrigger()
|
||||
{
|
||||
// this test verifies that modifier only shortcut triggers correctly
|
||||
Target target;
|
||||
QSignalSpy triggeredSpy(&target, &Target::shortcutTriggered);
|
||||
|
||||
KConfigGroup group = kwinApp()->config()->group(QStringLiteral("ModifierOnlyShortcuts"));
|
||||
QFETCH(QStringList, metaConfig);
|
||||
QFETCH(QStringList, altConfig);
|
||||
QFETCH(QStringList, shiftConfig);
|
||||
QFETCH(QStringList, controlConfig);
|
||||
group.writeEntry("Meta", metaConfig);
|
||||
group.writeEntry("Alt", altConfig);
|
||||
group.writeEntry("Shift", shiftConfig);
|
||||
group.writeEntry("Control", controlConfig);
|
||||
group.sync();
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
// configured shortcut should trigger
|
||||
quint32 timestamp = 1;
|
||||
QFETCH(int, modifier);
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 1);
|
||||
|
||||
// the other shortcuts should not trigger
|
||||
QFETCH(QList<int>, nonTriggeringMods);
|
||||
for (auto it = nonTriggeringMods.constBegin(), end = nonTriggeringMods.constEnd(); it != end; it++) {
|
||||
Test::keyboardKeyPressed(*it, timestamp++);
|
||||
Test::keyboardKeyReleased(*it, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 1);
|
||||
}
|
||||
|
||||
// try configured again
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 2);
|
||||
|
||||
// click another key while modifier is held
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::keyboardKeyPressed(KEY_A, timestamp++);
|
||||
Test::keyboardKeyReleased(KEY_A, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 2);
|
||||
|
||||
// release other key after modifier release
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::keyboardKeyPressed(KEY_A, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
Test::keyboardKeyReleased(KEY_A, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 2);
|
||||
|
||||
// press key before pressing modifier
|
||||
Test::keyboardKeyPressed(KEY_A, timestamp++);
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
Test::keyboardKeyReleased(KEY_A, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 2);
|
||||
|
||||
// mouse button pressed before clicking modifier
|
||||
Test::pointerButtonPressed(BTN_LEFT, timestamp++);
|
||||
QCOMPARE(input()->qtButtonStates(), Qt::LeftButton);
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
Test::pointerButtonReleased(BTN_LEFT, timestamp++);
|
||||
QCOMPARE(input()->qtButtonStates(), Qt::NoButton);
|
||||
QCOMPARE(triggeredSpy.count(), 2);
|
||||
|
||||
// mouse button press before mod press, release before mod release
|
||||
Test::pointerButtonPressed(BTN_LEFT, timestamp++);
|
||||
QCOMPARE(input()->qtButtonStates(), Qt::LeftButton);
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::pointerButtonReleased(BTN_LEFT, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(input()->qtButtonStates(), Qt::NoButton);
|
||||
QCOMPARE(triggeredSpy.count(), 2);
|
||||
|
||||
// mouse button click while mod is pressed
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::pointerButtonPressed(BTN_LEFT, timestamp++);
|
||||
QCOMPARE(input()->qtButtonStates(), Qt::LeftButton);
|
||||
Test::pointerButtonReleased(BTN_LEFT, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(input()->qtButtonStates(), Qt::NoButton);
|
||||
QCOMPARE(triggeredSpy.count(), 2);
|
||||
|
||||
// scroll while mod is pressed
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::pointerAxisVertical(5.0, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 2);
|
||||
|
||||
// same for horizontal
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::pointerAxisHorizontal(5.0, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 2);
|
||||
|
||||
#if KWIN_BUILD_SCREENLOCKER
|
||||
// now try to lock the screen while modifier key is pressed
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
QVERIFY(Test::lockScreen());
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 2);
|
||||
|
||||
// now trigger while screen is locked, should also not work
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 2);
|
||||
|
||||
QVERIFY(Test::unlockScreen());
|
||||
#endif
|
||||
}
|
||||
|
||||
void ModifierOnlyShortcutTest::testCapsLock()
|
||||
{
|
||||
// this test verifies that Capslock does not trigger the shift shortcut
|
||||
// but other shortcuts still trigger even when Capslock is on
|
||||
Target target;
|
||||
QSignalSpy triggeredSpy(&target, &Target::shortcutTriggered);
|
||||
|
||||
KConfigGroup group = kwinApp()->config()->group(QStringLiteral("ModifierOnlyShortcuts"));
|
||||
group.writeEntry("Meta", QStringList());
|
||||
group.writeEntry("Alt", QStringList());
|
||||
group.writeEntry("Shift", QStringList{s_serviceName, s_path, s_serviceName, QStringLiteral("shortcut")});
|
||||
group.writeEntry("Control", QStringList());
|
||||
group.sync();
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
// first test that the normal shortcut triggers
|
||||
quint32 timestamp = 1;
|
||||
const int modifier = KEY_LEFTSHIFT;
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 1);
|
||||
|
||||
// now capslock
|
||||
Test::keyboardKeyPressed(KEY_CAPSLOCK, timestamp++);
|
||||
Test::keyboardKeyReleased(KEY_CAPSLOCK, timestamp++);
|
||||
QCOMPARE(input()->keyboardModifiers(), Qt::ShiftModifier);
|
||||
QCOMPARE(triggeredSpy.count(), 1);
|
||||
|
||||
// currently caps lock is on
|
||||
// shift still triggers
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(input()->keyboardModifiers(), Qt::ShiftModifier);
|
||||
QCOMPARE(triggeredSpy.count(), 2);
|
||||
|
||||
// meta should also trigger
|
||||
group.writeEntry("Meta", QStringList{s_serviceName, s_path, s_serviceName, QStringLiteral("shortcut")});
|
||||
group.writeEntry("Alt", QStringList());
|
||||
group.writeEntry("Shift", QStringList{});
|
||||
group.writeEntry("Control", QStringList());
|
||||
group.sync();
|
||||
workspace()->slotReconfigure();
|
||||
Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++);
|
||||
QCOMPARE(input()->keyboardModifiers(), Qt::ShiftModifier | Qt::MetaModifier);
|
||||
QCOMPARE(input()->keyboard()->xkb()->modifiersRelevantForGlobalShortcuts(), Qt::MetaModifier);
|
||||
Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 3);
|
||||
|
||||
// set back to shift to ensure we don't trigger with capslock
|
||||
group.writeEntry("Meta", QStringList());
|
||||
group.writeEntry("Alt", QStringList());
|
||||
group.writeEntry("Shift", QStringList{s_serviceName, s_path, s_serviceName, QStringLiteral("shortcut")});
|
||||
group.writeEntry("Control", QStringList());
|
||||
group.sync();
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
// release caps lock
|
||||
Test::keyboardKeyPressed(KEY_CAPSLOCK, timestamp++);
|
||||
Test::keyboardKeyReleased(KEY_CAPSLOCK, timestamp++);
|
||||
QCOMPARE(input()->keyboardModifiers(), Qt::NoModifier);
|
||||
QCOMPARE(triggeredSpy.count(), 3);
|
||||
}
|
||||
|
||||
void ModifierOnlyShortcutTest::testGlobalShortcutsDisabled_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("metaConfig");
|
||||
QTest::addColumn<QStringList>("altConfig");
|
||||
QTest::addColumn<QStringList>("controlConfig");
|
||||
QTest::addColumn<QStringList>("shiftConfig");
|
||||
QTest::addColumn<int>("modifier");
|
||||
|
||||
const QStringList trigger = QStringList{s_serviceName, s_path, s_serviceName, QStringLiteral("shortcut")};
|
||||
const QStringList e = QStringList();
|
||||
|
||||
QTest::newRow("leftMeta") << trigger << e << e << e << KEY_LEFTMETA;
|
||||
QTest::newRow("rightMeta") << trigger << e << e << e << KEY_RIGHTMETA;
|
||||
QTest::newRow("leftAlt") << e << trigger << e << e << KEY_LEFTALT;
|
||||
QTest::newRow("rightAlt") << e << trigger << e << e << KEY_RIGHTALT;
|
||||
QTest::newRow("leftControl") << e << e << trigger << e << KEY_LEFTCTRL;
|
||||
QTest::newRow("rightControl") << e << e << trigger << e << KEY_RIGHTCTRL;
|
||||
QTest::newRow("leftShift") << e << e << e << trigger << KEY_LEFTSHIFT;
|
||||
QTest::newRow("rightShift") << e << e << e << trigger << KEY_RIGHTSHIFT;
|
||||
}
|
||||
|
||||
void ModifierOnlyShortcutTest::testGlobalShortcutsDisabled()
|
||||
{
|
||||
// this test verifies that when global shortcuts are disabled inside KWin (e.g. through a window rule)
|
||||
// the modifier only shortcuts do not trigger.
|
||||
// see BUG: 370146
|
||||
Target target;
|
||||
QSignalSpy triggeredSpy(&target, &Target::shortcutTriggered);
|
||||
|
||||
KConfigGroup group = kwinApp()->config()->group(QStringLiteral("ModifierOnlyShortcuts"));
|
||||
QFETCH(QStringList, metaConfig);
|
||||
QFETCH(QStringList, altConfig);
|
||||
QFETCH(QStringList, shiftConfig);
|
||||
QFETCH(QStringList, controlConfig);
|
||||
group.writeEntry("Meta", metaConfig);
|
||||
group.writeEntry("Alt", altConfig);
|
||||
group.writeEntry("Shift", shiftConfig);
|
||||
group.writeEntry("Control", controlConfig);
|
||||
group.sync();
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
// trigger once to verify the shortcut works
|
||||
quint32 timestamp = 1;
|
||||
QFETCH(int, modifier);
|
||||
QVERIFY(!workspace()->globalShortcutsDisabled());
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 1);
|
||||
triggeredSpy.clear();
|
||||
|
||||
// now disable global shortcuts
|
||||
workspace()->disableGlobalShortcutsForClient(true);
|
||||
QVERIFY(workspace()->globalShortcutsDisabled());
|
||||
// Should not get triggered
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 0);
|
||||
triggeredSpy.clear();
|
||||
|
||||
// enable again
|
||||
workspace()->disableGlobalShortcutsForClient(false);
|
||||
QVERIFY(!workspace()->globalShortcutsDisabled());
|
||||
// should get triggered again
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 1);
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(ModifierOnlyShortcutTest)
|
||||
#include "modifier_only_shortcut_test.moc"
|
|
@ -54,11 +54,6 @@ private Q_SLOTS:
|
|||
void testPointerMoveEnd_data();
|
||||
void testPointerMoveEnd();
|
||||
void testClientSideMove();
|
||||
void testNetMove();
|
||||
void testAdjustClientGeometryOfHiddenX11Panel_data();
|
||||
void testAdjustClientGeometryOfHiddenX11Panel();
|
||||
void testAdjustClientGeometryOfHiddenWaylandPanel_data();
|
||||
void testAdjustClientGeometryOfHiddenWaylandPanel();
|
||||
void testResizeForVirtualKeyboard_data();
|
||||
void testResizeForVirtualKeyboard();
|
||||
void testResizeForVirtualKeyboardWithMaximize();
|
||||
|
@ -536,234 +531,6 @@ void MoveResizeWindowTest::testClientSideMove()
|
|||
QCOMPARE(pointerEnteredSpy.last().last().toPoint(), QPoint(50, 25));
|
||||
}
|
||||
|
||||
void MoveResizeWindowTest::testNetMove()
|
||||
{
|
||||
// this test verifies that a move request for an X11 window through NET API works
|
||||
// create an xcb window
|
||||
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||
|
||||
xcb_window_t windowId = xcb_generate_id(c.get());
|
||||
xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId, rootWindow(),
|
||||
0, 0, 100, 100,
|
||||
0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr);
|
||||
xcb_size_hints_t hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
xcb_icccm_size_hints_set_position(&hints, 1, 0, 0);
|
||||
xcb_icccm_size_hints_set_size(&hints, 1, 100, 100);
|
||||
xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints);
|
||||
// let's set a no-border
|
||||
NETWinInfo winInfo(c.get(), windowId, rootWindow(), NET::WMWindowType, NET::Properties2());
|
||||
winInfo.setWindowType(NET::Override);
|
||||
xcb_map_window(c.get(), windowId);
|
||||
xcb_flush(c.get());
|
||||
|
||||
QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
|
||||
QVERIFY(windowCreatedSpy.wait());
|
||||
X11Window *window = windowCreatedSpy.first().first().value<X11Window *>();
|
||||
QVERIFY(window);
|
||||
QCOMPARE(window->window(), windowId);
|
||||
const QRectF origGeo = window->frameGeometry();
|
||||
|
||||
// let's move the cursor outside the window
|
||||
input()->pointer()->warp(workspace()->activeOutput()->geometry().center());
|
||||
QVERIFY(!exclusiveContains(origGeo, Cursors::self()->mouse()->pos()));
|
||||
|
||||
QSignalSpy interactiveMoveResizeStartedSpy(window, &X11Window::interactiveMoveResizeStarted);
|
||||
QSignalSpy interactiveMoveResizeFinishedSpy(window, &X11Window::interactiveMoveResizeFinished);
|
||||
QSignalSpy interactiveMoveResizeSteppedSpy(window, &X11Window::interactiveMoveResizeStepped);
|
||||
QVERIFY(!workspace()->moveResizeWindow());
|
||||
|
||||
// use NETRootInfo to trigger a move request
|
||||
NETRootInfo root(c.get(), NET::Properties());
|
||||
root.moveResizeRequest(windowId, origGeo.center().x(), origGeo.center().y(), NET::Move);
|
||||
xcb_flush(c.get());
|
||||
|
||||
QVERIFY(interactiveMoveResizeStartedSpy.wait());
|
||||
QCOMPARE(workspace()->moveResizeWindow(), window);
|
||||
QVERIFY(window->isInteractiveMove());
|
||||
QCOMPARE(window->geometryRestore(), origGeo);
|
||||
QCOMPARE(Cursors::self()->mouse()->pos(), origGeo.center());
|
||||
|
||||
// let's move a step
|
||||
input()->pointer()->warp(Cursors::self()->mouse()->pos() + QPoint(10, 10));
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.first().last(), origGeo.translated(10, 10));
|
||||
|
||||
// let's cancel the move resize again through the net API
|
||||
root.moveResizeRequest(windowId, window->frameGeometry().center().x(), window->frameGeometry().center().y(), NET::MoveResizeCancel);
|
||||
xcb_flush(c.get());
|
||||
QVERIFY(interactiveMoveResizeFinishedSpy.wait());
|
||||
|
||||
// and destroy the window again
|
||||
xcb_unmap_window(c.get(), windowId);
|
||||
xcb_destroy_window(c.get(), windowId);
|
||||
xcb_flush(c.get());
|
||||
c.reset();
|
||||
|
||||
QSignalSpy windowClosedSpy(window, &X11Window::closed);
|
||||
QVERIFY(windowClosedSpy.wait());
|
||||
}
|
||||
|
||||
void MoveResizeWindowTest::testAdjustClientGeometryOfHiddenX11Panel_data()
|
||||
{
|
||||
QTest::addColumn<QRect>("panelGeometry");
|
||||
QTest::addColumn<QPoint>("targetPoint");
|
||||
QTest::addColumn<QPoint>("expectedAdjustedPoint");
|
||||
QTest::addColumn<quint32>("hideLocation");
|
||||
|
||||
QTest::newRow("top") << QRect(0, 0, 100, 20) << QPoint(50, 25) << QPoint(50, 20) << 0u;
|
||||
QTest::newRow("bottom") << QRect(0, 1024 - 20, 100, 20) << QPoint(50, 1024 - 25 - 50) << QPoint(50, 1024 - 20 - 50) << 2u;
|
||||
QTest::newRow("left") << QRect(0, 0, 20, 100) << QPoint(25, 50) << QPoint(20, 50) << 3u;
|
||||
QTest::newRow("right") << QRect(1280 - 20, 0, 20, 100) << QPoint(1280 - 25 - 100, 50) << QPoint(1280 - 20 - 100, 50) << 1u;
|
||||
}
|
||||
|
||||
void MoveResizeWindowTest::testAdjustClientGeometryOfHiddenX11Panel()
|
||||
{
|
||||
// this test verifies that auto hiding panels are ignored when adjusting client geometry
|
||||
// see BUG 365892
|
||||
|
||||
// first create our panel
|
||||
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||
|
||||
xcb_window_t windowId = xcb_generate_id(c.get());
|
||||
QFETCH(QRect, panelGeometry);
|
||||
xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId, rootWindow(),
|
||||
panelGeometry.x(), panelGeometry.y(), panelGeometry.width(), panelGeometry.height(),
|
||||
0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr);
|
||||
xcb_size_hints_t hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
xcb_icccm_size_hints_set_position(&hints, 1, panelGeometry.x(), panelGeometry.y());
|
||||
xcb_icccm_size_hints_set_size(&hints, 1, panelGeometry.width(), panelGeometry.height());
|
||||
xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints);
|
||||
NETWinInfo winInfo(c.get(), windowId, rootWindow(), NET::WMWindowType, NET::Properties2());
|
||||
winInfo.setWindowType(NET::Dock);
|
||||
xcb_map_window(c.get(), windowId);
|
||||
xcb_flush(c.get());
|
||||
|
||||
QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
|
||||
QVERIFY(windowCreatedSpy.wait());
|
||||
X11Window *panel = windowCreatedSpy.first().first().value<X11Window *>();
|
||||
QVERIFY(panel);
|
||||
QCOMPARE(panel->window(), windowId);
|
||||
QCOMPARE(panel->frameGeometry(), panelGeometry);
|
||||
QVERIFY(panel->isDock());
|
||||
|
||||
// let's create a window
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
QVERIFY(surface != nullptr);
|
||||
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
QVERIFY(shellSurface != nullptr);
|
||||
auto testWindow = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
QVERIFY(testWindow);
|
||||
QVERIFY(testWindow->isMovable());
|
||||
// panel is not yet hidden, we should snap against it
|
||||
QFETCH(QPoint, targetPoint);
|
||||
QTEST(Workspace::self()->adjustWindowPosition(testWindow, targetPoint, false).toPoint(), "expectedAdjustedPoint");
|
||||
|
||||
// now let's hide the panel
|
||||
QSignalSpy panelHiddenSpy(panel, &Window::windowHidden);
|
||||
QFETCH(quint32, hideLocation);
|
||||
xcb_change_property(c.get(), XCB_PROP_MODE_REPLACE, windowId, atoms->kde_screen_edge_show, XCB_ATOM_CARDINAL, 32, 1, &hideLocation);
|
||||
xcb_flush(c.get());
|
||||
QVERIFY(panelHiddenSpy.wait());
|
||||
|
||||
// now try to snap again
|
||||
QCOMPARE(Workspace::self()->adjustWindowPosition(testWindow, targetPoint, false), targetPoint);
|
||||
|
||||
// and destroy the panel again
|
||||
xcb_unmap_window(c.get(), windowId);
|
||||
xcb_destroy_window(c.get(), windowId);
|
||||
xcb_flush(c.get());
|
||||
c.reset();
|
||||
|
||||
QSignalSpy panelClosedSpy(panel, &X11Window::closed);
|
||||
QVERIFY(panelClosedSpy.wait());
|
||||
|
||||
// snap once more
|
||||
QCOMPARE(Workspace::self()->adjustWindowPosition(testWindow, targetPoint, false), targetPoint);
|
||||
|
||||
// and close
|
||||
QSignalSpy windowClosedSpy(testWindow, &Window::closed);
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(windowClosedSpy.wait());
|
||||
}
|
||||
|
||||
void MoveResizeWindowTest::testAdjustClientGeometryOfHiddenWaylandPanel_data()
|
||||
{
|
||||
QTest::addColumn<uint32_t>("anchor");
|
||||
QTest::addColumn<QRect>("panelGeometry");
|
||||
QTest::addColumn<QPoint>("targetPoint");
|
||||
QTest::addColumn<QPoint>("expectedAdjustedPoint");
|
||||
|
||||
QTest::newRow("top") << uint32_t(Test::LayerSurfaceV1::anchor_top) << QRect(0, 0, 1280, 20) << QPoint(50, 25) << QPoint(50, 20);
|
||||
QTest::newRow("bottom") << uint32_t(Test::LayerSurfaceV1::anchor_bottom) << QRect(0, 1024 - 20, 1280, 20) << QPoint(50, 1024 - 25 - 50) << QPoint(50, 1024 - 20 - 50);
|
||||
QTest::newRow("left") << uint32_t(Test::LayerSurfaceV1::anchor_left) << QRect(0, 0, 20, 1024) << QPoint(25, 50) << QPoint(20, 50);
|
||||
QTest::newRow("right") << uint32_t(Test::LayerSurfaceV1::anchor_right) << QRect(1280 - 20, 0, 20, 1024) << QPoint(1280 - 25 - 100, 50) << QPoint(1280 - 20 - 100, 50);
|
||||
}
|
||||
|
||||
void MoveResizeWindowTest::testAdjustClientGeometryOfHiddenWaylandPanel()
|
||||
{
|
||||
// this test verifies that hidden panels are ignored when adjusting client geometry
|
||||
// see BUG 365892
|
||||
|
||||
// first create our panel
|
||||
std::unique_ptr<KWayland::Client::Surface> panelSurface(Test::createSurface());
|
||||
std::unique_ptr<Test::LayerSurfaceV1> panelShellSurface(Test::createLayerSurfaceV1(panelSurface.get(), QStringLiteral("dock")));
|
||||
QFETCH(QRect, panelGeometry);
|
||||
QFETCH(uint32_t, anchor);
|
||||
panelShellSurface->set_anchor(anchor);
|
||||
panelShellSurface->set_size(panelGeometry.width(), panelGeometry.height());
|
||||
panelSurface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
|
||||
// let's render
|
||||
QSignalSpy panelConfigureRequestedSpy(panelShellSurface.get(), &Test::LayerSurfaceV1::configureRequested);
|
||||
QVERIFY(panelConfigureRequestedSpy.wait());
|
||||
auto panel = Test::renderAndWaitForShown(panelSurface.get(), panelConfigureRequestedSpy.last().at(1).toSize(), Qt::blue);
|
||||
QVERIFY(panel);
|
||||
QCOMPARE(panel->frameGeometry(), panelGeometry);
|
||||
QVERIFY(panel->isDock());
|
||||
|
||||
// let's create a window
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
QVERIFY(surface != nullptr);
|
||||
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
QVERIFY(shellSurface != nullptr);
|
||||
auto testWindow = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
QVERIFY(testWindow);
|
||||
QVERIFY(testWindow->isMovable());
|
||||
// panel is not yet hidden, we should snap against it
|
||||
QFETCH(QPoint, targetPoint);
|
||||
QTEST(Workspace::self()->adjustWindowPosition(testWindow, targetPoint, false).toPoint(), "expectedAdjustedPoint");
|
||||
|
||||
// now let's hide the panel
|
||||
panel->setHidden(true);
|
||||
|
||||
// now try to snap again
|
||||
QCOMPARE(Workspace::self()->adjustWindowPosition(testWindow, targetPoint, false), targetPoint);
|
||||
|
||||
// and destroy the panel again
|
||||
QSignalSpy panelClosedSpy(panel, &Window::closed);
|
||||
panelShellSurface.reset();
|
||||
panelSurface.reset();
|
||||
QVERIFY(panelClosedSpy.wait());
|
||||
|
||||
// snap once more
|
||||
QCOMPARE(Workspace::self()->adjustWindowPosition(testWindow, targetPoint, false), targetPoint);
|
||||
|
||||
// and close
|
||||
QSignalSpy windowClosedSpy(testWindow, &Window::closed);
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(windowClosedSpy.wait());
|
||||
}
|
||||
|
||||
void MoveResizeWindowTest::testResizeForVirtualKeyboard_data()
|
||||
{
|
||||
QTest::addColumn<QRect>("windowRect");
|
||||
|
@ -1039,6 +806,12 @@ void MoveResizeWindowTest::testCancelInteractiveMoveResize()
|
|||
QVERIFY(shellSurface != nullptr);
|
||||
Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(window);
|
||||
QSignalSpy frameGeomtryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
||||
// tile / maximize window
|
||||
QFETCH(QuickTileMode, quickTileMode);
|
||||
|
@ -1048,21 +821,20 @@ void MoveResizeWindowTest::testCancelInteractiveMoveResize()
|
|||
} else {
|
||||
window->setQuickTileMode(quickTileMode, true);
|
||||
}
|
||||
QCOMPARE(window->quickTileMode(), quickTileMode);
|
||||
QCOMPARE(window->requestedQuickTileMode(), quickTileMode);
|
||||
QCOMPARE(window->requestedMaximizeMode(), maximizeMode);
|
||||
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().first().toSize(), Qt::blue);
|
||||
|
||||
QVERIFY(frameGeomtryChangedSpy.wait());
|
||||
QCOMPARE(window->quickTileMode(), quickTileMode);
|
||||
const QRectF geometry = window->moveResizeGeometry();
|
||||
const QRectF geometryRestore = window->geometryRestore();
|
||||
|
||||
// Start resizing the client.
|
||||
QSignalSpy interactiveMoveResizeStartedSpy(window, &Window::interactiveMoveResizeStarted);
|
||||
QSignalSpy interactiveMoveResizeFinishedSpy(window, &Window::interactiveMoveResizeFinished);
|
||||
|
||||
QCOMPARE(workspace()->moveResizeWindow(), nullptr);
|
||||
QCOMPARE(window->isInteractiveMove(), false);
|
||||
QCOMPARE(window->isInteractiveResize(), false);
|
||||
|
@ -1072,12 +844,22 @@ void MoveResizeWindowTest::testCancelInteractiveMoveResize()
|
|||
QCOMPARE(window->isInteractiveMove(), false);
|
||||
QCOMPARE(window->isInteractiveResize(), true);
|
||||
|
||||
Test::pointerMotionRelative(QPoint(1, 1), 1);
|
||||
Test::pointerMotionRelative(QPoint(-10, -10), 1);
|
||||
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().first().toSize(), Qt::blue);
|
||||
QVERIFY(frameGeomtryChangedSpy.wait());
|
||||
QCOMPARE(window->quickTileMode(), QuickTileMode());
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
|
||||
// cancel moveresize, all state from before should be restored
|
||||
window->keyPressEvent(Qt::Key::Key_Escape);
|
||||
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().first().toSize(), Qt::blue);
|
||||
QVERIFY(frameGeomtryChangedSpy.wait());
|
||||
QCOMPARE(window->moveResizeGeometry(), geometry);
|
||||
QCOMPARE(window->quickTileMode(), quickTileMode);
|
||||
QCOMPARE(window->requestedMaximizeMode(), maximizeMode);
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
using namespace KWin;
|
||||
|
||||
static const QString s_socketName = QStringLiteral("wayland_test_kwin_no_global_shortcuts-0");
|
||||
static const QString s_serviceName = QStringLiteral("org.kde.KWin.Test.ModifierOnlyShortcut");
|
||||
static const QString s_path = QStringLiteral("/Test");
|
||||
|
||||
Q_DECLARE_METATYPE(KWin::ElectricBorder)
|
||||
|
||||
|
@ -42,8 +40,6 @@ private Q_SLOTS:
|
|||
void init();
|
||||
void cleanup();
|
||||
|
||||
void testTrigger_data();
|
||||
void testTrigger();
|
||||
void testKGlobalAccel();
|
||||
void testPointerShortcut();
|
||||
void testAxisShortcut_data();
|
||||
|
@ -54,7 +50,6 @@ private Q_SLOTS:
|
|||
class Target : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.kde.KWin.Test.ModifierOnlyShortcut")
|
||||
|
||||
public:
|
||||
Target();
|
||||
|
@ -70,14 +65,10 @@ Q_SIGNALS:
|
|||
Target::Target()
|
||||
: QObject()
|
||||
{
|
||||
QDBusConnection::sessionBus().registerService(s_serviceName);
|
||||
QDBusConnection::sessionBus().registerObject(s_path, s_serviceName, this, QDBusConnection::ExportScriptableSlots);
|
||||
}
|
||||
|
||||
Target::~Target()
|
||||
{
|
||||
QDBusConnection::sessionBus().unregisterObject(s_path);
|
||||
QDBusConnection::sessionBus().unregisterService(s_serviceName);
|
||||
}
|
||||
|
||||
void Target::shortcut()
|
||||
|
@ -89,7 +80,8 @@ void NoGlobalShortcutsTest::initTestCase()
|
|||
{
|
||||
qRegisterMetaType<KWin::ElectricBorder>("ElectricBorder");
|
||||
QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
|
||||
QVERIFY(waylandServer()->init(s_socketName, KWin::WaylandServer::InitializationFlag::NoGlobalShortcuts));
|
||||
kwinApp()->setSupportsGlobalShortcuts(false);
|
||||
QVERIFY(waylandServer()->init(s_socketName));
|
||||
Test::setOutputConfig({
|
||||
QRect(0, 0, 1280, 1024),
|
||||
QRect(1280, 0, 1280, 1024),
|
||||
|
@ -113,62 +105,6 @@ void NoGlobalShortcutsTest::cleanup()
|
|||
{
|
||||
}
|
||||
|
||||
void NoGlobalShortcutsTest::testTrigger_data()
|
||||
{
|
||||
QTest::addColumn<QStringList>("metaConfig");
|
||||
QTest::addColumn<QStringList>("altConfig");
|
||||
QTest::addColumn<QStringList>("controlConfig");
|
||||
QTest::addColumn<QStringList>("shiftConfig");
|
||||
QTest::addColumn<int>("modifier");
|
||||
QTest::addColumn<QList<int>>("nonTriggeringMods");
|
||||
|
||||
const QStringList trigger = QStringList{s_serviceName, s_path, s_serviceName, QStringLiteral("shortcut")};
|
||||
const QStringList e = QStringList();
|
||||
|
||||
QTest::newRow("leftMeta") << trigger << e << e << e << KEY_LEFTMETA << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
||||
QTest::newRow("rightMeta") << trigger << e << e << e << KEY_RIGHTMETA << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
||||
QTest::newRow("leftAlt") << e << trigger << e << e << KEY_LEFTALT << QList<int>{KEY_LEFTMETA, KEY_RIGHTMETA, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
||||
QTest::newRow("rightAlt") << e << trigger << e << e << KEY_RIGHTALT << QList<int>{KEY_LEFTMETA, KEY_RIGHTMETA, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
||||
QTest::newRow("leftControl") << e << e << trigger << e << KEY_LEFTCTRL << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTMETA, KEY_RIGHTMETA, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
||||
QTest::newRow("rightControl") << e << e << trigger << e << KEY_RIGHTCTRL << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTMETA, KEY_RIGHTMETA, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
||||
QTest::newRow("leftShift") << e << e << e << trigger << KEY_LEFTSHIFT << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTMETA, KEY_RIGHTMETA};
|
||||
QTest::newRow("rightShift") << e << e << e << trigger << KEY_RIGHTSHIFT << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTMETA, KEY_RIGHTMETA};
|
||||
}
|
||||
|
||||
void NoGlobalShortcutsTest::testTrigger()
|
||||
{
|
||||
// test based on ModifierOnlyShortcutTest::testTrigger
|
||||
Target target;
|
||||
QSignalSpy triggeredSpy(&target, &Target::shortcutTriggered);
|
||||
|
||||
KConfigGroup group = kwinApp()->config()->group(QStringLiteral("ModifierOnlyShortcuts"));
|
||||
QFETCH(QStringList, metaConfig);
|
||||
QFETCH(QStringList, altConfig);
|
||||
QFETCH(QStringList, shiftConfig);
|
||||
QFETCH(QStringList, controlConfig);
|
||||
group.writeEntry("Meta", metaConfig);
|
||||
group.writeEntry("Alt", altConfig);
|
||||
group.writeEntry("Shift", shiftConfig);
|
||||
group.writeEntry("Control", controlConfig);
|
||||
group.sync();
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
// configured shortcut should trigger
|
||||
quint32 timestamp = 1;
|
||||
QFETCH(int, modifier);
|
||||
Test::keyboardKeyPressed(modifier, timestamp++);
|
||||
Test::keyboardKeyReleased(modifier, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 0);
|
||||
|
||||
// the other shortcuts should not trigger
|
||||
QFETCH(QList<int>, nonTriggeringMods);
|
||||
for (auto it = nonTriggeringMods.constBegin(), end = nonTriggeringMods.constEnd(); it != end; it++) {
|
||||
Test::keyboardKeyPressed(*it, timestamp++);
|
||||
Test::keyboardKeyReleased(*it, timestamp++);
|
||||
QCOMPARE(triggeredSpy.count(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void NoGlobalShortcutsTest::testKGlobalAccel()
|
||||
{
|
||||
std::unique_ptr<QAction> action(new QAction(nullptr));
|
||||
|
|
|
@ -10,11 +10,15 @@
|
|||
#include "core/outputbackend.h"
|
||||
#include "core/outputconfiguration.h"
|
||||
#include "pointer_input.h"
|
||||
#include "tiles/tilemanager.h"
|
||||
#include "wayland_server.h"
|
||||
#include "window.h"
|
||||
#include "workspace.h"
|
||||
#include "x11window.h"
|
||||
|
||||
#include <KWayland/Client/surface.h>
|
||||
#include <netwm.h>
|
||||
#include <xcb/xcb_icccm.h>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
|
@ -41,8 +45,16 @@ private Q_SLOTS:
|
|||
void testWindowRestoredAfterEnablingOutput();
|
||||
void testMaximizedWindowRestoredAfterEnablingOutput();
|
||||
void testFullScreenWindowRestoredAfterEnablingOutput();
|
||||
void testQuickTiledWindowRestoredAfterEnablingOutput();
|
||||
void testCustomTiledWindowRestoredAfterEnablingOutput_data();
|
||||
void testCustomTiledWindowRestoredAfterEnablingOutput();
|
||||
void testWindowRestoredAfterChangingScale();
|
||||
void testMaximizeStateRestoredAfterEnablingOutput_data();
|
||||
void testMaximizeStateRestoredAfterEnablingOutput();
|
||||
void testInvalidGeometryRestoreAfterEnablingOutput();
|
||||
void testMaximizedWindowDoesntDisappear_data();
|
||||
void testMaximizedWindowDoesntDisappear();
|
||||
void testXwaylandScaleChange();
|
||||
|
||||
void testWindowNotRestoredAfterMovingWindowAndEnablingOutput();
|
||||
void testLaptopLidClosed();
|
||||
|
@ -458,6 +470,182 @@ void OutputChangesTest::testFullScreenWindowRestoredAfterEnablingOutput()
|
|||
QCOMPARE(window->fullscreenGeometryRestore(), QRectF(1280 + 50, 100, 100, 50));
|
||||
}
|
||||
|
||||
void OutputChangesTest::testQuickTiledWindowRestoredAfterEnablingOutput()
|
||||
{
|
||||
// This test verifies that a quick tiled window will be moved to
|
||||
// its original output and tile when the output is re-enabled
|
||||
|
||||
const auto outputs = kwinApp()->outputBackend()->outputs();
|
||||
|
||||
// Create a window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(window);
|
||||
|
||||
// kwin will send a configure event with the actived state.
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
||||
// Move the window to the right monitor and tile it to the right.
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
window->move(QPointF(1280 + 50, 100));
|
||||
window->setQuickTileMode(QuickTileFlag::Right, true);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), QSize(1280 / 2, 1024));
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), QSize(1280 / 2, 1024), Qt::blue);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
const QRectF rightQuickTileGeom = QRectF(1280 + 1280 / 2, 0, 1280 / 2, 1024);
|
||||
QCOMPARE(window->frameGeometry(), rightQuickTileGeom);
|
||||
QCOMPARE(window->moveResizeGeometry(), rightQuickTileGeom);
|
||||
QCOMPARE(window->output(), outputs[1]);
|
||||
QCOMPARE(window->quickTileMode(), QuickTileFlag::Right);
|
||||
QCOMPARE(window->requestedQuickTileMode(), QuickTileFlag::Right);
|
||||
QCOMPARE(window->geometryRestore(), QRectF(1280 + 50, 100, 100, 50));
|
||||
|
||||
// Disable the right output.
|
||||
OutputConfiguration config1;
|
||||
{
|
||||
auto changeSet = config1.changeSet(outputs[1]);
|
||||
changeSet->enabled = false;
|
||||
}
|
||||
workspace()->applyOutputConfiguration(config1);
|
||||
|
||||
// The window will be moved to the left monitor
|
||||
QCOMPARE(window->output(), outputs[0]);
|
||||
|
||||
// Enable the right monitor again
|
||||
OutputConfiguration config2;
|
||||
{
|
||||
auto changeSet = config2.changeSet(outputs[1]);
|
||||
changeSet->enabled = true;
|
||||
}
|
||||
workspace()->applyOutputConfiguration(config2);
|
||||
|
||||
// The window will be moved back to the right monitor, and put in the correct tile
|
||||
QCOMPARE(window->frameGeometry(), rightQuickTileGeom);
|
||||
QCOMPARE(window->moveResizeGeometry(), rightQuickTileGeom);
|
||||
QCOMPARE(window->output(), outputs[1]);
|
||||
QCOMPARE(window->quickTileMode(), QuickTileFlag::Right);
|
||||
QCOMPARE(window->requestedQuickTileMode(), QuickTileFlag::Right);
|
||||
QCOMPARE(window->geometryRestore(), QRectF(1280 + 50, 100, 100, 50));
|
||||
}
|
||||
|
||||
void OutputChangesTest::testCustomTiledWindowRestoredAfterEnablingOutput_data()
|
||||
{
|
||||
const auto outputs = kwinApp()->outputBackend()->outputs();
|
||||
const size_t tileCount = workspace()->tileManager(outputs[1])->rootTile()->childTiles().size();
|
||||
|
||||
QTest::addColumn<size_t>("tileIndex");
|
||||
for (size_t i = 0; i < tileCount; i++) {
|
||||
QTest::addRow("tile %lu", i) << i;
|
||||
}
|
||||
}
|
||||
|
||||
void OutputChangesTest::testCustomTiledWindowRestoredAfterEnablingOutput()
|
||||
{
|
||||
// This test verifies that a custom tiled window will be moved to
|
||||
// its original output and tile when the output is re-enabled
|
||||
|
||||
const auto outputs = kwinApp()->outputBackend()->outputs();
|
||||
|
||||
// start with only one output
|
||||
{
|
||||
OutputConfiguration config;
|
||||
auto changeSet = config.changeSet(outputs[1]);
|
||||
changeSet->enabled = false;
|
||||
workspace()->applyOutputConfiguration(config);
|
||||
}
|
||||
|
||||
// Create a window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
const auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(window);
|
||||
|
||||
// kwin will send a configure event with the actived state.
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
||||
const QRectF originalGeometry = window->moveResizeGeometry();
|
||||
|
||||
// Enable the right output
|
||||
{
|
||||
OutputConfiguration config;
|
||||
auto changeSet = config.changeSet(outputs[1]);
|
||||
changeSet->enabled = true;
|
||||
workspace()->applyOutputConfiguration(config);
|
||||
}
|
||||
|
||||
QFETCH(size_t, tileIndex);
|
||||
const QRectF customTileGeom = workspace()->tileManager(outputs[1])->rootTile()->childTiles()[tileIndex]->windowGeometry();
|
||||
|
||||
// Move the window to the right monitor and put it in the middle tile.
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
window->move(customTileGeom.topLeft() + QPointF(50, 50));
|
||||
const auto geomBeforeTiling = window->moveResizeGeometry();
|
||||
window->setQuickTileMode(QuickTileFlag::Custom, true);
|
||||
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), customTileGeom.size().toSize());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), customTileGeom.size().toSize(), Qt::blue);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
|
||||
QCOMPARE(window->frameGeometry(), customTileGeom);
|
||||
QCOMPARE(window->moveResizeGeometry(), customTileGeom);
|
||||
QCOMPARE(window->output(), outputs[1]);
|
||||
QCOMPARE(window->quickTileMode(), QuickTileFlag::Custom);
|
||||
QCOMPARE(window->requestedQuickTileMode(), QuickTileFlag::Custom);
|
||||
QCOMPARE(window->geometryRestore(), geomBeforeTiling);
|
||||
|
||||
// Disable the right output.
|
||||
{
|
||||
OutputConfiguration config;
|
||||
auto changeSet = config.changeSet(outputs[1]);
|
||||
changeSet->enabled = false;
|
||||
workspace()->applyOutputConfiguration(config);
|
||||
}
|
||||
|
||||
// The window will be moved to the left monitor, and the original geometry restored
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), originalGeometry.size().toSize());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), originalGeometry.size().toSize(), Qt::blue);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
|
||||
QCOMPARE(window->frameGeometry(), originalGeometry);
|
||||
QCOMPARE(window->moveResizeGeometry(), originalGeometry);
|
||||
QCOMPARE(window->output(), outputs[0]);
|
||||
QCOMPARE(window->quickTileMode(), QuickTileFlag::None);
|
||||
QCOMPARE(window->requestedQuickTileMode(), QuickTileFlag::None);
|
||||
|
||||
// Enable the right monitor again
|
||||
{
|
||||
OutputConfiguration config;
|
||||
auto changeSet = config.changeSet(outputs[1]);
|
||||
changeSet->enabled = true;
|
||||
workspace()->applyOutputConfiguration(config);
|
||||
}
|
||||
|
||||
// The window will be moved back to the right monitor, and put in the correct tile
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), customTileGeom.size().toSize());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), customTileGeom.size().toSize(), Qt::blue);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
|
||||
QCOMPARE(window->frameGeometry(), customTileGeom);
|
||||
QCOMPARE(window->moveResizeGeometry(), customTileGeom);
|
||||
QCOMPARE(window->output(), outputs[1]);
|
||||
QCOMPARE(window->quickTileMode(), QuickTileFlag::Custom);
|
||||
QCOMPARE(window->requestedQuickTileMode(), QuickTileFlag::Custom);
|
||||
QCOMPARE(window->geometryRestore(), geomBeforeTiling);
|
||||
}
|
||||
|
||||
void OutputChangesTest::testWindowRestoredAfterChangingScale()
|
||||
{
|
||||
// This test verifies that a window will be moved to its original position after changing the scale of an output
|
||||
|
@ -501,11 +689,21 @@ void OutputChangesTest::testWindowRestoredAfterChangingScale()
|
|||
QCOMPARE(window->output(), output);
|
||||
}
|
||||
|
||||
void OutputChangesTest::testMaximizeStateRestoredAfterEnablingOutput_data()
|
||||
{
|
||||
QTest::addColumn<MaximizeMode>("maximizeMode");
|
||||
QTest::addRow("Vertical Maximization") << MaximizeMode::MaximizeVertical;
|
||||
QTest::addRow("Horizontal Maximization") << MaximizeMode::MaximizeHorizontal;
|
||||
QTest::addRow("Full Maximization") << MaximizeMode::MaximizeFull;
|
||||
}
|
||||
|
||||
void OutputChangesTest::testMaximizeStateRestoredAfterEnablingOutput()
|
||||
{
|
||||
// This test verifies that the window state will get restored after disabling and enabling an output,
|
||||
// even if its maximize state changed in the process
|
||||
|
||||
QFETCH(MaximizeMode, maximizeMode);
|
||||
|
||||
const auto outputs = kwinApp()->outputBackend()->outputs();
|
||||
|
||||
// Disable the right output
|
||||
|
@ -540,17 +738,16 @@ void OutputChangesTest::testMaximizeStateRestoredAfterEnablingOutput()
|
|||
// Move the window to the right monitor and make it maximized.
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
window->move(QPointF(1280 + 50, 100));
|
||||
window->maximize(MaximizeFull);
|
||||
window->maximize(maximizeMode);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), QSize(1280, 1024));
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), QSize(1280, 1024), Qt::blue);
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::blue);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->frameGeometry(), QRectF(1280, 0, 1280, 1024));
|
||||
QCOMPARE(window->moveResizeGeometry(), QRectF(1280, 0, 1280, 1024));
|
||||
const auto maximizedGeometry = window->moveResizeGeometry();
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry);
|
||||
QCOMPARE(window->output(), outputs[1]);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->maximizeMode(), maximizeMode);
|
||||
QCOMPARE(window->requestedMaximizeMode(), maximizeMode);
|
||||
QCOMPARE(window->geometryRestore(), QRectF(1280 + 50, 100, 100, 50));
|
||||
|
||||
// Disable the right output
|
||||
|
@ -581,23 +778,199 @@ void OutputChangesTest::testMaximizeStateRestoredAfterEnablingOutput()
|
|||
workspace()->applyOutputConfiguration(config);
|
||||
}
|
||||
|
||||
// The window will be moved back to the right monitor, maximized and the geometry restore will be updated
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), maximizedGeometry.size());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::blue);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry);
|
||||
QCOMPARE(window->moveResizeGeometry(), maximizedGeometry);
|
||||
QCOMPARE(window->output(), outputs[1]);
|
||||
QCOMPARE(window->maximizeMode(), maximizeMode);
|
||||
QCOMPARE(window->requestedMaximizeMode(), maximizeMode);
|
||||
QCOMPARE(window->geometryRestore(), QRectF(1280 + 50, 100, 100, 50));
|
||||
}
|
||||
|
||||
void OutputChangesTest::testInvalidGeometryRestoreAfterEnablingOutput()
|
||||
{
|
||||
// This test verifies that the geometry restore gets restore correctly, even if it's invalid
|
||||
|
||||
const auto outputs = kwinApp()->outputBackend()->outputs();
|
||||
|
||||
// Disable the right output
|
||||
{
|
||||
OutputConfiguration config;
|
||||
auto changeSet = config.changeSet(outputs[1]);
|
||||
changeSet->enabled = false;
|
||||
workspace()->applyOutputConfiguration(config);
|
||||
}
|
||||
|
||||
// Create a window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get(), Test::CreationSetup::CreateOnly));
|
||||
shellSurface->set_maximized();
|
||||
{
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
shellSurface->xdgSurface()->surface()->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().first().toUInt());
|
||||
}
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(1280, 1024), Qt::blue);
|
||||
QVERIFY(window);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
|
||||
const QRectF originalGeometry = window->moveResizeGeometry();
|
||||
const QRectF originalGeometryRestore = window->geometryRestore();
|
||||
|
||||
// Enable the right output
|
||||
{
|
||||
OutputConfiguration config;
|
||||
auto changeSet = config.changeSet(outputs[1]);
|
||||
changeSet->enabled = true;
|
||||
workspace()->applyOutputConfiguration(config);
|
||||
}
|
||||
|
||||
// Move the window to the right monitor
|
||||
window->sendToOutput(outputs[1]);
|
||||
surface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
QCOMPARE(window->frameGeometry(), QRectF(1280, 0, 1280, 1024));
|
||||
QCOMPARE(window->moveResizeGeometry(), QRectF(1280, 0, 1280, 1024));
|
||||
QCOMPARE(window->output(), outputs[1]);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeFull);
|
||||
QVERIFY(outputs[1]->geometry().contains(window->geometryRestore().topLeft().toPoint()));
|
||||
QCOMPARE(window->geometryRestore().size(), QSizeF(0, 0));
|
||||
|
||||
const QRectF rightGeometryRestore = window->geometryRestore();
|
||||
|
||||
// Disable the right output
|
||||
{
|
||||
OutputConfiguration config;
|
||||
auto changeSet = config.changeSet(outputs[1]);
|
||||
changeSet->enabled = false;
|
||||
workspace()->applyOutputConfiguration(config);
|
||||
}
|
||||
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
|
||||
// The window will be moved to its prior position on the left monitor, and still maximized
|
||||
QCOMPARE(window->frameGeometry(), originalGeometry);
|
||||
QCOMPARE(window->moveResizeGeometry(), originalGeometry);
|
||||
QCOMPARE(window->output(), outputs[0]);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeFull);
|
||||
QVERIFY(outputs[0]->geometry().contains(window->geometryRestore().topLeft().toPoint()));
|
||||
QCOMPARE(window->geometryRestore(), originalGeometryRestore);
|
||||
|
||||
// Enable the right output again
|
||||
{
|
||||
OutputConfiguration config;
|
||||
auto changeSet = config.changeSet(outputs[1]);
|
||||
changeSet->enabled = true;
|
||||
workspace()->applyOutputConfiguration(config);
|
||||
}
|
||||
|
||||
// The window will be moved back to the right monitor, maximized and the geometry restore will be updated
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), outputs[1]->geometry().size());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), outputs[1]->geometry().size(), Qt::blue);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->frameGeometry(), QRectF(1280, 0, 1280, 1024));
|
||||
QCOMPARE(window->moveResizeGeometry(), QRectF(1280, 0, 1280, 1024));
|
||||
QCOMPARE(window->output(), outputs[1]);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->geometryRestore(), QRectF(1280 + 50, 100, 100, 50));
|
||||
QCOMPARE(window->geometryRestore(), rightGeometryRestore);
|
||||
}
|
||||
|
||||
void OutputChangesTest::testMaximizedWindowDoesntDisappear_data()
|
||||
{
|
||||
QTest::addColumn<MaximizeMode>("maximizeMode");
|
||||
QTest::addRow("Vertical Maximization") << MaximizeMode::MaximizeVertical;
|
||||
QTest::addRow("Horizontal Maximization") << MaximizeMode::MaximizeHorizontal;
|
||||
QTest::addRow("Full Maximization") << MaximizeMode::MaximizeFull;
|
||||
}
|
||||
|
||||
void OutputChangesTest::testMaximizedWindowDoesntDisappear()
|
||||
{
|
||||
// This test verifies that (vertically, horizontally) maximized windows don't get placed out of the screen
|
||||
// when the output they're on gets disabled or removed
|
||||
|
||||
Test::setOutputConfig({
|
||||
Test::OutputInfo{
|
||||
.geometry = QRect(5120 / 3, 1440, 2256 / 1.3, 1504 / 1.3),
|
||||
.scale = 1.3,
|
||||
.internal = true,
|
||||
},
|
||||
Test::OutputInfo{
|
||||
.geometry = QRect(0, 0, 5120, 1440),
|
||||
.scale = 1,
|
||||
.internal = false,
|
||||
},
|
||||
});
|
||||
const auto outputs = kwinApp()->outputBackend()->outputs();
|
||||
QFETCH(MaximizeMode, maximizeMode);
|
||||
|
||||
workspace()->setActiveOutput(outputs[1]);
|
||||
|
||||
// Create a window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(500, 300), Qt::blue);
|
||||
QVERIFY(window);
|
||||
|
||||
// kwin will send a configure event with the actived state.
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
||||
window->move(outputs[1]->geometry().topLeft() + QPoint(3500, 500));
|
||||
const QRectF originalGeometry = window->frameGeometry();
|
||||
QVERIFY(outputs[1]->geometryF().contains(originalGeometry));
|
||||
|
||||
// vertically maximize the window
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
window->maximize(maximizeMode);
|
||||
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::blue);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
|
||||
QCOMPARE(window->output(), outputs[1]);
|
||||
const auto maximizedGeometry = window->moveResizeGeometry();
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry);
|
||||
QCOMPARE(window->maximizeMode(), maximizeMode);
|
||||
QCOMPARE(window->requestedMaximizeMode(), maximizeMode);
|
||||
QCOMPARE(window->geometryRestore(), originalGeometry);
|
||||
|
||||
// Disable the top output
|
||||
{
|
||||
OutputConfiguration config;
|
||||
auto changeSet0 = config.changeSet(outputs[0]);
|
||||
changeSet0->pos = QPoint(0, 0);
|
||||
auto changeSet = config.changeSet(outputs[1]);
|
||||
changeSet->enabled = false;
|
||||
workspace()->applyOutputConfiguration(config);
|
||||
}
|
||||
|
||||
// The window should be moved to the left output
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::blue);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
|
||||
QCOMPARE(window->output(), outputs[0]);
|
||||
QVERIFY(outputs[0]->geometryF().contains(window->frameGeometry()));
|
||||
QVERIFY(outputs[0]->geometryF().contains(window->moveResizeGeometry()));
|
||||
QCOMPARE(window->maximizeMode(), maximizeMode);
|
||||
QCOMPARE(window->requestedMaximizeMode(), maximizeMode);
|
||||
}
|
||||
|
||||
void OutputChangesTest::testLaptopLidClosed()
|
||||
{
|
||||
QSKIP("Laptop lid handling is disabled until config writing is moved into KWin");
|
||||
Test::setOutputConfig({
|
||||
Test::OutputInfo{
|
||||
.geometry = QRect(0, 0, 1280, 1024),
|
||||
|
@ -635,6 +1008,80 @@ void OutputChangesTest::testLaptopLidClosed()
|
|||
input()->removeInputDevice(lidSwitch.get());
|
||||
}
|
||||
|
||||
static X11Window *createX11Window(xcb_connection_t *connection, const QRect &geometry, std::function<void(xcb_window_t)> setup = {})
|
||||
{
|
||||
xcb_window_t windowId = xcb_generate_id(connection);
|
||||
xcb_create_window(connection, XCB_COPY_FROM_PARENT, windowId, rootWindow(),
|
||||
geometry.x(),
|
||||
geometry.y(),
|
||||
geometry.width(),
|
||||
geometry.height(),
|
||||
0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr);
|
||||
|
||||
xcb_size_hints_t hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
xcb_icccm_size_hints_set_position(&hints, 1, geometry.x(), geometry.y());
|
||||
xcb_icccm_size_hints_set_size(&hints, 1, geometry.width(), geometry.height());
|
||||
xcb_icccm_set_wm_normal_hints(connection, windowId, &hints);
|
||||
|
||||
if (setup) {
|
||||
setup(windowId);
|
||||
}
|
||||
|
||||
xcb_map_window(connection, windowId);
|
||||
xcb_flush(connection);
|
||||
|
||||
QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
|
||||
if (!windowCreatedSpy.wait()) {
|
||||
return nullptr;
|
||||
}
|
||||
return windowCreatedSpy.last().first().value<X11Window *>();
|
||||
}
|
||||
|
||||
void OutputChangesTest::testXwaylandScaleChange()
|
||||
{
|
||||
Test::setOutputConfig({
|
||||
QRect(0, 0, 1280, 1024),
|
||||
QRect(1280, 0, 1280, 1024),
|
||||
});
|
||||
const auto outputs = workspace()->outputs();
|
||||
|
||||
{
|
||||
OutputConfiguration config;
|
||||
config.changeSet(outputs[0])->scale = 2;
|
||||
config.changeSet(outputs[1])->scale = 1;
|
||||
workspace()->applyOutputConfiguration(config);
|
||||
}
|
||||
QCOMPARE(kwinApp()->xwaylandScale(), 2);
|
||||
|
||||
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||
X11Window *window = createX11Window(c.get(), QRect(0, 0, 100, 200));
|
||||
const QRectF originalGeometry = window->frameGeometry();
|
||||
|
||||
// disable the left output -> window gets moved to the right output
|
||||
{
|
||||
OutputConfiguration config;
|
||||
config.changeSet(outputs[0])->enabled = false;
|
||||
workspace()->applyOutputConfiguration(config);
|
||||
}
|
||||
|
||||
// the window should still have logical size of 100, 200
|
||||
QCOMPARE(kwinApp()->xwaylandScale(), 1);
|
||||
QCOMPARE(window->frameGeometry().size(), originalGeometry.size());
|
||||
|
||||
// enable the left output again
|
||||
{
|
||||
OutputConfiguration config;
|
||||
config.changeSet(outputs[0])->enabled = true;
|
||||
workspace()->applyOutputConfiguration(config);
|
||||
}
|
||||
|
||||
// the window should be back in its original geometry
|
||||
QCOMPARE(kwinApp()->xwaylandScale(), 2);
|
||||
QCOMPARE(window->frameGeometry(), originalGeometry);
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
||||
WAYLANDTEST_MAIN(KWin::OutputChangesTest)
|
||||
|
|
|
@ -25,13 +25,6 @@ using namespace KWin;
|
|||
|
||||
static const QString s_socketName = QStringLiteral("wayland_test_kwin_placement-0");
|
||||
|
||||
struct PlaceWindowResult
|
||||
{
|
||||
QSizeF initiallyConfiguredSize;
|
||||
Test::XdgToplevel::States initiallyConfiguredStates;
|
||||
QRectF finalGeometry;
|
||||
};
|
||||
|
||||
class TestPlacement : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -56,12 +49,24 @@ private Q_SLOTS:
|
|||
|
||||
private:
|
||||
void setPlacementPolicy(PlacementPolicy policy);
|
||||
struct WindowHandle
|
||||
{
|
||||
Window *window;
|
||||
std::unique_ptr<KWayland::Client::Surface> surface;
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface;
|
||||
};
|
||||
struct PlaceWindowResult
|
||||
{
|
||||
QSizeF initiallyConfiguredSize;
|
||||
Test::XdgToplevel::States initiallyConfiguredStates;
|
||||
QRectF finalGeometry;
|
||||
};
|
||||
/*
|
||||
* Create a window and return relevant results for testing
|
||||
* defaultSize is the buffer size to use if the compositor returns an empty size in the first configure
|
||||
* event.
|
||||
*/
|
||||
std::pair<PlaceWindowResult, std::unique_ptr<KWayland::Client::Surface>> createAndPlaceWindow(const QSize &defaultSize);
|
||||
std::tuple<PlaceWindowResult, WindowHandle> createAndPlaceWindow(const QSize &defaultSize);
|
||||
};
|
||||
|
||||
void TestPlacement::init()
|
||||
|
@ -105,15 +110,15 @@ void TestPlacement::setPlacementPolicy(PlacementPolicy policy)
|
|||
Workspace::self()->slotReconfigure();
|
||||
}
|
||||
|
||||
std::pair<PlaceWindowResult, std::unique_ptr<KWayland::Client::Surface>> TestPlacement::createAndPlaceWindow(const QSize &defaultSize)
|
||||
std::tuple<TestPlacement::PlaceWindowResult, TestPlacement::WindowHandle> TestPlacement::createAndPlaceWindow(const QSize &defaultSize)
|
||||
{
|
||||
PlaceWindowResult rc;
|
||||
|
||||
// create a new window
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
auto shellSurface = Test::createXdgToplevelSurface(surface.get(), Test::CreationSetup::CreateOnly, surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get(), Test::CreationSetup::CreateOnly);
|
||||
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface, &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
surface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
surfaceConfigureRequestedSpy.wait();
|
||||
|
@ -131,7 +136,11 @@ std::pair<PlaceWindowResult, std::unique_ptr<KWayland::Client::Surface>> TestPla
|
|||
auto window = Test::renderAndWaitForShown(surface.get(), size.toSize(), Qt::red);
|
||||
|
||||
rc.finalGeometry = window->frameGeometry();
|
||||
return {rc, std::move(surface)};
|
||||
return {rc, WindowHandle{
|
||||
.window = window,
|
||||
.surface = std::move(surface),
|
||||
.shellSurface = std::move(shellSurface),
|
||||
}};
|
||||
}
|
||||
|
||||
void TestPlacement::testPlaceSmart()
|
||||
|
@ -150,11 +159,11 @@ void TestPlacement::testPlaceSmart()
|
|||
|
||||
setPlacementPolicy(PlacementSmart);
|
||||
|
||||
std::vector<std::unique_ptr<KWayland::Client::Surface>> surfaces;
|
||||
std::vector<WindowHandle> handles;
|
||||
|
||||
for (const QRect &desiredGeometry : desiredGeometries) {
|
||||
auto [windowPlacement, surface] = createAndPlaceWindow(QSize(600, 500));
|
||||
surfaces.push_back(std::move(surface));
|
||||
auto [windowPlacement, handle] = createAndPlaceWindow(QSize(600, 500));
|
||||
handles.push_back(std::move(handle));
|
||||
|
||||
// smart placement shouldn't define a size on windows
|
||||
QCOMPARE(windowPlacement.initiallyConfiguredSize, QSize(0, 0));
|
||||
|
@ -181,15 +190,15 @@ void TestPlacement::testPlaceMaximized()
|
|||
QVERIFY(panelConfigureRequestedSpy.wait());
|
||||
Test::renderAndWaitForShown(panelSurface.get(), panelConfigureRequestedSpy.last().at(1).toSize(), Qt::blue);
|
||||
|
||||
std::vector<std::unique_ptr<KWayland::Client::Surface>> surfaces;
|
||||
std::vector<WindowHandle> handles;
|
||||
|
||||
// all windows should be initially maximized with an initial configure size sent
|
||||
for (int i = 0; i < 4; i++) {
|
||||
auto [windowPlacement, surface] = createAndPlaceWindow(QSize(600, 500));
|
||||
auto [windowPlacement, handle] = createAndPlaceWindow(QSize(600, 500));
|
||||
QVERIFY(windowPlacement.initiallyConfiguredStates & Test::XdgToplevel::State::Maximized);
|
||||
QCOMPARE(windowPlacement.initiallyConfiguredSize, QSize(1280, 1024 - 20));
|
||||
QCOMPARE(windowPlacement.finalGeometry, QRect(0, 20, 1280, 1024 - 20)); // under the panel
|
||||
surfaces.push_back(std::move(surface));
|
||||
handles.push_back(std::move(handle));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,14 +217,14 @@ void TestPlacement::testPlaceMaximizedLeavesFullscreen()
|
|||
QVERIFY(panelConfigureRequestedSpy.wait());
|
||||
Test::renderAndWaitForShown(panelSurface.get(), panelConfigureRequestedSpy.last().at(1).toSize(), Qt::blue);
|
||||
|
||||
std::vector<std::unique_ptr<KWayland::Client::Surface>> surfaces;
|
||||
std::vector<WindowHandle> handles;
|
||||
|
||||
// all windows should be initially fullscreen with an initial configure size sent, despite the policy
|
||||
for (int i = 0; i < 4; i++) {
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
auto shellSurface = Test::createXdgToplevelSurface(surface.get(), Test::CreationSetup::CreateOnly, surface.get());
|
||||
auto shellSurface = Test::createXdgToplevelSurface(surface.get(), Test::CreationSetup::CreateOnly);
|
||||
shellSurface->set_fullscreen(nullptr);
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface, &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
surface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
@ -230,7 +239,11 @@ void TestPlacement::testPlaceMaximizedLeavesFullscreen()
|
|||
QCOMPARE(initiallyConfiguredSize, QSize(1280, 1024));
|
||||
QCOMPARE(window->frameGeometry(), QRect(0, 0, 1280, 1024));
|
||||
|
||||
surfaces.push_back(std::move(surface));
|
||||
handles.emplace_back(WindowHandle{
|
||||
.window = window,
|
||||
.surface = std::move(surface),
|
||||
.shellSurface = std::move(shellSurface),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ void PlasmaSurfaceTest::testOSDPlacement()
|
|||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
QVERIFY(window);
|
||||
QCOMPARE(window->windowType(), NET::OnScreenDisplay);
|
||||
QCOMPARE(window->windowType(), WindowType::OnScreenDisplay);
|
||||
QVERIFY(window->isOnScreenDisplay());
|
||||
QCOMPARE(window->frameGeometry(), QRect(1280 / 2 - 100 / 2, 2 * 1024 / 3 - 50 / 2, 100, 50));
|
||||
|
||||
|
@ -224,7 +224,7 @@ void PlasmaSurfaceTest::testOSDPlacementManualPosition()
|
|||
|
||||
QVERIFY(window);
|
||||
QVERIFY(!window->isPlaceable());
|
||||
QCOMPARE(window->windowType(), NET::OnScreenDisplay);
|
||||
QCOMPARE(window->windowType(), WindowType::OnScreenDisplay);
|
||||
QVERIFY(window->isOnScreenDisplay());
|
||||
QCOMPARE(window->frameGeometry(), QRect(50, 70, 100, 50));
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ void PlasmaSurfaceTest::testPanelActivate()
|
|||
auto panel = Test::renderAndWaitForShown(surface.get(), QSize(100, 200), Qt::blue);
|
||||
|
||||
QVERIFY(panel);
|
||||
QCOMPARE(panel->windowType(), NET::Dock);
|
||||
QCOMPARE(panel->windowType(), WindowType::Dock);
|
||||
QVERIFY(panel->isDock());
|
||||
QFETCH(bool, active);
|
||||
QCOMPARE(panel->dockWantsInput(), active);
|
||||
|
|
|
@ -38,17 +38,6 @@
|
|||
namespace KWin
|
||||
{
|
||||
|
||||
static PlatformCursorImage loadReferenceThemeCursor_helper(const KXcursorTheme &theme,
|
||||
const QByteArray &name)
|
||||
{
|
||||
const QList<KXcursorSprite> sprites = theme.shape(name);
|
||||
if (sprites.isEmpty()) {
|
||||
return PlatformCursorImage();
|
||||
}
|
||||
|
||||
return PlatformCursorImage(sprites.constFirst().data(), sprites.constFirst().hotspot());
|
||||
}
|
||||
|
||||
static PlatformCursorImage loadReferenceThemeCursor(const QByteArray &name)
|
||||
{
|
||||
const Cursor *pointerCursor = Cursors::self()->mouse();
|
||||
|
@ -58,20 +47,11 @@ static PlatformCursorImage loadReferenceThemeCursor(const QByteArray &name)
|
|||
return PlatformCursorImage();
|
||||
}
|
||||
|
||||
PlatformCursorImage platformCursorImage = loadReferenceThemeCursor_helper(theme, name);
|
||||
if (!platformCursorImage.isNull()) {
|
||||
return platformCursorImage;
|
||||
}
|
||||
ShapeCursorSource source;
|
||||
source.setShape(name);
|
||||
source.setTheme(theme);
|
||||
|
||||
const QList<QByteArray> alternativeNames = Cursor::cursorAlternativeNames(name);
|
||||
for (const QByteArray &alternativeName : alternativeNames) {
|
||||
platformCursorImage = loadReferenceThemeCursor_helper(theme, alternativeName);
|
||||
if (!platformCursorImage.isNull()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return platformCursorImage;
|
||||
return PlatformCursorImage(source.image(), source.hotspot());
|
||||
}
|
||||
|
||||
static PlatformCursorImage loadReferenceThemeCursor(const CursorShape &shape)
|
||||
|
@ -114,6 +94,8 @@ private Q_SLOTS:
|
|||
void testWindowUnderCursorWhileButtonPressed();
|
||||
void testConfineToScreenGeometry_data();
|
||||
void testConfineToScreenGeometry();
|
||||
void testEdgeBarrier_data();
|
||||
void testEdgeBarrier();
|
||||
void testResizeCursor_data();
|
||||
void testResizeCursor();
|
||||
void testMoveCursor();
|
||||
|
@ -165,6 +147,11 @@ void PointerInputTest::init()
|
|||
m_compositor = Test::waylandCompositor();
|
||||
m_seat = Test::waylandSeat();
|
||||
|
||||
auto group = kwinApp()->config()->group(QStringLiteral("EdgeBarrier"));
|
||||
group.writeEntry("EdgeBarrier", 0);
|
||||
group.writeEntry("CornerBarrier", false);
|
||||
group.sync();
|
||||
Workspace::self()->slotReconfigure();
|
||||
workspace()->setActiveOutput(QPoint(640, 512));
|
||||
input()->pointer()->warp(QPoint(640, 512));
|
||||
}
|
||||
|
@ -195,7 +182,7 @@ void PointerInputTest::testWarpingUpdatesFocus()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
render(surface.get());
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -240,7 +227,7 @@ void PointerInputTest::testWarpingGeneratesPointerMotion()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
render(surface.get());
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -318,7 +305,7 @@ void PointerInputTest::testUpdateFocusAfterScreenChange()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
render(surface.get(), QSize(1280, 1024));
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -503,7 +490,7 @@ void PointerInputTest::testModifierClickUnrestrictedMove()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
render(surface.get());
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -568,10 +555,10 @@ void PointerInputTest::testModifierClickUnrestrictedFullscreenMove()
|
|||
// create a window
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
shellSurface->set_fullscreen(nullptr);
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface, &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
|
@ -623,7 +610,7 @@ void PointerInputTest::testModifierClickUnrestrictedMoveGlobalShortcutsDisabled(
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
render(surface.get());
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -694,7 +681,7 @@ void PointerInputTest::testModifierScrollOpacity()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
render(surface.get());
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -752,7 +739,7 @@ void PointerInputTest::testModifierScrollOpacityGlobalShortcutsDisabled()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
render(surface.get());
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -799,7 +786,7 @@ void PointerInputTest::testScrollAction()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface1 = Test::createSurface();
|
||||
QVERIFY(surface1);
|
||||
Test::XdgToplevel *shellSurface1 = Test::createXdgToplevelSurface(surface1.get(), surface1.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface1 = Test::createXdgToplevelSurface(surface1.get());
|
||||
QVERIFY(shellSurface1);
|
||||
render(surface1.get());
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -807,7 +794,7 @@ void PointerInputTest::testScrollAction()
|
|||
QVERIFY(window1);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface2 = Test::createSurface();
|
||||
QVERIFY(surface2);
|
||||
Test::XdgToplevel *shellSurface2 = Test::createXdgToplevelSurface(surface2.get(), surface2.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface2 = Test::createXdgToplevelSurface(surface2.get());
|
||||
QVERIFY(shellSurface2);
|
||||
render(surface2.get());
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -854,7 +841,7 @@ void PointerInputTest::testFocusFollowsMouse()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface1 = Test::createSurface();
|
||||
QVERIFY(surface1);
|
||||
Test::XdgToplevel *shellSurface1 = Test::createXdgToplevelSurface(surface1.get(), surface1.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface1 = Test::createXdgToplevelSurface(surface1.get());
|
||||
QVERIFY(shellSurface1);
|
||||
render(surface1.get(), QSize(800, 800));
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -862,7 +849,7 @@ void PointerInputTest::testFocusFollowsMouse()
|
|||
QVERIFY(window1);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface2 = Test::createSurface();
|
||||
QVERIFY(surface2);
|
||||
Test::XdgToplevel *shellSurface2 = Test::createXdgToplevelSurface(surface2.get(), surface2.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface2 = Test::createXdgToplevelSurface(surface2.get());
|
||||
QVERIFY(shellSurface2);
|
||||
render(surface2.get(), QSize(800, 800));
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -936,7 +923,7 @@ void PointerInputTest::testMouseActionInactiveWindow()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface1 = Test::createSurface();
|
||||
QVERIFY(surface1);
|
||||
Test::XdgToplevel *shellSurface1 = Test::createXdgToplevelSurface(surface1.get(), surface1.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface1 = Test::createXdgToplevelSurface(surface1.get());
|
||||
QVERIFY(shellSurface1);
|
||||
render(surface1.get(), QSize(800, 800));
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -944,7 +931,7 @@ void PointerInputTest::testMouseActionInactiveWindow()
|
|||
QVERIFY(window1);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface2 = Test::createSurface();
|
||||
QVERIFY(surface2);
|
||||
Test::XdgToplevel *shellSurface2 = Test::createXdgToplevelSurface(surface2.get(), surface2.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface2 = Test::createXdgToplevelSurface(surface2.get());
|
||||
QVERIFY(shellSurface2);
|
||||
render(surface2.get(), QSize(800, 800));
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -1021,7 +1008,7 @@ void PointerInputTest::testMouseActionActiveWindow()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface1 = Test::createSurface();
|
||||
QVERIFY(surface1);
|
||||
Test::XdgToplevel *shellSurface1 = Test::createXdgToplevelSurface(surface1.get(), surface1.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface1 = Test::createXdgToplevelSurface(surface1.get());
|
||||
QVERIFY(shellSurface1);
|
||||
render(surface1.get(), QSize(800, 800));
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -1030,7 +1017,7 @@ void PointerInputTest::testMouseActionActiveWindow()
|
|||
QSignalSpy window1DestroyedSpy(window1, &QObject::destroyed);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface2 = Test::createSurface();
|
||||
QVERIFY(surface2);
|
||||
Test::XdgToplevel *shellSurface2 = Test::createXdgToplevelSurface(surface2.get(), surface2.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface2 = Test::createXdgToplevelSurface(surface2.get());
|
||||
QVERIFY(shellSurface2);
|
||||
render(surface2.get(), QSize(800, 800));
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -1097,7 +1084,7 @@ void PointerInputTest::testCursorImage()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
render(surface.get());
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -1170,7 +1157,7 @@ void PointerInputTest::testCursorShapeV1()
|
|||
|
||||
// move cursor somewhere the new window won't open
|
||||
input()->pointer()->warp(QPointF(800, 800));
|
||||
QCOMPARE(currentCursorShape(), QByteArray("left_ptr"));
|
||||
QCOMPARE(currentCursorShape(), QByteArrayLiteral("default"));
|
||||
|
||||
// create a window
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
|
@ -1191,10 +1178,10 @@ void PointerInputTest::testCursorShapeV1()
|
|||
|
||||
// cursor shape won't be changed if the window has no pointer focus
|
||||
input()->pointer()->warp(QPointF(800, 800));
|
||||
QCOMPARE(currentCursorShape(), QByteArray("left_ptr"));
|
||||
QCOMPARE(currentCursorShape(), QByteArrayLiteral("default"));
|
||||
cursorShapeDevice->set_shape(enteredSpy.last().at(0).value<quint32>(), Test::CursorShapeDeviceV1::shape_grab);
|
||||
QVERIFY(Test::waylandSync());
|
||||
QCOMPARE(currentCursorShape(), QByteArray("left_ptr"));
|
||||
QCOMPARE(currentCursorShape(), QByteArrayLiteral("default"));
|
||||
}
|
||||
|
||||
class HelperEffect : public Effect
|
||||
|
@ -1227,7 +1214,7 @@ void PointerInputTest::testEffectOverrideCursorImage()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
render(surface.get());
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -1245,19 +1232,19 @@ void PointerInputTest::testEffectOverrideCursorImage()
|
|||
// now create an effect and set an override cursor
|
||||
std::unique_ptr<HelperEffect> effect(new HelperEffect);
|
||||
effects->startMouseInterception(effect.get(), Qt::SizeAllCursor);
|
||||
QCOMPARE(currentCursorShape(), QByteArray("size_all"));
|
||||
QCOMPARE(currentCursorShape(), QByteArrayLiteral("all-scroll"));
|
||||
|
||||
// let's change to arrow cursor, this should be our fallback
|
||||
effects->defineCursor(Qt::ArrowCursor);
|
||||
QCOMPARE(currentCursorShape(), QByteArray("left_ptr"));
|
||||
QCOMPARE(currentCursorShape(), QByteArrayLiteral("default"));
|
||||
|
||||
// back to size all
|
||||
effects->defineCursor(Qt::SizeAllCursor);
|
||||
QCOMPARE(currentCursorShape(), QByteArray("size_all"));
|
||||
QCOMPARE(currentCursorShape(), QByteArrayLiteral("all-scroll"));
|
||||
|
||||
// move cursor outside the window area
|
||||
input()->pointer()->warp(QPointF(800, 800));
|
||||
QCOMPARE(currentCursorShape(), QByteArray("size_all"));
|
||||
QCOMPARE(currentCursorShape(), QByteArrayLiteral("all-scroll"));
|
||||
|
||||
// move cursor to area of window
|
||||
input()->pointer()->warp(window->frameGeometry().center());
|
||||
|
@ -1270,7 +1257,7 @@ void PointerInputTest::testEffectOverrideCursorImage()
|
|||
QVERIFY(enteredSpy.wait());
|
||||
cursorShapeDevice->set_shape(enteredSpy.last().at(0).value<quint32>(), Test::CursorShapeDeviceV1::shape_crosshair);
|
||||
QVERIFY(cursorChanged.wait());
|
||||
QCOMPARE(currentCursorShape(), QByteArray("cross"));
|
||||
QCOMPARE(currentCursorShape(), QByteArrayLiteral("crosshair"));
|
||||
}
|
||||
|
||||
void PointerInputTest::testPopup()
|
||||
|
@ -1292,7 +1279,7 @@ void PointerInputTest::testPopup()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
render(surface.get());
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -1317,9 +1304,9 @@ void PointerInputTest::testPopup()
|
|||
positioner->set_gravity(Test::XdgPositioner::gravity_bottom_right);
|
||||
std::unique_ptr<KWayland::Client::Surface> popupSurface = Test::createSurface();
|
||||
QVERIFY(popupSurface);
|
||||
Test::XdgPopup *popupShellSurface = Test::createXdgPopupSurface(popupSurface.get(), shellSurface->xdgSurface(), positioner.get());
|
||||
std::unique_ptr<Test::XdgPopup> popupShellSurface = Test::createXdgPopupSurface(popupSurface.get(), shellSurface->xdgSurface(), positioner.get());
|
||||
QVERIFY(popupShellSurface);
|
||||
QSignalSpy doneReceivedSpy(popupShellSurface, &Test::XdgPopup::doneReceived);
|
||||
QSignalSpy doneReceivedSpy(popupShellSurface.get(), &Test::XdgPopup::doneReceived);
|
||||
popupShellSurface->grab(*Test::waylandSeat(), 0); // FIXME: Serial.
|
||||
render(popupSurface.get(), QSize(100, 50));
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -1398,9 +1385,9 @@ void PointerInputTest::testDecoCancelsPopup()
|
|||
positioner->set_gravity(Test::XdgPositioner::gravity_bottom_right);
|
||||
std::unique_ptr<KWayland::Client::Surface> popupSurface = Test::createSurface();
|
||||
QVERIFY(popupSurface);
|
||||
Test::XdgPopup *popupShellSurface = Test::createXdgPopupSurface(popupSurface.get(), shellSurface->xdgSurface(), positioner.get());
|
||||
std::unique_ptr<Test::XdgPopup> popupShellSurface = Test::createXdgPopupSurface(popupSurface.get(), shellSurface->xdgSurface(), positioner.get());
|
||||
QVERIFY(popupShellSurface);
|
||||
QSignalSpy doneReceivedSpy(popupShellSurface, &Test::XdgPopup::doneReceived);
|
||||
QSignalSpy doneReceivedSpy(popupShellSurface.get(), &Test::XdgPopup::doneReceived);
|
||||
popupShellSurface->grab(*Test::waylandSeat(), 0); // FIXME: Serial.
|
||||
auto popupWindow = Test::renderAndWaitForShown(popupSurface.get(), QSize(100, 50), Qt::red);
|
||||
QVERIFY(popupWindow);
|
||||
|
@ -1435,7 +1422,7 @@ void PointerInputTest::testWindowUnderCursorWhileButtonPressed()
|
|||
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), surface.get());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(shellSurface);
|
||||
render(surface.get());
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -1458,7 +1445,7 @@ void PointerInputTest::testWindowUnderCursorWhileButtonPressed()
|
|||
positioner->set_gravity(Test::XdgPositioner::gravity_bottom_right);
|
||||
std::unique_ptr<KWayland::Client::Surface> popupSurface = Test::createSurface();
|
||||
QVERIFY(popupSurface);
|
||||
Test::XdgPopup *popupShellSurface = Test::createXdgPopupSurface(popupSurface.get(), shellSurface->xdgSurface(), positioner.get());
|
||||
std::unique_ptr<Test::XdgPopup> popupShellSurface = Test::createXdgPopupSurface(popupSurface.get(), shellSurface->xdgSurface(), positioner.get());
|
||||
QVERIFY(popupShellSurface);
|
||||
render(popupSurface.get(), QSize(99, 49));
|
||||
QVERIFY(windowAddedSpy.wait());
|
||||
|
@ -1562,6 +1549,88 @@ void PointerInputTest::testConfineToScreenGeometry()
|
|||
QCOMPARE(Cursors::self()->mouse()->pos(), expectedPos);
|
||||
}
|
||||
|
||||
void PointerInputTest::testEdgeBarrier_data()
|
||||
{
|
||||
QTest::addColumn<QPoint>("startPos");
|
||||
QTest::addColumn<QList<QPoint>>("movements");
|
||||
QTest::addColumn<int>("targetOutputId");
|
||||
QTest::addColumn<bool>("cornerBarrier");
|
||||
|
||||
// screen layout:
|
||||
//
|
||||
// +----------+----------+---------+
|
||||
// | left | top | right |
|
||||
// +----------+----------+---------+
|
||||
// | bottom |
|
||||
// +----------+
|
||||
//
|
||||
QTest::newRow("move right - barred") << QPoint(1270, 512) << QList<QPoint>{QPoint(20, 0)} << 0 << false;
|
||||
QTest::newRow("move left - barred") << QPoint(1290, 512) << QList<QPoint>{QPoint(-20, 0)} << 1 << false;
|
||||
QTest::newRow("move down - barred") << QPoint(1920, 1014) << QList<QPoint>{QPoint(0, 20)} << 1 << false;
|
||||
QTest::newRow("move up - barred") << QPoint(1920, 1034) << QList<QPoint>{QPoint(0, -20)} << 3 << false;
|
||||
QTest::newRow("move top-right - barred") << QPoint(2550, 1034) << QList<QPoint>{QPoint(20, -20)} << 3 << false;
|
||||
QTest::newRow("move top-left - barred") << QPoint(1290, 1034) << QList<QPoint>{QPoint(-20, -20)} << 3 << false;
|
||||
QTest::newRow("move bottom-right - barred") << QPoint(1270, 1014) << QList<QPoint>{QPoint(20, 20)} << 0 << false;
|
||||
QTest::newRow("move bottom-left - barred") << QPoint(2570, 1014) << QList<QPoint>{QPoint(-20, 20)} << 2 << false;
|
||||
|
||||
QTest::newRow("move right - not barred") << QPoint(1270, 512) << QList<QPoint>{QPoint(100, 0)} << 1 << false;
|
||||
QTest::newRow("move left - not barred") << QPoint(1290, 512) << QList<QPoint>{QPoint(-100, 0)} << 0 << false;
|
||||
QTest::newRow("move down - not barred") << QPoint(1920, 1014) << QList<QPoint>{QPoint(0, 100)} << 3 << false;
|
||||
QTest::newRow("move up - not barred") << QPoint(1920, 1034) << QList<QPoint>{QPoint(0, -100)} << 1 << false;
|
||||
QTest::newRow("move top-right - not barred") << QPoint(2550, 1034) << QList<QPoint>{QPoint(100, -100)} << 2 << false;
|
||||
QTest::newRow("move top-left - not barred") << QPoint(1290, 1034) << QList<QPoint>{QPoint(-100, -100)} << 0 << false;
|
||||
QTest::newRow("move bottom-right - not barred") << QPoint(1270, 1014) << QList<QPoint>{QPoint(100, 100)} << 3 << false;
|
||||
QTest::newRow("move bottom-left - not barred") << QPoint(2570, 1014) << QList<QPoint>{QPoint(-100, 100)} << 3 << false;
|
||||
|
||||
QTest::newRow("move cumulative") << QPoint(1279, 512) << QList<QPoint>{QPoint(24, 0), QPoint(24, 0)} << 1 << false;
|
||||
QTest::newRow("move then idle") << QPoint(1279, 512) << QList<QPoint>{QPoint(24, 0), QPoint(0, 0), QPoint(0, 0), QPoint(3, 0)} << 0 << false;
|
||||
|
||||
QTest::newRow("move top-right - corner barrier") << QPoint(2550, 1034) << QList<QPoint>{QPoint(100, -100)} << 3 << true;
|
||||
QTest::newRow("move top-left - corner barrier") << QPoint(1290, 1034) << QList<QPoint>{QPoint(-100, -100)} << 3 << true;
|
||||
QTest::newRow("move bottom-right - corner barrier") << QPoint(1270, 1014) << QList<QPoint>{QPoint(100, 100)} << 0 << true;
|
||||
QTest::newRow("move bottom-left - corner barrier") << QPoint(2570, 1014) << QList<QPoint>{QPoint(-100, 100)} << 2 << true;
|
||||
}
|
||||
|
||||
void PointerInputTest::testEdgeBarrier()
|
||||
{
|
||||
// setup screen layout
|
||||
const QList<QRect> geometries{
|
||||
QRect(0, 0, 1280, 1024),
|
||||
QRect(1280, 0, 1280, 1024),
|
||||
QRect(2560, 0, 1280, 1024),
|
||||
QRect(1280, 1024, 1280, 1024)};
|
||||
Test::setOutputConfig(geometries);
|
||||
|
||||
const auto outputs = workspace()->outputs();
|
||||
QCOMPARE(outputs.count(), geometries.count());
|
||||
QCOMPARE(outputs[0]->geometry(), geometries.at(0));
|
||||
QCOMPARE(outputs[1]->geometry(), geometries.at(1));
|
||||
QCOMPARE(outputs[2]->geometry(), geometries.at(2));
|
||||
QCOMPARE(outputs[3]->geometry(), geometries.at(3));
|
||||
|
||||
QFETCH(QPoint, startPos);
|
||||
input()->pointer()->warp(startPos);
|
||||
quint32 timestamp = waylandServer()->seat()->timestamp().count() + 5000;
|
||||
Test::pointerMotionRelative(QPoint(0, 0), timestamp);
|
||||
timestamp += 1000;
|
||||
QCOMPARE(Cursors::self()->mouse()->pos(), startPos);
|
||||
|
||||
auto group = kwinApp()->config()->group(QStringLiteral("EdgeBarrier"));
|
||||
group.writeEntry("EdgeBarrier", 25);
|
||||
QFETCH(bool, cornerBarrier);
|
||||
group.writeEntry("CornerBarrier", cornerBarrier);
|
||||
group.sync();
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
QFETCH(QList<QPoint>, movements);
|
||||
for (const auto &movement : movements) {
|
||||
Test::pointerMotionRelative(movement, timestamp);
|
||||
timestamp += 1000;
|
||||
}
|
||||
QFETCH(int, targetOutputId);
|
||||
QCOMPARE(workspace()->outputAt(Cursors::self()->mouse()->pos()), workspace()->outputs().at(targetOutputId));
|
||||
}
|
||||
|
||||
void PointerInputTest::testResizeCursor_data()
|
||||
{
|
||||
QTest::addColumn<Qt::Edges>("edges");
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "effect/globals.h"
|
||||
#include "kwin_wayland_test.h"
|
||||
|
||||
#include "core/output.h"
|
||||
|
@ -14,6 +15,7 @@
|
|||
#include "decorations/settings.h"
|
||||
#include "pointer_input.h"
|
||||
#include "scripting/scripting.h"
|
||||
#include "tiles/tilemanager.h"
|
||||
#include "utils/common.h"
|
||||
#include "wayland_server.h"
|
||||
#include "window.h"
|
||||
|
@ -172,12 +174,15 @@ void QuickTilingTest::testQuickTiling()
|
|||
|
||||
QFETCH(QuickTileMode, mode);
|
||||
QFETCH(QRectF, expectedGeometry);
|
||||
const QuickTileMode oldQuickTileMode = window->quickTileMode();
|
||||
window->setQuickTileMode(mode, true);
|
||||
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||
|
||||
// at this point the geometry did not yet change
|
||||
QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
|
||||
// but quick tile mode already changed
|
||||
QCOMPARE(window->quickTileMode(), mode);
|
||||
// but requested quick tile mode already changed, proper quickTileMode not yet
|
||||
QCOMPARE(window->requestedQuickTileMode(), mode);
|
||||
// Actual quickTileMOde didn't change yet
|
||||
QCOMPARE(window->quickTileMode(), oldQuickTileMode);
|
||||
|
||||
// but we got requested a new geometry
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
@ -191,6 +196,8 @@ void QuickTilingTest::testQuickTiling()
|
|||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(frameGeometryChangedSpy.count(), 1);
|
||||
QCOMPARE(window->frameGeometry(), expectedGeometry);
|
||||
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||
QCOMPARE(window->quickTileMode(), mode);
|
||||
|
||||
// send window to other screen
|
||||
QList<Output *> outputs = workspace()->outputs();
|
||||
|
@ -200,9 +207,19 @@ void QuickTilingTest::testQuickTiling()
|
|||
// quick tile should not be changed
|
||||
QCOMPARE(window->quickTileMode(), mode);
|
||||
QTEST(window->frameGeometry(), "secondScreen");
|
||||
Tile *tile = workspace()->tileManager(outputs[1])->quickTile(mode);
|
||||
QCOMPARE(window->tile(), tile);
|
||||
|
||||
// now try to toggle again
|
||||
window->setQuickTileMode(mode, true);
|
||||
QTEST(window->requestedQuickTileMode(), "expectedModeAfterToggle");
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(surfaceConfigureRequestedSpy.count(), 3);
|
||||
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).toSize(), Qt::red);
|
||||
QVERIFY(quickTileChangedSpy.wait());
|
||||
QCOMPARE(quickTileChangedSpy.count(), 2);
|
||||
QTEST(window->quickTileMode(), "expectedModeAfterToggle");
|
||||
}
|
||||
|
||||
|
@ -243,13 +260,14 @@ void QuickTilingTest::testQuickMaximizing()
|
|||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
QSignalSpy maximizeChangedSpy(window, &Window::maximizedChanged);
|
||||
|
||||
const QuickTileMode oldQuickTileMode = window->quickTileMode();
|
||||
window->setQuickTileMode(QuickTileFlag::Maximize, true);
|
||||
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||
|
||||
// at this point the geometry did not yet change
|
||||
QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
|
||||
// but quick tile mode already changed
|
||||
QCOMPARE(window->quickTileMode(), QuickTileFlag::Maximize);
|
||||
// but requested quick tile mode already changed
|
||||
QCOMPARE(window->requestedQuickTileMode(), QuickTileFlag::Maximize);
|
||||
QCOMPARE(window->quickTileMode(), oldQuickTileMode);
|
||||
QCOMPARE(window->geometryRestore(), QRect(0, 0, 100, 50));
|
||||
|
||||
// but we got requested a new geometry
|
||||
|
@ -263,19 +281,19 @@ void QuickTilingTest::testQuickMaximizing()
|
|||
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(frameGeometryChangedSpy.count(), 1);
|
||||
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||
QCOMPARE(window->quickTileMode(), QuickTileFlag::Maximize);
|
||||
QCOMPARE(window->frameGeometry(), QRect(0, 0, 1280, 1024));
|
||||
QCOMPARE(window->geometryRestore(), QRect(0, 0, 100, 50));
|
||||
|
||||
// window is now set to maximised
|
||||
QCOMPARE(maximizeChangedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->tile(), nullptr);
|
||||
|
||||
// go back to quick tile none
|
||||
QFETCH(QuickTileMode, mode);
|
||||
window->setQuickTileMode(mode, true);
|
||||
QCOMPARE(window->quickTileMode(), QuickTileMode(QuickTileFlag::None));
|
||||
QCOMPARE(quickTileChangedSpy.count(), 2);
|
||||
QCOMPARE(window->requestedQuickTileMode(), QuickTileMode(QuickTileFlag::None));
|
||||
// geometry not yet changed
|
||||
QCOMPARE(window->frameGeometry(), QRect(0, 0, 1280, 1024));
|
||||
QCOMPARE(window->geometryRestore(), QRect(0, 0, 100, 50));
|
||||
|
@ -286,10 +304,12 @@ void QuickTilingTest::testQuickMaximizing()
|
|||
|
||||
// render again
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), QSize(100, 50), Qt::yellow);
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).toSize(), Qt::yellow);
|
||||
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(frameGeometryChangedSpy.count(), 2);
|
||||
QCOMPARE(quickTileChangedSpy.count(), 2);
|
||||
QCOMPARE(window->quickTileMode(), QuickTileMode(QuickTileFlag::None));
|
||||
QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
|
||||
QCOMPARE(window->geometryRestore(), QRect(0, 0, 100, 50));
|
||||
QCOMPARE(maximizeChangedSpy.count(), 2);
|
||||
|
@ -324,6 +344,12 @@ void QuickTilingTest::testQuickTilingKeyboardMove()
|
|||
QCOMPARE(window->quickTileMode(), QuickTileMode(QuickTileFlag::None));
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
|
||||
// We have to receive a configure event when the window becomes active.
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(surfaceConfigureRequestedSpy.count(), 1);
|
||||
|
||||
QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
|
||||
|
||||
workspace()->performWindowOperation(window, Options::UnrestrictedMoveOp);
|
||||
|
@ -355,6 +381,11 @@ void QuickTilingTest::testQuickTilingKeyboardMove()
|
|||
QCOMPARE(Cursors::self()->mouse()->pos(), targetPos);
|
||||
QVERIFY(!workspace()->moveResizeWindow());
|
||||
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(surfaceConfigureRequestedSpy.count(), 2);
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).toSize(), Qt::red);
|
||||
QVERIFY(quickTileChangedSpy.wait());
|
||||
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||
QTEST(window->quickTileMode(), "expectedMode");
|
||||
}
|
||||
|
@ -389,6 +420,7 @@ void QuickTilingTest::testQuickTilingPointerMove()
|
|||
// we have to receive a configure event when the window becomes active
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(surfaceConfigureRequestedSpy.count(), 1);
|
||||
|
||||
|
@ -405,13 +437,20 @@ void QuickTilingTest::testQuickTilingPointerMove()
|
|||
Test::pointerButtonPressed(BTN_LEFT, timestamp++);
|
||||
Test::pointerMotion(pointerPos, timestamp++);
|
||||
Test::pointerButtonReleased(BTN_LEFT, timestamp++);
|
||||
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||
QTEST(window->quickTileMode(), "expectedMode");
|
||||
QTEST(window->requestedQuickTileMode(), "expectedMode");
|
||||
QCOMPARE(window->geometryRestore(), QRect(0, 0, 100, 50));
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(surfaceConfigureRequestedSpy.count(), 2);
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), tileSize);
|
||||
|
||||
// attach a new image
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), tileSize, Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->frameGeometry().size(), tileSize);
|
||||
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||
QTEST(window->quickTileMode(), "expectedMode");
|
||||
|
||||
// verify that geometry restore is correct after user untiles the window, but changes
|
||||
// their mind and tiles the window again while still holding left button
|
||||
workspace()->performWindowOperation(window, Options::UnrestrictedMoveOp);
|
||||
|
@ -419,20 +458,34 @@ void QuickTilingTest::testQuickTilingPointerMove()
|
|||
|
||||
Test::pointerButtonPressed(BTN_LEFT, timestamp++); // untile the window
|
||||
Test::pointerMotion(QPoint(1280, 1024) / 2, timestamp++);
|
||||
QCOMPARE(quickTileChangedSpy.count(), 2);
|
||||
QCOMPARE(window->quickTileMode(), QuickTileMode(QuickTileFlag::None));
|
||||
QCOMPARE(window->requestedQuickTileMode(), QuickTileMode(QuickTileFlag::None));
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(surfaceConfigureRequestedSpy.count(), 3);
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), QSize(100, 50));
|
||||
|
||||
// attach a new image
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), QSize(100, 50), Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->frameGeometry().size(), QSize(100, 50));
|
||||
QCOMPARE(quickTileChangedSpy.count(), 2);
|
||||
QCOMPARE(window->quickTileMode(), QuickTileMode(QuickTileFlag::None));
|
||||
|
||||
Test::pointerMotion(pointerPos, timestamp++); // tile the window again
|
||||
Test::pointerButtonReleased(BTN_LEFT, timestamp++);
|
||||
QCOMPARE(quickTileChangedSpy.count(), 3);
|
||||
QTEST(window->quickTileMode(), "expectedMode");
|
||||
QTEST(window->requestedQuickTileMode(), "expectedMode");
|
||||
QCOMPARE(window->geometryRestore(), QRect(0, 0, 100, 50));
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(surfaceConfigureRequestedSpy.count(), 4);
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), tileSize);
|
||||
|
||||
// attach a new image
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), QSize(100, 50), Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->frameGeometry().size(), QSize(100, 50));
|
||||
QCOMPARE(quickTileChangedSpy.count(), 3);
|
||||
QTEST(window->quickTileMode(), "expectedMode");
|
||||
}
|
||||
|
||||
void QuickTilingTest::testQuickTilingTouchMove_data()
|
||||
|
@ -499,11 +552,17 @@ void QuickTilingTest::testQuickTilingTouchMove()
|
|||
// TODO: we should test both cases with fixed fake decoration for autotests.
|
||||
const bool hasBorders = Workspace::self()->decorationBridge()->settings()->borderSize() != KDecoration2::BorderSize::None;
|
||||
|
||||
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||
QTEST(window->quickTileMode(), "expectedMode");
|
||||
QTEST(window->requestedQuickTileMode(), "expectedMode");
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QTRY_COMPARE(surfaceConfigureRequestedSpy.count(), hasBorders ? 4 : 3);
|
||||
QCOMPARE(false, toplevelConfigureRequestedSpy.last().first().toSize().isEmpty());
|
||||
|
||||
// attach a new image
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).toSize(), Qt::red);
|
||||
QVERIFY(quickTileChangedSpy.wait());
|
||||
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||
QTEST(window->quickTileMode(), "expectedMode");
|
||||
}
|
||||
|
||||
void QuickTilingTest::testX11QuickTiling_data()
|
||||
|
@ -564,7 +623,6 @@ void QuickTilingTest::testX11QuickTiling()
|
|||
QCOMPARE(window->quickTileMode(), mode);
|
||||
QTEST(window->frameGeometry(), "expectedGeometry");
|
||||
QCOMPARE(window->geometryRestore(), origGeo);
|
||||
QEXPECT_FAIL("maximize", "For maximize we get two changed signals", Continue);
|
||||
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||
|
||||
// quick tile to same edge again should also act like send to screen
|
||||
|
@ -650,7 +708,6 @@ void QuickTilingTest::testX11QuickTilingAfterVertMaximize()
|
|||
window->setQuickTileMode(mode, true);
|
||||
QCOMPARE(window->quickTileMode(), mode);
|
||||
QTEST(window->frameGeometry(), "expectedGeometry");
|
||||
QEXPECT_FAIL("", "We get two changed events", Continue);
|
||||
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||
|
||||
// and destroy the window again
|
||||
|
@ -717,6 +774,9 @@ void QuickTilingTest::testShortcut()
|
|||
|
||||
const int numberOfQuickTileActions = shortcutList.count();
|
||||
|
||||
QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
|
||||
for (QString shortcut : shortcutList) {
|
||||
// invoke global shortcut through dbus
|
||||
auto msg = QDBusMessage::createMethodCall(
|
||||
|
@ -726,28 +786,24 @@ void QuickTilingTest::testShortcut()
|
|||
QStringLiteral("invokeShortcut"));
|
||||
msg.setArguments(QList<QVariant>{shortcut});
|
||||
QDBusConnection::sessionBus().asyncCall(msg);
|
||||
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).toSize(), Qt::red);
|
||||
QVERIFY(quickTileChangedSpy.wait());
|
||||
}
|
||||
|
||||
QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
|
||||
QCOMPARE(surfaceConfigureRequestedSpy.count(), numberOfQuickTileActions + 1);
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), expectedGeometry.size());
|
||||
QCOMPARE(frameGeometryChangedSpy.count(), numberOfQuickTileActions);
|
||||
|
||||
QTRY_COMPARE(quickTileChangedSpy.count(), numberOfQuickTileActions);
|
||||
// at this point the geometry did not yet change
|
||||
QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
|
||||
// but quick tile mode already changed
|
||||
// geometry already changed
|
||||
QCOMPARE(window->frameGeometry(), expectedGeometry);
|
||||
// quick tile mode already changed
|
||||
QTEST(window->quickTileMode(), "expectedMode");
|
||||
|
||||
// but we got requested a new geometry
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(surfaceConfigureRequestedSpy.count(), 2);
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), expectedGeometry.size());
|
||||
|
||||
// attach a new image
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), expectedGeometry.size(), Qt::red);
|
||||
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QEXPECT_FAIL("maximize", "Geometry changed called twice for maximize", Continue);
|
||||
QCOMPARE(frameGeometryChangedSpy.count(), 1);
|
||||
QCOMPARE(window->frameGeometry(), expectedGeometry);
|
||||
}
|
||||
|
||||
|
@ -812,16 +868,14 @@ void QuickTilingTest::testScript()
|
|||
QSignalSpy runningChangedSpy(s, &AbstractScript::runningChanged);
|
||||
s->run();
|
||||
|
||||
QVERIFY(quickTileChangedSpy.wait());
|
||||
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||
|
||||
QVERIFY(runningChangedSpy.wait());
|
||||
QCOMPARE(runningChangedSpy.count(), 1);
|
||||
QCOMPARE(runningChangedSpy.first().first().toBool(), true);
|
||||
|
||||
// at this point the geometry did not yet change
|
||||
QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
|
||||
// but quick tile mode already changed
|
||||
QCOMPARE(window->quickTileMode(), expectedMode);
|
||||
// but requested quick tile mode already changed
|
||||
QCOMPARE(window->requestedQuickTileMode(), expectedMode);
|
||||
|
||||
// but we got requested a new geometry
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
@ -833,6 +887,8 @@ void QuickTilingTest::testScript()
|
|||
Test::render(surface.get(), expectedGeometry.size(), Qt::red);
|
||||
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(quickTileChangedSpy.count(), 1);
|
||||
QCOMPARE(window->quickTileMode(), expectedMode);
|
||||
QEXPECT_FAIL("maximize", "Geometry changed called twice for maximize", Continue);
|
||||
QCOMPARE(frameGeometryChangedSpy.count(), 1);
|
||||
QCOMPARE(window->frameGeometry(), expectedGeometry);
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
#include <QPainter>
|
||||
#include <QScreen>
|
||||
|
||||
Q_DECLARE_METATYPE(PipeWireFrame);
|
||||
|
||||
#define QCOMPAREIMG(actual, expected, id) \
|
||||
{ \
|
||||
if ((actual) != (expected)) { \
|
||||
|
@ -49,8 +47,6 @@ public:
|
|||
ScreencastingTest()
|
||||
: GenericSceneOpenGLTest(QByteArrayLiteral("O2"))
|
||||
{
|
||||
qRegisterMetaType<PipeWireFrame>();
|
||||
|
||||
auto wrap = [this](const QString &process, const QStringList &arguments = {}) {
|
||||
// Make sure PipeWire is running. If it's already running it will just exit
|
||||
QProcess *p = new QProcess(this);
|
||||
|
@ -114,7 +110,9 @@ std::optional<QImage> ScreencastingTest::oneFrameAndClose(Test::ScreencastingStr
|
|||
|
||||
std::optional<QImage> img;
|
||||
connect(&pwStream, &PipeWireSourceStream::frameReceived, qGuiApp, [&img](const PipeWireFrame &frame) {
|
||||
img = frame.image;
|
||||
if (frame.dataFrame) {
|
||||
img = frame.dataFrame->toImage();
|
||||
}
|
||||
});
|
||||
|
||||
QSignalSpy spy(&pwStream, &PipeWireSourceStream::frameReceived);
|
||||
|
|
|
@ -65,6 +65,8 @@ private Q_SLOTS:
|
|||
void testPushBack();
|
||||
void testObjectEdge_data();
|
||||
void testObjectEdge();
|
||||
void testMultipleEntry_data();
|
||||
void testMultipleEntry();
|
||||
void testKdeNetWmScreenEdgeShow();
|
||||
};
|
||||
|
||||
|
@ -304,6 +306,50 @@ void ScreenEdgesTest::testObjectEdge()
|
|||
QCOMPARE(spy.count(), 2);
|
||||
}
|
||||
|
||||
void ScreenEdgesTest::testMultipleEntry_data()
|
||||
{
|
||||
QTest::addColumn<ElectricBorder>("border");
|
||||
QTest::addColumn<QPointF>("triggerPoint");
|
||||
QTest::addColumn<QPointF>("delta");
|
||||
|
||||
QTest::newRow("top") << ElectricTop << QPointF(640, 0) << QPointF(0, 50);
|
||||
QTest::newRow("right") << ElectricRight << QPointF(1279, 512) << QPointF(-50, 0);
|
||||
QTest::newRow("bottom") << ElectricBottom << QPointF(640, 1023) << QPointF(0, -50);
|
||||
QTest::newRow("left") << ElectricLeft << QPointF(0, 512) << QPointF(50, 0);
|
||||
}
|
||||
|
||||
void ScreenEdgesTest::testMultipleEntry()
|
||||
{
|
||||
TestObject callback;
|
||||
QSignalSpy spy(&callback, &TestObject::gotCallback);
|
||||
|
||||
// Reserve a screen edge border.
|
||||
QFETCH(ElectricBorder, border);
|
||||
workspace()->screenEdges()->reserve(border, &callback, "callback");
|
||||
|
||||
QFETCH(QPointF, triggerPoint);
|
||||
QFETCH(QPointF, delta);
|
||||
|
||||
qint64 timestamp = 0;
|
||||
|
||||
while (timestamp < 300) {
|
||||
// doesn't activate from repeated entries of short duration
|
||||
Test::pointerMotion(triggerPoint, timestamp);
|
||||
QVERIFY(spy.isEmpty());
|
||||
timestamp += 50;
|
||||
Test::pointerMotion(triggerPoint + delta, timestamp);
|
||||
QVERIFY(spy.isEmpty());
|
||||
timestamp += 50;
|
||||
}
|
||||
|
||||
// and this one triggers
|
||||
Test::pointerMotion(triggerPoint, timestamp);
|
||||
timestamp += 110;
|
||||
Test::pointerMotion(triggerPoint, timestamp);
|
||||
QVERIFY(!spy.isEmpty());
|
||||
QCOMPARE(spy.count(), 1);
|
||||
}
|
||||
|
||||
static void enableAutoHide(xcb_connection_t *connection, xcb_window_t windowId, ElectricBorder border)
|
||||
{
|
||||
if (border == ElectricNone) {
|
||||
|
@ -379,7 +425,7 @@ void ScreenEdgesTest::testKdeNetWmScreenEdgeShow()
|
|||
// _KDE_NET_WM_SCREEN_EDGE_SHOW has oneshot effect. It's deleted when the window is shown.
|
||||
|
||||
auto config = kwinApp()->config();
|
||||
config->group(QStringLiteral("Windows")).writeEntry("ElectricBorderDelay", 150);
|
||||
config->group(QStringLiteral("Windows")).writeEntry("ElectricBorderDelay", 75);
|
||||
config->sync();
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
|
@ -414,15 +460,14 @@ void ScreenEdgesTest::testKdeNetWmScreenEdgeShow()
|
|||
|
||||
ScreenEdgePropertyMonitor screenEdgeMonitor(c.get(), windowId);
|
||||
QSignalSpy withdrawnSpy(&screenEdgeMonitor, &ScreenEdgePropertyMonitor::withdrawn);
|
||||
QSignalSpy windowShownSpy(window, &Window::windowShown);
|
||||
QSignalSpy windowHiddenSpy(window, &Window::windowHidden);
|
||||
QSignalSpy hiddenChangedSpy(window, &Window::hiddenChanged);
|
||||
quint32 timestamp = 0;
|
||||
|
||||
// The window will be shown when the pointer approaches its reserved screen edge.
|
||||
{
|
||||
enableAutoHide(c.get(), windowId, ElectricBottom);
|
||||
xcb_flush(c.get());
|
||||
QVERIFY(windowHiddenSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(!window->isShown());
|
||||
|
||||
Test::pointerMotion(QPointF(640, 1023), timestamp);
|
||||
|
@ -439,7 +484,7 @@ void ScreenEdgesTest::testKdeNetWmScreenEdgeShow()
|
|||
{
|
||||
enableAutoHide(c.get(), windowId, ElectricBottom);
|
||||
xcb_flush(c.get());
|
||||
QVERIFY(windowHiddenSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(!window->isShown());
|
||||
|
||||
Test::touchDown(0, QPointF(640, 1023), timestamp++);
|
||||
|
@ -449,15 +494,20 @@ void ScreenEdgesTest::testKdeNetWmScreenEdgeShow()
|
|||
QVERIFY(window->isShown());
|
||||
}
|
||||
|
||||
// If the screen edge is destroyed (can happen when the screen layout changes), the window will be shown.
|
||||
// The screen edge reservation won't be affected when recreating screen edges (can happen when the screen layout changes).
|
||||
{
|
||||
enableAutoHide(c.get(), windowId, ElectricBottom);
|
||||
xcb_flush(c.get());
|
||||
QVERIFY(windowHiddenSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(!window->isShown());
|
||||
|
||||
workspace()->screenEdges()->recreateEdges();
|
||||
QVERIFY(withdrawnSpy.wait());
|
||||
QVERIFY(!withdrawnSpy.wait(50));
|
||||
QVERIFY(!window->isShown());
|
||||
|
||||
enableAutoHide(c.get(), windowId, ElectricNone);
|
||||
xcb_flush(c.get());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(window->isShown());
|
||||
}
|
||||
|
||||
|
@ -465,12 +515,12 @@ void ScreenEdgesTest::testKdeNetWmScreenEdgeShow()
|
|||
{
|
||||
enableAutoHide(c.get(), windowId, ElectricBottom);
|
||||
xcb_flush(c.get());
|
||||
QVERIFY(windowHiddenSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(!window->isShown());
|
||||
|
||||
enableAutoHide(c.get(), windowId, ElectricNone);
|
||||
xcb_flush(c.get());
|
||||
QVERIFY(windowShownSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(window->isShown());
|
||||
}
|
||||
|
||||
|
@ -479,7 +529,7 @@ void ScreenEdgesTest::testKdeNetWmScreenEdgeShow()
|
|||
QSignalSpy approachingSpy(workspace()->screenEdges(), &ScreenEdges::approaching);
|
||||
enableAutoHide(c.get(), windowId, ElectricBottom);
|
||||
xcb_flush(c.get());
|
||||
QVERIFY(windowHiddenSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(!window->isShown());
|
||||
|
||||
Test::pointerMotion(QPointF(640, 1020), timestamp++);
|
||||
|
@ -489,7 +539,7 @@ void ScreenEdgesTest::testKdeNetWmScreenEdgeShow()
|
|||
|
||||
enableAutoHide(c.get(), windowId, ElectricNone);
|
||||
xcb_flush(c.get());
|
||||
QVERIFY(windowShownSpy.wait());
|
||||
QVERIFY(hiddenChangedSpy.wait());
|
||||
QVERIFY(window->isShown());
|
||||
QVERIFY(approachingSpy.last().at(1).toReal() == 0.0);
|
||||
|
||||
|
|
|
@ -30,10 +30,8 @@ private Q_SLOTS:
|
|||
void initTestCase();
|
||||
void init();
|
||||
void cleanup();
|
||||
void testCurrent_data();
|
||||
void testCurrent();
|
||||
void testCurrentWithFollowsMouse_data();
|
||||
void testCurrentWithFollowsMouse();
|
||||
void testActiveOutputFollowsMouse_data();
|
||||
void testActiveOutputFollowsMouse();
|
||||
void testCurrentPoint_data();
|
||||
void testCurrentPoint();
|
||||
};
|
||||
|
@ -92,30 +90,7 @@ void ScreensTest::cleanup()
|
|||
});
|
||||
}
|
||||
|
||||
void ScreensTest::testCurrent_data()
|
||||
{
|
||||
QTest::addColumn<int>("currentId");
|
||||
|
||||
QTest::newRow("first") << 0;
|
||||
QTest::newRow("second") << 1;
|
||||
}
|
||||
|
||||
void ScreensTest::testCurrent()
|
||||
{
|
||||
QFETCH(int, currentId);
|
||||
Output *output = workspace()->outputs().at(currentId);
|
||||
|
||||
// Disable "active screen follows mouse"
|
||||
auto group = kwinApp()->config()->group(QStringLiteral("Windows"));
|
||||
group.writeEntry("ActiveMouseScreen", false);
|
||||
group.sync();
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
workspace()->setActiveOutput(output);
|
||||
QCOMPARE(workspace()->activeOutput(), output);
|
||||
}
|
||||
|
||||
void ScreensTest::testCurrentWithFollowsMouse_data()
|
||||
void ScreensTest::testActiveOutputFollowsMouse_data()
|
||||
{
|
||||
QTest::addColumn<QList<QRect>>("geometries");
|
||||
QTest::addColumn<QPoint>("cursorPos");
|
||||
|
@ -127,12 +102,12 @@ void ScreensTest::testCurrentWithFollowsMouse_data()
|
|||
QTest::newRow("gap") << QList<QRect>{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QPoint(15, 30) << 1;
|
||||
}
|
||||
|
||||
void ScreensTest::testCurrentWithFollowsMouse()
|
||||
void ScreensTest::testActiveOutputFollowsMouse()
|
||||
{
|
||||
// Enable "active screen follows mouse"
|
||||
auto group = kwinApp()->config()->group(QStringLiteral("Windows"));
|
||||
group.writeEntry("ActiveMouseScreen", true);
|
||||
group.sync();
|
||||
auto edgeBarrierGroup = kwinApp()->config()->group(QStringLiteral("EdgeBarrier"));
|
||||
edgeBarrierGroup.writeEntry("EdgeBarrier", 0);
|
||||
edgeBarrierGroup.writeEntry("CornerBarrier", false);
|
||||
edgeBarrierGroup.sync();
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
QFETCH(QList<QRect>, geometries);
|
||||
|
|
|
@ -28,6 +28,10 @@ private Q_SLOTS:
|
|||
|
||||
void testRestoreFocus();
|
||||
void testRestoreFocusWithDesktopWindow();
|
||||
void testQuitAfterActivatingHiddenWindow();
|
||||
void testDontQuitAfterActivatingDock();
|
||||
void testQuitAfterAddingWindow();
|
||||
void testDontQuitAfterAddingDock();
|
||||
};
|
||||
|
||||
void ShowingDesktopTest::initTestCase()
|
||||
|
@ -115,5 +119,121 @@ void ShowingDesktopTest::testRestoreFocusWithDesktopWindow()
|
|||
QCOMPARE(workspace()->activeWindow(), window2);
|
||||
}
|
||||
|
||||
void ShowingDesktopTest::testQuitAfterActivatingHiddenWindow()
|
||||
{
|
||||
// This test verifies that the show desktop mode is deactivated after activating a hidden window.
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
|
||||
auto window1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::blue);
|
||||
std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
|
||||
auto window2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::blue);
|
||||
QCOMPARE(workspace()->activeWindow(), window2);
|
||||
|
||||
workspace()->slotToggleShowDesktop();
|
||||
QVERIFY(workspace()->showingDesktop());
|
||||
|
||||
workspace()->activateWindow(window1);
|
||||
QVERIFY(!workspace()->showingDesktop());
|
||||
}
|
||||
|
||||
void ShowingDesktopTest::testDontQuitAfterActivatingDock()
|
||||
{
|
||||
// This test verifies that activating windows belonging to desktop doesn't break showing desktop mode.
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> desktopSurface(Test::createSurface());
|
||||
std::unique_ptr<Test::LayerSurfaceV1> desktopShellSurface(Test::createLayerSurfaceV1(desktopSurface.get(), QStringLiteral("desktop")));
|
||||
desktopShellSurface->set_keyboard_interactivity(1);
|
||||
desktopShellSurface->set_layer(Test::LayerShellV1::layer_background);
|
||||
desktopShellSurface->set_size(0, 0);
|
||||
desktopShellSurface->set_exclusive_zone(-1);
|
||||
desktopShellSurface->set_anchor(Test::LayerSurfaceV1::anchor_bottom
|
||||
| Test::LayerSurfaceV1::anchor_top
|
||||
| Test::LayerSurfaceV1::anchor_left
|
||||
| Test::LayerSurfaceV1::anchor_right);
|
||||
desktopSurface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
QSignalSpy desktopConfigureRequestedSpy(desktopShellSurface.get(), &Test::LayerSurfaceV1::configureRequested);
|
||||
QVERIFY(desktopConfigureRequestedSpy.wait());
|
||||
auto desktop = Test::renderAndWaitForShown(desktopSurface.get(), desktopConfigureRequestedSpy.last().at(1).toSize(), Qt::blue);
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> dockSurface{Test::createSurface()};
|
||||
std::unique_ptr<Test::LayerSurfaceV1> dockShellSurface{Test::createLayerSurfaceV1(dockSurface.get(), QStringLiteral("dock"))};
|
||||
dockShellSurface->set_size(1280, 50);
|
||||
dockShellSurface->set_anchor(Test::LayerSurfaceV1::anchor_bottom);
|
||||
dockShellSurface->set_exclusive_zone(50);
|
||||
dockShellSurface->set_keyboard_interactivity(1);
|
||||
dockSurface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
QSignalSpy dockConfigureRequestedSpy(dockShellSurface.get(), &Test::LayerSurfaceV1::configureRequested);
|
||||
QVERIFY(dockConfigureRequestedSpy.wait());
|
||||
auto dock = Test::renderAndWaitForShown(dockSurface.get(), dockConfigureRequestedSpy.last().at(1).toSize(), Qt::blue);
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(window->isActive());
|
||||
|
||||
workspace()->slotToggleShowDesktop();
|
||||
QVERIFY(workspace()->showingDesktop());
|
||||
QVERIFY(desktop->isActive());
|
||||
|
||||
workspace()->activateWindow(dock);
|
||||
QVERIFY(workspace()->showingDesktop());
|
||||
QVERIFY(dock->isActive());
|
||||
|
||||
workspace()->activateWindow(desktop);
|
||||
QVERIFY(workspace()->showingDesktop());
|
||||
QVERIFY(desktop->isActive());
|
||||
|
||||
workspace()->slotToggleShowDesktop();
|
||||
QVERIFY(!workspace()->showingDesktop());
|
||||
}
|
||||
|
||||
void ShowingDesktopTest::testQuitAfterAddingWindow()
|
||||
{
|
||||
// This test verifies that the show desktop mode is deactivated after mapping a new window.
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
|
||||
Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
workspace()->slotToggleShowDesktop();
|
||||
QVERIFY(workspace()->showingDesktop());
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
|
||||
Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
QVERIFY(!workspace()->showingDesktop());
|
||||
}
|
||||
|
||||
void ShowingDesktopTest::testDontQuitAfterAddingDock()
|
||||
{
|
||||
// This test verifies that the show desktop mode is not broken after adding a dock.
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(window->isActive());
|
||||
|
||||
workspace()->slotToggleShowDesktop();
|
||||
QVERIFY(workspace()->showingDesktop());
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> dockSurface{Test::createSurface()};
|
||||
std::unique_ptr<Test::LayerSurfaceV1> dockShellSurface{Test::createLayerSurfaceV1(dockSurface.get(), QStringLiteral("dock"))};
|
||||
dockShellSurface->set_size(1280, 50);
|
||||
dockShellSurface->set_anchor(Test::LayerSurfaceV1::anchor_bottom);
|
||||
dockShellSurface->set_exclusive_zone(50);
|
||||
dockShellSurface->set_keyboard_interactivity(1);
|
||||
dockSurface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
QSignalSpy dockConfigureRequestedSpy(dockShellSurface.get(), &Test::LayerSurfaceV1::configureRequested);
|
||||
QVERIFY(dockConfigureRequestedSpy.wait());
|
||||
auto dock = Test::renderAndWaitForShown(dockSurface.get(), dockConfigureRequestedSpy.last().at(1).toSize(), Qt::blue);
|
||||
QVERIFY(dock->isActive());
|
||||
|
||||
QVERIFY(workspace()->showingDesktop());
|
||||
workspace()->slotToggleShowDesktop();
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(ShowingDesktopTest)
|
||||
#include "showing_desktop_test.moc"
|
||||
|
|
|
@ -84,7 +84,7 @@ void StackingOrderTest::testTransientIsAboveParent()
|
|||
// Create the parent.
|
||||
std::unique_ptr<KWayland::Client::Surface> parentSurface = Test::createSurface();
|
||||
QVERIFY(parentSurface);
|
||||
std::unique_ptr<Test::XdgToplevel> parentShellSurface(Test::createXdgToplevelSurface(parentSurface.get(), parentSurface.get()));
|
||||
std::unique_ptr<Test::XdgToplevel> parentShellSurface(Test::createXdgToplevelSurface(parentSurface.get()));
|
||||
QVERIFY(parentShellSurface);
|
||||
Window *parent = Test::renderAndWaitForShown(parentSurface.get(), QSize(256, 256), Qt::blue);
|
||||
QVERIFY(parent);
|
||||
|
@ -97,7 +97,7 @@ void StackingOrderTest::testTransientIsAboveParent()
|
|||
// Create the transient.
|
||||
std::unique_ptr<KWayland::Client::Surface> transientSurface = Test::createSurface();
|
||||
QVERIFY(transientSurface);
|
||||
std::unique_ptr<Test::XdgToplevel> transientShellSurface(Test::createXdgToplevelSurface(transientSurface.get(), transientSurface.get()));
|
||||
std::unique_ptr<Test::XdgToplevel> transientShellSurface(Test::createXdgToplevelSurface(transientSurface.get()));
|
||||
QVERIFY(transientShellSurface);
|
||||
transientShellSurface->set_parent(parentShellSurface->object());
|
||||
Window *transient = Test::renderAndWaitForShown(transientSurface.get(), QSize(128, 128), Qt::red);
|
||||
|
@ -123,7 +123,7 @@ void StackingOrderTest::testRaiseTransient()
|
|||
// Create the parent.
|
||||
std::unique_ptr<KWayland::Client::Surface> parentSurface = Test::createSurface();
|
||||
QVERIFY(parentSurface);
|
||||
std::unique_ptr<Test::XdgToplevel> parentShellSurface(Test::createXdgToplevelSurface(parentSurface.get(), parentSurface.get()));
|
||||
std::unique_ptr<Test::XdgToplevel> parentShellSurface(Test::createXdgToplevelSurface(parentSurface.get()));
|
||||
QVERIFY(parentShellSurface);
|
||||
Window *parent = Test::renderAndWaitForShown(parentSurface.get(), QSize(256, 256), Qt::blue);
|
||||
QVERIFY(parent);
|
||||
|
@ -136,7 +136,7 @@ void StackingOrderTest::testRaiseTransient()
|
|||
// Create the transient.
|
||||
std::unique_ptr<KWayland::Client::Surface> transientSurface = Test::createSurface();
|
||||
QVERIFY(transientSurface);
|
||||
std::unique_ptr<Test::XdgToplevel> transientShellSurface(Test::createXdgToplevelSurface(transientSurface.get(), transientSurface.get()));
|
||||
std::unique_ptr<Test::XdgToplevel> transientShellSurface(Test::createXdgToplevelSurface(transientSurface.get()));
|
||||
QVERIFY(transientShellSurface);
|
||||
transientShellSurface->set_parent(parentShellSurface->object());
|
||||
Window *transient = Test::renderAndWaitForShown(transientSurface.get(), QSize(128, 128), Qt::red);
|
||||
|
@ -150,7 +150,7 @@ void StackingOrderTest::testRaiseTransient()
|
|||
// Create a window that doesn't have any relationship to the parent or the transient.
|
||||
std::unique_ptr<KWayland::Client::Surface> anotherSurface = Test::createSurface();
|
||||
QVERIFY(anotherSurface);
|
||||
std::unique_ptr<Test::XdgToplevel> anotherShellSurface(Test::createXdgToplevelSurface(anotherSurface.get(), anotherSurface.get()));
|
||||
std::unique_ptr<Test::XdgToplevel> anotherShellSurface(Test::createXdgToplevelSurface(anotherSurface.get()));
|
||||
QVERIFY(anotherShellSurface);
|
||||
Window *anotherWindow = Test::renderAndWaitForShown(anotherSurface.get(), QSize(128, 128), Qt::green);
|
||||
QVERIFY(anotherWindow);
|
||||
|
@ -200,8 +200,7 @@ void StackingOrderTest::testDeletedTransient()
|
|||
// Create the parent.
|
||||
std::unique_ptr<KWayland::Client::Surface> parentSurface = Test::createSurface();
|
||||
QVERIFY(parentSurface);
|
||||
std::unique_ptr<Test::XdgToplevel>
|
||||
parentShellSurface(Test::createXdgToplevelSurface(parentSurface.get(), parentSurface.get()));
|
||||
std::unique_ptr<Test::XdgToplevel> parentShellSurface(Test::createXdgToplevelSurface(parentSurface.get()));
|
||||
QVERIFY(parentShellSurface);
|
||||
Window *parent = Test::renderAndWaitForShown(parentSurface.get(), QSize(256, 256), Qt::blue);
|
||||
QVERIFY(parent);
|
||||
|
@ -213,7 +212,7 @@ void StackingOrderTest::testDeletedTransient()
|
|||
// Create the first transient.
|
||||
std::unique_ptr<KWayland::Client::Surface> transient1Surface = Test::createSurface();
|
||||
QVERIFY(transient1Surface);
|
||||
std::unique_ptr<Test::XdgToplevel> transient1ShellSurface(Test::createXdgToplevelSurface(transient1Surface.get(), transient1Surface.get()));
|
||||
std::unique_ptr<Test::XdgToplevel> transient1ShellSurface(Test::createXdgToplevelSurface(transient1Surface.get()));
|
||||
QVERIFY(transient1ShellSurface);
|
||||
transient1ShellSurface->set_parent(parentShellSurface->object());
|
||||
Window *transient1 = Test::renderAndWaitForShown(transient1Surface.get(), QSize(128, 128), Qt::red);
|
||||
|
@ -227,7 +226,7 @@ void StackingOrderTest::testDeletedTransient()
|
|||
// Create the second transient.
|
||||
std::unique_ptr<KWayland::Client::Surface> transient2Surface = Test::createSurface();
|
||||
QVERIFY(transient2Surface);
|
||||
std::unique_ptr<Test::XdgToplevel> transient2ShellSurface(Test::createXdgToplevelSurface(transient2Surface.get(), transient2Surface.get()));
|
||||
std::unique_ptr<Test::XdgToplevel> transient2ShellSurface(Test::createXdgToplevelSurface(transient2Surface.get()));
|
||||
QVERIFY(transient2ShellSurface);
|
||||
transient2ShellSurface->set_parent(transient1ShellSurface->object());
|
||||
Window *transient2 = Test::renderAndWaitForShown(transient2Surface.get(), QSize(128, 128), Qt::red);
|
||||
|
@ -517,7 +516,7 @@ void StackingOrderTest::testRaiseGroupTransient()
|
|||
// Create a Wayland window that is not a member of the window group.
|
||||
std::unique_ptr<KWayland::Client::Surface> anotherSurface = Test::createSurface();
|
||||
QVERIFY(anotherSurface);
|
||||
std::unique_ptr<Test::XdgToplevel> anotherShellSurface(Test::createXdgToplevelSurface(anotherSurface.get(), anotherSurface.get()));
|
||||
std::unique_ptr<Test::XdgToplevel> anotherShellSurface(Test::createXdgToplevelSurface(anotherSurface.get()));
|
||||
QVERIFY(anotherShellSurface);
|
||||
Window *anotherWindow = Test::renderAndWaitForShown(anotherSurface.get(), QSize(128, 128), Qt::green);
|
||||
QVERIFY(anotherWindow);
|
||||
|
@ -759,7 +758,7 @@ void StackingOrderTest::testKeepAbove()
|
|||
// Create the first window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface1 = Test::createSurface();
|
||||
QVERIFY(surface1);
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get(), surface1.get()));
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
|
||||
QVERIFY(shellSurface1);
|
||||
Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(128, 128), Qt::green);
|
||||
QVERIFY(window1);
|
||||
|
@ -771,7 +770,7 @@ void StackingOrderTest::testKeepAbove()
|
|||
// Create the second window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface2 = Test::createSurface();
|
||||
QVERIFY(surface2);
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get(), surface2.get()));
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
|
||||
QVERIFY(shellSurface2);
|
||||
Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(128, 128), Qt::green);
|
||||
QVERIFY(window2);
|
||||
|
@ -803,7 +802,7 @@ void StackingOrderTest::testKeepBelow()
|
|||
// Create the first window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface1 = Test::createSurface();
|
||||
QVERIFY(surface1);
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get(), surface1.get()));
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
|
||||
QVERIFY(shellSurface1);
|
||||
Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(128, 128), Qt::green);
|
||||
QVERIFY(window1);
|
||||
|
@ -815,7 +814,7 @@ void StackingOrderTest::testKeepBelow()
|
|||
// Create the second window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface2 = Test::createSurface();
|
||||
QVERIFY(surface2);
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get(), surface2.get()));
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
|
||||
QVERIFY(shellSurface2);
|
||||
Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(128, 128), Qt::green);
|
||||
QVERIFY(window2);
|
||||
|
@ -850,7 +849,7 @@ void StackingOrderTest::testPreserveRelativeWindowStacking()
|
|||
for (int i = 0; i < windowsQuantity; i++) {
|
||||
surfaces[i] = Test::createSurface();
|
||||
QVERIFY(surfaces[i]);
|
||||
shellSurfaces[i] = std::unique_ptr<Test::XdgToplevel>(Test::createXdgToplevelSurface(surfaces[i].get(), surfaces[i].get()));
|
||||
shellSurfaces[i] = Test::createXdgToplevelSurface(surfaces[i].get());
|
||||
QVERIFY(shellSurfaces[i]);
|
||||
}
|
||||
|
||||
|
|
|
@ -367,7 +367,7 @@ void StrutsTest::testX11Struts()
|
|||
QVERIFY(window);
|
||||
QCOMPARE(window->window(), windowId);
|
||||
QVERIFY(!window->isDecorated());
|
||||
QCOMPARE(window->windowType(), NET::Dock);
|
||||
QCOMPARE(window->windowType(), WindowType::Dock);
|
||||
QCOMPARE(window->frameGeometry(), windowGeometry);
|
||||
|
||||
// this should have affected the client area
|
||||
|
@ -479,7 +479,7 @@ void StrutsTest::test363804()
|
|||
QVERIFY(window);
|
||||
QCOMPARE(window->window(), windowId);
|
||||
QVERIFY(!window->isDecorated());
|
||||
QCOMPARE(window->windowType(), NET::Dock);
|
||||
QCOMPARE(window->windowType(), WindowType::Dock);
|
||||
QCOMPARE(window->frameGeometry(), windowGeometry);
|
||||
|
||||
// now verify the actual updated client areas
|
||||
|
@ -557,7 +557,7 @@ void StrutsTest::testLeftScreenSmallerBottomAligned()
|
|||
QVERIFY(window);
|
||||
QCOMPARE(window->window(), windowId);
|
||||
QVERIFY(!window->isDecorated());
|
||||
QCOMPARE(window->windowType(), NET::Dock);
|
||||
QCOMPARE(window->windowType(), WindowType::Dock);
|
||||
QCOMPARE(window->frameGeometry(), windowGeometry);
|
||||
|
||||
// now verify the actual updated client areas
|
||||
|
@ -638,7 +638,7 @@ void StrutsTest::testWindowMoveWithPanelBetweenScreens()
|
|||
QVERIFY(window);
|
||||
QCOMPARE(window->window(), windowId);
|
||||
QVERIFY(!window->isDecorated());
|
||||
QCOMPARE(window->windowType(), NET::Dock);
|
||||
QCOMPARE(window->windowType(), WindowType::Dock);
|
||||
QCOMPARE(window->frameGeometry(), windowGeometry);
|
||||
|
||||
// now verify the actual updated client areas
|
||||
|
|
|
@ -104,11 +104,11 @@ void TabBoxTest::testCapsLock()
|
|||
quint32 timestamp = 0;
|
||||
Test::keyboardKeyPressed(KEY_CAPSLOCK, timestamp++);
|
||||
Test::keyboardKeyReleased(KEY_CAPSLOCK, timestamp++);
|
||||
QCOMPARE(input()->keyboardModifiers(), Qt::ShiftModifier);
|
||||
QCOMPARE(input()->keyboardModifiers(), Qt::NoModifier);
|
||||
|
||||
// press alt+tab
|
||||
Test::keyboardKeyPressed(KEY_LEFTALT, timestamp++);
|
||||
QCOMPARE(input()->keyboardModifiers(), Qt::ShiftModifier | Qt::AltModifier);
|
||||
QCOMPARE(input()->keyboardModifiers(), Qt::AltModifier);
|
||||
Test::keyboardKeyPressed(KEY_TAB, timestamp++);
|
||||
Test::keyboardKeyReleased(KEY_TAB, timestamp++);
|
||||
|
||||
|
|
|
@ -269,6 +269,21 @@ SecurityContextManagerV1::~SecurityContextManagerV1()
|
|||
destroy();
|
||||
}
|
||||
|
||||
XdgWmDialogV1::~XdgWmDialogV1()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
XdgDialogV1::XdgDialogV1(XdgWmDialogV1 *wm, XdgToplevel *toplevel)
|
||||
: QtWayland::xdg_dialog_v1(wm->get_xdg_dialog(toplevel->object()))
|
||||
{
|
||||
}
|
||||
|
||||
XdgDialogV1::~XdgDialogV1()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
KWayland::Client::ConnectionThread *connection = nullptr;
|
||||
|
@ -302,6 +317,7 @@ static struct
|
|||
CursorShapeManagerV1 *cursorShapeManagerV1 = nullptr;
|
||||
FakeInput *fakeInput = nullptr;
|
||||
SecurityContextManagerV1 *securityContextManagerV1 = nullptr;
|
||||
XdgWmDialogV1 *xdgWmDialogV1;
|
||||
} s_waylandConnection;
|
||||
|
||||
MockInputMethod *inputMethod()
|
||||
|
@ -326,14 +342,27 @@ void MockInputMethod::zwp_input_method_v1_activate(struct ::zwp_input_method_con
|
|||
{
|
||||
if (!m_inputSurface) {
|
||||
m_inputSurface = Test::createSurface();
|
||||
m_inputMethodSurface = Test::createInputPanelSurfaceV1(m_inputSurface.get(), s_waylandConnection.outputs.first());
|
||||
m_inputMethodSurface = Test::createInputPanelSurfaceV1(m_inputSurface.get(), s_waylandConnection.outputs.first(), m_mode);
|
||||
}
|
||||
m_context = context;
|
||||
Test::render(m_inputSurface.get(), QSize(1280, 400), Qt::blue);
|
||||
|
||||
switch (m_mode) {
|
||||
case Mode::TopLevel:
|
||||
Test::render(m_inputSurface.get(), QSize(1280, 400), Qt::blue);
|
||||
break;
|
||||
case Mode::Overlay:
|
||||
Test::render(m_inputSurface.get(), QSize(200, 50), Qt::blue);
|
||||
break;
|
||||
}
|
||||
|
||||
Q_EMIT activate();
|
||||
}
|
||||
|
||||
void MockInputMethod::setMode(MockInputMethod::Mode mode)
|
||||
{
|
||||
m_mode = mode;
|
||||
}
|
||||
|
||||
void MockInputMethod::zwp_input_method_v1_deactivate(struct ::zwp_input_method_context_v1 *context)
|
||||
{
|
||||
QCOMPARE(context, m_context);
|
||||
|
@ -344,8 +373,7 @@ void MockInputMethod::zwp_input_method_v1_deactivate(struct ::zwp_input_method_c
|
|||
m_inputSurface->release();
|
||||
m_inputSurface->destroy();
|
||||
m_inputSurface.reset();
|
||||
delete m_inputMethodSurface;
|
||||
m_inputMethodSurface = nullptr;
|
||||
m_inputMethodSurface.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -505,6 +533,12 @@ bool setupWaylandConnection(AdditionalWaylandInterfaces flags)
|
|||
s_waylandConnection.securityContextManagerV1->init(*registry, name, version);
|
||||
}
|
||||
}
|
||||
if (flags & AdditionalWaylandInterface::XdgDialogV1) {
|
||||
if (interface == xdg_wm_dialog_v1_interface.name) {
|
||||
s_waylandConnection.xdgWmDialogV1 = new XdgWmDialogV1();
|
||||
s_waylandConnection.xdgWmDialogV1->init(*registry, name, version);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
QSignalSpy allAnnounced(registry, &KWayland::Client::Registry::interfacesAnnounced);
|
||||
|
@ -630,6 +664,8 @@ void destroyWaylandConnection()
|
|||
s_waylandConnection.fakeInput = nullptr;
|
||||
delete s_waylandConnection.securityContextManagerV1;
|
||||
s_waylandConnection.securityContextManagerV1 = nullptr;
|
||||
delete s_waylandConnection.xdgWmDialogV1;
|
||||
s_waylandConnection.xdgWmDialogV1 = nullptr;
|
||||
|
||||
delete s_waylandConnection.queue; // Must be destroyed last
|
||||
s_waylandConnection.queue = nullptr;
|
||||
|
@ -892,20 +928,19 @@ std::unique_ptr<KWayland::Client::Surface> createSurface()
|
|||
return s->isValid() ? std::move(s) : nullptr;
|
||||
}
|
||||
|
||||
KWayland::Client::SubSurface *createSubSurface(KWayland::Client::Surface *surface, KWayland::Client::Surface *parentSurface, QObject *parent)
|
||||
std::unique_ptr<KWayland::Client::SubSurface> createSubSurface(KWayland::Client::Surface *surface, KWayland::Client::Surface *parentSurface)
|
||||
{
|
||||
if (!s_waylandConnection.subCompositor) {
|
||||
return nullptr;
|
||||
}
|
||||
auto s = s_waylandConnection.subCompositor->createSubSurface(surface, parentSurface, parent);
|
||||
std::unique_ptr<KWayland::Client::SubSurface> s(s_waylandConnection.subCompositor->createSubSurface(surface, parentSurface));
|
||||
if (!s->isValid()) {
|
||||
delete s;
|
||||
return nullptr;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
LayerSurfaceV1 *createLayerSurfaceV1(KWayland::Client::Surface *surface, const QString &scope, KWayland::Client::Output *output, LayerShellV1::layer layer)
|
||||
std::unique_ptr<LayerSurfaceV1> createLayerSurfaceV1(KWayland::Client::Surface *surface, const QString &scope, KWayland::Client::Output *output, LayerShellV1::layer layer)
|
||||
{
|
||||
LayerShellV1 *shell = s_waylandConnection.layerShellV1;
|
||||
if (!shell) {
|
||||
|
@ -918,37 +953,42 @@ LayerSurfaceV1 *createLayerSurfaceV1(KWayland::Client::Surface *surface, const Q
|
|||
nativeOutput = *output;
|
||||
}
|
||||
|
||||
LayerSurfaceV1 *shellSurface = new LayerSurfaceV1();
|
||||
auto shellSurface = std::make_unique<LayerSurfaceV1>();
|
||||
shellSurface->init(shell->get_layer_surface(*surface, nativeOutput, layer, scope));
|
||||
|
||||
return shellSurface;
|
||||
}
|
||||
|
||||
QtWayland::zwp_input_panel_surface_v1 *createInputPanelSurfaceV1(KWayland::Client::Surface *surface, KWayland::Client::Output *output)
|
||||
std::unique_ptr<QtWayland::zwp_input_panel_surface_v1> createInputPanelSurfaceV1(KWayland::Client::Surface *surface, KWayland::Client::Output *output, MockInputMethod::Mode mode)
|
||||
{
|
||||
if (!s_waylandConnection.inputPanelV1) {
|
||||
qWarning() << "Unable to create the input panel surface. The interface input_panel global is not bound";
|
||||
return nullptr;
|
||||
}
|
||||
QtWayland::zwp_input_panel_surface_v1 *s = new QtWayland::zwp_input_panel_surface_v1(s_waylandConnection.inputPanelV1->get_input_panel_surface(*surface));
|
||||
|
||||
auto s = std::make_unique<QtWayland::zwp_input_panel_surface_v1>(s_waylandConnection.inputPanelV1->get_input_panel_surface(*surface));
|
||||
if (!s->isInitialized()) {
|
||||
delete s;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
s->set_toplevel(output->output(), QtWayland::zwp_input_panel_surface_v1::position_center_bottom);
|
||||
switch (mode) {
|
||||
case MockInputMethod::Mode::TopLevel:
|
||||
s->set_toplevel(output->output(), QtWayland::zwp_input_panel_surface_v1::position_center_bottom);
|
||||
break;
|
||||
case MockInputMethod::Mode::Overlay:
|
||||
s->set_overlay_panel();
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
FractionalScaleV1 *createFractionalScaleV1(KWayland::Client::Surface *surface)
|
||||
std::unique_ptr<FractionalScaleV1> createFractionalScaleV1(KWayland::Client::Surface *surface)
|
||||
{
|
||||
if (!s_waylandConnection.fractionalScaleManagerV1) {
|
||||
qWarning() << "Unable to create fractional scale surface. The global is not bound";
|
||||
return nullptr;
|
||||
}
|
||||
auto scale = new FractionalScaleV1();
|
||||
auto scale = std::make_unique<FractionalScaleV1>();
|
||||
scale->init(s_waylandConnection.fractionalScaleManagerV1->get_fractional_scale(*surface));
|
||||
|
||||
return scale;
|
||||
|
@ -964,12 +1004,12 @@ static void waitForConfigured(XdgSurface *shellSurface)
|
|||
shellSurface->ack_configure(surfaceConfigureRequestedSpy.last().first().toUInt());
|
||||
}
|
||||
|
||||
XdgToplevel *createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent)
|
||||
std::unique_ptr<XdgToplevel> createXdgToplevelSurface(KWayland::Client::Surface *surface)
|
||||
{
|
||||
return createXdgToplevelSurface(surface, CreationSetup::CreateAndConfigure, parent);
|
||||
return createXdgToplevelSurface(surface, CreationSetup::CreateAndConfigure);
|
||||
}
|
||||
|
||||
XdgToplevel *createXdgToplevelSurface(KWayland::Client::Surface *surface, CreationSetup configureMode, QObject *parent)
|
||||
std::unique_ptr<XdgToplevel> createXdgToplevelSurface(KWayland::Client::Surface *surface, CreationSetup configureMode)
|
||||
{
|
||||
XdgShell *shell = s_waylandConnection.xdgShell;
|
||||
|
||||
|
@ -979,7 +1019,7 @@ XdgToplevel *createXdgToplevelSurface(KWayland::Client::Surface *surface, Creati
|
|||
}
|
||||
|
||||
XdgSurface *xdgSurface = new XdgSurface(shell, surface);
|
||||
XdgToplevel *xdgToplevel = new XdgToplevel(xdgSurface, parent);
|
||||
std::unique_ptr<XdgToplevel> xdgToplevel = std::make_unique<XdgToplevel>(xdgSurface);
|
||||
|
||||
if (configureMode == CreationSetup::CreateAndConfigure) {
|
||||
waitForConfigured(xdgSurface);
|
||||
|
@ -988,7 +1028,25 @@ XdgToplevel *createXdgToplevelSurface(KWayland::Client::Surface *surface, Creati
|
|||
return xdgToplevel;
|
||||
}
|
||||
|
||||
XdgPositioner *createXdgPositioner()
|
||||
std::unique_ptr<XdgToplevel> createXdgToplevelSurface(KWayland::Client::Surface *surface, std::function<void(XdgToplevel *toplevel)> setup)
|
||||
{
|
||||
XdgShell *shell = s_waylandConnection.xdgShell;
|
||||
|
||||
if (!shell) {
|
||||
qWarning() << "Could not create an xdg_toplevel surface because xdg_wm_base global is not bound";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
XdgSurface *xdgSurface = new XdgSurface(shell, surface);
|
||||
std::unique_ptr<XdgToplevel> xdgToplevel = std::make_unique<XdgToplevel>(xdgSurface);
|
||||
|
||||
setup(xdgToplevel.get());
|
||||
waitForConfigured(xdgSurface);
|
||||
|
||||
return xdgToplevel;
|
||||
}
|
||||
|
||||
std::unique_ptr<XdgPositioner> createXdgPositioner()
|
||||
{
|
||||
XdgShell *shell = s_waylandConnection.xdgShell;
|
||||
|
||||
|
@ -997,11 +1055,10 @@ XdgPositioner *createXdgPositioner()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return new XdgPositioner(shell);
|
||||
return std::make_unique<XdgPositioner>(shell);
|
||||
}
|
||||
|
||||
XdgPopup *createXdgPopupSurface(KWayland::Client::Surface *surface, XdgSurface *parentSurface, XdgPositioner *positioner,
|
||||
CreationSetup configureMode, QObject *parent)
|
||||
std::unique_ptr<XdgPopup> createXdgPopupSurface(KWayland::Client::Surface *surface, XdgSurface *parentSurface, XdgPositioner *positioner, CreationSetup configureMode)
|
||||
{
|
||||
XdgShell *shell = s_waylandConnection.xdgShell;
|
||||
|
||||
|
@ -1011,7 +1068,7 @@ XdgPopup *createXdgPopupSurface(KWayland::Client::Surface *surface, XdgSurface *
|
|||
}
|
||||
|
||||
XdgSurface *xdgSurface = new XdgSurface(shell, surface);
|
||||
XdgPopup *xdgPopup = new XdgPopup(xdgSurface, parentSurface, positioner, parent);
|
||||
std::unique_ptr<XdgPopup> xdgPopup = std::make_unique<XdgPopup>(xdgSurface, parentSurface, positioner);
|
||||
|
||||
if (configureMode == CreationSetup::CreateAndConfigure) {
|
||||
waitForConfigured(xdgSurface);
|
||||
|
@ -1020,7 +1077,7 @@ XdgPopup *createXdgPopupSurface(KWayland::Client::Surface *surface, XdgSurface *
|
|||
return xdgPopup;
|
||||
}
|
||||
|
||||
XdgToplevelDecorationV1 *createXdgToplevelDecorationV1(XdgToplevel *toplevel, QObject *parent)
|
||||
std::unique_ptr<XdgToplevelDecorationV1> createXdgToplevelDecorationV1(XdgToplevel *toplevel)
|
||||
{
|
||||
XdgDecorationManagerV1 *manager = s_waylandConnection.xdgDecorationManagerV1;
|
||||
|
||||
|
@ -1029,10 +1086,10 @@ XdgToplevelDecorationV1 *createXdgToplevelDecorationV1(XdgToplevel *toplevel, QO
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return new XdgToplevelDecorationV1(manager, toplevel, parent);
|
||||
return std::make_unique<XdgToplevelDecorationV1>(manager, toplevel);
|
||||
}
|
||||
|
||||
IdleInhibitorV1 *createIdleInhibitorV1(KWayland::Client::Surface *surface)
|
||||
std::unique_ptr<IdleInhibitorV1> createIdleInhibitorV1(KWayland::Client::Surface *surface)
|
||||
{
|
||||
IdleInhibitManagerV1 *manager = s_waylandConnection.idleInhibitManagerV1;
|
||||
if (!manager) {
|
||||
|
@ -1040,10 +1097,10 @@ IdleInhibitorV1 *createIdleInhibitorV1(KWayland::Client::Surface *surface)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return new IdleInhibitorV1(manager, surface);
|
||||
return std::make_unique<IdleInhibitorV1>(manager, surface);
|
||||
}
|
||||
|
||||
AutoHideScreenEdgeV1 *createAutoHideScreenEdgeV1(KWayland::Client::Surface *surface, uint32_t border)
|
||||
std::unique_ptr<AutoHideScreenEdgeV1> createAutoHideScreenEdgeV1(KWayland::Client::Surface *surface, uint32_t border)
|
||||
{
|
||||
ScreenEdgeManagerV1 *manager = s_waylandConnection.screenEdgeManagerV1;
|
||||
if (!manager) {
|
||||
|
@ -1051,10 +1108,10 @@ AutoHideScreenEdgeV1 *createAutoHideScreenEdgeV1(KWayland::Client::Surface *surf
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return new AutoHideScreenEdgeV1(manager, surface, border);
|
||||
return std::make_unique<AutoHideScreenEdgeV1>(manager, surface, border);
|
||||
}
|
||||
|
||||
CursorShapeDeviceV1 *createCursorShapeDeviceV1(KWayland::Client::Pointer *pointer)
|
||||
std::unique_ptr<CursorShapeDeviceV1> createCursorShapeDeviceV1(KWayland::Client::Pointer *pointer)
|
||||
{
|
||||
CursorShapeManagerV1 *manager = s_waylandConnection.cursorShapeManagerV1;
|
||||
if (!manager) {
|
||||
|
@ -1062,7 +1119,17 @@ CursorShapeDeviceV1 *createCursorShapeDeviceV1(KWayland::Client::Pointer *pointe
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return new CursorShapeDeviceV1(manager, pointer);
|
||||
return std::make_unique<CursorShapeDeviceV1>(manager, pointer);
|
||||
}
|
||||
|
||||
std::unique_ptr<XdgDialogV1> createXdgDialogV1(XdgToplevel *toplevel)
|
||||
{
|
||||
XdgWmDialogV1 *wm = s_waylandConnection.xdgWmDialogV1;
|
||||
if (!wm) {
|
||||
qWarning() << "Could not create a xdg_dialog_v1 because xdg_wm_dialog_v1 global is not bound";
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_unique<XdgDialogV1>(wm, toplevel);
|
||||
}
|
||||
|
||||
bool waitForWindowClosed(Window *window)
|
||||
|
@ -1163,6 +1230,7 @@ bool renderNodeAvailable()
|
|||
});
|
||||
}
|
||||
|
||||
#if KWIN_BUILD_X11
|
||||
void XcbConnectionDeleter::operator()(xcb_connection_t *pointer)
|
||||
{
|
||||
xcb_disconnect(pointer);
|
||||
|
@ -1180,6 +1248,7 @@ Test::XcbConnectionPtr createX11Connection()
|
|||
e.exec();
|
||||
return Test::XcbConnectionPtr(future.result());
|
||||
}
|
||||
#endif
|
||||
|
||||
WaylandOutputManagementV2::WaylandOutputManagementV2(struct ::wl_registry *registry, int id, int version)
|
||||
: QObject()
|
||||
|
@ -1542,11 +1611,6 @@ bool VirtualInputDevice::isKeyboard() const
|
|||
return m_keyboard;
|
||||
}
|
||||
|
||||
bool VirtualInputDevice::isAlphaNumericKeyboard() const
|
||||
{
|
||||
return m_keyboard;
|
||||
}
|
||||
|
||||
bool VirtualInputDevice::isPointer() const
|
||||
{
|
||||
return m_pointer;
|
||||
|
|
|
@ -46,7 +46,14 @@ private Q_SLOTS:
|
|||
void testGestureDetection();
|
||||
|
||||
private:
|
||||
std::pair<Window *, std::unique_ptr<KWayland::Client::Surface>> showWindow(bool decorated = false);
|
||||
struct WindowHandle
|
||||
{
|
||||
Window *window;
|
||||
std::unique_ptr<KWayland::Client::Surface> surface;
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface;
|
||||
std::unique_ptr<Test::XdgToplevelDecorationV1> decoration;
|
||||
};
|
||||
WindowHandle showWindow(bool decorated = false);
|
||||
KWayland::Client::Touch *m_touch = nullptr;
|
||||
};
|
||||
|
||||
|
@ -87,21 +94,22 @@ void TouchInputTest::cleanup()
|
|||
Test::destroyWaylandConnection();
|
||||
}
|
||||
|
||||
std::pair<Window *, std::unique_ptr<KWayland::Client::Surface>> TouchInputTest::showWindow(bool decorated)
|
||||
TouchInputTest::WindowHandle TouchInputTest::showWindow(bool decorated)
|
||||
{
|
||||
#define VERIFY(statement) \
|
||||
if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__)) \
|
||||
return {nullptr, nullptr};
|
||||
return {};
|
||||
#define COMPARE(actual, expected) \
|
||||
if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__, __LINE__)) \
|
||||
return {nullptr, nullptr};
|
||||
return {};
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
VERIFY(surface.get());
|
||||
Test::XdgToplevel *shellSurface = Test::createXdgToplevelSurface(surface.get(), Test::CreationSetup::CreateOnly, surface.get());
|
||||
VERIFY(shellSurface);
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface = Test::createXdgToplevelSurface(surface.get(), Test::CreationSetup::CreateOnly);
|
||||
VERIFY(shellSurface.get());
|
||||
std::unique_ptr<Test::XdgToplevelDecorationV1> decoration;
|
||||
if (decorated) {
|
||||
auto decoration = Test::createXdgToplevelDecorationV1(shellSurface, shellSurface);
|
||||
decoration = Test::createXdgToplevelDecorationV1(shellSurface.get());
|
||||
decoration->set_mode(Test::XdgToplevelDecorationV1::mode_server_side);
|
||||
}
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
|
@ -117,7 +125,7 @@ std::pair<Window *, std::unique_ptr<KWayland::Client::Surface>> TouchInputTest::
|
|||
#undef VERIFY
|
||||
#undef COMPARE
|
||||
|
||||
return {window, std::move(surface)};
|
||||
return {window, std::move(surface), std::move(shellSurface), std::move(decoration)};
|
||||
}
|
||||
|
||||
void TouchInputTest::testTouchHidesCursor()
|
||||
|
@ -155,7 +163,7 @@ void TouchInputTest::testMultipleTouchPoints_data()
|
|||
void TouchInputTest::testMultipleTouchPoints()
|
||||
{
|
||||
QFETCH(bool, decorated);
|
||||
auto [window, surface] = showWindow(decorated);
|
||||
auto [window, surface, shellSurface, decoration] = showWindow(decorated);
|
||||
QCOMPARE(window->isDecorated(), decorated);
|
||||
window->move(QPoint(100, 100));
|
||||
QVERIFY(window);
|
||||
|
@ -210,7 +218,7 @@ void TouchInputTest::testMultipleTouchPoints()
|
|||
|
||||
void TouchInputTest::testCancel()
|
||||
{
|
||||
auto [window, surface] = showWindow();
|
||||
auto [window, surface, shellSurface, decoration] = showWindow();
|
||||
window->move(QPoint(100, 100));
|
||||
QVERIFY(window);
|
||||
QSignalSpy sequenceStartedSpy(m_touch, &KWayland::Client::Touch::sequenceStarted);
|
||||
|
@ -233,9 +241,9 @@ void TouchInputTest::testTouchMouseAction()
|
|||
// this test verifies that a touch down on an inactive window will activate it
|
||||
|
||||
// create two windows
|
||||
auto [c1, surface] = showWindow();
|
||||
auto [c1, surface, shellSurface, decoration] = showWindow();
|
||||
QVERIFY(c1);
|
||||
auto [c2, surface2] = showWindow();
|
||||
auto [c2, surface2, shellSurface2, decoration2] = showWindow();
|
||||
QVERIFY(c2);
|
||||
|
||||
QVERIFY(!c1->isActive());
|
||||
|
|
|
@ -114,7 +114,7 @@ void TransientPlacementTest::testXdgPopup_data()
|
|||
.anchor = Test::XdgPositioner::anchor_none,
|
||||
.gravity = Test::XdgPositioner::gravity_bottom_right,
|
||||
};
|
||||
QTest::newRow("anchorCentre") << QSize(500, 500) << QPoint(300, 300) << layoutAnchorCenter << QRect(550, 550, 200, 200);
|
||||
QTest::newRow("anchorCenter") << QSize(500, 500) << QPoint(300, 300) << layoutAnchorCenter << QRect(550, 550, 200, 200);
|
||||
|
||||
const PopupLayout layoutAnchorTopLeft{
|
||||
.anchorRect = QRect(50, 50, 400, 400),
|
||||
|
@ -189,7 +189,7 @@ void TransientPlacementTest::testXdgPopup_data()
|
|||
.anchor = Test::XdgPositioner::anchor_bottom_right,
|
||||
.gravity = Test::XdgPositioner::gravity_none,
|
||||
};
|
||||
QTest::newRow("gravityCentre") << QSize(500, 500) << QPoint(300, 300) << layoutGravityCenter << QRect(650, 650, 200, 200);
|
||||
QTest::newRow("gravityCenter") << QSize(500, 500) << QPoint(300, 300) << layoutGravityCenter << QRect(650, 650, 200, 200);
|
||||
|
||||
const PopupLayout layoutGravityTopLeft{
|
||||
.anchorRect = QRect(50, 50, 400, 400),
|
||||
|
@ -423,7 +423,7 @@ void TransientPlacementTest::testXdgPopup()
|
|||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface();
|
||||
QVERIFY(surface);
|
||||
auto parentShellSurface = Test::createXdgToplevelSurface(surface.get(), Test::waylandCompositor());
|
||||
std::unique_ptr<Test::XdgToplevel> parentShellSurface = Test::createXdgToplevelSurface(surface.get());
|
||||
QVERIFY(parentShellSurface);
|
||||
auto parent = Test::renderAndWaitForShown(surface.get(), parentSize, Qt::blue);
|
||||
QVERIFY(parent);
|
||||
|
@ -480,7 +480,7 @@ void TransientPlacementTest::testXdgPopupWithPanel()
|
|||
QVERIFY(dockConfigureRequestedSpy.wait());
|
||||
auto dock = Test::renderAndWaitForShown(dockSurface.get(), dockConfigureRequestedSpy.last().at(1).toSize(), Qt::blue);
|
||||
QVERIFY(dock);
|
||||
QCOMPARE(dock->windowType(), NET::Dock);
|
||||
QCOMPARE(dock->windowType(), WindowType::Dock);
|
||||
QVERIFY(dock->isDock());
|
||||
QCOMPARE(dock->frameGeometry(), QRect(0, output->geometry().height() - 50, 1280, 50));
|
||||
QCOMPARE(dock->hasStrut(), true);
|
||||
|
@ -497,7 +497,7 @@ void TransientPlacementTest::testXdgPopupWithPanel()
|
|||
|
||||
QVERIFY(!parent->isDecorated());
|
||||
parent->move(QPointF(0, output->geometry().height() - 600));
|
||||
parent->keepInArea(workspace()->clientArea(PlacementArea, parent));
|
||||
parent->moveResize(parent->keepInArea(parent->moveResizeGeometry(), workspace()->clientArea(PlacementArea, parent)));
|
||||
QCOMPARE(parent->frameGeometry(), QRect(0, output->geometry().height() - 600 - 50, 800, 600));
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> transientSurface(Test::createSurface());
|
||||
|
@ -522,7 +522,7 @@ void TransientPlacementTest::testXdgPopupWithPanel()
|
|||
QVERIFY(Test::waitForWindowClosed(transient));
|
||||
|
||||
// now parent to fullscreen - on fullscreen the panel is ignored
|
||||
QSignalSpy toplevelConfigureRequestedSpy(parentShellSurface, &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy toplevelConfigureRequestedSpy(parentShellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(parentShellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
parent->setFullScreen(true);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
@ -542,7 +542,7 @@ void TransientPlacementTest::testXdgPopupWithPanel()
|
|||
positioner2->set_size(200, 200);
|
||||
positioner2->set_anchor_rect(anchorRect2.x(), anchorRect2.y(), anchorRect2.width(), anchorRect2.height());
|
||||
positioner2->set_constraint_adjustment(Test::XdgPositioner::constraint_adjustment_slide_x | Test::XdgPositioner::constraint_adjustment_slide_y);
|
||||
transientShellSurface.reset(Test::createXdgPopupSurface(transientSurface.get(), parentShellSurface->xdgSurface(), positioner2.get()));
|
||||
transientShellSurface = Test::createXdgPopupSurface(transientSurface.get(), parentShellSurface->xdgSurface(), positioner2.get());
|
||||
transient = Test::renderAndWaitForShown(transientSurface.get(), QSize(200, 200), Qt::red);
|
||||
QVERIFY(transient);
|
||||
|
||||
|
|
|
@ -9,12 +9,15 @@
|
|||
#include "kwin_wayland_test.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "utils/xcbutils.h"
|
||||
#include "virtualdesktops.h"
|
||||
#include "wayland_server.h"
|
||||
#include "window.h"
|
||||
#include "workspace.h"
|
||||
|
||||
#if KWIN_BUILD_X11
|
||||
#include "utils/xcbutils.h"
|
||||
#endif
|
||||
|
||||
#include <KWayland/Client/surface.h>
|
||||
|
||||
using namespace KWin;
|
||||
|
@ -28,8 +31,9 @@ private Q_SLOTS:
|
|||
void initTestCase();
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
#if KWIN_BUILD_X11
|
||||
void testNetCurrentDesktop();
|
||||
#endif
|
||||
void testLastDesktopRemoved();
|
||||
void testWindowOnMultipleDesktops();
|
||||
void testRemoveDesktopWithWindow();
|
||||
|
@ -52,6 +56,7 @@ void VirtualDesktopTest::initTestCase()
|
|||
kwinApp()->start();
|
||||
QVERIFY(applicationStartedSpy.wait());
|
||||
|
||||
#if KWIN_BUILD_X11
|
||||
if (kwinApp()->x11Connection()) {
|
||||
// verify the current desktop x11 property on startup, see BUG: 391034
|
||||
Xcb::Atom currentDesktopAtom("_NET_CURRENT_DESKTOP");
|
||||
|
@ -61,6 +66,7 @@ void VirtualDesktopTest::initTestCase()
|
|||
QCOMPARE(currentDesktop.value(0, &ok), 0);
|
||||
QVERIFY(ok);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void VirtualDesktopTest::init()
|
||||
|
@ -75,6 +81,7 @@ void VirtualDesktopTest::cleanup()
|
|||
Test::destroyWaylandConnection();
|
||||
}
|
||||
|
||||
#if KWIN_BUILD_X11
|
||||
void VirtualDesktopTest::testNetCurrentDesktop()
|
||||
{
|
||||
if (!kwinApp()->x11Connection()) {
|
||||
|
@ -115,6 +122,7 @@ void VirtualDesktopTest::testNetCurrentDesktop()
|
|||
QCOMPARE(currentDesktop.value(0, &ok), 0);
|
||||
QVERIFY(ok);
|
||||
}
|
||||
#endif
|
||||
|
||||
void VirtualDesktopTest::testLastDesktopRemoved()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2024 David Edmundson <davidedmundson@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "kwin_wayland_test.h"
|
||||
|
||||
#include "input.h"
|
||||
#include "options.h"
|
||||
#include "pointer_input.h"
|
||||
#include "qabstracteventdispatcher.h"
|
||||
#include "qsocketnotifier.h"
|
||||
#include "wayland/keyboard.h"
|
||||
#include "wayland/seat.h"
|
||||
#include "wayland_server.h"
|
||||
#include "workspace.h"
|
||||
#include <KConfigGroup>
|
||||
#include <linux/input.h>
|
||||
|
||||
#define explicit xcb_explicit
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xcbext.h>
|
||||
#include <xcb/xinput.h>
|
||||
#include <xcb/xkb.h>
|
||||
#undef explicit
|
||||
|
||||
using namespace KWin;
|
||||
|
||||
static const QString s_socketName = QStringLiteral("wayland_test_kwin_x11-key-read-0");
|
||||
|
||||
enum class State {
|
||||
Press,
|
||||
Release
|
||||
} state;
|
||||
typedef QPair<State, int> KeyAction;
|
||||
Q_DECLARE_METATYPE(KeyAction);
|
||||
|
||||
/*
|
||||
* This tests the "Legacy App Support" feature of allowing X11 apps to get notified of some key press events
|
||||
*/
|
||||
class X11KeyReadTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private Q_SLOTS:
|
||||
void initTestCase_data();
|
||||
void initTestCase();
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
void testSimpleLetter();
|
||||
void onlyModifier();
|
||||
void letterWithModifier();
|
||||
|
||||
private:
|
||||
QList<KeyAction> recievedX11EventsForInput(const QList<KeyAction> &keyEventsIn);
|
||||
};
|
||||
|
||||
void X11KeyReadTest::initTestCase_data()
|
||||
{
|
||||
QTest::addColumn<XwaylandEavesdropsMode>("operatingMode");
|
||||
QTest::newRow("all") << XwaylandEavesdropsMode::All;
|
||||
QTest::newRow("allWithModifier") << XwaylandEavesdropsMode::AllKeysWithModifier;
|
||||
QTest::newRow("nonCharacter") << XwaylandEavesdropsMode::NonCharacterKeys;
|
||||
QTest::newRow("none") << XwaylandEavesdropsMode::None;
|
||||
}
|
||||
|
||||
void X11KeyReadTest::initTestCase()
|
||||
{
|
||||
QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
|
||||
QVERIFY(waylandServer()->init(s_socketName));
|
||||
Test::setOutputConfig({
|
||||
QRect(0, 0, 1280, 1024),
|
||||
});
|
||||
|
||||
qputenv("KWIN_XKB_DEFAULT_KEYMAP", "1");
|
||||
qputenv("XKB_DEFAULT_RULES", "evdev");
|
||||
|
||||
kwinApp()->start();
|
||||
QVERIFY(applicationStartedSpy.wait());
|
||||
|
||||
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||
}
|
||||
|
||||
void X11KeyReadTest::init()
|
||||
{
|
||||
QFETCH_GLOBAL(XwaylandEavesdropsMode, operatingMode);
|
||||
options->setXwaylandEavesdrops(operatingMode);
|
||||
workspace()->setActiveOutput(QPoint(640, 512));
|
||||
KWin::input()->pointer()->warp(QPoint(640, 512));
|
||||
}
|
||||
|
||||
void X11KeyReadTest::cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
void X11KeyReadTest::testSimpleLetter()
|
||||
{
|
||||
// press a
|
||||
QList<KeyAction> keyEvents = {
|
||||
{State::Press, KEY_A},
|
||||
{State::Release, KEY_A},
|
||||
};
|
||||
auto received = recievedX11EventsForInput(keyEvents);
|
||||
|
||||
QList<KeyAction> expected;
|
||||
QFETCH_GLOBAL(XwaylandEavesdropsMode, operatingMode);
|
||||
switch (operatingMode) {
|
||||
case XwaylandEavesdropsMode::None:
|
||||
case XwaylandEavesdropsMode::NonCharacterKeys:
|
||||
case XwaylandEavesdropsMode::AllKeysWithModifier:
|
||||
expected = {};
|
||||
break;
|
||||
case XwaylandEavesdropsMode::All:
|
||||
expected = keyEvents;
|
||||
break;
|
||||
}
|
||||
|
||||
QCOMPARE(received, expected);
|
||||
}
|
||||
|
||||
void X11KeyReadTest::onlyModifier()
|
||||
{
|
||||
QList<KeyAction> keyEvents = {
|
||||
{State::Press, KEY_LEFTALT},
|
||||
{State::Release, KEY_LEFTALT},
|
||||
};
|
||||
auto received = recievedX11EventsForInput(keyEvents);
|
||||
|
||||
QList<KeyAction> expected;
|
||||
QFETCH_GLOBAL(XwaylandEavesdropsMode, operatingMode);
|
||||
switch (operatingMode) {
|
||||
case XwaylandEavesdropsMode::None:
|
||||
expected = {};
|
||||
break;
|
||||
case XwaylandEavesdropsMode::NonCharacterKeys:
|
||||
case XwaylandEavesdropsMode::AllKeysWithModifier:
|
||||
case XwaylandEavesdropsMode::All:
|
||||
expected = keyEvents;
|
||||
break;
|
||||
}
|
||||
|
||||
QCOMPARE(received, expected);
|
||||
}
|
||||
|
||||
void X11KeyReadTest::letterWithModifier()
|
||||
{
|
||||
QList<KeyAction> keyEvents = {
|
||||
{State::Press, KEY_LEFTALT},
|
||||
{State::Press, KEY_F},
|
||||
{State::Release, KEY_F},
|
||||
{State::Release, KEY_LEFTALT},
|
||||
};
|
||||
auto received = recievedX11EventsForInput(keyEvents);
|
||||
|
||||
QList<KeyAction> expected;
|
||||
QFETCH_GLOBAL(XwaylandEavesdropsMode, operatingMode);
|
||||
switch (operatingMode) {
|
||||
case XwaylandEavesdropsMode::None:
|
||||
expected = {};
|
||||
break;
|
||||
case XwaylandEavesdropsMode::NonCharacterKeys:
|
||||
expected = {
|
||||
{State::Press, KEY_LEFTALT},
|
||||
{State::Release, KEY_LEFTALT},
|
||||
};
|
||||
break;
|
||||
case XwaylandEavesdropsMode::AllKeysWithModifier:
|
||||
case XwaylandEavesdropsMode::All:
|
||||
expected = keyEvents;
|
||||
break;
|
||||
}
|
||||
QCOMPARE(received, expected);
|
||||
}
|
||||
|
||||
class X11EventRecorder :
|
||||
public
|
||||
QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
X11EventRecorder(xcb_connection_t * c);
|
||||
QList<KeyAction> keyEvents() const
|
||||
{
|
||||
return m_keyEvents;
|
||||
}
|
||||
Q_SIGNALS:
|
||||
void fenceReceived();
|
||||
|
||||
private:
|
||||
void processXcbEvents();
|
||||
QList<KeyAction> m_keyEvents;
|
||||
xcb_connection_t *m_connection;
|
||||
QSocketNotifier *m_notifier;
|
||||
};
|
||||
|
||||
X11EventRecorder::X11EventRecorder(xcb_connection_t * c)
|
||||
: QObject()
|
||||
, m_connection(c)
|
||||
, m_notifier(new QSocketNotifier(xcb_get_file_descriptor(m_connection), QSocketNotifier::Read, this))
|
||||
{
|
||||
struct
|
||||
{
|
||||
xcb_input_event_mask_t head;
|
||||
xcb_input_xi_event_mask_t mask;
|
||||
} mask;
|
||||
mask.head.deviceid = XCB_INPUT_DEVICE_ALL;
|
||||
mask.head.mask_len = sizeof(mask.mask) / sizeof(uint32_t);
|
||||
mask.mask = static_cast<xcb_input_xi_event_mask_t>(
|
||||
XCB_INPUT_XI_EVENT_MASK_KEY_PRESS
|
||||
| XCB_INPUT_XI_EVENT_MASK_KEY_RELEASE
|
||||
| XCB_INPUT_RAW_KEY_PRESS
|
||||
| XCB_INPUT_RAW_KEY_RELEASE);
|
||||
|
||||
xcb_input_xi_select_events(c, kwinApp()->x11RootWindow(), 1, &mask.head);
|
||||
xcb_flush(c);
|
||||
|
||||
connect(m_notifier, &QSocketNotifier::activated, this, &X11EventRecorder::processXcbEvents);
|
||||
connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, this, &X11EventRecorder::processXcbEvents);
|
||||
connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::awake, this, &X11EventRecorder::processXcbEvents);
|
||||
}
|
||||
|
||||
void X11EventRecorder::processXcbEvents()
|
||||
{
|
||||
xcb_generic_event_t *event;
|
||||
while ((event = xcb_poll_for_event(m_connection))) {
|
||||
u_int8_t responseType = event->response_type & ~0x80;
|
||||
if (responseType == XCB_GE_GENERIC) {
|
||||
auto *geEvent = reinterpret_cast<xcb_ge_generic_event_t *>(event);
|
||||
if (geEvent->event_type == XCB_INPUT_KEY_PRESS || geEvent->event_type == XCB_INPUT_KEY_RELEASE) {
|
||||
|
||||
auto keyEvent = reinterpret_cast<xcb_input_key_press_event_t *>(geEvent);
|
||||
int nativeKeyCode = keyEvent->detail - 0x08;
|
||||
|
||||
if (nativeKeyCode == 0) {
|
||||
Q_EMIT fenceReceived();
|
||||
} else {
|
||||
KeyAction action({geEvent->event_type == XCB_INPUT_KEY_PRESS ? State::Press : State::Release, nativeKeyCode});
|
||||
m_keyEvents << action;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::free(event);
|
||||
}
|
||||
|
||||
xcb_flush(m_connection);
|
||||
}
|
||||
|
||||
QList<KeyAction> X11KeyReadTest::recievedX11EventsForInput(const QList<KeyAction> &keysIn)
|
||||
{
|
||||
quint32 timestamp = 1;
|
||||
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||
|
||||
X11EventRecorder eventReader(c.get());
|
||||
|
||||
QSignalSpy fenceEventSpy(&eventReader, &X11EventRecorder::fenceReceived);
|
||||
|
||||
for (const KeyAction &action : keysIn) {
|
||||
if (action.first == State::Press) {
|
||||
Test::keyboardKeyPressed(action.second, timestamp++);
|
||||
} else {
|
||||
Test::keyboardKeyReleased(action.second, timestamp++);
|
||||
}
|
||||
Test::flushWaylandConnection();
|
||||
QTest::qWait(5);
|
||||
}
|
||||
// special case, explicitly send key 0, to use as a fence
|
||||
ClientConnection *xwaylandClient = waylandServer()->xWaylandConnection();
|
||||
waylandServer()->seat()->keyboard()->sendKey(0, KeyboardKeyState::Pressed, xwaylandClient);
|
||||
|
||||
Test::flushWaylandConnection();
|
||||
|
||||
bool fenceComplete = fenceEventSpy.wait();
|
||||
Q_ASSERT(fenceComplete);
|
||||
|
||||
return eventReader.keyEvents();
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(X11KeyReadTest)
|
||||
#include "x11keyread.moc"
|
|
@ -151,6 +151,14 @@ private Q_SLOTS:
|
|||
void testScreenApplyNow();
|
||||
void testScreenForceTemporarily();
|
||||
|
||||
void testLayerDontAffect();
|
||||
void testLayerForce();
|
||||
void testLayerForceTemporarily();
|
||||
|
||||
void testCloseableDontAffect();
|
||||
void testCloseableForce();
|
||||
void testCloseableForceTemporarily();
|
||||
|
||||
void testMatchAfterNameChange();
|
||||
|
||||
private:
|
||||
|
@ -167,6 +175,7 @@ private:
|
|||
Window *m_window;
|
||||
std::unique_ptr<KWayland::Client::Surface> m_surface;
|
||||
std::unique_ptr<Test::XdgToplevel> m_shellSurface;
|
||||
std::unique_ptr<Test::XdgToplevelDecorationV1> m_decoration;
|
||||
|
||||
std::unique_ptr<QSignalSpy> m_toplevelConfigureRequestedSpy;
|
||||
std::unique_ptr<QSignalSpy> m_surfaceConfigureRequestedSpy;
|
||||
|
@ -229,15 +238,15 @@ void TestXdgShellWindowRules::createTestWindow(ClientFlags flags)
|
|||
: Test::XdgToplevelDecorationV1::mode_client_side;
|
||||
// Create an xdg surface.
|
||||
m_surface = Test::createSurface();
|
||||
m_shellSurface.reset(Test::createXdgToplevelSurface(m_surface.get(), Test::CreationSetup::CreateOnly, m_surface.get()));
|
||||
Test::XdgToplevelDecorationV1 *decoration = Test::createXdgToplevelDecorationV1(m_shellSurface.get(), m_shellSurface.get());
|
||||
m_shellSurface = Test::createXdgToplevelSurface(m_surface.get(), Test::CreationSetup::CreateOnly);
|
||||
m_decoration = Test::createXdgToplevelDecorationV1(m_shellSurface.get());
|
||||
|
||||
// Add signal watchers
|
||||
m_toplevelConfigureRequestedSpy = std::make_unique<QSignalSpy>(m_shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
m_surfaceConfigureRequestedSpy = std::make_unique<QSignalSpy>(m_shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
|
||||
m_shellSurface->set_app_id(QStringLiteral("org.kde.foo"));
|
||||
decoration->set_mode(decorationMode);
|
||||
m_decoration->set_mode(decorationMode);
|
||||
|
||||
// Wait for the initial configure event
|
||||
m_surface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
|
@ -269,6 +278,7 @@ void TestXdgShellWindowRules::destroyTestWindow()
|
|||
{
|
||||
m_surfaceConfigureRequestedSpy.reset();
|
||||
m_toplevelConfigureRequestedSpy.reset();
|
||||
m_decoration.reset();
|
||||
m_shellSurface.reset();
|
||||
m_surface.reset();
|
||||
QVERIFY(Test::waitForWindowClosed(m_window));
|
||||
|
@ -2821,7 +2831,7 @@ void TestXdgShellWindowRules::testScreenDontAffect()
|
|||
QCOMPARE(m_window->output()->name(), outputs.at(0)->name());
|
||||
|
||||
// The user can still move the window to another screen.
|
||||
workspace()->sendWindowToOutput(m_window, outputs.at(1));
|
||||
m_window->sendToOutput(outputs.at(1));
|
||||
QCOMPARE(m_window->output()->name(), outputs.at(1)->name());
|
||||
|
||||
destroyTestWindow();
|
||||
|
@ -2840,7 +2850,7 @@ void TestXdgShellWindowRules::testScreenApply()
|
|||
QCOMPARE(m_window->output()->name(), outputs.at(1)->name());
|
||||
|
||||
// The user can move the window to another screen.
|
||||
workspace()->sendWindowToOutput(m_window, outputs.at(0));
|
||||
m_window->sendToOutput(outputs.at(0));
|
||||
QCOMPARE(m_window->output()->name(), outputs.at(0)->name());
|
||||
|
||||
destroyTestWindow();
|
||||
|
@ -2858,11 +2868,12 @@ void TestXdgShellWindowRules::testScreenRemember()
|
|||
QCOMPARE(m_window->output()->name(), outputs.at(0)->name());
|
||||
|
||||
// Move the window to the second screen.
|
||||
workspace()->sendWindowToOutput(m_window, outputs.at(1));
|
||||
m_window->sendToOutput(outputs.at(1));
|
||||
QCOMPARE(m_window->output()->name(), outputs.at(1)->name());
|
||||
|
||||
// Close and reopen the window.
|
||||
destroyTestWindow();
|
||||
workspace()->setActiveOutput(outputs.at(0));
|
||||
createTestWindow();
|
||||
|
||||
QEXPECT_FAIL("", "Applying a screen rule on a new client fails on Wayland", Continue);
|
||||
|
@ -2884,7 +2895,7 @@ void TestXdgShellWindowRules::testScreenForce()
|
|||
QCOMPARE(m_window->output()->name(), outputs.at(1)->name());
|
||||
|
||||
// User should not be able to move the window to another screen.
|
||||
workspace()->sendWindowToOutput(m_window, outputs.at(0));
|
||||
m_window->sendToOutput(outputs.at(0));
|
||||
QCOMPARE(m_window->output()->name(), outputs.at(1)->name());
|
||||
|
||||
// Disable the output where the window is on, so the window is moved the other screen
|
||||
|
@ -2926,7 +2937,7 @@ void TestXdgShellWindowRules::testScreenApplyNow()
|
|||
QCOMPARE(m_window->output()->name(), outputs.at(1)->name());
|
||||
|
||||
// The user can move the window to another screen.
|
||||
workspace()->sendWindowToOutput(m_window, outputs.at(0));
|
||||
m_window->sendToOutput(outputs.at(0));
|
||||
QCOMPARE(m_window->output()->name(), outputs.at(0)->name());
|
||||
|
||||
// The rule should not be applied again.
|
||||
|
@ -2948,11 +2959,12 @@ void TestXdgShellWindowRules::testScreenForceTemporarily()
|
|||
QCOMPARE(m_window->output()->name(), outputs.at(1)->name());
|
||||
|
||||
// User is not allowed to move it
|
||||
workspace()->sendWindowToOutput(m_window, outputs.at(0));
|
||||
m_window->sendToOutput(outputs.at(0));
|
||||
QCOMPARE(m_window->output()->name(), outputs.at(1)->name());
|
||||
|
||||
// Close and reopen the window.
|
||||
destroyTestWindow();
|
||||
workspace()->setActiveOutput(outputs.at(0));
|
||||
createTestWindow();
|
||||
|
||||
// The rule should be discarded now
|
||||
|
@ -2980,5 +2992,78 @@ void TestXdgShellWindowRules::testMatchAfterNameChange()
|
|||
QCOMPARE(window->keepAbove(), true);
|
||||
}
|
||||
|
||||
void TestXdgShellWindowRules::testLayerDontAffect()
|
||||
{
|
||||
setWindowRule("layer", QStringLiteral("overlay"), int(Rules::DontAffect));
|
||||
|
||||
createTestWindow();
|
||||
|
||||
// The layer should not be affected by the rule.
|
||||
QCOMPARE(m_window->layer(), NormalLayer);
|
||||
|
||||
destroyTestWindow();
|
||||
}
|
||||
|
||||
void TestXdgShellWindowRules::testLayerForce()
|
||||
{
|
||||
setWindowRule("layer", QStringLiteral("overlay"), int(Rules::Force));
|
||||
|
||||
createTestWindow();
|
||||
QCOMPARE(m_window->layer(), OverlayLayer);
|
||||
|
||||
destroyTestWindow();
|
||||
}
|
||||
|
||||
void TestXdgShellWindowRules::testLayerForceTemporarily()
|
||||
{
|
||||
setWindowRule("layer", QStringLiteral("overlay"), int(Rules::ForceTemporarily));
|
||||
|
||||
createTestWindow();
|
||||
QCOMPARE(m_window->layer(), OverlayLayer);
|
||||
|
||||
// The rule should be discarded when the window is closed.
|
||||
destroyTestWindow();
|
||||
createTestWindow();
|
||||
QCOMPARE(m_window->layer(), NormalLayer);
|
||||
|
||||
destroyTestWindow();
|
||||
}
|
||||
|
||||
void TestXdgShellWindowRules::testCloseableDontAffect()
|
||||
{
|
||||
setWindowRule("closeable", false, int(Rules::DontAffect));
|
||||
|
||||
createTestWindow();
|
||||
|
||||
QVERIFY(m_window->isCloseable());
|
||||
|
||||
destroyTestWindow();
|
||||
}
|
||||
|
||||
void TestXdgShellWindowRules::testCloseableForce()
|
||||
{
|
||||
setWindowRule("closeable", false, int(Rules::Force));
|
||||
|
||||
createTestWindow();
|
||||
QVERIFY(!m_window->isCloseable());
|
||||
|
||||
destroyTestWindow();
|
||||
}
|
||||
|
||||
void TestXdgShellWindowRules::testCloseableForceTemporarily()
|
||||
{
|
||||
setWindowRule("closeable", false, int(Rules::ForceTemporarily));
|
||||
|
||||
createTestWindow();
|
||||
QVERIFY(!m_window->isCloseable());
|
||||
|
||||
// The rule should be discarded when the window is closed.
|
||||
destroyTestWindow();
|
||||
createTestWindow();
|
||||
QVERIFY(m_window->isCloseable());
|
||||
|
||||
destroyTestWindow();
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(TestXdgShellWindowRules)
|
||||
#include "xdgshellwindow_rules_test.moc"
|
||||
|
|
|
@ -68,11 +68,14 @@ private Q_SLOTS:
|
|||
void testMaximizedToFullscreen_data();
|
||||
void testMaximizedToFullscreen();
|
||||
void testSendMaximizedWindowToAnotherOutput();
|
||||
void testInteractiveMoveUnmaximizeFull();
|
||||
void testInteractiveMoveUnmaximizeInitiallyFull();
|
||||
void testInteractiveMoveUnmaximizeHorizontal();
|
||||
void testInteractiveMoveUnmaximizeVertical();
|
||||
void testFullscreenMultipleOutputs();
|
||||
void testHidden();
|
||||
void testDesktopFileName();
|
||||
void testCaptionSimplified();
|
||||
void testCaptionMultipleWindows();
|
||||
void testUnresponsiveWindow_data();
|
||||
void testUnresponsiveWindow();
|
||||
void testAppMenu();
|
||||
|
@ -101,6 +104,9 @@ private Q_SLOTS:
|
|||
void testMaximizeAndChangeDecorationModeAfterInitialCommit();
|
||||
void testFullScreenAndChangeDecorationModeAfterInitialCommit();
|
||||
void testChangeDecorationModeAfterInitialCommit();
|
||||
void testModal();
|
||||
void testCloseModal();
|
||||
void testCloseInactiveModal();
|
||||
};
|
||||
|
||||
void TestXdgShellWindow::testXdgPopupReactive_data()
|
||||
|
@ -203,7 +209,7 @@ void TestXdgShellWindow::initTestCase()
|
|||
|
||||
void TestXdgShellWindow::init()
|
||||
{
|
||||
QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::Seat | Test::AdditionalWaylandInterface::XdgDecorationV1 | Test::AdditionalWaylandInterface::AppMenu));
|
||||
QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::Seat | Test::AdditionalWaylandInterface::XdgDecorationV1 | Test::AdditionalWaylandInterface::AppMenu | Test::AdditionalWaylandInterface::XdgDialogV1));
|
||||
QVERIFY(Test::waitForWaylandPointer());
|
||||
|
||||
workspace()->setActiveOutput(QPoint(640, 512));
|
||||
|
@ -475,7 +481,7 @@ void TestXdgShellWindow::testSendFullScreenWindowToAnotherOutput()
|
|||
QCOMPARE(window->output(), outputs[0]);
|
||||
|
||||
// Send the window to another output.
|
||||
workspace()->sendWindowToOutput(window, outputs[1]);
|
||||
window->sendToOutput(outputs[1]);
|
||||
QCOMPARE(window->isFullScreen(), true);
|
||||
QCOMPARE(window->frameGeometry(), QRectF(1280, 0, 1280, 1024));
|
||||
QCOMPARE(window->fullscreenGeometryRestore(), QRectF(1280 + 10, 20, 100, 50));
|
||||
|
@ -708,52 +714,6 @@ void TestXdgShellWindow::testCaptionSimplified()
|
|||
QCOMPARE(window->caption(), origTitle.simplified());
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testCaptionMultipleWindows()
|
||||
{
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
shellSurface->set_title(QStringLiteral("foo"));
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(window);
|
||||
QCOMPARE(window->caption(), QStringLiteral("foo"));
|
||||
QCOMPARE(window->captionNormal(), QStringLiteral("foo"));
|
||||
QCOMPARE(window->captionSuffix(), QString());
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
|
||||
shellSurface2->set_title(QStringLiteral("foo"));
|
||||
auto c2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(c2);
|
||||
QCOMPARE(c2->caption(), QStringLiteral("foo <2>"));
|
||||
QCOMPARE(c2->captionNormal(), QStringLiteral("foo"));
|
||||
QCOMPARE(c2->captionSuffix(), QStringLiteral(" <2>"));
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface3(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface3(Test::createXdgToplevelSurface(surface3.get()));
|
||||
shellSurface3->set_title(QStringLiteral("foo"));
|
||||
auto c3 = Test::renderAndWaitForShown(surface3.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(c3);
|
||||
QCOMPARE(c3->caption(), QStringLiteral("foo <3>"));
|
||||
QCOMPARE(c3->captionNormal(), QStringLiteral("foo"));
|
||||
QCOMPARE(c3->captionSuffix(), QStringLiteral(" <3>"));
|
||||
|
||||
std::unique_ptr<KWayland::Client::Surface> surface4(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface4(Test::createXdgToplevelSurface(surface4.get()));
|
||||
shellSurface4->set_title(QStringLiteral("bar"));
|
||||
auto c4 = Test::renderAndWaitForShown(surface4.get(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(c4);
|
||||
QCOMPARE(c4->caption(), QStringLiteral("bar"));
|
||||
QCOMPARE(c4->captionNormal(), QStringLiteral("bar"));
|
||||
QCOMPARE(c4->captionSuffix(), QString());
|
||||
QSignalSpy captionChangedSpy(c4, &Window::captionChanged);
|
||||
shellSurface4->set_title(QStringLiteral("foo"));
|
||||
QVERIFY(captionChangedSpy.wait());
|
||||
QCOMPARE(captionChangedSpy.count(), 1);
|
||||
QCOMPARE(c4->caption(), QStringLiteral("foo <4>"));
|
||||
QCOMPARE(c4->captionNormal(), QStringLiteral("foo"));
|
||||
QCOMPARE(c4->captionSuffix(), QStringLiteral(" <4>"));
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testUnresponsiveWindow_data()
|
||||
{
|
||||
QTest::addColumn<QString>("shellInterface"); // see env selection in qwaylandintegration.cpp
|
||||
|
@ -1835,13 +1795,321 @@ void TestXdgShellWindow::testSendMaximizedWindowToAnotherOutput()
|
|||
QCOMPARE(window->output(), outputs[0]);
|
||||
|
||||
// Send the window to another output.
|
||||
workspace()->sendWindowToOutput(window, outputs[1]);
|
||||
window->sendToOutput(outputs[1]);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->frameGeometry(), QRectF(1280, 0, 1280, 1024));
|
||||
QCOMPARE(window->geometryRestore(), QRectF(1280 + 10, 20, 100, 50));
|
||||
QCOMPARE(window->output(), outputs[1]);
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testInteractiveMoveUnmaximizeFull()
|
||||
{
|
||||
// This test verifies that a maximized xdg-toplevel is going to be properly unmaximized when it's dragged.
|
||||
|
||||
// Create the window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
// Wait for the compositor to send a configure event with the activated state.
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
||||
// Make the window maximized.
|
||||
const QRectF originalGeometry = window->frameGeometry();
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
window->maximize(MaximizeFull);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeFull);
|
||||
|
||||
// Start interactive move.
|
||||
QSignalSpy interactiveMoveResizeStartedSpy(window, &Window::interactiveMoveResizeStarted);
|
||||
QSignalSpy interactiveMoveResizeSteppedSpy(window, &Window::interactiveMoveResizeStepped);
|
||||
QSignalSpy interactiveMoveResizeFinishedSpy(window, &Window::interactiveMoveResizeFinished);
|
||||
const qreal xOffset = 0.25;
|
||||
const qreal yOffset = 0.5;
|
||||
quint32 timestamp = 0;
|
||||
Test::pointerMotion(QPointF(window->x() + window->width() * xOffset, window->y() + window->height() * yOffset), timestamp++);
|
||||
window->performMouseCommand(Options::MouseMove, input()->pointer()->pos());
|
||||
QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeFull);
|
||||
|
||||
// Move the window to unmaximize it.
|
||||
const QRectF maximizedGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(0, 100), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry);
|
||||
|
||||
// Move the window a tiny bit more.
|
||||
Test::pointerMotionRelative(QPointF(0, 10), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry);
|
||||
|
||||
// Render the window at the new size.
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), QRectF(input()->pointer()->pos() - QPointF(originalGeometry.width() * xOffset, originalGeometry.height() * yOffset), originalGeometry.size()));
|
||||
|
||||
// Move the window again.
|
||||
const QRectF normalGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(0, 10), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), normalGeometry.translated(0, 10));
|
||||
|
||||
// Finish interactive move.
|
||||
window->keyPressEvent(Qt::Key_Enter);
|
||||
QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testInteractiveMoveUnmaximizeInitiallyFull()
|
||||
{
|
||||
// This test verifies that an initially maximized xdg-toplevel will be properly unmaximized when it's dragged.
|
||||
|
||||
// Create the window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get(), [](Test::XdgToplevel *toplevel) {
|
||||
toplevel->set_maximized();
|
||||
}));
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
// Wait for the compositor to send a configure event with the activated state.
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
||||
// Start interactive move.
|
||||
QSignalSpy interactiveMoveResizeStartedSpy(window, &Window::interactiveMoveResizeStarted);
|
||||
QSignalSpy interactiveMoveResizeSteppedSpy(window, &Window::interactiveMoveResizeStepped);
|
||||
QSignalSpy interactiveMoveResizeFinishedSpy(window, &Window::interactiveMoveResizeFinished);
|
||||
const qreal xOffset = 0.25;
|
||||
const qreal yOffset = 0.5;
|
||||
quint32 timestamp = 0;
|
||||
Test::pointerMotion(QPointF(window->x() + window->width() * xOffset, window->y() + window->height() * yOffset), timestamp++);
|
||||
window->performMouseCommand(Options::MouseMove, input()->pointer()->pos());
|
||||
QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeFull);
|
||||
|
||||
// Move the window to unmaximize it.
|
||||
const QRectF maximizedGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(0, 100), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry);
|
||||
|
||||
// Move the window a tiny bit more.
|
||||
Test::pointerMotionRelative(QPointF(0, 10), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry);
|
||||
|
||||
// Render the window at the new size.
|
||||
const QSize restoredSize(100, 50);
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), QSize(0, 0));
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), restoredSize, Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), QRectF(input()->pointer()->pos() - QPointF(restoredSize.width() * xOffset, restoredSize.height() * yOffset), restoredSize));
|
||||
|
||||
// Move the window again.
|
||||
const QRectF normalGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(0, 10), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), normalGeometry.translated(0, 10));
|
||||
|
||||
// Finish interactive move.
|
||||
window->keyPressEvent(Qt::Key_Enter);
|
||||
QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testInteractiveMoveUnmaximizeHorizontal()
|
||||
{
|
||||
// This test verifies that a maximized horizontally xdg-toplevel is going to be properly unmaximized when it's dragged horizontally.
|
||||
|
||||
// Create the window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
// Wait for the compositor to send a configure event with the activated state.
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
||||
// Make the window maximized.
|
||||
const QRectF originalGeometry = window->frameGeometry();
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
window->maximize(MaximizeHorizontal);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->maximizeMode(), MaximizeHorizontal);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeHorizontal);
|
||||
|
||||
// Start interactive move.
|
||||
QSignalSpy interactiveMoveResizeStartedSpy(window, &Window::interactiveMoveResizeStarted);
|
||||
QSignalSpy interactiveMoveResizeSteppedSpy(window, &Window::interactiveMoveResizeStepped);
|
||||
QSignalSpy interactiveMoveResizeFinishedSpy(window, &Window::interactiveMoveResizeFinished);
|
||||
const qreal xOffset = 0.25;
|
||||
const qreal yOffset = 0.5;
|
||||
quint32 timestamp = 0;
|
||||
Test::pointerMotion(QPointF(window->x() + window->width() * xOffset, window->y() + window->height() * yOffset), timestamp++);
|
||||
window->performMouseCommand(Options::MouseMove, input()->pointer()->pos());
|
||||
QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeHorizontal);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeHorizontal);
|
||||
|
||||
// Move the window vertically, it's not going to be unmaximized.
|
||||
const QRectF maximizedGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(0, 100), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeHorizontal);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeHorizontal);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry.translated(0, 100));
|
||||
|
||||
// Move the window horizontally.
|
||||
Test::pointerMotionRelative(QPointF(100, 0), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeHorizontal);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry.translated(0, 100));
|
||||
|
||||
// Move the window to the right a bit more.
|
||||
Test::pointerMotionRelative(QPointF(10, 0), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeHorizontal);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry.translated(0, 100));
|
||||
|
||||
// Render the window at the new size.
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), QRectF(input()->pointer()->pos() - QPointF(originalGeometry.width() * xOffset, originalGeometry.height() * yOffset), originalGeometry.size()));
|
||||
|
||||
// Move the window again.
|
||||
const QRectF normalGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(10, 0), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 2);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), normalGeometry.translated(10, 0));
|
||||
|
||||
// Finish interactive move.
|
||||
window->keyPressEvent(Qt::Key_Enter);
|
||||
QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testInteractiveMoveUnmaximizeVertical()
|
||||
{
|
||||
// This test verifies that a maximized vertically xdg-toplevel is going to be properly unmaximized when it's dragged vertically.
|
||||
|
||||
// Create the window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
// Wait for the compositor to send a configure event with the activated state.
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
||||
// Make the window maximized.
|
||||
const QRectF originalGeometry = window->frameGeometry();
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
window->maximize(MaximizeVertical);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->maximizeMode(), MaximizeVertical);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeVertical);
|
||||
|
||||
// Start interactive move.
|
||||
QSignalSpy interactiveMoveResizeStartedSpy(window, &Window::interactiveMoveResizeStarted);
|
||||
QSignalSpy interactiveMoveResizeSteppedSpy(window, &Window::interactiveMoveResizeStepped);
|
||||
QSignalSpy interactiveMoveResizeFinishedSpy(window, &Window::interactiveMoveResizeFinished);
|
||||
const qreal xOffset = 0.25;
|
||||
const qreal yOffset = 0.5;
|
||||
quint32 timestamp = 0;
|
||||
Test::pointerMotion(QPointF(window->x() + window->width() * xOffset, window->y() + window->height() * yOffset), timestamp++);
|
||||
window->performMouseCommand(Options::MouseMove, input()->pointer()->pos());
|
||||
QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeVertical);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeVertical);
|
||||
|
||||
// Move the window to the right, it's not going to be unmaximized.
|
||||
const QRectF maximizedGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(100, 0), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeVertical);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeVertical);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry.translated(100, 0));
|
||||
|
||||
// Move the window vertically.
|
||||
Test::pointerMotionRelative(QPointF(0, 100), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeVertical);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry.translated(100, 0));
|
||||
|
||||
// Move the window down a bit more.
|
||||
Test::pointerMotionRelative(QPointF(0, 10), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeVertical);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry.translated(100, 0));
|
||||
|
||||
// Render the window at the new size.
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), QRectF(input()->pointer()->pos() - QPointF(originalGeometry.width() * xOffset, originalGeometry.height() * yOffset), originalGeometry.size()));
|
||||
|
||||
// Move the window again.
|
||||
const QRectF normalGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(0, 10), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 2);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), normalGeometry.translated(0, 10));
|
||||
|
||||
// Finish interactive move.
|
||||
window->keyPressEvent(Qt::Key_Enter);
|
||||
QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testMaximizeAndChangeDecorationModeAfterInitialCommit()
|
||||
{
|
||||
// Ideally, the app would initialize the xdg-toplevel surface before the initial commit, but
|
||||
|
@ -1925,5 +2193,134 @@ void TestXdgShellWindow::testChangeDecorationModeAfterInitialCommit()
|
|||
QCOMPARE(decorationConfigureRequestedSpy.last().at(0).value<Test::XdgToplevelDecorationV1::mode>(), Test::XdgToplevelDecorationV1::mode_client_side);
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testModal()
|
||||
{
|
||||
auto parentSurface = Test::createSurface();
|
||||
auto parentToplevel = Test::createXdgToplevelSurface(parentSurface.get());
|
||||
auto parentWindow = Test::renderAndWaitForShown(parentSurface.get(), {200, 200}, Qt::cyan);
|
||||
QVERIFY(parentWindow);
|
||||
|
||||
auto childSurface = Test::createSurface();
|
||||
auto childToplevel = Test::createXdgToplevelSurface(childSurface.get(), [&parentToplevel](Test::XdgToplevel *toplevel) {
|
||||
toplevel->set_parent(parentToplevel->object());
|
||||
});
|
||||
auto childWindow = Test::renderAndWaitForShown(childSurface.get(), {200, 200}, Qt::yellow);
|
||||
QVERIFY(childWindow);
|
||||
QVERIFY(!childWindow->isModal());
|
||||
QCOMPARE(childWindow->transientFor(), parentWindow);
|
||||
|
||||
auto dialog = Test::createXdgDialogV1(childToplevel.get());
|
||||
QVERIFY(Test::waylandSync());
|
||||
QVERIFY(dialog);
|
||||
QVERIFY(!childWindow->isModal());
|
||||
|
||||
QSignalSpy modalChangedSpy(childWindow, &Window::modalChanged);
|
||||
|
||||
dialog->set_modal();
|
||||
Test::flushWaylandConnection();
|
||||
QVERIFY(modalChangedSpy.wait());
|
||||
QVERIFY(childWindow->isModal());
|
||||
|
||||
dialog->unset_modal();
|
||||
Test::flushWaylandConnection();
|
||||
QVERIFY(modalChangedSpy.wait());
|
||||
QVERIFY(!childWindow->isModal());
|
||||
|
||||
dialog->set_modal();
|
||||
Test::flushWaylandConnection();
|
||||
QVERIFY(modalChangedSpy.wait());
|
||||
Workspace::self()->activateWindow(parentWindow);
|
||||
QCOMPARE(Workspace::self()->activeWindow(), childWindow);
|
||||
|
||||
dialog.reset();
|
||||
Test::flushWaylandConnection();
|
||||
QVERIFY(modalChangedSpy.wait());
|
||||
QVERIFY(!childWindow->isModal());
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testCloseModal()
|
||||
{
|
||||
// This test verifies that the parent window will be activated when an active modal dialog is closed.
|
||||
|
||||
// Create a parent and a child windows.
|
||||
auto parentSurface = Test::createSurface();
|
||||
auto parentToplevel = Test::createXdgToplevelSurface(parentSurface.get());
|
||||
auto parent = Test::renderAndWaitForShown(parentSurface.get(), {200, 200}, Qt::cyan);
|
||||
QVERIFY(parent);
|
||||
|
||||
auto childSurface = Test::createSurface();
|
||||
auto childToplevel = Test::createXdgToplevelSurface(childSurface.get(), [&parentToplevel](Test::XdgToplevel *toplevel) {
|
||||
toplevel->set_parent(parentToplevel->object());
|
||||
});
|
||||
auto child = Test::renderAndWaitForShown(childSurface.get(), {200, 200}, Qt::yellow);
|
||||
QVERIFY(child);
|
||||
QVERIFY(!child->isModal());
|
||||
QCOMPARE(child->transientFor(), parent);
|
||||
|
||||
// Set modal state.
|
||||
auto dialog = Test::createXdgDialogV1(childToplevel.get());
|
||||
QSignalSpy modalChangedSpy(child, &Window::modalChanged);
|
||||
dialog->set_modal();
|
||||
Test::flushWaylandConnection();
|
||||
QVERIFY(modalChangedSpy.wait());
|
||||
QVERIFY(child->isModal());
|
||||
QCOMPARE(workspace()->activeWindow(), child);
|
||||
|
||||
// Close the child.
|
||||
QSignalSpy childClosedSpy(child, &Window::closed);
|
||||
childToplevel.reset();
|
||||
childSurface.reset();
|
||||
dialog.reset();
|
||||
Test::flushWaylandConnection();
|
||||
QVERIFY(childClosedSpy.wait());
|
||||
QCOMPARE(workspace()->activeWindow(), parent);
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testCloseInactiveModal()
|
||||
{
|
||||
// This test verifies that the parent window will not be activated when an inactive modal dialog is closed.
|
||||
|
||||
// Create a parent and a child windows.
|
||||
auto parentSurface = Test::createSurface();
|
||||
auto parentToplevel = Test::createXdgToplevelSurface(parentSurface.get());
|
||||
auto parent = Test::renderAndWaitForShown(parentSurface.get(), {200, 200}, Qt::cyan);
|
||||
QVERIFY(parent);
|
||||
|
||||
auto childSurface = Test::createSurface();
|
||||
auto childToplevel = Test::createXdgToplevelSurface(childSurface.get(), [&parentToplevel](Test::XdgToplevel *toplevel) {
|
||||
toplevel->set_parent(parentToplevel->object());
|
||||
});
|
||||
auto child = Test::renderAndWaitForShown(childSurface.get(), {200, 200}, Qt::yellow);
|
||||
QVERIFY(child);
|
||||
QVERIFY(!child->isModal());
|
||||
QCOMPARE(child->transientFor(), parent);
|
||||
|
||||
// Set modal state.
|
||||
auto dialog = Test::createXdgDialogV1(childToplevel.get());
|
||||
QSignalSpy modalChangedSpy(child, &Window::modalChanged);
|
||||
dialog->set_modal();
|
||||
Test::flushWaylandConnection();
|
||||
QVERIFY(modalChangedSpy.wait());
|
||||
QVERIFY(child->isModal());
|
||||
QCOMPARE(workspace()->activeWindow(), child);
|
||||
|
||||
// Show another window.
|
||||
auto otherSurface = Test::createSurface();
|
||||
auto otherToplevel = Test::createXdgToplevelSurface(otherSurface.get());
|
||||
auto otherWindow = Test::renderAndWaitForShown(otherSurface.get(), {200, 200}, Qt::magenta);
|
||||
QVERIFY(otherWindow);
|
||||
workspace()->setActiveWindow(otherWindow);
|
||||
QCOMPARE(workspace()->activeWindow(), otherWindow);
|
||||
|
||||
// Close the child.
|
||||
QSignalSpy childClosedSpy(child, &Window::closed);
|
||||
childToplevel.reset();
|
||||
childSurface.reset();
|
||||
dialog.reset();
|
||||
Test::flushWaylandConnection();
|
||||
QVERIFY(childClosedSpy.wait());
|
||||
QCOMPARE(workspace()->activeWindow(), otherWindow);
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(TestXdgShellWindow)
|
||||
#include "xdgshellwindow_test.moc"
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2024 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "kwin_wayland_test.h"
|
||||
|
||||
#include "core/output.h"
|
||||
#include "wayland_server.h"
|
||||
#include "workspace.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
static const QString s_socketName = QStringLiteral("wayland_test_kwin_xinerama-0");
|
||||
|
||||
class XineramaTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void indexToOutput();
|
||||
};
|
||||
|
||||
void XineramaTest::initTestCase()
|
||||
{
|
||||
QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
|
||||
QVERIFY(waylandServer()->init(s_socketName));
|
||||
kwinApp()->start();
|
||||
QVERIFY(applicationStartedSpy.wait());
|
||||
}
|
||||
|
||||
void XineramaTest::indexToOutput()
|
||||
{
|
||||
Test::setOutputConfig({
|
||||
Test::OutputInfo{
|
||||
.geometry = QRect(0, 0, 1280, 1024),
|
||||
.scale = 1.5,
|
||||
},
|
||||
Test::OutputInfo{
|
||||
.geometry = QRect(1280, 0, 1280, 1024),
|
||||
.scale = 1.5,
|
||||
},
|
||||
});
|
||||
kwinApp()->setXwaylandScale(1.5);
|
||||
|
||||
// Start Xwayland
|
||||
Test::XcbConnectionPtr c = Test::createX11Connection();
|
||||
QVERIFY(!xcb_connection_has_error(c.get()));
|
||||
|
||||
const auto outputs = workspace()->outputs();
|
||||
QCOMPARE(workspace()->xineramaIndexToOutput(0), outputs.at(0));
|
||||
QCOMPARE(workspace()->xineramaIndexToOutput(1), outputs.at(1));
|
||||
|
||||
workspace()->setOutputOrder({outputs[1], outputs[0]});
|
||||
QCOMPARE(workspace()->xineramaIndexToOutput(0), outputs.at(1));
|
||||
QCOMPARE(workspace()->xineramaIndexToOutput(1), outputs.at(0));
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
||||
WAYLANDTEST_MAIN(KWin::XineramaTest)
|
||||
#include "xinerama_test.moc"
|
|
@ -53,7 +53,7 @@ void InputEventsTest::testInitMouseEvent()
|
|||
QFETCH(QEvent::Type, type);
|
||||
// now create our own event
|
||||
MouseEvent event(type, QPointF(100, 200), Qt::LeftButton, Qt::LeftButton | Qt::RightButton,
|
||||
Qt::ShiftModifier | Qt::ControlModifier, 300ms, QPointF(1, 2), QPointF(3, 4), &d);
|
||||
Qt::ShiftModifier | Qt::ControlModifier, 300ms, QPointF(1, 2), QPointF(3, 4), &d, false);
|
||||
// and verify the contract of QMouseEvent
|
||||
QCOMPARE(event.type(), type);
|
||||
QCOMPARE(event.globalPos(), QPoint(100, 200));
|
||||
|
|
|
@ -20,6 +20,7 @@ public:
|
|||
private Q_SLOTS:
|
||||
void roundtripConversion_data();
|
||||
void roundtripConversion();
|
||||
void nonNormalizedPrimaries();
|
||||
};
|
||||
|
||||
static bool compareVectors(const QVector3D &one, const QVector3D &two, float maxDifference)
|
||||
|
@ -33,6 +34,8 @@ static bool compareVectors(const QVector3D &one, const QVector3D &two, float max
|
|||
return ret;
|
||||
}
|
||||
|
||||
static const double s_resolution10bit = std::pow(1.0 / 2.0, 10);
|
||||
|
||||
void TestColorspaces::roundtripConversion_data()
|
||||
{
|
||||
QTest::addColumn<NamedColorimetry>("srcColorimetry");
|
||||
|
@ -41,12 +44,11 @@ void TestColorspaces::roundtripConversion_data()
|
|||
QTest::addColumn<NamedTransferFunction>("dstTransferFunction");
|
||||
QTest::addColumn<double>("requiredAccuracy");
|
||||
|
||||
const double resolution10bit = std::pow(1.0 / 2.0, 10);
|
||||
QTest::addRow("BT709 (sRGB) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::sRGB << NamedColorimetry::BT2020 << NamedTransferFunction::linear << resolution10bit;
|
||||
QTest::addRow("BT709 (gamma 2.2) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::gamma22 << NamedColorimetry::BT2020 << NamedTransferFunction::linear << resolution10bit;
|
||||
QTest::addRow("BT709 (scRGB) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::scRGB << NamedColorimetry::BT2020 << NamedTransferFunction::linear << resolution10bit;
|
||||
QTest::addRow("BT709 (linear) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::linear << NamedColorimetry::BT2020 << NamedTransferFunction::linear << resolution10bit;
|
||||
QTest::addRow("BT709 (PQ) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::PerceptualQuantizer << NamedColorimetry::BT2020 << NamedTransferFunction::linear << 3 * resolution10bit;
|
||||
QTest::addRow("BT709 (sRGB) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::sRGB << NamedColorimetry::BT2020 << NamedTransferFunction::linear << s_resolution10bit;
|
||||
QTest::addRow("BT709 (gamma 2.2) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::gamma22 << NamedColorimetry::BT2020 << NamedTransferFunction::linear << s_resolution10bit;
|
||||
QTest::addRow("BT709 (scRGB) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::scRGB << NamedColorimetry::BT2020 << NamedTransferFunction::linear << s_resolution10bit;
|
||||
QTest::addRow("BT709 (linear) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::linear << NamedColorimetry::BT2020 << NamedTransferFunction::linear << s_resolution10bit;
|
||||
QTest::addRow("BT709 (PQ) <-> BT2020 (linear)") << NamedColorimetry::BT709 << NamedTransferFunction::PerceptualQuantizer << NamedColorimetry::BT2020 << NamedTransferFunction::linear << 3 * s_resolution10bit;
|
||||
}
|
||||
|
||||
void TestColorspaces::roundtripConversion()
|
||||
|
@ -57,8 +59,8 @@ void TestColorspaces::roundtripConversion()
|
|||
QFETCH(NamedTransferFunction, dstTransferFunction);
|
||||
QFETCH(double, requiredAccuracy);
|
||||
|
||||
const auto src = ColorDescription(srcColorimetry, srcTransferFunction, 100, 0, 100, 100, 0);
|
||||
const auto dst = ColorDescription(dstColorimetry, dstTransferFunction, 100, 0, 100, 100, 0);
|
||||
const auto src = ColorDescription(srcColorimetry, srcTransferFunction, 100, 0, 100, 100);
|
||||
const auto dst = ColorDescription(dstColorimetry, dstTransferFunction, 100, 0, 100, 100);
|
||||
|
||||
const QVector3D red(1, 0, 0);
|
||||
const QVector3D green(0, 1, 0);
|
||||
|
@ -71,6 +73,18 @@ void TestColorspaces::roundtripConversion()
|
|||
QVERIFY(compareVectors(dst.mapTo(src.mapTo(white, dst), src), white, requiredAccuracy));
|
||||
}
|
||||
|
||||
void TestColorspaces::nonNormalizedPrimaries()
|
||||
{
|
||||
// this test ensures that non-normalized primaries don't mess up the transformations between color spaces
|
||||
const auto from = Colorimetry::fromName(NamedColorimetry::BT709);
|
||||
const auto to = Colorimetry(Colorimetry::xyToXYZ(from.red()) * 2, Colorimetry::xyToXYZ(from.green()) * 2, Colorimetry::xyToXYZ(from.blue()) * 2, Colorimetry::xyToXYZ(from.white()) * 2);
|
||||
|
||||
const auto convertedWhite = from.toOther(to) * QVector3D(1, 1, 1);
|
||||
QCOMPARE_LE(std::abs(1 - convertedWhite.x()), s_resolution10bit);
|
||||
QCOMPARE_LE(std::abs(1 - convertedWhite.y()), s_resolution10bit);
|
||||
QCOMPARE_LE(std::abs(1 - convertedWhite.z()), s_resolution10bit);
|
||||
}
|
||||
|
||||
QTEST_MAIN(TestColorspaces)
|
||||
|
||||
#include "test_colorspaces.moc"
|
||||
|
|
|
@ -419,47 +419,32 @@ void TestVirtualDesktops::updateGrid_data()
|
|||
{
|
||||
QTest::addColumn<uint>("initCount");
|
||||
QTest::addColumn<QSize>("size");
|
||||
QTest::addColumn<Qt::Orientation>("orientation");
|
||||
QTest::addColumn<QPoint>("coords");
|
||||
QTest::addColumn<uint>("desktop");
|
||||
const Qt::Orientation h = Qt::Horizontal;
|
||||
const Qt::Orientation v = Qt::Vertical;
|
||||
|
||||
QTest::newRow("one desktop, h") << (uint)1 << QSize(1, 1) << h << QPoint(0, 0) << (uint)1;
|
||||
QTest::newRow("one desktop, v") << (uint)1 << QSize(1, 1) << v << QPoint(0, 0) << (uint)1;
|
||||
QTest::newRow("one desktop, h, 0") << (uint)1 << QSize(1, 1) << h << QPoint(1, 0) << (uint)0;
|
||||
QTest::newRow("one desktop, v, 0") << (uint)1 << QSize(1, 1) << v << QPoint(0, 1) << (uint)0;
|
||||
QTest::newRow("one desktop, h") << (uint)1 << QSize(1, 1) << QPoint(0, 0) << (uint)1;
|
||||
QTest::newRow("one desktop, h, 0") << (uint)1 << QSize(1, 1) << QPoint(1, 0) << (uint)0;
|
||||
|
||||
QTest::newRow("two desktops, h, 1") << (uint)2 << QSize(2, 1) << h << QPoint(0, 0) << (uint)1;
|
||||
QTest::newRow("two desktops, h, 2") << (uint)2 << QSize(2, 1) << h << QPoint(1, 0) << (uint)2;
|
||||
QTest::newRow("two desktops, h, 3") << (uint)2 << QSize(2, 1) << h << QPoint(0, 1) << (uint)0;
|
||||
QTest::newRow("two desktops, h, 4") << (uint)2 << QSize(2, 1) << h << QPoint(2, 0) << (uint)0;
|
||||
QTest::newRow("two desktops, h, 1") << (uint)2 << QSize(2, 1) << QPoint(0, 0) << (uint)1;
|
||||
QTest::newRow("two desktops, h, 2") << (uint)2 << QSize(2, 1) << QPoint(1, 0) << (uint)2;
|
||||
QTest::newRow("two desktops, h, 3") << (uint)2 << QSize(2, 1) << QPoint(0, 1) << (uint)0;
|
||||
QTest::newRow("two desktops, h, 4") << (uint)2 << QSize(2, 1) << QPoint(2, 0) << (uint)0;
|
||||
|
||||
QTest::newRow("two desktops, v, 1") << (uint)2 << QSize(2, 1) << v << QPoint(0, 0) << (uint)1;
|
||||
QTest::newRow("two desktops, v, 2") << (uint)2 << QSize(2, 1) << v << QPoint(1, 0) << (uint)2;
|
||||
QTest::newRow("two desktops, v, 3") << (uint)2 << QSize(2, 1) << v << QPoint(0, 1) << (uint)0;
|
||||
QTest::newRow("two desktops, v, 4") << (uint)2 << QSize(2, 1) << v << QPoint(2, 0) << (uint)0;
|
||||
QTest::newRow("four desktops, h, one row, 1") << (uint)4 << QSize(4, 1) << QPoint(0, 0) << (uint)1;
|
||||
QTest::newRow("four desktops, h, one row, 2") << (uint)4 << QSize(4, 1) << QPoint(1, 0) << (uint)2;
|
||||
QTest::newRow("four desktops, h, one row, 3") << (uint)4 << QSize(4, 1) << QPoint(2, 0) << (uint)3;
|
||||
QTest::newRow("four desktops, h, one row, 4") << (uint)4 << QSize(4, 1) << QPoint(3, 0) << (uint)4;
|
||||
|
||||
QTest::newRow("four desktops, h, one row, 1") << (uint)4 << QSize(4, 1) << h << QPoint(0, 0) << (uint)1;
|
||||
QTest::newRow("four desktops, h, one row, 2") << (uint)4 << QSize(4, 1) << h << QPoint(1, 0) << (uint)2;
|
||||
QTest::newRow("four desktops, h, one row, 3") << (uint)4 << QSize(4, 1) << h << QPoint(2, 0) << (uint)3;
|
||||
QTest::newRow("four desktops, h, one row, 4") << (uint)4 << QSize(4, 1) << h << QPoint(3, 0) << (uint)4;
|
||||
QTest::newRow("four desktops, h, grid, 1") << (uint)4 << QSize(2, 2) << QPoint(0, 0) << (uint)1;
|
||||
QTest::newRow("four desktops, h, grid, 2") << (uint)4 << QSize(2, 2) << QPoint(1, 0) << (uint)2;
|
||||
QTest::newRow("four desktops, h, grid, 3") << (uint)4 << QSize(2, 2) << QPoint(0, 1) << (uint)3;
|
||||
QTest::newRow("four desktops, h, grid, 4") << (uint)4 << QSize(2, 2) << QPoint(1, 1) << (uint)4;
|
||||
QTest::newRow("four desktops, h, grid, 0/3") << (uint)4 << QSize(2, 2) << QPoint(0, 3) << (uint)0;
|
||||
|
||||
QTest::newRow("four desktops, v, one column, 1") << (uint)4 << QSize(1, 4) << v << QPoint(0, 0) << (uint)1;
|
||||
QTest::newRow("four desktops, v, one column, 2") << (uint)4 << QSize(1, 4) << v << QPoint(0, 1) << (uint)2;
|
||||
QTest::newRow("four desktops, v, one column, 3") << (uint)4 << QSize(1, 4) << v << QPoint(0, 2) << (uint)3;
|
||||
QTest::newRow("four desktops, v, one column, 4") << (uint)4 << QSize(1, 4) << v << QPoint(0, 3) << (uint)4;
|
||||
|
||||
QTest::newRow("four desktops, h, grid, 1") << (uint)4 << QSize(2, 2) << h << QPoint(0, 0) << (uint)1;
|
||||
QTest::newRow("four desktops, h, grid, 2") << (uint)4 << QSize(2, 2) << h << QPoint(1, 0) << (uint)2;
|
||||
QTest::newRow("four desktops, h, grid, 3") << (uint)4 << QSize(2, 2) << h << QPoint(0, 1) << (uint)3;
|
||||
QTest::newRow("four desktops, h, grid, 4") << (uint)4 << QSize(2, 2) << h << QPoint(1, 1) << (uint)4;
|
||||
QTest::newRow("four desktops, h, grid, 0/3") << (uint)4 << QSize(2, 2) << h << QPoint(0, 3) << (uint)0;
|
||||
|
||||
QTest::newRow("three desktops, h, grid, 1") << (uint)3 << QSize(2, 2) << h << QPoint(0, 0) << (uint)1;
|
||||
QTest::newRow("three desktops, h, grid, 2") << (uint)3 << QSize(2, 2) << h << QPoint(1, 0) << (uint)2;
|
||||
QTest::newRow("three desktops, h, grid, 3") << (uint)3 << QSize(2, 2) << h << QPoint(0, 1) << (uint)3;
|
||||
QTest::newRow("three desktops, h, grid, 4") << (uint)3 << QSize(2, 2) << h << QPoint(1, 1) << (uint)0;
|
||||
QTest::newRow("three desktops, h, grid, 1") << (uint)3 << QSize(2, 2) << QPoint(0, 0) << (uint)1;
|
||||
QTest::newRow("three desktops, h, grid, 2") << (uint)3 << QSize(2, 2) << QPoint(1, 0) << (uint)2;
|
||||
QTest::newRow("three desktops, h, grid, 3") << (uint)3 << QSize(2, 2) << QPoint(0, 1) << (uint)3;
|
||||
QTest::newRow("three desktops, h, grid, 4") << (uint)3 << QSize(2, 2) << QPoint(1, 1) << (uint)0;
|
||||
}
|
||||
|
||||
void TestVirtualDesktops::updateGrid()
|
||||
|
@ -470,9 +455,8 @@ void TestVirtualDesktops::updateGrid()
|
|||
VirtualDesktopGrid grid;
|
||||
|
||||
QFETCH(QSize, size);
|
||||
QFETCH(Qt::Orientation, orientation);
|
||||
QCOMPARE(vds->desktops().count(), int(initCount));
|
||||
grid.update(size, orientation, vds->desktops());
|
||||
grid.update(size, vds->desktops());
|
||||
QCOMPARE(grid.size(), size);
|
||||
QCOMPARE(grid.width(), size.width());
|
||||
QCOMPARE(grid.height(), size.height());
|
||||
|
|
|
@ -19,6 +19,8 @@ class XkbTest : public QObject
|
|||
private Q_SLOTS:
|
||||
void testToQtKey_data();
|
||||
void testToQtKey();
|
||||
void testFromQtKey_data();
|
||||
void testFromQtKey();
|
||||
};
|
||||
|
||||
// from kwindowsystem/src/platforms/xcb/kkeyserver.cpp
|
||||
|
@ -457,6 +459,28 @@ static const TransKey g_rgQtToSymX[] = {
|
|||
{XKB_KEY_KP_7, Qt::Key_7, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_8, Qt::Key_8, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_9, Qt::Key_9, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Space, Qt::Key_Space, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Tab, Qt::Key_Tab, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Enter, Qt::Key_Enter, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Home, Qt::Key_Home, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Left, Qt::Key_Left, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Up, Qt::Key_Up, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Right, Qt::Key_Right, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Down, Qt::Key_Down, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Prior, Qt::Key_PageUp, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Next, Qt::Key_PageDown, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_End, Qt::Key_End, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Begin, Qt::Key_Clear, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Insert, Qt::Key_Insert, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Delete, Qt::Key_Delete, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Equal, Qt::Key_Equal, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Multiply, Qt::Key_Asterisk, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Add, Qt::Key_Plus, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Separator, Qt::Key_Comma, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Subtract, Qt::Key_Minus, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Decimal, Qt::Key_Period, Qt::KeypadModifier},
|
||||
{XKB_KEY_KP_Divide, Qt::Key_Slash, Qt::KeypadModifier},
|
||||
|
||||
};
|
||||
|
||||
void XkbTest::testToQtKey_data()
|
||||
|
@ -476,5 +500,31 @@ void XkbTest::testToQtKey()
|
|||
QTEST(xkb.toQtKey(keySym), "qt");
|
||||
}
|
||||
|
||||
void XkbTest::testFromQtKey_data()
|
||||
{
|
||||
QTest::addColumn<xkb_keysym_t>("keySym");
|
||||
QTest::addColumn<int>("keyQt");
|
||||
for (std::size_t i = 0; i < sizeof(g_rgQtToSymX) / sizeof(TransKey); i++) {
|
||||
const QByteArray row = QByteArray::number(g_rgQtToSymX[i].keySymX, 16);
|
||||
QTest::newRow(row.constData()) << g_rgQtToSymX[i].keySymX << (g_rgQtToSymX[i].keySymQt | g_rgQtToSymX[i].modifiers).toCombined();
|
||||
}
|
||||
}
|
||||
|
||||
void XkbTest::testFromQtKey()
|
||||
{
|
||||
Xkb xkb;
|
||||
QFETCH(xkb_keysym_t, keySym);
|
||||
QFETCH(int, keyQt);
|
||||
QList<xkb_keysym_t> keys = xkb.keysymsFromQtKey(keyQt);
|
||||
|
||||
QEXPECT_FAIL(QByteArray::number(XKB_KEY_Hyper_L, 16), "keysymsFromQtKey doesn't map hyper to meta", Continue);
|
||||
QEXPECT_FAIL(QByteArray::number(XKB_KEY_Hyper_R, 16), "keysymsFromQtKey doesn't map hyper to meta", Continue);
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 7, 1)
|
||||
QEXPECT_FAIL(QByteArray::number(XKB_KEY_KP_Equal, 16), "KP_Equal is not correctly identified as keypad key in Qt 6.7.0; fixed in 6.7.1: https://codereview.qt-project.org/c/qt/qtbase/+/546889", Continue);
|
||||
#endif
|
||||
|
||||
QVERIFY(keys.contains(keySym));
|
||||
}
|
||||
|
||||
QTEST_MAIN(XkbTest)
|
||||
#include "test_xkb.moc"
|
||||
|
|
|
@ -274,8 +274,6 @@ void TestDragAndDrop::testPointerDragAndDrop()
|
|||
|
||||
// verify that we did not get any further input events
|
||||
QVERIFY(pointerMotionSpy.isEmpty());
|
||||
// the release event is sent primarily for xwayland
|
||||
QCOMPARE(buttonPressSpy.count(), 2);
|
||||
}
|
||||
|
||||
void TestDragAndDrop::testTouchDragAndDrop()
|
||||
|
@ -394,6 +392,7 @@ void TestDragAndDrop::testDragAndDropWithCancelByDestroyDataSource()
|
|||
QSignalSpy dragEnteredSpy(m_dataDevice, &KWayland::Client::DataDevice::dragEntered);
|
||||
QSignalSpy dragMotionSpy(m_dataDevice, &KWayland::Client::DataDevice::dragMotion);
|
||||
QSignalSpy pointerMotionSpy(m_pointer, &KWayland::Client::Pointer::motion);
|
||||
QSignalSpy pointerLeftSpy(m_pointer, &KWayland::Client::Pointer::left);
|
||||
QSignalSpy dragLeftSpy(m_dataDevice, &KWayland::Client::DataDevice::dragLeft);
|
||||
|
||||
// now we can start the drag and drop
|
||||
|
@ -401,11 +400,12 @@ void TestDragAndDrop::testDragAndDropWithCancelByDestroyDataSource()
|
|||
m_dataSource->setDragAndDropActions(KWayland::Client::DataDeviceManager::DnDAction::Copy | KWayland::Client::DataDeviceManager::DnDAction::Move);
|
||||
m_dataDevice->startDrag(buttonPressSpy.first().first().value<quint32>(), m_dataSource, s.get());
|
||||
QVERIFY(dragStartedSpy.wait());
|
||||
|
||||
QCOMPARE(m_seatInterface->dragSurface(), serverSurface);
|
||||
QCOMPARE(m_seatInterface->dragSurfaceTransformation(), QMatrix4x4());
|
||||
QVERIFY(!m_seatInterface->dragIcon());
|
||||
QCOMPARE(SeatInterfacePrivate::get(m_seatInterface)->drag.dragImplicitGrabSerial, buttonPressSpy.first().first().value<quint32>());
|
||||
QVERIFY(dragEnteredSpy.wait());
|
||||
QVERIFY(dragEnteredSpy.count() || dragEnteredSpy.wait());
|
||||
QCOMPARE(dragEnteredSpy.count(), 1);
|
||||
QCOMPARE(dragEnteredSpy.first().first().value<quint32>(), m_display->serial());
|
||||
QCOMPARE(dragEnteredSpy.first().last().toPointF(), QPointF(0, 0));
|
||||
|
@ -452,7 +452,6 @@ void TestDragAndDrop::testDragAndDropWithCancelByDestroyDataSource()
|
|||
|
||||
// verify that we did not get any further input events
|
||||
QVERIFY(pointerMotionSpy.isEmpty());
|
||||
QCOMPARE(buttonPressSpy.count(), 2);
|
||||
}
|
||||
|
||||
void TestDragAndDrop::testPointerEventsIgnored()
|
||||
|
@ -528,14 +527,12 @@ void TestDragAndDrop::testPointerEventsIgnored()
|
|||
m_seatInterface->notifyPointerButton(1, PointerButtonState::Released);
|
||||
m_seatInterface->notifyPointerFrame();
|
||||
QVERIFY(cancelledSpy.wait());
|
||||
QVERIFY(pointerLeftSpy.count() || pointerLeftSpy.wait());
|
||||
|
||||
// all the changes should have been ignored
|
||||
QCOMPARE(axisSpy.count(), 1);
|
||||
QCOMPARE(pointerMotionSpy.count(), 1);
|
||||
QCOMPARE(pointerEnteredSpy.count(), 1);
|
||||
QVERIFY(pointerLeftSpy.isEmpty());
|
||||
// the release event is sent primary for xwayland, see BUG 465444
|
||||
QCOMPARE(buttonSpy.count(), 2);
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(TestDragAndDrop)
|
||||
|
|
|
@ -81,7 +81,6 @@ void TestWaylandServerDisplay::testClientConnection()
|
|||
QVERIFY(client);
|
||||
|
||||
QVERIFY(connectedSpy.isEmpty());
|
||||
QVERIFY(display.connections().isEmpty());
|
||||
ClientConnection *connection = display.getConnection(client);
|
||||
QVERIFY(connection);
|
||||
QCOMPARE(connection->client(), client);
|
||||
|
@ -101,8 +100,6 @@ void TestWaylandServerDisplay::testClientConnection()
|
|||
QCOMPARE((wl_client *)constRef, client);
|
||||
QCOMPARE(connectedSpy.count(), 1);
|
||||
QCOMPARE(connectedSpy.first().first().value<ClientConnection *>(), connection);
|
||||
QCOMPARE(display.connections().count(), 1);
|
||||
QCOMPARE(display.connections().first(), connection);
|
||||
|
||||
QCOMPARE(connection, display.getConnection(client));
|
||||
QCOMPARE(connectedSpy.count(), 1);
|
||||
|
@ -119,10 +116,6 @@ void TestWaylandServerDisplay::testClientConnection()
|
|||
QCOMPARE(connectedSpy.first().first().value<ClientConnection *>(), connection);
|
||||
QCOMPARE(connectedSpy.last().first().value<ClientConnection *>(), connection2);
|
||||
QCOMPARE(connectedSpy.last().first().value<ClientConnection *>(), client2);
|
||||
QCOMPARE(display.connections().count(), 2);
|
||||
QCOMPARE(display.connections().first(), connection);
|
||||
QCOMPARE(display.connections().last(), connection2);
|
||||
QCOMPARE(display.connections().last(), client2);
|
||||
|
||||
// and destroy
|
||||
QVERIFY(disconnectedSpy.isEmpty());
|
||||
|
@ -136,7 +129,6 @@ void TestWaylandServerDisplay::testClientConnection()
|
|||
close(sv[1]);
|
||||
close(sv2[0]);
|
||||
close(sv2[1]);
|
||||
QVERIFY(display.connections().isEmpty());
|
||||
}
|
||||
|
||||
void TestWaylandServerDisplay::testConnectNoSocket()
|
||||
|
|
|
@ -17,6 +17,11 @@ uint32_t Xcb::toXNative(qreal value)
|
|||
return value;
|
||||
}
|
||||
|
||||
QRect Xcb::toXNative(const QRectF &rect)
|
||||
{
|
||||
return rect.toRect();
|
||||
}
|
||||
|
||||
qreal Xcb::fromXNative(int value)
|
||||
{
|
||||
return value;
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
# SPDX-FileCopyrightText: 2024 David Redondo <kde@david-redono.de>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PKG_Libeis QUIET libeis-1.0)
|
||||
|
||||
find_path(Libeis_INCLUDE_DIR
|
||||
NAMES libeis.h
|
||||
HINTS ${PKG_Libeis_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(Libeis_LIBRARY
|
||||
NAMES eis
|
||||
PATHS ${PKG_Libeis_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
set(Libeis_VERSION ${PKG_Libeis_VERSION})
|
||||
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Libeis-1.0
|
||||
FOUND_VAR Libeis-1.0_FOUND
|
||||
REQUIRED_VARS
|
||||
Libeis_LIBRARY
|
||||
Libeis_INCLUDE_DIR
|
||||
VERSION_VAR Libeis_VERSION
|
||||
)
|
||||
|
||||
if(Libeis-1.0_FOUND AND NOT TARGET Libeis::Libeis)
|
||||
add_library(Libeis::Libeis UNKNOWN IMPORTED)
|
||||
set_target_properties(Libeis::Libeis PROPERTIES
|
||||
IMPORTED_LOCATION "${Libeis_LIBRARY}"
|
||||
INTERFACE_COMPILE_OPTIONS "${PKG_Libeis_CFLAGS_OTHER}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Libeis_INCLUDE_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(Libeis_INCLUDE_DIR Libeis_LIBRARY)
|
|
@ -12,6 +12,8 @@
|
|||
# The version of Xwayland
|
||||
# ``Xwayland_HAVE_LISTENFD``
|
||||
# True if (the requested version of) Xwayland has -listenfd option
|
||||
# ``Xwayland_HAVE_ENABLE_EI_PORTAL``
|
||||
# True if (the requested version of) Xwayland has -enable-ei-portal option
|
||||
|
||||
#=============================================================================
|
||||
# SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
@ -25,6 +27,7 @@ pkg_check_modules(PKG_xwayland QUIET xwayland)
|
|||
|
||||
set(Xwayland_VERSION ${PKG_xwayland_VERSION})
|
||||
pkg_get_variable(Xwayland_HAVE_LISTENFD xwayland have_listenfd)
|
||||
pkg_get_variable(Xwayland_HAVE_ENABLE_EI_PORTAL xwayland have_enable_ei_portal)
|
||||
|
||||
find_program(Xwayland_EXECUTABLE NAMES Xwayland)
|
||||
find_package_handle_standard_args(Xwayland
|
||||
|
|
Before Width: | Height: | Size: 380 B After Width: | Height: | Size: 379 B |
Before Width: | Height: | Size: 611 B After Width: | Height: | Size: 609 B |
Before Width: | Height: | Size: 877 B After Width: | Height: | Size: 874 B |
|
@ -9,11 +9,13 @@
|
|||
|
||||
// read additional window rules and add them to kwinrulesrc
|
||||
|
||||
#include <KConfig>
|
||||
#include <KConfigGroup>
|
||||
#include <QCoreApplication>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusMessage>
|
||||
#include <QDebug>
|
||||
#include <QStandardPaths>
|
||||
#include <QtDBus>
|
||||
#include <kconfig.h>
|
||||
#include <kconfiggroup.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 122 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 412 B |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 152 KiB |
Before Width: | Height: | Size: 512 B After Width: | Height: | Size: 491 B |
Before Width: | Height: | Size: 375 B After Width: | Height: | Size: 354 B |
Before Width: | Height: | Size: 163 KiB After Width: | Height: | Size: 134 KiB |
|
@ -284,15 +284,6 @@ This controls the behavior of window focus with multiple screens. Note that thes
|
|||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><guilabel>Active screen follows mouse</guilabel></term>
|
||||
<listitem>
|
||||
<para>
|
||||
When this option is enabled, the active screen (where new windows appear, for example) is the screen containing the mouse pointer. When disabled, the active screen is the screen containing the focused window.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><guilabel>Separate screen focus</guilabel></term>
|
||||
<listitem>
|
||||
|
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 123 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 33 KiB |