Compare commits
869 Commits
Applicatio
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4d4cc19b8 | ||
|
|
1fae4f397f | ||
|
|
63b76148fd | ||
|
|
171252e127 | ||
|
|
2fef7cf822 | ||
|
|
0333ab2bf7 | ||
|
|
c5ac0fd31c | ||
|
|
01b0da2155 | ||
|
|
b0415769fb | ||
|
|
dc6f413417 | ||
|
|
6b68494264 | ||
|
|
c521740404 | ||
|
|
88f1636fef | ||
|
|
a78abfcb93 | ||
|
|
842c91e45d | ||
|
|
c99239d59b | ||
|
|
1ac32eab69 | ||
|
|
1b16ab8e60 | ||
|
|
0c7d124d2d | ||
|
|
16bf626baf | ||
|
|
d8f6679364 | ||
|
|
b693a28aaf | ||
|
|
d5ab56bb9d | ||
|
|
475b8b58a1 | ||
|
|
d15e6f29cf | ||
|
|
5c98ccf62c | ||
|
|
a620a6cb9f | ||
|
|
616c16d3c7 | ||
|
|
d1b574888e | ||
|
|
e7b0d8de56 | ||
|
|
6d18278464 | ||
|
|
22084c348c | ||
|
|
acf5271781 | ||
|
|
f6b394645c | ||
|
|
66dd912bd6 | ||
|
|
1800b476e5 | ||
|
|
b07427aa90 | ||
|
|
a98fe61680 | ||
|
|
659159a5e8 | ||
|
|
5eb64b06b4 | ||
|
|
ad8343d85a | ||
|
|
035ee11e71 | ||
|
|
8409a4678b | ||
|
|
2f8b66463c | ||
|
|
8ce98ad65c | ||
|
|
5d210f6c0b | ||
|
|
3abd0de621 | ||
|
|
213aa27fb5 | ||
|
|
655165f25e | ||
|
|
fe7b111011 | ||
|
|
e6ea4a14dc | ||
|
|
36e8b60170 | ||
|
|
960c9084f5 | ||
|
|
e0b2701489 | ||
|
|
00290d52a4 | ||
|
|
ff96bc1c62 | ||
|
|
47f0fd573f | ||
|
|
bd84fd6d8b | ||
|
|
74be91f2a9 | ||
|
|
b903ccea43 | ||
|
|
c17260b390 | ||
|
|
dab3d905e7 | ||
|
|
af57e23deb | ||
|
|
a465fa2fb7 | ||
|
|
6cd3a6e5a1 | ||
|
|
78a4ce1ce7 | ||
|
|
57b93f371d | ||
|
|
29248ac0d9 | ||
|
|
b0b7557574 | ||
|
|
7e7c0ee341 | ||
|
|
f06724ffb6 | ||
|
|
e574a0a1d7 | ||
|
|
8ef7204c5f | ||
|
|
5973cc20a7 | ||
|
|
1f1b798532 | ||
|
|
acc704344c | ||
|
|
d9b8535d21 | ||
|
|
4075e8d7c6 | ||
|
|
2b7b0a8d97 | ||
|
|
7e34a75b8e | ||
|
|
c434224d23 | ||
|
|
c5b2b0cea3 | ||
|
|
6379e0169d | ||
|
|
8b2a7710e5 | ||
|
|
2c61391149 | ||
|
|
caa11fb498 | ||
|
|
7b8e02825d | ||
|
|
6b32137f8f | ||
|
|
cc4affab49 | ||
|
|
252c51a1bc | ||
|
|
affecefa88 | ||
|
|
5112dfe162 | ||
|
|
e9d2da5285 | ||
|
|
dda0c10d40 | ||
|
|
92a4bb29d3 | ||
|
|
9a5643b5e4 | ||
|
|
988bb60a52 | ||
|
|
19679c5be9 | ||
|
|
4b989e801a | ||
|
|
90975e7799 | ||
|
|
3129dd98f1 | ||
|
|
50d9606aae | ||
|
|
4c6907a965 | ||
|
|
577afe9548 | ||
|
|
4777375716 | ||
|
|
58d2afd573 | ||
|
|
5b8a250780 | ||
|
|
481b048253 | ||
|
|
a4b1d62af9 | ||
|
|
01f1c2114e | ||
|
|
c88a3e1f34 | ||
|
|
9bea080205 | ||
|
|
cb8272be98 | ||
|
|
8bc55acf57 | ||
|
|
b1d5825df6 | ||
|
|
31a8aff379 | ||
|
|
6488840fa2 | ||
|
|
83161a6df8 | ||
|
|
2336935f57 | ||
|
|
ec40d5f024 | ||
|
|
9c10e7a50f | ||
|
|
a002a5e8da | ||
|
|
2400a2d344 | ||
|
|
3a950e5664 | ||
|
|
6073f25525 | ||
|
|
cece62bf4e | ||
|
|
fdb0282869 | ||
|
|
ed767e3b0a | ||
|
|
06349d34d8 | ||
|
|
4f7448759b | ||
|
|
af7fa3a487 | ||
|
|
ab13d92584 | ||
|
|
a4dbf9b23c | ||
|
|
6179693a91 | ||
|
|
07fcbbc70a | ||
|
|
6e182ebf69 | ||
|
|
62a6869875 | ||
|
|
5bd49a9f29 | ||
|
|
d65cdeea6f | ||
|
|
77810b6d46 | ||
|
|
a73a81d38a | ||
|
|
a5571d99ed | ||
|
|
9556de8c87 | ||
|
|
b18dd5e56f | ||
|
|
606e1a53d3 | ||
|
|
573968242c | ||
|
|
067b55b06f | ||
|
|
92c529f8ba | ||
|
|
b7fcb8584a | ||
|
|
d51db17209 | ||
|
|
5cf1bf4c20 | ||
|
|
de4bfacd1c | ||
|
|
ccb50a7ab5 | ||
|
|
f071ad4eba | ||
|
|
24a3a261f8 | ||
|
|
cd43f1107a | ||
|
|
b22ec60da2 | ||
|
|
503c9f55a6 | ||
|
|
36349df89b | ||
|
|
f9838deac0 | ||
|
|
5b012bbd3d | ||
|
|
8dca12a10b | ||
|
|
1e1c3d6f12 | ||
|
|
1d9e67631d | ||
|
|
854768b250 | ||
|
|
8a1a10209e | ||
|
|
0d3a38f39e | ||
|
|
8ee8075f82 | ||
|
|
6e6c694625 | ||
|
|
6e7a5ba569 | ||
|
|
1894fce111 | ||
|
|
d3a7020420 | ||
|
|
da27fc48f0 | ||
|
|
dc8c4aafbe | ||
|
|
882447a1af | ||
|
|
014ced6e67 | ||
|
|
bb050e50b9 | ||
|
|
c6212b781a | ||
|
|
35db6b5f46 | ||
|
|
0c516c3b32 | ||
|
|
8a07b1c6e2 | ||
|
|
1d89ef5079 | ||
|
|
d43f2c20f7 | ||
|
|
abac8a4209 | ||
|
|
7a0c0bd6e1 | ||
|
|
3ae94343e4 | ||
|
|
ae6d83b8c3 | ||
|
|
fffb112dc5 | ||
|
|
7ea7e53e95 | ||
|
|
dc15975fd9 | ||
|
|
3644c0255f | ||
|
|
5a84af1e8f | ||
|
|
e9029de27f | ||
|
|
36ecf445be | ||
|
|
378472f8b2 | ||
|
|
2995637d27 | ||
|
|
eddb7e2394 | ||
|
|
6dd3e1da55 | ||
|
|
1da563ca71 | ||
|
|
4249e7aa6c | ||
|
|
e89c87ce8c | ||
|
|
1abd178dc0 | ||
|
|
7d5160e64e | ||
|
|
a41a003304 | ||
|
|
f4e97af144 | ||
|
|
a600986562 | ||
|
|
3a31ba75f6 | ||
|
|
bacf163970 | ||
|
|
d647cc3a6e | ||
|
|
91a457d38a | ||
|
|
b3e3042bd8 | ||
|
|
4abd4c8b06 | ||
|
|
821120d873 | ||
|
|
406cb4bc5b | ||
|
|
a3b082f402 | ||
|
|
c77bd6a38d | ||
|
|
b7d98b7b72 | ||
|
|
9064d18228 | ||
|
|
a87302156a | ||
|
|
345ec522db | ||
|
|
91a730f18c | ||
|
|
aca3f8fbd0 | ||
|
|
74f92d69c6 | ||
|
|
9d0b4072ad | ||
|
|
1160a4ae0b | ||
|
|
b08d0387e0 | ||
|
|
4d08b1429d | ||
|
|
ce0625c265 | ||
|
|
4bec964bfa | ||
|
|
39c83720bf | ||
|
|
08dbfaced4 | ||
|
|
549affa4c3 | ||
|
|
422ce406c9 | ||
|
|
73504294c1 | ||
|
|
b8e011dd1c | ||
|
|
a8b840daac | ||
|
|
990d5c341a | ||
|
|
4753904c13 | ||
|
|
ba75f0d7ed | ||
|
|
b7a2db5c71 | ||
|
|
caab08ba15 | ||
|
|
a1760c13d3 | ||
|
|
9f01d44a13 | ||
|
|
2b53b784c8 | ||
|
|
f3b8c85ad6 | ||
|
|
45f0e75dd4 | ||
|
|
772e720b3b | ||
|
|
f24120faec | ||
|
|
328c708a8b | ||
|
|
5b375106dd | ||
|
|
0c9f71eabe | ||
|
|
1a6a0cd89d | ||
|
|
9da46e0b08 | ||
|
|
18d7e766e1 | ||
|
|
65157c1c22 | ||
|
|
a3654c058e | ||
|
|
38e9d57591 | ||
|
|
132b895b03 | ||
|
|
dffc379f03 | ||
|
|
6fada45b5a | ||
|
|
02c6cccf43 | ||
|
|
b29b374f08 | ||
|
|
bb028c0c3b | ||
|
|
3996ffd60b | ||
|
|
34870b5c78 | ||
|
|
d542437e2a | ||
|
|
33b7fe0a28 | ||
|
|
f7154d0e2b | ||
|
|
ed89040197 | ||
|
|
d7cdb7f981 | ||
|
|
6bfdd98da6 | ||
|
|
bbd948f2bc | ||
|
|
23038987cf | ||
|
|
6f999ac27c | ||
|
|
699995116f | ||
|
|
3086522a0a | ||
|
|
5ef85f4ea1 | ||
|
|
84886d4f86 | ||
|
|
636c2bbc1e | ||
|
|
993232d73b | ||
|
|
02d2d2e971 | ||
|
|
df30f91225 | ||
|
|
ce562e82bb | ||
|
|
a06121e653 | ||
|
|
fa8dec332a | ||
|
|
de373dd0bc | ||
|
|
54f0f51b9d | ||
|
|
6efc1194aa | ||
|
|
827877e4bb | ||
|
|
5c0c53717c | ||
|
|
f2fc9cacbb | ||
|
|
57ab28f641 | ||
|
|
e56e070a52 | ||
|
|
5b350140d7 | ||
|
|
828f0837b2 | ||
|
|
e6d86a9f56 | ||
|
|
afc2e1fef8 | ||
|
|
641e24e8ae | ||
|
|
6221508a96 | ||
|
|
d937a95d57 | ||
|
|
9c7f354f72 | ||
|
|
4b1d314d6c | ||
|
|
fe7bc043ad | ||
|
|
6d2221afd4 | ||
|
|
0477d02b43 | ||
|
|
d8ec878951 | ||
|
|
d658607908 | ||
|
|
ec720c034d | ||
|
|
8782122406 | ||
|
|
7bd3ddd4a2 | ||
|
|
5fbfcbd494 | ||
|
|
c8cf2386ab | ||
|
|
3259321a7a | ||
|
|
c92c4108b0 | ||
|
|
854bc782a0 | ||
|
|
20c787931c | ||
|
|
b740b6518e | ||
|
|
acc304fb94 | ||
|
|
01c775f2e8 | ||
|
|
953cc4218b | ||
|
|
e865b187a2 | ||
|
|
86fe436fd0 | ||
|
|
21b2361c9f | ||
|
|
09e6984b58 | ||
|
|
df52969067 | ||
|
|
e0ec84ef65 | ||
|
|
336af069cf | ||
|
|
83654bd33d | ||
|
|
4db9c65083 | ||
|
|
4f924c2306 | ||
|
|
d7cafa3dfc | ||
|
|
2e06f4f370 | ||
|
|
0ec2f9f01b | ||
|
|
43b91cc93a | ||
|
|
e805ce0e55 | ||
|
|
462c7295d2 | ||
|
|
f97f9a79fd | ||
|
|
ab13b9a16f | ||
|
|
fba34da8da | ||
|
|
21763fe544 | ||
|
|
9699e7ad2a | ||
|
|
62da564888 | ||
|
|
adecd9b0a4 | ||
|
|
74bb886ac2 | ||
|
|
c131eb9813 | ||
|
|
5c7a4f5e29 | ||
|
|
f1014c54f1 | ||
|
|
c614ca10cc | ||
|
|
085d30862e | ||
|
|
1a2def038b | ||
|
|
d160324b1b | ||
|
|
549b09eff4 | ||
|
|
c59abf032e | ||
|
|
4606fcaeba | ||
|
|
a8ccd7ca5a | ||
|
|
04494dfeb0 | ||
|
|
4169a9f50a | ||
|
|
5173e7ff29 | ||
|
|
745a5d53f2 | ||
|
|
ce0d6fe648 | ||
|
|
42ed3c5707 | ||
|
|
2cd15b6313 | ||
|
|
d1d085008a | ||
|
|
00725ca11b | ||
|
|
e3e1571cea | ||
|
|
b9dd0ac0d6 | ||
|
|
9dfca797dd | ||
|
|
720478a317 | ||
|
|
60161dacf8 | ||
|
|
18591e967c | ||
|
|
4d65b52b47 | ||
|
|
44336093da | ||
|
|
df10a81baa | ||
|
|
172229294c | ||
|
|
3d614c2bd6 | ||
|
|
58d47d3947 | ||
|
|
a03b8db322 | ||
|
|
ea5d2f40bc | ||
|
|
22420a22af | ||
|
|
6f1d60b3ba | ||
|
|
8365e97f9a | ||
|
|
f1da76277e | ||
|
|
ba4329d9b7 | ||
|
|
17d3f53561 | ||
|
|
fbf4fcbce0 | ||
|
|
5158d14147 | ||
|
|
c7ee6f1e0e | ||
|
|
0d8cc44ec2 | ||
|
|
d7c559b017 | ||
|
|
fcebbfb2d4 | ||
|
|
d45679bdbd | ||
|
|
a58c787986 | ||
|
|
96f164c67d | ||
|
|
9b634ae795 | ||
|
|
a80f5f140d | ||
|
|
4a6970d684 | ||
|
|
e2f3910f7a | ||
|
|
c14d37e56f | ||
|
|
2d391672e5 | ||
|
|
64252e52f6 | ||
|
|
a4fed2f0d5 | ||
|
|
70488a7b59 | ||
|
|
78205f9116 | ||
|
|
59db6f6b7b | ||
|
|
18e76cfc0c | ||
|
|
1222c2067c | ||
|
|
25f5492f33 | ||
|
|
96eb21da35 | ||
|
|
cf5f045cab | ||
|
|
dce8e6dc85 | ||
|
|
1e5ff7f93a | ||
|
|
6bec921ec0 | ||
|
|
b13a8e9613 | ||
|
|
8a1261191f | ||
|
|
dddb12708d | ||
|
|
384cfdcbed | ||
|
|
9b26c11c2f | ||
|
|
2c6cb1e6f5 | ||
|
|
6794b9d9fb | ||
|
|
cf2d198c1f | ||
|
|
a0fd0c3a31 | ||
|
|
6a01a98c9f | ||
|
|
7285574c74 | ||
|
|
899bc892c3 | ||
|
|
30455f6308 | ||
|
|
cbafc2fdad | ||
|
|
4815017e04 | ||
|
|
ba8a97b7c8 | ||
|
|
f7b690ea7d | ||
|
|
1d23966d79 | ||
|
|
61d464676c | ||
|
|
775d3c7a97 | ||
|
|
18f98326d4 | ||
|
|
0b65306f15 | ||
|
|
4a2c13135d | ||
|
|
5860226875 | ||
|
|
f30d0b65e3 | ||
|
|
4707bde236 | ||
|
|
608762c7ac | ||
|
|
be01a1e42b | ||
|
|
00c3d1c2ed | ||
|
|
a90970900a | ||
|
|
d1e7614716 | ||
|
|
2127fc927d | ||
|
|
9d5d45c7af | ||
|
|
b4eccc2134 | ||
|
|
97cbf48059 | ||
|
|
c8207581f4 | ||
|
|
4727061d74 | ||
|
|
3bf587a097 | ||
|
|
26c468009f | ||
|
|
fb909eadf4 | ||
|
|
f72674db18 | ||
|
|
df9e6d62d2 | ||
|
|
b55de9645e | ||
|
|
a9241dfe88 | ||
|
|
23c0218f3d | ||
|
|
4a524c6f0a | ||
|
|
cb86f9c018 | ||
|
|
0eaf1bc550 | ||
|
|
cb7164d755 | ||
|
|
75bff9d5f9 | ||
|
|
c729e9e048 | ||
|
|
45548e020a | ||
|
|
dc64af6f5e | ||
|
|
2af26baf56 | ||
|
|
e07f2c1f11 | ||
|
|
e5e2b293e8 | ||
|
|
6cb2b22bf6 | ||
|
|
0316c376f2 | ||
|
|
b8f972d59e | ||
|
|
073cec3dc3 | ||
|
|
58088b6ca0 | ||
|
|
a4cc0e8e7b | ||
|
|
3a1a5ad7a2 | ||
|
|
8e667abe69 | ||
|
|
2e82546012 | ||
|
|
6f342f45ae | ||
|
|
acc70e4cee | ||
|
|
4d84d14070 | ||
|
|
adc8b8069c | ||
|
|
218f0e20f6 | ||
|
|
4f2861415a | ||
|
|
eb1dc503bd | ||
|
|
8f0de62401 | ||
|
|
028ac099ea | ||
|
|
5e18689b8e | ||
|
|
68866dc4fa | ||
|
|
15f5654e5b | ||
|
|
76e36c0761 | ||
|
|
0afcfc82b9 | ||
|
|
730e4d74a8 | ||
|
|
d533b76f9b | ||
|
|
34a0e0c361 | ||
|
|
e1fdba3014 | ||
|
|
73500f837e | ||
|
|
f9a062ffa9 | ||
|
|
a4177eac39 | ||
|
|
15068b250c | ||
|
|
326d58a439 | ||
|
|
1a7f3a8517 | ||
|
|
3625b0cee3 | ||
|
|
7ef0dce382 | ||
|
|
72270006ca | ||
|
|
938f98cef5 | ||
|
|
93eb2d78d4 | ||
|
|
f041cdf095 | ||
|
|
e1e359fa7b | ||
|
|
50b72f26a8 | ||
|
|
2c184a22bf | ||
|
|
bb35068a1d | ||
|
|
706d4853b2 | ||
|
|
f03b829814 | ||
|
|
4335f83dab | ||
|
|
08d967af66 | ||
|
|
f0c1bc787e | ||
|
|
230040c5a9 | ||
|
|
dad7f0184b | ||
|
|
74070d3baa | ||
|
|
cceab8c12a | ||
|
|
b5a328b905 | ||
|
|
513b717fac | ||
|
|
a5f3009530 | ||
|
|
2b1f48b92a | ||
|
|
617f237d4e | ||
|
|
dcc1bb2de5 | ||
|
|
14aa98ccca | ||
|
|
717607b1c6 | ||
|
|
4e0aa9c78b | ||
|
|
e34043d514 | ||
|
|
8010c34bf1 | ||
|
|
5610c0a292 | ||
|
|
280c852a4e | ||
|
|
6518c17362 | ||
|
|
fcad3620db | ||
|
|
de7050d8b7 | ||
|
|
60c5d93f20 | ||
|
|
3a83ce6279 | ||
|
|
a109e3d6c9 | ||
|
|
4993e65d59 | ||
|
|
d91bbdcb05 | ||
|
|
1d429a9bc6 | ||
|
|
2b9cb5c58c | ||
|
|
6d9226c8d9 | ||
|
|
f67f629899 | ||
|
|
0e3733c327 | ||
|
|
fd362fd642 | ||
|
|
b14b7cc3a8 | ||
|
|
b71652061a | ||
|
|
9d02f073bd | ||
|
|
05f36df893 | ||
|
|
251d8f2e0e | ||
|
|
5aa1acd96b | ||
|
|
da2f51de6a | ||
|
|
47fbb3f316 | ||
|
|
7ba81f52df | ||
|
|
b9efda5956 | ||
|
|
f83d5102b6 | ||
|
|
8afd5c8df2 | ||
|
|
ef6b3a6093 | ||
|
|
9e1680d122 | ||
|
|
f3587b224f | ||
|
|
d4175c0f22 | ||
|
|
481972a129 | ||
|
|
e432a4ee7c | ||
|
|
f5768411e6 | ||
|
|
c5d6abab58 | ||
|
|
c5e157fa82 | ||
|
|
3e00ff22f9 | ||
|
|
068ce93465 | ||
|
|
9bb6fd224b | ||
|
|
024ce87b3a | ||
|
|
97951fc296 | ||
|
|
52fded8831 | ||
|
|
740f5c1449 | ||
|
|
1e9a91e83e | ||
|
|
933169b4c0 | ||
|
|
6f58476dbe | ||
|
|
f839da9ba2 | ||
|
|
76c2f08c9e | ||
|
|
b135370c5c | ||
|
|
b5adcd23c6 | ||
|
|
13f5de2518 | ||
|
|
cb83a9d539 | ||
|
|
c4f012a919 | ||
|
|
04c3f3e01e | ||
|
|
0cdc848844 | ||
|
|
e2daae290b | ||
|
|
c73c58b55d | ||
|
|
d983ed6869 | ||
|
|
b948d90c84 | ||
|
|
287919dbe2 | ||
|
|
b561ec1415 | ||
|
|
04d050a685 | ||
|
|
4f3e2f8bd9 | ||
|
|
f284736978 | ||
|
|
bdb4e9efbf | ||
|
|
425783b825 | ||
|
|
3cc2af7e18 | ||
|
|
49add727b0 | ||
|
|
10923d2e01 | ||
|
|
ebbedab547 | ||
|
|
e824ea5534 | ||
|
|
3462004357 | ||
|
|
d57a7e5aef | ||
|
|
60f8a418cd | ||
|
|
ed56b1b8f7 | ||
|
|
3f0f6e9efb | ||
|
|
3e2a8b0ce2 | ||
|
|
f178121c54 | ||
|
|
3f5dabf76b | ||
|
|
bb403a310f | ||
|
|
f32dde2af7 | ||
|
|
4e6062e9af | ||
|
|
8ea2ca9afb | ||
|
|
081d1222b6 | ||
|
|
55d749ce9a | ||
|
|
07b48fe44f | ||
|
|
1da8e3c84a | ||
|
|
92c9905f36 | ||
|
|
a62ef07e9d | ||
|
|
a20cc6963a | ||
|
|
024f02a70f | ||
|
|
f473c88aff | ||
|
|
4acb23aa5e | ||
|
|
f162574aba | ||
|
|
5f53df2e76 | ||
|
|
ba87204070 | ||
|
|
8df008137a | ||
|
|
9b422f1338 | ||
|
|
92b6f2fe68 | ||
|
|
bb59ce2776 | ||
|
|
6c78a2f98d | ||
|
|
8a7965fa6f | ||
|
|
c136ef0681 | ||
|
|
afc1fb6b88 | ||
|
|
e4362a655e | ||
|
|
e2ebae3b19 | ||
|
|
f3648d11a3 | ||
|
|
e897ce9b49 | ||
|
|
8ff1f8fb21 | ||
|
|
f139985c99 | ||
|
|
45d4a9cad7 | ||
|
|
dd7f1af0bc | ||
|
|
b8861cd229 | ||
|
|
80db244c7d | ||
|
|
439bacb527 | ||
|
|
28f2cca952 | ||
|
|
f2b1e60106 | ||
|
|
08c8bd84b1 | ||
|
|
7a42bd3b65 | ||
|
|
7190908aa3 | ||
|
|
28fbf6c89c | ||
|
|
853eeaa050 | ||
|
|
8848a11ba4 | ||
|
|
0234025013 | ||
|
|
5498ce6390 | ||
|
|
46560f2f6a | ||
|
|
1c8afa165b | ||
|
|
4ffe2ce140 | ||
|
|
e472644e10 | ||
|
|
1a23694b32 | ||
|
|
210b1cfac9 | ||
|
|
49c9dc2311 | ||
|
|
1b5daefe54 | ||
|
|
62be4e43fd | ||
|
|
1190610710 | ||
|
|
69c492a54b | ||
|
|
06d711dd79 | ||
|
|
f417d230d7 | ||
|
|
6b7a17a327 | ||
|
|
13f6082465 | ||
|
|
0c1aaa62c1 | ||
|
|
826904c4ca | ||
|
|
eb1b74d90b | ||
|
|
fad81c061a | ||
|
|
a360e5c8ae | ||
|
|
9e9acb4833 | ||
|
|
d22dca0833 | ||
|
|
b0712e1874 | ||
|
|
142a652b25 | ||
|
|
87ad1774a2 | ||
|
|
388aa12a96 | ||
|
|
ed9fe37985 | ||
|
|
bd9e576684 | ||
|
|
bfeba242ea | ||
|
|
be4ec5fe7a | ||
|
|
8e51ddfb45 | ||
|
|
445cb49e16 | ||
|
|
a4c4dd29a5 | ||
|
|
078a05e368 | ||
|
|
f1ec721e47 | ||
|
|
f8e02290a3 | ||
|
|
0e5ac2d9aa | ||
|
|
9828143609 | ||
|
|
0cc47b9a06 | ||
|
|
656c90916c | ||
|
|
296f5db567 | ||
|
|
e15c5d634d | ||
|
|
22b017e0b0 | ||
|
|
05b96c0bd0 | ||
|
|
fa7c32fbb9 | ||
|
|
acf4f7393e | ||
|
|
43aeee4c3e | ||
|
|
aab2869883 | ||
|
|
306a094540 | ||
|
|
a774e678bb | ||
|
|
718b0ac000 | ||
|
|
4230b2234b | ||
|
|
f5467f826c | ||
|
|
0a0a7f096a | ||
|
|
94ea33aaa4 | ||
|
|
3f471e6fd1 | ||
|
|
e018e1a7c5 | ||
|
|
576cef1a12 | ||
|
|
77f5ae8230 | ||
|
|
c05707884c | ||
|
|
7624aee8e2 | ||
|
|
6ecb4248b8 | ||
|
|
61cedda6b3 | ||
|
|
895ec578c6 | ||
|
|
aa189daffd | ||
|
|
9797ff196e | ||
|
|
7519e7918c | ||
|
|
6ef393ba1c | ||
|
|
c47ee269f0 | ||
|
|
a0992f7fea | ||
|
|
ef6491a5c9 | ||
|
|
63d6314b1b | ||
|
|
78ed74ec1e | ||
|
|
1cf5785007 | ||
|
|
0f506011d0 | ||
|
|
d5aff98912 | ||
|
|
d77506c4c2 | ||
|
|
c3d0313280 | ||
|
|
1fc7238699 | ||
|
|
e4a82e3a52 | ||
|
|
c57e9bc5f4 | ||
|
|
2916395ea9 | ||
|
|
3c63cf9563 | ||
|
|
554f2994cc | ||
|
|
313b4bbc67 | ||
|
|
ff5ae6a885 | ||
|
|
f8dfbee9ed | ||
|
|
d6bc236426 | ||
|
|
015518cb9f | ||
|
|
b2fcfeb7f5 | ||
|
|
77c6c35d3e | ||
|
|
d7380a93a3 | ||
|
|
8df92c41c4 | ||
|
|
546a588c18 | ||
|
|
e4fed2991a | ||
|
|
349b99ab47 | ||
|
|
927016cd85 | ||
|
|
abd7bf04ae | ||
|
|
8d19229593 | ||
|
|
c8e4869c8a | ||
|
|
91c62af9bd | ||
|
|
bb9bf0bfc7 | ||
|
|
258e8bd22b | ||
|
|
c5fc5fc68e | ||
|
|
54fd606e82 | ||
|
|
9d44beac84 | ||
|
|
438bddcb27 | ||
|
|
68dafe3f24 | ||
|
|
d1273a8f56 | ||
|
|
6373c44b8d | ||
|
|
6368bdf25b | ||
|
|
b72e478df0 | ||
|
|
b1df09d2bf | ||
|
|
da36f0a7fb | ||
|
|
be70800a74 | ||
|
|
798fc5c2e6 | ||
|
|
26a70c411a | ||
|
|
0945680770 | ||
|
|
39a99107ce | ||
|
|
fc3e3951a4 | ||
|
|
6fc934b0ef | ||
|
|
788d64927d | ||
|
|
d0b0740066 | ||
|
|
438fc15a64 | ||
|
|
8167a114da | ||
|
|
736c598c43 | ||
|
|
822b8c41b9 | ||
|
|
2fee3471f5 | ||
|
|
4ff990b6ea | ||
|
|
9c65f423b5 | ||
|
|
bd26204f96 | ||
|
|
0b9f16cfc7 | ||
|
|
8397b41027 | ||
|
|
709c207af8 | ||
|
|
2f34058010 | ||
|
|
9b2cbaec6f | ||
|
|
25a0e089ef | ||
|
|
004c84a849 | ||
|
|
4473e12434 | ||
|
|
bcec53db13 | ||
|
|
dab8b421eb | ||
|
|
69d278caa8 | ||
|
|
0ac20f797c | ||
|
|
a66fc2d2b8 | ||
|
|
011ac5633f | ||
|
|
90c332ddcf | ||
|
|
52fb6655a1 | ||
|
|
44ae70244d | ||
|
|
69aa649d9c | ||
|
|
1fb61059a7 | ||
|
|
0689b72f38 | ||
|
|
4564c91b64 | ||
|
|
01ec550abf | ||
|
|
47c40225fd | ||
|
|
f131f7ddba | ||
|
|
b2cb3e8204 | ||
|
|
c92ef2f230 | ||
|
|
b2fe612ec4 | ||
|
|
831ec6c9be | ||
|
|
4b01a1cac7 | ||
|
|
09b643f5cb | ||
|
|
77ef270323 | ||
|
|
e487c45f34 | ||
|
|
2a60739a16 | ||
|
|
8eecd9097e | ||
|
|
e3b9a0b30a | ||
|
|
6561a9db15 | ||
|
|
c0ceb8a83d | ||
|
|
f107a73d28 | ||
|
|
4974154cc3 | ||
|
|
05dc124c8b | ||
|
|
b960bb4ba4 | ||
|
|
f702422c9d | ||
|
|
27e48f1114 | ||
|
|
9e77d1f5ac | ||
|
|
c12697e23f | ||
|
|
3ce5047a6f | ||
|
|
60b6f7b86b | ||
|
|
b1f1a2f8d6 | ||
|
|
ee863548d9 | ||
|
|
ccc9ed069f | ||
|
|
8c7138b592 | ||
|
|
364cee9ba2 | ||
|
|
215d20c004 | ||
|
|
315b401227 | ||
|
|
9289a22d8a | ||
|
|
d529e22430 | ||
|
|
b6fbb67af1 | ||
|
|
da4de72d55 | ||
|
|
b3e1624469 | ||
|
|
aa80d3915d | ||
|
|
0b210563cb | ||
|
|
b4713d4755 | ||
|
|
34d9387aa0 | ||
|
|
eb7caf8594 | ||
|
|
e761ee832e | ||
|
|
699d7f9a27 | ||
|
|
43083c52dc | ||
|
|
903692c299 | ||
|
|
2885bf2c5a | ||
|
|
6544fd56e9 | ||
|
|
3fc2398707 | ||
|
|
c1efd7158f | ||
|
|
cbc43a390f | ||
|
|
631d3c85ac | ||
|
|
ae15751847 | ||
|
|
f1a3e2b31c | ||
|
|
b95a5b285d | ||
|
|
0ee5738bf5 | ||
|
|
5195783757 | ||
|
|
1b6702167d | ||
|
|
8b7fcb023d |
100
.flatpak-manifest.json
Normal file
@@ -0,0 +1,100 @@
|
||||
{
|
||||
"id": "org.kde.krfb",
|
||||
"branch": "master",
|
||||
"runtime": "org.kde.Platform",
|
||||
"runtime-version": "6.10",
|
||||
"sdk": "org.kde.Sdk",
|
||||
"command": "krfb",
|
||||
"tags": [
|
||||
"nightly"
|
||||
],
|
||||
"desktop-file-name-suffix": " (Nightly)",
|
||||
"finish-args": [
|
||||
"--share=ipc",
|
||||
"--socket=fallback-x11",
|
||||
"--socket=wayland"
|
||||
],
|
||||
"rename-icon": "krfb",
|
||||
"modules": [
|
||||
{
|
||||
"name": "libgpg-error",
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://www.gnupg.org/ftp/gcrypt/libgpg-error/libgpg-error-1.61.tar.bz2",
|
||||
"sha256": "7a85413f2bc354f4f8aa832b718af122e48965e9e0eb9012ee659c13c6385c93",
|
||||
"x-checker-data": {
|
||||
"type": "anitya",
|
||||
"project-id": 1628,
|
||||
"stable-only": true,
|
||||
"url-template": "https://www.gnupg.org/ftp/gcrypt/libgpg-error/libgpg-error-${version}.tar.bz2"
|
||||
}
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
"/lib/libgpg-error.la"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "libgcrypt",
|
||||
"config-opts": [
|
||||
"--disable-doc"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.12.2.tar.bz2",
|
||||
"sha256": "7ce33c2492221a0436f96a8500215e9f3e3dcb5fd26a757cd415e7a843babd5e",
|
||||
"x-checker-data": {
|
||||
"type": "anitya",
|
||||
"project-id": 1623,
|
||||
"stable-only": true,
|
||||
"url-template": "https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-$version.tar.bz2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "libvncserver",
|
||||
"buildsystem": "cmake-ninja",
|
||||
"config-opts": [
|
||||
"-DCMAKE_POLICY_VERSION_MINIMUM=3.5"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/LibVNC/libvncserver",
|
||||
"branch": "LibVNCServer-0.9.14"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "kpipewire",
|
||||
"buildsystem": "cmake-ninja",
|
||||
"config-opts": [
|
||||
"-DBUILD_TESTING=OFF"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://invent.kde.org/plasma/kpipewire.git",
|
||||
"branch": "master"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "krfb",
|
||||
"buildsystem": "cmake-ninja",
|
||||
"config-opts": [
|
||||
"-DCMAKE_BUILD_TYPE=debug",
|
||||
"-DPLASMA_ENABLED=OFF"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "dir",
|
||||
"path": "."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
2
.flatpak-manifest.json.license
Normal file
@@ -0,0 +1,2 @@
|
||||
# SPDX-FileCopyrightText: None
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
26
.gitignore
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
# Ignore the following files
|
||||
*~
|
||||
*.[oa]
|
||||
*.diff
|
||||
*.kate-swp
|
||||
*.kdev4
|
||||
.kdev_include_paths
|
||||
*.kdevelop.pcs
|
||||
*.moc
|
||||
*.moc.cpp
|
||||
*.orig
|
||||
*.user
|
||||
.*.swp
|
||||
.swp.*
|
||||
Doxyfile
|
||||
Makefile
|
||||
/build*/
|
||||
.cmake/
|
||||
CMakeLists.txt.user*
|
||||
*.unc-backup*
|
||||
.clang-format
|
||||
/compile_commands.json
|
||||
.clangd
|
||||
.cache
|
||||
.idea
|
||||
/cmake-build*
|
||||
12
.gitlab-ci.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
# SPDX-FileCopyrightText: None
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
include:
|
||||
- project: sysadmin/ci-utilities
|
||||
file:
|
||||
- /gitlab-templates/linux-qt6.yml
|
||||
- /gitlab-templates/linux-qt6-next.yml
|
||||
- /gitlab-templates/freebsd-qt6.yml
|
||||
- /gitlab-templates/flatpak.yml
|
||||
- /gitlab-templates/xml-lint.yml
|
||||
- /gitlab-templates/yaml-lint.yml
|
||||
26
.kde-ci.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
# SPDX-FileCopyrightText: None
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
Dependencies:
|
||||
- 'on': ['@all']
|
||||
'require':
|
||||
'frameworks/extra-cmake-modules': '@latest-kf6'
|
||||
'frameworks/ki18n': '@latest-kf6'
|
||||
'frameworks/kconfig': '@latest-kf6'
|
||||
'frameworks/kcoreaddons': '@latest-kf6'
|
||||
'frameworks/kdbusaddons': '@latest-kf6'
|
||||
'frameworks/kdnssd': '@latest-kf6'
|
||||
'frameworks/kdoctools': '@latest-kf6'
|
||||
'frameworks/knotifications': '@latest-kf6'
|
||||
'frameworks/kwallet': '@latest-kf6'
|
||||
'frameworks/kwidgetsaddons': '@latest-kf6'
|
||||
'frameworks/kwindowsystem': '@latest-kf6'
|
||||
'frameworks/kxmlgui': '@latest-kf6'
|
||||
'frameworks/kcrash': '@latest-kf6'
|
||||
'frameworks/kstatusnotifieritem': '@latest-kf6'
|
||||
'libraries/plasma-wayland-protocols': '@latest-kf6'
|
||||
'plasma/kwayland': '@latest-kf6'
|
||||
'plasma/kpipewire': '@latest-kf6'
|
||||
|
||||
Options:
|
||||
require-passing-tests-on: ['Linux', 'FreeBSD', 'Windows']
|
||||
112
CMakeLists.txt
@@ -1,75 +1,125 @@
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(krfb)
|
||||
# KDE Application Version, managed by release script
|
||||
set (RELEASE_SERVICE_VERSION_MAJOR "26")
|
||||
set (RELEASE_SERVICE_VERSION_MINOR "07")
|
||||
set (RELEASE_SERVICE_VERSION_MICRO "70")
|
||||
set (RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
|
||||
|
||||
include(FeatureSummary)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Core DBus Widgets X11Extras)
|
||||
project(krfb VERSION ${RELEASE_SERVICE_VERSION})
|
||||
|
||||
find_package(ECM 1.7.0 NO_MODULE REQUIRED)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
|
||||
set(QT_MIN_VERSION 6.5.0)
|
||||
set(KF6_MIN_VERSION 6.2.0)
|
||||
|
||||
find_package(ECM ${KF6_MIN_VERSION} NO_MODULE REQUIRED)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" ${ECM_MODULE_PATH})
|
||||
|
||||
include(KDEInstallDirs)
|
||||
include(KDECMakeSettings)
|
||||
include(KDECompilerSettings)
|
||||
include(KDECompilerSettings NO_POLICY_SCOPE)
|
||||
include(ECMInstallIcons)
|
||||
include(ECMAddAppIcon)
|
||||
include(ECMSetupVersion)
|
||||
include(ECMQtDeclareLoggingCategory)
|
||||
include(ECMDeprecationSettings)
|
||||
include(FeatureSummary)
|
||||
include(CheckIncludeFile)
|
||||
|
||||
find_package(KF5 REQUIRED COMPONENTS
|
||||
include(KDEClangFormat)
|
||||
include(KDEGitCommitHooks)
|
||||
|
||||
# add clang-format target for all our real source files
|
||||
file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES *.cpp *.h)
|
||||
kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES})
|
||||
kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT)
|
||||
|
||||
check_include_file("linux/input.h" HAVE_LINUX_INPUT_H)
|
||||
|
||||
find_package(Qt6 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core DBus Widgets)
|
||||
if (Qt6Gui_VERSION VERSION_GREATER_EQUAL "6.10.0")
|
||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
||||
endif()
|
||||
find_package(KF6 ${KF6_MIN_VERSION} REQUIRED COMPONENTS
|
||||
I18n
|
||||
Completion
|
||||
Config
|
||||
CoreAddons
|
||||
Crash
|
||||
DBusAddons
|
||||
DNSSD
|
||||
DocTools
|
||||
Notifications
|
||||
Wallet
|
||||
WidgetsAddons
|
||||
WindowSystem
|
||||
XmlGui
|
||||
StatusNotifierItem
|
||||
Crash
|
||||
)
|
||||
|
||||
find_package(X11 REQUIRED)
|
||||
|
||||
find_package(XCB REQUIRED COMPONENTS
|
||||
XCB
|
||||
RENDER
|
||||
SHAPE
|
||||
XFIXES
|
||||
DAMAGE
|
||||
SHM
|
||||
IMAGE
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${KDEWIN32_LIBRARIES})
|
||||
set(CMAKE_REQUIRED_INCLUDES ${KDEWIN32_INCLUDES})
|
||||
endif(WIN32)
|
||||
add_definitions(${QT_DEFINITIONS} ${QT_QTDBUS_DEFINITIONS})
|
||||
add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
|
||||
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} )
|
||||
|
||||
set(CMAKE_MODULE_PATH
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules"
|
||||
${CMAKE_MODULE_PATH}
|
||||
ecm_set_disabled_deprecation_versions(
|
||||
QT 6.7.0
|
||||
KF 6.5.0
|
||||
)
|
||||
|
||||
find_package(LibVNCServer REQUIRED)
|
||||
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} )
|
||||
|
||||
if (HAVE_XDAMAGE)
|
||||
set(X11_Xdamage_FOUND 1)
|
||||
else()
|
||||
set(X11_Xdamage_FOUND 0)
|
||||
find_package(LibVNCServer 0.9.14 REQUIRED)
|
||||
|
||||
|
||||
option(DISABLE_PIPEWIRE "Disable PipeWire support." OFF)
|
||||
if(NOT DISABLE_PIPEWIRE)
|
||||
find_package(KPipeWire CONFIG REQUIRED)
|
||||
pkg_check_modules(PipeWire IMPORTED_TARGET libpipewire-0.3)
|
||||
add_feature_info(PipeWire PipeWire_FOUND "Required for pipewire screencast plugin")
|
||||
endif()
|
||||
if (HAVE_XSHM)
|
||||
set(X11_XShm_FOUND 1)
|
||||
else()
|
||||
set(X11_XShm_FOUND 0)
|
||||
|
||||
find_package(PlasmaWaylandProtocols 1.5.0)
|
||||
|
||||
if(KPipeWire_FOUND AND PipeWire_FOUND AND PlasmaWaylandProtocols_FOUND)
|
||||
find_package(KWayland REQUIRED)
|
||||
find_package(QtWaylandScanner REQUIRED)
|
||||
find_package(Qt6WaylandClient)
|
||||
find_package(Wayland REQUIRED COMPONENTS Client)
|
||||
endif()
|
||||
|
||||
ecm_setup_version(PROJECT
|
||||
VARIABLE_PREFIX KRFB
|
||||
VERSION_HEADER "krfb_version.h")
|
||||
|
||||
include_directories ("${CMAKE_CURRENT_BINARY_DIR}/krfb"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/krfb"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/krfb/ui"
|
||||
)
|
||||
|
||||
if(Q_WS_X11)
|
||||
if(NOT X11_XTest_FOUND)
|
||||
message(FATAL_ERROR "krfb requires the libXtst (http://xorg.freedesktop.org) to be built")
|
||||
endif(NOT X11_XTest_FOUND)
|
||||
endif(Q_WS_X11)
|
||||
|
||||
add_subdirectory(events)
|
||||
add_subdirectory(krfb)
|
||||
add_subdirectory(framebuffers)
|
||||
add_subdirectory(doc)
|
||||
add_subdirectory(icons)
|
||||
|
||||
ki18n_install(po)
|
||||
kdoctools_install(po)
|
||||
|
||||
ecm_qt_install_logging_categories(
|
||||
EXPORT KRFB
|
||||
FILE krfb.categories
|
||||
DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}
|
||||
)
|
||||
|
||||
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||
|
||||
128
CMakePresets.json
Normal file
@@ -0,0 +1,128 @@
|
||||
{
|
||||
"version": 2,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "dev",
|
||||
"displayName": "Build as debug",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "asan",
|
||||
"displayName": "Build with Asan support.",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build-asan",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"ECM_ENABLE_SANITIZERS" : "'address;undefined'",
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "dev-clang",
|
||||
"displayName": "dev-clang",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build-clang",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
|
||||
},
|
||||
"environment": {
|
||||
"CXX": "clang++",
|
||||
"CCACHE_DISABLE": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "unity",
|
||||
"displayName": "Build with CMake unity support.",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build-unity",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_UNITY_BUILD": "ON",
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "release",
|
||||
"displayName": "Build as release mode.",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build-release",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "profile",
|
||||
"displayName": "profile",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build-profile",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "clazy",
|
||||
"displayName": "clazy",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build-clazy",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
},
|
||||
"environment": {
|
||||
"CXX": "clazy",
|
||||
"CCACHE_DISABLE": "ON"
|
||||
}
|
||||
}
|
||||
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "dev",
|
||||
"configurePreset": "dev"
|
||||
},
|
||||
{
|
||||
"name": "release",
|
||||
"configurePreset": "release"
|
||||
},
|
||||
{
|
||||
"name": "dev-clang",
|
||||
"configurePreset": "dev-clang"
|
||||
},
|
||||
{
|
||||
"name": "asan",
|
||||
"configurePreset": "asan"
|
||||
},
|
||||
{
|
||||
"name": "unity",
|
||||
"configurePreset": "unity"
|
||||
},
|
||||
{
|
||||
"name": "clazy",
|
||||
"configurePreset": "clazy",
|
||||
"environment": {
|
||||
"CLAZY_CHECKS" : "level0,level1,detaching-member,ifndef-define-typo,isempty-vs-count,qrequiredresult-candidates,reserve-candidates,signal-with-return-value,unneeded-cast,function-args-by-ref,function-args-by-value,returning-void-expression,no-ctor-missing-parent-argument,isempty-vs-count,qhash-with-char-pointer-key,raw-environment-function,qproperty-type-mismatch,old-style-connect,qstring-allocations,container-inside-loop,heap-allocated-small-trivial-type,inefficient-qlist,qstring-varargs,level2,detaching-member,heap-allocated-small-trivial-type,isempty-vs-count,qstring-varargs,qvariant-template-instantiation,raw-environment-function,reserve-candidates,signal-with-return-value,thread-with-slots,no-ctor-missing-parent-argument,no-missing-typeinfo",
|
||||
"CCACHE_DISABLE" : "ON"
|
||||
}
|
||||
}
|
||||
],
|
||||
"testPresets": [
|
||||
{
|
||||
"name": "dev",
|
||||
"configurePreset": "dev",
|
||||
"output": {"outputOnFailure": true},
|
||||
"execution": {"noTestsAction": "error", "stopOnFailure": false}
|
||||
},
|
||||
{
|
||||
"name": "asan",
|
||||
"configurePreset": "asan",
|
||||
"output": {"outputOnFailure": true},
|
||||
"execution": {"noTestsAction": "error", "stopOnFailure": true}
|
||||
}
|
||||
]
|
||||
}
|
||||
2
CMakePresets.json.license
Normal file
@@ -0,0 +1,2 @@
|
||||
# SPDX-FileCopyrightText: 2021 Laurent Montel <montel@kde.org>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
26
LICENSES/BSD-3-Clause.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
Copyright (c) <year> <owner>. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
121
LICENSES/CC0-1.0.txt
Normal file
@@ -0,0 +1,121 @@
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
||||
311
LICENSES/GPL-2.0-or-later.txt
Normal file
@@ -0,0 +1,311 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||
document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your freedom to share
|
||||
and change it. By contrast, the GNU General Public License is intended to
|
||||
guarantee your freedom to share and change free software--to make sure the
|
||||
software is free for all its users. This General Public License applies to
|
||||
most of the Free Software Foundation's software and to any other program whose
|
||||
authors commit to using it. (Some other Free Software Foundation software
|
||||
is covered by the GNU Lesser General Public License instead.) You can apply
|
||||
it to your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not price. Our
|
||||
General Public Licenses are designed to make sure that you have the freedom
|
||||
to distribute copies of free software (and charge for this service if you
|
||||
wish), that you receive source code or can get it if you want it, that you
|
||||
can change the software or use pieces of it in new free programs; and that
|
||||
you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid anyone to
|
||||
deny you these rights or to ask you to surrender the rights. These restrictions
|
||||
translate to certain responsibilities for you if you distribute copies of
|
||||
the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether gratis or
|
||||
for a fee, you must give the recipients all the rights that you have. You
|
||||
must make sure that they, too, receive or can get the source code. And you
|
||||
must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and (2)
|
||||
offer you this license which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain that
|
||||
everyone understands that there is no warranty for this free software. If
|
||||
the software is modified by someone else and passed on, we want its recipients
|
||||
to know that what they have is not the original, so that any problems introduced
|
||||
by others will not reflect on the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software patents. We
|
||||
wish to avoid the danger that redistributors of a free program will individually
|
||||
obtain patent licenses, in effect making the program proprietary. To prevent
|
||||
this, we have made it clear that any patent must be licensed for everyone's
|
||||
free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and modification
|
||||
follow.
|
||||
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains a notice
|
||||
placed by the copyright holder saying it may be distributed under the terms
|
||||
of this General Public License. The "Program", below, refers to any such program
|
||||
or work, and a "work based on the Program" means either the Program or any
|
||||
derivative work under copyright law: that is to say, a work containing the
|
||||
Program or a portion of it, either verbatim or with modifications and/or translated
|
||||
into another language. (Hereinafter, translation is included without limitation
|
||||
in the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not covered
|
||||
by this License; they are outside its scope. The act of running the Program
|
||||
is not restricted, and the output from the Program is covered only if its
|
||||
contents constitute a work based on the Program (independent of having been
|
||||
made by running the Program). Whether that is true depends on what the Program
|
||||
does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's source code
|
||||
as you receive it, in any medium, provided that you conspicuously and appropriately
|
||||
publish on each copy an appropriate copyright notice and disclaimer of warranty;
|
||||
keep intact all the notices that refer to this License and to the absence
|
||||
of any warranty; and give any other recipients of the Program a copy of this
|
||||
License along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and you
|
||||
may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion of it,
|
||||
thus forming a work based on the Program, and copy and distribute such modifications
|
||||
or work under the terms of Section 1 above, provided that you also meet all
|
||||
of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices stating that
|
||||
you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in whole or
|
||||
in part contains or is derived from the Program or any part thereof, to be
|
||||
licensed as a whole at no charge to all third parties under the terms of this
|
||||
License.
|
||||
|
||||
c) If the modified program normally reads commands interactively when run,
|
||||
you must cause it, when started running for such interactive use in the most
|
||||
ordinary way, to print or display an announcement including an appropriate
|
||||
copyright notice and a notice that there is no warranty (or else, saying that
|
||||
you provide a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this License.
|
||||
(Exception: if the Program itself is interactive but does not normally print
|
||||
such an announcement, your work based on the Program is not required to print
|
||||
an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If identifiable
|
||||
sections of that work are not derived from the Program, and can be reasonably
|
||||
considered independent and separate works in themselves, then this License,
|
||||
and its terms, do not apply to those sections when you distribute them as
|
||||
separate works. But when you distribute the same sections as part of a whole
|
||||
which is a work based on the Program, the distribution of the whole must be
|
||||
on the terms of this License, whose permissions for other licensees extend
|
||||
to the entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest your
|
||||
rights to work written entirely by you; rather, the intent is to exercise
|
||||
the right to control the distribution of derivative or collective works based
|
||||
on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program with
|
||||
the Program (or with a work based on the Program) on a volume of a storage
|
||||
or distribution medium does not bring the other work under the scope of this
|
||||
License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it, under Section
|
||||
2) in object code or executable form under the terms of Sections 1 and 2 above
|
||||
provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable source code,
|
||||
which must be distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three years, to give
|
||||
any third party, for a charge no more than your cost of physically performing
|
||||
source distribution, a complete machine-readable copy of the corresponding
|
||||
source code, to be distributed under the terms of Sections 1 and 2 above on
|
||||
a medium customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer to distribute
|
||||
corresponding source code. (This alternative is allowed only for noncommercial
|
||||
distribution and only if you received the program in object code or executable
|
||||
form with such an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for making
|
||||
modifications to it. For an executable work, complete source code means all
|
||||
the source code for all modules it contains, plus any associated interface
|
||||
definition files, plus the scripts used to control compilation and installation
|
||||
of the executable. However, as a special exception, the source code distributed
|
||||
need not include anything that is normally distributed (in either source or
|
||||
binary form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component itself
|
||||
accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering access to
|
||||
copy from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place counts as distribution of the source code,
|
||||
even though third parties are not compelled to copy the source along with
|
||||
the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program except
|
||||
as expressly provided under this License. Any attempt otherwise to copy, modify,
|
||||
sublicense or distribute the Program is void, and will automatically terminate
|
||||
your rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses terminated
|
||||
so long as such parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not signed
|
||||
it. However, nothing else grants you permission to modify or distribute the
|
||||
Program or its derivative works. These actions are prohibited by law if you
|
||||
do not accept this License. Therefore, by modifying or distributing the Program
|
||||
(or any work based on the Program), you indicate your acceptance of this License
|
||||
to do so, and all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the Program),
|
||||
the recipient automatically receives a license from the original licensor
|
||||
to copy, distribute or modify the Program subject to these terms and conditions.
|
||||
You may not impose any further restrictions on the recipients' exercise of
|
||||
the rights granted herein. You are not responsible for enforcing compliance
|
||||
by third parties to this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent infringement
|
||||
or for any other reason (not limited to patent issues), conditions are imposed
|
||||
on you (whether by court order, agreement or otherwise) that contradict the
|
||||
conditions of this License, they do not excuse you from the conditions of
|
||||
this License. If you cannot distribute so as to satisfy simultaneously your
|
||||
obligations under this License and any other pertinent obligations, then as
|
||||
a consequence you may not distribute the Program at all. For example, if a
|
||||
patent license would not permit royalty-free redistribution of the Program
|
||||
by all those who receive copies directly or indirectly through you, then the
|
||||
only way you could satisfy both it and this License would be to refrain entirely
|
||||
from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply and
|
||||
the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any patents
|
||||
or other property right claims or to contest validity of any such claims;
|
||||
this section has the sole purpose of protecting the integrity of the free
|
||||
software distribution system, which is implemented by public license practices.
|
||||
Many people have made generous contributions to the wide range of software
|
||||
distributed through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing to
|
||||
distribute software through any other system and a licensee cannot impose
|
||||
that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to be a
|
||||
consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in certain
|
||||
countries either by patents or by copyrighted interfaces, the original copyright
|
||||
holder who places the Program under this License may add an explicit geographical
|
||||
distribution limitation excluding those countries, so that distribution is
|
||||
permitted only in or among countries not thus excluded. In such case, this
|
||||
License incorporates the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions of
|
||||
the General Public License from time to time. Such new versions will be similar
|
||||
in spirit to the present version, but may differ in detail to address new
|
||||
problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program specifies
|
||||
a version number of this License which applies to it and "any later version",
|
||||
you have the option of following the terms and conditions either of that version
|
||||
or of any later version published by the Free Software Foundation. If the
|
||||
Program does not specify a version number of this License, you may choose
|
||||
any version ever published by the Free Software Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free programs
|
||||
whose distribution conditions are different, write to the author to ask for
|
||||
permission. For software which is copyrighted by the Free Software Foundation,
|
||||
write to the Free Software Foundation; we sometimes make exceptions for this.
|
||||
Our decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing and reuse
|
||||
of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
|
||||
THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
|
||||
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
|
||||
"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
|
||||
OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE
|
||||
OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA
|
||||
OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES
|
||||
OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH
|
||||
HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest possible
|
||||
use to the public, the best way to achieve this is to make it free software
|
||||
which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to attach
|
||||
them to the start of each source file to most effectively convey the exclusion
|
||||
of warranty; and each file should have at least the "copyright" line and a
|
||||
pointer to where the full notice is found.
|
||||
|
||||
one line to give the program's name and an idea of what it does. Copyright
|
||||
(C) yyyy name of author
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
|
||||
Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how
|
||||
to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this when
|
||||
it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
|
||||
with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software,
|
||||
and you are welcome to redistribute it under certain conditions; type `show
|
||||
c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may be
|
||||
called something other than `show w' and `show c'; they could even be mouse-clicks
|
||||
or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary. Here
|
||||
is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision'
|
||||
(which makes passes at compilers) written by James Hacker.
|
||||
|
||||
signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice
|
||||
604
LICENSES/GPL-3.0-or-later.txt
Normal file
@@ -0,0 +1,604 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||
document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for software and
|
||||
other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed to take
|
||||
away your freedom to share and change the works. By contrast, the GNU General
|
||||
Public License is intended to guarantee your freedom to share and change all
|
||||
versions of a program--to make sure it remains free software for all its users.
|
||||
We, the Free Software Foundation, use the GNU General Public License for most
|
||||
of our software; it applies also to any other work released this way by its
|
||||
authors. You can apply it to your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not price. Our
|
||||
General Public Licenses are designed to make sure that you have the freedom
|
||||
to distribute copies of free software (and charge for them if you wish), that
|
||||
you receive source code or can get it if you want it, that you can change
|
||||
the software or use pieces of it in new free programs, and that you know you
|
||||
can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you these rights
|
||||
or asking you to surrender the rights. Therefore, you have certain responsibilities
|
||||
if you distribute copies of the software, or if you modify it: responsibilities
|
||||
to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether gratis or
|
||||
for a fee, you must pass on to the recipients the same freedoms that you received.
|
||||
You must make sure that they, too, receive or can get the source code. And
|
||||
you must show them these terms so they know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps: (1) assert
|
||||
copyright on the software, and (2) offer you this License giving you legal
|
||||
permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains that
|
||||
there is no warranty for this free software. For both users' and authors'
|
||||
sake, the GPL requires that modified versions be marked as changed, so that
|
||||
their problems will not be attributed erroneously to authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run modified
|
||||
versions of the software inside them, although the manufacturer can do so.
|
||||
This is fundamentally incompatible with the aim of protecting users' freedom
|
||||
to change the software. The systematic pattern of such abuse occurs in the
|
||||
area of products for individuals to use, which is precisely where it is most
|
||||
unacceptable. Therefore, we have designed this version of the GPL to prohibit
|
||||
the practice for those products. If such problems arise substantially in other
|
||||
domains, we stand ready to extend this provision to those domains in future
|
||||
versions of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents. States
|
||||
should not allow patents to restrict development and use of software on general-purpose
|
||||
computers, but in those that do, we wish to avoid the special danger that
|
||||
patents applied to a free program could make it effectively proprietary. To
|
||||
prevent this, the GPL assures that patents cannot be used to render the program
|
||||
non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and modification
|
||||
follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
“This License” refers to version 3 of the GNU General Public License.
|
||||
|
||||
“Copyright” also means copyright-like laws that apply to other kinds of works,
|
||||
such as semiconductor masks.
|
||||
|
||||
“The Program” refers to any copyrightable work licensed under this License.
|
||||
Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals
|
||||
or organizations.
|
||||
|
||||
To “modify” a work means to copy from or adapt all or part of the work in
|
||||
a fashion requiring copyright permission, other than the making of an exact
|
||||
copy. The resulting work is called a “modified version” of the earlier work
|
||||
or a work “based on” the earlier work.
|
||||
|
||||
A “covered work” means either the unmodified Program or a work based on the
|
||||
Program.
|
||||
|
||||
To “propagate” a work means to do anything with it that, without permission,
|
||||
would make you directly or secondarily liable for infringement under applicable
|
||||
copyright law, except executing it on a computer or modifying a private copy.
|
||||
Propagation includes copying, distribution (with or without modification),
|
||||
making available to the public, and in some countries other activities as
|
||||
well.
|
||||
|
||||
To “convey” a work means any kind of propagation that enables other parties
|
||||
to make or receive copies. Mere interaction with a user through a computer
|
||||
network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays “Appropriate Legal Notices” to the
|
||||
extent that it includes a convenient and prominently visible feature that
|
||||
(1) displays an appropriate copyright notice, and (2) tells the user that
|
||||
there is no warranty for the work (except to the extent that warranties are
|
||||
provided), that licensees may convey the work under this License, and how
|
||||
to view a copy of this License. If the interface presents a list of user commands
|
||||
or options, such as a menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
The “source code” for a work means the preferred form of the work for making
|
||||
modifications to it. “Object code” means any non-source form of a work.
|
||||
|
||||
A “Standard Interface” means an interface that either is an official standard
|
||||
defined by a recognized standards body, or, in the case of interfaces specified
|
||||
for a particular programming language, one that is widely used among developers
|
||||
working in that language.
|
||||
|
||||
The “System Libraries” of an executable work include anything, other than
|
||||
the work as a whole, that (a) is included in the normal form of packaging
|
||||
a Major Component, but which is not part of that Major Component, and (b)
|
||||
serves only to enable use of the work with that Major Component, or to implement
|
||||
a Standard Interface for which an implementation is available to the public
|
||||
in source code form. A “Major Component”, in this context, means a major essential
|
||||
component (kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to produce
|
||||
the work, or an object code interpreter used to run it.
|
||||
|
||||
The “Corresponding Source” for a work in object code form means all the source
|
||||
code needed to generate, install, and (for an executable work) run the object
|
||||
code and to modify the work, including scripts to control those activities.
|
||||
However, it does not include the work's System Libraries, or general-purpose
|
||||
tools or generally available free programs which are used unmodified in performing
|
||||
those activities but which are not part of the work. For example, Corresponding
|
||||
Source includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically linked
|
||||
subprograms that the work is specifically designed to require, such as by
|
||||
intimate data communication or control flow between those subprograms and
|
||||
other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users can regenerate
|
||||
automatically from other parts of the Corresponding Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
All rights granted under this License are granted for the term of copyright
|
||||
on the Program, and are irrevocable provided the stated conditions are met.
|
||||
This License explicitly affirms your unlimited permission to run the unmodified
|
||||
Program. The output from running a covered work is covered by this License
|
||||
only if the output, given its content, constitutes a covered work. This License
|
||||
acknowledges your rights of fair use or other equivalent, as provided by copyright
|
||||
law.
|
||||
|
||||
You may make, run and propagate covered works that you do not convey, without
|
||||
conditions so long as your license otherwise remains in force. You may convey
|
||||
covered works to others for the sole purpose of having them make modifications
|
||||
exclusively for you, or provide you with facilities for running those works,
|
||||
provided that you comply with the terms of this License in conveying all material
|
||||
for which you do not control copyright. Those thus making or running the covered
|
||||
works for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of your copyrighted
|
||||
material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under the conditions
|
||||
stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
No covered work shall be deemed part of an effective technological measure
|
||||
under any applicable law fulfilling obligations under article 11 of the WIPO
|
||||
copyright treaty adopted on 20 December 1996, or similar laws prohibiting
|
||||
or restricting circumvention of such measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid circumvention
|
||||
of technological measures to the extent such circumvention is effected by
|
||||
exercising rights under this License with respect to the covered work, and
|
||||
you disclaim any intention to limit operation or modification of the work
|
||||
as a means of enforcing, against the work's users, your or third parties'
|
||||
legal rights to forbid circumvention of technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
You may convey verbatim copies of the Program's source code as you receive
|
||||
it, in any medium, provided that you conspicuously and appropriately publish
|
||||
on each copy an appropriate copyright notice; keep intact all notices stating
|
||||
that this License and any non-permissive terms added in accord with section
|
||||
7 apply to the code; keep intact all notices of the absence of any warranty;
|
||||
and give all recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey, and you
|
||||
may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
You may convey a work based on the Program, or the modifications to produce
|
||||
it from the Program, in the form of source code under the terms of section
|
||||
4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified it, and
|
||||
giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is released under
|
||||
this License and any conditions added under section 7. This requirement modifies
|
||||
the requirement in section 4 to “keep intact all notices”.
|
||||
|
||||
c) You must license the entire work, as a whole, under this License to anyone
|
||||
who comes into possession of a copy. This License will therefore apply, along
|
||||
with any applicable section 7 additional terms, to the whole of the work,
|
||||
and all its parts, regardless of how they are packaged. This License gives
|
||||
no permission to license the work in any other way, but it does not invalidate
|
||||
such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display Appropriate
|
||||
Legal Notices; however, if the Program has interactive interfaces that do
|
||||
not display Appropriate Legal Notices, your work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent works,
|
||||
which are not by their nature extensions of the covered work, and which are
|
||||
not combined with it such as to form a larger program, in or on a volume of
|
||||
a storage or distribution medium, is called an “aggregate” if the compilation
|
||||
and its resulting copyright are not used to limit the access or legal rights
|
||||
of the compilation's users beyond what the individual works permit. Inclusion
|
||||
of a covered work in an aggregate does not cause this License to apply to
|
||||
the other parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
You may convey a covered work in object code form under the terms of sections
|
||||
4 and 5, provided that you also convey the machine-readable Corresponding
|
||||
Source under the terms of this License, in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product (including
|
||||
a physical distribution medium), accompanied by the Corresponding Source fixed
|
||||
on a durable physical medium customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product (including
|
||||
a physical distribution medium), accompanied by a written offer, valid for
|
||||
at least three years and valid for as long as you offer spare parts or customer
|
||||
support for that product model, to give anyone who possesses the object code
|
||||
either (1) a copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical medium customarily
|
||||
used for software interchange, for a price no more than your reasonable cost
|
||||
of physically performing this conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the written
|
||||
offer to provide the Corresponding Source. This alternative is allowed only
|
||||
occasionally and noncommercially, and only if you received the object code
|
||||
with such an offer, in accord with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated place (gratis
|
||||
or for a charge), and offer equivalent access to the Corresponding Source
|
||||
in the same way through the same place at no further charge. You need not
|
||||
require recipients to copy the Corresponding Source along with the object
|
||||
code. If the place to copy the object code is a network server, the Corresponding
|
||||
Source may be on a different server (operated by you or a third party) that
|
||||
supports equivalent copying facilities, provided you maintain clear directions
|
||||
next to the object code saying where to find the Corresponding Source. Regardless
|
||||
of what server hosts the Corresponding Source, you remain obligated to ensure
|
||||
that it is available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided you inform
|
||||
other peers where the object code and Corresponding Source of the work are
|
||||
being offered to the general public at no charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded from
|
||||
the Corresponding Source as a System Library, need not be included in conveying
|
||||
the object code work.
|
||||
|
||||
A “User Product” is either (1) a “consumer product”, which means any tangible
|
||||
personal property which is normally used for personal, family, or household
|
||||
purposes, or (2) anything designed or sold for incorporation into a dwelling.
|
||||
In determining whether a product is a consumer product, doubtful cases shall
|
||||
be resolved in favor of coverage. For a particular product received by a particular
|
||||
user, “normally used” refers to a typical or common use of that class of product,
|
||||
regardless of the status of the particular user or of the way in which the
|
||||
particular user actually uses, or expects or is expected to use, the product.
|
||||
A product is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent the
|
||||
only significant mode of use of the product.
|
||||
|
||||
“Installation Information” for a User Product means any methods, procedures,
|
||||
authorization keys, or other information required to install and execute modified
|
||||
versions of a covered work in that User Product from a modified version of
|
||||
its Corresponding Source. The information must suffice to ensure that the
|
||||
continued functioning of the modified object code is in no case prevented
|
||||
or interfered with solely because modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or specifically
|
||||
for use in, a User Product, and the conveying occurs as part of a transaction
|
||||
in which the right of possession and use of the User Product is transferred
|
||||
to the recipient in perpetuity or for a fixed term (regardless of how the
|
||||
transaction is characterized), the Corresponding Source conveyed under this
|
||||
section must be accompanied by the Installation Information. But this requirement
|
||||
does not apply if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has been installed
|
||||
in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a requirement
|
||||
to continue to provide support service, warranty, or updates for a work that
|
||||
has been modified or installed by the recipient, or for the User Product in
|
||||
which it has been modified or installed. Access to a network may be denied
|
||||
when the modification itself materially and adversely affects the operation
|
||||
of the network or violates the rules and protocols for communication across
|
||||
the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided, in accord
|
||||
with this section must be in a format that is publicly documented (and with
|
||||
an implementation available to the public in source code form), and must require
|
||||
no special password or key for unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
“Additional permissions” are terms that supplement the terms of this License
|
||||
by making exceptions from one or more of its conditions. Additional permissions
|
||||
that are applicable to the entire Program shall be treated as though they
|
||||
were included in this License, to the extent that they are valid under applicable
|
||||
law. If additional permissions apply only to part of the Program, that part
|
||||
may be used separately under those permissions, but the entire Program remains
|
||||
governed by this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option remove any
|
||||
additional permissions from that copy, or from any part of it. (Additional
|
||||
permissions may be written to require their own removal in certain cases when
|
||||
you modify the work.) You may place additional permissions on material, added
|
||||
by you to a covered work, for which you have or can give appropriate copyright
|
||||
permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you add
|
||||
to a covered work, you may (if authorized by the copyright holders of that
|
||||
material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the terms of
|
||||
sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or author
|
||||
attributions in that material or in the Appropriate Legal Notices displayed
|
||||
by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or requiring
|
||||
that modified versions of such material be marked in reasonable ways as different
|
||||
from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or authors
|
||||
of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some trade names,
|
||||
trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that material by
|
||||
anyone who conveys the material (or modified versions of it) with contractual
|
||||
assumptions of liability to the recipient, for any liability that these contractual
|
||||
assumptions directly impose on those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered “further restrictions”
|
||||
within the meaning of section 10. If the Program as you received it, or any
|
||||
part of it, contains a notice stating that it is governed by this License
|
||||
along with a term that is a further restriction, you may remove that term.
|
||||
If a license document contains a further restriction but permits relicensing
|
||||
or conveying under this License, you may add to a covered work material governed
|
||||
by the terms of that license document, provided that the further restriction
|
||||
does not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you must place,
|
||||
in the relevant source files, a statement of the additional terms that apply
|
||||
to those files, or a notice indicating where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the form
|
||||
of a separately written license, or stated as exceptions; the above requirements
|
||||
apply either way.
|
||||
|
||||
8. Termination.
|
||||
You may not propagate or modify a covered work except as expressly provided
|
||||
under this License. Any attempt otherwise to propagate or modify it is void,
|
||||
and will automatically terminate your rights under this License (including
|
||||
any patent licenses granted under the third paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your license from
|
||||
a particular copyright holder is reinstated (a) provisionally, unless and
|
||||
until the copyright holder explicitly and finally terminates your license,
|
||||
and (b) permanently, if the copyright holder fails to notify you of the violation
|
||||
by some reasonable means prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is reinstated permanently
|
||||
if the copyright holder notifies you of the violation by some reasonable means,
|
||||
this is the first time you have received notice of violation of this License
|
||||
(for any work) from that copyright holder, and you cure the violation prior
|
||||
to 30 days after your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the licenses
|
||||
of parties who have received copies or rights from you under this License.
|
||||
If your rights have been terminated and not permanently reinstated, you do
|
||||
not qualify to receive new licenses for the same material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
You are not required to accept this License in order to receive or run a copy
|
||||
of the Program. Ancillary propagation of a covered work occurring solely as
|
||||
a consequence of using peer-to-peer transmission to receive a copy likewise
|
||||
does not require acceptance. However, nothing other than this License grants
|
||||
you permission to propagate or modify any covered work. These actions infringe
|
||||
copyright if you do not accept this License. Therefore, by modifying or propagating
|
||||
a covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
Each time you convey a covered work, the recipient automatically receives
|
||||
a license from the original licensors, to run, modify and propagate that work,
|
||||
subject to this License. You are not responsible for enforcing compliance
|
||||
by third parties with this License.
|
||||
|
||||
An “entity transaction” is a transaction transferring control of an organization,
|
||||
or substantially all assets of one, or subdividing an organization, or merging
|
||||
organizations. If propagation of a covered work results from an entity transaction,
|
||||
each party to that transaction who receives a copy of the work also receives
|
||||
whatever licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the Corresponding
|
||||
Source of the work from the predecessor in interest, if the predecessor has
|
||||
it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the rights
|
||||
granted or affirmed under this License. For example, you may not impose a
|
||||
license fee, royalty, or other charge for exercise of rights granted under
|
||||
this License, and you may not initiate litigation (including a cross-claim
|
||||
or counterclaim in a lawsuit) alleging that any patent claim is infringed
|
||||
by making, using, selling, offering for sale, or importing the Program or
|
||||
any portion of it.
|
||||
|
||||
11. Patents.
|
||||
A “contributor” is a copyright holder who authorizes use under this License
|
||||
of the Program or a work on which the Program is based. The work thus licensed
|
||||
is called the contributor's “contributor version”.
|
||||
|
||||
A contributor's “essential patent claims” are all patent claims owned or controlled
|
||||
by the contributor, whether already acquired or hereafter acquired, that would
|
||||
be infringed by some manner, permitted by this License, of making, using,
|
||||
or selling its contributor version, but do not include claims that would be
|
||||
infringed only as a consequence of further modification of the contributor
|
||||
version. For purposes of this definition, “control” includes the right to
|
||||
grant patent sublicenses in a manner consistent with the requirements of this
|
||||
License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free patent
|
||||
license under the contributor's essential patent claims, to make, use, sell,
|
||||
offer for sale, import and otherwise run, modify and propagate the contents
|
||||
of its contributor version.
|
||||
|
||||
In the following three paragraphs, a “patent license” is any express agreement
|
||||
or commitment, however denominated, not to enforce a patent (such as an express
|
||||
permission to practice a patent or covenant not to sue for patent infringement).
|
||||
To “grant” such a patent license to a party means to make such an agreement
|
||||
or commitment not to enforce a patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license, and the
|
||||
Corresponding Source of the work is not available for anyone to copy, free
|
||||
of charge and under the terms of this License, through a publicly available
|
||||
network server or other readily accessible means, then you must either (1)
|
||||
cause the Corresponding Source to be so available, or (2) arrange to deprive
|
||||
yourself of the benefit of the patent license for this particular work, or
|
||||
(3) arrange, in a manner consistent with the requirements of this License,
|
||||
to extend the patent license to downstream recipients. “Knowingly relying”
|
||||
means you have actual knowledge that, but for the patent license, your conveying
|
||||
the covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that country
|
||||
that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or arrangement,
|
||||
you convey, or propagate by procuring conveyance of, a covered work, and grant
|
||||
a patent license to some of the parties receiving the covered work authorizing
|
||||
them to use, propagate, modify or convey a specific copy of the covered work,
|
||||
then the patent license you grant is automatically extended to all recipients
|
||||
of the covered work and works based on it.
|
||||
|
||||
A patent license is “discriminatory” if it does not include within the scope
|
||||
of its coverage, prohibits the exercise of, or is conditioned on the non-exercise
|
||||
of one or more of the rights that are specifically granted under this License.
|
||||
You may not convey a covered work if you are a party to an arrangement with
|
||||
a third party that is in the business of distributing software, under which
|
||||
you make payment to the third party based on the extent of your activity of
|
||||
conveying the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory patent
|
||||
license (a) in connection with copies of the covered work conveyed by you
|
||||
(or copies made from those copies), or (b) primarily for and in connection
|
||||
with specific products or compilations that contain the covered work, unless
|
||||
you entered into that arrangement, or that patent license was granted, prior
|
||||
to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting any implied
|
||||
license or other defenses to infringement that may otherwise be available
|
||||
to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
If conditions are imposed on you (whether by court order, agreement or otherwise)
|
||||
that contradict the conditions of this License, they do not excuse you from
|
||||
the conditions of this License. If you cannot convey a covered work so as
|
||||
to satisfy simultaneously your obligations under this License and any other
|
||||
pertinent obligations, then as a consequence you may not convey it at all.
|
||||
For example, if you agree to terms that obligate you to collect a royalty
|
||||
for further conveying from those to whom you convey the Program, the only
|
||||
way you could satisfy both those terms and this License would be to refrain
|
||||
entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
Notwithstanding any other provision of this License, you have permission to
|
||||
link or combine any covered work with a work licensed under version 3 of the
|
||||
GNU Affero General Public License into a single combined work, and to convey
|
||||
the resulting work. The terms of this License will continue to apply to the
|
||||
part which is the covered work, but the special requirements of the GNU Affero
|
||||
General Public License, section 13, concerning interaction through a network
|
||||
will apply to the combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
The Free Software Foundation may publish revised and/or new versions of the
|
||||
GNU General Public License from time to time. Such new versions will be similar
|
||||
in spirit to the present version, but may differ in detail to address new
|
||||
problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program specifies
|
||||
that a certain numbered version of the GNU General Public License “or any
|
||||
later version” applies to it, you have the option of following the terms and
|
||||
conditions either of that numbered version or of any later version published
|
||||
by the Free Software Foundation. If the Program does not specify a version
|
||||
number of the GNU General Public License, you may choose any version ever
|
||||
published by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future versions of
|
||||
the GNU General Public License can be used, that proxy's public statement
|
||||
of acceptance of a version permanently authorizes you to choose that version
|
||||
for the Program.
|
||||
|
||||
Later license versions may give you additional or different permissions. However,
|
||||
no additional obligations are imposed on any author or copyright holder as
|
||||
a result of your choosing to follow a later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE
|
||||
LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM
|
||||
PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
|
||||
CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
|
||||
ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM
|
||||
AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
|
||||
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO
|
||||
USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
|
||||
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE
|
||||
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
|
||||
PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
If the disclaimer of warranty and limitation of liability provided above cannot
|
||||
be given local legal effect according to their terms, reviewing courts shall
|
||||
apply local law that most closely approximates an absolute waiver of all civil
|
||||
liability in connection with the Program, unless a warranty or assumption
|
||||
of liability accompanies a copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest possible
|
||||
use to the public, the best way to achieve this is to make it free software
|
||||
which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to attach
|
||||
them to the start of each source file to most effectively state the exclusion
|
||||
of warranty; and each file should have at least the “copyright” line and a
|
||||
pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short notice like
|
||||
this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it under certain
|
||||
conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands might
|
||||
be different; for a GUI interface, you would use an “about box”.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a “copyright disclaimer” for the program, if necessary. For
|
||||
more information on this, and how to apply and follow the GNU GPL, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General Public
|
||||
License instead of this License. But first, please read <http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
462
LICENSES/LGPL-2.1-only.txt
Normal file
@@ -0,0 +1,462 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||
document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts as
|
||||
the successor of the GNU Library Public License, version 2, hence the version
|
||||
number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your freedom to share
|
||||
and change it. By contrast, the GNU General Public Licenses are intended to
|
||||
guarantee your freedom to share and change free software--to make sure the
|
||||
software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some specially
|
||||
designated software packages--typically libraries--of the Free Software Foundation
|
||||
and other authors who decide to use it. You can use it too, but we suggest
|
||||
you first think carefully about whether this license or the ordinary General
|
||||
Public License is the better strategy to use in any particular case, based
|
||||
on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use, not price.
|
||||
Our General Public Licenses are designed to make sure that you have the freedom
|
||||
to distribute copies of free software (and charge for this service if you
|
||||
wish); that you receive source code or can get it if you want it; that you
|
||||
can change the software and use pieces of it in new free programs; and that
|
||||
you are informed that you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid distributors
|
||||
to deny you these rights or to ask you to surrender these rights. These restrictions
|
||||
translate to certain responsibilities for you if you distribute copies of
|
||||
the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis or for
|
||||
a fee, you must give the recipients all the rights that we gave you. You must
|
||||
make sure that they, too, receive or can get the source code. If you link
|
||||
other code with the library, you must provide complete object files to the
|
||||
recipients, so that they can relink them with the library after making changes
|
||||
to the library and recompiling it. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the library,
|
||||
and (2) we offer you this license, which gives you legal permission to copy,
|
||||
distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that there is no
|
||||
warranty for the free library. Also, if the library is modified by someone
|
||||
else and passed on, the recipients should know that what they have is not
|
||||
the original version, so that the original author's reputation will not be
|
||||
affected by problems that might be introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of any free
|
||||
program. We wish to make sure that a company cannot effectively restrict the
|
||||
users of a free program by obtaining a restrictive license from a patent holder.
|
||||
Therefore, we insist that any patent license obtained for a version of the
|
||||
library must be consistent with the full freedom of use specified in this
|
||||
license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary GNU
|
||||
General Public License. This license, the GNU Lesser General Public License,
|
||||
applies to certain designated libraries, and is quite different from the ordinary
|
||||
General Public License. We use this license for certain libraries in order
|
||||
to permit linking those libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using a shared
|
||||
library, the combination of the two is legally speaking a combined work, a
|
||||
derivative of the original library. The ordinary General Public License therefore
|
||||
permits such linking only if the entire combination fits its criteria of freedom.
|
||||
The Lesser General Public License permits more lax criteria for linking other
|
||||
code with the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it does Less
|
||||
to protect the user's freedom than the ordinary General Public License. It
|
||||
also provides other free software developers Less of an advantage over competing
|
||||
non-free programs. These disadvantages are the reason we use the ordinary
|
||||
General Public License for many libraries. However, the Lesser license provides
|
||||
advantages in certain special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to encourage the
|
||||
widest possible use of a certain library, so that it becomes a de-facto standard.
|
||||
To achieve this, non-free programs must be allowed to use the library. A more
|
||||
frequent case is that a free library does the same job as widely used non-free
|
||||
libraries. In this case, there is little to gain by limiting the free library
|
||||
to free software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free programs
|
||||
enables a greater number of people to use a large body of free software. For
|
||||
example, permission to use the GNU C Library in non-free programs enables
|
||||
many more people to use the whole GNU operating system, as well as its variant,
|
||||
the GNU/Linux operating system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the users'
|
||||
freedom, it does ensure that the user of a program that is linked with the
|
||||
Library has the freedom and the wherewithal to run that program using a modified
|
||||
version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and modification
|
||||
follow. Pay close attention to the difference between a "work based on the
|
||||
library" and a "work that uses the library". The former contains code derived
|
||||
from the library, whereas the latter must be combined with the library in
|
||||
order to run.
|
||||
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other program
|
||||
which contains a notice placed by the copyright holder or other authorized
|
||||
party saying it may be distributed under the terms of this Lesser General
|
||||
Public License (also called "this License"). Each licensee is addressed as
|
||||
"you".
|
||||
|
||||
A "library" means a collection of software functions and/or data prepared
|
||||
so as to be conveniently linked with application programs (which use some
|
||||
of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work which has
|
||||
been distributed under these terms. A "work based on the Library" means either
|
||||
the Library or any derivative work under copyright law: that is to say, a
|
||||
work containing the Library or a portion of it, either verbatim or with modifications
|
||||
and/or translated straightforwardly into another language. (Hereinafter, translation
|
||||
is included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for making modifications
|
||||
to it. For a library, complete source code means all the source code for all
|
||||
modules it contains, plus any associated interface definition files, plus
|
||||
the scripts used to control compilation and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not covered
|
||||
by this License; they are outside its scope. The act of running a program
|
||||
using the Library is not restricted, and output from such a program is covered
|
||||
only if its contents constitute a work based on the Library (independent of
|
||||
the use of the Library in a tool for writing it). Whether that is true depends
|
||||
on what the Library does and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's complete source
|
||||
code as you receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice and disclaimer
|
||||
of warranty; keep intact all the notices that refer to this License and to
|
||||
the absence of any warranty; and distribute a copy of this License along with
|
||||
the Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and you
|
||||
may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion of it,
|
||||
thus forming a work based on the Library, and copy and distribute such modifications
|
||||
or work under the terms of Section 1 above, provided that you also meet all
|
||||
of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices stating that
|
||||
you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no charge to all
|
||||
third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a table of
|
||||
data to be supplied by an application program that uses the facility, other
|
||||
than as an argument passed when the facility is invoked, then you must make
|
||||
a good faith effort to ensure that, in the event an application does not supply
|
||||
such function or table, the facility still operates, and performs whatever
|
||||
part of its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has a purpose
|
||||
that is entirely well-defined independent of the application. Therefore, Subsection
|
||||
2d requires that any application-supplied function or table used by this function
|
||||
must be optional: if the application does not supply it, the square root function
|
||||
must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If identifiable
|
||||
sections of that work are not derived from the Library, and can be reasonably
|
||||
considered independent and separate works in themselves, then this License,
|
||||
and its terms, do not apply to those sections when you distribute them as
|
||||
separate works. But when you distribute the same sections as part of a whole
|
||||
which is a work based on the Library, the distribution of the whole must be
|
||||
on the terms of this License, whose permissions for other licensees extend
|
||||
to the entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest your
|
||||
rights to work written entirely by you; rather, the intent is to exercise
|
||||
the right to control the distribution of derivative or collective works based
|
||||
on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library with
|
||||
the Library (or with a work based on the Library) on a volume of a storage
|
||||
or distribution medium does not bring the other work under the scope of this
|
||||
License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public License
|
||||
instead of this License to a given copy of the Library. To do this, you must
|
||||
alter all the notices that refer to this License, so that they refer to the
|
||||
ordinary GNU General Public License, version 2, instead of to this License.
|
||||
(If a newer version than version 2 of the ordinary GNU General Public License
|
||||
has appeared, then you can specify that version instead if you wish.) Do not
|
||||
make any other change in these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for that copy,
|
||||
so the ordinary GNU General Public License applies to all subsequent copies
|
||||
and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of the Library
|
||||
into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or derivative of
|
||||
it, under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you accompany it with the complete corresponding
|
||||
machine-readable source code, which must be distributed under the terms of
|
||||
Sections 1 and 2 above on a medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy from a designated
|
||||
place, then offering equivalent access to copy the source code from the same
|
||||
place satisfies the requirement to distribute the source code, even though
|
||||
third parties are not compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the Library, but
|
||||
is designed to work with the Library by being compiled or linked with it,
|
||||
is called a "work that uses the Library". Such a work, in isolation, is not
|
||||
a derivative work of the Library, and therefore falls outside the scope of
|
||||
this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library creates an
|
||||
executable that is a derivative of the Library (because it contains portions
|
||||
of the Library), rather than a "work that uses the library". The executable
|
||||
is therefore covered by this License. Section 6 states terms for distribution
|
||||
of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file that
|
||||
is part of the Library, the object code for the work may be a derivative work
|
||||
of the Library even though the source code is not. Whether this is true is
|
||||
especially significant if the work can be linked without the Library, or if
|
||||
the work is itself a library. The threshold for this to be true is not precisely
|
||||
defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data structure layouts
|
||||
and accessors, and small macros and small inline functions (ten lines or less
|
||||
in length), then the use of the object file is unrestricted, regardless of
|
||||
whether it is legally a derivative work. (Executables containing this object
|
||||
code plus portions of the Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may distribute
|
||||
the object code for the work under the terms of Section 6. Any executables
|
||||
containing that work also fall under Section 6, whether or not they are linked
|
||||
directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or link a "work
|
||||
that uses the Library" with the Library to produce a work containing portions
|
||||
of the Library, and distribute that work under terms of your choice, provided
|
||||
that the terms permit modification of the work for the customer's own use
|
||||
and reverse engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the Library
|
||||
is used in it and that the Library and its use are covered by this License.
|
||||
You must supply a copy of this License. If the work during execution displays
|
||||
copyright notices, you must include the copyright notice for the Library among
|
||||
them, as well as a reference directing the user to the copy of this License.
|
||||
Also, you must do one of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding machine-readable source
|
||||
code for the Library including whatever changes were used in the work (which
|
||||
must be distributed under Sections 1 and 2 above); and, if the work is an
|
||||
executable linked with the Library, with the complete machine-readable "work
|
||||
that uses the Library", as object code and/or source code, so that the user
|
||||
can modify the Library and then relink to produce a modified executable containing
|
||||
the modified Library. (It is understood that the user who changes the contents
|
||||
of definitions files in the Library will not necessarily be able to recompile
|
||||
the application to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the Library. A
|
||||
suitable mechanism is one that (1) uses at run time a copy of the library
|
||||
already present on the user's computer system, rather than copying library
|
||||
functions into the executable, and (2) will operate properly with a modified
|
||||
version of the library, if the user installs one, as long as the modified
|
||||
version is interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at least three years,
|
||||
to give the same user the materials specified in Subsection 6a, above, for
|
||||
a charge no more than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy from a designated
|
||||
place, offer equivalent access to copy the above specified materials from
|
||||
the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these materials or
|
||||
that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the Library" must
|
||||
include any data and utility programs needed for reproducing the executable
|
||||
from it. However, as a special exception, the materials to be distributed
|
||||
need not include anything that is normally distributed (in either source or
|
||||
binary form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component itself
|
||||
accompanies the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license restrictions of
|
||||
other proprietary libraries that do not normally accompany the operating system.
|
||||
Such a contradiction means you cannot use both them and the Library together
|
||||
in an executable that you distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the Library side-by-side
|
||||
in a single library together with other library facilities not covered by
|
||||
this License, and distribute such a combined library, provided that the separate
|
||||
distribution of the work based on the Library and of the other library facilities
|
||||
is otherwise permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based on the
|
||||
Library, uncombined with any other library facilities. This must be distributed
|
||||
under the terms of the Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact that part of
|
||||
it is a work based on the Library, and explaining where to find the accompanying
|
||||
uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute the Library
|
||||
except as expressly provided under this License. Any attempt otherwise to
|
||||
copy, modify, sublicense, link with, or distribute the Library is void, and
|
||||
will automatically terminate your rights under this License. However, parties
|
||||
who have received copies, or rights, from you under this License will not
|
||||
have their licenses terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not signed
|
||||
it. However, nothing else grants you permission to modify or distribute the
|
||||
Library or its derivative works. These actions are prohibited by law if you
|
||||
do not accept this License. Therefore, by modifying or distributing the Library
|
||||
(or any work based on the Library), you indicate your acceptance of this License
|
||||
to do so, and all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the Library),
|
||||
the recipient automatically receives a license from the original licensor
|
||||
to copy, distribute, link with or modify the Library subject to these terms
|
||||
and conditions. You may not impose any further restrictions on the recipients'
|
||||
exercise of the rights granted herein. You are not responsible for enforcing
|
||||
compliance by third parties with this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent infringement
|
||||
or for any other reason (not limited to patent issues), conditions are imposed
|
||||
on you (whether by court order, agreement or otherwise) that contradict the
|
||||
conditions of this License, they do not excuse you from the conditions of
|
||||
this License. If you cannot distribute so as to satisfy simultaneously your
|
||||
obligations under this License and any other pertinent obligations, then as
|
||||
a consequence you may not distribute the Library at all. For example, if a
|
||||
patent license would not permit royalty-free redistribution of the Library
|
||||
by all those who receive copies directly or indirectly through you, then the
|
||||
only way you could satisfy both it and this License would be to refrain entirely
|
||||
from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any patents
|
||||
or other property right claims or to contest validity of any such claims;
|
||||
this section has the sole purpose of protecting the integrity of the free
|
||||
software distribution system which is implemented by public license practices.
|
||||
Many people have made generous contributions to the wide range of software
|
||||
distributed through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing to
|
||||
distribute software through any other system and a licensee cannot impose
|
||||
that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to be a
|
||||
consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in certain
|
||||
countries either by patents or by copyrighted interfaces, the original copyright
|
||||
holder who places the Library under this License may add an explicit geographical
|
||||
distribution limitation excluding those countries, so that distribution is
|
||||
permitted only in or among countries not thus excluded. In such case, this
|
||||
License incorporates the limitation as if written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new versions of
|
||||
the Lesser General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to address
|
||||
new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library specifies
|
||||
a version number of this License which applies to it and "any later version",
|
||||
you have the option of following the terms and conditions either of that version
|
||||
or of any later version published by the Free Software Foundation. If the
|
||||
Library does not specify a license version number, you may choose any version
|
||||
ever published by the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free programs
|
||||
whose distribution conditions are incompatible with these, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free Software
|
||||
Foundation, write to the Free Software Foundation; we sometimes make exceptions
|
||||
for this. Our decision will be guided by the two goals of preserving the free
|
||||
status of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
|
||||
THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
|
||||
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY
|
||||
"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
|
||||
OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
|
||||
THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE
|
||||
OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA
|
||||
OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES
|
||||
OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH
|
||||
HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest possible
|
||||
use to the public, we recommend making it free software that everyone can
|
||||
redistribute and change. You can do so by permitting redistribution under
|
||||
these terms (or, alternatively, under the terms of the ordinary General Public
|
||||
License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is safest
|
||||
to attach them to the start of each source file to most effectively convey
|
||||
the exclusion of warranty; and each file should have at least the "copyright"
|
||||
line and a pointer to where the full notice is found.
|
||||
|
||||
one line to give the library's name and an idea of what it does.
|
||||
Copyright (C) year name of author
|
||||
|
||||
This library is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information
|
||||
on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your school,
|
||||
if any, to sign a "copyright disclaimer" for the library, if necessary. Here
|
||||
is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in
|
||||
the library `Frob' (a library for tweaking knobs) written
|
||||
by James Random Hacker.
|
||||
|
||||
signature of Ty Coon, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
That's all there is to it!
|
||||
144
LICENSES/LGPL-3.0-only.txt
Normal file
@@ -0,0 +1,144 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||
document, but changing it is not allowed.
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates the terms
|
||||
and conditions of version 3 of the GNU General Public License, supplemented
|
||||
by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser General
|
||||
Public License, and the "GNU GPL" refers to version 3 of the GNU General Public
|
||||
License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License, other than
|
||||
an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided by the
|
||||
Library, but which is not otherwise based on the Library. Defining a subclass
|
||||
of a class defined by the Library is deemed a mode of using an interface provided
|
||||
by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an Application
|
||||
with the Library. The particular version of the Library with which the Combined
|
||||
Work was made is also called the "Linked Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the Corresponding
|
||||
Source for the Combined Work, excluding any source code for portions of the
|
||||
Combined Work that, considered in isolation, are based on the Application,
|
||||
and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the object
|
||||
code and/or source code for the Application, including any data and utility
|
||||
programs needed for reproducing the Combined Work from the Application, but
|
||||
excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
You may convey a covered work under sections 3 and 4 of this License without
|
||||
being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
If you modify a copy of the Library, and, in your modifications, a facility
|
||||
refers to a function or data to be supplied by an Application that uses the
|
||||
facility (other than as an argument passed when the facility is invoked),
|
||||
then you may convey a copy of the modified version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to ensure
|
||||
that, in the event an Application does not supply the function or data, the
|
||||
facility still operates, and performs whatever part of its purpose remains
|
||||
meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of this License
|
||||
applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
The object code form of an Application may incorporate material from a header
|
||||
file that is part of the Library. You may convey such object code under terms
|
||||
of your choice, provided that, if the incorporated material is not limited
|
||||
to numerical parameters, data structure layouts and accessors, or small macros,
|
||||
inline functions and templates (ten or fewer lines in length), you do both
|
||||
of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the Library
|
||||
is used in it and that the Library and its use are covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license document.
|
||||
|
||||
4. Combined Works.
|
||||
You may convey a Combined Work under terms of your choice that, taken together,
|
||||
effectively do not restrict modification of the portions of the Library contained
|
||||
in the Combined Work and reverse engineering for debugging such modifications,
|
||||
if you also do each of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that the Library
|
||||
is used in it and that the Library and its use are covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during execution, include
|
||||
the copyright notice for the Library among these notices, as well as a reference
|
||||
directing the user to the copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this License,
|
||||
and the Corresponding Application Code in a form suitable for, and under terms
|
||||
that permit, the user to recombine or relink the Application with a modified
|
||||
version of the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the Library.
|
||||
A suitable mechanism is one that (a) uses at run time a copy of the Library
|
||||
already present on the user's computer system, and (b) will operate properly
|
||||
with a modified version of the Library that is interface-compatible with the
|
||||
Linked Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise be required
|
||||
to provide such information under section 6 of the GNU GPL, and only to the
|
||||
extent that such information is necessary to install and execute a modified
|
||||
version of the Combined Work produced by recombining or relinking the Application
|
||||
with a modified version of the Linked Version. (If you use option 4d0, the
|
||||
Installation Information must accompany the Minimal Corresponding Source and
|
||||
Corresponding Application Code. If you use option 4d1, you must provide the
|
||||
Installation Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
You may place library facilities that are a work based on the Library side
|
||||
by side in a single library together with other library facilities that are
|
||||
not Applications and are not covered by this License, and convey such a combined
|
||||
library under terms of your choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based on the
|
||||
Library, uncombined with any other library facilities, conveyed under the
|
||||
terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it is a work
|
||||
based on the Library, and explaining where to find the accompanying uncombined
|
||||
form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
The Free Software Foundation may publish revised and/or new versions of the
|
||||
GNU Lesser General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to address
|
||||
new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library as you
|
||||
received it specifies that a certain numbered version of the GNU Lesser General
|
||||
Public License "or any later version" applies to it, you have the option of
|
||||
following the terms and conditions either of that published version or of
|
||||
any later version published by the Free Software Foundation. If the Library
|
||||
as you received it does not specify a version number of the GNU Lesser General
|
||||
Public License, you may choose any version of the GNU Lesser General Public
|
||||
License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide whether
|
||||
future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is permanent
|
||||
authorization for you to choose that version for the Library.
|
||||
12
LICENSES/LicenseRef-KDE-Accepted-LGPL.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the license or (at your option) any later version
|
||||
that is accepted by the membership of KDE e.V. (or its successor
|
||||
approved by the membership of KDE e.V.), which shall act as a
|
||||
proxy as defined in Section 6 of version 3 of the license.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
4
NOTES
@@ -1,7 +1,7 @@
|
||||
Comments on various aspects of KRfb:
|
||||
|
||||
- KRfb has been designed for three use cases:
|
||||
* a user who needs help from an administrator or friend. The adminstrator can
|
||||
* a user who needs help from an administrator or friend. The administrator can
|
||||
connect to the user and change settings and so on while both are talking
|
||||
on the telephone or using VoIP.
|
||||
* a user who wants to show something to a friend, so he lets his friend
|
||||
@@ -12,7 +12,7 @@ Comments on various aspects of KRfb:
|
||||
so KRfb is pre-configured for them. Case 3 is for advanced users and
|
||||
therefore a little bit more difficult to configure.
|
||||
- design goal of KRfb is to make it as easy to use as possible. I tried to
|
||||
limit functionality whereever possible.
|
||||
limit functionality wherever possible.
|
||||
- the new-connection-dialog is extra large and has the pixmap on the left
|
||||
side to capture the attention of the user before allowing a connection.
|
||||
- the RFBController class is a mess. The interactions between the threaded,
|
||||
|
||||
4
README
@@ -12,8 +12,4 @@ x0rfbserver left. Since version 0.6 it uses libvncserver
|
||||
|
||||
Guide to documentation:
|
||||
TODO - things to be done
|
||||
INSTALL - Very short installation instructions
|
||||
NOTES - reasons for various decisions
|
||||
DCOP-INTERFACE - short documentation of the DCOP interface
|
||||
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
# cmake macro to test LIBVNCSERVER LIB
|
||||
|
||||
# Copyright (c) 2006, Alessandro Praduroux <pradu@pradu.it>
|
||||
# Copyright (c) 2007, Urs Wolfer <uwolfer @ kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
INCLUDE(CheckStructHasMember)
|
||||
|
||||
IF (LIBVNCSERVER_INCLUDE_DIR AND LIBVNCSERVER_LIBRARIES)
|
||||
# Already in cache, be silent
|
||||
SET(LIBVNCSERVER_FIND_QUIETLY TRUE)
|
||||
ENDIF (LIBVNCSERVER_INCLUDE_DIR AND LIBVNCSERVER_LIBRARIES)
|
||||
|
||||
FIND_PATH(LIBVNCSERVER_INCLUDE_DIR rfb/rfb.h)
|
||||
|
||||
FIND_LIBRARY(LIBVNCSERVER_LIBRARIES NAMES vncserver libvncserver)
|
||||
|
||||
# libvncserver and libvncclient are in the same package, so it does
|
||||
# not make sense to add a new cmake script for finding libvncclient.
|
||||
# instead just find the libvncclient also in this file.
|
||||
FIND_PATH(LIBVNCCLIENT_INCLUDE_DIR rfb/rfbclient.h)
|
||||
FIND_LIBRARY(LIBVNCCLIENT_LIBRARIES NAMES vncclient libvncclient)
|
||||
|
||||
IF (LIBVNCSERVER_INCLUDE_DIR AND LIBVNCSERVER_LIBRARIES)
|
||||
SET(CMAKE_REQUIRED_INCLUDES "${LIBVNCSERVER_INCLUDE_DIR}" "${CMAKE_REQUIRED_INCLUDES}")
|
||||
CHECK_STRUCT_HAS_MEMBER("struct _rfbClient" GotXCutText rfb/rfbclient.h LIBVNCSERVER_FOUND)
|
||||
ENDIF (LIBVNCSERVER_INCLUDE_DIR AND LIBVNCSERVER_LIBRARIES)
|
||||
|
||||
IF (LIBVNCSERVER_FOUND)
|
||||
IF (NOT LIBVNCSERVER_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found LibVNCServer: ${LIBVNCSERVER_LIBRARIES}")
|
||||
ENDIF (NOT LIBVNCSERVER_FIND_QUIETLY)
|
||||
ELSE (LIBVNCSERVER_FOUND)
|
||||
IF (LIBVNCSERVER_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could NOT find acceptable version of LibVNCServer (version 0.9 or later required).")
|
||||
ENDIF (LIBVNCSERVER_FIND_REQUIRED)
|
||||
ENDIF (LIBVNCSERVER_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(LIBVNCSERVER_INCLUDE_DIR LIBVNCSERVER_LIBRARIES)
|
||||
104
cmake/modules/Findgbm.cmake
Normal file
@@ -0,0 +1,104 @@
|
||||
#.rst:
|
||||
# Findgbm
|
||||
# -------
|
||||
#
|
||||
# Try to find gbm on a Unix system.
|
||||
#
|
||||
# This will define the following variables:
|
||||
#
|
||||
# ``gbm_FOUND``
|
||||
# True if (the requested version of) gbm is available
|
||||
# ``gbm_VERSION``
|
||||
# The version of gbm
|
||||
# ``gbm_LIBRARIES``
|
||||
# This can be passed to target_link_libraries() instead of the ``gbm::gbm``
|
||||
# target
|
||||
# ``gbm_INCLUDE_DIRS``
|
||||
# This should be passed to target_include_directories() if the target is not
|
||||
# used for linking
|
||||
# ``gbm_DEFINITIONS``
|
||||
# This should be passed to target_compile_options() if the target is not
|
||||
# used for linking
|
||||
#
|
||||
# If ``gbm_FOUND`` is TRUE, it will also define the following imported target:
|
||||
#
|
||||
# ``gbm::gbm``
|
||||
# The gbm library
|
||||
#
|
||||
# In general we recommend using the imported target, as it is easier to use.
|
||||
# Bear in mind, however, that if the target is in the link interface of an
|
||||
# exported library, it must be made available by the package config file.
|
||||
|
||||
#=============================================================================
|
||||
# SPDX-FileCopyrightText: 2014 Alex Merry <alex.merry@kde.org>
|
||||
# SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#=============================================================================
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS 2.8.12)
|
||||
message(FATAL_ERROR "CMake 2.8.12 is required by Findgbm.cmake")
|
||||
endif()
|
||||
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12)
|
||||
message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use Findgbm.cmake")
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
# Use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PKG_gbm QUIET gbm)
|
||||
|
||||
set(gbm_DEFINITIONS ${PKG_gbm_CFLAGS_OTHER})
|
||||
set(gbm_VERSION ${PKG_gbm_VERSION})
|
||||
|
||||
find_path(gbm_INCLUDE_DIR
|
||||
NAMES
|
||||
gbm.h
|
||||
HINTS
|
||||
${PKG_gbm_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(gbm_LIBRARY
|
||||
NAMES
|
||||
gbm
|
||||
HINTS
|
||||
${PKG_gbm_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(gbm
|
||||
FOUND_VAR
|
||||
gbm_FOUND
|
||||
REQUIRED_VARS
|
||||
gbm_LIBRARY
|
||||
gbm_INCLUDE_DIR
|
||||
VERSION_VAR
|
||||
gbm_VERSION
|
||||
)
|
||||
|
||||
if(gbm_FOUND AND NOT TARGET gbm::gbm)
|
||||
add_library(gbm::gbm UNKNOWN IMPORTED)
|
||||
set_target_properties(gbm::gbm PROPERTIES
|
||||
IMPORTED_LOCATION "${gbm_LIBRARY}"
|
||||
INTERFACE_COMPILE_OPTIONS "${gbm_DEFINITIONS}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${gbm_INCLUDE_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(gbm_LIBRARY gbm_INCLUDE_DIR)
|
||||
|
||||
# compatibility variables
|
||||
set(gbm_LIBRARIES ${gbm_LIBRARY})
|
||||
set(gbm_INCLUDE_DIRS ${gbm_INCLUDE_DIR})
|
||||
set(gbm_VERSION_STRING ${gbm_VERSION})
|
||||
|
||||
else()
|
||||
message(STATUS "Findgbm.cmake cannot find gbm on Windows systems.")
|
||||
set(gbm_FOUND FALSE)
|
||||
endif()
|
||||
|
||||
include(FeatureSummary)
|
||||
set_package_properties(gbm PROPERTIES
|
||||
URL "https://www.mesa3d.org"
|
||||
DESCRIPTION "Mesa gbm library."
|
||||
)
|
||||
507
dbus/xdp_dbus_remotedesktop_interface.xml
Normal file
@@ -0,0 +1,507 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Copyright (C) 2017-2018 Red Hat, Inc.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
|
||||
<!--
|
||||
org.freedesktop.portal.RemoteDesktop:
|
||||
@short_description: Remote desktop portal
|
||||
|
||||
The Remote desktop portal allows to create remote desktop sessions.
|
||||
|
||||
This documentation describes version 2 of this interface.
|
||||
-->
|
||||
<interface name="org.freedesktop.portal.RemoteDesktop">
|
||||
<!--
|
||||
CreateSession:
|
||||
@options: Vardict with optional further information
|
||||
@handle: Object path for the #org.freedesktop.portal.Request object representing this call
|
||||
|
||||
Create a remote desktop session.
|
||||
|
||||
A remote desktop session is used to allow remote controlling a desktop
|
||||
session.
|
||||
|
||||
A remote desktop session may only be started and stopped with this interface,
|
||||
but you can use the #org.freedesktop.portal.Session object created with this
|
||||
method together with certain methods on the #org.freedesktop.portal.ScreenCast and
|
||||
#org.freedesktop.portal.Clipboard interfaces. Specifically, you can call
|
||||
org.freedesktop.portal.ScreenCast.SelectSources() to also get screen content,
|
||||
and org.freedesktop.portal.ScreenCast.OpenPipeWireRemote() to acquire a file
|
||||
descriptor for a PipeWire remote. See #org.freedesktop.portal.ScreenCast for
|
||||
more information on how to use those methods. To capture clipboard content,
|
||||
you can call org.freedesktop.portal.Clipboard.RequestClipboard(). See
|
||||
#org.freedesktop.portal.Clipboard for more information on the clipboard
|
||||
integration.
|
||||
|
||||
Supported keys in the @options vardict include:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>handle_token s</term>
|
||||
<listitem><para>
|
||||
A string that will be used as the last element of the @handle. Must be a valid
|
||||
object path element. See the #org.freedesktop.portal.Request documentation for
|
||||
more information about the @handle.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>session_handle_token s</term>
|
||||
<listitem><para>
|
||||
A string that will be used as the last element of the session handle. Must be a valid
|
||||
object path element. See the #org.freedesktop.portal.Session documentation for
|
||||
more information about the session handle.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
The following results get returned via the #org.freedesktop.portal.Request::Response signal:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>session_handle o</term>
|
||||
<listitem><para>
|
||||
The session handle. An object path for the
|
||||
#org.freedesktop.portal.Session object representing the created
|
||||
session.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
-->
|
||||
<method name="CreateSession">
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
|
||||
<arg type="o" name="handle" direction="out"/>
|
||||
</method>
|
||||
<!--
|
||||
SelectDevices:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@options: Vardict with optional further information
|
||||
@handle: Object path for the #org.freedesktop.portal.Request object representing this call
|
||||
|
||||
Select input devices to remote control.
|
||||
|
||||
Supported keys in the @options vardict include:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>handle_token s</term>
|
||||
<listitem><para>
|
||||
A string that will be used as the last element of the @handle. Must be a valid
|
||||
object path element. See the #org.freedesktop.portal.Request documentation for
|
||||
more information about the @handle.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>types u</term>
|
||||
<listitem><para>
|
||||
Bitmask of what device types to request remote controlling of.
|
||||
Default is all.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>restore_token s</term>
|
||||
<listitem><para>
|
||||
The token to restore a previous session.
|
||||
|
||||
If the stored session cannot be restored, this value is ignored
|
||||
and the user will be prompted normally. This may happen when, for
|
||||
example, the session contains a monitor or a window that is not
|
||||
available anymore, or when the stored permissions are withdrawn.
|
||||
|
||||
The restore token is invalidated after using it once. To restore
|
||||
the same session again, use the new restore token sent in response
|
||||
to starting this session.
|
||||
|
||||
This option was added in version 2 of this interface.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>persist_mode u</term>
|
||||
<listitem><para>
|
||||
How this session should persist. Default is 0. Accepted values are:
|
||||
|
||||
<simplelist>
|
||||
<member>0: Do not persist (default)</member>
|
||||
<member>1: Permissions persist as long as the application is running</member>
|
||||
<member>2: Permissions persist until explicitly revoked</member>
|
||||
</simplelist>
|
||||
|
||||
If the permission for the session to persist is granted, a restore token will
|
||||
be returned via the #org.freedesktop.portal.Request::Response signal of the
|
||||
start method used to start the session.
|
||||
|
||||
This option was added in version 2 of this interface.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
For available device types, see the AvailableDeviceTypes property.
|
||||
-->
|
||||
<method name="SelectDevices">
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
|
||||
<arg type="o" name="handle" direction="out"/>
|
||||
</method>
|
||||
<!--
|
||||
Start:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@parent_window: Identifier for the application window, see <link linkend="parent_window">Common Conventions</link>
|
||||
@options: Vardict with optional further information
|
||||
@handle: Object path for the #org.freedesktop.portal.Request object representing this call
|
||||
|
||||
Start the remote desktop session. This will typically result in the portal
|
||||
presenting a dialog letting the user select what to share, including
|
||||
devices and optionally screen content if screen cast sources was
|
||||
selected.
|
||||
|
||||
Supported keys in the @options vardict include:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>handle_token s</term>
|
||||
<listitem><para>
|
||||
A string that will be used as the last element of the @handle. Must be a valid
|
||||
object path element. See the #org.freedesktop.portal.Request documentation for
|
||||
more information about the @handle.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
The following results get returned via the
|
||||
#org.freedesktop.portal.Request::Response signal:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>devices u</term>
|
||||
<listitem><para>
|
||||
A bitmask of the devices selected by the user.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>clipboard_enabled b</term>
|
||||
<listitem><para>
|
||||
A boolean for whether the clipboard was enabled ('true') or not ('false').
|
||||
See the #org.freedesktop.portal.Clipboard documentation for more information.
|
||||
Since version 2.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>restore_token s</term>
|
||||
<listitem><para>
|
||||
The restore token. This token is a single use token that can later
|
||||
be used to restore a session. See
|
||||
org.freedesktop.portal.RemoteDesktop.SelectDevices() for details.
|
||||
|
||||
This response option was added in version 2 of this interface.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
If a screen cast source was selected, the results of the
|
||||
#org.freedesktop.portal.ScreenCast.Start response signal may be
|
||||
included.
|
||||
-->
|
||||
<method name="Start">
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="s" name="parent_window" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QVariantMap"/>
|
||||
<arg type="o" name="handle" direction="out"/>
|
||||
</method>
|
||||
<!--
|
||||
NotifyPointerMotion:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@options: Vardict with optional further information
|
||||
@dx: Relative movement on the x axis
|
||||
@dy: Relative movement on the y axis
|
||||
|
||||
Notify about a new relative pointer motion event. The (dx, dy) vector
|
||||
represents the new pointer position in the streams logical coordinate
|
||||
space.
|
||||
-->
|
||||
<method name="NotifyPointerMotion">
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
|
||||
<arg type="d" name="dx" direction="in"/>
|
||||
<arg type="d" name="dy" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
NotifyPointerMotionAbsolute:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@options: Vardict with optional further information
|
||||
@stream: The PipeWire stream node the coordinate is relative to
|
||||
@x: Pointer motion x coordinate
|
||||
@y: Pointer motion y coordinate
|
||||
|
||||
Notify about a new absolute pointer motion event. The (x, y) position
|
||||
represents the new pointer position in the streams logical coordinate
|
||||
space (see the logical_size stream property in
|
||||
#org.freedesktop.portal.ScreenCast).
|
||||
-->
|
||||
<method name="NotifyPointerMotionAbsolute">
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
|
||||
<arg type="u" name="stream" direction="in"/>
|
||||
<arg type="d" name="x" direction="in"/>
|
||||
<arg type="d" name="y" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
NotifyPointerButton:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@options: Vardict with optional further information
|
||||
@button: The pointer button was pressed or released
|
||||
@state: The new state of the button
|
||||
|
||||
The pointer button is encoded according to Linux Evdev button codes.
|
||||
|
||||
May only be called if POINTER access was provided after starting the
|
||||
session.
|
||||
|
||||
Available button states:
|
||||
<simplelist>
|
||||
<member>0: Released</member>
|
||||
<member>1: Pressed</member>
|
||||
</simplelist>
|
||||
-->
|
||||
<method name="NotifyPointerButton">
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
|
||||
<arg type="i" name="button" direction="in"/>
|
||||
<arg type="u" name="state" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
NotifyPointerAxis:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@options: Vardict with optional further information
|
||||
@dx: Relative axis movement on the x axis
|
||||
@dy: Relative axis movement on the y axis
|
||||
|
||||
The axis movement from a 'smooth scroll' device, such as a touchpad.
|
||||
When applicable, the size of the motion delta should be equivalent to
|
||||
the motion vector of a pointer motion done using the same advice.
|
||||
|
||||
May only be called if POINTER access was provided after starting the
|
||||
session.
|
||||
|
||||
Supported keys in the @options vardict include:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>finish b</term>
|
||||
<listitem><para>
|
||||
If set to true, this is the last axis event in a series, for
|
||||
example as a result of the fingers being lifted from a touchpad
|
||||
after a two-finger scroll. Default is false.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
-->
|
||||
<method name="NotifyPointerAxis">
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
|
||||
<arg type="d" name="dx" direction="in"/>
|
||||
<arg type="d" name="dy" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
NotifyPointerAxisDiscrete:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@options: Vardict with optional further information
|
||||
@axis: The axis that was scrolled
|
||||
@steps: The number of steps scrolled
|
||||
|
||||
May only be called if POINTER access was provided after starting the
|
||||
session.
|
||||
|
||||
Available axes:
|
||||
<simplelist>
|
||||
<member>0: Vertical scroll</member>
|
||||
<member>1: Horizontal scroll</member>
|
||||
</simplelist>
|
||||
-->
|
||||
<method name="NotifyPointerAxisDiscrete">
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
|
||||
<arg type="u" name="axis" direction="in"/>
|
||||
<arg type="i" name="steps" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
NotifyKeyboardKeycode:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@options: Vardict with optional further information
|
||||
@keycode: Keyboard code that was pressed or released
|
||||
@state: New state of keyboard keycode
|
||||
|
||||
May only be called if KEYBOARD access was provided after starting the
|
||||
session.
|
||||
|
||||
Available keyboard keycode states:
|
||||
<simplelist>
|
||||
<member>0: Released</member>
|
||||
<member>1: Pressed</member>
|
||||
</simplelist>
|
||||
-->
|
||||
<method name="NotifyKeyboardKeycode">
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
|
||||
<arg type="i" name="keycode" direction="in"/>
|
||||
<arg type="u" name="state" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
NotifyKeyboardKeysym:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@options: Vardict with optional further information
|
||||
@keysym: Keyboard symbol that was pressed or released
|
||||
@state: New state of keyboard keysym
|
||||
|
||||
May only be called if KEYBOARD access was provided after starting the
|
||||
session.
|
||||
|
||||
Available keyboard keysym states:
|
||||
<simplelist>
|
||||
<member>0: Released</member>
|
||||
<member>1: Pressed</member>
|
||||
</simplelist>
|
||||
-->
|
||||
<method name="NotifyKeyboardKeysym">
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
|
||||
<arg type="i" name="keysym" direction="in"/>
|
||||
<arg type="u" name="state" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
NotifyTouchDown:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@options: Vardict with optional further information
|
||||
@stream: The PipeWire stream node the coordinate is relative to
|
||||
@slot: Touch slot where touch point appeared
|
||||
@x: Touch down x coordinate
|
||||
@y: Touch down y coordinate
|
||||
|
||||
May only be called if TOUCHSCREEN access was provided after starting the
|
||||
session.
|
||||
|
||||
Notify about a new touch down event. The (x, y) position
|
||||
represents the new touch point position in the streams logical
|
||||
coordinate space (see the logical_size stream property in
|
||||
#org.freedesktop.portal.ScreenCast).
|
||||
-->
|
||||
<method name="NotifyTouchDown">
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
|
||||
<arg type="u" name="stream" direction="in"/>
|
||||
<arg type="u" name="slot" direction="in"/>
|
||||
<arg type="d" name="x" direction="in"/>
|
||||
<arg type="d" name="y" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
NotifyTouchMotion:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@options: Vardict with optional further information
|
||||
@stream: The PipeWire stream node the coordinate is relative to
|
||||
@slot: Touch slot where touch point appeared
|
||||
@x: Touch motion x coordinate
|
||||
@y: Touch motion y coordinate
|
||||
|
||||
May only be called if TOUCHSCREEN access was provided after starting the
|
||||
session.
|
||||
|
||||
Notify about a new touch motion event. The (x, y) position
|
||||
represents where the touch point position in the streams logical
|
||||
coordinate space moved (see the logical_size stream property in
|
||||
#org.freedesktop.portal.ScreenCast).
|
||||
-->
|
||||
<method name="NotifyTouchMotion">
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
|
||||
<arg type="u" name="stream" direction="in"/>
|
||||
<arg type="u" name="slot" direction="in"/>
|
||||
<arg type="d" name="x" direction="in"/>
|
||||
<arg type="d" name="y" direction="in"/>
|
||||
</method>
|
||||
<!--
|
||||
NotifyTouchUp:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@options: Vardict with optional further information
|
||||
@slot: Touch slot where touch point appeared
|
||||
|
||||
May only be called if TOUCHSCREEN access was provided after starting the
|
||||
session.
|
||||
|
||||
Notify about a new touch up event.
|
||||
-->
|
||||
<method name="NotifyTouchUp">
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
|
||||
<arg type="u" name="slot" direction="in"/>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
ConnectToEIS:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@options: Vardict with optional further information
|
||||
@fd: A file descriptor to an EIS implementation that can be passed to a libei sender context
|
||||
|
||||
Request a connection to an EIS implementation. The returned handle can
|
||||
be passed to ei_setup_backend_fd() for a libei sender context to
|
||||
complete the connection. All information about available devices and the
|
||||
event flow is subject to libei. Please see the libei documentation for details.
|
||||
|
||||
This method may only be called once per session, where the EIS
|
||||
implementation disconnects the session should be closed.
|
||||
|
||||
This method must be called after #org.freedesktop.portal.RemoteDesktop.Start()
|
||||
|
||||
Once an EIS connection is established, input events must be sent exclusively via
|
||||
the EIS connection. Any events submitted via NotifyPointerMotion,
|
||||
NotifyKeyboardKeycode and other Notify* methods will return an error.
|
||||
|
||||
To see how to pair a PipeWire stream with a libei device region, see the
|
||||
documentation for the mapping_id stream property in
|
||||
#org.freedesktop.portal.RemoteDesktop.Start().
|
||||
|
||||
This method was added in version 2 of this interface.
|
||||
-->
|
||||
<method name="ConnectToEIS">
|
||||
<annotation name="org.gtk.GDBus.C.Name" value="connect_to_eis"/>
|
||||
<annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
|
||||
<arg type="h" name="fd" direction="out"/>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
AvailableDeviceTypes:
|
||||
|
||||
A bitmask of available source types. Currently defined types are:
|
||||
|
||||
<simplelist>
|
||||
<member>1: KEYBOARD</member>
|
||||
<member>2: POINTER</member>
|
||||
<member>4: TOUCHSCREEN</member>
|
||||
</simplelist>
|
||||
-->
|
||||
<property name="AvailableDeviceTypes" type="u" access="read"/>
|
||||
<property name="version" type="u" access="read"/>
|
||||
</interface>
|
||||
</node>
|
||||
186
dbus/xdp_dbus_screencast_interface.xml
Normal file
@@ -0,0 +1,186 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Copyright (C) 2017-2018 Red Hat, Inc.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
|
||||
<!--
|
||||
org.freedesktop.portal.ScreenCast:
|
||||
@short_description: Screen cast portal
|
||||
-->
|
||||
<interface name="org.freedesktop.portal.ScreenCast">
|
||||
<!--
|
||||
CreateSession:
|
||||
@options: Vardict with optional further information
|
||||
@handle: Object path for the #org.freedesktop.portal.Request object representing this call
|
||||
|
||||
Create a screen cast session. A successfully created session can at
|
||||
any time be closed using org.freedesktop.portal.Session::Close, or may
|
||||
at any time be closed by the portal implementation, which will be
|
||||
signalled via org.freedesktop.portal.Session::Closed.
|
||||
|
||||
The following results get returned via the #org.freedesktop.portal.Request::Response signal:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>session_handle o</term>
|
||||
<listitem><para>
|
||||
The session handle. An object path for the
|
||||
#org.freedesktop.portal.Session object representing the created
|
||||
session.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
-->
|
||||
<method name="CreateSession">
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
|
||||
<arg type="o" name="handle" direction="out"/>
|
||||
</method>
|
||||
<!--
|
||||
SelectSources:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@options: Vardict with optional further information
|
||||
@handle: Object path for the #org.freedesktop.portal.Request object representing this call
|
||||
|
||||
Configure what the screen cast session should record. This method must
|
||||
be called before starting the session.
|
||||
|
||||
Passing invalid input to this method will cause the session to be
|
||||
closed. An application may only attempt to select sources once per
|
||||
session.
|
||||
|
||||
Supported keys in the @options vardict include:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>types u</term>
|
||||
<listitem><para>
|
||||
Bitmask of what types of content to record. Default is MONITOR.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>multiple b</term>
|
||||
<listitem><para>
|
||||
Whether to allow selecting multiple sources. Default is no.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
For available source types, see the AvailableSourceTypes property.
|
||||
-->
|
||||
<method name="SelectSources">
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
|
||||
<arg type="o" name="handle" direction="out"/>
|
||||
</method>
|
||||
<!--
|
||||
Start:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@parent_window: Identifier for the application window
|
||||
@options: Vardict with optional further information
|
||||
@handle: Object path for the #org.freedesktop.portal.Request object representing this call
|
||||
|
||||
Start the screen cast session. This will typically result the portal
|
||||
presenting a dialog letting the user do the selection set up by
|
||||
SelectSources. An application can only attempt start a session once.
|
||||
|
||||
A screen cast session may only be started after having selected sources
|
||||
using org.freedesktop.portal.ScreenCast::SelectSources.
|
||||
|
||||
The @parent_window identifier must be of the form "x11:$XID" for an X11
|
||||
window. Support for other window systems may be added in the future.
|
||||
|
||||
The following results get returned via the
|
||||
#org.freedesktop.portal.Request::Response signal:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>streams a(ua{sv})</term>
|
||||
<listitem><para>
|
||||
An array of PipeWire streams. Each stream consists of a PipeWire
|
||||
node ID (the first element in the tuple, and a Vardict of
|
||||
properties.
|
||||
|
||||
The array will contain a single stream if 'multiple' (see
|
||||
SelectSources) was set to 'false', or at least one stream if
|
||||
'multiple' was set to 'true' as part of the SelectSources method.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
Stream properties include:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>position (ii)</term>
|
||||
<listitem><para>
|
||||
A tuple consisting of the position (x, y) in the compositor
|
||||
coordinate space. Note that the position may not be equivalent to a
|
||||
position in a pixel coordinate space. Only available for monitor
|
||||
streams.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>size (ii)</term>
|
||||
<listitem><para>
|
||||
A tuple consisting of (width, height). The size represents the size
|
||||
of the stream as it is displayed in the compositor coordinate
|
||||
space. Note that this size may not be equivalent to a size in a
|
||||
pixel coordinate space. The size may differ from the size of the
|
||||
stream.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
-->
|
||||
<method name="Start">
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="s" name="parent_window" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QVariantMap"/>
|
||||
<arg type="o" name="handle" direction="out"/>
|
||||
</method>
|
||||
<!--
|
||||
OpenPipeWireRemote:
|
||||
@session_handle: Object path for the #org.freedesktop.portal.Session object
|
||||
@options: Vardict with optional further information
|
||||
@fd: File descriptor of an open PipeWire remote.
|
||||
|
||||
Open a file descriptor to the PipeWire remote where the screen cast
|
||||
streams are available. The file descriptor should be used to create a
|
||||
<classname>pw_remote</classname> object, by using
|
||||
<function>pw_remote_connect_fd</function>. Only the screen cast stream
|
||||
nodes will be available from this PipeWire node.
|
||||
-->
|
||||
<method name="OpenPipeWireRemote">
|
||||
<annotation name="org.gtk.GDBus.C.Name" value="open_pipewire_remote"/>
|
||||
<annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
|
||||
<arg type="o" name="session_handle" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
|
||||
<arg type="h" name="fd" direction="out"/>
|
||||
</method>
|
||||
<!--
|
||||
AvailableSourceTypes:
|
||||
|
||||
A bitmask of available source types. Currently defined types are:
|
||||
|
||||
<simplelist>
|
||||
<member>1: MONITOR</member>
|
||||
<member>2: WINDOW</member>
|
||||
</simplelist>
|
||||
-->
|
||||
<property name="AvailableSourceTypes" type="u" access="read"/>
|
||||
<property name="version" type="u" access="read"/>
|
||||
</interface>
|
||||
</node>
|
||||
@@ -1,2 +1,2 @@
|
||||
########### install files ###############
|
||||
kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/en SUBDIR krfb)
|
||||
kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR krfb)
|
||||
|
||||
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 45 KiB |
@@ -1,22 +1,11 @@
|
||||
<?xml version="1.0" ?>
|
||||
<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN" "dtd/kdedbx45.dtd" [
|
||||
<!ENTITY kappname "&krfb;">
|
||||
<!ENTITY package "kdenetwork">
|
||||
<!ENTITY % addindex "IGNORE">
|
||||
<!ENTITY % English "INCLUDE"> <!-- ONLY If you are writing non-English
|
||||
original documentation, change
|
||||
the language here -->
|
||||
|
||||
<!-- Do not define any other entities; instead, use the entities
|
||||
from entities/general.entities and $LANG/user.entities. -->
|
||||
<!ENTITY % English "INCLUDE">
|
||||
]>
|
||||
<!-- Based on kdoctemplate v0.9 January 10 2003 -->
|
||||
|
||||
<book id="krfb" lang="&language;">
|
||||
|
||||
<!-- This header contains all of the meta-information for the document such
|
||||
as Authors, publish date, the abstract, and Keywords -->
|
||||
|
||||
<bookinfo>
|
||||
<title>The &krfb; Handbook</title>
|
||||
|
||||
@@ -32,21 +21,11 @@ as Authors, publish date, the abstract, and Keywords -->
|
||||
<year>2003</year>
|
||||
<holder>&Brad.Hards;</holder>
|
||||
</copyright>
|
||||
<!-- Translators: put here the copyright notice of the translation -->
|
||||
|
||||
<legalnotice>&FDLNotice;</legalnotice>
|
||||
|
||||
<!-- Date and version information of the documentation
|
||||
Don't forget to include this last date and this last revision number, we
|
||||
need them for translation coordination !
|
||||
Please respect the format of the date (YYYY-MM-DD) and of the version
|
||||
(V.MM.LL), it could be used by automation scripts.
|
||||
Do NOT change these in the translation. -->
|
||||
|
||||
<date>2013-06-19</date>
|
||||
<releaseinfo>&kde; 4.11</releaseinfo>
|
||||
|
||||
<!-- Abstract about this handbook -->
|
||||
<date>2016-07-25</date>
|
||||
<releaseinfo>5.0 (Applications 16.08)</releaseinfo>
|
||||
|
||||
<abstract>
|
||||
<para>
|
||||
@@ -56,10 +35,6 @@ view or even control the desktop.
|
||||
</para>
|
||||
</abstract>
|
||||
|
||||
<!-- This is a set of Keywords for indexing by search engines.
|
||||
Please at least include KDE, the KDE package it is in, the name
|
||||
of your application, and a few relevant keywords. -->
|
||||
|
||||
<keywordset>
|
||||
<keyword>KDE</keyword>
|
||||
<keyword>kdenetwork</keyword>
|
||||
@@ -75,23 +50,9 @@ Please at least include KDE, the KDE package it is in, the name
|
||||
|
||||
</bookinfo>
|
||||
|
||||
<!-- The contents of the documentation begin here. Label
|
||||
each chapter so with the id attribute. This is necessary for two reasons: it
|
||||
allows you to easily reference the chapter from other chapters of your
|
||||
document, and if there is no ID, the name of the generated HTML files will vary
|
||||
from time to time making it hard to manage for maintainers and for the CVS
|
||||
system. Any chapter labelled (OPTIONAL) may be left out at the author's
|
||||
discretion. Other chapters should not be left out in order to maintain a
|
||||
consistent documentation style across all KDE apps. -->
|
||||
|
||||
<chapter id="introduction">
|
||||
<title>Introduction</title>
|
||||
|
||||
<!-- The introduction chapter contains a brief introduction for the
|
||||
application that explains what it does and where to report
|
||||
problems. Basically a long version of the abstract. Don't include a
|
||||
revision history. (see installation appendix comment) -->
|
||||
|
||||
<para>
|
||||
&krfb; is a server application that allows you to share your current
|
||||
session with a user on another machine, who can use a <acronym>VNC</acronym> client to
|
||||
@@ -112,7 +73,7 @@ to help you perform a task.
|
||||
<para>
|
||||
Please report any problems or feature requests to the &kde; mailing
|
||||
lists or file a bug at <ulink
|
||||
url="http://bugs.kde.org">http://bugs.kde.org</ulink>.
|
||||
url="https://bugs.kde.org">https://bugs.kde.org</ulink>.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
@@ -165,10 +126,8 @@ use &krfb; over other links, but performance is unlikely to be as good.
|
||||
<chapter id="using-krfb">
|
||||
<title>Using &krfb;</title>
|
||||
|
||||
<!-- This chapter should tell the user how to use your app. You should use as
|
||||
many sections (Chapter, Sect1, Sect3, etc...) as is necessary to fully document
|
||||
your application. -->
|
||||
|
||||
<sect1 id="main-windw">
|
||||
<title>&krfb; Main Window</title>
|
||||
<para>
|
||||
It is very easy to use &krfb; - it has a simple interface, as shown in
|
||||
the screenshot below.
|
||||
@@ -189,64 +148,69 @@ the screenshot below.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When you want to allow someone to access your desktop, you can create
|
||||
an personal invitation using the <guibutton>New Personal
|
||||
Invitation...</guibutton> button, which will bring up a window
|
||||
containing the information needed to access your desktop. An example
|
||||
is shown below.
|
||||
When you want to allow someone to access your desktop, you have to
|
||||
enable the checkbox <guilabel>Enable Desktop Sharing</guilabel>,
|
||||
which will start the server.
|
||||
</para>
|
||||
|
||||
<sect2 id="connection-details">
|
||||
<title>Connection Details</title>
|
||||
|
||||
<para>
|
||||
The <guilabel>Address</guilabel> contains the address of your
|
||||
computer and the port number, separated by a colon.
|
||||
The address is just a hint - you can use any address that can
|
||||
reach your computer. &krfb; tries to guess your address from your
|
||||
network configuration, but does not always succeed in doing so.
|
||||
If your computer is behind a firewall it may have a different
|
||||
address or be unreachable for other computers.
|
||||
</para>
|
||||
<para>
|
||||
You can change the port on the <guilabel>Network</guilabel>
|
||||
page in the configuration dialog.
|
||||
</para>
|
||||
<para>
|
||||
The next field is prefilled with an automatically generated password.
|
||||
Click in the icon at the right of the field to change the password.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="unattended-access">
|
||||
<title>Unattended Access</title>
|
||||
|
||||
<para>
|
||||
Any remote user with the desktop sharing password will have to be authenticated.
|
||||
If unattended access is activated, and the remote user provides the password
|
||||
for unattended mode, desktop sharing access will be granted without explicit
|
||||
confirmation.
|
||||
</para>
|
||||
<para>
|
||||
By default the password for this mode is empty, to change that click on
|
||||
the button and enter a password.
|
||||
</para>
|
||||
<para>
|
||||
If unattended access is allowed, then you should probably specify a
|
||||
password.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<screenshot>
|
||||
<screeninfo>Example &krfb; personal invitation</screeninfo>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="personal_invitation.png" format="PNG"/>
|
||||
</imageobject>
|
||||
<textobject>
|
||||
<phrase>Example &krfb; personal invitation</phrase>
|
||||
</textobject>
|
||||
</mediaobject>
|
||||
</screenshot>
|
||||
If the machine is a server and you are using &krfb; for remote
|
||||
administration, you probably want to use unattended access.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To increase security, the invitation is only valid for an
|
||||
hour after it is created, and of course the person connecting has to
|
||||
have the correct password.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="transfer-login-information">
|
||||
<title>Transfer Login Information</title>
|
||||
|
||||
<para>
|
||||
Since you may want to invite someone to access your desktop by email,
|
||||
&krfb; can create invitations as email messages. You can create such
|
||||
an invitation using the <guibutton>New Email Invitation...</guibutton>
|
||||
button on the &krfb; main window. This will usually bring up an email
|
||||
message that looks like the following, ready for you to type in the
|
||||
email address of the person you are sending the invitation to.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<screenshot>
|
||||
<screeninfo>Example &krfb; email invitation</screeninfo>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="email_invitation.png" format="PNG"/>
|
||||
</imageobject>
|
||||
<textobject>
|
||||
<phrase>Example &krfb; email invitation</phrase>
|
||||
</textobject>
|
||||
</mediaobject>
|
||||
</screenshot>
|
||||
</para>
|
||||
|
||||
<warning>
|
||||
<para>
|
||||
&krfb; will warn you about the security implications of sending this
|
||||
information across an insecure link. You must heed those warnings.
|
||||
&krfb; has no invitation feature any more as in previous versions.
|
||||
So you have to transfer the login information yourself using email
|
||||
or a personal invitation.
|
||||
</para>
|
||||
<para>
|
||||
If you cannot encrypt the email (or otherwise secure the link),
|
||||
sending invitations by email is a very serious security risk, since
|
||||
sending a password by email is a very serious security risk, since
|
||||
anyone can read the password and address from the email as it passes
|
||||
over the network. This means that they can potentially take control of
|
||||
your machine.
|
||||
@@ -255,33 +219,32 @@ your machine.
|
||||
If you cannot encrypt the email message, it may be better to use a
|
||||
personal invitation, telephone the person you are giving access to,
|
||||
verify the identity of that person, and provide the required
|
||||
invitation information that way.
|
||||
information that way.
|
||||
</para>
|
||||
</warning>
|
||||
|
||||
<sect1 id="krfb-managing-invitations">
|
||||
<title>Managing &krfb; invitations</title>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Having created an invitation (either a personal invitation or one that
|
||||
was sent by email), &krfb; main window allows you to delete existing
|
||||
invitations. To just delete one of the invitations, select it with the
|
||||
mouse (it should become highlighted), and then select
|
||||
the <guibutton>Delete</guibutton>. To delete all invitations, just
|
||||
select the <guibutton>Delete All</guibutton> button.
|
||||
&krfb; uses the normal <acronym>RFB</acronym> password system, which does not transfer
|
||||
your password in the clear across the network. Instead, it uses a
|
||||
challenge-response system. This is reasonably secure, as long as the
|
||||
password is securely guarded.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
</sect1>
|
||||
</sect2>
|
||||
|
||||
<sect1 id="krfb-qit">
|
||||
<sect2 id="krfb-qqit">
|
||||
<title>Quit &krfb;</title>
|
||||
|
||||
<para>
|
||||
If you close the &krfb; main window the server keeps running, which is
|
||||
indicated by an icon in the system tray.
|
||||
To stop &krfb; right click on the icon in the systems tray and select
|
||||
If you close the &krfb; main window by clicking on the window close icon or using the
|
||||
shortcut <keycombo action="simul">&Alt;<keycap>F4</keycap></keycombo> the server
|
||||
keeps running, which is indicated by an icon in the system tray.
|
||||
To stop &krfb; either use <menuchoice><guimenu>File</guimenu><guimenuitem>Quit</guimenuitem></menuchoice>
|
||||
in the main window or right click on the icon in the system tray and select
|
||||
<guimenuitem>Quit</guimenuitem>.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
|
||||
@@ -290,7 +253,7 @@ To stop &krfb; right click on the icon in the systems tray and select
|
||||
<para>
|
||||
In addition to the main &krfb; interface shown and described above,
|
||||
you can also control &krfb; using the
|
||||
<guibutton>Configure...</guibutton> on the &krfb; main window. The &krfb;
|
||||
<guimenuitem>Configure...</guimenuitem> on the &krfb; main window. The &krfb;
|
||||
configuration has two pages, as shown in the screenshot below:
|
||||
</para>
|
||||
|
||||
@@ -314,8 +277,8 @@ The <guilabel>Network</guilabel> page allows control over the port that
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <guilabel>Announce service on the network</guilabel> checkbox
|
||||
controls whether &krfb; announces invitations over the network using
|
||||
The <guilabel>Announce service on the local network</guilabel> checkbox
|
||||
controls whether &krfb; announces the service over the local network using
|
||||
Service Location Protocol. This is normally a good idea, but only
|
||||
works really well with a Service Location Protocol aware client, such
|
||||
as &krdc;.
|
||||
@@ -323,8 +286,8 @@ as &krdc;.
|
||||
|
||||
<para>
|
||||
If you select the <guilabel>Use default port</guilabel> checkbox,
|
||||
then &krfb; will locate a suitable port, and invitations will match
|
||||
this port. If you deselect this checkbox, you can specify a particular
|
||||
then &krfb; will locate a suitable port.
|
||||
If you deselect this checkbox, you can specify a particular
|
||||
port. Specifying a particular port may be useful if you are using
|
||||
port-forwarding on the firewall. Note that if Service Location
|
||||
Protocol is turned on, this will automatically deal with identifying
|
||||
@@ -332,8 +295,8 @@ the correct port.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <guilabel>Security</guilabel> page allows you configure settings
|
||||
related to access to the &krfb; server.
|
||||
The <guilabel>Security</guilabel> page allows you to configure whether the
|
||||
person connecting to the &krfb; server can control the desktop, or only view.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -350,41 +313,15 @@ related to access to the &krfb; server.
|
||||
</screenshot>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <guilabel>Allow uninvited connections</guilabel> check box controls
|
||||
whether &krfb; allows connection without an invitation. If uninvited
|
||||
connections are allowed, then you should probably specify a
|
||||
password. You can also use the check boxes here to choose whether you
|
||||
have to confirm the connection before it proceeds, and whether the
|
||||
person connecting can control the desktop, or only view.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If the machine is a workstation, and you choose to allow uninvited
|
||||
connections, you probably want to select the <guilabel>Ask
|
||||
before accepting connections </guilabel>. Conversely, if the
|
||||
machine is a server and you are using &krfb; for remote
|
||||
administration, you probably want to deselect this option.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
&krfb; uses the normal <acronym>RFB</acronym> password system, which does not transfer
|
||||
your password in the clear across the network. Instead, it uses a
|
||||
challenge-response system. This is reasonably secure, as long as the
|
||||
password is securely guarded.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="krfb-connection">
|
||||
<title>What happens when someone connects to &krfb;</title>
|
||||
<title>Connecting to &krfb;</title>
|
||||
|
||||
<para>
|
||||
When someone connects to &krfb; on your machine, you will get a pop-up
|
||||
notification that looks like the following screenshot, unless you are
|
||||
accepting uninvited connections without warning.
|
||||
accepting unattended access without confirmation.
|
||||
</para>
|
||||
<para>
|
||||
<screenshot>
|
||||
@@ -402,8 +339,8 @@ accepting uninvited connections without warning.
|
||||
|
||||
<para>
|
||||
If you <guibutton>Accept Connection</guibutton>, the client can
|
||||
proceed to authenticate (which requires the correct password for a
|
||||
personal invitation or email invitation). If you <guibutton>Refuse
|
||||
proceed to authenticate, which requires the correct password for a
|
||||
login. If you <guibutton>Refuse
|
||||
Connection</guibutton>, then the attempt to connect will be terminated.
|
||||
</para>
|
||||
|
||||
@@ -413,23 +350,11 @@ mouse</guilabel> check box determines whether this client can only
|
||||
observe, or can take control of your machine.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If the client connection is successful, and used the password from a
|
||||
personal invitation or email invitation, then that invitation is
|
||||
deleted and cannot be used again. You will also get a small pop-up
|
||||
window in the dock, that shows that the connection has been made.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="credits">
|
||||
|
||||
<!-- Include credits for the programmers, documentation writers, and
|
||||
contributors here. The license for your software should then be included below
|
||||
the credits with a reference to the appropriate license file included in the KDE
|
||||
distribution. -->
|
||||
|
||||
<title>Credits and License</title>
|
||||
|
||||
<para>
|
||||
@@ -458,33 +383,6 @@ Documentation Copyright © 2003 &Brad.Hards; &Brad.Hards.mail;
|
||||
|
||||
</chapter>
|
||||
|
||||
<appendix id="installation">
|
||||
<title>Installation</title>
|
||||
|
||||
<sect1 id="getting-krfb">
|
||||
<title>How to obtain &krfb;</title>
|
||||
|
||||
<!-- This first entity contains boiler plate for applications that are
|
||||
part of KDE CVS. You should remove it if you are releasing your
|
||||
application -->
|
||||
|
||||
&install.intro.documentation;
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="compilation">
|
||||
<title>Compilation and Installation</title>
|
||||
|
||||
<!-- This entity contains the boilerplate text for standard -->
|
||||
<!-- compilation instructions. If your application requires any -->
|
||||
<!-- special handling, remove it, and replace with your own text. -->
|
||||
|
||||
&install.compile.documentation;
|
||||
|
||||
</sect1>
|
||||
|
||||
</appendix>
|
||||
|
||||
&documentation.index;
|
||||
</book>
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 33 KiB |
6
events/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
add_subdirectory(x11)
|
||||
|
||||
# Makes sense to use only when PW framebuffer is used
|
||||
if (TARGET K::KPipeWire)
|
||||
add_subdirectory(xdp)
|
||||
endif()
|
||||
19
events/x11/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
set (krfb_events_x11_SRCS
|
||||
x11events.cpp
|
||||
x11eventsplugin.cpp
|
||||
)
|
||||
|
||||
add_library (krfb_events_x11 MODULE ${krfb_events_x11_SRCS})
|
||||
|
||||
target_link_libraries (krfb_events_x11
|
||||
${X11_XTest_LIB}
|
||||
KF6::CoreAddons
|
||||
krfbprivate
|
||||
)
|
||||
set_target_properties(krfb_events_x11 PROPERTIES OUTPUT_NAME x11)
|
||||
|
||||
install (TARGETS krfb_events_x11 DESTINATION ${KDE_INSTALL_PLUGINDIR}/krfb/events)
|
||||
191
events/x11/x11events.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
|
||||
SPDX-FileCopyrightText: 2016 Oleg Chernovskiy <kanedias@xaker.ru>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "x11events.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QGlobalStatic>
|
||||
#include <QtGui/private/qtx11extras_p.h>
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
#include <X11/keysym.h>
|
||||
|
||||
enum {
|
||||
LEFTSHIFT = 1,
|
||||
RIGHTSHIFT = 2,
|
||||
ALTGR = 4,
|
||||
};
|
||||
|
||||
class EventData
|
||||
{
|
||||
public:
|
||||
EventData();
|
||||
|
||||
// keyboard
|
||||
Display *dpy = nullptr;
|
||||
signed char modifiers[0x100] = {};
|
||||
KeyCode keycodes[0x100] = {};
|
||||
KeyCode leftShiftCode = 0;
|
||||
KeyCode rightShiftCode = 0;
|
||||
KeyCode altGrCode = 0;
|
||||
char modifierState = 0;
|
||||
|
||||
// mouse
|
||||
int buttonMask = 0;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
private:
|
||||
void init();
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(EventData, data)
|
||||
|
||||
EventData::EventData()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void EventData::init()
|
||||
{
|
||||
buttonMask = 0;
|
||||
|
||||
dpy = QX11Info::display();
|
||||
// initialize keycodes
|
||||
KeySym key, *keymap;
|
||||
int i, j, minkey, maxkey, syms_per_keycode;
|
||||
|
||||
memset(modifiers, -1, sizeof(modifiers));
|
||||
|
||||
XDisplayKeycodes(dpy, &minkey, &maxkey);
|
||||
Q_ASSERT(minkey >= 8);
|
||||
Q_ASSERT(maxkey < 256);
|
||||
keymap = (KeySym *)XGetKeyboardMapping(dpy, minkey,
|
||||
(maxkey - minkey + 1),
|
||||
&syms_per_keycode);
|
||||
Q_ASSERT(keymap);
|
||||
|
||||
for (i = minkey; i <= maxkey; i++) {
|
||||
for (j = 0; j < syms_per_keycode; j++) {
|
||||
key = keymap[(i - minkey) * syms_per_keycode + j];
|
||||
|
||||
if (key >= ' ' && key < 0x100 && i == XKeysymToKeycode(dpy, key)) {
|
||||
keycodes[key] = i;
|
||||
modifiers[key] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leftShiftCode = XKeysymToKeycode(dpy, XK_Shift_L);
|
||||
rightShiftCode = XKeysymToKeycode(dpy, XK_Shift_R);
|
||||
altGrCode = XKeysymToKeycode(dpy, XK_Mode_switch);
|
||||
|
||||
XFree((char *)keymap);
|
||||
}
|
||||
|
||||
/* this function adjusts the modifiers according to mod (as from modifiers) and data->modifierState */
|
||||
static void tweakModifiers(signed char mod, bool down)
|
||||
{
|
||||
bool isShift = data->modifierState & (LEFTSHIFT | RIGHTSHIFT);
|
||||
|
||||
if (mod < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isShift && mod != 1) {
|
||||
if (data->modifierState & LEFTSHIFT) {
|
||||
XTestFakeKeyEvent(data->dpy, data->leftShiftCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
|
||||
if (data->modifierState & RIGHTSHIFT) {
|
||||
XTestFakeKeyEvent(data->dpy, data->rightShiftCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isShift && mod == 1) {
|
||||
XTestFakeKeyEvent(data->dpy, data->leftShiftCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
|
||||
if ((data->modifierState & ALTGR) && mod != 2) {
|
||||
XTestFakeKeyEvent(data->dpy, data->altGrCode,
|
||||
!down, CurrentTime);
|
||||
}
|
||||
|
||||
if (!(data->modifierState & ALTGR) && mod == 2) {
|
||||
XTestFakeKeyEvent(data->dpy, data->altGrCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
void X11EventHandler::handleKeyboard(bool down, rfbKeySym keySym)
|
||||
{
|
||||
#define ADJUSTMOD(sym, state) \
|
||||
if (keySym == sym) { \
|
||||
if (down) \
|
||||
data->modifierState |= state; \
|
||||
else \
|
||||
data->modifierState &= ~state; \
|
||||
}
|
||||
|
||||
if (QX11Info::isPlatformX11()) {
|
||||
ADJUSTMOD(XK_Shift_L, LEFTSHIFT);
|
||||
ADJUSTMOD(XK_Shift_R, RIGHTSHIFT);
|
||||
ADJUSTMOD(XK_Mode_switch, ALTGR);
|
||||
|
||||
if (keySym >= ' ' && keySym < 0x100) {
|
||||
KeyCode k;
|
||||
|
||||
if (down) {
|
||||
tweakModifiers(data->modifiers[keySym], True);
|
||||
}
|
||||
|
||||
k = data->keycodes[keySym];
|
||||
|
||||
if (k != NoSymbol) {
|
||||
XTestFakeKeyEvent(data->dpy, k, down, CurrentTime);
|
||||
}
|
||||
|
||||
if (down) {
|
||||
tweakModifiers(data->modifiers[keySym], False);
|
||||
}
|
||||
} else {
|
||||
KeyCode k = XKeysymToKeycode(data->dpy, keySym);
|
||||
|
||||
if (k != NoSymbol) {
|
||||
XTestFakeKeyEvent(data->dpy, k, down, CurrentTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
// Wayland platform and pipweire plugin in use
|
||||
if (KrfbConfig::preferredFrameBufferPlugin() == QStringLiteral("pw")) {
|
||||
|
||||
}*/
|
||||
}
|
||||
|
||||
void X11EventHandler::handlePointer(int buttonMask, int x, int y)
|
||||
{
|
||||
if (QX11Info::isPlatformX11()) {
|
||||
XTestFakeMotionEvent(data->dpy, 0, x, y, CurrentTime);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if ((data->buttonMask & (1 << i)) != (buttonMask & (1 << i))) {
|
||||
XTestFakeButtonEvent(data->dpy,
|
||||
i + 1,
|
||||
(buttonMask & (1 << i)) ? True : False,
|
||||
CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
data->buttonMask = buttonMask;
|
||||
}
|
||||
}
|
||||
28
events/x11/x11events.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
|
||||
SPDX-FileCopyrightText: 2016 Oleg Chernovskiy <kanedias@xaker.ru>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef EVENTS_X11EVENTS_H
|
||||
#define EVENTS_X11EVENTS_H
|
||||
|
||||
#include "../../krfb/events.h"
|
||||
|
||||
class X11EventHandler : public EventHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit X11EventHandler(QObject *parent = nullptr)
|
||||
: EventHandler(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void handleKeyboard(bool down, rfbKeySym key) override;
|
||||
void handlePointer(int buttonMask, int x, int y) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
32
events/x11/x11eventsplugin.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2016 Oleg Chernovskiy <kanedias@xaker.ru>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "x11eventsplugin.h"
|
||||
|
||||
#include "x11events.h"
|
||||
|
||||
#include <KPluginFactory>
|
||||
|
||||
#include <QtGui/private/qtx11extras_p.h>
|
||||
|
||||
K_PLUGIN_CLASS(X11EventsPlugin)
|
||||
|
||||
X11EventsPlugin::X11EventsPlugin(QObject *parent, const QVariantList &args)
|
||||
: EventsPlugin(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
EventHandler *X11EventsPlugin::eventHandler()
|
||||
{
|
||||
// works only under X11
|
||||
if (!QX11Info::isPlatformX11()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new X11EventHandler();
|
||||
}
|
||||
|
||||
#include "x11eventsplugin.moc"
|
||||
29
events/x11/x11eventsplugin.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2016 Oleg Chernovskiy <kanedias@xaker.ru>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KRFB_EVENTS_X11_X11EVENTSPLUGIN_H
|
||||
#define KRFB_EVENTS_X11_X11EVENTSPLUGIN_H
|
||||
|
||||
#include "eventsplugin.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class EventHandler;
|
||||
|
||||
class X11EventsPlugin : public EventsPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
X11EventsPlugin(QObject *parent, const QVariantList &args);
|
||||
|
||||
EventHandler *eventHandler() override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(X11EventsPlugin)
|
||||
};
|
||||
|
||||
#endif // Header guard
|
||||
28
events/xdp/CMakeLists.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
set (krfb_events_xdp_SRCS
|
||||
xdpevents.cpp
|
||||
xdpeventsplugin.cpp
|
||||
)
|
||||
|
||||
qt_add_dbus_interface(
|
||||
krfb_events_xdp_SRCS
|
||||
${CMAKE_SOURCE_DIR}/dbus/xdp_dbus_remotedesktop_interface.xml
|
||||
xdp_dbus_remotedesktop_interface
|
||||
)
|
||||
|
||||
add_library (krfb_events_xdp MODULE ${krfb_events_xdp_SRCS})
|
||||
|
||||
target_link_libraries (krfb_events_xdp
|
||||
KF6::CoreAddons
|
||||
KF6::I18n
|
||||
Qt::DBus
|
||||
krfbprivate
|
||||
)
|
||||
set_target_properties(krfb_events_xdp PROPERTIES OUTPUT_NAME xdp)
|
||||
|
||||
install (TARGETS krfb_events_xdp
|
||||
DESTINATION ${KDE_INSTALL_PLUGINDIR}/krfb/events
|
||||
)
|
||||
108
events/xdp/xdpevents.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
|
||||
SPDX-FileCopyrightText: 2018-2019 Jan Grulich <jgrulich@redhat.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "xdpevents.h"
|
||||
|
||||
#include "rfbservermanager.h"
|
||||
#include "xdp_dbus_remotedesktop_interface.h"
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QGlobalStatic>
|
||||
|
||||
class EventData
|
||||
{
|
||||
public:
|
||||
EventData();
|
||||
|
||||
// mouse
|
||||
int buttonMask = 0;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
QScopedPointer<OrgFreedesktopPortalRemoteDesktopInterface> dbusXdpRemoteDesktopService;
|
||||
|
||||
private:
|
||||
void init();
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(EventData, data)
|
||||
|
||||
EventData::EventData()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void EventData::init()
|
||||
{
|
||||
dbusXdpRemoteDesktopService.reset(new OrgFreedesktopPortalRemoteDesktopInterface(QStringLiteral("org.freedesktop.portal.Desktop"),
|
||||
QStringLiteral("/org/freedesktop/portal/desktop"), QDBusConnection::sessionBus()));
|
||||
}
|
||||
|
||||
void XdpEventHandler::handleKeyboard(bool down, rfbKeySym keySym)
|
||||
{
|
||||
const QDBusObjectPath sessionHandle = frameBuffer()->customProperty(QStringLiteral("session_handle")).value<QDBusObjectPath>();
|
||||
data->dbusXdpRemoteDesktopService->NotifyKeyboardKeysym(sessionHandle, {}, keySym, down);
|
||||
}
|
||||
|
||||
void XdpEventHandler::handlePointer(int buttonMask, int x, int y)
|
||||
{
|
||||
const uint streamNodeId = frameBuffer()->customProperty(QStringLiteral("stream_node_id")).toUInt();
|
||||
const QDBusObjectPath sessionHandle = frameBuffer()->customProperty(QStringLiteral("session_handle")).value<QDBusObjectPath>();
|
||||
|
||||
if (streamNodeId == 0 || sessionHandle.path().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (x != data->x || y != data->y) {
|
||||
data->dbusXdpRemoteDesktopService->NotifyPointerMotionAbsolute(sessionHandle, QVariantMap(), streamNodeId, x, y);
|
||||
data->x = x;
|
||||
data->y = y;
|
||||
}
|
||||
|
||||
if (buttonMask != data->buttonMask) {
|
||||
int i = 0;
|
||||
QList<int> buttons = {BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, 0, 0, 0, 0, BTN_SIDE, BTN_EXTRA};
|
||||
for (auto it = buttons.constBegin(); it != buttons.constEnd(); ++it) {
|
||||
int prevButtonState = (data->buttonMask >> i) & 0x01;
|
||||
int currentButtonState = (buttonMask >> i) & 0x01;
|
||||
|
||||
if (prevButtonState != currentButtonState) {
|
||||
if (*it) {
|
||||
data->dbusXdpRemoteDesktopService->NotifyPointerButton(sessionHandle, QVariantMap(), *it, buttonMask);
|
||||
} else {
|
||||
int axis = 0;
|
||||
int steps = 0;
|
||||
switch (i) {
|
||||
case 3:
|
||||
axis = 0; // Vertical
|
||||
steps = -1;
|
||||
break;
|
||||
case 4:
|
||||
axis = 0; // Vertical
|
||||
steps = 1;
|
||||
break;
|
||||
case 5:
|
||||
axis = 1; // Horizontal
|
||||
steps = -1;
|
||||
break;
|
||||
case 6:
|
||||
axis = 1; // Horizontal
|
||||
steps = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
data->dbusXdpRemoteDesktopService->NotifyPointerAxisDiscrete(sessionHandle, QVariantMap(), axis, steps);
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
data->buttonMask = buttonMask;
|
||||
}
|
||||
}
|
||||
23
events/xdp/xdpevents.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
|
||||
SPDX-FileCopyrightText: 2018-2019 Jan Grulich <jgrulich@redhat.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef EVENTS_XDPEVENTS_H
|
||||
#define EVENTS_XDPEVENTS_H
|
||||
|
||||
#include "../../krfb/events.h"
|
||||
|
||||
class XdpEventHandler : public EventHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
void handleKeyboard(bool down, rfbKeySym key) override;
|
||||
void handlePointer(int buttonMask, int x, int y) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
28
events/xdp/xdpeventsplugin.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
|
||||
SPDX-FileCopyrightText: 2018-2019 Jan Grulich <jgrulich@redhat.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "xdpeventsplugin.h"
|
||||
|
||||
#include "xdpevents.h"
|
||||
|
||||
#include <KPluginFactory>
|
||||
|
||||
K_PLUGIN_CLASS(XdpEventsPlugin)
|
||||
|
||||
XdpEventsPlugin::XdpEventsPlugin(QObject *parent, const QVariantList &args)
|
||||
: EventsPlugin(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
EventHandler *XdpEventsPlugin::eventHandler()
|
||||
{
|
||||
// works only under Wayland
|
||||
return new XdpEventHandler();
|
||||
}
|
||||
|
||||
#include "xdpeventsplugin.moc"
|
||||
31
events/xdp/xdpeventsplugin.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
|
||||
SPDX-FileCopyrightText: 2018-2019 Jan Grulich <jgrulich@redhat.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KRFB_EVENTS_XDP_XDPEVENTSPLUGIN_H
|
||||
#define KRFB_EVENTS_XDP_XDPEVENTSPLUGIN_H
|
||||
|
||||
#include "eventsplugin.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class EventHandler;
|
||||
|
||||
class XdpEventsPlugin : public EventsPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
XdpEventsPlugin(QObject *parent, const QVariantList &args);
|
||||
|
||||
EventHandler *eventHandler() override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(XdpEventsPlugin)
|
||||
};
|
||||
|
||||
#endif // Header guard
|
||||
@@ -1,3 +1,7 @@
|
||||
add_subdirectory (qt)
|
||||
add_subdirectory (x11)
|
||||
if (${XCB_DAMAGE_FOUND} AND ${XCB_SHM_FOUND} AND ${XCB_IMAGE_FOUND})
|
||||
add_subdirectory (xcb)
|
||||
endif()
|
||||
|
||||
if (TARGET K::KPipeWire)
|
||||
add_subdirectory(pipewire)
|
||||
endif()
|
||||
|
||||
76
framebuffers/pipewire/CMakeLists.txt
Normal file
@@ -0,0 +1,76 @@
|
||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
set (krfb_framebuffer_pw_SRCS
|
||||
pw_framebuffer.cpp
|
||||
pw_framebufferplugin.cpp
|
||||
|
||||
screencasting.cpp
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(krfb_framebuffer_pw_SRCS
|
||||
HEADER krfb_fb_pipewire_debug.h
|
||||
IDENTIFIER KRFB_FB_PIPEWIRE
|
||||
CATEGORY_NAME krfb.framebuffer.pipewire
|
||||
DESCRIPTION "KRFB PipeWire framebuffer plugin"
|
||||
EXPORT KRFB
|
||||
)
|
||||
|
||||
qt_add_dbus_interface(
|
||||
krfb_framebuffer_pw_SRCS
|
||||
${CMAKE_SOURCE_DIR}/dbus/xdp_dbus_screencast_interface.xml
|
||||
xdp_dbus_screencast_interface
|
||||
)
|
||||
|
||||
qt_add_dbus_interface(
|
||||
krfb_framebuffer_pw_SRCS
|
||||
${CMAKE_SOURCE_DIR}/dbus/xdp_dbus_remotedesktop_interface.xml
|
||||
xdp_dbus_remotedesktop_interface
|
||||
)
|
||||
|
||||
add_library(krfb_framebuffer_pw
|
||||
MODULE
|
||||
${krfb_framebuffer_pw_SRCS}
|
||||
)
|
||||
|
||||
if (Qt6_VERSION VERSION_LESS "6.7.1")
|
||||
ecm_add_qtwayland_client_protocol(krfb_framebuffer_pw
|
||||
PROTOCOL ${PLASMA_WAYLAND_PROTOCOLS_DIR}/screencast.xml
|
||||
BASENAME zkde-screencast-unstable-v1
|
||||
)
|
||||
else()
|
||||
if (Qt6_VERSION VERSION_GREATER_EQUAL "6.8.0")
|
||||
set(private_code_option "PRIVATE_CODE")
|
||||
endif()
|
||||
qt6_generate_wayland_protocol_client_sources(krfb_framebuffer_pw
|
||||
${private_code_option}
|
||||
FILES ${PLASMA_WAYLAND_PROTOCOLS_DIR}/screencast.xml
|
||||
)
|
||||
endif()
|
||||
|
||||
if (KPipeWire_VERSION VERSION_LESS "6.0.80")
|
||||
target_compile_definitions(krfb_framebuffer_pw PRIVATE -DKPIPEWIRE60=1)
|
||||
else()
|
||||
target_compile_definitions(krfb_framebuffer_pw PRIVATE -DKPIPEWIRE60=0)
|
||||
endif()
|
||||
set_property(TARGET krfb_framebuffer_pw PROPERTY C_STANDARD 99)
|
||||
|
||||
target_link_libraries(krfb_framebuffer_pw
|
||||
Qt::Core
|
||||
Qt::Gui
|
||||
Qt::DBus
|
||||
KF6::CoreAddons
|
||||
KF6::ConfigCore
|
||||
PkgConfig::PipeWire
|
||||
Plasma::KWaylandClient
|
||||
Wayland::Client
|
||||
krfbprivate
|
||||
K::KPipeWire
|
||||
K::KPipeWireDmaBuf
|
||||
)
|
||||
|
||||
set_target_properties(krfb_framebuffer_pw PROPERTIES OUTPUT_NAME pw)
|
||||
install (TARGETS krfb_framebuffer_pw
|
||||
DESTINATION ${KDE_INSTALL_PLUGINDIR}/krfb/framebuffer
|
||||
)
|
||||
5
framebuffers/pipewire/pipewire.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"X-KDE-OnlyShowOnQtPlatforms": [
|
||||
"wayland"
|
||||
]
|
||||
}
|
||||
530
framebuffers/pipewire/pw_framebuffer.cpp
Normal file
@@ -0,0 +1,530 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2018-2021 Jan Grulich <jgrulich@redhat.com>
|
||||
SPDX-FileCopyrightText: 2018 Oleg Chernovskiy <kanedias@xaker.ru>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "config-krfb.h"
|
||||
|
||||
// system
|
||||
#include <cstring>
|
||||
#include <sys/mman.h>
|
||||
|
||||
// Qt
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QGuiApplication>
|
||||
#include <QRandomGenerator>
|
||||
#include <QScreen>
|
||||
#include <QSocketNotifier>
|
||||
|
||||
#include <KConfigGroup>
|
||||
#include <KSharedConfig>
|
||||
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/registry.h>
|
||||
|
||||
// pipewire
|
||||
#include <climits>
|
||||
|
||||
#include "krfb_fb_pipewire_debug.h"
|
||||
#include "pw_framebuffer.h"
|
||||
#include "screencasting.h"
|
||||
#include "xdp_dbus_remotedesktop_interface.h"
|
||||
#include "xdp_dbus_screencast_interface.h"
|
||||
#include <DmaBufHandler>
|
||||
#include <PipeWireSourceStream>
|
||||
|
||||
static const int BYTES_PER_PIXEL = 4;
|
||||
static const uint MIN_SUPPORTED_XDP_KDE_SC_VERSION = 1;
|
||||
|
||||
Q_DECLARE_METATYPE(PWFrameBuffer::Stream);
|
||||
Q_DECLARE_METATYPE(PWFrameBuffer::Streams);
|
||||
|
||||
const QDBusArgument &operator>>(const QDBusArgument &arg, PWFrameBuffer::Stream &stream)
|
||||
{
|
||||
arg.beginStructure();
|
||||
arg >> stream.nodeId;
|
||||
|
||||
arg.beginMap();
|
||||
while (!arg.atEnd()) {
|
||||
QString key;
|
||||
QVariant map;
|
||||
arg.beginMapEntry();
|
||||
arg >> key >> map;
|
||||
arg.endMapEntry();
|
||||
stream.map.insert(key, map);
|
||||
}
|
||||
arg.endMap();
|
||||
arg.endStructure();
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The PWFrameBuffer::Private class - private counterpart of PWFramebuffer class. This is the entity where
|
||||
* whole logic resides, for more info search for "d-pointer pattern" information.
|
||||
*/
|
||||
class PWFrameBuffer::Private
|
||||
{
|
||||
public:
|
||||
Private(PWFrameBuffer *q);
|
||||
~Private();
|
||||
|
||||
private:
|
||||
friend class PWFrameBuffer;
|
||||
|
||||
void initDbus();
|
||||
|
||||
// dbus handling
|
||||
void handleSessionCreated(quint32 code, const QVariantMap &results);
|
||||
void handleDevicesSelected(quint32 code, const QVariantMap &results);
|
||||
void handleSourcesSelected(quint32 code, const QVariantMap &results);
|
||||
void handleRemoteDesktopStarted(quint32 code, const QVariantMap &results);
|
||||
void setVideoSize(const QSize &size);
|
||||
|
||||
// pw handling
|
||||
void handleFrame(const PipeWireFrame &frame);
|
||||
|
||||
// link to public interface
|
||||
PWFrameBuffer *q;
|
||||
|
||||
// requests a session from XDG Desktop Portal
|
||||
// auto-generated and compiled from xdp_dbus_interface.xml file
|
||||
QScopedPointer<OrgFreedesktopPortalScreenCastInterface> dbusXdpScreenCastService;
|
||||
QScopedPointer<OrgFreedesktopPortalRemoteDesktopInterface> dbusXdpRemoteDesktopService;
|
||||
|
||||
// XDP screencast session handle
|
||||
QDBusObjectPath sessionPath;
|
||||
|
||||
// screen geometry holder
|
||||
QSize videoSize;
|
||||
|
||||
// sanity indicator
|
||||
bool isValid = true;
|
||||
std::unique_ptr<PipeWireSourceStream> stream;
|
||||
std::optional<PipeWireCursor> cursor;
|
||||
DmaBufHandler m_dmabufHandler;
|
||||
};
|
||||
|
||||
PWFrameBuffer::Private::Private(PWFrameBuffer *q)
|
||||
: q(q)
|
||||
, stream(new PipeWireSourceStream(q))
|
||||
{
|
||||
QObject::connect(stream.get(), &PipeWireSourceStream::frameReceived, q, [this](const PipeWireFrame &frame) {
|
||||
handleFrame(frame);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PWFrameBuffer::Private::initDbus - initialize D-Bus connectivity with XDG Desktop Portal.
|
||||
* Based on XDG_CURRENT_DESKTOP environment variable it will give us implementation that we need,
|
||||
* in case of KDE it is xdg-desktop-portal-kde binary.
|
||||
*/
|
||||
void PWFrameBuffer::Private::initDbus()
|
||||
{
|
||||
qInfo() << "Initializing D-Bus connectivity with XDG Desktop Portal";
|
||||
dbusXdpScreenCastService.reset(new OrgFreedesktopPortalScreenCastInterface(QStringLiteral("org.freedesktop.portal.Desktop"),
|
||||
QStringLiteral("/org/freedesktop/portal/desktop"),
|
||||
QDBusConnection::sessionBus()));
|
||||
dbusXdpRemoteDesktopService.reset(new OrgFreedesktopPortalRemoteDesktopInterface(QStringLiteral("org.freedesktop.portal.Desktop"),
|
||||
QStringLiteral("/org/freedesktop/portal/desktop"),
|
||||
QDBusConnection::sessionBus()));
|
||||
auto version = dbusXdpScreenCastService->version();
|
||||
if (version < MIN_SUPPORTED_XDP_KDE_SC_VERSION) {
|
||||
qCWarning(KRFB_FB_PIPEWIRE) << "Unsupported XDG Portal screencast interface version:" << version;
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// create session
|
||||
auto sessionParameters = QVariantMap{
|
||||
{QStringLiteral("session_handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())},
|
||||
{QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())}};
|
||||
auto sessionReply = dbusXdpRemoteDesktopService->CreateSession(sessionParameters);
|
||||
sessionReply.waitForFinished();
|
||||
if (!sessionReply.isValid()) {
|
||||
qWarning("Couldn't initialize XDP-KDE screencast session");
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
qInfo() << "DBus session created: " << sessionReply.value().path();
|
||||
QDBusConnection::sessionBus().connect(QString(),
|
||||
sessionReply.value().path(),
|
||||
QStringLiteral("org.freedesktop.portal.Request"),
|
||||
QStringLiteral("Response"),
|
||||
this->q,
|
||||
SLOT(handleXdpSessionCreated(uint, QVariantMap)));
|
||||
}
|
||||
|
||||
void PWFrameBuffer::handleXdpSessionCreated(quint32 code, const QVariantMap &results)
|
||||
{
|
||||
d->handleSessionCreated(code, results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PWFrameBuffer::Private::handleSessionCreated - handle creation of ScreenCast session.
|
||||
* XDG Portal answers with session path if it was able to successfully create the screencast.
|
||||
*
|
||||
* @param code return code for dbus call. Zero is success, non-zero means error
|
||||
* @param results map with results of call.
|
||||
*/
|
||||
void PWFrameBuffer::Private::handleSessionCreated(quint32 code, const QVariantMap &results)
|
||||
{
|
||||
if (code != 0) {
|
||||
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to create session: " << code;
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
sessionPath = QDBusObjectPath(results.value(QStringLiteral("session_handle")).toString());
|
||||
|
||||
// select sources for the session
|
||||
auto selectionOptions = QVariantMap{
|
||||
// We have to specify it's an uint, otherwise xdg-desktop-portal will not forward it to backend implementation
|
||||
{QStringLiteral("types"), QVariant::fromValue<uint>(7)}, // request all (KeyBoard, Pointer, TouchScreen)
|
||||
{QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())},
|
||||
{QStringLiteral("persist_mode"), QVariant::fromValue<uint>(2)}, // Persist permission until explicitly revoked by user
|
||||
};
|
||||
|
||||
KConfigGroup stateConfig = KSharedConfig::openStateConfig()->group(QStringLiteral("XdgPortal"));
|
||||
const QString restoreToken = stateConfig.readEntry(QStringLiteral("RestoreToken"), QString());
|
||||
if (!restoreToken.isEmpty()) {
|
||||
selectionOptions[QStringLiteral("restore_token")] = restoreToken;
|
||||
}
|
||||
|
||||
auto selectorReply = dbusXdpRemoteDesktopService->SelectDevices(sessionPath, selectionOptions);
|
||||
selectorReply.waitForFinished();
|
||||
if (!selectorReply.isValid()) {
|
||||
qCWarning(KRFB_FB_PIPEWIRE) << "Couldn't select devices for the remote-desktop session";
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
QDBusConnection::sessionBus().connect(QString(),
|
||||
selectorReply.value().path(),
|
||||
QStringLiteral("org.freedesktop.portal.Request"),
|
||||
QStringLiteral("Response"),
|
||||
this->q,
|
||||
SLOT(handleXdpDevicesSelected(uint, QVariantMap)));
|
||||
}
|
||||
|
||||
void PWFrameBuffer::handleXdpDevicesSelected(quint32 code, const QVariantMap &results)
|
||||
{
|
||||
d->handleDevicesSelected(code, results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PWFrameBuffer::Private::handleDevicesCreated - handle selection of devices we want to use for remote desktop
|
||||
*
|
||||
* @param code return code for dbus call. Zero is success, non-zero means error
|
||||
* @param results map with results of call.
|
||||
*/
|
||||
void PWFrameBuffer::Private::handleDevicesSelected(quint32 code, const QVariantMap &results)
|
||||
{
|
||||
Q_UNUSED(results)
|
||||
if (code != 0) {
|
||||
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to select devices: " << code;
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// select sources for the session
|
||||
auto selectionOptions = QVariantMap{
|
||||
{QStringLiteral("types"), QVariant::fromValue<uint>(1)}, // only MONITOR is supported
|
||||
{QStringLiteral("multiple"), false},
|
||||
{QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())}};
|
||||
auto selectorReply = dbusXdpScreenCastService->SelectSources(sessionPath, selectionOptions);
|
||||
selectorReply.waitForFinished();
|
||||
if (!selectorReply.isValid()) {
|
||||
qCWarning(KRFB_FB_PIPEWIRE) << "Couldn't select sources for the screen-casting session";
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
QDBusConnection::sessionBus().connect(QString(),
|
||||
selectorReply.value().path(),
|
||||
QStringLiteral("org.freedesktop.portal.Request"),
|
||||
QStringLiteral("Response"),
|
||||
this->q,
|
||||
SLOT(handleXdpSourcesSelected(uint, QVariantMap)));
|
||||
}
|
||||
|
||||
void PWFrameBuffer::handleXdpSourcesSelected(quint32 code, const QVariantMap &results)
|
||||
{
|
||||
d->handleSourcesSelected(code, results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PWFrameBuffer::Private::handleSourcesSelected - handle Screencast sources selection.
|
||||
* XDG Portal shows a dialog at this point which allows you to select monitor from the list.
|
||||
* This function is called after you make a selection.
|
||||
*
|
||||
* @param code return code for dbus call. Zero is success, non-zero means error
|
||||
* @param results map with results of call.
|
||||
*/
|
||||
void PWFrameBuffer::Private::handleSourcesSelected(quint32 code, const QVariantMap &)
|
||||
{
|
||||
if (code != 0) {
|
||||
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to select sources: " << code;
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// start session
|
||||
auto startParameters = QVariantMap{
|
||||
{QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())}};
|
||||
auto startReply = dbusXdpRemoteDesktopService->Start(sessionPath, QString(), startParameters);
|
||||
startReply.waitForFinished();
|
||||
QDBusConnection::sessionBus().connect(QString(),
|
||||
startReply.value().path(),
|
||||
QStringLiteral("org.freedesktop.portal.Request"),
|
||||
QStringLiteral("Response"),
|
||||
this->q,
|
||||
SLOT(handleXdpRemoteDesktopStarted(uint, QVariantMap)));
|
||||
}
|
||||
|
||||
void PWFrameBuffer::handleXdpRemoteDesktopStarted(quint32 code, const QVariantMap &results)
|
||||
{
|
||||
d->handleRemoteDesktopStarted(code, results);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PWFrameBuffer::Private::handleScreencastStarted - handle Screencast start.
|
||||
* At this point there shall be ready pipewire stream to consume.
|
||||
*
|
||||
* @param code return code for dbus call. Zero is success, non-zero means error
|
||||
* @param results map with results of call.
|
||||
*/
|
||||
void PWFrameBuffer::Private::handleRemoteDesktopStarted(quint32 code, const QVariantMap &results)
|
||||
{
|
||||
if (code != 0) {
|
||||
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to start screencast: " << code;
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (results.value(QStringLiteral("devices")).toUInt() == 0) {
|
||||
qCWarning(KRFB_FB_PIPEWIRE) << "No devices were granted" << results;
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// there should be only one stream
|
||||
const Streams streams = qdbus_cast<Streams>(results.value(QStringLiteral("streams")));
|
||||
if (streams.isEmpty()) {
|
||||
// maybe we should check deeper with qdbus_cast but this suffices for now
|
||||
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to get screencast streams";
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
auto streamReply = dbusXdpScreenCastService->OpenPipeWireRemote(sessionPath, QVariantMap());
|
||||
streamReply.waitForFinished();
|
||||
if (!streamReply.isValid()) {
|
||||
qCWarning(KRFB_FB_PIPEWIRE) << "Couldn't open pipewire remote for the screen-casting session";
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
QDBusUnixFileDescriptor pipewireFd = streamReply.value();
|
||||
if (!pipewireFd.isValid()) {
|
||||
qCWarning(KRFB_FB_PIPEWIRE) << "Couldn't get pipewire connection file descriptor";
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!stream->createStream(streams.first().nodeId, pipewireFd.takeFileDescriptor())) {
|
||||
qCWarning(KRFB_FB_PIPEWIRE) << "Couldn't create the pipewire stream";
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// save restore token
|
||||
KConfigGroup stateConfig = KSharedConfig::openStateConfig()->group(QStringLiteral("XdgPortal"));
|
||||
stateConfig.writeEntry(QStringLiteral("RestoreToken"), results[QStringLiteral("restore_token")].toString());
|
||||
}
|
||||
|
||||
void PWFrameBuffer::Private::handleFrame(const PipeWireFrame &frame)
|
||||
{
|
||||
cursor = frame.cursor;
|
||||
|
||||
#if KPIPEWIRE60
|
||||
if (!frame.dmabuf && !frame.image) {
|
||||
#else
|
||||
if (!frame.dmabuf && !frame.dataFrame) {
|
||||
#endif
|
||||
qCDebug(KRFB_FB_PIPEWIRE) << "Got empty buffer. The buffer possibly carried only "
|
||||
"information about the mouse cursor.";
|
||||
return;
|
||||
}
|
||||
|
||||
#if KPIPEWIRE60
|
||||
if (frame.image) {
|
||||
memcpy(q->fb, frame.image->constBits(), frame.image->sizeInBytes());
|
||||
setVideoSize(frame.image->size());
|
||||
}
|
||||
#else
|
||||
if (frame.dataFrame) {
|
||||
// FIXME: Assuming stride == width * 4, not sure to which extent this holds
|
||||
setVideoSize(frame.dataFrame->size);
|
||||
memcpy(q->fb, frame.dataFrame->data, frame.dataFrame->size.height() * frame.dataFrame->stride);
|
||||
}
|
||||
#endif
|
||||
else if (frame.dmabuf) {
|
||||
// FIXME: Assuming stride == width * 4, not sure to which extent this holds
|
||||
const QSize size = {frame.dmabuf->width, frame.dmabuf->height};
|
||||
setVideoSize(size);
|
||||
QImage src(reinterpret_cast<uchar *>(q->fb), size.width(), size.height(), QImage::Format_RGB32);
|
||||
if (!m_dmabufHandler.downloadFrame(src, frame)) {
|
||||
stream->renegotiateModifierFailed(frame.format, frame.dmabuf->modifier);
|
||||
qCDebug(KRFB_FB_PIPEWIRE) << "Failed to download frame.";
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
qCDebug(KRFB_FB_PIPEWIRE) << "Unknown kind of frame";
|
||||
}
|
||||
|
||||
if (auto damage = frame.damage) {
|
||||
for (const auto &rect : *damage) {
|
||||
q->tiles.append(rect);
|
||||
}
|
||||
} else {
|
||||
q->tiles.append(QRect(0, 0, videoSize.width(), videoSize.height()));
|
||||
}
|
||||
}
|
||||
|
||||
void PWFrameBuffer::Private::setVideoSize(const QSize &size)
|
||||
{
|
||||
if (q->fb && videoSize == size) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(q->fb);
|
||||
q->fb = static_cast<char *>(malloc(size.width() * size.height() * BYTES_PER_PIXEL));
|
||||
if (!q->fb) {
|
||||
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to allocate buffer";
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
videoSize = size;
|
||||
|
||||
Q_EMIT q->frameBufferChanged();
|
||||
}
|
||||
|
||||
PWFrameBuffer::Private::~Private()
|
||||
{
|
||||
}
|
||||
|
||||
PWFrameBuffer::PWFrameBuffer(QObject *parent)
|
||||
: FrameBuffer(parent)
|
||||
, d(new Private(this))
|
||||
{
|
||||
}
|
||||
|
||||
PWFrameBuffer::~PWFrameBuffer()
|
||||
{
|
||||
free(fb);
|
||||
fb = nullptr;
|
||||
}
|
||||
|
||||
void PWFrameBuffer::initDBus()
|
||||
{
|
||||
d->initDbus();
|
||||
}
|
||||
|
||||
void PWFrameBuffer::startVirtualMonitor(const QString &name, const QSize &resolution, qreal dpr)
|
||||
{
|
||||
d->videoSize = resolution * dpr;
|
||||
using namespace KWayland::Client;
|
||||
auto connection = ConnectionThread::fromApplication(this);
|
||||
if (!connection) {
|
||||
qWarning() << "Failed getting Wayland connection from QPA";
|
||||
QCoreApplication::exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
auto registry = new Registry(this);
|
||||
connect(registry, &KWayland::Client::Registry::interfaceAnnounced, this, [this, registry, name, dpr, resolution](const QByteArray &interfaceName, quint32 wlname, quint32 version) {
|
||||
if (interfaceName != "zkde_screencast_unstable_v1") {
|
||||
return;
|
||||
}
|
||||
|
||||
auto screencasting = new Screencasting(registry, wlname, version, this);
|
||||
auto r = screencasting->createVirtualMonitorStream(name, resolution, dpr, Screencasting::Metadata);
|
||||
connect(r, &ScreencastingStream::created, this, [this](quint32 nodeId) {
|
||||
d->stream->createStream(nodeId, 0);
|
||||
});
|
||||
});
|
||||
registry->create(connection);
|
||||
registry->setup();
|
||||
}
|
||||
|
||||
int PWFrameBuffer::depth()
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
int PWFrameBuffer::height()
|
||||
{
|
||||
if (!d->videoSize.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
return d->videoSize.height();
|
||||
}
|
||||
|
||||
int PWFrameBuffer::width()
|
||||
{
|
||||
if (!d->videoSize.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
return d->videoSize.width();
|
||||
}
|
||||
|
||||
int PWFrameBuffer::paddedWidth()
|
||||
{
|
||||
return width() * 4;
|
||||
}
|
||||
|
||||
void PWFrameBuffer::getServerFormat(rfbPixelFormat &format)
|
||||
{
|
||||
format.bitsPerPixel = 32;
|
||||
format.depth = 32;
|
||||
format.trueColour = true;
|
||||
format.bigEndian = false;
|
||||
}
|
||||
|
||||
void PWFrameBuffer::startMonitor()
|
||||
{
|
||||
}
|
||||
|
||||
void PWFrameBuffer::stopMonitor()
|
||||
{
|
||||
}
|
||||
|
||||
QVariant PWFrameBuffer::customProperty(const QString &property) const
|
||||
{
|
||||
if (property == QLatin1String("stream_node_id")) {
|
||||
return QVariant::fromValue<uint>(d->stream->nodeId());
|
||||
}
|
||||
if (property == QLatin1String("session_handle")) {
|
||||
return QVariant::fromValue<QDBusObjectPath>(d->sessionPath);
|
||||
}
|
||||
|
||||
return FrameBuffer::customProperty(property);
|
||||
}
|
||||
|
||||
bool PWFrameBuffer::isValid() const
|
||||
{
|
||||
return d->isValid;
|
||||
}
|
||||
|
||||
QPoint PWFrameBuffer::cursorPosition()
|
||||
{
|
||||
const auto cursor = d->cursor;
|
||||
if (cursor) {
|
||||
return cursor->position;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
62
framebuffers/pipewire/pw_framebuffer.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2018 Oleg Chernovskiy <kanedias@xaker.ru>
|
||||
SPDX-FileCopyrightText: 2018-2020 Jan Grulich <jgrulich@redhat.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
#ifndef KRFB_FRAMEBUFFER_XCB_XCB_FRAMEBUFFER_H
|
||||
#define KRFB_FRAMEBUFFER_XCB_XCB_FRAMEBUFFER_H
|
||||
|
||||
#include "framebuffer.h"
|
||||
#include <QVariantMap>
|
||||
#include <QWidget>
|
||||
|
||||
/**
|
||||
* @brief The PWFrameBuffer class - framebuffer implementation based on XDG Desktop Portal ScreenCast interface.
|
||||
* The design relies heavily on a presence of XDG D-Bus service and PipeWire daemon.
|
||||
*
|
||||
* @author Oleg Chernovskiy <kanedias@xaker.ru>
|
||||
*/
|
||||
class PWFrameBuffer : public FrameBuffer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using Stream = struct
|
||||
{
|
||||
uint nodeId;
|
||||
QVariantMap map;
|
||||
};
|
||||
using Streams = QList<Stream>;
|
||||
|
||||
PWFrameBuffer(QObject *parent = nullptr);
|
||||
virtual ~PWFrameBuffer() override;
|
||||
|
||||
void initDBus();
|
||||
void startVirtualMonitor(const QString &name, const QSize &resolution, qreal dpr);
|
||||
|
||||
int depth() override;
|
||||
int height() override;
|
||||
int width() override;
|
||||
int paddedWidth() override;
|
||||
void getServerFormat(rfbPixelFormat &format) override;
|
||||
void startMonitor() override;
|
||||
void stopMonitor() override;
|
||||
QPoint cursorPosition() override;
|
||||
|
||||
QVariant customProperty(const QString &property) const override;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void handleXdpSessionCreated(quint32 code, const QVariantMap &results);
|
||||
void handleXdpDevicesSelected(quint32 code, const QVariantMap &results);
|
||||
void handleXdpSourcesSelected(quint32 code, const QVariantMap &results);
|
||||
void handleXdpRemoteDesktopStarted(quint32 code, const QVariantMap &results);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
const QScopedPointer<Private> d;
|
||||
};
|
||||
|
||||
#endif
|
||||
38
framebuffers/pipewire/pw_framebufferplugin.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2018 Oleg Chernovskiy <kanedias@xaker.ru>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "pw_framebufferplugin.h"
|
||||
#include "pw_framebuffer.h"
|
||||
#include <KPluginFactory>
|
||||
|
||||
K_PLUGIN_CLASS_WITH_JSON(PWFrameBufferPlugin, "pipewire.json")
|
||||
|
||||
PWFrameBufferPlugin::PWFrameBufferPlugin(QObject *parent, const QVariantList &args)
|
||||
: FrameBufferPlugin(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
FrameBuffer *PWFrameBufferPlugin::frameBuffer(const QVariantMap &args)
|
||||
{
|
||||
auto pwfb = new PWFrameBuffer;
|
||||
if (args.contains(QLatin1String("name"))) {
|
||||
pwfb->startVirtualMonitor(args[QStringLiteral("name")].toString(), args[QStringLiteral("resolution")].toSize(), args[QStringLiteral("scale")].toDouble());
|
||||
} else {
|
||||
// D-Bus is most important in XDG-Desktop-Portals init chain, no toys for us if something is wrong with XDP
|
||||
// PipeWire connectivity is initialized after D-Bus session is started
|
||||
pwfb->initDBus();
|
||||
}
|
||||
|
||||
// sanity check for dbus/wayland/pipewire errors
|
||||
if (!pwfb->isValid()) {
|
||||
delete pwfb;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pwfb;
|
||||
}
|
||||
|
||||
#include "pw_framebufferplugin.moc"
|
||||
27
framebuffers/pipewire/pw_framebufferplugin.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2018 Oleg Chernovskiy <kanedias@xaker.ru>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KRFB_FRAMEBUFFER_PW_PWFRAMEBUFFERPLUGIN_H
|
||||
#define KRFB_FRAMEBUFFER_PW_PWFRAMEBUFFERPLUGIN_H
|
||||
|
||||
#include "framebufferplugin.h"
|
||||
|
||||
class FrameBuffer;
|
||||
|
||||
class PWFrameBufferPlugin : public FrameBufferPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PWFrameBufferPlugin(QObject *parent, const QVariantList &args);
|
||||
|
||||
FrameBuffer *frameBuffer(const QVariantMap &args) override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PWFrameBufferPlugin)
|
||||
};
|
||||
|
||||
#endif // Header guard
|
||||
117
framebuffers/pipewire/screencasting.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#include "screencasting.h"
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 7, 1)
|
||||
#include "qwayland-zkde-screencast-unstable-v1.h"
|
||||
#else
|
||||
#include "qwayland-screencast.h"
|
||||
#endif
|
||||
#include <KWayland/Client/registry.h>
|
||||
#include <QDebug>
|
||||
#include <QPointer>
|
||||
#include <QRect>
|
||||
|
||||
using namespace KWayland::Client;
|
||||
|
||||
class ScreencastingStreamPrivate : public QtWayland::zkde_screencast_stream_unstable_v1
|
||||
{
|
||||
public:
|
||||
ScreencastingStreamPrivate(ScreencastingStream *q)
|
||||
: q(q)
|
||||
{
|
||||
}
|
||||
~ScreencastingStreamPrivate() override
|
||||
{
|
||||
close();
|
||||
q->deleteLater();
|
||||
}
|
||||
|
||||
void zkde_screencast_stream_unstable_v1_created(uint32_t node) override
|
||||
{
|
||||
m_nodeId = node;
|
||||
Q_EMIT q->created(node);
|
||||
}
|
||||
|
||||
void zkde_screencast_stream_unstable_v1_closed() override
|
||||
{
|
||||
Q_EMIT q->closed();
|
||||
}
|
||||
|
||||
void zkde_screencast_stream_unstable_v1_failed(const QString &error) override
|
||||
{
|
||||
Q_EMIT q->failed(error);
|
||||
}
|
||||
|
||||
uint m_nodeId = 0;
|
||||
QPointer<ScreencastingStream> q;
|
||||
};
|
||||
|
||||
ScreencastingStream::ScreencastingStream(QObject *parent)
|
||||
: QObject(parent)
|
||||
, d(new ScreencastingStreamPrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
ScreencastingStream::~ScreencastingStream() = default;
|
||||
|
||||
quint32 ScreencastingStream::nodeId() const
|
||||
{
|
||||
return d->m_nodeId;
|
||||
}
|
||||
|
||||
class ScreencastingPrivate : public QtWayland::zkde_screencast_unstable_v1
|
||||
{
|
||||
public:
|
||||
ScreencastingPrivate(Registry *registry, int id, int version, Screencasting *q)
|
||||
: QtWayland::zkde_screencast_unstable_v1(*registry, id, version)
|
||||
, q(q)
|
||||
{
|
||||
}
|
||||
|
||||
ScreencastingPrivate(::zkde_screencast_unstable_v1 *screencasting, Screencasting *q)
|
||||
: QtWayland::zkde_screencast_unstable_v1(screencasting)
|
||||
, q(q)
|
||||
{
|
||||
}
|
||||
|
||||
~ScreencastingPrivate() override
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
Screencasting *const q;
|
||||
};
|
||||
|
||||
Screencasting::Screencasting(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
Screencasting::Screencasting(Registry *registry, int id, int version, QObject *parent)
|
||||
: QObject(parent)
|
||||
, d(new ScreencastingPrivate(registry, id, version, this))
|
||||
{
|
||||
}
|
||||
|
||||
Screencasting::~Screencasting() = default;
|
||||
|
||||
ScreencastingStream *Screencasting::createVirtualMonitorStream(const QString &name, const QSize &resolution, qreal dpr, Screencasting::CursorMode mode)
|
||||
{
|
||||
auto stream = new ScreencastingStream(this);
|
||||
stream->d->init(d->stream_virtual_output(name, resolution.width(), resolution.height(), wl_fixed_from_double(dpr), mode));
|
||||
return stream;
|
||||
}
|
||||
|
||||
void Screencasting::setup(::zkde_screencast_unstable_v1 *screencasting)
|
||||
{
|
||||
d.reset(new ScreencastingPrivate(screencasting, this));
|
||||
}
|
||||
|
||||
void Screencasting::destroy()
|
||||
{
|
||||
d.reset(nullptr);
|
||||
}
|
||||
79
framebuffers/pipewire/screencasting.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
#include <optional>
|
||||
|
||||
struct zkde_screencast_unstable_v1;
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Client
|
||||
{
|
||||
|
||||
class PlasmaWindow;
|
||||
class Registry;
|
||||
class Output;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class ScreencastingPrivate;
|
||||
class ScreencastingSourcePrivate;
|
||||
class ScreencastingStreamPrivate;
|
||||
class ScreencastingStream : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScreencastingStream(QObject *parent);
|
||||
~ScreencastingStream() override;
|
||||
|
||||
quint32 nodeId() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void created(quint32 nodeid);
|
||||
void failed(const QString &error);
|
||||
void closed();
|
||||
|
||||
private:
|
||||
friend class Screencasting;
|
||||
QScopedPointer<ScreencastingStreamPrivate> d;
|
||||
};
|
||||
|
||||
class Screencasting : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Screencasting(QObject *parent = nullptr);
|
||||
explicit Screencasting(KWayland::Client::Registry *registry, int id, int version, QObject *parent = nullptr);
|
||||
~Screencasting() override;
|
||||
|
||||
enum CursorMode {
|
||||
Hidden = 1,
|
||||
Embedded = 2,
|
||||
Metadata = 4,
|
||||
};
|
||||
Q_ENUM(CursorMode)
|
||||
|
||||
ScreencastingStream *createVirtualMonitorStream(const QString &name, const QSize &resolution, qreal dpr, CursorMode mode);
|
||||
|
||||
void setup(zkde_screencast_unstable_v1 *screencasting);
|
||||
void destroy();
|
||||
|
||||
Q_SIGNALS:
|
||||
void initialized();
|
||||
void removed();
|
||||
void sourcesChanged();
|
||||
|
||||
private:
|
||||
QScopedPointer<ScreencastingPrivate> d;
|
||||
};
|
||||
@@ -1,24 +0,0 @@
|
||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
set (krfb_framebuffer_qt_SRCS
|
||||
qtframebuffer.cpp
|
||||
qtframebufferplugin.cpp
|
||||
)
|
||||
|
||||
add_library(krfb_framebuffer_qt
|
||||
MODULE
|
||||
${krfb_framebuffer_qt_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries (krfb_framebuffer_qt
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
KF5::CoreAddons
|
||||
krfbprivate
|
||||
)
|
||||
|
||||
install (TARGETS krfb_framebuffer_qt
|
||||
DESTINATION ${PLUGIN_INSTALL_DIR}/krfb
|
||||
)
|
||||
@@ -1,107 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Comment=Qt based Framebuffer for KRfb.
|
||||
Comment[ast]=Esquema Qt de buffer pa KRfb
|
||||
Comment[bg]=Основан на Qt фреймбуфер за KRfb.
|
||||
Comment[bs]=Kadrobafer za KRfb na osnovu Qt.
|
||||
Comment[ca]=«Framebuffer» basat en Qt per al KRfb.
|
||||
Comment[ca@valencia]=«Framebuffer» basat en Qt per al KRfb.
|
||||
Comment[cs]=Framebuffer založený na Qt pro KRfb.
|
||||
Comment[da]=Qt-baseret framebuffer til KRfb.
|
||||
Comment[de]=Qt-basierter Framebuffer für KRfb
|
||||
Comment[el]=Μνήμη εξόδου βίντεο καρέ με βάση το Qt για το KRfb.
|
||||
Comment[en_GB]=Qt based Framebuffer for KRfb.
|
||||
Comment[es]=Memoria intermedia de vídeo basada en Qt para KRfb.
|
||||
Comment[et]=KRfb Qt põhine kaadripuhver
|
||||
Comment[eu]=Qt-n oinarritutako KRfb-ren irteerako bideoa
|
||||
Comment[fi]=QT-perustainen Kehyspuskuri KRfb:lle
|
||||
Comment[fr]=Sortie vidéo fondée sur Qt pour Krfb.
|
||||
Comment[ga]=Maolán fráma le haghaidh KRfb, bunaithe ar Qt.
|
||||
Comment[gl]=Framebuffer baseado en Qt para KRfb.
|
||||
Comment[hr]=Međuspremnik okvira baziran na Qt-u za KRfb.
|
||||
Comment[hu]=Qt-alapú framebuffer a Krfb-hez.
|
||||
Comment[ia]=Framebuffer basate sur Qt per KRfb
|
||||
Comment[it]=Framebuffer basato su Qt per KRfb.
|
||||
Comment[kk]=Qt негіздеген KRfb-нің кадр буфері.
|
||||
Comment[km]=Framebuffer មានមូលដ្ឋានលើ Qt សម្រាប់ KRfb ។
|
||||
Comment[ko]=KRfb를 위한 Qt 기반 프레임버퍼.
|
||||
Comment[lt]=Qt pagrindu veikiantis Framebuffer skirtas KRfb.
|
||||
Comment[lv]=Qt balstīts kadrbuferis priekš KRfb.
|
||||
Comment[nb]=Qt-basert rammebuffer for KRfb.
|
||||
Comment[nds]=Op Qt opbuut Bildpuffer för KRfb
|
||||
Comment[nl]=Op Qt gebaseerd framebuffer voor KRfb.
|
||||
Comment[nn]=Qt basert framebuffer for KRfb.
|
||||
Comment[pl]=Bufor ramki na podstawie Qt dla KRfb.
|
||||
Comment[pt]='Framebuffer' baseado no Qt para o KRfb.
|
||||
Comment[pt_BR]=Framebuffer baseado no Qt para o KRfb.
|
||||
Comment[ru]=Буфер экрана для KRfb на базе Qt.
|
||||
Comment[si]=KRfb සඳහා Qt මත පදනම් වූ රාමු බෆරය
|
||||
Comment[sk]=Framebuffer založený na Qt pre KRfb.
|
||||
Comment[sl]=Slikovni medpomnilnik za KRFB, ki temelji na Qt
|
||||
Comment[sr]=Кадробафер за КРФБ на основу КуТ‑у
|
||||
Comment[sr@ijekavian]=Кадробафер за КРФБ на основу КуТ‑у
|
||||
Comment[sr@ijekavianlatin]=Kadrobafer za KRFB na osnovu Qt‑u
|
||||
Comment[sr@latin]=Kadrobafer za KRFB na osnovu Qt‑u
|
||||
Comment[sv]=Qt-baserad rambuffert för Krfb.
|
||||
Comment[tr]=KRfb için Qt temelli Çerçeve tamponu.
|
||||
Comment[uk]=Заснований на Qt буфер кадрів для KRfb.
|
||||
Comment[x-test]=xxQt based Framebuffer for KRfb.xx
|
||||
Comment[zh_CN]=基于 Qt 的 KRfb 帧缓冲机制
|
||||
Comment[zh_TW]=KRfb 的 Qt-based Framebuffer
|
||||
Name=Qt Framebuffer for KRfb
|
||||
Name[ast]=Esquema Qt de buffer pa KRfb
|
||||
Name[bg]=Qt фреймбуфер за KRfb
|
||||
Name[bs]=Qt-ov kadrobafer za KRFB
|
||||
Name[ca]=«Framebuffer» Qt per al KRfb.
|
||||
Name[ca@valencia]=«Framebuffer» Qt per al KRfb.
|
||||
Name[cs]=Qt Framebuffer pro KRfb
|
||||
Name[da]=Qt-framebuffer til KRfb
|
||||
Name[de]=Qt-Framebuffer für KRfb
|
||||
Name[el]=Qt Framebuffer for KRfb
|
||||
Name[en_GB]=Qt Framebuffer for KRfb
|
||||
Name[es]=Memoria intermedia de vídeo Qt para KRfb
|
||||
Name[et]=KRfb Qt kaadripuhver
|
||||
Name[eu]=KRfb-ren Qt-ko irteerako bideoa
|
||||
Name[fi]=QT-kehyspuskuri KRfb:lle
|
||||
Name[fr]=Sortie vidéo Qt pour Krfb
|
||||
Name[ga]=Maolán fráma Qt le haghaidh KRfb
|
||||
Name[gl]=Framebuffer de Qt para KRfb
|
||||
Name[hr]=Qt Framebuffer za KRfb
|
||||
Name[hu]=Qt framebuffer a Krfb-hez
|
||||
Name[ia]=Framebuffer Qt per KRfb
|
||||
Name[it]=Framebuffer Qt per KRfb
|
||||
Name[kk]=Qt KRfb кадр буфері
|
||||
Name[km]=Qt Framebuffer សម្រាប់for KRfb
|
||||
Name[ko]=KRfb를 위한 Qt 프레임버퍼
|
||||
Name[lt]=Qt Framebufferis skirtas KRfb
|
||||
Name[lv]=Qt kadrbuferis priekš KRfb.
|
||||
Name[nb]=Qt rammebuffer for KRfb
|
||||
Name[nds]=Qt-Bildpuffer för KRfb
|
||||
Name[nl]=Qt-framebuffer voor KRfb
|
||||
Name[nn]=Qt-framebuffer for KRfb
|
||||
Name[pl]=Bufor ramki Qt dla KRfb
|
||||
Name[pt]='Framebuffer' do Qt para o KRfb
|
||||
Name[pt_BR]=Framebuffer do Qt para o KRfb
|
||||
Name[ru]=Буфер экрана Qt для KRfb
|
||||
Name[si]=KRfb සඳහා වන Qt රාමුබෆරය
|
||||
Name[sk]=Qt Framebuffer pre KRfb
|
||||
Name[sl]=Slikovni medpomnilnik Qt za KRFB
|
||||
Name[sr]=КуТ‑ов кадробафер за КРФБ
|
||||
Name[sr@ijekavian]=КуТ‑ов кадробафер за КРФБ
|
||||
Name[sr@ijekavianlatin]=Qt‑ov kadrobafer za KRFB
|
||||
Name[sr@latin]=Qt‑ov kadrobafer za KRFB
|
||||
Name[sv]=Qt-rambuffert för Krfb
|
||||
Name[tr]=KRfb için Qt Çerçeve tamponu
|
||||
Name[uk]=Буфер кадрів на Qt для KRfb
|
||||
Name[x-test]=xxQt Framebuffer for KRfbxx
|
||||
Name[zh_CN]=KRfb 的 Qt 帧缓冲机制
|
||||
Name[zh_TW]=Krfb 的 Qt Framebuffer
|
||||
Type=Service
|
||||
ServiceTypes=krfb/framebuffer
|
||||
|
||||
X-KDE-Library=krfb_framebuffer_qt
|
||||
X-KDE-PluginInfo-Name=qt
|
||||
X-KDE-PluginInfo-Version=0.1
|
||||
X-KDE-PluginInfo-Website=http://www.kde.org
|
||||
X-KDE-PluginInfo-License=GPL
|
||||
X-KDE-PluginInfo-EnabledByDefault=true
|
||||
@@ -1,66 +0,0 @@
|
||||
{
|
||||
"Encoding": "UTF-8",
|
||||
"KPlugin": {
|
||||
"Description": "Qt based Framebuffer for KRfb.",
|
||||
"Description[ca@valencia]": "«Framebuffer» basat en Qt per al KRfb.",
|
||||
"Description[ca]": "«Framebuffer» basat en Qt per al KRfb.",
|
||||
"Description[cs]": "Framebuffer založený na Qt pro KRfb.",
|
||||
"Description[de]": "Qt-basierter Framebuffer für KRfb",
|
||||
"Description[en_GB]": "Qt based Framebuffer for KRfb.",
|
||||
"Description[es]": "Framebuffer basado en Qt para KRfb.",
|
||||
"Description[fi]": "QT-perustainen Kehyspuskuri KRfb:lle",
|
||||
"Description[gl]": "Framebuffer baseado en Qt para KRfb.",
|
||||
"Description[it]": "Framebuffer basato su Qt per KRfb.",
|
||||
"Description[ko]": "KRfb용 Qt 기반 프레임버퍼입니다.",
|
||||
"Description[nl]": "Op Qt gebaseerd framebuffer voor KRfb.",
|
||||
"Description[pl]": "Bufor ramki na podstawie Qt dla KRfb.",
|
||||
"Description[pt]": "'Framebuffer' baseado no Qt para o KRfb.",
|
||||
"Description[pt_BR]": "Framebuffer baseado no Qt para o KRfb.",
|
||||
"Description[sk]": "Framebuffer založený na Qt pre KRfb.",
|
||||
"Description[sl]": "Slikovni medpomnilnik za KRfb, ki temelji na Qt",
|
||||
"Description[sr@ijekavian]": "Кадробафер за КРФБ на основу КуТ‑у",
|
||||
"Description[sr@ijekavianlatin]": "Kadrobafer za KRFB na osnovu Qt‑u",
|
||||
"Description[sr@latin]": "Kadrobafer za KRFB na osnovu Qt‑u",
|
||||
"Description[sr]": "Кадробафер за КРФБ на основу КуТ‑у",
|
||||
"Description[sv]": "X11-rambuffert för Krfb.",
|
||||
"Description[uk]": "Заснований на Qt буфер кадрів для KRfb.",
|
||||
"Description[x-test]": "xxQt based Framebuffer for KRfb.xx",
|
||||
"Description[zh_CN]": "KRfb 的基于 Qt 的帧缓冲。",
|
||||
"Description[zh_TW]": "KRfb 的 Qt-based Framebuffer",
|
||||
"EnabledByDefault": true,
|
||||
"Id": "qt",
|
||||
"License": "GPL",
|
||||
"Name": "Qt Framebuffer for KRfb",
|
||||
"Name[ast]": "Framebuffer Qt pa KRfb",
|
||||
"Name[ca@valencia]": "«Framebuffer» Qt per al KRfb.",
|
||||
"Name[ca]": "«Framebuffer» Qt per al KRfb.",
|
||||
"Name[cs]": "Qt Framebuffer pro KRfb",
|
||||
"Name[de]": "Qt-Framebuffer für KRfb",
|
||||
"Name[en_GB]": "Qt Framebuffer for KRfb",
|
||||
"Name[es]": "Framebuffer de Qt para KRfb",
|
||||
"Name[fi]": "QT-kehyspuskuri KRfb:lle",
|
||||
"Name[gl]": "Framebuffer de Qt para KRfb",
|
||||
"Name[it]": "Framebuffer Qt per KRfb",
|
||||
"Name[ko]": "KRfb용 Qt 프레임버퍼",
|
||||
"Name[nl]": "Qt-framebuffer voor KRfb",
|
||||
"Name[pl]": "Bufor ramki Qt dla KRfb",
|
||||
"Name[pt]": "'Framebuffer' do Qt para o KRfb",
|
||||
"Name[pt_BR]": "Framebuffer do Qt para o KRfb",
|
||||
"Name[sk]": "Qt Framebuffer pre KRfb",
|
||||
"Name[sl]": "Slikovni medpomnilnik Qt za KRfb",
|
||||
"Name[sr@ijekavian]": "КуТ‑ов кадробафер за КРФБ",
|
||||
"Name[sr@ijekavianlatin]": "Qt‑ov kadrobafer za KRFB",
|
||||
"Name[sr@latin]": "Qt‑ov kadrobafer za KRFB",
|
||||
"Name[sr]": "КуТ‑ов кадробафер за КРФБ",
|
||||
"Name[sv]": "X11-rambuffert för Krfb",
|
||||
"Name[uk]": "Буфер кадрів на Qt для KRfb",
|
||||
"Name[x-test]": "xxQt Framebuffer for KRfbxx",
|
||||
"Name[zh_CN]": "KRfb 的 Qt 帧缓冲",
|
||||
"Name[zh_TW]": "Krfb 的 Qt Framebuffer",
|
||||
"ServiceTypes": [
|
||||
"krfb/framebuffer"
|
||||
],
|
||||
"Version": "0.1",
|
||||
"Website": "http://www.kde.org"
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "qtframebuffer.h"
|
||||
#include "qtframebuffer.moc"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QRegion>
|
||||
#include <QPixmap>
|
||||
#include <QBitmap>
|
||||
|
||||
|
||||
const int UPDATE_TIME = 500;
|
||||
|
||||
QtFrameBuffer::QtFrameBuffer(WId id, QObject *parent)
|
||||
: FrameBuffer(id, parent)
|
||||
{
|
||||
fbImage = QPixmap::grabWindow(win).toImage();
|
||||
fb = new char[fbImage.byteCount()];
|
||||
t = new QTimer(this);
|
||||
connect(t, &QTimer::timeout, this, &QtFrameBuffer::updateFrameBuffer);
|
||||
}
|
||||
|
||||
|
||||
QtFrameBuffer::~QtFrameBuffer()
|
||||
{
|
||||
delete [] fb;
|
||||
fb = 0;
|
||||
}
|
||||
|
||||
int QtFrameBuffer::depth()
|
||||
{
|
||||
return fbImage.depth();
|
||||
}
|
||||
|
||||
int QtFrameBuffer::height()
|
||||
{
|
||||
return fbImage.height();
|
||||
}
|
||||
|
||||
int QtFrameBuffer::width()
|
||||
{
|
||||
return fbImage.width();
|
||||
}
|
||||
|
||||
void QtFrameBuffer::getServerFormat(rfbPixelFormat &format)
|
||||
{
|
||||
format.bitsPerPixel = 32;
|
||||
format.depth = 32;
|
||||
format.trueColour = true;
|
||||
|
||||
format.bigEndian = false;
|
||||
format.redShift = 16;
|
||||
format.greenShift = 8;
|
||||
format.blueShift = 0;
|
||||
format.redMax = 0xff;
|
||||
format.greenMax = 0xff;
|
||||
format.blueMax = 0xff;
|
||||
}
|
||||
|
||||
void QtFrameBuffer::updateFrameBuffer()
|
||||
{
|
||||
QImage img = QPixmap::grabWindow(win).toImage();
|
||||
#if 0 // This is actually slower than updating the whole desktop...
|
||||
QSize imgSize = img.size();
|
||||
|
||||
|
||||
// verify what part of the image need to be marked as changed
|
||||
// fbImage is the previous version of the image,
|
||||
// img is the current one
|
||||
|
||||
QImage map(imgSize, QImage::Format_Mono);
|
||||
map.fill(0);
|
||||
|
||||
for (int x = 0; x < imgSize.width(); x++) {
|
||||
for (int y = 0; y < imgSize.height(); y++) {
|
||||
if (img.pixel(x, y) != fbImage.pixel(x, y)) {
|
||||
map.setPixel(x, y, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QRegion r(QBitmap::fromImage(map));
|
||||
tiles = tiles + r.rects();
|
||||
|
||||
#else
|
||||
tiles.append(img.rect());
|
||||
#endif
|
||||
|
||||
memcpy(fb, (const char *)img.bits(), img.byteCount());
|
||||
fbImage = img;
|
||||
|
||||
}
|
||||
|
||||
int QtFrameBuffer::paddedWidth()
|
||||
{
|
||||
return fbImage.width() * 4;
|
||||
}
|
||||
|
||||
void QtFrameBuffer::startMonitor()
|
||||
{
|
||||
t->start(UPDATE_TIME);
|
||||
}
|
||||
|
||||
void QtFrameBuffer::stopMonitor()
|
||||
{
|
||||
t->stop();
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef KRFB_FRAMEBUFFER_QT_QTFRAMEBUFFER_H
|
||||
#define KRFB_FRAMEBUFFER_QT_QTFRAMEBUFFER_H
|
||||
|
||||
#include <QImage>
|
||||
#include "framebuffer.h"
|
||||
|
||||
class QTimer;
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class QtFrameBuffer : public FrameBuffer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QtFrameBuffer(WId id, QObject *parent = 0);
|
||||
|
||||
~QtFrameBuffer();
|
||||
|
||||
int depth() override;
|
||||
int height() override;
|
||||
int width() override;
|
||||
int paddedWidth() override;
|
||||
void getServerFormat(rfbPixelFormat &format) override;
|
||||
void startMonitor() override;
|
||||
void stopMonitor() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void updateFrameBuffer();
|
||||
|
||||
private:
|
||||
QImage fbImage;
|
||||
QTimer *t;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,45 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "qtframebufferplugin.h"
|
||||
|
||||
#include "qtframebuffer.h"
|
||||
|
||||
#include <KPluginFactory>
|
||||
|
||||
K_PLUGIN_FACTORY_WITH_JSON(QtFrameBufferPluginFactory, "krfb_framebuffer_qt.json",
|
||||
registerPlugin<QtFrameBufferPlugin>();)
|
||||
|
||||
QtFrameBufferPlugin::QtFrameBufferPlugin(QObject *parent, const QVariantList &args)
|
||||
: FrameBufferPlugin(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
QtFrameBufferPlugin::~QtFrameBufferPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
FrameBuffer *QtFrameBufferPlugin::frameBuffer(WId id)
|
||||
{
|
||||
return new QtFrameBuffer(id);
|
||||
}
|
||||
|
||||
#include "qtframebufferplugin.moc"
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef KRFB_FRAMEBUFFER_QT_QTFRAMEBUFFERPLUGIN_H
|
||||
#define KRFB_FRAMEBUFFER_QT_QTFRAMEBUFFERPLUGIN_H
|
||||
|
||||
#include "framebufferplugin.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class FrameBuffer;
|
||||
|
||||
class QtFrameBufferPlugin : public FrameBufferPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QtFrameBufferPlugin(QObject *parent, const QVariantList &args);
|
||||
virtual ~QtFrameBufferPlugin();
|
||||
|
||||
FrameBuffer *frameBuffer(WId id) override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QtFrameBufferPlugin)
|
||||
};
|
||||
|
||||
|
||||
#endif // Header guard
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
set (krfb_framebuffer_x11_SRCS
|
||||
x11framebuffer.cpp
|
||||
x11framebufferplugin.cpp
|
||||
)
|
||||
|
||||
add_library(krfb_framebuffer_x11
|
||||
MODULE
|
||||
${krfb_framebuffer_x11_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries (krfb_framebuffer_x11
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
${X11_X11_LIB}
|
||||
${X11_Xdamage_LIB}
|
||||
${X11_Xext_LIB}
|
||||
KF5::CoreAddons
|
||||
krfbprivate
|
||||
)
|
||||
|
||||
install (TARGETS krfb_framebuffer_x11
|
||||
DESTINATION ${PLUGIN_INSTALL_DIR}/krfb
|
||||
)
|
||||
@@ -1,107 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Comment=X11 XDamage/XShm based Framebuffer for KRfb.
|
||||
Comment[ast]=Esquema de buffer pa KRfb basáu en XDamage/XShm
|
||||
Comment[bg]=Основан на X11 XDamage/XShm фреймбуфер за KRfb.
|
||||
Comment[bs]=X11 XDamage/XShm baziran framebafer za KRfb.
|
||||
Comment[ca]=«Framebuffer» basat en XDamage/XShmQt del X11 per al KRfb.
|
||||
Comment[ca@valencia]=«Framebuffer» basat en XDamage/XShmQt del X11 per al KRfb.
|
||||
Comment[cs]=Framebuffer založený na X11 XDamage/XShm pro KRfb.
|
||||
Comment[da]=X11 XDamage/XShm-baseret framebuffer til KRfb.
|
||||
Comment[de]=X11 XDamage/XShm-basierter Framebuffer für KRfb.
|
||||
Comment[el]=Μνήμη εξόδου βίντεο καρέ με βάση το X11 XDamage/XShm για το KRfb.
|
||||
Comment[en_GB]=X11 XDamage/XShm based Framebuffer for KRfb.
|
||||
Comment[es]=Memoria intermedia de vídeo basada en X11 Damage/XShm para KRfb.
|
||||
Comment[et]=KRfb X11 XDamage/XShm põhine kaadripuhver
|
||||
Comment[eu]=X11 XDamage/XShm oinarritutako KRfb-ren irteerako bideoa.
|
||||
Comment[fi]=X11 XDamage/XShm-perustainen kehyspuskui KRfb:lle.
|
||||
Comment[fr]=Sortie vidéo fondée sur X11 « XDamage / XShm » pour Krfb.
|
||||
Comment[ga]=Maolán fráma le haghaidh KRfb, bunaithe ar X11 XDamage/XShm
|
||||
Comment[gl]=Framebuffer baseado en Xll XDamage/Xshm para XRfb.
|
||||
Comment[hr]=Međuspreminik okvira baziran na X11 XDamage/XShm za KRfb.
|
||||
Comment[hu]=X11 XDamage/XShm-alapú framebuffer a Krfb-hez.
|
||||
Comment[ia]=Framebuffer basate sur X11 XDamage/XShm per KRfb.
|
||||
Comment[it]=Framebuffer basato su XDamage/XShm di X11 per KRfb.
|
||||
Comment[kk]=X11 XDamage/XShm негіздеген KRfb кадр буфері.
|
||||
Comment[km]=X11 XDamage/XShm based Framebuffer សម្រាប់ KRfb ។
|
||||
Comment[ko]=KRfb를 위한 X11 XDamage/XShm 기반 프레임버퍼.
|
||||
Comment[lt]=X11 XDamage/XShm paremtas Framebuffer skirtas KRfb.
|
||||
Comment[lv]=X11 XDamage/XShm balstīts kadrbuferis priekš KRfb.
|
||||
Comment[nb]=Rammebuffer for KRfb basert på X11 XDamage/XShm.
|
||||
Comment[nds]=Op X11-XDamage/-XShm opbuut Bildpuffer för KRfb
|
||||
Comment[nl]=Op X11 XDamage/XShm gebaseerd framebuffer voor KRfb.
|
||||
Comment[nn]=X11 XDamage/XShm basert framebuffer for KRfb.
|
||||
Comment[pl]=Bufor ramki na podstawie X11 XDamage/XShm dla KRfb.
|
||||
Comment[pt]='Framebuffer' baseado no XDamage/XShm do X11 para o KRfb.
|
||||
Comment[pt_BR]=Framebuffer baseado no XDamage/XShm do X11 para o KRfb.
|
||||
Comment[ru]=Буфер экрана для KRfb на базе X11 XDamage/XShm
|
||||
Comment[si]=KRfb සඳහා වන රාමු බෆරය මත පදනම් වූ X11 XDamage/XShm.
|
||||
Comment[sk]=Framebuffer založený na X11 XDamage/XShm pre KRfb.
|
||||
Comment[sl]=Slikovni medpomnilnik za KRFB, ki temelji na X11 XDamage/XShm
|
||||
Comment[sr]=Кадробафер за КРФБ на основу Икс‑демиџа/Икс‑схма у Иксу11.
|
||||
Comment[sr@ijekavian]=Кадробафер за КРФБ на основу Икс‑демиџа/Икс‑схма у Иксу11.
|
||||
Comment[sr@ijekavianlatin]=Kadrobafer za KRFB na osnovu XDamagea/XShma u X11.
|
||||
Comment[sr@latin]=Kadrobafer za KRFB na osnovu XDamagea/XShma u X11.
|
||||
Comment[sv]=X11 XDamage/XShm-baserad rambuffert för Krfb.
|
||||
Comment[tr]=KRfb için X11 XDamage/XShm temelli Çerçeve Tamponu.
|
||||
Comment[uk]=Заснований на XDamage/XShm X11 буфер кадрів для KRfb.
|
||||
Comment[x-test]=xxX11 XDamage/XShm based Framebuffer for KRfb.xx
|
||||
Comment[zh_CN]=基于 X11 XDamage/XShm 扩展的 KRfb 帧缓冲机制。
|
||||
Comment[zh_TW]=KRfb 的 X11 XDamage/XShm based Framebuffer
|
||||
Name=X11 Framebuffer for KRfb
|
||||
Name[ast]=Buffer de X11 pa KRfb
|
||||
Name[bg]=X11 фреймбуфер за KRfb
|
||||
Name[bs]=X11 frame bafer za KRfb
|
||||
Name[ca]=«Framebuffer» del X11 per al KRfb.
|
||||
Name[ca@valencia]=«Framebuffer» del X11 per al KRfb.
|
||||
Name[cs]=X11 Framebuffer pro KRfb
|
||||
Name[da]=X11-framebuffer til KRfb
|
||||
Name[de]=X11-Framebuffer für KRfb
|
||||
Name[el]=X11 Framebuffer for KRfb
|
||||
Name[en_GB]=X11 Framebuffer for KRfb
|
||||
Name[es]=Memoria intermedia de vídeo X11 para KRfb
|
||||
Name[et]=KRfb X11 kaadripuhver
|
||||
Name[eu]=KRfb-ren X11-ko irteerako bideoa
|
||||
Name[fi]=X11-kehyspuskuri KRfb:lle
|
||||
Name[fr]=Sortie vidéo X11 pour Krfb
|
||||
Name[ga]=Maolán fráma X11 le haghaidh KRfb
|
||||
Name[gl]=Framebuffer de X11 para KRfb
|
||||
Name[hr]=Međuspremnik okvira X11 za KRfb
|
||||
Name[hu]=X11 framebuffer a Krfb-hez
|
||||
Name[ia]=Framebuffer X11 per KRfb
|
||||
Name[it]=Framebuffer X11 per KRfb
|
||||
Name[kk]=X11 KRfb кадр буфері
|
||||
Name[km]=X11 Framebuffer សម្រាប់ KRfb
|
||||
Name[ko]=KRfb를 위한 X11 프레임버퍼
|
||||
Name[lt]=X11 Framebuffer skirtas KRfb
|
||||
Name[lv]=X11 kadrbuferis priekš KRfb
|
||||
Name[nb]=X11 rammebuffer for KRfb
|
||||
Name[nds]=X11-Bildpuffer för KRfb
|
||||
Name[nl]=X11 framebuffer voor KRfb
|
||||
Name[nn]=X11-framebuffer for KRfb
|
||||
Name[pl]=Bufor ramki X11 dla KRfb
|
||||
Name[pt]='Framebuffer' do X11 para o KRfb
|
||||
Name[pt_BR]=Framebuffer do X11 para o KRfb
|
||||
Name[ru]=Буфер экрана X11 для KRfb
|
||||
Name[si]=KRfb සඳහා X11 රාමු බෆරය
|
||||
Name[sk]=X11 Framebuffer pre KRfb
|
||||
Name[sl]=Slikovni medpomnilnik X11 za KRFB
|
||||
Name[sr]=Икс11 кадробафер за КРФБ.
|
||||
Name[sr@ijekavian]=Икс11 кадробафер за КРФБ.
|
||||
Name[sr@ijekavianlatin]=X11 kadrobafer za KRFB.
|
||||
Name[sr@latin]=X11 kadrobafer za KRFB.
|
||||
Name[sv]=X11-rambuffert för Krfb
|
||||
Name[tr]=KRfb için X11 Çerçeve Tamponu
|
||||
Name[uk]=Буфер кадрів X11 для KRfb
|
||||
Name[x-test]=xxX11 Framebuffer for KRfbxx
|
||||
Name[zh_CN]=KRfb 的 X11 帧缓冲机制
|
||||
Name[zh_TW]=KRfb 的 X11 Framebuffer
|
||||
Type=Service
|
||||
ServiceTypes=krfb/framebuffer
|
||||
|
||||
X-KDE-Library=krfb_framebuffer_x11
|
||||
X-KDE-PluginInfo-Name=x11
|
||||
X-KDE-PluginInfo-Version=0.1
|
||||
X-KDE-PluginInfo-Website=http://www.kde.org
|
||||
X-KDE-PluginInfo-License=GPL
|
||||
X-KDE-PluginInfo-EnabledByDefault=true
|
||||
@@ -1,65 +0,0 @@
|
||||
{
|
||||
"Encoding": "UTF-8",
|
||||
"KPlugin": {
|
||||
"Description": "X11 XDamage/XShm based Framebuffer for KRfb.",
|
||||
"Description[ca@valencia]": "«Framebuffer» basat en XDamage/XShmQt del X11 per al KRfb.",
|
||||
"Description[ca]": "«Framebuffer» basat en XDamage/XShmQt del X11 per al KRfb.",
|
||||
"Description[cs]": "Framebuffer založený na X11 XDamage/XShm pro KRfb.",
|
||||
"Description[de]": "X11 XDamage/XShm-basierter Framebuffer für KRfb.",
|
||||
"Description[en_GB]": "X11 XDamage/XShm based Framebuffer for KRfb.",
|
||||
"Description[es]": "Framebuffer basado en XDamage/XShm de X11 para KRfb.",
|
||||
"Description[fi]": "X11 XDamage/XShm-perustainen kehyspuskui KRfb:lle.",
|
||||
"Description[gl]": "Framebuffer baseado en Xll XDamage/Xshm para XRfb.",
|
||||
"Description[it]": "Framebuffer basato su XDamage/XShm di X11 per KRfb.",
|
||||
"Description[ko]": "KRfb용 X11 XDamage/XShm 기반 프레임버퍼입니다.",
|
||||
"Description[nl]": "Op X11 XDamage/XShm gebaseerd framebuffer voor KRfb.",
|
||||
"Description[pl]": "Bufor ramki na podstawie X11 XDamage/XShm dla KRfb.",
|
||||
"Description[pt]": "'Framebuffer' do X11, baseado no XDamage/XShm, para o KRfb.",
|
||||
"Description[pt_BR]": "Framebuffer baseado no XDamage/XShm do X11 para o KRfb.",
|
||||
"Description[sk]": "Framebuffer založený na X11 XDamage/XShm pre KRfb.",
|
||||
"Description[sl]": "Slikovni medpomnilnik za KRfb, ki temelji na X11 XDamage/XShm",
|
||||
"Description[sr@ijekavian]": "Кадробафер за КРФБ на основу Икс‑демиџа/Икс‑схма у Иксу11.",
|
||||
"Description[sr@ijekavianlatin]": "Kadrobafer za KRFB na osnovu XDamagea/XShma u X11.",
|
||||
"Description[sr@latin]": "Kadrobafer za KRFB na osnovu XDamagea/XShma u X11.",
|
||||
"Description[sr]": "Кадробафер за КРФБ на основу Икс‑демиџа/Икс‑схма у Иксу11.",
|
||||
"Description[sv]": "X11 XDamage/XShm-baserad rambuffert för Krfb.",
|
||||
"Description[uk]": "Заснований на XDamage/XShm X11 буфер кадрів для KRfb.",
|
||||
"Description[x-test]": "xxX11 XDamage/XShm based Framebuffer for KRfb.xx",
|
||||
"Description[zh_CN]": "KRfb 的基于 X11 XDamage/XShm 的帧缓冲。",
|
||||
"Description[zh_TW]": "KRfb 的 X11 XDamage/XShm based Framebuffer",
|
||||
"EnabledByDefault": true,
|
||||
"Id": "x11",
|
||||
"License": "GPL",
|
||||
"Name": "X11 Framebuffer for KRfb",
|
||||
"Name[ca@valencia]": "«Framebuffer» del X11 per al KRfb.",
|
||||
"Name[ca]": "«Framebuffer» del X11 per al KRfb.",
|
||||
"Name[cs]": "X11 Framebuffer pro KRfb",
|
||||
"Name[de]": "X11-Framebuffer für KRfb",
|
||||
"Name[en_GB]": "X11 Framebuffer for KRfb",
|
||||
"Name[es]": "Framebuffer X11 para KRfb",
|
||||
"Name[fi]": "X11-kehyspuskuri KRfb:lle",
|
||||
"Name[gl]": "Framebuffer de X11 para KRfb",
|
||||
"Name[it]": "Framebuffer X11 per KRfb",
|
||||
"Name[ko]": "KRfb용 X11 프레임버퍼",
|
||||
"Name[nl]": "X11 framebuffer voor KRfb",
|
||||
"Name[pl]": "Bufor ramki X11 dla KRfb",
|
||||
"Name[pt]": "'Framebuffer' do X11 para o KRfb",
|
||||
"Name[pt_BR]": "Framebuffer do X11 para o KRfb",
|
||||
"Name[sk]": "X11 Framebuffer pre KRfb",
|
||||
"Name[sl]": "Slikovni medpomnilnik X11 za KRfb",
|
||||
"Name[sr@ijekavian]": "Икс11 кадробафер за КРФБ.",
|
||||
"Name[sr@ijekavianlatin]": "X11 kadrobafer za KRFB.",
|
||||
"Name[sr@latin]": "X11 kadrobafer za KRFB.",
|
||||
"Name[sr]": "Икс11 кадробафер за КРФБ.",
|
||||
"Name[sv]": "X11-rambuffert för Krfb",
|
||||
"Name[uk]": "Буфер кадрів X11 для KRfb",
|
||||
"Name[x-test]": "xxX11 Framebuffer for KRfbxx",
|
||||
"Name[zh_CN]": "XRfb 的 X11 帧缓冲",
|
||||
"Name[zh_TW]": "KRfb 的 X11 Framebuffer",
|
||||
"ServiceTypes": [
|
||||
"krfb/framebuffer"
|
||||
],
|
||||
"Version": "0.1",
|
||||
"Website": "http://www.kde.org"
|
||||
}
|
||||
}
|
||||
@@ -1,389 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "x11framebuffer.h"
|
||||
#include "x11framebuffer.moc"
|
||||
|
||||
#include <config-krfb.h>
|
||||
|
||||
#include <QX11Info>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XSHM
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#endif
|
||||
|
||||
class X11FrameBuffer::P
|
||||
{
|
||||
|
||||
public:
|
||||
#ifdef HAVE_XDAMAGE
|
||||
Damage damage;
|
||||
#endif
|
||||
#ifdef HAVE_XSHM
|
||||
XShmSegmentInfo shminfo;
|
||||
#endif
|
||||
|
||||
XImage *framebufferImage;
|
||||
XImage *updateTile;
|
||||
EvWidget *ev;
|
||||
bool useShm;
|
||||
int xdamageBaseEvent;
|
||||
bool running;
|
||||
};
|
||||
|
||||
X11FrameBuffer::X11FrameBuffer(WId id, QObject *parent)
|
||||
: FrameBuffer(id, parent), d(new X11FrameBuffer::P)
|
||||
{
|
||||
#ifdef HAVE_XSHM
|
||||
d->useShm = XShmQueryExtension(QX11Info::display());
|
||||
//qDebug() << "shm: " << d->useShm;
|
||||
#else
|
||||
d->useShm = false;
|
||||
#endif
|
||||
d->running = false;
|
||||
d->framebufferImage = XGetImage(QX11Info::display(),
|
||||
id,
|
||||
0,
|
||||
0,
|
||||
QApplication::desktop()->width(), //arg, must get a widget ???
|
||||
QApplication::desktop()->height(),
|
||||
AllPlanes,
|
||||
ZPixmap);
|
||||
|
||||
if (d->useShm) {
|
||||
#ifdef HAVE_XSHM
|
||||
d->updateTile = XShmCreateImage(QX11Info::display(),
|
||||
DefaultVisual(QX11Info::display(), 0),
|
||||
d->framebufferImage->bits_per_pixel,
|
||||
ZPixmap,
|
||||
NULL,
|
||||
&d->shminfo,
|
||||
32,
|
||||
32);
|
||||
d->shminfo.shmid = shmget(IPC_PRIVATE,
|
||||
d->updateTile->bytes_per_line * d->updateTile->height,
|
||||
IPC_CREAT | 0777);
|
||||
|
||||
d->shminfo.shmaddr = d->updateTile->data = (char *)
|
||||
shmat(d->shminfo.shmid, 0, 0);
|
||||
d->shminfo.readOnly = False;
|
||||
|
||||
XShmAttach(QX11Info::display(), &d->shminfo);
|
||||
#endif
|
||||
} else {
|
||||
;
|
||||
}
|
||||
|
||||
qDebug() << "Got image. bpp: " << d->framebufferImage->bits_per_pixel
|
||||
<< ", depth: " << d->framebufferImage->depth
|
||||
<< ", padded width: " << d->framebufferImage->bytes_per_line
|
||||
<< " (sent: " << d->framebufferImage->width * 4 << ")"
|
||||
<< endl;
|
||||
|
||||
fb = d->framebufferImage->data;
|
||||
#ifdef HAVE_XDAMAGE
|
||||
d->ev = new EvWidget(this);
|
||||
qApp->installX11EventFilter(d->ev);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
X11FrameBuffer::~X11FrameBuffer()
|
||||
{
|
||||
XDestroyImage(d->framebufferImage);
|
||||
#ifdef HAVE_XDAMAGE
|
||||
qApp->removeX11EventFilter(d->ev);
|
||||
#endif
|
||||
#ifdef HAVE_XSHM
|
||||
XShmDetach(QX11Info::display(), &d->shminfo);
|
||||
XDestroyImage(d->updateTile);
|
||||
shmdt(d->shminfo.shmaddr);
|
||||
shmctl(d->shminfo.shmid, IPC_RMID, 0);
|
||||
#endif
|
||||
delete d;
|
||||
fb = 0; // already deleted by XDestroyImage
|
||||
}
|
||||
|
||||
|
||||
int X11FrameBuffer::depth()
|
||||
{
|
||||
return d->framebufferImage->depth;
|
||||
}
|
||||
|
||||
int X11FrameBuffer::height()
|
||||
{
|
||||
return d->framebufferImage->height;
|
||||
}
|
||||
|
||||
int X11FrameBuffer::width()
|
||||
{
|
||||
return d->framebufferImage->width;
|
||||
}
|
||||
|
||||
int X11FrameBuffer::paddedWidth()
|
||||
{
|
||||
return d->framebufferImage->bytes_per_line;
|
||||
}
|
||||
|
||||
void X11FrameBuffer::getServerFormat(rfbPixelFormat &format)
|
||||
{
|
||||
format.bitsPerPixel = d->framebufferImage->bits_per_pixel;
|
||||
format.depth = d->framebufferImage->depth;
|
||||
format.trueColour = true;
|
||||
format.bigEndian = ((d->framebufferImage->bitmap_bit_order == MSBFirst) ? true : false);
|
||||
|
||||
if (format.bitsPerPixel == 8) {
|
||||
format.redShift = 0;
|
||||
format.greenShift = 3;
|
||||
format.blueShift = 6;
|
||||
format.redMax = 7;
|
||||
format.greenMax = 7;
|
||||
format.blueMax = 3;
|
||||
} else {
|
||||
format.redShift = 0;
|
||||
|
||||
if (d->framebufferImage->red_mask)
|
||||
while (!(d->framebufferImage->red_mask & (1 << format.redShift))) {
|
||||
format.redShift++;
|
||||
}
|
||||
|
||||
format.greenShift = 0;
|
||||
|
||||
if (d->framebufferImage->green_mask)
|
||||
while (!(d->framebufferImage->green_mask & (1 << format.greenShift))) {
|
||||
format.greenShift++;
|
||||
}
|
||||
|
||||
format.blueShift = 0;
|
||||
|
||||
if (d->framebufferImage->blue_mask)
|
||||
while (!(d->framebufferImage->blue_mask & (1 << format.blueShift))) {
|
||||
format.blueShift++;
|
||||
}
|
||||
|
||||
format.redMax = d->framebufferImage->red_mask >> format.redShift;
|
||||
format.greenMax = d->framebufferImage->green_mask >> format.greenShift;
|
||||
format.blueMax = d->framebufferImage->blue_mask >> format.blueShift;
|
||||
}
|
||||
}
|
||||
|
||||
void X11FrameBuffer::handleXDamage(XEvent *event)
|
||||
{
|
||||
#ifdef HAVE_XDAMAGE
|
||||
XDamageNotifyEvent *dev = (XDamageNotifyEvent *)event;
|
||||
QRect r(dev->area.x, dev->area.y, dev->area.width, dev->area.height);
|
||||
tiles.append(r);
|
||||
|
||||
/*if (!dev->more) {
|
||||
XDamageSubtract(QX11Info::display(),d->damage, None, None);
|
||||
}*/
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void X11FrameBuffer::cleanupRects()
|
||||
{
|
||||
|
||||
QList<QRect> cpy = tiles;
|
||||
bool inserted = false;
|
||||
tiles.clear();
|
||||
// //qDebug() << "before cleanup: " << cpy.size();
|
||||
foreach(const QRect & r, cpy) {
|
||||
if (tiles.size() > 0) {
|
||||
for (int i = 0; i < tiles.size(); i++) {
|
||||
// //qDebug() << r << tiles[i];
|
||||
if (r.intersects(tiles[i])) {
|
||||
tiles[i] |= r;
|
||||
inserted = true;
|
||||
break;
|
||||
// //qDebug() << "merged into " << tiles[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (!inserted) {
|
||||
tiles.append(r);
|
||||
// //qDebug() << "appended " << r;
|
||||
}
|
||||
} else {
|
||||
// //qDebug() << "appended " << r;
|
||||
tiles.append(r);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < tiles.size(); i++) {
|
||||
tiles[i].adjust(-30, -30, 30, 30);
|
||||
|
||||
if (tiles[i].top() < 0) {
|
||||
tiles[i].setTop(0);
|
||||
}
|
||||
|
||||
if (tiles[i].left() < 0) {
|
||||
tiles[i].setLeft(0);
|
||||
}
|
||||
|
||||
if (tiles[i].bottom() > d->framebufferImage->height) {
|
||||
tiles[i].setBottom(d->framebufferImage->height);
|
||||
}
|
||||
|
||||
if (tiles[i].right() > d->framebufferImage->width) {
|
||||
tiles[i].setRight(d->framebufferImage->width);
|
||||
}
|
||||
}
|
||||
|
||||
// //qDebug() << "after cleanup: " << tiles.size();
|
||||
}
|
||||
|
||||
void X11FrameBuffer::acquireEvents()
|
||||
{
|
||||
|
||||
XEvent ev;
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
while (XCheckTypedEvent(QX11Info::display(), d->xdamageBaseEvent + XDamageNotify, &ev)) {
|
||||
handleXDamage(&ev);
|
||||
}
|
||||
|
||||
XDamageSubtract(QX11Info::display(), d->damage, None, None);
|
||||
#endif
|
||||
}
|
||||
|
||||
QList< QRect > X11FrameBuffer::modifiedTiles()
|
||||
{
|
||||
QList<QRect> ret;
|
||||
|
||||
if (!d->running) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
qApp->processEvents(); // try to make sure every damage event goes trough;
|
||||
cleanupRects();
|
||||
QRect gl;
|
||||
|
||||
//d->useShm = false;
|
||||
if (tiles.size() > 0) {
|
||||
if (d->useShm) {
|
||||
#ifdef HAVE_XSHM
|
||||
|
||||
foreach(const QRect & r, tiles) {
|
||||
// //qDebug() << r;
|
||||
gl |= r;
|
||||
int y = r.y();
|
||||
int x = r.x();
|
||||
|
||||
while (x < r.right()) {
|
||||
while (y < r.bottom()) {
|
||||
if (y + d->updateTile->height > d->framebufferImage->height) {
|
||||
y = d->framebufferImage->height - d->updateTile->height;
|
||||
}
|
||||
|
||||
if (x + d->updateTile->width > d->framebufferImage->width) {
|
||||
x = d->framebufferImage->width - d->updateTile->width;
|
||||
}
|
||||
|
||||
// //qDebug() << "x: " << x << " (" << r.x() << ") y: " << y << " (" << r.y() << ") " << r;
|
||||
XShmGetImage(QX11Info::display(), win, d->updateTile, x, y, AllPlanes);
|
||||
int pxsize = d->framebufferImage->bits_per_pixel / 8;
|
||||
char *dest = fb + ((d->framebufferImage->bytes_per_line * y) + (x * pxsize));
|
||||
char *src = d->updateTile->data;
|
||||
|
||||
for (int i = 0; i < d->updateTile->height; i++) {
|
||||
memcpy(dest, src, d->updateTile->bytes_per_line);
|
||||
dest += d->framebufferImage->bytes_per_line;
|
||||
src += d->updateTile->bytes_per_line;
|
||||
}
|
||||
|
||||
y += d->updateTile->height;
|
||||
}
|
||||
|
||||
x += d->updateTile->width;
|
||||
y = r.y();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
foreach(const QRect & r, tiles) {
|
||||
XGetSubImage(QX11Info::display(),
|
||||
win,
|
||||
r.left(),
|
||||
r.top(),
|
||||
r.width(),
|
||||
r.height(),
|
||||
AllPlanes,
|
||||
ZPixmap,
|
||||
d->framebufferImage,
|
||||
r.left(),
|
||||
r.top()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// //qDebug() << "tot: " << gl;
|
||||
// //qDebug() << tiles.size();
|
||||
ret = tiles;
|
||||
tiles.clear();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void X11FrameBuffer::startMonitor()
|
||||
{
|
||||
d->running = true;
|
||||
#ifdef HAVE_XDAMAGE
|
||||
d->damage = XDamageCreate(QX11Info::display(), win, XDamageReportRawRectangles);
|
||||
XDamageSubtract(QX11Info::display(), d->damage, None, None);
|
||||
#endif
|
||||
}
|
||||
|
||||
void X11FrameBuffer::stopMonitor()
|
||||
{
|
||||
d->running = false;
|
||||
#ifdef HAVE_XDAMAGE
|
||||
XDamageDestroy(QX11Info::display(), d->damage);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
EvWidget::EvWidget(X11FrameBuffer *x11fb)
|
||||
: QWidget(0), fb(x11fb)
|
||||
{
|
||||
#ifdef HAVE_XDAMAGE
|
||||
int er;
|
||||
XDamageQueryExtension(QX11Info::display(), &xdamageBaseEvent, &er);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool EvWidget::x11Event(XEvent *event)
|
||||
{
|
||||
#ifdef HAVE_XDAMAGE
|
||||
|
||||
if (event->type == xdamageBaseEvent + XDamageNotify) {
|
||||
fb->handleXDamage(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
#ifndef KRFB_FRAMEBUFFER_X11_X11FRAMEBUFFER_H
|
||||
#define KRFB_FRAMEBUFFER_X11_X11FRAMEBUFFER_H
|
||||
|
||||
#include <framebuffer.h>
|
||||
#include <QWidget>
|
||||
|
||||
class X11FrameBuffer;
|
||||
typedef union _XEvent XEvent;
|
||||
|
||||
class EvWidget: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EvWidget(X11FrameBuffer *x11fb);
|
||||
|
||||
protected:
|
||||
bool x11Event(XEvent *event);
|
||||
|
||||
private:
|
||||
X11FrameBuffer *fb;
|
||||
int xdamageBaseEvent;
|
||||
};
|
||||
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class X11FrameBuffer : public FrameBuffer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
X11FrameBuffer(WId id, QObject *parent = 0);
|
||||
|
||||
~X11FrameBuffer();
|
||||
|
||||
QList<QRect> modifiedTiles() override;
|
||||
int depth() override;
|
||||
int height() override;
|
||||
int width() override;
|
||||
int paddedWidth() override;
|
||||
void getServerFormat(rfbPixelFormat &format) override;
|
||||
void startMonitor() override;
|
||||
void stopMonitor() override;
|
||||
|
||||
|
||||
void handleXDamage(XEvent *event);
|
||||
private:
|
||||
void cleanupRects();
|
||||
void acquireEvents();
|
||||
|
||||
class P;
|
||||
P *const d;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,45 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "x11framebufferplugin.h"
|
||||
|
||||
#include "x11framebuffer.h"
|
||||
|
||||
#include <KPluginFactory>
|
||||
|
||||
K_PLUGIN_FACTORY_WITH_JSON(X11FrameBufferPluginFactory, "krfb_framebuffer_x11.json",
|
||||
registerPlugin<X11FrameBufferPlugin>();)
|
||||
|
||||
X11FrameBufferPlugin::X11FrameBufferPlugin(QObject *parent, const QVariantList &args)
|
||||
: FrameBufferPlugin(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
X11FrameBufferPlugin::~X11FrameBufferPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
FrameBuffer *X11FrameBufferPlugin::frameBuffer(WId id)
|
||||
{
|
||||
return new X11FrameBuffer(id);
|
||||
}
|
||||
|
||||
#include "x11framebufferplugin.moc"
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef KRFB_FRAMEBUFFER_X11_X11FRAMEBUFFERPLUGIN_H
|
||||
#define KRFB_FRAMEBUFFER_X11_X11FRAMEBUFFERPLUGIN_H
|
||||
|
||||
#include "framebufferplugin.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class FrameBuffer;
|
||||
|
||||
class X11FrameBufferPlugin : public FrameBufferPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
X11FrameBufferPlugin(QObject *parent, const QVariantList &args);
|
||||
virtual ~X11FrameBufferPlugin();
|
||||
|
||||
FrameBuffer *frameBuffer(WId id) override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(X11FrameBufferPlugin)
|
||||
};
|
||||
|
||||
|
||||
#endif // Header guard
|
||||
|
||||
38
framebuffers/xcb/CMakeLists.txt
Normal file
@@ -0,0 +1,38 @@
|
||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
set (krfb_framebuffer_xcb_SRCS
|
||||
xcb_framebufferplugin.cpp
|
||||
xcb_framebuffer.cpp
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(krfb_framebuffer_xcb_SRCS
|
||||
HEADER krfb_fb_xcb_debug.h
|
||||
IDENTIFIER KRFB_FB_XCB
|
||||
CATEGORY_NAME krfb.framebuffer.xcb
|
||||
DESCRIPTION "KRFB XCB framebuffer plugin"
|
||||
EXPORT KRFB
|
||||
)
|
||||
|
||||
add_library(krfb_framebuffer_xcb MODULE ${krfb_framebuffer_xcb_SRCS})
|
||||
|
||||
target_link_libraries (krfb_framebuffer_xcb
|
||||
Qt::Core
|
||||
Qt::Gui
|
||||
Qt::GuiPrivate
|
||||
XCB::XCB
|
||||
XCB::RENDER
|
||||
XCB::SHAPE
|
||||
XCB::XFIXES
|
||||
XCB::DAMAGE
|
||||
XCB::SHM
|
||||
XCB::IMAGE
|
||||
KF6::CoreAddons
|
||||
krfbprivate
|
||||
)
|
||||
|
||||
set_target_properties(krfb_framebuffer_xcb PROPERTIES OUTPUT_NAME xcb)
|
||||
install (TARGETS krfb_framebuffer_xcb
|
||||
DESTINATION ${KDE_INSTALL_PLUGINDIR}/krfb/framebuffer
|
||||
)
|
||||
6
framebuffers/xcb/xcb.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"X-KDE-OnlyShowOnQtPlatforms": [
|
||||
"xcb"
|
||||
]
|
||||
}
|
||||
|
||||
700
framebuffers/xcb/xcb_framebuffer.cpp
Normal file
@@ -0,0 +1,700 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2017 Alexey Min <alexey.min@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "xcb_framebuffer.h"
|
||||
#include "krfb_fb_xcb_debug.h"
|
||||
|
||||
#include <xcb/damage.h>
|
||||
#include <xcb/shm.h>
|
||||
#include <xcb/xcb_image.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#include <QApplication>
|
||||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
#include <QtGui/private/qtx11extras_p.h>
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
|
||||
class KrfbXCBEventFilter : public QAbstractNativeEventFilter
|
||||
{
|
||||
public:
|
||||
KrfbXCBEventFilter(XCBFrameBuffer *owner);
|
||||
|
||||
public:
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override;
|
||||
|
||||
public:
|
||||
int xdamageBaseEvent;
|
||||
int xdamageBaseError;
|
||||
int xshmBaseEvent;
|
||||
int xshmBaseError;
|
||||
bool xshmAvail;
|
||||
XCBFrameBuffer *fb_owner;
|
||||
};
|
||||
|
||||
KrfbXCBEventFilter::KrfbXCBEventFilter(XCBFrameBuffer *owner)
|
||||
: xdamageBaseEvent(0)
|
||||
, xdamageBaseError(0)
|
||||
, xshmBaseEvent(0)
|
||||
, xshmBaseError(0)
|
||||
, xshmAvail(false)
|
||||
, fb_owner(owner)
|
||||
{
|
||||
const xcb_query_extension_reply_t *xdamage_data = xcb_get_extension_data(
|
||||
QX11Info::connection(), &xcb_damage_id);
|
||||
if (xdamage_data) {
|
||||
// also query extension version!
|
||||
// ATTENTION: if we don't do that, xcb_damage_create() will always FAIL!
|
||||
xcb_damage_query_version_reply_t *xdamage_version = xcb_damage_query_version_reply(
|
||||
QX11Info::connection(),
|
||||
xcb_damage_query_version(
|
||||
QX11Info::connection(),
|
||||
XCB_DAMAGE_MAJOR_VERSION,
|
||||
XCB_DAMAGE_MINOR_VERSION),
|
||||
nullptr);
|
||||
if (!xdamage_version) {
|
||||
qWarning() << "xcb framebuffer: ERROR: Failed to get XDamage extension version!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: XDamage extension version:" << xdamage_version->major_version << "." << xdamage_version->minor_version;
|
||||
#endif
|
||||
|
||||
free(xdamage_version);
|
||||
|
||||
xdamageBaseEvent = xdamage_data->first_event;
|
||||
xdamageBaseError = xdamage_data->first_error;
|
||||
|
||||
// XShm presence is optional. If it is present, all image getting
|
||||
// operations will be faster, without XShm it will only be slower.
|
||||
const xcb_query_extension_reply_t *xshm_data = xcb_get_extension_data(
|
||||
QX11Info::connection(), &xcb_shm_id);
|
||||
if (xshm_data) {
|
||||
xshmAvail = true;
|
||||
xshmBaseEvent = xshm_data->first_event;
|
||||
xshmBaseError = xshm_data->first_error;
|
||||
} else {
|
||||
xshmAvail = false;
|
||||
qWarning() << "xcb framebuffer: WARNING: XSHM extension not available!";
|
||||
}
|
||||
} else {
|
||||
// if there is no xdamage available, this plugin can be considered useless anyway.
|
||||
// you can use just qt framebuffer plugin instead...
|
||||
qWarning() << "xcb framebuffer: ERROR: no XDamage extension available. I am useless.";
|
||||
qWarning() << "xcb framebuffer: use qt framebuffer plugin instead.";
|
||||
}
|
||||
}
|
||||
|
||||
bool KrfbXCBEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||
void *message, qintptr *result)
|
||||
{
|
||||
Q_UNUSED(result); // "result" is only used on windows
|
||||
|
||||
if (xdamageBaseEvent == 0) {
|
||||
return false; // no xdamage extension
|
||||
}
|
||||
|
||||
if (eventType == "xcb_generic_event_t") {
|
||||
auto ev = static_cast<xcb_generic_event_t *>(message);
|
||||
if ((ev->response_type & 0x7F) == (xdamageBaseEvent + XCB_DAMAGE_NOTIFY)) {
|
||||
// this is xdamage notification
|
||||
this->fb_owner->handleXDamageNotify(ev);
|
||||
return true; // filter out this event, stop its processing
|
||||
}
|
||||
}
|
||||
|
||||
// continue event processing
|
||||
return false;
|
||||
}
|
||||
|
||||
class XCBFrameBuffer::P
|
||||
{
|
||||
public:
|
||||
xcb_damage_damage_t damage;
|
||||
xcb_shm_segment_info_t shminfo;
|
||||
xcb_screen_t *rootScreen; // X screen info (all monitors)
|
||||
xcb_image_t *framebufferImage;
|
||||
xcb_image_t *updateTile;
|
||||
|
||||
KrfbXCBEventFilter *x11EvtFilter;
|
||||
|
||||
bool running;
|
||||
|
||||
QRect area; // capture area, primary monitor coordinates
|
||||
WId win;
|
||||
};
|
||||
|
||||
static xcb_screen_t *get_xcb_screen(xcb_connection_t *conn, int screen_num)
|
||||
{
|
||||
xcb_screen_t *screen = nullptr;
|
||||
xcb_screen_iterator_t screens_iter = xcb_setup_roots_iterator(xcb_get_setup(conn));
|
||||
for (; screens_iter.rem; --screen_num, xcb_screen_next(&screens_iter)) {
|
||||
if (screen_num == 0) {
|
||||
screen = screens_iter.data;
|
||||
}
|
||||
}
|
||||
return screen;
|
||||
}
|
||||
|
||||
XCBFrameBuffer::XCBFrameBuffer(QObject *parent)
|
||||
: FrameBuffer(parent)
|
||||
, d(new XCBFrameBuffer::P)
|
||||
{
|
||||
d->running = false;
|
||||
d->damage = XCB_NONE;
|
||||
d->framebufferImage = nullptr;
|
||||
d->shminfo.shmaddr = nullptr;
|
||||
d->shminfo.shmid = XCB_NONE;
|
||||
d->shminfo.shmseg = XCB_NONE;
|
||||
d->updateTile = nullptr;
|
||||
d->area.setRect(0, 0, 0, 0);
|
||||
d->x11EvtFilter = new KrfbXCBEventFilter(this);
|
||||
d->rootScreen = get_xcb_screen(QX11Info::connection(), QX11Info::appScreen());
|
||||
|
||||
this->fb = nullptr;
|
||||
|
||||
QScreen *primaryScreen = QGuiApplication::primaryScreen();
|
||||
if (primaryScreen) {
|
||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
||||
d->win = reinterpret_cast<WId>(native->nativeResourceForScreen(QByteArrayLiteral("rootwindow"), primaryScreen));
|
||||
qreal scaleFactor = primaryScreen->devicePixelRatio();
|
||||
d->area = {primaryScreen->geometry().topLeft() * scaleFactor,
|
||||
primaryScreen->geometry().bottomRight() * scaleFactor};
|
||||
|
||||
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: Primary screen: " << primaryScreen->name()
|
||||
<< ", geometry: " << primaryScreen->geometry()
|
||||
<< ", device scaling: " << scaleFactor
|
||||
<< ", native size: " << d->area
|
||||
<< ", depth: " << primaryScreen->depth();
|
||||
} else {
|
||||
qWarning() << "xcb framebuffer: ERROR: Failed to get application's primary screen info!";
|
||||
return;
|
||||
}
|
||||
|
||||
d->framebufferImage = xcb_image_get(QX11Info::connection(),
|
||||
d->win,
|
||||
d->area.left(),
|
||||
d->area.top(),
|
||||
d->area.width(),
|
||||
d->area.height(),
|
||||
0xFFFFFFFF, // == Xlib: AllPlanes ((unsigned long)~0L)
|
||||
XCB_IMAGE_FORMAT_Z_PIXMAP);
|
||||
if (d->framebufferImage) {
|
||||
#ifdef _DEBUG
|
||||
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: Got primary screen image. bpp: " << d->framebufferImage->bpp
|
||||
<< ", size (" << d->framebufferImage->width << d->framebufferImage->height << ")"
|
||||
<< ", depth: " << d->framebufferImage->depth
|
||||
<< ", padded width: " << d->framebufferImage->stride;
|
||||
#endif
|
||||
this->fb = (char *)d->framebufferImage->data;
|
||||
} else {
|
||||
qWarning() << "xcb framebuffer: ERROR: Failed to get primary screen image!";
|
||||
return;
|
||||
}
|
||||
|
||||
// all XShm operations should take place only if Xshm extension was loaded
|
||||
if (d->x11EvtFilter->xshmAvail) {
|
||||
// Create xcb_image_t structure, but do not automatically allocate memory
|
||||
// for image data storage - it will be allocated as shared memory.
|
||||
// "If base == 0 and bytes == ~0 and data == 0, no storage will be auto-allocated."
|
||||
// Width and height of the image = size of the capture area.
|
||||
d->updateTile = xcb_image_create_native(
|
||||
QX11Info::connection(),
|
||||
d->area.width(), // width
|
||||
d->area.height(), // height
|
||||
XCB_IMAGE_FORMAT_Z_PIXMAP, // image format
|
||||
d->rootScreen->root_depth, // depth
|
||||
nullptr, // base address = 0
|
||||
(uint32_t)~0, // bytes = 0xffffffff
|
||||
nullptr); // data = 0
|
||||
if (d->updateTile) {
|
||||
#ifdef _DEBUG
|
||||
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: Successfully created new empty image in native format"
|
||||
<< "\n size: " << d->updateTile->width << "x" << d->updateTile->height
|
||||
<< "(stride: " << d->updateTile->stride << ")"
|
||||
<< "\n bpp, depth: " << d->updateTile->bpp << d->updateTile->depth // 32, 24
|
||||
<< "\n addr of base, data: " << d->updateTile->base << (void *)d->updateTile->data
|
||||
<< "\n size: " << d->updateTile->size
|
||||
<< "\n image byte order = " << d->updateTile->byte_order // == 0 .._LSB_FIRST
|
||||
<< "\n image bit order = " << d->updateTile->bit_order // == 1 .._MSB_FIRST
|
||||
<< "\n image plane_mask = " << d->updateTile->plane_mask; // == 16777215 == 0x00FFFFFF
|
||||
#endif
|
||||
|
||||
// allocate shared memory block only once, make its size large enough
|
||||
// to fit whole capture area (d->area rect)
|
||||
// so, we get as many bytes as needed for image (updateTile->size)
|
||||
d->shminfo.shmid = shmget(IPC_PRIVATE, d->updateTile->size, IPC_CREAT | 0777);
|
||||
// attached shared memory address is stored both in shminfo structure and in xcb_image_t->data
|
||||
d->shminfo.shmaddr = (uint8_t *)shmat(d->shminfo.shmid, nullptr, 0);
|
||||
d->updateTile->data = d->shminfo.shmaddr;
|
||||
// we keep updateTile->base == NULL here, so xcb_image_destroy() will not attempt
|
||||
// to free this block, just in case.
|
||||
|
||||
// attach this shm segment also to X server
|
||||
d->shminfo.shmseg = xcb_generate_id(QX11Info::connection());
|
||||
xcb_shm_attach(QX11Info::connection(), d->shminfo.shmseg, d->shminfo.shmid, 0);
|
||||
|
||||
#ifdef _DEBUG
|
||||
qCDebug(KRFB_FB_XCB) << " shm id: " << d->shminfo.shmseg << ", addr: " << (void *)d->shminfo.shmaddr;
|
||||
#endif
|
||||
|
||||
// will return 1 on success (yes!)
|
||||
int shmget_res = xcb_image_shm_get(
|
||||
QX11Info::connection(),
|
||||
d->win,
|
||||
d->updateTile,
|
||||
d->shminfo,
|
||||
d->area.left(), // x
|
||||
d->area.top(), // y (size taken from image structure itself)?
|
||||
0xFFFFFFFF);
|
||||
|
||||
if (shmget_res == 0) {
|
||||
// error! shared mem not working?
|
||||
// will not use shared mem! detach and cleanup
|
||||
xcb_shm_detach(QX11Info::connection(), d->shminfo.shmseg);
|
||||
shmdt(d->shminfo.shmaddr);
|
||||
shmctl(d->shminfo.shmid, IPC_RMID, nullptr); // mark shm segment as removed
|
||||
d->x11EvtFilter->xshmAvail = false;
|
||||
d->shminfo.shmaddr = nullptr;
|
||||
d->shminfo.shmid = XCB_NONE;
|
||||
d->shminfo.shmseg = XCB_NONE;
|
||||
qWarning() << "xcb framebuffer: ERROR: xcb_image_shm_get() result: " << shmget_res;
|
||||
}
|
||||
|
||||
// image is freed, and recreated again for every new damage rectangle
|
||||
// data was allocated manually and points to shared mem;
|
||||
// tell xcb_image_destroy() do not free image data
|
||||
d->updateTile->data = nullptr;
|
||||
xcb_image_destroy(d->updateTile);
|
||||
d->updateTile = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: XCBFrameBuffer(), xshm base event = " << d->x11EvtFilter->xshmBaseEvent
|
||||
<< ", xshm base error = " << d->x11EvtFilter->xdamageBaseError
|
||||
<< ", xdamage base event = " << d->x11EvtFilter->xdamageBaseEvent
|
||||
<< ", xdamage base error = " << d->x11EvtFilter->xdamageBaseError;
|
||||
#endif
|
||||
|
||||
QCoreApplication::instance()->installNativeEventFilter(d->x11EvtFilter);
|
||||
}
|
||||
|
||||
XCBFrameBuffer::~XCBFrameBuffer()
|
||||
{
|
||||
// first - uninstall x11 event filter
|
||||
QCoreApplication::instance()->removeNativeEventFilter(d->x11EvtFilter);
|
||||
//
|
||||
if (d->framebufferImage) {
|
||||
xcb_image_destroy(d->framebufferImage);
|
||||
fb = nullptr; // image data was already destroyed by above call
|
||||
}
|
||||
if (d->x11EvtFilter->xshmAvail) {
|
||||
// detach shared memory
|
||||
if (d->shminfo.shmseg != XCB_NONE) {
|
||||
xcb_shm_detach(QX11Info::connection(), d->shminfo.shmseg); // detach from X server
|
||||
}
|
||||
if (d->shminfo.shmaddr) {
|
||||
shmdt(d->shminfo.shmaddr); // detach addr from our address space
|
||||
}
|
||||
if (d->shminfo.shmid != XCB_NONE) {
|
||||
shmctl(d->shminfo.shmid, IPC_RMID, nullptr); // mark shm segment as removed
|
||||
}
|
||||
}
|
||||
// and delete image used for shared mem
|
||||
if (d->updateTile) {
|
||||
d->updateTile->base = nullptr;
|
||||
d->updateTile->data = nullptr;
|
||||
xcb_image_destroy(d->updateTile);
|
||||
}
|
||||
// we don't use d->x11EvtFilter anymore, can delete it now
|
||||
if (d->x11EvtFilter) {
|
||||
delete d->x11EvtFilter;
|
||||
}
|
||||
delete d;
|
||||
}
|
||||
|
||||
int XCBFrameBuffer::depth()
|
||||
{
|
||||
if (d->framebufferImage) {
|
||||
return d->framebufferImage->depth;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XCBFrameBuffer::height()
|
||||
{
|
||||
if (d->framebufferImage) {
|
||||
return d->framebufferImage->height;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XCBFrameBuffer::width()
|
||||
{
|
||||
if (d->framebufferImage) {
|
||||
return d->framebufferImage->width;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XCBFrameBuffer::paddedWidth()
|
||||
{
|
||||
if (d->framebufferImage) {
|
||||
return d->framebufferImage->stride;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void XCBFrameBuffer::getServerFormat(rfbPixelFormat &format)
|
||||
{
|
||||
if (!d->framebufferImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get information about XCB visual params
|
||||
xcb_visualtype_t *root_visualtype = nullptr; // visual info
|
||||
if (d->rootScreen) {
|
||||
xcb_visualid_t root_visual = d->rootScreen->root_visual;
|
||||
xcb_depth_iterator_t depth_iter;
|
||||
// To get the xcb_visualtype_t structure, it's a bit less easy.
|
||||
// You have to get the xcb_screen_t structure that you want, get its
|
||||
// root_visual member, then iterate over the xcb_depth_t's and the
|
||||
// xcb_visualtype_t's, and compare the xcb_visualid_t of these
|
||||
// xcb_visualtype_ts: with root_visual
|
||||
depth_iter = xcb_screen_allowed_depths_iterator(d->rootScreen);
|
||||
for (; depth_iter.rem; xcb_depth_next(&depth_iter)) {
|
||||
xcb_visualtype_iterator_t visual_iter;
|
||||
visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
|
||||
for (; visual_iter.rem; xcb_visualtype_next(&visual_iter)) {
|
||||
if (root_visual == visual_iter.data->visual_id) {
|
||||
root_visualtype = visual_iter.data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fill in format common info
|
||||
format.bitsPerPixel = d->framebufferImage->bpp;
|
||||
format.depth = d->framebufferImage->depth;
|
||||
format.trueColour = true; // not using color palettes
|
||||
format.bigEndian = false; // always false for ZPIXMAP format!
|
||||
|
||||
// information about pixels layout
|
||||
|
||||
if (root_visualtype) {
|
||||
#ifdef _DEBUG
|
||||
qDebug("xcb framebuffer: Got info about root visual:\n"
|
||||
" bits per rgb value: %d\n"
|
||||
" red mask: %08x\n"
|
||||
" green mask: %08x\n"
|
||||
" blue mask: %08x\n",
|
||||
(int)root_visualtype->bits_per_rgb_value,
|
||||
root_visualtype->red_mask,
|
||||
root_visualtype->green_mask,
|
||||
root_visualtype->blue_mask);
|
||||
#endif
|
||||
|
||||
// calculate shifts
|
||||
format.redShift = 0;
|
||||
if (root_visualtype->red_mask) {
|
||||
while (!(root_visualtype->red_mask & (1 << format.redShift))) {
|
||||
format.redShift++;
|
||||
}
|
||||
}
|
||||
format.greenShift = 0;
|
||||
if (root_visualtype->green_mask) {
|
||||
while (!(root_visualtype->green_mask & (1 << format.greenShift))) {
|
||||
format.greenShift++;
|
||||
}
|
||||
}
|
||||
format.blueShift = 0;
|
||||
if (root_visualtype->blue_mask) {
|
||||
while (!(root_visualtype->blue_mask & (1 << format.blueShift))) {
|
||||
format.blueShift++;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate pixel max value.
|
||||
// NOTE: bits_per_rgb_value is unreliable, thus should be avoided.
|
||||
format.redMax = root_visualtype->red_mask >> format.redShift;
|
||||
format.greenMax = root_visualtype->green_mask >> format.greenShift;
|
||||
format.blueMax = root_visualtype->blue_mask >> format.blueShift;
|
||||
|
||||
#ifdef _DEBUG
|
||||
qCDebug(KRFB_FB_XCB,
|
||||
" Calculated redShift = %d\n"
|
||||
" Calculated greenShift = %d\n"
|
||||
" Calculated blueShift = %d\n"
|
||||
" Calculated max values: R%d G%d B%d",
|
||||
format.redShift, format.greenShift, format.blueShift format.redMax, format.greenMax, format.blueMax);
|
||||
#endif
|
||||
} else {
|
||||
// some kind of fallback (unlikely code execution will go this way)
|
||||
// idea taken from qt framefuffer sources
|
||||
if (format.bitsPerPixel == 8) {
|
||||
format.redShift = 0;
|
||||
format.greenShift = 3;
|
||||
format.blueShift = 6;
|
||||
format.redMax = 7;
|
||||
format.greenMax = 7;
|
||||
format.blueMax = 3;
|
||||
} else if (format.bitsPerPixel == 16) {
|
||||
// TODO: 16 bits per pixel format ??
|
||||
// what format of pixels does X server use for 16-bpp?
|
||||
} else if (format.bitsPerPixel == 32) {
|
||||
format.redMax = 0xff;
|
||||
format.greenMax = 0xff;
|
||||
format.blueMax = 0xff;
|
||||
if (format.bigEndian) {
|
||||
format.redShift = 0;
|
||||
format.greenShift = 8;
|
||||
format.blueShift = 16;
|
||||
} else {
|
||||
format.redShift = 16;
|
||||
format.greenShift = 8;
|
||||
format.blueShift = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function contents was taken from X11 framebuffer source code.
|
||||
* It simply several intersecting rectangles into one bigger rect.
|
||||
* Non-intersecting rects are treated as different rects and exist
|
||||
* separately in this->tiles QList.
|
||||
*/
|
||||
void XCBFrameBuffer::cleanupRects()
|
||||
{
|
||||
QList<QRect> cpy = tiles;
|
||||
bool inserted = false;
|
||||
tiles.clear();
|
||||
|
||||
QListIterator<QRect> iter(cpy);
|
||||
while (iter.hasNext()) {
|
||||
const QRect &r = iter.next();
|
||||
// skip rects not intersecting with primary monitor
|
||||
if (!r.intersects(d->area)) {
|
||||
continue;
|
||||
}
|
||||
// only take intersection of this rect with primary monitor rect
|
||||
QRect ri = r.intersected(d->area);
|
||||
|
||||
if (tiles.size() > 0) {
|
||||
for (auto &tile : tiles) {
|
||||
// if current rect has intersection with tile, unite them
|
||||
if (ri.intersects(tile)) {
|
||||
tile |= ri;
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!inserted) {
|
||||
// else, append to list as different rect
|
||||
tiles.append(ri);
|
||||
}
|
||||
} else {
|
||||
// tiles list is empty, append first item
|
||||
tiles.append(ri);
|
||||
}
|
||||
}
|
||||
|
||||
// increase all rectangles size by 30 pixels each side.
|
||||
// limit coordinates to primary monitor boundaries.
|
||||
for (auto &tile : tiles) {
|
||||
tile.adjust(-30, -30, 30, 30);
|
||||
if (tile.top() < d->area.top()) {
|
||||
tile.setTop(d->area.top());
|
||||
}
|
||||
if (tile.bottom() > d->area.bottom()) {
|
||||
tile.setBottom(d->area.bottom());
|
||||
}
|
||||
//
|
||||
if (tile.left() < d->area.left()) {
|
||||
tile.setLeft(d->area.left());
|
||||
}
|
||||
if (tile.right() > d->area.right()) {
|
||||
tile.setRight(d->area.right());
|
||||
}
|
||||
// move update rects so that they are positioned relative to
|
||||
// framebuffer image, not whole screen
|
||||
tile.moveTo(tile.left() - d->area.left(),
|
||||
tile.top() - d->area.top());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called by RfbServerManager::updateScreens()
|
||||
* approximately every 50ms (!!), driven by QTimer to get all
|
||||
* modified rectangles on the screen
|
||||
*/
|
||||
QList<QRect> XCBFrameBuffer::modifiedTiles()
|
||||
{
|
||||
QList<QRect> ret;
|
||||
if (!d->running) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
cleanupRects();
|
||||
|
||||
if (tiles.size() > 0) {
|
||||
if (d->x11EvtFilter->xshmAvail) {
|
||||
// loop over all damage rectangles gathered up to this time
|
||||
QListIterator<QRect> iter(tiles);
|
||||
// foreach(const QRect &r, tiles) {
|
||||
while (iter.hasNext()) {
|
||||
const QRect &r = iter.next();
|
||||
|
||||
// get image data into shared memory segment
|
||||
// now rects are positioned relative to framebufferImage,
|
||||
// but we need to get image from the whole screen, so
|
||||
// translate the coordinates
|
||||
xcb_shm_get_image_cookie_t sgi_cookie = xcb_shm_get_image(
|
||||
QX11Info::connection(),
|
||||
d->win,
|
||||
d->area.left() + r.left(),
|
||||
d->area.top() + r.top(),
|
||||
r.width(),
|
||||
r.height(),
|
||||
0xFFFFFFFF,
|
||||
XCB_IMAGE_FORMAT_Z_PIXMAP,
|
||||
d->shminfo.shmseg,
|
||||
0);
|
||||
|
||||
xcb_shm_get_image_reply_t *sgi_reply = xcb_shm_get_image_reply(
|
||||
QX11Info::connection(), sgi_cookie, nullptr);
|
||||
if (sgi_reply) {
|
||||
// create temporary image to get update rect contents into
|
||||
d->updateTile = xcb_image_create_native(
|
||||
QX11Info::connection(),
|
||||
r.width(),
|
||||
r.height(),
|
||||
XCB_IMAGE_FORMAT_Z_PIXMAP,
|
||||
d->rootScreen->root_depth,
|
||||
nullptr, // base == 0
|
||||
(uint32_t)~0, // bytes == ~0
|
||||
nullptr);
|
||||
|
||||
if (d->updateTile) {
|
||||
d->updateTile->data = d->shminfo.shmaddr;
|
||||
|
||||
// copy pixels from this damage rectangle image
|
||||
// to our total framebuffer image
|
||||
int pxsize = d->framebufferImage->bpp / 8;
|
||||
char *dest = fb + ((d->framebufferImage->stride * r.top()) + (r.left() * pxsize));
|
||||
char *src = (char *)d->updateTile->data;
|
||||
for (int i = 0; i < d->updateTile->height; i++) {
|
||||
memcpy(dest, src, d->updateTile->stride); // copy whole row of pixels
|
||||
dest += d->framebufferImage->stride;
|
||||
src += d->updateTile->stride;
|
||||
}
|
||||
|
||||
// delete temporary image
|
||||
d->updateTile->data = nullptr;
|
||||
xcb_image_destroy(d->updateTile);
|
||||
d->updateTile = nullptr;
|
||||
}
|
||||
|
||||
free(sgi_reply);
|
||||
}
|
||||
} // foreach
|
||||
} else {
|
||||
// not using shared memory
|
||||
// will use just xcb_image_get() and copy pixels
|
||||
for (const QRect &r : std::as_const(tiles)) {
|
||||
// I did not find XGetSubImage() analog in XCB!!
|
||||
// need function that copies pixels from one image to another
|
||||
xcb_image_t *damagedImage = xcb_image_get(
|
||||
QX11Info::connection(),
|
||||
d->win,
|
||||
r.left(),
|
||||
r.top(),
|
||||
r.width(),
|
||||
r.height(),
|
||||
0xFFFFFFFF, // AllPlanes
|
||||
XCB_IMAGE_FORMAT_Z_PIXMAP);
|
||||
// manually copy pixels
|
||||
int pxsize = d->framebufferImage->bpp / 8;
|
||||
char *dest = fb + ((d->framebufferImage->stride * r.top()) + (r.left() * pxsize));
|
||||
char *src = (char *)damagedImage->data;
|
||||
// loop every row in damaged image
|
||||
for (int i = 0; i < damagedImage->height; i++) {
|
||||
// copy whole row of pixels from src image to dest
|
||||
memcpy(dest, src, damagedImage->stride);
|
||||
dest += d->framebufferImage->stride; // move 1 row down in dest
|
||||
src += damagedImage->stride; // move 1 row down in src
|
||||
}
|
||||
//
|
||||
xcb_image_destroy(damagedImage);
|
||||
}
|
||||
}
|
||||
} // if (tiles.size() > 0)
|
||||
|
||||
ret = tiles;
|
||||
tiles.clear();
|
||||
// ^^ If we clear here all our known "damage areas", then we can also clear
|
||||
// damaged area for xdamage? No, we don't need to in our case
|
||||
// (XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES report mode)
|
||||
// xcb_damage_subtract(QX11Info::connection(), d->damage, XCB_NONE, XCB_NONE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void XCBFrameBuffer::startMonitor()
|
||||
{
|
||||
if (d->running) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->running = true;
|
||||
d->damage = xcb_generate_id(QX11Info::connection());
|
||||
xcb_damage_create(QX11Info::connection(), d->damage, d->win,
|
||||
XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES);
|
||||
|
||||
// (currently) we do not call xcb_damage_subtract() EVER, because
|
||||
// RAW rectangles are reported. every time some area of the screen
|
||||
// was changed, we get only that rectangle
|
||||
// xcb_damage_subtract(QX11Info::connection(), d->damage, XCB_NONE, XCB_NONE);
|
||||
}
|
||||
|
||||
void XCBFrameBuffer::stopMonitor()
|
||||
{
|
||||
if (!d->running) {
|
||||
return;
|
||||
}
|
||||
d->running = false;
|
||||
xcb_damage_destroy(QX11Info::connection(), d->damage);
|
||||
}
|
||||
|
||||
// void XCBFrameBuffer::acquireEvents() {} // this function was totally unused
|
||||
// in X11 framebuffer, but it was the only function where XDamageSubtract() was called?
|
||||
// Also it had a blocking event loop like:
|
||||
//
|
||||
// XEvent ev;
|
||||
// while (XCheckTypedEvent(QX11Info::display(), d->xdamageBaseEvent + XDamageNotify, &ev)) {
|
||||
// handleXDamage(&ev);
|
||||
// }
|
||||
// XDamageSubtract(QX11Info::display(), d->damage, None, None);
|
||||
//
|
||||
// This loop takes all available Xdamage events from queue, and ends if there are no
|
||||
// more such events in input queue.
|
||||
|
||||
void XCBFrameBuffer::handleXDamageNotify(xcb_generic_event_t *xevent)
|
||||
{
|
||||
auto xdevt = (xcb_damage_notify_event_t *)xevent;
|
||||
|
||||
QRect r((int)xdevt->area.x, (int)xdevt->area.y,
|
||||
(int)xdevt->area.width, (int)xdevt->area.height);
|
||||
this->tiles.append(r);
|
||||
}
|
||||
44
framebuffers/xcb/xcb_framebuffer.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2017 Alexey Min <alexey.min@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#ifndef KRFB_FRAMEBUFFER_XCB_XCB_FRAMEBUFFER_H
|
||||
#define KRFB_FRAMEBUFFER_XCB_XCB_FRAMEBUFFER_H
|
||||
|
||||
#include "framebuffer.h"
|
||||
#include <QWidget>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
/**
|
||||
@author Alexey Min <alexey.min@gmail.com>
|
||||
*/
|
||||
class XCBFrameBuffer : public FrameBuffer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit XCBFrameBuffer(QObject *parent = nullptr);
|
||||
~XCBFrameBuffer() override;
|
||||
|
||||
public:
|
||||
QList<QRect> modifiedTiles() override;
|
||||
int depth() override;
|
||||
int height() override;
|
||||
int width() override;
|
||||
int paddedWidth() override;
|
||||
void getServerFormat(rfbPixelFormat &format) override;
|
||||
void startMonitor() override;
|
||||
void stopMonitor() override;
|
||||
|
||||
public:
|
||||
void handleXDamageNotify(xcb_generic_event_t *xevent);
|
||||
|
||||
private:
|
||||
void cleanupRects();
|
||||
|
||||
class P;
|
||||
P *const d;
|
||||
};
|
||||
|
||||
#endif
|
||||
24
framebuffers/xcb/xcb_framebufferplugin.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2017 Alexey Min <alexey.min@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "xcb_framebufferplugin.h"
|
||||
#include "xcb_framebuffer.h"
|
||||
#include <KPluginFactory>
|
||||
|
||||
K_PLUGIN_CLASS_WITH_JSON(XCBFrameBufferPlugin, "xcb.json")
|
||||
|
||||
XCBFrameBufferPlugin::XCBFrameBufferPlugin(QObject *parent, const QVariantList &args)
|
||||
: FrameBufferPlugin(parent, args)
|
||||
{
|
||||
}
|
||||
|
||||
FrameBuffer *XCBFrameBufferPlugin::frameBuffer(const QVariantMap &args)
|
||||
{
|
||||
Q_UNUSED(args);
|
||||
return new XCBFrameBuffer;
|
||||
}
|
||||
|
||||
#include "xcb_framebufferplugin.moc"
|
||||
28
framebuffers/xcb/xcb_framebufferplugin.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: Alexey Min <alexey.min@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KRFB_FRAMEBUFFER_XCB_XCBFRAMEBUFFERPLUGIN_H
|
||||
#define KRFB_FRAMEBUFFER_XCB_XCBFRAMEBUFFERPLUGIN_H
|
||||
|
||||
#include "framebufferplugin.h"
|
||||
#include <QWidget>
|
||||
|
||||
class FrameBuffer;
|
||||
|
||||
class XCBFrameBufferPlugin : public FrameBufferPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
XCBFrameBufferPlugin(QObject *parent, const QVariantList &args);
|
||||
|
||||
FrameBuffer *frameBuffer(const QVariantMap &args) override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(XCBFrameBufferPlugin)
|
||||
};
|
||||
|
||||
#endif // Header guard
|
||||
BIN
icons/48-apps-krfb.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
4
icons/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
ecm_install_icons(ICONS
|
||||
sc-apps-krfb.svgz
|
||||
48-apps-krfb.png
|
||||
DESTINATION ${KDE_INSTALL_ICONDIR} THEME hicolor )
|
||||
BIN
icons/sc-apps-krfb.svgz
Normal file
@@ -1,3 +0,0 @@
|
||||
[Project]
|
||||
Manager=KDevCMakeManager
|
||||
Name=krfb
|
||||
@@ -11,6 +11,8 @@ include(GenerateExportHeader)
|
||||
set (krfbprivate_SRCS
|
||||
framebuffer.cpp
|
||||
framebufferplugin.cpp
|
||||
events.cpp
|
||||
eventsplugin.cpp
|
||||
)
|
||||
|
||||
add_library (krfbprivate
|
||||
@@ -19,12 +21,13 @@ add_library (krfbprivate
|
||||
)
|
||||
generate_export_header(krfbprivate BASE_NAME krfbprivate)
|
||||
|
||||
|
||||
target_link_libraries (krfbprivate
|
||||
Qt5::Core
|
||||
Qt5::Widgets
|
||||
Qt5::X11Extras
|
||||
Qt::Core
|
||||
Qt::Widgets
|
||||
Qt::GuiPrivate
|
||||
${X11_X11_LIB}
|
||||
${LIBVNCSERVER_LIBRARIES}
|
||||
LibVNCServer::vncserver
|
||||
)
|
||||
|
||||
set_target_properties (krfbprivate PROPERTIES
|
||||
@@ -33,23 +36,19 @@ set_target_properties (krfbprivate PROPERTIES
|
||||
)
|
||||
|
||||
install (TARGETS krfbprivate
|
||||
${INSTALL_TARGETS_DEFAULT_ARGS}
|
||||
${KDE_INSTALL_TARGETS_DEFAULT_ARGS}
|
||||
LIBRARY NAMELINK_SKIP
|
||||
)
|
||||
|
||||
install (FILES
|
||||
krfb-framebuffer.desktop
|
||||
DESTINATION ${SERVICETYPES_INSTALL_DIR}
|
||||
)
|
||||
|
||||
#####################################
|
||||
# Second target: krfb - the app
|
||||
# itself.
|
||||
|
||||
set (krfb_SRCS
|
||||
connectiondialog.cpp
|
||||
events.cpp
|
||||
framebuffermanager.cpp
|
||||
events.cpp
|
||||
eventsmanager.cpp
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
sockethelpers.cpp
|
||||
@@ -61,39 +60,54 @@ set (krfb_SRCS
|
||||
invitationsrfbclient.cpp
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(krfb_SRCS
|
||||
HEADER krfbdebug.h
|
||||
IDENTIFIER KRFB
|
||||
CATEGORY_NAME krfb.krfb
|
||||
DESCRIPTION "KRFB Application"
|
||||
EXPORT KRFB
|
||||
)
|
||||
|
||||
kconfig_add_kcfg_files (krfb_SRCS
|
||||
krfbconfig.kcfgc
|
||||
)
|
||||
|
||||
ki18n_wrap_ui (krfb_SRCS
|
||||
ki18n_wrap_ui (krfb_UI_SRCS
|
||||
ui/configtcp.ui
|
||||
ui/configsecurity.ui
|
||||
ui/configframebuffer.ui
|
||||
ui/connectionwidget.ui
|
||||
ui/mainwidget.ui
|
||||
)
|
||||
|
||||
qt_add_resources(krfb_SRCS
|
||||
krfb.qrc
|
||||
)
|
||||
|
||||
add_executable (krfb
|
||||
${krfb_SRCS}
|
||||
${krfb_UI_SRCS}
|
||||
)
|
||||
|
||||
target_link_libraries (krfb
|
||||
krfbprivate
|
||||
vncserver
|
||||
${JPEG_LIBRARIES}
|
||||
${X11_Xext_LIB}
|
||||
${X11_X11_LIB}
|
||||
${X11_Xdamage_LIB}
|
||||
Qt5::Network
|
||||
KF5::Completion
|
||||
KF5::CoreAddons
|
||||
KF5::DBusAddons
|
||||
KF5::DNSSD
|
||||
KF5::I18n
|
||||
KF5::Notifications
|
||||
KF5::Wallet
|
||||
KF5::WidgetsAddons
|
||||
KF5::XmlGui
|
||||
${LIBVNCSERVER_LIBRARIES}
|
||||
Qt::Network
|
||||
KF6::CoreAddons
|
||||
KF6::DBusAddons
|
||||
KF6::DNSSD
|
||||
KF6::I18n
|
||||
KF6::Notifications
|
||||
KF6::Wallet
|
||||
KF6::WidgetsAddons
|
||||
KF6::WindowSystem
|
||||
KF6::XmlGui
|
||||
KF6::StatusNotifierItem
|
||||
KF6::Crash
|
||||
LibVNCServer::vncserver
|
||||
)
|
||||
|
||||
if (X11_XTest_FOUND)
|
||||
@@ -103,16 +117,55 @@ if (X11_XTest_FOUND)
|
||||
endif (X11_XTest_FOUND)
|
||||
|
||||
install (TARGETS krfb
|
||||
${INSTALL_TARGETS_DEFAULT_ARGS}
|
||||
${KDE_INSTALL_TARGETS_DEFAULT_ARGS}
|
||||
)
|
||||
|
||||
#################################
|
||||
kconfig_add_kcfg_files (krfbvm_SRCS
|
||||
krfbconfig.kcfgc
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(krfbvm_SRCS
|
||||
HEADER krfbdebug.h
|
||||
IDENTIFIER KRFB
|
||||
CATEGORY_NAME krfb.krfb
|
||||
DESCRIPTION "KRFB Application"
|
||||
EXPORT KRFB
|
||||
)
|
||||
|
||||
add_executable(krfb-virtualmonitor main-virtualmonitor.cpp ${krfbvm_SRCS} ${krfb_UI_SRCS}
|
||||
rfbserver.cpp rfbclient.cpp rfbservermanager.cpp eventsmanager.cpp framebuffermanager.cpp sockethelpers.cpp)
|
||||
target_link_libraries(krfb-virtualmonitor
|
||||
krfbprivate
|
||||
Qt::Gui
|
||||
Qt::Network
|
||||
KF6::ConfigGui
|
||||
KF6::CoreAddons
|
||||
KF6::I18n
|
||||
KF6::Notifications
|
||||
KF6::WindowSystem
|
||||
KF6::Crash
|
||||
)
|
||||
|
||||
install (TARGETS krfb-virtualmonitor
|
||||
${KDE_INSTALL_TARGETS_DEFAULT_ARGS}
|
||||
)
|
||||
|
||||
configure_file(org.kde.krfb.virtualmonitor.desktop.cmake ${CMAKE_CURRENT_BINARY_DIR}/org.kde.krfb.virtualmonitor.desktop @ONLY)
|
||||
install (PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/org.kde.krfb.virtualmonitor.desktop
|
||||
DESTINATION ${KDE_INSTALL_APPDIR}
|
||||
)
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install (PROGRAMS org.kde.krfb.desktop
|
||||
DESTINATION ${XDG_APPS_INSTALL_DIR}
|
||||
DESTINATION ${KDE_INSTALL_APPDIR}
|
||||
)
|
||||
|
||||
install(FILES org.kde.krfb.appdata.xml
|
||||
DESTINATION ${KDE_INSTALL_METAINFODIR}
|
||||
)
|
||||
|
||||
install (FILES krfb.notifyrc
|
||||
DESTINATION ${DATA_INSTALL_DIR}/krfb
|
||||
DESTINATION ${KDE_INSTALL_DATADIR}/krfb
|
||||
)
|
||||
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2004 Nadeem Hasan <nhasan@kde.org>
|
||||
SPDX-FileCopyrightText: 2010 Collabora Ltd <info@collabora.co.uk>
|
||||
SPDX-FileContributor: George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
SPDX-FileCopyrightText: 2004 Nadeem Hasan <nhasan@kde.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "connectiondialog.h"
|
||||
@@ -24,22 +11,22 @@
|
||||
#include <QCheckBox>
|
||||
#include <QIcon>
|
||||
|
||||
#include <KConfigGroup>
|
||||
#include <KGuiItem>
|
||||
#include <KLocalizedString>
|
||||
#include <KStandardGuiItem>
|
||||
#include <KConfigGroup>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include <KGuiItem>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
template <typename UI>
|
||||
template<typename UI>
|
||||
ConnectionDialog<UI>::ConnectionDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(i18n("New Connection"));
|
||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
|
||||
QWidget *mainWidget = new QWidget(this);
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
auto mainWidget = new QWidget(this);
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
setLayout(mainLayout);
|
||||
mainLayout->addWidget(mainWidget);
|
||||
QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
|
||||
@@ -55,7 +42,7 @@ ConnectionDialog<UI>::ConnectionDialog(QWidget *parent)
|
||||
m_connectWidget = new QWidget(this);
|
||||
m_ui.setupUi(m_connectWidget);
|
||||
|
||||
m_ui.pixmapLabel->setPixmap(QIcon::fromTheme("krfb").pixmap(128));
|
||||
m_ui.pixmapLabel->setPixmap(QIcon::fromTheme(QStringLiteral("krfb")).pixmap(128));
|
||||
|
||||
KGuiItem accept = KStandardGuiItem::ok();
|
||||
accept.setText(i18n("Accept Connection"));
|
||||
@@ -80,7 +67,3 @@ void InvitationsConnectionDialog::setRemoteHost(const QString &host)
|
||||
{
|
||||
m_ui.remoteHost->setText(host);
|
||||
}
|
||||
|
||||
//**********
|
||||
|
||||
#include "connectiondialog.moc"
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2004 Nadeem Hasan <nhasan@kde.org>
|
||||
SPDX-FileCopyrightText: 2010 Collabora Ltd <info@collabora.co.uk>
|
||||
SPDX-FileContributor: George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
SPDX-FileCopyrightText: 2004 Nadeem Hasan <nhasan@kde.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef CONNECTIONDIALOG_H
|
||||
@@ -25,12 +12,14 @@
|
||||
#include "ui_connectionwidget.h"
|
||||
#include <QDialog>
|
||||
|
||||
template <typename UI>
|
||||
template<typename UI>
|
||||
class ConnectionDialog : public QDialog
|
||||
{
|
||||
public:
|
||||
ConnectionDialog(QWidget *parent);
|
||||
~ConnectionDialog() {};
|
||||
explicit ConnectionDialog(QWidget *parent);
|
||||
~ConnectionDialog() override
|
||||
{
|
||||
}
|
||||
|
||||
void setAllowRemoteControl(bool b);
|
||||
bool allowRemoteControl();
|
||||
@@ -40,14 +29,14 @@ protected:
|
||||
UI m_ui;
|
||||
};
|
||||
|
||||
template <typename UI>
|
||||
template<typename UI>
|
||||
void ConnectionDialog<UI>::setAllowRemoteControl(bool b)
|
||||
{
|
||||
m_ui.cbAllowRemoteControl->setChecked(b);
|
||||
m_ui.cbAllowRemoteControl->setVisible(b);
|
||||
}
|
||||
|
||||
template <typename UI>
|
||||
template<typename UI>
|
||||
bool ConnectionDialog<UI>::allowRemoteControl()
|
||||
{
|
||||
return m_ui.cbAllowRemoteControl->isChecked();
|
||||
@@ -58,12 +47,12 @@ bool ConnectionDialog<UI>::allowRemoteControl()
|
||||
class InvitationsConnectionDialog : public ConnectionDialog<Ui::ConnectionWidget>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InvitationsConnectionDialog(QWidget *parent);
|
||||
void setRemoteHost(const QString & host);
|
||||
explicit InvitationsConnectionDialog(QWidget *parent);
|
||||
void setRemoteHost(const QString &host);
|
||||
};
|
||||
|
||||
//*********
|
||||
|
||||
#endif // CONNECTIONDIALOG_H
|
||||
|
||||
|
||||
195
krfb/events.cpp
@@ -1,200 +1,27 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
|
||||
Copyright (C) 2010 Collabora Ltd.
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
Copyright (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
SPDX-FileCopyrightText: 2010 Collabora Ltd.
|
||||
SPDX-FileContributor: George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
SPDX-FileCopyrightText: 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
SPDX-FileCopyrightText: 2001-2003 Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "events.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QX11Info>
|
||||
#include <QDesktopWidget>
|
||||
#include <QGlobalStatic>
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
enum {
|
||||
LEFTSHIFT = 1,
|
||||
RIGHTSHIFT = 2,
|
||||
ALTGR = 4
|
||||
};
|
||||
|
||||
class EventData
|
||||
EventHandler::EventHandler(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
public:
|
||||
EventData();
|
||||
|
||||
//keyboard
|
||||
Display *dpy;
|
||||
signed char modifiers[0x100];
|
||||
KeyCode keycodes[0x100];
|
||||
KeyCode leftShiftCode;
|
||||
KeyCode rightShiftCode;
|
||||
KeyCode altGrCode;
|
||||
char modifierState;
|
||||
|
||||
//mouse
|
||||
int buttonMask;
|
||||
|
||||
private:
|
||||
void init();
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(EventData, data)
|
||||
|
||||
EventData::EventData()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void EventData::init()
|
||||
void EventHandler::setFrameBufferPlugin(const QSharedPointer<FrameBuffer> &frameBuffer)
|
||||
{
|
||||
dpy = QX11Info::display();
|
||||
buttonMask = 0;
|
||||
|
||||
//initialize keycodes
|
||||
KeySym key, *keymap;
|
||||
int i, j, minkey, maxkey, syms_per_keycode;
|
||||
|
||||
memset(modifiers, -1, sizeof(modifiers));
|
||||
|
||||
XDisplayKeycodes(dpy, &minkey, &maxkey);
|
||||
Q_ASSERT(minkey >= 8);
|
||||
Q_ASSERT(maxkey < 256);
|
||||
keymap = (KeySym *) XGetKeyboardMapping(dpy, minkey,
|
||||
(maxkey - minkey + 1),
|
||||
&syms_per_keycode);
|
||||
Q_ASSERT(keymap);
|
||||
|
||||
for (i = minkey; i <= maxkey; i++) {
|
||||
for (j = 0; j < syms_per_keycode; j++) {
|
||||
key = keymap[(i-minkey)*syms_per_keycode+j];
|
||||
|
||||
if (key >= ' ' && key < 0x100 && i == XKeysymToKeycode(dpy, key)) {
|
||||
keycodes[key] = i;
|
||||
modifiers[key] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leftShiftCode = XKeysymToKeycode(dpy, XK_Shift_L);
|
||||
rightShiftCode = XKeysymToKeycode(dpy, XK_Shift_R);
|
||||
altGrCode = XKeysymToKeycode(dpy, XK_Mode_switch);
|
||||
|
||||
XFree((char *)keymap);
|
||||
fb = frameBuffer;
|
||||
}
|
||||
|
||||
/* this function adjusts the modifiers according to mod (as from modifiers) and data->modifierState */
|
||||
static void tweakModifiers(signed char mod, bool down)
|
||||
QSharedPointer<FrameBuffer> EventHandler::frameBuffer()
|
||||
{
|
||||
bool isShift = data->modifierState & (LEFTSHIFT | RIGHTSHIFT);
|
||||
|
||||
if (mod < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isShift && mod != 1) {
|
||||
if (data->modifierState & LEFTSHIFT) {
|
||||
XTestFakeKeyEvent(data->dpy, data->leftShiftCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
|
||||
if (data->modifierState & RIGHTSHIFT) {
|
||||
XTestFakeKeyEvent(data->dpy, data->rightShiftCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isShift && mod == 1) {
|
||||
XTestFakeKeyEvent(data->dpy, data->leftShiftCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
|
||||
if ((data->modifierState & ALTGR) && mod != 2) {
|
||||
XTestFakeKeyEvent(data->dpy, data->altGrCode,
|
||||
!down, CurrentTime);
|
||||
}
|
||||
|
||||
if (!(data->modifierState & ALTGR) && mod == 2) {
|
||||
XTestFakeKeyEvent(data->dpy, data->altGrCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
void EventHandler::handleKeyboard(bool down, rfbKeySym keySym)
|
||||
{
|
||||
#define ADJUSTMOD(sym,state) \
|
||||
if(keySym==sym) { if(down) data->modifierState|=state; else data->modifierState&=~state; }
|
||||
|
||||
ADJUSTMOD(XK_Shift_L, LEFTSHIFT);
|
||||
ADJUSTMOD(XK_Shift_R, RIGHTSHIFT);
|
||||
ADJUSTMOD(XK_Mode_switch, ALTGR);
|
||||
|
||||
if (keySym >= ' ' && keySym < 0x100) {
|
||||
KeyCode k;
|
||||
|
||||
if (down) {
|
||||
tweakModifiers(data->modifiers[keySym], True);
|
||||
}
|
||||
|
||||
k = data->keycodes[keySym];
|
||||
|
||||
if (k != NoSymbol) {
|
||||
XTestFakeKeyEvent(data->dpy, k, down, CurrentTime);
|
||||
}
|
||||
|
||||
if (down) {
|
||||
tweakModifiers(data->modifiers[keySym], False);
|
||||
}
|
||||
} else {
|
||||
KeyCode k = XKeysymToKeycode(data->dpy, keySym);
|
||||
|
||||
if (k != NoSymbol) {
|
||||
XTestFakeKeyEvent(data->dpy, k, down, CurrentTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventHandler::handlePointer(int buttonMask, int x, int y)
|
||||
{
|
||||
QDesktopWidget *desktopWidget = QApplication::desktop();
|
||||
|
||||
int screen = desktopWidget->screenNumber();
|
||||
|
||||
if (screen < 0) {
|
||||
screen = 0;
|
||||
}
|
||||
|
||||
XTestFakeMotionEvent(data->dpy, screen, x, y, CurrentTime);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if ((data->buttonMask&(1 << i)) != (buttonMask&(1 << i))) {
|
||||
XTestFakeButtonEvent(data->dpy,
|
||||
i + 1,
|
||||
(buttonMask&(1 << i)) ? True : False,
|
||||
CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
data->buttonMask = buttonMask;
|
||||
return fb;
|
||||
}
|
||||
|
||||
@@ -1,37 +1,39 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
|
||||
Copyright (C) 2010 Collabora Ltd.
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
Copyright (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
SPDX-FileCopyrightText: 2010 Collabora Ltd.
|
||||
SPDX-FileContributor: George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
SPDX-FileCopyrightText: 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
SPDX-FileCopyrightText: 2001-2003 Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef EVENTS_H
|
||||
#define EVENTS_H
|
||||
|
||||
#include "framebuffer.h"
|
||||
#include "krfbprivate_export.h"
|
||||
#include "rfb.h"
|
||||
|
||||
class EventHandler
|
||||
#include <QObject>
|
||||
|
||||
class KRFBPRIVATE_EXPORT EventHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static void handleKeyboard(bool down, rfbKeySym key);
|
||||
static void handlePointer(int buttonMask, int x, int y);
|
||||
explicit EventHandler(QObject *parent = nullptr);
|
||||
~EventHandler() override = default;
|
||||
virtual void handleKeyboard(bool down, rfbKeySym key) = 0;
|
||||
virtual void handlePointer(int buttonMask, int x, int y) = 0;
|
||||
|
||||
void setFrameBufferPlugin(const QSharedPointer<FrameBuffer> &frameBuffer);
|
||||
QSharedPointer<FrameBuffer> frameBuffer();
|
||||
|
||||
private:
|
||||
// Used to track framebuffer plugin which we need for xdp event plugin
|
||||
QSharedPointer<FrameBuffer> fb;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
62
krfb/eventsmanager.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
SPDX-FileContributor: George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "eventsmanager.h"
|
||||
|
||||
#include "eventsplugin.h"
|
||||
#include "krfbconfig.h"
|
||||
#include "krfbdebug.h"
|
||||
#include "rfbservermanager.h"
|
||||
|
||||
#include <QGlobalStatic>
|
||||
|
||||
#include <KPluginFactory>
|
||||
#include <KPluginMetaData>
|
||||
|
||||
class EventsManagerStatic
|
||||
{
|
||||
public:
|
||||
EventsManager instance;
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(EventsManagerStatic, eventsManagerStatic)
|
||||
|
||||
EventsManager::EventsManager()
|
||||
{
|
||||
const QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("krfb/events"), {}, KPluginMetaData::AllowEmptyMetaData);
|
||||
for (const KPluginMetaData &data : plugins) {
|
||||
const KPluginFactory::Result<EventsPlugin> result = KPluginFactory::instantiatePlugin<EventsPlugin>(data);
|
||||
if (result.plugin) {
|
||||
m_plugins.insert(data.pluginId(), result.plugin);
|
||||
qCDebug(KRFB) << "Loaded plugin with name " << data.pluginId();
|
||||
} else {
|
||||
qCDebug(KRFB) << "unable to load plugin for " << data.fileName() << result.errorString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EventsManager::~EventsManager() = default;
|
||||
|
||||
EventsManager *EventsManager::instance()
|
||||
{
|
||||
return &eventsManagerStatic->instance;
|
||||
}
|
||||
|
||||
QSharedPointer<EventHandler> EventsManager::eventHandler()
|
||||
{
|
||||
for (auto it = m_plugins.cbegin(); it != m_plugins.constEnd(); it++) {
|
||||
QSharedPointer<EventHandler> eventHandler(it.value()->eventHandler());
|
||||
if (eventHandler) {
|
||||
eventHandler->setFrameBufferPlugin(RfbServerManager::instance()->framebuffer());
|
||||
return eventHandler;
|
||||
}
|
||||
}
|
||||
|
||||
// No valid events plugin found.
|
||||
qCDebug(KRFB) << "No valid event handlers found. returning null.";
|
||||
return QSharedPointer<EventHandler>();
|
||||
}
|
||||
46
krfb/eventsmanager.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
SPDX-FileContributor: George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KRFB_EVENTSMANAGER_H
|
||||
#define KRFB_EVENTSMANAGER_H
|
||||
|
||||
#include "events.h"
|
||||
|
||||
#include "krfbprivate_export.h"
|
||||
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QWeakPointer>
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class EventsPlugin;
|
||||
class KPluginFactory;
|
||||
|
||||
class KRFBPRIVATE_EXPORT EventsManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class EventsManagerStatic;
|
||||
|
||||
public:
|
||||
static EventsManager *instance();
|
||||
|
||||
~EventsManager() override;
|
||||
|
||||
QSharedPointer<EventHandler> eventHandler();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(EventsManager)
|
||||
|
||||
EventsManager();
|
||||
|
||||
QMap<QString, EventsPlugin *> m_plugins;
|
||||
QList<QWeakPointer<EventHandler>> m_eventHandlers;
|
||||
};
|
||||
|
||||
#endif // Header guard
|
||||
18
krfb/eventsplugin.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2016 Oleg Chernovskiy <kanedias@xaker.ru>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "eventsplugin.h"
|
||||
|
||||
#include "events.h"
|
||||
|
||||
EventsPlugin::EventsPlugin(QObject *parent, const QVariantList &)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
EventsPlugin::~EventsPlugin()
|
||||
{
|
||||
}
|
||||
29
krfb/eventsplugin.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
SPDX-FileContributor: George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef LIB_KRFB_EVENTSPLUGIN_H
|
||||
#define LIB_KRFB_EVENTSPLUGIN_H
|
||||
|
||||
#include "krfbprivate_export.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QtCore/QVariantList>
|
||||
|
||||
class EventHandler;
|
||||
|
||||
class KRFBPRIVATE_EXPORT EventsPlugin : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EventsPlugin(QObject *parent, const QVariantList &args);
|
||||
~EventsPlugin() override;
|
||||
|
||||
virtual EventHandler *eventHandler() = 0;
|
||||
};
|
||||
|
||||
#endif // Header guard
|
||||
@@ -1,21 +1,18 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
SPDX-FileCopyrightText: 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "framebuffer.h"
|
||||
|
||||
#include "config-krfb.h"
|
||||
#include <QCursor>
|
||||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
#include <config-krfb.h>
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
|
||||
FrameBuffer::FrameBuffer(WId id, QObject *parent)
|
||||
: QObject(parent), win(id)
|
||||
FrameBuffer::FrameBuffer(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -29,7 +26,7 @@ char *FrameBuffer::data()
|
||||
return fb;
|
||||
}
|
||||
|
||||
QList< QRect > FrameBuffer::modifiedTiles()
|
||||
QList<QRect> FrameBuffer::modifiedTiles()
|
||||
{
|
||||
QList<QRect> ret = tiles;
|
||||
tiles.clear();
|
||||
@@ -50,6 +47,12 @@ void FrameBuffer::getServerFormat(rfbPixelFormat &)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant FrameBuffer::customProperty(const QString &property) const
|
||||
{
|
||||
Q_UNUSED(property)
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int FrameBuffer::depth()
|
||||
{
|
||||
return 32;
|
||||
@@ -68,6 +71,16 @@ void FrameBuffer::stopMonitor()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#include "framebuffer.moc"
|
||||
|
||||
QPoint FrameBuffer::cursorPosition()
|
||||
{
|
||||
QPoint cursorPos = QCursor::pos();
|
||||
QScreen *primaryScreen = QGuiApplication::primaryScreen();
|
||||
if (primaryScreen) {
|
||||
qreal scaleFactor = primaryScreen->devicePixelRatio();
|
||||
cursorPos.setX(qRound(cursorPos.x() * scaleFactor));
|
||||
cursorPos.setY(qRound(cursorPos.y() * scaleFactor));
|
||||
} else {
|
||||
qWarning() << "cursorPosition: ERROR: Failed to get application's primary screen info!";
|
||||
}
|
||||
return cursorPos;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
SPDX-FileCopyrightText: 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef FRAMEBUFFER_H
|
||||
@@ -14,12 +11,12 @@
|
||||
|
||||
#include "krfbprivate_export.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QRect>
|
||||
#include <QtCore/QList>
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QRect>
|
||||
#include <QVariant>
|
||||
#include <QWidget>
|
||||
|
||||
|
||||
class FrameBuffer;
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
@@ -27,10 +24,11 @@ class FrameBuffer;
|
||||
class KRFBPRIVATE_EXPORT FrameBuffer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FrameBuffer(WId id, QObject *parent = 0);
|
||||
|
||||
virtual ~FrameBuffer();
|
||||
public:
|
||||
explicit FrameBuffer(QObject *parent = nullptr);
|
||||
|
||||
~FrameBuffer() override;
|
||||
|
||||
char *data();
|
||||
|
||||
@@ -41,17 +39,21 @@ public:
|
||||
virtual int depth();
|
||||
virtual void startMonitor();
|
||||
virtual void stopMonitor();
|
||||
virtual QPoint cursorPosition();
|
||||
|
||||
virtual void getServerFormat(rfbPixelFormat &format);
|
||||
|
||||
virtual QVariant customProperty(const QString &property) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void frameBufferChanged();
|
||||
|
||||
protected:
|
||||
WId win;
|
||||
char *fb;
|
||||
char *fb = nullptr;
|
||||
QList<QRect> tiles;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(FrameBuffer)
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,37 +1,22 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
SPDX-FileCopyrightText: 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
SPDX-FileContributor: George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "framebuffermanager.h"
|
||||
|
||||
#include "framebufferplugin.h"
|
||||
#include "krfbconfig.h"
|
||||
#include "krfbdebug.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QGlobalStatic>
|
||||
#include <QGuiApplication>
|
||||
|
||||
#include <KPluginFactory>
|
||||
#include <KPluginLoader>
|
||||
#include <KPluginMetaData>
|
||||
|
||||
#include <QtCore/QSharedPointer>
|
||||
|
||||
class FrameBufferManagerStatic
|
||||
{
|
||||
public:
|
||||
@@ -42,100 +27,64 @@ Q_GLOBAL_STATIC(FrameBufferManagerStatic, frameBufferManagerStatic)
|
||||
|
||||
FrameBufferManager::FrameBufferManager()
|
||||
{
|
||||
//qDebug();
|
||||
|
||||
loadPlugins();
|
||||
const auto platformFilter = [](const KPluginMetaData &pluginData) {
|
||||
return pluginData.value(QStringLiteral("X-KDE-OnlyShowOnQtPlatforms"), QStringList()).contains(QGuiApplication::platformName());
|
||||
};
|
||||
const QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("krfb/framebuffer"), platformFilter, KPluginMetaData::AllowEmptyMetaData);
|
||||
for (const KPluginMetaData &data : plugins) {
|
||||
const KPluginFactory::Result<FrameBufferPlugin> result = KPluginFactory::instantiatePlugin<FrameBufferPlugin>(data);
|
||||
if (result.plugin) {
|
||||
m_plugins.insert(data.pluginId(), result.plugin);
|
||||
qCDebug(KRFB) << "Loaded plugin with name " << data.pluginId();
|
||||
} else {
|
||||
qCDebug(KRFB) << "unable to load plugin for " << data.fileName() << result.errorString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FrameBufferManager::~FrameBufferManager()
|
||||
{
|
||||
//qDebug();
|
||||
}
|
||||
|
||||
FrameBufferManager *FrameBufferManager::instance()
|
||||
{
|
||||
//qDebug();
|
||||
|
||||
return &frameBufferManagerStatic->instance;
|
||||
}
|
||||
|
||||
void FrameBufferManager::loadPlugins()
|
||||
QSharedPointer<FrameBuffer> FrameBufferManager::frameBuffer(WId id, const QVariantMap &args)
|
||||
{
|
||||
//qDebug();
|
||||
|
||||
const QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(QStringLiteral("krfb"), [](const KPluginMetaData & md) {
|
||||
return md.serviceTypes().contains(QStringLiteral("krfb/framebuffer"));
|
||||
});
|
||||
|
||||
QVectorIterator<KPluginMetaData> i(plugins);
|
||||
i.toBack();
|
||||
QSet<QString> unique;
|
||||
while (i.hasPrevious()) {
|
||||
KPluginMetaData data = i.previous();
|
||||
// only load plugins once, even if found multiple times!
|
||||
if (unique.contains(data.name()))
|
||||
continue;
|
||||
KPluginFactory *factory = KPluginLoader(data.fileName()).factory();
|
||||
|
||||
if (!factory) {
|
||||
qDebug() << "KPluginFactory could not load the plugin:" << data.fileName();
|
||||
} else {
|
||||
qDebug() << "found plugin at " << data.fileName();
|
||||
}
|
||||
|
||||
FrameBufferPlugin *plugin = factory->create<FrameBufferPlugin>(this);
|
||||
if (plugin) {
|
||||
m_plugins.insert(data.pluginId(), plugin);
|
||||
qDebug() << "Loaded plugin with name " << data.pluginId();
|
||||
} else {
|
||||
qDebug() << "unable to load pluign for " << data.fileName();
|
||||
}
|
||||
unique.insert (data.name());
|
||||
}
|
||||
}
|
||||
|
||||
QSharedPointer<FrameBuffer> FrameBufferManager::frameBuffer(WId id)
|
||||
{
|
||||
//qDebug();
|
||||
|
||||
// See if there is still an existing framebuffer to this WId.
|
||||
if (m_frameBuffers.contains(id)) {
|
||||
QWeakPointer<FrameBuffer> weakFrameBuffer = m_frameBuffers.value(id);
|
||||
|
||||
if (weakFrameBuffer) {
|
||||
//qDebug() << "Found cached frame buffer.";
|
||||
// qDebug() << "Found cached frame buffer.";
|
||||
return weakFrameBuffer.toStrongRef();
|
||||
} else {
|
||||
//qDebug() << "Found deleted cached frame buffer. Don't use.";
|
||||
// qDebug() << "Found deleted cached frame buffer. Don't use.";
|
||||
m_frameBuffers.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
// We don't already have that frame buffer.
|
||||
QMap<QString, FrameBufferPlugin *>::const_iterator iter = m_plugins.constBegin();
|
||||
|
||||
while (iter != m_plugins.constEnd()) {
|
||||
|
||||
if (iter.key() == KrfbConfig::preferredFrameBufferPlugin()) {
|
||||
qDebug() << "Using FrameBuffer:" << KrfbConfig::preferredFrameBufferPlugin();
|
||||
|
||||
QSharedPointer<FrameBuffer> frameBuffer(iter.value()->frameBuffer(id));
|
||||
|
||||
if (frameBuffer) {
|
||||
m_frameBuffers.insert(id, frameBuffer.toWeakRef());
|
||||
|
||||
return frameBuffer;
|
||||
}
|
||||
if (auto preferredPlugin = m_plugins.value(KrfbConfig::preferredFrameBufferPlugin())) {
|
||||
if (auto frameBuffer = QSharedPointer<FrameBuffer>(preferredPlugin->frameBuffer(args))) {
|
||||
qCDebug(KRFB) << "Using FrameBuffer:" << KrfbConfig::preferredFrameBufferPlugin();
|
||||
m_frameBuffers.insert(id, frameBuffer.toWeakRef());
|
||||
return frameBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
++iter;
|
||||
// We don't already have that frame buffer.
|
||||
for (auto it = m_plugins.cbegin(); it != m_plugins.constEnd(); it++) {
|
||||
QSharedPointer<FrameBuffer> frameBuffer(it.value()->frameBuffer(args));
|
||||
if (frameBuffer) {
|
||||
qCDebug(KRFB) << "Using FrameBuffer:" << it.key();
|
||||
m_frameBuffers.insert(id, frameBuffer.toWeakRef());
|
||||
return frameBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
// No valid framebuffer plugin found.
|
||||
qDebug() << "No valid framebuffer found. returning null.";
|
||||
qCDebug(KRFB) << "No valid framebuffer found. returning null.";
|
||||
return QSharedPointer<FrameBuffer>();
|
||||
}
|
||||
|
||||
|
||||
#include "framebuffermanager.moc"
|
||||
|
||||
|
||||
@@ -1,21 +1,8 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
SPDX-FileCopyrightText: 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
SPDX-FileContributor: George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KRFB_FRAMEBUFFERMANAGER_H
|
||||
@@ -25,10 +12,10 @@
|
||||
|
||||
#include "krfbprivate_export.h"
|
||||
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QWeakPointer>
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
#include <QWeakPointer>
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
@@ -43,21 +30,17 @@ class KRFBPRIVATE_EXPORT FrameBufferManager : public QObject
|
||||
public:
|
||||
static FrameBufferManager *instance();
|
||||
|
||||
virtual ~FrameBufferManager();
|
||||
~FrameBufferManager() override;
|
||||
|
||||
QSharedPointer<FrameBuffer> frameBuffer(WId id);
|
||||
QSharedPointer<FrameBuffer> frameBuffer(WId id, const QVariantMap &args);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(FrameBufferManager)
|
||||
|
||||
FrameBufferManager();
|
||||
|
||||
void loadPlugins();
|
||||
|
||||
QMap<QString, FrameBufferPlugin *> m_plugins;
|
||||
QMap<WId, QWeakPointer<FrameBuffer> > m_frameBuffers;
|
||||
QMap<WId, QWeakPointer<FrameBuffer>> m_frameBuffers;
|
||||
};
|
||||
|
||||
|
||||
#endif // Header guard
|
||||
|
||||
#endif // Header guard
|
||||
|
||||
@@ -1,21 +1,8 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
SPDX-FileCopyrightText: 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
SPDX-FileContributor: George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "framebufferplugin.h"
|
||||
@@ -30,7 +17,3 @@ FrameBufferPlugin::FrameBufferPlugin(QObject *parent, const QVariantList &)
|
||||
FrameBufferPlugin::~FrameBufferPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#include "framebufferplugin.moc"
|
||||
|
||||
|
||||
@@ -1,21 +1,8 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
SPDX-FileCopyrightText: 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
SPDX-FileContributor: George Goldberg <george.goldberg@collabora.co.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef LIB_KRFB_FRAMEBUFFERPLUGIN_H
|
||||
@@ -23,10 +10,9 @@
|
||||
|
||||
#include "krfbprivate_export.h"
|
||||
|
||||
#include <QtCore/QVariantList>
|
||||
#include <QVariantList>
|
||||
#include <QWidget>
|
||||
|
||||
|
||||
class FrameBuffer;
|
||||
|
||||
class KRFBPRIVATE_EXPORT FrameBufferPlugin : public QObject
|
||||
@@ -34,11 +20,10 @@ class KRFBPRIVATE_EXPORT FrameBufferPlugin : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FrameBufferPlugin(QObject *parent, const QVariantList &args);
|
||||
virtual ~FrameBufferPlugin();
|
||||
explicit FrameBufferPlugin(QObject *parent, const QVariantList &args);
|
||||
~FrameBufferPlugin() override;
|
||||
|
||||
virtual FrameBuffer *frameBuffer(WId id) = 0;
|
||||
virtual FrameBuffer *frameBuffer(const QVariantMap &args) = 0;
|
||||
};
|
||||
|
||||
#endif // Header guard
|
||||
|
||||
#endif // Header guard
|
||||
|
||||
@@ -1,61 +1,50 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
Copyright (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
SPDX-FileCopyrightText: 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
SPDX-FileContributor: George Goldberg <george.goldberg@collabora.co.uk>
|
||||
SPDX-FileContributor: George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
SPDX-FileCopyrightText: 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
SPDX-FileCopyrightText: 2001-2003 Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "rfb.h"
|
||||
#include "invitationsrfbclient.h"
|
||||
#include "connectiondialog.h"
|
||||
#include "invitationsrfbserver.h"
|
||||
#include "krfbconfig.h"
|
||||
#include "krfbdebug.h"
|
||||
#include "rfb.h"
|
||||
#include "sockethelpers.h"
|
||||
#include "connectiondialog.h"
|
||||
|
||||
#include <KNotification>
|
||||
#include <KLocalizedString>
|
||||
#include <KNotification>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QtCore/QSocketNotifier>
|
||||
#include <poll.h>
|
||||
#include <KConfigGroup>
|
||||
#include <QSocketNotifier>
|
||||
#include <poll.h>
|
||||
|
||||
struct PendingInvitationsRfbClient::Private
|
||||
{
|
||||
Private(rfbClientPtr client) :
|
||||
client(client),
|
||||
askOnConnect(true)
|
||||
{}
|
||||
Private(rfbClientPtr client)
|
||||
: client(client)
|
||||
, askOnConnect(true)
|
||||
{
|
||||
}
|
||||
|
||||
rfbClientPtr client;
|
||||
QSocketNotifier *notifier;
|
||||
QSocketNotifier *notifier = nullptr;
|
||||
bool askOnConnect;
|
||||
};
|
||||
|
||||
static void clientGoneHookNoop(rfbClientPtr cl) { Q_UNUSED(cl); }
|
||||
static void clientGoneHookNoop(rfbClientPtr cl)
|
||||
{
|
||||
Q_UNUSED(cl);
|
||||
}
|
||||
|
||||
PendingInvitationsRfbClient::PendingInvitationsRfbClient(rfbClientPtr client, QObject *parent) :
|
||||
PendingRfbClient(client, parent),
|
||||
d(new Private(client))
|
||||
PendingInvitationsRfbClient::PendingInvitationsRfbClient(rfbClientPtr client, QObject *parent)
|
||||
: PendingRfbClient(client, parent)
|
||||
, d(new Private(client))
|
||||
{
|
||||
d->client->clientGoneHook = clientGoneHookNoop;
|
||||
d->notifier = new QSocketNotifier(client->sock, QSocketNotifier::Read, this);
|
||||
d->notifier->setEnabled(true);
|
||||
connect(d->notifier, &QSocketNotifier::activated,
|
||||
this, &PendingInvitationsRfbClient::onSocketActivated);
|
||||
}
|
||||
|
||||
PendingInvitationsRfbClient::~PendingInvitationsRfbClient()
|
||||
@@ -65,21 +54,19 @@ PendingInvitationsRfbClient::~PendingInvitationsRfbClient()
|
||||
|
||||
void PendingInvitationsRfbClient::processNewClient()
|
||||
{
|
||||
QString host = peerAddress(m_rfbClient->sock) + ":" + QString::number(peerPort(m_rfbClient->sock));
|
||||
QString host = peerAddress(m_rfbClient->sock) + QLatin1Char(':') + QString::number(peerPort(m_rfbClient->sock));
|
||||
|
||||
if (d->askOnConnect == false) {
|
||||
|
||||
KNotification::event("NewConnectionAutoAccepted",
|
||||
KNotification::event(QStringLiteral("NewConnectionAutoAccepted"),
|
||||
i18n("Accepted connection from %1", host));
|
||||
accept(new InvitationsRfbClient(m_rfbClient, parent()));
|
||||
|
||||
} else {
|
||||
KNotification::event(QStringLiteral("NewConnectionOnHold"),
|
||||
i18n("Received connection from %1, on hold (waiting for confirmation)",
|
||||
host));
|
||||
|
||||
KNotification::event("NewConnectionOnHold",
|
||||
i18n("Received connection from %1, on hold (waiting for confirmation)",
|
||||
host));
|
||||
|
||||
InvitationsConnectionDialog *dialog = new InvitationsConnectionDialog(0);
|
||||
auto dialog = new InvitationsConnectionDialog(nullptr);
|
||||
dialog->setRemoteHost(host);
|
||||
dialog->setAllowRemoteControl(KrfbConfig::allowDesktopControl());
|
||||
|
||||
@@ -90,64 +77,26 @@ void PendingInvitationsRfbClient::processNewClient()
|
||||
}
|
||||
}
|
||||
|
||||
void PendingInvitationsRfbClient::onSocketActivated()
|
||||
bool PendingInvitationsRfbClient::checkPassword(const QByteArray &encryptedPassword)
|
||||
{
|
||||
//Process not only one, but all pending messages.
|
||||
//poll() idea/code copied from vino:
|
||||
// Copyright (C) 2003 Sun Microsystems, Inc.
|
||||
// License: GPL v2 or later
|
||||
struct pollfd pollfd = { d->client->sock, POLLIN|POLLPRI, 0 };
|
||||
qCDebug(KRFB) << "about to start authentication";
|
||||
|
||||
while(poll(&pollfd, 1, 0) == 1) {
|
||||
|
||||
if(d->client->state == rfbClientRec::RFB_INITIALISATION) {
|
||||
d->notifier->setEnabled(false);
|
||||
//Client is Authenticated
|
||||
processNewClient();
|
||||
break;
|
||||
}
|
||||
rfbProcessClientMessage(d->client);
|
||||
|
||||
//This is how we handle disconnection.
|
||||
//if rfbProcessClientMessage() finds out that it can't read the socket,
|
||||
//it closes it and sets it to -1. So, we just have to check this here
|
||||
//and call rfbClientConnectionGone() if necessary. This will call
|
||||
//the clientGoneHook which in turn will remove this RfbClient instance
|
||||
//from the server manager and will call deleteLater() to delete it
|
||||
if (d->client->sock == -1) {
|
||||
qDebug() << "disconnected from socket signal";
|
||||
d->notifier->setEnabled(false);
|
||||
rfbClientConnectionGone(d->client);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PendingInvitationsRfbClient::checkPassword(const QByteArray & encryptedPassword)
|
||||
{
|
||||
QByteArray password ;
|
||||
qDebug() << "about to start autentication";
|
||||
|
||||
if(InvitationsRfbServer::instance->allowUnattendedAccess() && vncAuthCheckPassword(
|
||||
InvitationsRfbServer::instance->unattendedPassword().toLocal8Bit(),
|
||||
encryptedPassword) ) {
|
||||
if (InvitationsRfbServer::instance->allowUnattendedAccess() && vncAuthCheckPassword(InvitationsRfbServer::instance->unattendedPassword().toLocal8Bit(), encryptedPassword)) {
|
||||
d->askOnConnect = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return vncAuthCheckPassword(
|
||||
InvitationsRfbServer::instance->desktopPassword().toLocal8Bit(),
|
||||
encryptedPassword);
|
||||
InvitationsRfbServer::instance->desktopPassword().toLocal8Bit(),
|
||||
encryptedPassword);
|
||||
}
|
||||
|
||||
void PendingInvitationsRfbClient::dialogAccepted()
|
||||
{
|
||||
InvitationsConnectionDialog *dialog = qobject_cast<InvitationsConnectionDialog *>(sender());
|
||||
auto dialog = qobject_cast<InvitationsConnectionDialog *>(sender());
|
||||
Q_ASSERT(dialog);
|
||||
|
||||
InvitationsRfbClient *client = new InvitationsRfbClient(m_rfbClient, parent());
|
||||
auto client = new InvitationsRfbClient(m_rfbClient, parent());
|
||||
client->setControlEnabled(dialog->allowRemoteControl());
|
||||
accept(client);
|
||||
}
|
||||
|
||||
#include "invitationsrfbclient.moc"
|
||||
|
||||
@@ -1,19 +1,8 @@
|
||||
/*
|
||||
Copyright (C) 2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
SPDX-FileCopyrightText: 2010 Collabora Ltd <info@collabora.co.uk>
|
||||
SPDX-FileContributor: George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#ifndef INVITATIONSRFBCLIENT_H
|
||||
#define INVITATIONSRFBCLIENT_H
|
||||
@@ -23,29 +12,30 @@
|
||||
class InvitationsRfbClient : public RfbClient
|
||||
{
|
||||
public:
|
||||
InvitationsRfbClient(rfbClientPtr client, QObject* parent = 0)
|
||||
: RfbClient(client, parent) {}
|
||||
explicit InvitationsRfbClient(rfbClientPtr client, QObject *parent = nullptr)
|
||||
: RfbClient(client, parent)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class PendingInvitationsRfbClient : public PendingRfbClient
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PendingInvitationsRfbClient(rfbClientPtr client, QObject *parent = 0);
|
||||
virtual ~PendingInvitationsRfbClient();
|
||||
explicit PendingInvitationsRfbClient(rfbClientPtr client, QObject *parent = nullptr);
|
||||
~PendingInvitationsRfbClient() override;
|
||||
|
||||
protected Q_SLOTS:
|
||||
void processNewClient() override;
|
||||
virtual void onSocketActivated();
|
||||
bool checkPassword(const QByteArray & encryptedPassword) override;
|
||||
bool checkPassword(const QByteArray &encryptedPassword) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void dialogAccepted();
|
||||
|
||||
private:
|
||||
struct Private;
|
||||
Private* const d;
|
||||
Private *const d;
|
||||
};
|
||||
|
||||
#endif // INVITATIONSRFBCLIENT_H
|
||||
|
||||
@@ -1,89 +1,82 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
Copyright (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
SPDX-FileCopyrightText: 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
SPDX-FileContributor: George Goldberg <george.goldberg@collabora.co.uk>
|
||||
SPDX-FileContributor: George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
SPDX-FileCopyrightText: 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
SPDX-FileCopyrightText: 2001-2003 Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "invitationsrfbserver.h"
|
||||
#include "invitationsrfbclient.h"
|
||||
#include "krfbconfig.h"
|
||||
#include "rfbservermanager.h"
|
||||
#include <QtCore/QTimer>
|
||||
#include "krfbdebug.h"
|
||||
#include <QApplication>
|
||||
#include <QtNetwork/QHostInfo>
|
||||
#include <QDebug>
|
||||
#include <QHostInfo>
|
||||
#include <QRandomGenerator>
|
||||
#include <QTimer>
|
||||
|
||||
#include <KLocalizedString>
|
||||
#include <KUser>
|
||||
#include <KRandom>
|
||||
#include <KStringHandler>
|
||||
#include <KWallet/KWallet>
|
||||
#include <KUser>
|
||||
#include <KWallet>
|
||||
|
||||
#include <KDNSSD/PublicService>
|
||||
|
||||
#include <dnssd/publicservice.h>
|
||||
using KWallet::Wallet;
|
||||
|
||||
//static
|
||||
// used for KWallet folder name
|
||||
static const QString s_krfbFolderName(QStringLiteral("krfb"));
|
||||
|
||||
// static
|
||||
InvitationsRfbServer *InvitationsRfbServer::instance;
|
||||
|
||||
//static
|
||||
// static
|
||||
void InvitationsRfbServer::init()
|
||||
{
|
||||
instance = new InvitationsRfbServer;
|
||||
instance->m_publicService = new KDNSSD::PublicService(
|
||||
i18n("%1@%2 (shared desktop)",
|
||||
KUser().loginName(),
|
||||
QHostInfo::localHostName()),
|
||||
"_rfb._tcp",
|
||||
KrfbConfig::port());
|
||||
i18n("%1@%2 (shared desktop)",
|
||||
KUser().loginName(),
|
||||
QHostInfo::localHostName()),
|
||||
QStringLiteral("_rfb._tcp"),
|
||||
KrfbConfig::port());
|
||||
instance->setListeningAddress("0.0.0.0");
|
||||
instance->setListeningPort(KrfbConfig::port());
|
||||
instance->setPasswordRequired(true);
|
||||
|
||||
instance->m_wallet = nullptr;
|
||||
if (KrfbConfig::noWallet()) {
|
||||
instance->walletOpened(false);
|
||||
}
|
||||
else {
|
||||
instance->m_wallet = Wallet::openWallet(
|
||||
Wallet::NetworkWallet(), 0, Wallet::Asynchronous);
|
||||
if(instance->m_wallet) {
|
||||
connect(instance->m_wallet, &KWallet::Wallet::walletOpened,
|
||||
instance, &InvitationsRfbServer::walletOpened);
|
||||
}
|
||||
instance->readPasswordFromConfig();
|
||||
} else {
|
||||
instance->openKWallet();
|
||||
}
|
||||
}
|
||||
|
||||
const QString& InvitationsRfbServer::desktopPassword() const
|
||||
const QString &InvitationsRfbServer::desktopPassword() const
|
||||
{
|
||||
return m_desktopPassword;
|
||||
}
|
||||
|
||||
void InvitationsRfbServer::setDesktopPassword(const QString& password)
|
||||
void InvitationsRfbServer::setDesktopPassword(const QString &password)
|
||||
{
|
||||
m_desktopPassword = password;
|
||||
// this is called from GUI every time desktop password is edited.
|
||||
// make sure we save settings immediately each time
|
||||
saveSecuritySettings();
|
||||
}
|
||||
|
||||
const QString& InvitationsRfbServer::unattendedPassword() const
|
||||
const QString &InvitationsRfbServer::unattendedPassword() const
|
||||
{
|
||||
return m_unattendedPassword;
|
||||
}
|
||||
|
||||
void InvitationsRfbServer::setUnattendedPassword(const QString& password)
|
||||
void InvitationsRfbServer::setUnattendedPassword(const QString &password)
|
||||
{
|
||||
m_unattendedPassword = password;
|
||||
// this is called from GUI every time unattended password is edited.
|
||||
// make sure we save settings immediately each time
|
||||
saveSecuritySettings();
|
||||
}
|
||||
|
||||
bool InvitationsRfbServer::allowUnattendedAccess() const
|
||||
@@ -93,9 +86,10 @@ bool InvitationsRfbServer::allowUnattendedAccess() const
|
||||
|
||||
bool InvitationsRfbServer::start()
|
||||
{
|
||||
if(RfbServer::start()) {
|
||||
if(KrfbConfig::publishService())
|
||||
if (RfbServer::start()) {
|
||||
if (KrfbConfig::publishService()) {
|
||||
m_publicService->publishAsync();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -103,94 +97,82 @@ bool InvitationsRfbServer::start()
|
||||
|
||||
void InvitationsRfbServer::stop()
|
||||
{
|
||||
if(m_publicService->isPublished())
|
||||
if (m_publicService->isPublished()) {
|
||||
m_publicService->stop();
|
||||
}
|
||||
RfbServer::stop();
|
||||
}
|
||||
|
||||
void InvitationsRfbServer::toggleUnattendedAccess(bool allow)
|
||||
{
|
||||
m_allowUnattendedAccess = allow;
|
||||
// this is called from GUI every time unattended access is toggled.
|
||||
// make sure we save settings immediately each time
|
||||
saveSecuritySettings();
|
||||
}
|
||||
|
||||
InvitationsRfbServer::InvitationsRfbServer()
|
||||
{
|
||||
m_desktopPassword = readableRandomString(4)+"-"+readableRandomString(3);
|
||||
m_unattendedPassword = readableRandomString(4)+"-"+readableRandomString(3);
|
||||
KConfigGroup krfbConfig(KSharedConfig::openConfig(),"Security");
|
||||
m_desktopPassword = readableRandomString(4) + QLatin1Char('-') + readableRandomString(3);
|
||||
m_unattendedPassword = readableRandomString(4) + QLatin1Char('-') + readableRandomString(3);
|
||||
KConfigGroup krfbConfig(KSharedConfig::openConfig(), QStringLiteral("Security"));
|
||||
m_allowUnattendedAccess = krfbConfig.readEntry(
|
||||
"allowUnattendedAccess", QVariant(false)).toBool();
|
||||
"allowUnattendedAccess", QVariant(false))
|
||||
.toBool();
|
||||
}
|
||||
|
||||
InvitationsRfbServer::~InvitationsRfbServer()
|
||||
{
|
||||
stop();
|
||||
KConfigGroup krfbConfig(KSharedConfig::openConfig(),"Security");
|
||||
krfbConfig.writeEntry("allowUnattendedAccess",m_allowUnattendedAccess);
|
||||
if(!KrfbConfig::noWallet()) {
|
||||
if (m_wallet && m_wallet->isOpen()) {
|
||||
if( (m_wallet->currentFolder()=="krfb") ||
|
||||
((m_wallet->hasFolder("krfb") || m_wallet->createFolder("krfb")) &&
|
||||
m_wallet->setFolder("krfb")) ) {
|
||||
|
||||
m_wallet->writePassword("desktopSharingPassword",m_desktopPassword);
|
||||
m_wallet->writePassword("unattendedAccessPassword",m_unattendedPassword);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
krfbConfig.writeEntry("desktopPassword",
|
||||
KStringHandler::obscure(m_desktopPassword));
|
||||
krfbConfig.writeEntry("unattendedPassword",
|
||||
KStringHandler::obscure(m_unattendedPassword));
|
||||
krfbConfig.writeEntry("allowUnattendedAccess",
|
||||
m_allowUnattendedAccess);
|
||||
InvitationsRfbServer::stop(); // calling virtual funcs in destructor is bad
|
||||
saveSecuritySettings();
|
||||
// ^^ also saves passwords in kwallet,
|
||||
// do it before closing kwallet
|
||||
if (!KrfbConfig::noWallet() && m_wallet) {
|
||||
closeKWallet();
|
||||
}
|
||||
}
|
||||
|
||||
PendingRfbClient* InvitationsRfbServer::newClient(rfbClientPtr client)
|
||||
PendingRfbClient *InvitationsRfbServer::newClient(rfbClientPtr client)
|
||||
{
|
||||
return new PendingInvitationsRfbClient(client, this);
|
||||
}
|
||||
|
||||
void InvitationsRfbServer::openKWallet()
|
||||
{
|
||||
m_wallet = Wallet::openWallet(Wallet::NetworkWallet(), 0, Wallet::Asynchronous);
|
||||
if (m_wallet) {
|
||||
connect(instance->m_wallet, &KWallet::Wallet::walletOpened,
|
||||
this, &InvitationsRfbServer::walletOpened);
|
||||
}
|
||||
}
|
||||
|
||||
void InvitationsRfbServer::closeKWallet()
|
||||
{
|
||||
if (m_wallet && m_wallet->isOpen()) {
|
||||
delete m_wallet; // closes the wallet
|
||||
m_wallet = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void InvitationsRfbServer::walletOpened(bool opened)
|
||||
{
|
||||
QString desktopPassword;
|
||||
QString unattendedPassword;
|
||||
Q_ASSERT(m_wallet);
|
||||
if( opened &&
|
||||
( m_wallet->hasFolder("krfb") || m_wallet->createFolder("krfb") ) &&
|
||||
m_wallet->setFolder("krfb") ) {
|
||||
|
||||
if(m_wallet->readPassword("desktopSharingPassword", desktopPassword)==0 &&
|
||||
!desktopPassword.isEmpty()) {
|
||||
if (opened && m_wallet->hasFolder(s_krfbFolderName) && m_wallet->setFolder(s_krfbFolderName)) {
|
||||
if (m_wallet->readPassword(QStringLiteral("desktopSharingPassword"), desktopPassword) == 0 && !desktopPassword.isEmpty()) {
|
||||
m_desktopPassword = desktopPassword;
|
||||
emit passwordChanged(m_desktopPassword);
|
||||
Q_EMIT passwordChanged(m_desktopPassword);
|
||||
}
|
||||
|
||||
if(m_wallet->readPassword("unattendedAccessPassword", unattendedPassword)==0 &&
|
||||
!unattendedPassword.isEmpty()) {
|
||||
if (m_wallet->readPassword(QStringLiteral("unattendedAccessPassword"), unattendedPassword) == 0 && !unattendedPassword.isEmpty()) {
|
||||
m_unattendedPassword = unattendedPassword;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
qDebug() << "Could not open KWallet, Falling back to config file";
|
||||
KConfigGroup krfbConfig(KSharedConfig::openConfig(),"Security");
|
||||
|
||||
desktopPassword = KStringHandler::obscure(krfbConfig.readEntry(
|
||||
"desktopPassword", QString()));
|
||||
if(!desktopPassword.isEmpty()) {
|
||||
m_desktopPassword = desktopPassword;
|
||||
emit passwordChanged(m_desktopPassword);
|
||||
}
|
||||
|
||||
unattendedPassword = KStringHandler::obscure(krfbConfig.readEntry(
|
||||
"unattendedPassword", QString()));
|
||||
if(!unattendedPassword.isEmpty()) {
|
||||
m_unattendedPassword = unattendedPassword;
|
||||
}
|
||||
|
||||
qCDebug(KRFB) << "Could not open KWallet, Falling back to config file";
|
||||
readPasswordFromConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +182,7 @@ QString InvitationsRfbServer::readableRandomString(int length)
|
||||
{
|
||||
QString str;
|
||||
while (length) {
|
||||
int r = KRandom::random() % 62;
|
||||
int r = QRandomGenerator::global()->bounded(62);
|
||||
r += 48;
|
||||
if (r > 57) {
|
||||
r += 7;
|
||||
@@ -209,19 +191,59 @@ QString InvitationsRfbServer::readableRandomString(int length)
|
||||
r += 6;
|
||||
}
|
||||
char c = char(r);
|
||||
if ((c == 'i') ||
|
||||
(c == 'I') ||
|
||||
(c == '1') ||
|
||||
(c == 'l') ||
|
||||
(c == 'o') ||
|
||||
(c == 'O') ||
|
||||
(c == '0')) {
|
||||
if ((c == 'i') || (c == 'I') || (c == '1') || (c == 'l') || (c == 'o') || (c == 'O') || (c == '0')) {
|
||||
continue;
|
||||
}
|
||||
str += c;
|
||||
str += QLatin1Char(c);
|
||||
length--;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
#include "invitationsrfbserver.moc"
|
||||
// one place to deal with all security configuration
|
||||
void InvitationsRfbServer::saveSecuritySettings()
|
||||
{
|
||||
KConfigGroup secConfigGroup(KSharedConfig::openConfig(), QStringLiteral("Security"));
|
||||
secConfigGroup.writeEntry("allowUnattendedAccess", m_allowUnattendedAccess);
|
||||
if (KrfbConfig::noWallet()) {
|
||||
// save passwords in config file only if not using kwallet integration
|
||||
secConfigGroup.writeEntry("desktopPassword", KStringHandler::obscure(m_desktopPassword));
|
||||
secConfigGroup.writeEntry("unattendedPassword", KStringHandler::obscure(m_unattendedPassword));
|
||||
} else {
|
||||
// using KWallet, erase possibly stored passwords from krfbrc file
|
||||
secConfigGroup.deleteEntry("desktopPassword");
|
||||
secConfigGroup.deleteEntry("unattendedPassword");
|
||||
// update passwords in kwallet
|
||||
if (m_wallet && m_wallet->isOpen()) {
|
||||
if (!m_wallet->hasFolder(s_krfbFolderName)) {
|
||||
m_wallet->createFolder(s_krfbFolderName);
|
||||
}
|
||||
if (m_wallet->currentFolder() != s_krfbFolderName) {
|
||||
m_wallet->setFolder(s_krfbFolderName);
|
||||
}
|
||||
m_wallet->writePassword(QStringLiteral("desktopSharingPassword"), m_desktopPassword);
|
||||
m_wallet->writePassword(QStringLiteral("unattendedAccessPassword"), m_unattendedPassword);
|
||||
}
|
||||
}
|
||||
KrfbConfig::self()->save();
|
||||
}
|
||||
|
||||
void InvitationsRfbServer::readPasswordFromConfig()
|
||||
{
|
||||
QString desktopPassword;
|
||||
QString unattendedPassword;
|
||||
KConfigGroup krfbConfig(KSharedConfig::openConfig(), QStringLiteral("Security"));
|
||||
|
||||
desktopPassword = KStringHandler::obscure(krfbConfig.readEntry(
|
||||
"desktopPassword", QString()));
|
||||
if (!desktopPassword.isEmpty()) {
|
||||
m_desktopPassword = desktopPassword;
|
||||
Q_EMIT passwordChanged(m_desktopPassword);
|
||||
}
|
||||
|
||||
unattendedPassword = KStringHandler::obscure(krfbConfig.readEntry(
|
||||
"unattendedPassword", QString()));
|
||||
if (!unattendedPassword.isEmpty()) {
|
||||
m_unattendedPassword = unattendedPassword;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,72 +1,72 @@
|
||||
/*
|
||||
Copyright (C) 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
SPDX-FileCopyrightText: 2009-2010 Collabora Ltd <info@collabora.co.uk>
|
||||
SPDX-FileContributor: George Goldberg <george.goldberg@collabora.co.uk>
|
||||
SPDX-FileContributor: George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
|
||||
SPDX-FileCopyrightText: 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#ifndef INVITATIONSRFBSERVER_H
|
||||
#define INVITATIONSRFBSERVER_H
|
||||
|
||||
#include "rfbserver.h"
|
||||
|
||||
namespace KWallet {
|
||||
class Wallet;
|
||||
namespace KWallet
|
||||
{
|
||||
|
||||
class Wallet;
|
||||
|
||||
}
|
||||
|
||||
namespace KDNSSD {
|
||||
class PublicService;
|
||||
namespace KDNSSD
|
||||
{
|
||||
|
||||
class PublicService;
|
||||
|
||||
}
|
||||
|
||||
class InvitationsRfbServer : public RfbServer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static InvitationsRfbServer *instance;
|
||||
static void init();
|
||||
|
||||
const QString& desktopPassword() const;
|
||||
void setDesktopPassword(const QString&);
|
||||
const QString& unattendedPassword() const;
|
||||
void setUnattendedPassword(const QString&);
|
||||
const QString &desktopPassword() const;
|
||||
void setDesktopPassword(const QString &);
|
||||
const QString &unattendedPassword() const;
|
||||
void setUnattendedPassword(const QString &);
|
||||
bool allowUnattendedAccess() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void passwordChanged(const QString&);
|
||||
void passwordChanged(const QString &);
|
||||
|
||||
public Q_SLOTS:
|
||||
bool start() override;
|
||||
void stop() override;
|
||||
void toggleUnattendedAccess(bool allow);
|
||||
void openKWallet();
|
||||
void closeKWallet();
|
||||
void saveSecuritySettings();
|
||||
|
||||
protected:
|
||||
InvitationsRfbServer();
|
||||
virtual ~InvitationsRfbServer();
|
||||
PendingRfbClient* newClient(rfbClientPtr client) override;
|
||||
~InvitationsRfbServer() override;
|
||||
PendingRfbClient *newClient(rfbClientPtr client) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void walletOpened(bool);
|
||||
|
||||
private:
|
||||
KDNSSD::PublicService *m_publicService;
|
||||
KDNSSD::PublicService *m_publicService = nullptr;
|
||||
bool m_allowUnattendedAccess;
|
||||
QString m_desktopPassword;
|
||||
QString m_unattendedPassword;
|
||||
KWallet::Wallet *m_wallet;
|
||||
KWallet::Wallet *m_wallet = nullptr;
|
||||
|
||||
QString readableRandomString(int);
|
||||
void readPasswordFromConfig();
|
||||
Q_DISABLE_COPY(InvitationsRfbServer)
|
||||
};
|
||||
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=ServiceType
|
||||
X-KDE-ServiceType=krfb/framebuffer
|
||||
|
||||
Comment=Frame Buffer plugins for KRfb
|
||||
Comment[ast]=Complementu de buffer pa KRfb
|
||||
Comment[bg]=Приставки за фреймбуфер за KRfb
|
||||
Comment[bs]=Priključci framebafera za KRfb
|
||||
Comment[ca]=Connectors de «framebuffer» per al KRfb.
|
||||
Comment[ca@valencia]=Connectors de «framebuffer» per al KRfb.
|
||||
Comment[cs]=Moduly Frame bufferu pro KRfb
|
||||
Comment[da]=Framebuffer-plugins til KRfb
|
||||
Comment[de]=Framebuffer-Module für KRfb
|
||||
Comment[el]=Πρόσθετα μνήμης εξόδου βίντεο καρέ για το KRfb
|
||||
Comment[en_GB]=Frame Buffer plugins for KRfb
|
||||
Comment[es]=Complementos de memoria intermedia de vídeo para KRfb
|
||||
Comment[et]=KRfb kaadripuhvri plugin
|
||||
Comment[eu]=Irteerako bideoaren pluginak KRfb-rentzako
|
||||
Comment[fi]=Kehyspuskuriliitännäinen kohteelle KRfb
|
||||
Comment[fr]=Modules externes de sortie vidéo pour Krfb
|
||||
Comment[ga]=Breiseáin Mhaoláin Fráma le haghaidh KRfb
|
||||
Comment[gl]=Engadido de frame buffer para KRfb
|
||||
Comment[hr]=Priključci za međuspremnike okvira za KRfb
|
||||
Comment[hu]=Framebuffer bővítmények a Krfb-hez
|
||||
Comment[ia]=Plug-ins de Frame Buffer per KRfb
|
||||
Comment[it]=Estensioni del framebuffer per KRfb
|
||||
Comment[ja]=KRfb の フレームバッファプラグイン
|
||||
Comment[kk]=KRfb кадр буфер плагині
|
||||
Comment[km]=កម្មវិធីជំនួយ Frame Buffer សម្រាប់ KRfb
|
||||
Comment[ko]=KRfb 프레임버퍼 플러그인
|
||||
Comment[lt]=Frame Buffer papildiniai skirti KRfb
|
||||
Comment[lv]=Kadru bufera sprudņi priekš KRfb
|
||||
Comment[nb]=Rammebuffer-programtillegg for KRfb
|
||||
Comment[nds]=Bildpuffer-Modulen för KRfb
|
||||
Comment[nl]=Framebuffer-plugins voor KRfb
|
||||
Comment[nn]=Framebuffer-tillegg KRfb
|
||||
Comment[pa]=KRfb ਲਈ ਫਰੇਮ ਬਫ਼ਰ ਪਲੱਗਇਨ
|
||||
Comment[pl]=Wtyczki buforów ramek dla KRfb
|
||||
Comment[pt]='Plugins' de 'framebuffers' para o KRfb
|
||||
Comment[pt_BR]=Plugins de framebuffers para o KRfb
|
||||
Comment[ru]=Модуль буфера кадров для KRfb
|
||||
Comment[si]=KRfb සඳහා රාමු බෆර ප්ලගින
|
||||
Comment[sk]=Frame Buffer modul pre KRfb
|
||||
Comment[sl]=Vstavki slikovnih medpomnilnikov za KRFB
|
||||
Comment[sr]=Прикључци кадробафера за КРФБ
|
||||
Comment[sr@ijekavian]=Прикључци кадробафера за КРФБ
|
||||
Comment[sr@ijekavianlatin]=Priključci kadrobafera za KRFB
|
||||
Comment[sr@latin]=Priključci kadrobafera za KRFB
|
||||
Comment[sv]=Insticksprogram med rambuffert för Krfb
|
||||
Comment[th]=ส่วนเสริมของ KRfb สำหรับจัดการเฟรมบัฟเฟอร์
|
||||
Comment[tr]=KRfb için Çerçeve Tamponu eklentileri
|
||||
Comment[uk]=Додатки буфера кадрів для KRfb
|
||||
Comment[x-test]=xxFrame Buffer plugins for KRfbxx
|
||||
Comment[zh_CN]=KRfb 帧缓冲插件
|
||||
Comment[zh_TW]=KRfb 的 Frame Buffer 外掛程式
|
||||
@@ -1,32 +0,0 @@
|
||||
{
|
||||
"KPlugin": {
|
||||
"Description": "Frame Buffer plugins for KRfb",
|
||||
"Description[ca@valencia]": "Connectors de «framebuffer» per al KRfb.",
|
||||
"Description[ca]": "Connectors de «framebuffer» per al KRfb.",
|
||||
"Description[cs]": "Moduly Frame bufferu pro KRfb",
|
||||
"Description[da]": "Framebuffer-plugins til KRfb",
|
||||
"Description[de]": "Framebuffer-Module für KRfb",
|
||||
"Description[en_GB]": "Frame Buffer plugins for KRfb",
|
||||
"Description[es]": "Complementos de framebuffer para KRfb",
|
||||
"Description[fi]": "Kehyspuskuriliitännäinen kohteelle KRfb",
|
||||
"Description[gl]": "Engadido de frame buffer para KRfb",
|
||||
"Description[it]": "Estensioni del framebuffer per KRfb",
|
||||
"Description[ko]": "KRfb 프레임버퍼 플러그인",
|
||||
"Description[nl]": "Framebuffer-plugins voor KRfb",
|
||||
"Description[pl]": "Wtyczki buforów ramek dla KRfb",
|
||||
"Description[pt]": "'Plugins' do 'Framebuffer' para o KRfb",
|
||||
"Description[pt_BR]": "Plugins de framebuffers para o KRfb",
|
||||
"Description[sk]": "Frame Buffer modul pre KRfb",
|
||||
"Description[sl]": "Vstavki slikovnih medpomnilnikov za KRfb",
|
||||
"Description[sr@ijekavian]": "Прикључци кадробафера за КРФБ",
|
||||
"Description[sr@ijekavianlatin]": "Priključci kadrobafera za KRFB",
|
||||
"Description[sr@latin]": "Priključci kadrobafera za KRFB",
|
||||
"Description[sr]": "Прикључци кадробафера за КРФБ",
|
||||
"Description[sv]": "Insticksprogram med rambuffert för Krfb",
|
||||
"Description[uk]": "Додатки буфера кадрів для KRfb",
|
||||
"Description[x-test]": "xxFrame Buffer plugins for KRfbxx",
|
||||
"Description[zh_CN]": "KRfb 的帧缓冲插件",
|
||||
"Description[zh_TW]": "KRfb 的 Frame Buffer 外掛程式"
|
||||
},
|
||||
"X-KDE-ServiceType": "krfb/framebuffer"
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE kcfg SYSTEM
|
||||
"http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
|
||||
<kcfg>
|
||||
<kcfgfile />
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<kcfgfile name="krfbrc"/>
|
||||
<group name="MainWindow">
|
||||
<entry name="startMinimized" type="Bool">
|
||||
<label>Start minimized</label>
|
||||
@@ -46,7 +47,7 @@
|
||||
<group name="FrameBuffer">
|
||||
<entry name="preferredFrameBufferPlugin" type="String">
|
||||
<label>Preferred Frame Buffer Plugin</label>
|
||||
<default>x11</default>
|
||||
<default>xcb</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
|
||||
@@ -3,13 +3,12 @@ IconName=krfb
|
||||
Comment=Desktop Sharing
|
||||
Comment[af]=Werkskerm Deeling
|
||||
Comment[ar]=مشاركة سطح المكتب
|
||||
Comment[ast]=Escritoriu compartíu
|
||||
Comment[bg]=Споделяне на работния плот
|
||||
Comment[bn]=ডেস্কটপ ভাগাভাগি
|
||||
Comment[br]=Rannañ ar vurev
|
||||
Comment[bs]=Dijeljenje radne površine
|
||||
Comment[ca]=Compartició de l'escriptori
|
||||
Comment[ca@valencia]=Compartició de l'escriptori
|
||||
Comment[ca]=Compartir l'escriptori
|
||||
Comment[ca@valencia]=Compartir l'escriptori
|
||||
Comment[cs]=Sdílení pracovní plochy
|
||||
Comment[cy]=Rhannu Penbwrdd
|
||||
Comment[da]=Skrivebordsdeling
|
||||
@@ -30,13 +29,15 @@ Comment[hne]=डेस्कटाप साझेदारी
|
||||
Comment[hr]=Dijeljenje radne površine
|
||||
Comment[hu]=Munkaasztal-megosztás
|
||||
Comment[ia]=Compartir de scriptorio
|
||||
Comment[id]=Desktop Sharing
|
||||
Comment[is]=Skjáborðamiðlun
|
||||
Comment[it]=Condivisione del desktop
|
||||
Comment[ja]=デスクトップ共有
|
||||
Comment[ka]=სამუშაო მაგიდის გაზიარება
|
||||
Comment[kk]=Үстелді ортақтастыру
|
||||
Comment[km]=ការចែករំលែកផ្ទែតុ
|
||||
Comment[ko]=데스크톱 공유
|
||||
Comment[lt]=Dalinimasis darbalaukiu
|
||||
Comment[lt]=Darbalaukio bendrinimas
|
||||
Comment[lv]=Darbvirsmas koplietošana
|
||||
Comment[mk]=Делење на работната површина
|
||||
Comment[ml]=പണിയിടം പങ്കുവെക്കല്
|
||||
@@ -52,6 +53,7 @@ Comment[pt]=Partilha do Ecrã
|
||||
Comment[pt_BR]=Compartilhamento do ambiente de trabalho
|
||||
Comment[ro]=Partajare birou
|
||||
Comment[ru]=Параметры общего рабочего стола
|
||||
Comment[sa]=डेस्कटॉप् साझेदारी
|
||||
Comment[si]=වැඩතල හවුල්
|
||||
Comment[sk]=Zdieľanie pracovnej plochy
|
||||
Comment[sl]=Souporaba namizja
|
||||
@@ -67,7 +69,6 @@ Comment[tr]=Masaüstü Paylaşımı
|
||||
Comment[ug]=ئۈستەلئۈستىنى ھەمبەھىرلەش
|
||||
Comment[uk]=Спільні стільниці
|
||||
Comment[xh]=Ulwahlulelano lwe Desktop
|
||||
Comment[x-test]=xxDesktop Sharingxx
|
||||
Comment[zh_CN]=桌面共享
|
||||
Comment[zh_HK]=桌面分享
|
||||
Comment[zh_TW]=桌面分享
|
||||
@@ -75,7 +76,6 @@ Comment[zh_TW]=桌面分享
|
||||
[Event/UserAcceptsConnection]
|
||||
Name=User Accepts Connection
|
||||
Name[ar]=المستخدم يقبل الاتصال
|
||||
Name[ast]=L'usuariu aceuta la conexón
|
||||
Name[bg]=Потребителят приема връзката
|
||||
Name[bs]=Korisnik prihvata vezu
|
||||
Name[ca]=L'usuari accepta la connexió
|
||||
@@ -93,14 +93,17 @@ Name[fi]=Käyttäjä hyväksyy yhteyden
|
||||
Name[fr]=L'utilisateur accepte la connexion
|
||||
Name[ga]=Glacann an tÚsáideoir Le Ceangal
|
||||
Name[gl]=O usuario acepta a conexión
|
||||
Name[he]=המשתמש מאשר חיבור
|
||||
Name[hi]=उपयोक्ता ने कनेक्शन स्वीकारा
|
||||
Name[hne]=कमइया हर कनेक्सन स्वीकारा
|
||||
Name[hr]=Korisnik prihvaća vezu
|
||||
Name[hu]=A felhasználó engedélyezi a csatlakozást
|
||||
Name[ia]=Usator da acceptation a connexion
|
||||
Name[id]=Pengguna Menyetujui Koneksi
|
||||
Name[is]=Notandi samþykkir tengingar
|
||||
Name[it]=L'utente accetta la connessione
|
||||
Name[ja]=ユーザが接続を許可
|
||||
Name[ka]=მომხმარებელი დაეთანხმა მიერთებას
|
||||
Name[kk]=Пайдаланушы қосылымды қабылдайды
|
||||
Name[km]=អ្នកប្រើទទួលយកការតភ្ជាប់
|
||||
Name[ko]=사용자가 연결을 수락함
|
||||
@@ -118,6 +121,7 @@ Name[pt]=O Utilizador Aceita a Ligação
|
||||
Name[pt_BR]=O usuário aceita a conexão
|
||||
Name[ro]=Utilizatorul acceptă conexiunea
|
||||
Name[ru]=Пользователь принимает соединения
|
||||
Name[sa]=उपयोक्ता संयोजनं स्वीकुर्वति
|
||||
Name[si]=සබැඳිය පරිශීලකයා තහවුරු කරයි
|
||||
Name[sk]=Užívateľ akceptuje pripojenie
|
||||
Name[sl]=Uporabnik sprejema povezavo
|
||||
@@ -130,13 +134,11 @@ Name[th]=ผู้ใช้ยอมรับการเชื่อมต่
|
||||
Name[tr]=Kullanıcı Bağlantıyı Kabul Etti
|
||||
Name[ug]=ئىشلەتكۈچى باغلىنىشقا قوشۇلدى
|
||||
Name[uk]=Користувач приймає з’єднання
|
||||
Name[x-test]=xxUser Accepts Connectionxx
|
||||
Name[zh_CN]=用户接受连接
|
||||
Name[zh_TW]=使用者接受連線
|
||||
Comment=User accepts connection
|
||||
Comment[af]=Gebruiker aanvaar verbinding
|
||||
Comment[ar]=المستخدم يقبل الاتصال
|
||||
Comment[ast]=L'usuariu aceuta la conexón
|
||||
Comment[bg]=Потребителят приема връзката
|
||||
Comment[bn]=ব্যবহারকারী সংযোগ গ্রহণ করে
|
||||
Comment[bs]=Korisnik prihvata vezu
|
||||
@@ -156,15 +158,17 @@ Comment[fi]=Käyttäjä hyväksyy yhteyden
|
||||
Comment[fr]=L'utilisateur accepte la connexion
|
||||
Comment[ga]=Glacann úsáideoir le ceangal
|
||||
Comment[gl]=O usuario acepta a conexión
|
||||
Comment[he]=המשתמש מקבל את החיבור
|
||||
Comment[he]=המשתמש מאשר את החיבור
|
||||
Comment[hi]=उपयोक्ता ने कनेक्शन स्वीकारा
|
||||
Comment[hne]=कमइया हर कनेक्सन स्वीकारा
|
||||
Comment[hr]=Korisnik prihvaća vezu
|
||||
Comment[hu]=A felhasználó engedélyezi a csatlakozást
|
||||
Comment[ia]=Usator da acceptation a connexion
|
||||
Comment[id]=Pengguna menyetujui koneksi
|
||||
Comment[is]=Notandi samþykkir tengingu
|
||||
Comment[it]=L'utente accetta la connessione
|
||||
Comment[ja]=ユーザが接続を許可
|
||||
Comment[ka]=მომხმარებელი დაეთანხმა მიერთებას
|
||||
Comment[kk]=Пайдаланушы қосылымды қабылдайды
|
||||
Comment[km]=អ្នកប្រើទទួលយកការតភ្ជាប់
|
||||
Comment[ko]=사용자가 연결을 수락함
|
||||
@@ -184,6 +188,7 @@ Comment[pt]=O utilizador aceita a ligação
|
||||
Comment[pt_BR]=O usuário aceita a conexão
|
||||
Comment[ro]=Utilizatorul acceptă conexiunea
|
||||
Comment[ru]=Пользователь принимает соединения
|
||||
Comment[sa]=उपयोक्ता संयोजनं स्वीकुर्वति
|
||||
Comment[si]=සබැඳිය පරිශීලකයා තහවුරු කරයි
|
||||
Comment[sk]=Užívateľ akceptuje pripojenie
|
||||
Comment[sl]=Uporabnik sprejema povezavo
|
||||
@@ -199,7 +204,6 @@ Comment[tr]=Kullanıcı bağlantıyı kabul etti
|
||||
Comment[ug]=ئىشلەتكۈچى باغلىنىشقا قوشۇلدى
|
||||
Comment[uk]=Користувач приймає з’єднання
|
||||
Comment[xh]=Umsebenzisi wamkela uxhulumaniso
|
||||
Comment[x-test]=xxUser accepts connectionxx
|
||||
Comment[zh_CN]=用户接受连接
|
||||
Comment[zh_HK]=用戶接受連線
|
||||
Comment[zh_TW]=使用者接受連線
|
||||
@@ -208,7 +212,6 @@ Action=Popup
|
||||
[Event/UserRefusesConnection]
|
||||
Name=User Refuses Connection
|
||||
Name[ar]=المستخدم يرفض الاتصال
|
||||
Name[ast]=L'usuariu refuga la conexón
|
||||
Name[bg]=Потребителят отказва връзката
|
||||
Name[bs]=Korisnik odbija vezu
|
||||
Name[ca]=L'usuari refusa la connexió
|
||||
@@ -226,14 +229,17 @@ Name[fi]=Käyttäjä hylkää yhteyden
|
||||
Name[fr]=L'utilisateur refuse la connexion
|
||||
Name[ga]=Diúltaíonn an tÚsáideoir Le Ceangal
|
||||
Name[gl]=O usuario rexeita a conexión
|
||||
Name[he]=המשתמש מסרב לחיבור
|
||||
Name[hi]=उपयोक्ता ने कनेक्शन अस्वीकारा
|
||||
Name[hne]=कमइया हर कनेक्सन अस्वीकारा
|
||||
Name[hr]=Korisnik odbija vezu
|
||||
Name[hu]=A felhasználó elutasítja a csatlakozást
|
||||
Name[ia]=Usator refuta connexion
|
||||
Name[id]=Pengguna Menampik Koneksi
|
||||
Name[is]=Notandi hafnar tengingum
|
||||
Name[it]=L'utente rifiuta la connessione
|
||||
Name[ja]=ユーザが接続を拒否
|
||||
Name[ka]=მომხმარებელმა უარყო მიერთებას
|
||||
Name[kk]=Пайдаланушы қосылымдан бас тартады
|
||||
Name[km]=អ្នកប្រើបដិសេធការតភ្ជាប់
|
||||
Name[ko]=사용자가 연결을 거부함
|
||||
@@ -251,6 +257,7 @@ Name[pt]=O Utilizador Recusa a Ligação
|
||||
Name[pt_BR]=O usuário rejeita a conexão
|
||||
Name[ro]=Utilizatorul refuză conexiunea
|
||||
Name[ru]=Пользователь отклоняет соединения
|
||||
Name[sa]=उपयोक्ता संयोजनं अङ्गीकुर्वति
|
||||
Name[si]=සබැඳිය පරිශීලකයා තහවුරු නොකරයි
|
||||
Name[sk]=Užívateľ odmieta pripojenie
|
||||
Name[sl]=Uporabnik zavrača povezavo
|
||||
@@ -263,13 +270,11 @@ Name[th]=ผู้ใช้ปฏิเสธการเชื่อมต่
|
||||
Name[tr]=Kullanıcı Bağlantıyı Reddetti
|
||||
Name[ug]=ئىشلەتكۈچى باغلىنىشنى رەت قىلدى
|
||||
Name[uk]=Користувач не приймає з’єднання
|
||||
Name[x-test]=xxUser Refuses Connectionxx
|
||||
Name[zh_CN]=用户拒绝连接
|
||||
Name[zh_TW]=使用者拒絕連線
|
||||
Comment=User refuses connection
|
||||
Comment[af]=Gebruiker weier verbinding
|
||||
Comment[ar]=المستخدم يرفض الاتصال
|
||||
Comment[ast]=L'usuariu refuga la conexón
|
||||
Comment[bg]=Потребителят отказва връзката
|
||||
Comment[bn]=ব্যবহারকারী সংযোগ অস্বীকার করে
|
||||
Comment[bs]=Korisnik odbija vezu
|
||||
@@ -295,9 +300,11 @@ Comment[hne]=कमइया हर कनेक्सन अस्वीका
|
||||
Comment[hr]=Korisnik odbija vezu
|
||||
Comment[hu]=A felhasználó elutasítja a csatlakozást
|
||||
Comment[ia]=Usator refuta connexion
|
||||
Comment[id]=Pengguna menampik koneksi
|
||||
Comment[is]=Notandi hafnar tengingu
|
||||
Comment[it]=L'utente rifiuta la connessione
|
||||
Comment[ja]=ユーザが接続を拒否
|
||||
Comment[ka]=მომხმარებელმა უარყო მიერთებას
|
||||
Comment[kk]=Пайдаланушы қосылымды қабылдамайды
|
||||
Comment[km]=អ្នកប្រើបដិសេធការតភ្ជាប់
|
||||
Comment[ko]=사용자가 연결을 거부함
|
||||
@@ -317,6 +324,7 @@ Comment[pt]=O utilizador recusa a ligação
|
||||
Comment[pt_BR]=O usuário rejeita a conexão
|
||||
Comment[ro]=Utilizatorul refuză conexiunea
|
||||
Comment[ru]=Пользователь отклоняет соединения
|
||||
Comment[sa]=उपयोक्ता संयोजनं नकारयति
|
||||
Comment[si]=සබැඳිය පරිශීලකයා තහවුරු නොකරයි
|
||||
Comment[sk]=Užívateľ odmieta pripojenie
|
||||
Comment[sl]=Uporabnik zavrača povezavo
|
||||
@@ -332,7 +340,6 @@ Comment[tr]=Kullanıcı bağlantıyı reddetti
|
||||
Comment[ug]=ئىشلەتكۈچى باغلىنىشنى رەت قىلدى
|
||||
Comment[uk]=Користувач не приймає з’єднання
|
||||
Comment[xh]=Umsebenzisi wala uxhulumaniso
|
||||
Comment[x-test]=xxUser refuses connectionxx
|
||||
Comment[zh_CN]=用户拒绝连接
|
||||
Comment[zh_HK]=用戶拒絕連線
|
||||
Comment[zh_TW]=使用者拒絕連線使用者
|
||||
@@ -341,7 +348,6 @@ Action=Popup
|
||||
[Event/ConnectionClosed]
|
||||
Name=Connection Closed
|
||||
Name[ar]=الاتصال أغلق
|
||||
Name[ast]=Conexón zarrada
|
||||
Name[bg]=Връзката е прекъсната
|
||||
Name[bs]=Konekcija zatvorena
|
||||
Name[ca]=Connexió tancada
|
||||
@@ -358,20 +364,23 @@ Name[eu]=Konexioa itxi da
|
||||
Name[fi]=Yhteys suljettu
|
||||
Name[fr]=Connexion fermée
|
||||
Name[ga]=Ceangal Dúnta
|
||||
Name[gl]=Conexión fechada
|
||||
Name[gl]=Conexión pechada
|
||||
Name[he]=החיבור נסגר
|
||||
Name[hi]=कनेक्शन बन्द
|
||||
Name[hne]=कनेक्सन बन्द
|
||||
Name[hr]=Veza prekinuta
|
||||
Name[hu]=A kapcsolat megszűnt
|
||||
Name[ia]=Connexion claudite
|
||||
Name[id]=Koneksi Ditutup
|
||||
Name[is]=Tengingu lokað
|
||||
Name[it]=Connessione chiusa
|
||||
Name[ja]=接続切断
|
||||
Name[ka]=კავშირი დაიხურა
|
||||
Name[kk]=Қосылымдан жабылды
|
||||
Name[km]=បានបិទការតភ្ជាប់
|
||||
Name[ko]=연결이 닫힘
|
||||
Name[lt]=Ryšys baigtas
|
||||
Name[lv]=Savienojums slēgts
|
||||
Name[lt]=Ryšys nutrauktas
|
||||
Name[lv]=Savienojums ir slēgts
|
||||
Name[mai]=संबंधन बन्न भ' गेल
|
||||
Name[ml]=ബന്ധം അടച്ചു
|
||||
Name[mr]=जुळवणी बंद केली
|
||||
@@ -385,6 +394,7 @@ Name[pt]=Ligação Fechada
|
||||
Name[pt_BR]=Conexão encerrada
|
||||
Name[ro]=Conexiune închisă
|
||||
Name[ru]=Соединение закрыто
|
||||
Name[sa]=संयोजनं बन्दम्
|
||||
Name[si]=සබඳතාව වසා දැමිනි
|
||||
Name[sk]=Pripojenie bolo ukončené
|
||||
Name[sl]=Povezava zaprta
|
||||
@@ -398,13 +408,11 @@ Name[th]=การเชื่อมต่อยุติ
|
||||
Name[tr]=Bağlantı Kapatıldı
|
||||
Name[ug]=باغلىنىش يېپىلدى
|
||||
Name[uk]=З'єднання закрито
|
||||
Name[x-test]=xxConnection Closedxx
|
||||
Name[zh_CN]=连接关闭
|
||||
Name[zh_TW]=連線已關閉
|
||||
Comment=Connection closed
|
||||
Comment[af]=Verbinding gesluit
|
||||
Comment[ar]=تمّ غلق الاتصال
|
||||
Comment[ast]=Conexón zarrada
|
||||
Comment[bg]=Връзката е прекъсната
|
||||
Comment[bn]=সংযোগ বন্ধ করা হল
|
||||
Comment[br]=Serret eo ar gevreadenn
|
||||
@@ -424,21 +432,23 @@ Comment[eu]=Konexioa itxi da
|
||||
Comment[fi]=Yhteys suljettu
|
||||
Comment[fr]=Connexion fermée
|
||||
Comment[ga]=Ceangal dúnta
|
||||
Comment[gl]=A conexión está fechada
|
||||
Comment[gl]=A conexión está pechada
|
||||
Comment[he]=החיבור נסגר
|
||||
Comment[hi]=कनेक्शन बन्द
|
||||
Comment[hne]=कनेक्सन बन्द
|
||||
Comment[hr]=Veza prekinuta
|
||||
Comment[hu]=A kapcsolat megszűnt
|
||||
Comment[ia]=Connexion claudite
|
||||
Comment[id]=Koneksi ditutup
|
||||
Comment[is]=Tengingu lokað
|
||||
Comment[it]=Connessione chiusa
|
||||
Comment[ja]=接続が閉じられました
|
||||
Comment[ka]=კავშირი დახურულია
|
||||
Comment[kk]=Қосылым жабылды
|
||||
Comment[km]=បានបិទការតភ្ជាប់
|
||||
Comment[ko]=연결이 닫힘
|
||||
Comment[lt]=Ryšys baigtas
|
||||
Comment[lv]=Savienojums tika slēgts
|
||||
Comment[lt]=Ryšys nutrauktas
|
||||
Comment[lv]=Savienojums ir slēgts
|
||||
Comment[mk]=Поврзувањето е затворено
|
||||
Comment[ml]=ബന്ധം അടച്ചു
|
||||
Comment[mr]=जुळवणी बंद केली
|
||||
@@ -453,6 +463,7 @@ Comment[pt]=A ligação foi encerrada
|
||||
Comment[pt_BR]=Conexão encerrada
|
||||
Comment[ro]=Conexiune închisă
|
||||
Comment[ru]=Соединение закрыто
|
||||
Comment[sa]=संयोजनं बन्दम्
|
||||
Comment[si]=සබඳතාව වසාදැමිනි
|
||||
Comment[sk]=Pripojenie bolo ukončené
|
||||
Comment[sl]=Povezava zaprta
|
||||
@@ -471,7 +482,6 @@ Comment[uk]=З'єднання закрито
|
||||
Comment[uz]=Aloqa uzildi
|
||||
Comment[uz@cyrillic]=Алоқа узилди
|
||||
Comment[xh]=Uxhulumaniso luvaliwe
|
||||
Comment[x-test]=xxConnection closedxx
|
||||
Comment[zh_CN]=连接关闭
|
||||
Comment[zh_HK]=連線已關閉
|
||||
Comment[zh_TW]=連線已關閉
|
||||
@@ -479,8 +489,7 @@ Action=Popup
|
||||
|
||||
[Event/InvalidPassword]
|
||||
Name=Invalid Password
|
||||
Name[ar]=كلمة المرور غير صحيحة
|
||||
Name[ast]=Contraseña incorreuta
|
||||
Name[ar]=كلمة السر غير صحيحة
|
||||
Name[bg]=Неправилна парола
|
||||
Name[bs]=Neispravna šifra
|
||||
Name[ca]=Contrasenya no vàlida
|
||||
@@ -497,19 +506,22 @@ Name[eu]=Baliogabeko pasahitza
|
||||
Name[fi]=Virheellinen salasana
|
||||
Name[fr]=Mot de passe non valable
|
||||
Name[ga]=Focal Faire Neamhbhailí
|
||||
Name[gl]=O contrasinal non é válido
|
||||
Name[gl]=O contrasinal é incorrecto
|
||||
Name[he]=סיסמה שגויה
|
||||
Name[hi]=अवैध पासवर्ड
|
||||
Name[hne]=अवैध पासवर्ड
|
||||
Name[hr]=Nevažeća zaporka
|
||||
Name[hu]=Érvénytelen jelszó
|
||||
Name[ia]=Contrasigno invalide
|
||||
Name[id]=Sandi Tidak Absah
|
||||
Name[is]=Ógilt lykilorð
|
||||
Name[it]=Password non valida
|
||||
Name[ja]=無効なパスワード
|
||||
Name[ka]=არასწორი პაროლი
|
||||
Name[kk]=Жарамсыз паролі
|
||||
Name[km]=ពាក្យសម្ងាត់មិនត្រឹមត្រូវ
|
||||
Name[ko]=잘못된 암호
|
||||
Name[lt]=Neteisingas slaptažodžis
|
||||
Name[lt]=Neteisingas slaptažodis
|
||||
Name[lv]=Nederīga parole
|
||||
Name[ml]=അസാധുവായ അടയാളവാക്ക്
|
||||
Name[mr]=अवैध गुप्तशब्द
|
||||
@@ -518,11 +530,12 @@ Name[nds]=Leeg Passwoort
|
||||
Name[nl]=Ongeldig wachtwoord
|
||||
Name[nn]=Ugyldig passord
|
||||
Name[pa]=ਗਲਤ ਪਾਸਵਰਡ
|
||||
Name[pl]=Błędne hasło
|
||||
Name[pl]=Nieprawidłowe hasło
|
||||
Name[pt]=Senha Inválida
|
||||
Name[pt_BR]=Senha inválida
|
||||
Name[ro]=Parolă nevalidă
|
||||
Name[ru]=Неверный пароль
|
||||
Name[sa]=अमान्य गुप्तशब्दः
|
||||
Name[si]=වැරදි මුරපදය
|
||||
Name[sk]=Neplatné heslo
|
||||
Name[sl]=Neveljavno geslo
|
||||
@@ -537,13 +550,11 @@ Name[tr]=Geçersiz Parola
|
||||
Name[ug]=ئىناۋەتسىز ئىم
|
||||
Name[uk]=Неправильний пароль
|
||||
Name[wa]=Sicret nén valåbe
|
||||
Name[x-test]=xxInvalid Passwordxx
|
||||
Name[zh_CN]=无效密码
|
||||
Name[zh_TW]=不正確的密碼
|
||||
Comment=Invalid password
|
||||
Comment[af]=Ongeldige wagwoord
|
||||
Comment[ar]=كلمة المرور غير صحيحة
|
||||
Comment[ast]=Contraseña incorreuta
|
||||
Comment[ar]=كلمة السر غير صحيحة
|
||||
Comment[bg]=Неправилна парола
|
||||
Comment[bn]=অবৈধ পাসওয়ার্ড
|
||||
Comment[br]=Tremenger siek
|
||||
@@ -563,16 +574,18 @@ Comment[eu]=Baliogabeko pasahitza
|
||||
Comment[fi]=Virheellinen salasana
|
||||
Comment[fr]=Mot de passe non valable
|
||||
Comment[ga]=Focal faire neamhbhailí
|
||||
Comment[gl]=Este contrasinal non é válido
|
||||
Comment[gl]=Este contrasinal é incorrecto
|
||||
Comment[he]=הסיסמה שגויה
|
||||
Comment[hi]=अवैध पासवर्ड
|
||||
Comment[hne]=अवैध पासवर्ड
|
||||
Comment[hr]=Nevažeća šifra
|
||||
Comment[hu]=Érvénytelen jelszó
|
||||
Comment[ia]=Contrasigno invalide
|
||||
Comment[id]=Sandi tidak absah
|
||||
Comment[is]=Lykilorð ógilt
|
||||
Comment[it]=Password non valida
|
||||
Comment[ja]=無効なパスワード
|
||||
Comment[ka]=არასწორი პაროლი
|
||||
Comment[kk]=Паролі дұрыс емес
|
||||
Comment[km]=ពាក្យសម្ងាត់មិនត្រឹមត្រូវ
|
||||
Comment[ko]=잘못된 암호
|
||||
@@ -589,11 +602,12 @@ Comment[nl]=Ongeldig wachtwoord
|
||||
Comment[nn]=Passordet var ugyldig
|
||||
Comment[oc]=Mot de pas invalid
|
||||
Comment[pa]=ਗਲਤ ਪਾਸਵਰਡ
|
||||
Comment[pl]=Błędne hasło
|
||||
Comment[pl]=Nieprawidłowe hasło
|
||||
Comment[pt]=A senha é inválida
|
||||
Comment[pt_BR]=Senha inválida
|
||||
Comment[ro]=Parolă nevalidă
|
||||
Comment[ru]=Неверный пароль
|
||||
Comment[sa]=अमान्यगुप्तशब्दः
|
||||
Comment[si]=වැරදි මුරපදය
|
||||
Comment[sk]=Neplatné heslo
|
||||
Comment[sl]=Neveljavno geslo
|
||||
@@ -613,7 +627,6 @@ Comment[uz]=Maxfiy soʻz haqiqiy emas
|
||||
Comment[uz@cyrillic]=Махфий сўз ҳақиқий эмас
|
||||
Comment[wa]=Sicret nén valide
|
||||
Comment[xh]=Igama lokugqitha elingasebenziyo
|
||||
Comment[x-test]=xxInvalid passwordxx
|
||||
Comment[zh_CN]=无效密码
|
||||
Comment[zh_HK]=無效的密碼
|
||||
Comment[zh_TW]=不正確的密碼
|
||||
@@ -621,12 +634,11 @@ Action=Popup
|
||||
|
||||
[Event/InvalidPasswordInvitations]
|
||||
Name=Invalid Password Invitations
|
||||
Name[ar]=كلمة المرور الدعوات غير صحيحة
|
||||
Name[ast]=Contraseñas d'invitaciones incorreutes
|
||||
Name[ar]=كلمة السر الدعوات غير صحيحة
|
||||
Name[bg]=Неправилна парола за покана
|
||||
Name[bs]=Neispravna šifra pozivnice
|
||||
Name[ca]=Contrasenya de les invitacions no vàlides
|
||||
Name[ca@valencia]=Contrasenya de les invitacions no vàlides
|
||||
Name[ca]=Contrasenya no vàlida de les invitacions
|
||||
Name[ca@valencia]=Contrasenya no vàlida de les invitacions
|
||||
Name[cs]=Neplatné hesla výzev
|
||||
Name[da]=Ugyldige adgangskodeinvitationer
|
||||
Name[de]=Ungültiges Einladungs-Passwort
|
||||
@@ -639,15 +651,18 @@ Name[eu]=Gonbitearen pasahitza baliogabea
|
||||
Name[fi]=Virheellinen salasana kutsuun
|
||||
Name[fr]=Invitations de mots de passe non valables
|
||||
Name[ga]=Cuirí Neamhbhailí Focal Faire
|
||||
Name[gl]=O contrasinal de convidado non válido
|
||||
Name[gl]=O contrasinal de convidado incorrecto
|
||||
Name[he]=סיסמה שגויה להזמנות
|
||||
Name[hi]=अवैध पासवर्ड निमंत्रण
|
||||
Name[hne]=अवैध पासवर्ड निमंत्रन
|
||||
Name[hr]=Pozivnice s nevažećim zaporkama
|
||||
Name[hu]=Érvénytelen jelszavas meghívó
|
||||
Name[ia]=Invitationes de contrasigno invalide
|
||||
Name[id]=Undangan Sandi Tidak Absah
|
||||
Name[is]=Ógild lykilorðsboð
|
||||
Name[it]=Password di invito non valida
|
||||
Name[ja]=招待に対する無効なパスワード
|
||||
Name[ka]=არასწორი პაროლის მოსაწვევები
|
||||
Name[kk]=Жарамсыз паролімен шақыру
|
||||
Name[km]=ការអញ្ជើញពាក្យសម្ងាត់មិនត្រឹមត្រូវ
|
||||
Name[ko]=잘못된 암호 초대장
|
||||
@@ -665,6 +680,7 @@ Name[pt]=Convites de Senha Inválidos
|
||||
Name[pt_BR]=Avisos de senha inválida
|
||||
Name[ro]=Parolă nevalidă Invitații
|
||||
Name[ru]=Неверный пароль приглашения
|
||||
Name[sa]=अमान्यगुप्तशब्दनिमन्त्रणानि
|
||||
Name[si]=වැරදි මුරපද ආරාධනාවක්
|
||||
Name[sk]=Neplatné heslo pozvánky
|
||||
Name[sl]=Povabila z neveljavnimi gesli
|
||||
@@ -677,13 +693,11 @@ Name[th]=รหัสผ่านของการเชื้อเชิญ
|
||||
Name[tr]=Geçersiz Parola Daveti
|
||||
Name[ug]=ئىناۋەتسىز ئىم تەكلىپلىرى
|
||||
Name[uk]=Запрошення з некоректними паролями
|
||||
Name[x-test]=xxInvalid Password Invitationsxx
|
||||
Name[zh_CN]=无效密码邀请
|
||||
Name[zh_TW]=不合法的密碼邀請
|
||||
Name[zh_TW]=無效的密碼邀請
|
||||
Comment=The invited party sent an invalid password. Connection refused.
|
||||
Comment[af]=Die uitgenooi party gestuur 'n ongeldige wagwoord. Verbinding geweier.
|
||||
Comment[ar]=المدعو أرسل كلمة مرور غير صحيحة. رفض الإتصال.
|
||||
Comment[ast]=L'invitáu unvió una contraseña incorreuta. Conexón refugada.
|
||||
Comment[ar]=المدعو أرسل كلمة سر غير صحيحة. رُفض الاتصال.
|
||||
Comment[bg]=Поканената страна изпрати неправилна парола. Връзката е отказана.
|
||||
Comment[bn]=আমন্ত্রিত দল একটি অবৈধ পাসওয়ার্ড পাঠাল। সংযোগ অস্বীকার করা হল।
|
||||
Comment[bs]=Pozvana strana je poslala pogrešnu šifru. Veza je odbijena.
|
||||
@@ -702,20 +716,22 @@ Comment[eu]=Gonbidatutako parekoak baliogabeko pasahitza bidali du. Konexioa uka
|
||||
Comment[fi]=Kutsuttu taho lähetti virheellisen salasanan. Yhteys hylättiin.
|
||||
Comment[fr]=La partie invitée a envoyé un mot de passe non valable. Connexion refusée.
|
||||
Comment[ga]=Sheol an duine le cuireadh focal faire neamhbhailí. Diúltaíodh an ceangal.
|
||||
Comment[gl]=A parte convidada envioulle un contrasinal non válido. A conexión foi rexeitada.
|
||||
Comment[gl]=A parte convidada envioulle un contrasinal incorrecto. Rexeitouse a conexión.
|
||||
Comment[he]=הצד המוזמן שלח סיסמה שגויה. החיבור נדחה.
|
||||
Comment[hi]=निमंत्रित पार्टी ने अवैध पासवर्ड भेजा. कनेक्शन अस्वीकृत.
|
||||
Comment[hne]=निमंत्रित पार्टी हर अवैध पासवर्ड भेजिस. कनेक्सन अस्वीकृत.
|
||||
Comment[hr]=Stranka koju ste pozvali je poslala nevažeću šifru. Veza odbijena.
|
||||
Comment[hu]=A meghívott fél érvénytelen jelszót küldött. A csatlakozási kérés elutasítva.
|
||||
Comment[ia]=Le partita invitate inviava un contrasigno invalide. Connexion refusate.
|
||||
Comment[id]=Undangan mengirimkan sebuah sandi tidak absah. Koneksi ditampik.
|
||||
Comment[is]=Boðinn aðili sendi ógilt lykilorð. Tengingu hafnað
|
||||
Comment[it]=La parte invitata ha inviato una password non valida. Connessione rifiutata.
|
||||
Comment[ja]=招待された人が無効なパスワードを送ってきました。接続を拒否しました。
|
||||
Comment[ka]=მოწვეული მხრის გამოგზავნილი პაროლი არასწორია. კავშირი უარყოფილია.
|
||||
Comment[kk]=Шқырылған жақ дұрыс емес парольді жіберді. Қосылымдан бас тартылды..
|
||||
Comment[km]=ភាគីដែលបានអញ្ជើញ បានផ្ញើពាក្យសម្ងាត់មិនត្រឹមត្រូវ ។ ការតភ្ជាប់ត្រូវបានបដិសេធ ។
|
||||
Comment[ko]=초대한 사람이 잘못된 암호를 보냈습니다. 연결이 잘못되었습니다.
|
||||
Comment[lt]=Pakviestoji pusė atsiuntė neteisingą slaptažodį. Ryšys nutrauktas.
|
||||
Comment[lt]=Pakviestoji pusė atsiuntė neteisingą slaptažodį. Ryšys atmestas.
|
||||
Comment[lv]=Ielūgtā persona nosūtīja nepareizu paroli. Savienojums noraidīts.
|
||||
Comment[mk]=Поканетата страна испрати невалидна лозинка. Поврзувањето е одбиено.
|
||||
Comment[ml]=ക്ഷണിച്ച പാര്ട്ടി അസാധുവായ അടയാളവാക്കാണ് അയച്ചത്. ബന്ധം നിഷേധിച്ചു.
|
||||
@@ -729,6 +745,7 @@ Comment[pt]=O utilizador convidado enviou uma senha inválida. A ligação foi r
|
||||
Comment[pt_BR]=A parte "convidada" enviou uma senha inválida. Conexão recusada.
|
||||
Comment[ro]=Partea care invită a trimis o parolă nevalidă. Conexiune refuzată.
|
||||
Comment[ru]=Приглашённый пользователь ввёл неправильный пароль. Соединение отклонено.
|
||||
Comment[sa]=आमन्त्रितः पक्षः अमान्यगुप्तशब्दं प्रेषितवान् । संयोजनं नकारितम्।
|
||||
Comment[si]=ආරාධිත පාර්ශවය වැරදි මුරපදයක් එවන ලද බැවින් සබඳතාව ප්රතික්ෂේප විය.
|
||||
Comment[sk]=Pozvaná strana poslala neplatné heslo. Pripojenie bolo odmietnuté.
|
||||
Comment[sl]=Povabljena stranka je poslala neveljavno geslo. Povezava zavrnjena.
|
||||
@@ -744,7 +761,6 @@ Comment[tr]=Davet edilenden gönderilmiş geçersiz parola. Bağlantı reddedild
|
||||
Comment[ug]=تەكلىپ قىلغۇچى ئەۋەتكەن ئىم ئىناۋەتسىز. باغلىنىش رەت قىلىندى.
|
||||
Comment[uk]=Запрошений учасник надіслав некоректний пароль. У з’єднанні відмовлено.
|
||||
Comment[xh]=Umhlangano omenyiweyo uthumele igama lokugqitha elisebenzayo. Uxhulumano lwa liwe.
|
||||
Comment[x-test]=xxThe invited party sent an invalid password. Connection refused.xx
|
||||
Comment[zh_CN]=受邀请方发送的密码不对。连接被拒绝。
|
||||
Comment[zh_HK]=被邀請的一方送出無效的密碼。已拒絕連線。
|
||||
Comment[zh_TW]=邀請的人送出了不合法的密碼邀請。連線已拒絕。
|
||||
@@ -753,11 +769,10 @@ Action=Popup
|
||||
[Event/NewConnectionOnHold]
|
||||
Name=New Connection on Hold
|
||||
Name[ar]=اتصال جديد على التوقف
|
||||
Name[ast]=Conexón nueva a la espera
|
||||
Name[bg]=Изчакване на новата връзка
|
||||
Name[bs]=Nova veza je na čekanju
|
||||
Name[ca]=Nova connexió en espera
|
||||
Name[ca@valencia]=Nova connexió en espera
|
||||
Name[ca]=Connexió nova en espera
|
||||
Name[ca@valencia]=Connexió nova en espera
|
||||
Name[cs]=Nové spojení pozdrženo
|
||||
Name[da]=Ny forbindelse sat til at vente
|
||||
Name[de]=Neue Verbindung wartet
|
||||
@@ -771,14 +786,17 @@ Name[fi]=Uusi yhteys odottaa
|
||||
Name[fr]=Nouvelle connexion en attente
|
||||
Name[ga]=Ceangal Nua Ag Fanacht
|
||||
Name[gl]=Nova conexión en espera
|
||||
Name[he]=חיבור חדש בהמתנה
|
||||
Name[hi]=नया कनेक्शन होल्ड पर रखा
|
||||
Name[hne]=नवा कनेक्सन होल्ड मं रखा
|
||||
Name[hr]=Nova veza na čekanju
|
||||
Name[hu]=Új kapcsolat tartva
|
||||
Name[ia]=Nove connexion in pausa
|
||||
Name[id]=Koneksi Baru sedang Tertahan
|
||||
Name[is]=Ný tenging á bið
|
||||
Name[it]=Nuova connessione in attesa
|
||||
Name[ja]=保留中の新しい接続
|
||||
Name[ka]=ახალი შეერთება შეჩერებულია
|
||||
Name[kk]=Жаңа қосылым күтілуде
|
||||
Name[km]=ការតភ្ជាប់ថ្មី កំពុងស្ថិតនៅក្នុងការរង់ចាំ
|
||||
Name[ko]=새 연결 대기 중
|
||||
@@ -796,6 +814,7 @@ Name[pt]=Ligação Nova em Espera
|
||||
Name[pt_BR]=Nova conexão ativa
|
||||
Name[ro]=Conexiune nouă în așteptare
|
||||
Name[ru]=Новое соединение приостановлено
|
||||
Name[sa]=नूतनं संयोजनं स्थगितम् अस्ति
|
||||
Name[si]=නව සබඳතාවක් රඳවා ඇත
|
||||
Name[sk]=Nové pripojenie bolo pozdržané
|
||||
Name[sl]=Nova povezava na čakanju
|
||||
@@ -807,18 +826,16 @@ Name[sv]=Ny anslutning väntar
|
||||
Name[th]=การเชื่อมต่อใหม่ถูกพักรอไว้ก่อน
|
||||
Name[tr]=Yeni Açık Bağlantı
|
||||
Name[uk]=Очікування на нове з’єднання
|
||||
Name[x-test]=xxNew Connection on Holdxx
|
||||
Name[zh_CN]=新连接已搁置
|
||||
Name[zh_TW]=新連線等待處理
|
||||
Comment=Connection requested, user must accept
|
||||
Comment[af]=Verbinding versoekte, gebruiker moet aanvaar
|
||||
Comment[ar]=الاتصال طلب، يجب موافقة المستخدم
|
||||
Comment[ast]=Conexón solicitada, l'usuario tien d'aceutala
|
||||
Comment[bg]=Поискана е връзка, следва потребителят да приеме
|
||||
Comment[bn]=সংযোগ অনুরোধ করা হল, ব্যবহারকারীকে অবশ্যই স্বীকার করতে হবে
|
||||
Comment[bs]=Veza je zahtijevana, korinik mora da je prihvati
|
||||
Comment[ca]=Connexió sol·licitada, l'usuari ha d'acceptar-la
|
||||
Comment[ca@valencia]=Connexió sol·licitada, l'usuari ha d'acceptar-la
|
||||
Comment[ca]=Connexió sol·licitada, l'usuari l'ha d'acceptar
|
||||
Comment[ca@valencia]=Connexió sol·licitada, l'usuari l'ha d'acceptar
|
||||
Comment[cs]=Vyžadováno spojení, uživatel musí přijmout
|
||||
Comment[cy]=Cais wedi'i wneud am gysylltiad,rhaid i'r ddefnyddiwr ei dderbyn
|
||||
Comment[da]=Forbindelse forespurgt, bruger skal acceptere
|
||||
@@ -833,19 +850,21 @@ Comment[fi]=Pyydettiin yhteyttä, käyttäjän tulee hyväksyä
|
||||
Comment[fr]=Connexion demandée. L'utilisateur doit accepter
|
||||
Comment[ga]=Ceangal iarrtha; ní mór don úsáideoir glacadh leis
|
||||
Comment[gl]=Pediuse a conexión; o usuario debe aceptar
|
||||
Comment[he]=נתבקש חיבור, על המשתמש לקבלו
|
||||
Comment[he]=התבקש חיבור, על המשתמש לאשרו
|
||||
Comment[hi]=कनेक्शन निवेदित. उपयोक्ता को स्वीकार होना चाहिए
|
||||
Comment[hne]=कनेक्सन निवेदित. कमइया ल स्वीकार होना चाही
|
||||
Comment[hr]=Veza je zatražena, korisnik mora prihvatiti
|
||||
Comment[hu]=Csatlakozási kérés, a felhasználónak el kell fogadnia
|
||||
Comment[ia]=Connexion requirite, usator debe dar acceptation
|
||||
Comment[id]=Koneksi diminta, pengguna harus menyetujui
|
||||
Comment[is]=Beiðni um tengingu, notandi verður að samþykkja
|
||||
Comment[it]=Connessione richiesta, l'utente deve accettare
|
||||
Comment[ja]=接続が要求されています。ユーザが許可しなければなりません。
|
||||
Comment[ka]=მიერთება მოთხოვნილია. მომხმარებელი მას უნდა დაეთანხმოს
|
||||
Comment[kk]=Қосылым сұралды, пайдаланушы жауап беруге тиіс
|
||||
Comment[km]=បានស្នើការតភ្ជាប់ អ្នកប្រើត្រូវតែទទួលយក
|
||||
Comment[ko]=연결 요청됨, 사용자가 수락해야 함
|
||||
Comment[lt]=Kvietimas ryšiui išsiųstas, naudotojas turi priimti kvietimą
|
||||
Comment[lt]=Kvietimas ryšiui išsiųstas, naudotojas privalo priimti kvietimą
|
||||
Comment[lv]=Ir pieprasīts jauns savienojums, kurš lietotājam ir jāapstiprina
|
||||
Comment[mk]=Побарано е поврзување, корисникот мора да прифати
|
||||
Comment[ml]=ബന്ധം ആവശ്യപ്പെട്ടിട്ടുണ്ട്, ഉപയോക്താവ് സ്വീകരിക്കണം
|
||||
@@ -860,6 +879,7 @@ Comment[pt]=Foi pedida uma ligação que o utilizador deverá aceitar
|
||||
Comment[pt_BR]=Conexão requisitada; o usuário deve aceitar
|
||||
Comment[ro]=Conexiune cerută, utilizatorul trebuie să accepte
|
||||
Comment[ru]=Запрос на соединение, требуется подтверждение пользователя
|
||||
Comment[sa]=संयोजनं अनुरोधितं, उपयोक्त्रेण अवश्यमेव स्वीकारणीयम्
|
||||
Comment[si]=සබඳතාව ඉල්ලා ඇත, පරිශීලක තහවුරු කල යුතුයි
|
||||
Comment[sk]=Vyžiadané pripojenie, užívateľ ho musí akceptovať
|
||||
Comment[sl]=Povezava zahtevana, uporabnik mora sprejeti
|
||||
@@ -875,7 +895,6 @@ Comment[tr]=Bağlantı isteği, kullanıcı kabul etmeli
|
||||
Comment[ug]=باغلىنىش ئىلتىماس قىلىندى، ئىشلەتكۈچى قوشۇلۇشى كېرەك
|
||||
Comment[uk]=Отримано запит на з’єднання, користувач має його прийняти
|
||||
Comment[xh]=Uxhulumaniso luceliwe, umsebenzisi kufanele amkele
|
||||
Comment[x-test]=xxConnection requested, user must acceptxx
|
||||
Comment[zh_CN]=连接已请求,用户必须接受
|
||||
Comment[zh_HK]=已請求連線,用戶必須接受
|
||||
Comment[zh_TW]=連線已要求,必須等使用者接受
|
||||
@@ -883,12 +902,11 @@ Action=Popup
|
||||
|
||||
[Event/NewConnectionAutoAccepted]
|
||||
Name=New Connection Auto Accepted
|
||||
Name[ar]=اتصال جديد مقبول تلقائيا
|
||||
Name[ast]=Conexón nueva aceutada automáticamente
|
||||
Name[ar]=اتصال جديد مقبول آليّا
|
||||
Name[bg]=Автоматично приемане на новата връзка
|
||||
Name[bs]=Nova veza je automatski prihvaćena
|
||||
Name[ca]=Nova connexió acceptada automàticament
|
||||
Name[ca@valencia]=Nova connexió acceptada automàticament
|
||||
Name[ca]=Connexió nova acceptada automàticament
|
||||
Name[ca@valencia]=Connexió nova acceptada automàticament
|
||||
Name[cs]=Nové spojení automaticky přijato
|
||||
Name[da]=Ny forbindelse automatisk accepteret
|
||||
Name[de]=Neue Verbindung automatisch angenommen
|
||||
@@ -902,14 +920,17 @@ Name[fi]=Uusi yhteys hyväksyttiin automaattisesti
|
||||
Name[fr]=Nouvelle connexion acceptée automatiquement
|
||||
Name[ga]=Ceangal nua bunaithe go huathoibríoch
|
||||
Name[gl]=Nova conexión aceptada automaticamente
|
||||
Name[he]=חיבור חדש אושר אוטומטית
|
||||
Name[hi]=नय कनेक्शन स्वचालित स्वीकारा
|
||||
Name[hne]=नय कनेक्सन अपने अपन स्वीकारा
|
||||
Name[hr]=Nova veza automatski prihvaćena
|
||||
Name[hu]=Új kapcsolat automatikusan engedélyezve
|
||||
Name[ia]=Nove connexion con acceptation automatic
|
||||
Name[id]=Koneksi Baru Tersetujui Otomatis
|
||||
Name[is]=Ný tenging sjálfvirkt samþykkt
|
||||
Name[it]=Nuova connessione accettata automaticamente
|
||||
Name[ja]=新しい接続の自動受け入れ
|
||||
Name[ka]=ახალი მიერთება ავტომატურად მიღებულია
|
||||
Name[kk]=Жаңа қосылым автоқабылданды
|
||||
Name[km]=បានទទួលយកការតភ្ជាប់ថ្មីដោយស្វ័យប្រវត្តិ
|
||||
Name[ko]=새 연결 자동 수락
|
||||
@@ -926,6 +947,7 @@ Name[pt]=Nova Ligação Aceite Automaticamente
|
||||
Name[pt_BR]=Nova conexão com aceitação automática
|
||||
Name[ro]=Conexiune nouă acceptată automat
|
||||
Name[ru]=Новое соединение принимается автоматически
|
||||
Name[sa]=नवीनं संयोजनं स्वतः स्वीकृतम्
|
||||
Name[si]=නව සබඳතාව ස්වයංක්රීයව පිළිගැණිනි
|
||||
Name[sk]=Nové pripojenie bolo automaticky akceptované
|
||||
Name[sl]=Nova povezava samodejno sprejeta
|
||||
@@ -938,18 +960,16 @@ Name[th]=รับการเชื่อมต่อใหม่โดยอ
|
||||
Name[tr]=Yeni Bağlantı Otomatik olarak Kabul Edildi
|
||||
Name[ug]=يېڭى باغلىنىش ئۆزلۈكىدىن قوشۇلدى
|
||||
Name[uk]=Нове з’єднання автоматично прийнято
|
||||
Name[x-test]=xxNew Connection Auto Acceptedxx
|
||||
Name[zh_CN]=新连接自动接受
|
||||
Name[zh_TW]=新連線自動接受
|
||||
Comment=New connection automatically established
|
||||
Comment[af]=Nuwe verbinding automaties vasgestel
|
||||
Comment[ar]=اتصال جديد مفعل تلقائيا
|
||||
Comment[ast]=Conexón nueva afitada automáticamente
|
||||
Comment[ar]=اتصال جديد مفعل آليّا
|
||||
Comment[bg]=Новата връзка е автоматично приета
|
||||
Comment[bn]=নতুন সংযোগ স্বয়ংক্রীয়ভাবে স্থাপন করা হল
|
||||
Comment[bs]=Nova veza je automatski uspostavljena
|
||||
Comment[ca]=Nova connexió establerta automàticament
|
||||
Comment[ca@valencia]=Nova connexió establerta automàticament
|
||||
Comment[ca]=Connexió nova establerta automàticament
|
||||
Comment[ca@valencia]=Connexió nova establida automàticament
|
||||
Comment[cs]=Automaticky navázáno nové spojení
|
||||
Comment[cy]=Sefydlwyd cysylltiad newydd yn awtomatig
|
||||
Comment[da]=Ny forbindelse automatisk etableret
|
||||
@@ -964,15 +984,17 @@ Comment[fi]=Uusi yhteys muodostettiin automaattisesti
|
||||
Comment[fr]=Nouvelle connexion établie automatiquement
|
||||
Comment[ga]=Ceangal nua bunaithe go huathoibríoch
|
||||
Comment[gl]=Estabeleceuse automaticamente unha conexión nova
|
||||
Comment[he]=נוצר חיבור חדש באופן אוטומטי
|
||||
Comment[he]=חיבור חדש נוצר אוטומטית
|
||||
Comment[hi]=नया कनेक्शन स्वचलित स्थापित
|
||||
Comment[hne]=नवा कनेक्सन अपने अपन स्थापित
|
||||
Comment[hr]=Nova veza automatski prihvaćena
|
||||
Comment[hu]=Automatikusan létrejött egy új kapcsolat
|
||||
Comment[ia]=Nove connexion establite automaticamente
|
||||
Comment[id]=Koneksi baru secara otomatis terpancang
|
||||
Comment[is]=Nýjar tengingar sjálfkrafa samþykktar
|
||||
Comment[it]=Nuova connessione stabilita automaticamente
|
||||
Comment[ja]=新しい接続を自動的に確立しました
|
||||
Comment[ka]=ახალი მიერთება ავტომატურად დამყარებულია
|
||||
Comment[kk]=Жаңа қосылым автоматты түрде орнатылды
|
||||
Comment[km]=បានបង្កើតការតភ្ជាប់ថ្មីដោយស្វ័យប្រវត្តិ
|
||||
Comment[ko]=새 연결이 자동으로 성립됨
|
||||
@@ -991,6 +1013,7 @@ Comment[pt]=Foi estabelecida automaticamente uma nova ligação
|
||||
Comment[pt_BR]=Nova conexão estabelecida automaticamente
|
||||
Comment[ro]=Conexiune nouă stabilită automat
|
||||
Comment[ru]=Новое соединение устанавливается автоматически
|
||||
Comment[sa]=स्वयमेव नूतनं संयोजनं स्थापितं
|
||||
Comment[si]=නව සබඳතාව ස්වයංක්රීයව සැකසිනි
|
||||
Comment[sk]=Nové pripojenie bolo automaticky nadviazané
|
||||
Comment[sl]=Nova povezava samodejno vzpostavljena
|
||||
@@ -1006,7 +1029,6 @@ Comment[tr]=Yeni bağlantı otomatik olarak kuruldu
|
||||
Comment[ug]=يېڭى باغلىنىش ئۆزلۈكىدىن قۇرۇلدى
|
||||
Comment[uk]=Автоматично встановлено нове з’єднання
|
||||
Comment[xh]=Uxhulumaniso olutsha lufunyenwe ngokuzenzekelayo
|
||||
Comment[x-test]=xxNew connection automatically establishedxx
|
||||
Comment[zh_CN]=自动建立新连接
|
||||
Comment[zh_HK]=已自動建立新連線
|
||||
Comment[zh_TW]=新連線自動建立
|
||||
@@ -1015,7 +1037,6 @@ Action=Popup
|
||||
[Event/TooManyConnections]
|
||||
Name=Too Many Connections
|
||||
Name[ar]=اتصالات عديدة
|
||||
Name[ast]=Abondes conexones
|
||||
Name[bg]=Твърде много връзки
|
||||
Name[bs]=Previše veza
|
||||
Name[ca]=Massa connexions
|
||||
@@ -1033,14 +1054,17 @@ Name[fi]=Liikaa yhteyksiä
|
||||
Name[fr]=Trop de connexions
|
||||
Name[ga]=An Iomarca Ceangal
|
||||
Name[gl]=Demasiadas conexións
|
||||
Name[he]=יותר מדי חיבורים
|
||||
Name[hi]=बहुत सारे कनेक्शन
|
||||
Name[hne]=बहुत अकन कनेक्सन
|
||||
Name[hr]=Previše veza
|
||||
Name[hu]=Túl sok kapcsolat
|
||||
Name[ia]=Nimie connexiones
|
||||
Name[id]=Terlalu Banyak Koneksi
|
||||
Name[is]=Of margar tengingar
|
||||
Name[it]=Troppe connessioni
|
||||
Name[ja]=多すぎる接続
|
||||
Name[ka]=მეტისმეტად ბევრი მიერთება
|
||||
Name[kk]=Тым көп қосылым
|
||||
Name[km]=ការតភ្ជាប់ច្រើនពេក
|
||||
Name[ko]=너무 많은 연결
|
||||
@@ -1057,6 +1081,7 @@ Name[pt]=Demasiadas Ligações
|
||||
Name[pt_BR]=Conexões em excesso
|
||||
Name[ro]=Prea multe conexiuni
|
||||
Name[ru]=Слишком много соединений
|
||||
Name[sa]=अत्यधिकं संयोजनानि
|
||||
Name[si]=වඩා වැඩි සබඳතා ගණනක්
|
||||
Name[sk]=Príliš veľa pripojení
|
||||
Name[sl]=Preveč povezav
|
||||
@@ -1069,13 +1094,11 @@ Name[th]=มีการเชื่อมต่อมากเกินไป
|
||||
Name[tr]=Çok Fazla Bağlantı
|
||||
Name[ug]=باغلىنىش بەك كۆپ
|
||||
Name[uk]=Забагато з’єднань
|
||||
Name[x-test]=xxToo Many Connectionsxx
|
||||
Name[zh_CN]=连接过多
|
||||
Name[zh_TW]=太多連線
|
||||
Comment=Busy, connection refused
|
||||
Comment[af]=Besig, verbinding geweier
|
||||
Comment[ar]=مشغول، الإتصال رفض
|
||||
Comment[ast]=Ocupáu, conexón refugada
|
||||
Comment[ar]=مشغول، الاتصال رفض
|
||||
Comment[bg]=Заето. Връзката е отказана.
|
||||
Comment[bn]=ব্যস্ত, সংযোগ অস্বীকার করল
|
||||
Comment[br]=Dalc'het, kevreadenn disteuleret
|
||||
@@ -1095,20 +1118,22 @@ Comment[eu]=Lanpetuta, konexioa ukatu da
|
||||
Comment[fi]=Varattu, yhteys hylättiin
|
||||
Comment[fr]=Occupé. Connexion refusée
|
||||
Comment[ga]=Gnóthach; ceangal diúltaithe
|
||||
Comment[gl]=Ocupado; a conexión foi rexeitada
|
||||
Comment[gl]=Ocupado, rexeitouse a conexión.
|
||||
Comment[he]=תפוס, החיבור נדחה
|
||||
Comment[hi]=व्यस्त, कनेक्शन अस्वीकृत
|
||||
Comment[hne]=व्यस्त, कनेक्सन अस्वीकृत
|
||||
Comment[hr]=Zauzeto, veza odbijena
|
||||
Comment[hu]=A csatlakozási kérés elutasítva túlterhelés miatt
|
||||
Comment[ia]=Occupate, connexion refusate
|
||||
Comment[id]=Sibuk, koneksi ditampik
|
||||
Comment[is]=Uptekinn, tengingu hafnað
|
||||
Comment[it]=Occupato, connessione rifiutata
|
||||
Comment[ja]=ビジーです、接続を拒否しました
|
||||
Comment[ka]=დაკავებულია, დაკავშირება უარყოფილია
|
||||
Comment[kk]=Бос емес, қосылым болмады
|
||||
Comment[km]=រវល់ បដិសេធការតភ្ជាប់
|
||||
Comment[ko]=바쁨, 연결 거부됨
|
||||
Comment[lt]=Užimta, kvietimas ryšiui atmestas
|
||||
Comment[lt]=Užimta, ryšys atmestas
|
||||
Comment[lv]=Aizņemts, savienojums noraidīts
|
||||
Comment[mk]=Зафатено, поврзувањето е одбиено
|
||||
Comment[ml]=തിരക്കിലാണ്, ബന്ധം നിഷേധിച്ചു
|
||||
@@ -1123,6 +1148,7 @@ Comment[pt]=Ocupado, pelo a ligação foi recusada
|
||||
Comment[pt_BR]=Ocupado; conexão recusada
|
||||
Comment[ro]=Ocupat, conexiune refuzată
|
||||
Comment[ru]=Занят, соединение отклонено
|
||||
Comment[sa]=व्यस्तः, सम्पर्कः अङ्गीकृतः
|
||||
Comment[si]=කාර්යබහුලයි, සබඳතාව නොපිළිගැණිනි
|
||||
Comment[sk]=Zaneprázdnený, pripojenie bolo odmietnuté
|
||||
Comment[sl]=Zaposlen, povezava zavrnjena
|
||||
@@ -1140,7 +1166,6 @@ Comment[uk]=Зайнято, у з’єднанні відмовлено
|
||||
Comment[uz]=Band, aloqa rad etildi
|
||||
Comment[uz@cyrillic]=Банд, алоқа рад этилди
|
||||
Comment[xh]=Uxhulumaniso, olu xakekileyo lwaliwe
|
||||
Comment[x-test]=xxBusy, connection refusedxx
|
||||
Comment[zh_CN]=对方处于忙碌状态,连接被拒绝
|
||||
Comment[zh_HK]=忙碌,已拒絕連線
|
||||
Comment[zh_TW]=忙碌,連線被拒
|
||||
@@ -1149,7 +1174,6 @@ Action=Popup
|
||||
[Event/UnexpectedConnection]
|
||||
Name=Unexpected Connection
|
||||
Name[ar]=الاتصال غير متوقّع
|
||||
Name[ast]=Conexón inesperada
|
||||
Name[bg]=Неочаквана връзка
|
||||
Name[bs]=Neočekivana veza
|
||||
Name[ca]=Connexió inesperada
|
||||
@@ -1167,18 +1191,21 @@ Name[fi]=Odottamaton yhteys
|
||||
Name[fr]=Connexion inattendue
|
||||
Name[ga]=Ceangal Gan Choinne
|
||||
Name[gl]=Conexión non agardada
|
||||
Name[he]=חיבור בלתי צפוי
|
||||
Name[hi]=अप्रत्याशित कनेक्शन
|
||||
Name[hne]=अप्रत्यासित कनेक्सन
|
||||
Name[hr]=Neočekivana veza
|
||||
Name[hu]=Nem várt kapcsolat
|
||||
Name[ia]=Connexion impreviste
|
||||
Name[id]=Koneksi Tak Terduga
|
||||
Name[is]=Óvænt Tenging
|
||||
Name[it]=Connessione inattesa
|
||||
Name[ja]=予期しない接続
|
||||
Name[ka]=მოულოდნელი შეერთება
|
||||
Name[kk]=Күтпеген қосылым
|
||||
Name[km]=ការតភ្ជាប់ដែលមិនបានរំពឹងទុក
|
||||
Name[ko]=예상하지 않은 연결
|
||||
Name[lt]=Netikėtas kvietimas ryšiui
|
||||
Name[lt]=Netikėtas ryšys
|
||||
Name[lv]=Negaidīts savienojums
|
||||
Name[ml]=അപ്രതീക്ഷിതമായ ബന്ധം
|
||||
Name[nb]=Uventet tilkobling
|
||||
@@ -1191,6 +1218,7 @@ Name[pt]=Ligação Inesperada
|
||||
Name[pt_BR]=Conexão inesperada
|
||||
Name[ro]=Conexiune neașteptată
|
||||
Name[ru]=Неожиданное соединение
|
||||
Name[sa]=अप्रत्याशितसंयोजनम्
|
||||
Name[si]=බලාපොරොත්තු රහිත සබඳතාවක්
|
||||
Name[sk]=Neočakávané pripojenie
|
||||
Name[sl]=Nepričakovana povezava
|
||||
@@ -1204,18 +1232,16 @@ Name[th]=เกิดการเชื่อมต่อที่ไม่ค
|
||||
Name[tr]=Beklenmeyen Bağlantı
|
||||
Name[ug]=كۈتۈلمىگەن باغلىنىش
|
||||
Name[uk]=Неочікуване з’єднання
|
||||
Name[x-test]=xxUnexpected Connectionxx
|
||||
Name[zh_CN]=未预料的连接
|
||||
Name[zh_TW]=未知的連線
|
||||
Comment=Received unexpected connection, abort
|
||||
Comment[af]=Ontvang onverwagte verbinding, staak
|
||||
Comment[ar]=استقبال اتصال غير متوقع، إنهاء
|
||||
Comment[ast]=Recibióse conexón inesperada, albortando
|
||||
Comment[bg]=Получена е неочаквана връзка. Прекъсване.
|
||||
Comment[bn]=অপ্রত্যাশিত সংযোগ গ্রহণ করল, বাতিল করুন
|
||||
Comment[bs]=Primljena je neočekivana veza, prekini
|
||||
Comment[ca]=Rebuda una connexió inesperada, avortant
|
||||
Comment[ca@valencia]=Rebuda una connexió inesperada, avortant
|
||||
Comment[ca]=S'ha rebut una connexió inesperada, s'està interrompent
|
||||
Comment[ca@valencia]=S'ha rebut una connexió inesperada, s'està interrompent
|
||||
Comment[cs]=Obdrženo neočekávané spojení, přerušeno
|
||||
Comment[cy]=Derbynwyd cysylltiad annisgwyl,terfynu
|
||||
Comment[da]=Modtog uventet forbindelse, afbrød
|
||||
@@ -1229,20 +1255,22 @@ Comment[eu]=Ustekabeko konexioa jaso da, abortatzen
|
||||
Comment[fi]=Vastaanotettiin odottamaton yhteys, lopeta
|
||||
Comment[fr]=Connexion inattendue reçue. Annulation
|
||||
Comment[ga]=Fuarthas ceangal gan choinne, á thobscor
|
||||
Comment[gl]=Recibiuse unha conexión non agardada; cancélase
|
||||
Comment[he]=נתקבל חיבור בלתי צפוי, בוטל
|
||||
Comment[gl]=Recibiuse unha conexión non agardada; interrómpese
|
||||
Comment[he]=התקבל חיבור בלתי צפוי, בוטל
|
||||
Comment[hi]=अप्रत्याशित कनेक्शन प्राप्त. छोड़ा
|
||||
Comment[hne]=अप्रत्यासित कनेक्सन प्राप्त. छोड़ा
|
||||
Comment[hr]=Primio sam neočekivanu vezu, prekid
|
||||
Comment[hu]=Nem várt csatlakozási kérés érkezett, megszakítás
|
||||
Comment[ia]=On recipeva connexion impreviste, aborta
|
||||
Comment[id]=Diperoleh koneksi tak terduga, gugurkan
|
||||
Comment[is]=Tók á móti óvæntri tengingu, hætti
|
||||
Comment[it]=Ricevuta connessione inattesa, terminata
|
||||
Comment[ja]=予期しない接続を受信しました。廃棄します。
|
||||
Comment[ka]=მიღებულია მოულოდნელი მიერთება. გაუქმდება
|
||||
Comment[kk]=Күтпеген қосылым ұсынысы, доғарылды
|
||||
Comment[km]=បានទទួលយកការតភ្ជាប់ដែលមិនបានរំពឹងទុក បោះបង់
|
||||
Comment[ko]=예상하지 않은 연결을 받았습니다, 중지합니다
|
||||
Comment[lt]=Sulaukta netikėto kvietimo ryšiui, nutraukiama
|
||||
Comment[lt]=Sulaukta netikėto ryšio, nutraukiama
|
||||
Comment[lv]=Saņemts negaidīts savienojums, pārtraukts
|
||||
Comment[mk]=Примено е неочекувано поврзување, се прекинува
|
||||
Comment[ml]=അപ്രതീക്ഷിതമായ ബന്ധം ലഭിച്ചു, നിരസിക്കുക
|
||||
@@ -1253,9 +1281,10 @@ Comment[nl]=Ontving een onverwachte verbinding, afgebroken
|
||||
Comment[nn]=Fekk ei uventa tilkopling, så avbryt no
|
||||
Comment[pl]=Otrzymano niespodziewane połączenie. Przerwane.
|
||||
Comment[pt]=Foi recebida uma ligação inesperada, pelo que foi interrompida
|
||||
Comment[pt_BR]=Conexão recebida inesperadamente; abortar
|
||||
Comment[pt_BR]=Conexão recebida inesperadamente; cancelar
|
||||
Comment[ro]=Conexiune neașteptată recepționată, abandonare
|
||||
Comment[ru]=Получено неожиданное соединение. Отключение
|
||||
Comment[sa]=अप्रत्याशितसंयोजनं प्राप्तवान्, गर्भपातं करोतु
|
||||
Comment[si]=බලාපොරොත්තු රහිත සබඳතාවක් ලැබිනි, පිටවෙමින්
|
||||
Comment[sk]=Prijaté neočakávané pripojenie, prerušené
|
||||
Comment[sl]=Prejeta nepričakovana povezava, prekinjeno
|
||||
@@ -1271,7 +1300,6 @@ Comment[tr]=Beklenmeyen bir bağlantı alındı, vazgeçiliyor
|
||||
Comment[ug]=ئويلاشمىغان باغلىنىشنى تاپشۇرۇۋالدى، توختات
|
||||
Comment[uk]=Отримано з’єднання, яке не очікувалось, припиняється
|
||||
Comment[xh]=Ufumene uxhulumaniso olungalindelekanga, lahla
|
||||
Comment[x-test]=xxReceived unexpected connection, abortxx
|
||||
Comment[zh_CN]=收到意外连接,已中止
|
||||
Comment[zh_HK]=接收到非預期的連線,中止
|
||||
Comment[zh_TW]=已接收到未知的連線,中止。
|
||||
|
||||
6
krfb/krfb.qrc
Normal file
@@ -0,0 +1,6 @@
|
||||
<!DOCTYPE RCC>
|
||||
<RCC version="1.0">
|
||||
<qresource prefix="/kxmlgui5/krfb">
|
||||
<file>krfbui.rc</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -1,7 +0,0 @@
|
||||
[org.freedesktop.Telepathy.Client]
|
||||
Interfaces=org.freedesktop.Telepathy.Client.Handler;
|
||||
|
||||
[org.freedesktop.Telepathy.Client.Handler.HandlerChannelFilter 0]
|
||||
org.freedesktop.Telepathy.Channel.ChannelType s=org.freedesktop.Telepathy.Channel.Type.StreamTube
|
||||
org.freedesktop.Telepathy.Channel.Type.StreamTube.Service s=rfb
|
||||
org.freedesktop.Telepathy.Channel.Requested b=true
|
||||
7
krfb/krfbui.rc
Normal file
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE gui SYSTEM "kpartgui.dtd">
|
||||
<gui name="krfb" version="0">
|
||||
|
||||
<MenuBar>
|
||||
</MenuBar>
|
||||
|
||||
</gui>
|
||||
189
krfb/main-virtualmonitor.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
/* This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "krfb_version.h"
|
||||
#include "rfbserver.h"
|
||||
#include "rfbservermanager.h"
|
||||
#include "sockethelpers.h"
|
||||
#include <KAboutData>
|
||||
#include <KCrash>
|
||||
#include <KLocalizedString>
|
||||
#include <KNotification>
|
||||
#include <KWindowSystem>
|
||||
#include <QApplication>
|
||||
#include <QCommandLineOption>
|
||||
#include <QCommandLineParser>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
#include <signal.h>
|
||||
|
||||
class VirtualMonitorRfbClient : public RfbClient
|
||||
{
|
||||
public:
|
||||
explicit VirtualMonitorRfbClient(rfbClientPtr client, QObject *parent = nullptr)
|
||||
: RfbClient(client, parent)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class PendingVirtualMonitorRfbClient : public PendingRfbClient
|
||||
{
|
||||
public:
|
||||
explicit PendingVirtualMonitorRfbClient(rfbClientPtr client, QObject *parent = nullptr)
|
||||
: PendingRfbClient(client, parent)
|
||||
{
|
||||
}
|
||||
~PendingVirtualMonitorRfbClient() override
|
||||
{
|
||||
}
|
||||
|
||||
static QByteArray password;
|
||||
|
||||
protected:
|
||||
void processNewClient() override
|
||||
{
|
||||
qDebug() << "new client!";
|
||||
const QString host = peerAddress(m_rfbClient->sock) + QLatin1Char(':') + QString::number(peerPort(m_rfbClient->sock));
|
||||
|
||||
KNotification::event(QStringLiteral("NewConnectionAutoAccepted"),
|
||||
i18n("Creating a Virtual Monitor from %1", host));
|
||||
}
|
||||
bool checkPassword(const QByteArray &encryptedPassword) override
|
||||
{
|
||||
bool b = vncAuthCheckPassword(password, encryptedPassword);
|
||||
if (b) {
|
||||
QTimer::singleShot(0, this, [this] {
|
||||
accept(new VirtualMonitorRfbClient(m_rfbClient, parent()));
|
||||
});
|
||||
}
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
QByteArray PendingVirtualMonitorRfbClient::password;
|
||||
|
||||
class VirtualMonitorRfbServer : public RfbServer
|
||||
{
|
||||
public:
|
||||
PendingRfbClient *newClient(rfbClientPtr client) override
|
||||
{
|
||||
qDebug() << "new client request";
|
||||
return new PendingVirtualMonitorRfbClient(client, this);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
KLocalizedString::setApplicationDomain("krfb");
|
||||
|
||||
KAboutData aboutData(QStringLiteral("krfb-virtualmonitor"),
|
||||
i18n("Remote Virtual Monitor"),
|
||||
QStringLiteral(KRFB_VERSION_STRING),
|
||||
i18n("Offer a Virtual Monitor that can be accessed remotely"),
|
||||
KAboutLicense::GPL,
|
||||
i18n("(c) 2009-2010, Collabora Ltd.\n"
|
||||
"(c) 2007, Alessandro Praduroux\n"
|
||||
"(c) 2001-2003, Tim Jansen\n"
|
||||
"(c) 2001, Johannes E. Schindelin\n"
|
||||
"(c) 2000-2001, Const Kaplinsky\n"
|
||||
"(c) 2000, Tridia Corporation\n"
|
||||
"(c) 1999, AT&T Laboratories Boston\n"));
|
||||
aboutData.addAuthor(QStringLiteral("Aleix Pol i Gonzalez"), i18n("Virtual Monitor implementation"), QStringLiteral("aleixpol@kde.org"));
|
||||
aboutData.addAuthor(i18n("George Kiagiadakis"), QString(), QStringLiteral("george.kiagiadakis@collabora.co.uk"));
|
||||
aboutData.addAuthor(i18n("Alessandro Praduroux"), i18n("KDE4 porting"), QStringLiteral("pradu@pradu.it"));
|
||||
aboutData.addAuthor(i18n("Tim Jansen"), i18n("Original author"), QStringLiteral("tim@tjansen.de"));
|
||||
aboutData.addCredit(i18n("Johannes E. Schindelin"),
|
||||
i18n("libvncserver"));
|
||||
aboutData.addCredit(i18n("Const Kaplinsky"),
|
||||
i18n("TightVNC encoder"));
|
||||
aboutData.addCredit(i18n("Tridia Corporation"),
|
||||
i18n("ZLib encoder"));
|
||||
aboutData.addCredit(i18n("AT&T Laboratories Boston"),
|
||||
i18n("original VNC encoders and "
|
||||
"protocol design"));
|
||||
KAboutData::setApplicationData(aboutData);
|
||||
|
||||
KCrash::initialize();
|
||||
|
||||
QCommandLineParser parser;
|
||||
aboutData.setupCommandLine(&parser);
|
||||
|
||||
const QCommandLineOption resolutionOption(
|
||||
{QStringLiteral("resolution")},
|
||||
i18n("Logical resolution of the new monitor"),
|
||||
i18n("resolution"),
|
||||
QStringLiteral("1920x1080"));
|
||||
parser.addOption(resolutionOption);
|
||||
|
||||
const QCommandLineOption nameOption(
|
||||
{QStringLiteral("name")},
|
||||
i18n("Name of the monitor"),
|
||||
i18n("name"),
|
||||
QStringLiteral("Monitor"));
|
||||
parser.addOption(nameOption);
|
||||
|
||||
const QCommandLineOption passwordOption(
|
||||
{QStringLiteral("password")},
|
||||
i18n("Password for the client to connect to it"),
|
||||
i18n("password"));
|
||||
parser.addOption(passwordOption);
|
||||
|
||||
const QCommandLineOption scaleOption(
|
||||
{QStringLiteral("scale")},
|
||||
i18n("The device-pixel-ratio of the device, the scaling factor"),
|
||||
i18n("dpr"),
|
||||
QStringLiteral("1"));
|
||||
parser.addOption(scaleOption);
|
||||
|
||||
const QCommandLineOption portOption(
|
||||
{QStringLiteral("port")},
|
||||
i18n("The port we will be listening to"),
|
||||
i18n("number"),
|
||||
QStringLiteral("5900"));
|
||||
parser.addOption(portOption);
|
||||
|
||||
parser.process(app);
|
||||
aboutData.processCommandLine(&parser);
|
||||
|
||||
app.setQuitOnLastWindowClosed(false);
|
||||
|
||||
if (!KWindowSystem::isPlatformWayland()) {
|
||||
qCritical() << "Virtual Monitors are only supported on Wayland.";
|
||||
return 1;
|
||||
}
|
||||
const QString res = parser.value(resolutionOption);
|
||||
const auto resSplit = res.split(QLatin1Char('x'));
|
||||
const QSize size = {resSplit[0].toInt(), resSplit[1].toInt()};
|
||||
if (resSplit.size() != 2 || size.isEmpty()) {
|
||||
qCritical() << "The resolution should be formatted as WIDTHxHEIGHT (e.g. --resolution 1920x1080).";
|
||||
return 2;
|
||||
}
|
||||
|
||||
RfbServerManager::s_pluginArgs = {
|
||||
{QStringLiteral("name"), parser.value(nameOption)},
|
||||
{QStringLiteral("resolution"), size},
|
||||
{QStringLiteral("scale"), parser.value(scaleOption).toDouble()},
|
||||
};
|
||||
|
||||
VirtualMonitorRfbServer server;
|
||||
server.setPasswordRequired(true);
|
||||
server.setPasswordSet(!parser.value(passwordOption).isEmpty());
|
||||
server.setListeningPort(parser.value(portOption).toInt());
|
||||
PendingVirtualMonitorRfbClient::password = parser.value(passwordOption).toUtf8();
|
||||
|
||||
sigset_t sigs;
|
||||
sigemptyset(&sigs);
|
||||
sigaddset(&sigs, SIGPIPE);
|
||||
sigprocmask(SIG_BLOCK, &sigs, nullptr);
|
||||
if (!server.start()) {
|
||||
qCritical() << "Could not start the VNC server.";
|
||||
return 3;
|
||||
}
|
||||
|
||||
return app.exec();
|
||||
}
|
||||