Compare commits
698 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
790269db95 | ||
![]() |
cb82bd8afa | ||
![]() |
b1e06ed110 | ||
![]() |
fabe66e65f | ||
![]() |
4a965a37d1 | ||
![]() |
302ff7b95a | ||
![]() |
e2e241340c | ||
![]() |
461aea47dd | ||
![]() |
d87093fe29 | ||
![]() |
0cde7879d6 | ||
![]() |
89ffcee7ca | ||
![]() |
1250afef7b | ||
![]() |
3a577edaa7 | ||
![]() |
48dfde2073 | ||
![]() |
4a41d415f8 | ||
![]() |
1fb7ca398d | ||
![]() |
2b79935fd8 | ||
![]() |
e3c915350e | ||
![]() |
2e06a6765c | ||
![]() |
b63291069d | ||
![]() |
f10cb02cbf | ||
![]() |
276df8f18d | ||
![]() |
d61dde12cb | ||
![]() |
c8cc4344f2 | ||
![]() |
ae292c856b | ||
![]() |
35dd1e644d | ||
![]() |
be85ead2f8 | ||
![]() |
5c40345128 | ||
![]() |
43b3573c51 | ||
![]() |
ac6ec168da | ||
![]() |
dbb7b9e85b | ||
![]() |
1de740955f | ||
![]() |
21f123c69f | ||
![]() |
d6624b0a75 | ||
![]() |
9c465a2d5a | ||
![]() |
e53456d87c | ||
![]() |
5716fc4b90 | ||
![]() |
e926ebafdb | ||
![]() |
7125b801f2 | ||
![]() |
d20dae3553 | ||
![]() |
73a47cec2a | ||
![]() |
514d3b4bde | ||
![]() |
6910ab5389 | ||
![]() |
4052b0f048 | ||
![]() |
493c0f71d2 | ||
![]() |
ab40dfdd51 | ||
![]() |
52678c39e6 | ||
![]() |
a676249c0c | ||
![]() |
2833c702c6 | ||
![]() |
611f6741c2 | ||
![]() |
df2587a61c | ||
![]() |
30e7044746 | ||
![]() |
458953268b | ||
![]() |
1c227baf81 | ||
![]() |
892699da73 | ||
![]() |
f163a15b13 | ||
![]() |
87779ed34e | ||
![]() |
04bc846ef3 | ||
![]() |
301acac163 | ||
![]() |
9401196e88 | ||
![]() |
3457366066 | ||
![]() |
cb66cf6398 | ||
![]() |
73573a85de | ||
![]() |
b49a4ae0bc | ||
![]() |
2f63c39fa6 | ||
![]() |
95d9a95b2b | ||
![]() |
44ecb1c050 | ||
![]() |
0706de5378 | ||
![]() |
9dd9938c38 | ||
![]() |
e27bbdc769 | ||
![]() |
09b46029fa | ||
![]() |
5c289b7eab | ||
![]() |
656573c5d2 | ||
![]() |
59c5ac0cb5 | ||
![]() |
53092424e6 | ||
![]() |
6ba0491adf | ||
![]() |
e3fb9e4cee | ||
![]() |
8d53ae894b | ||
![]() |
d50f8afa9e | ||
![]() |
98fa343588 | ||
![]() |
9ceb3fbb9a | ||
![]() |
22d95546a7 | ||
![]() |
33689ec558 | ||
![]() |
602dd7fdf2 | ||
![]() |
7f15c995b7 | ||
![]() |
9be3e56b70 | ||
![]() |
24119b8a9c | ||
![]() |
4d75de006c | ||
![]() |
e19516ec5a | ||
![]() |
1ed607f398 | ||
![]() |
7e0822c5b1 | ||
![]() |
037c3438a3 | ||
![]() |
cde5d4acfa | ||
![]() |
d79db68bf8 | ||
![]() |
b3b9d9e161 | ||
![]() |
3f1f1645c7 | ||
![]() |
18a82688e2 | ||
![]() |
27d6b2645e | ||
![]() |
fee40353e2 | ||
![]() |
659360d543 | ||
![]() |
3ea6424b8f | ||
![]() |
96bee8e60d | ||
![]() |
883c4a7b0f | ||
![]() |
d4317ba1e4 | ||
![]() |
9d69b2a963 | ||
![]() |
ef3b000050 | ||
![]() |
a4a688ed83 | ||
![]() |
17dc5c57dd | ||
![]() |
ef5f939db8 | ||
![]() |
cb4751da4c | ||
![]() |
0685f17f73 | ||
![]() |
4b260d5d9f | ||
![]() |
c8f015c6d7 | ||
![]() |
604d2155ba | ||
![]() |
e7727d698f | ||
![]() |
a3f75f401c | ||
![]() |
d342f7c429 | ||
![]() |
bb2b26ca44 | ||
![]() |
2f9840a51c | ||
![]() |
09aefdba43 | ||
![]() |
4c8a408afc | ||
![]() |
4c08d9a53b | ||
![]() |
b091cbf361 | ||
![]() |
a6fcda69ac | ||
![]() |
9063e4568c | ||
![]() |
3d37b5d696 | ||
![]() |
3a8bad1e6f | ||
![]() |
e822e51752 | ||
![]() |
f9818f890b | ||
![]() |
6526118d9f | ||
![]() |
c15b3b4a09 | ||
![]() |
e1acb69cf1 | ||
![]() |
8f757c7b80 | ||
![]() |
01a47c7d6d | ||
![]() |
3ee09c6251 | ||
![]() |
bb54f91dd1 | ||
![]() |
41a79530e9 | ||
![]() |
31f5a916f4 | ||
![]() |
5657a671c1 | ||
![]() |
ecc254c659 | ||
![]() |
9cb1c95e49 | ||
![]() |
e73c46ce03 | ||
![]() |
952e9c52bc | ||
![]() |
b879af46b3 | ||
![]() |
9feb9d6bca | ||
![]() |
dc0437a5b5 | ||
![]() |
55331a0678 | ||
![]() |
f5580f61f9 | ||
![]() |
30953cf2d7 | ||
![]() |
c7fa446ee7 | ||
![]() |
9ecbac365b | ||
![]() |
80f6fb6329 | ||
![]() |
1b596a114d | ||
![]() |
265c00235b | ||
![]() |
fae37222a7 | ||
![]() |
d41449b578 | ||
![]() |
34979c3fe8 | ||
![]() |
711f0c0c50 | ||
![]() |
933d05a565 | ||
![]() |
8a0da1cb07 | ||
![]() |
1445903a34 | ||
![]() |
5d9386df0c | ||
![]() |
6fd1de226b | ||
![]() |
ac099343da | ||
![]() |
bce5f3f108 | ||
![]() |
35e0982e35 | ||
![]() |
767455e8d8 | ||
![]() |
6b8dda0d00 | ||
![]() |
277df44cfb | ||
![]() |
2dded1e510 | ||
![]() |
a7b1b1da80 | ||
![]() |
de69678085 | ||
![]() |
5f7b81eb95 | ||
![]() |
f4f70afe31 | ||
![]() |
116957b339 | ||
![]() |
1af0033368 | ||
![]() |
3645c63c08 | ||
![]() |
04ddfe0a6f | ||
![]() |
ec3dc4a607 | ||
![]() |
0b98fbab0a | ||
![]() |
5b8dc37c31 | ||
![]() |
f42258327b | ||
![]() |
7d1ef3f447 | ||
![]() |
652fe57cdd | ||
![]() |
20a6243c85 | ||
![]() |
679edac9c3 | ||
![]() |
bb59b8c249 | ||
![]() |
c5c6b2257f | ||
![]() |
6acf7b06f4 | ||
![]() |
d0c004c93c | ||
![]() |
53876d2b62 | ||
![]() |
2b63b17327 | ||
![]() |
226a09b38c | ||
![]() |
527c53a2a0 | ||
![]() |
19795c1681 | ||
![]() |
1999fcaa8f | ||
![]() |
6b5ff8fd74 | ||
![]() |
821d946a72 | ||
![]() |
5f7c901727 | ||
![]() |
7b8ee4ee1e | ||
![]() |
32cf4afb04 | ||
![]() |
e0c92befd5 | ||
![]() |
827e0341ab | ||
![]() |
8627b65f8d | ||
![]() |
9c62a907c5 | ||
![]() |
a119ea96a3 | ||
![]() |
06d55bf019 | ||
![]() |
320f38de47 | ||
![]() |
7adfaceccf | ||
![]() |
67be4e2bf3 | ||
![]() |
c3e87ee896 | ||
![]() |
f2283ec634 | ||
![]() |
d06e4beb7f | ||
![]() |
e24863d175 | ||
![]() |
2de2241690 | ||
![]() |
977de8c5d4 | ||
![]() |
fb6438cdd4 | ||
![]() |
517e8f6fbd | ||
![]() |
0e758a9e65 | ||
![]() |
64a915a68d | ||
![]() |
d233238c64 | ||
![]() |
71a4fe746e | ||
![]() |
f28c7835a1 | ||
![]() |
cecf7f4bf0 | ||
![]() |
c687cf9db6 | ||
![]() |
54d2218ac2 | ||
![]() |
471e6b9e13 | ||
![]() |
f8dcea3975 | ||
![]() |
d931af33c4 | ||
![]() |
a0e3c05428 | ||
![]() |
b8c13cc426 | ||
![]() |
38253a9f73 | ||
![]() |
cbc92b847f | ||
![]() |
a5f993f269 | ||
![]() |
31361e464a | ||
![]() |
bb977c00ca | ||
![]() |
39f65f9f86 | ||
![]() |
bda2d6d1ac | ||
![]() |
1e225ecdaf | ||
![]() |
cfb85d9a9a | ||
![]() |
f88c20f335 | ||
![]() |
c98824bc9e | ||
![]() |
69a35bb85f | ||
![]() |
a3bb6c12e5 | ||
![]() |
586f118279 | ||
![]() |
31081e5dac | ||
![]() |
ef363e9d2e | ||
![]() |
9fa77acb8c | ||
![]() |
1e30db64d1 | ||
![]() |
e830b66604 | ||
![]() |
5f0fab2156 | ||
![]() |
467465c99c | ||
![]() |
e935b52e51 | ||
![]() |
879407c10c | ||
![]() |
e76be14dbb | ||
![]() |
7fa15c74b4 | ||
![]() |
c3950699bf | ||
![]() |
e6b950e31b | ||
![]() |
9440bdb1aa | ||
![]() |
e320b06aaa | ||
![]() |
b284126d3b | ||
![]() |
6858cb261f | ||
![]() |
2d6954186e | ||
![]() |
d72bf0cd5d | ||
![]() |
584460deec | ||
![]() |
e3d5969282 | ||
![]() |
249468bbea | ||
![]() |
f0f4c31d96 | ||
![]() |
27f012ffad | ||
![]() |
7d54631ebf | ||
![]() |
513628e4ad | ||
![]() |
101b215d6b | ||
![]() |
6af48de0b8 | ||
![]() |
e5c4fedd55 | ||
![]() |
2ce23072d3 | ||
![]() |
97f4eb6b75 | ||
![]() |
75cbf3d730 | ||
![]() |
bf9fdf448d | ||
![]() |
63c627ec18 | ||
![]() |
dadbd793be | ||
![]() |
75b6e917ad | ||
![]() |
ab53c0e943 | ||
![]() |
c2fe6a18ad | ||
![]() |
b7119c55a6 | ||
![]() |
d0f2c6be6d | ||
![]() |
3a535b6722 | ||
![]() |
f9a77aec3f | ||
![]() |
bee6d2b240 | ||
![]() |
9a6a189e36 | ||
![]() |
505eabb78c | ||
![]() |
b0ba325f0e | ||
![]() |
6fbd21001b | ||
![]() |
626e4965b1 | ||
![]() |
a15042b7e5 | ||
![]() |
e56f963574 | ||
![]() |
65a8f9100c | ||
![]() |
6954d23444 | ||
![]() |
6c624e1c26 | ||
![]() |
cc839029b9 | ||
![]() |
25f8eaf1ac | ||
![]() |
8fdd226b8b | ||
![]() |
6c5595fa9c | ||
![]() |
e6558f838e | ||
![]() |
57037a45b8 | ||
![]() |
c844611052 | ||
![]() |
b60e02956d | ||
![]() |
4fe66ce0a9 | ||
![]() |
4b5a503cee | ||
![]() |
817995d97f | ||
![]() |
0e7221c361 | ||
![]() |
938fb8e6c8 | ||
![]() |
fd8c49ff0a | ||
![]() |
cd84317346 | ||
![]() |
4f55e16fe9 | ||
![]() |
c30ef668de | ||
![]() |
62e0c42803 | ||
![]() |
70aee2d95e | ||
![]() |
63c7591698 | ||
![]() |
930361b988 | ||
![]() |
baadb75a5e | ||
![]() |
f28f5dc0b6 | ||
![]() |
41fdc4ac2e | ||
![]() |
177ec27cca | ||
![]() |
37652ca2cf | ||
![]() |
6c22759d29 | ||
![]() |
25b6a40ad4 | ||
![]() |
fbea59b326 | ||
![]() |
38e4906f72 | ||
![]() |
029d69919b | ||
![]() |
5e395fb676 | ||
![]() |
ac448bd42b | ||
![]() |
f55737ec06 | ||
![]() |
80de15face | ||
![]() |
32565e096d | ||
![]() |
1d8e4bdd6d | ||
![]() |
1677a068ce | ||
![]() |
a02b8441b1 | ||
![]() |
dfe1c106f2 | ||
![]() |
e49bbe2ed8 | ||
![]() |
6ee5a1437c | ||
![]() |
93a3383e60 | ||
![]() |
c9a2a561f8 | ||
![]() |
ac0b2fdc6f | ||
![]() |
46b9984414 | ||
![]() |
f9743e2174 | ||
![]() |
a3c55c2692 | ||
![]() |
692eb4d957 | ||
![]() |
826751429b | ||
![]() |
5621d3c0c7 | ||
![]() |
b5f46c9171 | ||
![]() |
166b8c042c | ||
![]() |
d34ece6f1a | ||
![]() |
679844f791 | ||
![]() |
9316256e10 | ||
![]() |
90d7737fc1 | ||
![]() |
567ca15610 | ||
![]() |
558b323485 | ||
![]() |
1a05da8296 | ||
![]() |
5df59f75cd | ||
![]() |
029673d0ee | ||
![]() |
3a57f843d5 | ||
![]() |
182a267f69 | ||
![]() |
3de40434fa | ||
![]() |
bc8328d7c2 | ||
![]() |
12c1a06e60 | ||
![]() |
b11405570a | ||
![]() |
3b85e4b2b9 | ||
![]() |
c5abf5ddbb | ||
![]() |
2a3d4b62a7 | ||
![]() |
8ff81bcc37 | ||
![]() |
7159d3bc35 | ||
![]() |
941d202938 | ||
![]() |
5ea0cf8bab | ||
![]() |
df9a5f867f | ||
![]() |
06e4778072 | ||
![]() |
92388892b3 | ||
![]() |
5d124ac00a | ||
![]() |
a57c3ae105 | ||
![]() |
55354f5c38 | ||
![]() |
379bb0a77d | ||
![]() |
39357fc242 | ||
![]() |
799de4f0f4 | ||
![]() |
c34b5c1cf0 | ||
![]() |
46361c3e28 | ||
![]() |
f9d33b2efc | ||
![]() |
2185904fcb | ||
![]() |
eb952819c2 | ||
![]() |
d7d8c92a9a | ||
![]() |
88a7790d44 | ||
![]() |
806dabe2d7 | ||
![]() |
740e7ddd69 | ||
![]() |
bee97ab6a7 | ||
![]() |
59fc17c355 | ||
![]() |
5f25ca0c3a | ||
![]() |
41b4a079c7 | ||
![]() |
e4235376d8 | ||
![]() |
043a201f90 | ||
![]() |
d1a588a94f | ||
![]() |
01b6d9bfe2 | ||
![]() |
9711d95996 | ||
![]() |
b87db00fdb | ||
![]() |
6190b65056 | ||
![]() |
10fe91d704 | ||
![]() |
36bb05b10e | ||
![]() |
a7b7213017 | ||
![]() |
031154a400 | ||
![]() |
463b50e746 | ||
![]() |
1749a85e96 | ||
![]() |
1af9e92e91 | ||
![]() |
12d0c98fb5 | ||
![]() |
817c6986a0 | ||
![]() |
7c68aaea4c | ||
![]() |
6fea46e0cf | ||
![]() |
59fa74fed1 | ||
![]() |
581335fbea | ||
![]() |
9b5d6cc008 | ||
![]() |
d0f98ec1ba | ||
![]() |
a977fcf3d0 | ||
![]() |
664f6ef420 | ||
![]() |
06a31992e3 | ||
![]() |
4e2092d593 | ||
![]() |
9755f308e5 | ||
![]() |
09610daea1 | ||
![]() |
13b7fa4eba | ||
![]() |
909a46087f | ||
![]() |
c10c8649f5 | ||
![]() |
82dce6758a | ||
![]() |
024652bfb4 | ||
![]() |
789608b637 | ||
![]() |
d05b750b8d | ||
![]() |
704cae1de3 | ||
![]() |
23b074481a | ||
![]() |
5dc8fa6690 | ||
![]() |
a9ba98686f | ||
![]() |
59382bace2 | ||
![]() |
2edf822bc6 | ||
![]() |
355621b0ab | ||
![]() |
a307e13a63 | ||
![]() |
f807207b65 | ||
![]() |
30b54aae34 | ||
![]() |
79e682bcd0 | ||
![]() |
a05ae8654c | ||
![]() |
0db172edbf | ||
![]() |
7b0930f798 | ||
![]() |
0919b37c34 | ||
![]() |
faf55c4627 | ||
![]() |
f351c5d304 | ||
![]() |
63bca17ab6 | ||
![]() |
c2abe43ee7 | ||
![]() |
1de2fd7122 | ||
![]() |
e377e82cfd | ||
![]() |
fa8174a200 | ||
![]() |
d22448731c | ||
![]() |
ef95133b1c | ||
![]() |
c068c2122d | ||
![]() |
d8c47b0abd | ||
![]() |
66eb4bc34c | ||
![]() |
bce812ecbc | ||
![]() |
02220ed6c7 | ||
![]() |
8d08851f28 | ||
![]() |
af135c0b0b | ||
![]() |
42c972735e | ||
![]() |
110c79d10e | ||
![]() |
b9d867cb86 | ||
![]() |
ea3b961e43 | ||
![]() |
bc510378b3 | ||
![]() |
0a47d135ac | ||
![]() |
ec8ed1dbb0 | ||
![]() |
203e5335ab | ||
![]() |
f1d8428650 | ||
![]() |
8d29d22e99 | ||
![]() |
9c6e527d4b | ||
![]() |
077606c057 | ||
![]() |
a615f93060 | ||
![]() |
c562657f1e | ||
![]() |
7b3922f8e9 | ||
![]() |
c14382181f | ||
![]() |
b2183dfda7 | ||
![]() |
bb92054c86 | ||
![]() |
4e4a6eb5d7 | ||
![]() |
692acbd986 | ||
![]() |
901901825c | ||
![]() |
97f2de37e1 | ||
![]() |
967b6c33df | ||
![]() |
00c7a27732 | ||
![]() |
048ba353c4 | ||
![]() |
555e2f6de2 | ||
![]() |
ff8d5281f0 | ||
![]() |
4f9b994e73 | ||
![]() |
b8b0dc5c78 | ||
![]() |
d0cafab836 | ||
![]() |
24d7c5ebe3 | ||
![]() |
dc6decefb5 | ||
![]() |
25d7e48077 | ||
![]() |
b0b8f37240 | ||
![]() |
188e4e1b92 | ||
![]() |
9d5273bb15 | ||
![]() |
3c0fae74f1 | ||
![]() |
86dae6d4c7 | ||
![]() |
d06600aeb0 | ||
![]() |
895a3d1f39 | ||
![]() |
381ef5c683 | ||
![]() |
62097897be | ||
![]() |
2d2c47ba49 | ||
![]() |
89cdfc9194 | ||
![]() |
ad60ea9e0e | ||
![]() |
a7350475e8 | ||
![]() |
f3d7c9cff9 | ||
![]() |
906cbeed61 | ||
![]() |
0fccb0fc86 | ||
![]() |
8100cefd4c | ||
![]() |
d7e99a3f86 | ||
![]() |
6af944fe2c | ||
![]() |
12fc394b92 | ||
![]() |
53814fefc1 | ||
![]() |
e87a01c80b | ||
![]() |
21d7c1a850 | ||
![]() |
e33c58297d | ||
![]() |
5350120db4 | ||
![]() |
0997cf7fee | ||
![]() |
af3aae7295 | ||
![]() |
98e219da4b | ||
![]() |
fba022cc06 | ||
![]() |
3f6c6f1dd9 | ||
![]() |
ebc2e7221b | ||
![]() |
7cb30ced23 | ||
![]() |
7b449ac56c | ||
![]() |
724953101d | ||
![]() |
8734477d52 | ||
![]() |
ec8ba4b5f9 | ||
![]() |
2250865eb6 | ||
![]() |
847a3bbee3 | ||
![]() |
410a002ddd | ||
![]() |
8766db2593 | ||
![]() |
e362227514 | ||
![]() |
da311f266d | ||
![]() |
f5a4e996a8 | ||
![]() |
a7f083897f | ||
![]() |
e2105dc721 | ||
![]() |
b64548ee1f | ||
![]() |
53425fa721 | ||
![]() |
048f035d30 | ||
![]() |
b32c837df9 | ||
![]() |
dd03a76d51 | ||
![]() |
806a666950 | ||
![]() |
b240a5e819 | ||
![]() |
fe823b3553 | ||
![]() |
d380d30ef4 | ||
![]() |
1fe5b3e7d5 | ||
![]() |
a8df208a5c | ||
![]() |
f3f3c94831 | ||
![]() |
6e06648f7a | ||
![]() |
afb41f715b | ||
![]() |
19d26dde92 | ||
![]() |
4acb902423 | ||
![]() |
626516d12e | ||
![]() |
1c94df2553 | ||
![]() |
43762da9d3 | ||
![]() |
266166a2d6 | ||
![]() |
3a0af0faae | ||
![]() |
0890eaa3fe | ||
![]() |
d4058d947b | ||
![]() |
b704659899 | ||
![]() |
0a9187a6e9 | ||
![]() |
31db32e826 | ||
![]() |
c2ea650b3c | ||
![]() |
969131f00e | ||
![]() |
c98090c061 | ||
![]() |
3168d3b5e6 | ||
![]() |
efcd7d86e7 | ||
![]() |
04449923bd | ||
![]() |
47b3336ffa | ||
![]() |
0f37c1b58e | ||
![]() |
a3747725ed | ||
![]() |
c448650a60 | ||
![]() |
c45f616fdc | ||
![]() |
9402691aaa | ||
![]() |
cbffbb0be0 | ||
![]() |
9df5b17940 | ||
![]() |
feae23506b | ||
![]() |
6408e59c7c | ||
![]() |
47d72680ff | ||
![]() |
6513cbb470 | ||
![]() |
50b81fe4b9 | ||
![]() |
f38c1f6ab4 | ||
![]() |
f159611fab | ||
![]() |
f1a7231ac2 | ||
![]() |
21991a7edb | ||
![]() |
3f1b6ddc8f | ||
![]() |
aa84813400 | ||
![]() |
dd243813e1 | ||
![]() |
d8c2933c58 | ||
![]() |
2b798511de | ||
![]() |
6c37f6e601 | ||
![]() |
92e9f3d467 | ||
![]() |
05419b8450 | ||
![]() |
e215c07439 | ||
![]() |
5b7dff7a57 | ||
![]() |
1a3aa75385 | ||
![]() |
41880778b5 | ||
![]() |
ecb4e09ec5 | ||
![]() |
d02505852d | ||
![]() |
3941dc7537 | ||
![]() |
e790c45303 | ||
![]() |
ae4e553ddb | ||
![]() |
809568280b | ||
![]() |
4053c92abf | ||
![]() |
56906a29e0 | ||
![]() |
2c0ad5bef7 | ||
![]() |
4a7939268c | ||
![]() |
80266d3071 | ||
![]() |
8e5cfccf49 | ||
![]() |
dcf64ca167 | ||
![]() |
f93fc1506b | ||
![]() |
4ee8fb8154 | ||
![]() |
446b75907e | ||
![]() |
550f1989ff | ||
![]() |
91a6f42345 | ||
![]() |
e97cae0eb3 | ||
![]() |
8640982e68 | ||
![]() |
480a853263 | ||
![]() |
b05953d960 | ||
![]() |
3a0de6a4f1 | ||
![]() |
fb9f22c02f | ||
![]() |
10ac1000f7 | ||
![]() |
c81a0dede2 | ||
![]() |
fc8a2b8a42 | ||
![]() |
2ae0a72dad | ||
![]() |
5b17c72047 | ||
![]() |
8d9653dece | ||
![]() |
e2b7b26f28 | ||
![]() |
ff2eb77fcd | ||
![]() |
0588399ac7 | ||
![]() |
71544fbf4e | ||
![]() |
c8f3820956 | ||
![]() |
f57b0726a0 | ||
![]() |
da175bca52 | ||
![]() |
33cb7f4a2c | ||
![]() |
7732447abc | ||
![]() |
c49c37999c | ||
![]() |
91f35d6a01 | ||
![]() |
549df04ed8 | ||
![]() |
4334135c52 | ||
![]() |
03c4de5590 | ||
![]() |
7a109a18af | ||
![]() |
d9b72b0f43 | ||
![]() |
a7ea54bd7d | ||
![]() |
df642b96e2 | ||
![]() |
f56cc1f733 | ||
![]() |
f5bff4b7f3 | ||
![]() |
bbfdf5dd2a | ||
![]() |
9b95eda42a | ||
![]() |
2d225a3386 | ||
![]() |
7b3cdc8f96 | ||
![]() |
b6f9500ccc | ||
![]() |
ea354e96cb | ||
![]() |
098c8908ed | ||
![]() |
ab632e36a5 | ||
![]() |
1427d20922 | ||
![]() |
aed671810c | ||
![]() |
324d7d720d | ||
![]() |
413e39ecbb | ||
![]() |
2ca2c18c2a | ||
![]() |
01cd4b2ba0 | ||
![]() |
bca210db45 | ||
![]() |
66d6f73af2 | ||
![]() |
bc8799d7d7 | ||
![]() |
fd5c14550a | ||
![]() |
a5cca5296c | ||
![]() |
f4ef4b79f9 | ||
![]() |
6c7a51378f | ||
![]() |
9c4908b44a | ||
![]() |
afaab8aef2 | ||
![]() |
845fdda22c | ||
![]() |
fa29a1a99e | ||
![]() |
f9bffae9fd | ||
![]() |
31c925c602 | ||
![]() |
5d310e06ba | ||
![]() |
25a16c3379 | ||
![]() |
730ed6f75f | ||
![]() |
a6601e92aa | ||
![]() |
f3a2bb7779 | ||
![]() |
73e2d7049a | ||
![]() |
a6353944f6 | ||
![]() |
43d6088ebb | ||
![]() |
e3001794f2 | ||
![]() |
e97ca325e6 | ||
![]() |
c9c6645284 | ||
![]() |
57bb297450 | ||
![]() |
06ca99c3a3 | ||
![]() |
4b5593c67f | ||
![]() |
acb3dc6754 | ||
![]() |
4c21a46452 | ||
![]() |
900ae2c1fa | ||
![]() |
01b6445708 | ||
![]() |
292d502205 | ||
![]() |
adf2e44a82 | ||
![]() |
b075d576a0 |
35
.cvsignore
35
.cvsignore
@@ -1,35 +0,0 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
confdefs.h
|
||||
config.cache
|
||||
config.guess
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
configure.scan
|
||||
libtool
|
||||
ltconfig
|
||||
ltmain.sh
|
||||
stamp-h
|
||||
stamp-h.in
|
||||
stamp-h1
|
||||
stamp.h
|
||||
version.h
|
||||
config.h.in
|
||||
install-sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
INSTALL
|
||||
intl
|
||||
ABOUT-NLS
|
||||
COPYING
|
||||
intltool-*
|
||||
metacity.spec
|
||||
autom4te.cache
|
||||
compile
|
||||
depcomp
|
||||
omf.make
|
||||
xmldocs.make
|
37
.gitignore
vendored
37
.gitignore
vendored
@@ -3,6 +3,7 @@ Makefile.in
|
||||
Makefile.in.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
build-aux
|
||||
compile
|
||||
config.guess
|
||||
config.h
|
||||
@@ -19,11 +20,11 @@ libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
.deps
|
||||
src/50-mutter-navigation.xml
|
||||
src/50-mutter-system.xml
|
||||
src/50-mutter-windows.xml
|
||||
src/mutter.desktop
|
||||
src/mutter-wayland.desktop
|
||||
50-mutter-navigation.xml
|
||||
50-mutter-system.xml
|
||||
50-mutter-windows.xml
|
||||
mutter.desktop
|
||||
mutter-wayland.desktop
|
||||
*.o
|
||||
*.a
|
||||
*.lo
|
||||
@@ -32,10 +33,6 @@ src/mutter-wayland.desktop
|
||||
*.swp
|
||||
*.gir
|
||||
*.typelib
|
||||
tidy-enum-types.[ch]
|
||||
tidy-marshal.[ch]
|
||||
stamp-tidy-enum-types.h
|
||||
stamp-tidy-marshal.h
|
||||
stamp-h1
|
||||
*.gmo
|
||||
*.make
|
||||
@@ -44,11 +41,12 @@ stamp-it
|
||||
.intltool-merge-cache
|
||||
POTFILES
|
||||
po/*.pot
|
||||
50-metacity-desktop-key.xml
|
||||
50-metacity-key.xml
|
||||
libmutter.pc
|
||||
mutter
|
||||
mutter-launch
|
||||
mutter-restart-helper
|
||||
mutter-test-client
|
||||
mutter-test-runner
|
||||
mutter-all.test
|
||||
org.gnome.mutter.gschema.valid
|
||||
org.gnome.mutter.gschema.xml
|
||||
org.gnome.mutter.wayland.gschema.valid
|
||||
@@ -57,19 +55,6 @@ testasyncgetprop
|
||||
testboxes
|
||||
testgradient
|
||||
m4/*
|
||||
mutter-grayscale
|
||||
mutter-mag
|
||||
mutter-message
|
||||
mutter-window-demo
|
||||
focus-window
|
||||
test-attached
|
||||
test-focus
|
||||
test-gravity
|
||||
test-resizing
|
||||
test-size-hints
|
||||
# We can't say just "wm-tester" here or it will ignore the directory
|
||||
# rather than the binary
|
||||
src/wm-tester/wm-tester
|
||||
INSTALL
|
||||
mkinstalldirs
|
||||
src/mutter-enum-types.[ch]
|
||||
@@ -78,12 +63,14 @@ src/mutter-marshal.[ch]
|
||||
src/stamp-mutter-marshal.h
|
||||
src/meta-dbus-display-config.[ch]
|
||||
src/meta-dbus-idle-monitor.[ch]
|
||||
src/meta-dbus-login1.[ch]
|
||||
src/gtk-shell-protocol.c
|
||||
src/gtk-shell-server-protocol.h
|
||||
src/xdg-shell-protocol.c
|
||||
src/xdg-shell-server-protocol.h
|
||||
src/xserver-protocol.c
|
||||
src/xserver-server-protocol.h
|
||||
src/meta/meta-version.h
|
||||
doc/reference/*.args
|
||||
doc/reference/*.bak
|
||||
doc/reference/*.hierarchy
|
||||
|
11
Makefile.am
11
Makefile.am
@@ -1,10 +1,13 @@
|
||||
|
||||
SUBDIRS=src po doc
|
||||
SUBDIRS = data src po doc
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
|
||||
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
|
||||
DISTCLEANFILES = \
|
||||
intltool-extract \
|
||||
intltool-merge \
|
||||
intltool-update \
|
||||
po/stamp-it \
|
||||
po/.intltool-merge-cache
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
|
125
NEWS
125
NEWS
@@ -1,3 +1,128 @@
|
||||
3.14.0
|
||||
======
|
||||
* Fix placement of popup windows on wayland [Jasper; #736812]
|
||||
* Only increment serial once per event [Jasper; #736840]
|
||||
* Fix window positioning regression with non-GTK+ toolkits [Owen; #736719]
|
||||
|
||||
Contributors:
|
||||
Jasper St. Pierre, Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Saibal Ray [bn_IN], Dušan Kazik [sk], Manoj Kumar Giri [or],
|
||||
Christian Kirbach [de], Ask H. Larsen [da], YunQiang Su [zh_CN],
|
||||
Bernd Homuth [de], Shankar Prasad [kn], Petr Kovar [cs], Rajesh Ranjan [hi]
|
||||
|
||||
3.13.92
|
||||
=======
|
||||
* Rewrite background code [Owen; #735637, #736568]
|
||||
* Fix size in nested mode [Owen; #736279]
|
||||
* Fix destroy animation of background windows [Florian; #735927]
|
||||
* Wire keymap changes up to the wayland frontend [Rui; #736433]
|
||||
* Add a test framework and stacking tests [Owen; #736505]
|
||||
* Simplify handling of the merged X and wayland stack [Owen; #736559]
|
||||
* Fix cursor size on HiDPI [Adel; #729337]
|
||||
* Misc. bug fixes [Owen; #735632, #736589, #736694]
|
||||
|
||||
Contributors:
|
||||
Adel Gadllah, Rui Matos, Florian Müllner, Jasper St. Pierre, Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Andika Triwidada [id], Piotr Drąg [pl], Changwoo Ryu [ko],
|
||||
Kjartan Maraas [nb], Ville-Pekka Vainio [fi], Yuri Myasoedov [ru],
|
||||
Aurimas Černius [lt], Balázs Úr [hu], Sweta Kothari [gu], A S Alam [pa],
|
||||
Sandeep Sheshrao Shedmake [mr], Shantha kumar [ta], Gil Forcada [ca],
|
||||
Carles Ferrando [ca@valencia], Mattias Eriksson [sv]
|
||||
|
||||
3.13.91
|
||||
=======
|
||||
* Misc. bug fixes [Carlos; #735452]
|
||||
|
||||
Contributors:
|
||||
Adel Gadllah, Carlos Garnacho, Rui Matos, Jasper St. Pierre,
|
||||
Rico Tzschichholz
|
||||
|
||||
Translations:
|
||||
Chao-Hsiung Liao po/zh_HK, zh_TW.po, Enrico Nicoletto [pt_BR],
|
||||
Kjartan Maraas [nb], Fran Diéguez [gl], Yosef Or Boczko [he],
|
||||
Maria Mavridou [el], Claude Paroz [fr]
|
||||
|
||||
3.13.90
|
||||
=======
|
||||
* Only call XSync() once per frame [Rui; #728464]
|
||||
* Update capabilities on device list changes [Carlos; #733563]
|
||||
* Make use of GLSL optional [Adel; #733623]
|
||||
* Handle gestures and touch events on wayland [Carlos; #733631]
|
||||
* Add support for unminimize compositor effects [Cosimo; #733789]
|
||||
* Always set the frame background to None [Giovanni; #734054]
|
||||
* Add backend methods to handle keymaps [Rui; #734301]
|
||||
* Actually mark revalidated MetaTextureTower levels as valid [Owen; #734400]
|
||||
* Rely on explicit -backward switcher keybindings instead of <shift>-magic
|
||||
[Christophe; #732295, #732385]
|
||||
* Misc. bug fixes and cleanups [Rui, Adel, Christophe; #727178, #734852,
|
||||
#734960]
|
||||
|
||||
Contributors:
|
||||
Emmanuele Bassi, Giovanni Campagna, Cosimo Cecchi, Piotr Drąg,
|
||||
Christophe Fergeau, Adel Gadllah, Carlos Garnacho, Rui Matos,
|
||||
Florian Müllner, Jasper St. Pierre, Rico Tzschichholz, Olav Vitters,
|
||||
Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Kjartan Maraas [nb], Inaki Larranaga Murgoitio [eu], Lasse Liehu [fi],
|
||||
ngoswami [as], Daniel Mustieles [es]
|
||||
|
||||
3.13.4
|
||||
======
|
||||
* Fix move/resize operations for wayland clients [Marek; #731237]
|
||||
* Add ::first-frame signal to MetaWindowActor [Owen; #732343]
|
||||
* Handle keysyms without the XF86 prefix [Owen; #727993]
|
||||
* Add touch gesture support [Carlos]
|
||||
* Fix a deadlock when exiting [Owen; #733068]
|
||||
* Add framework for restarting the compositor with nice visuals
|
||||
[Owen; #733026]
|
||||
* Toggle seat capabilities on VT switch [Carlos; #733563]
|
||||
* Misc bug fixes [Florian, Owen; #732695, #732350]
|
||||
|
||||
Contributors:
|
||||
Tom Beckmann, Giovanni Campagna, Marek Chalupa, Adel Gadllah,
|
||||
Carlos Garnacho, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz,
|
||||
Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Yuri Myasoedov [ru], Fran Diéguez [gl], Aurimas Černius [lt], MarMav [el],
|
||||
Enrico Nicoletto [pt_BR]
|
||||
|
||||
3.13.3
|
||||
======
|
||||
* Improve behavior of window buttons with compositor menus [Florian; #731058]
|
||||
* Implement touch support on wayland [Carlos; #724442]
|
||||
* Update window shadows [Nikita; #731866]
|
||||
* Keep windows on the preferred output [Florian; #731760]
|
||||
* Misc bug fixes [Jonas, Florian, Jasper; #729601, #730681, #731353, #731332,
|
||||
#730527, #662962]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Nikita Churaev, Carlos Garnacho, Florian Müllner,
|
||||
Jasper St. Pierre, Rico Tzschichholz
|
||||
|
||||
3.13.2
|
||||
======
|
||||
* Add basic HiDPI support on wayland [Adel; #728902]
|
||||
* Fix crash when monitors change during suspend [Giovanni; #725637]
|
||||
* Replace mutter-launch with logind integration [Jasper; #724604]
|
||||
* Move window menu into the compositor [Jasper; #726352]
|
||||
* Fix delayed focus-follows-mouse support [Florian; #730541]
|
||||
* Support fallback app menu in window decorations [Florian; #730752]
|
||||
* Misc. bug fixes and cleanups [Giovanni, Jonas, Jasper; #729732, #729602,
|
||||
#726714]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Giovanni Campagna, Adel Gadllah, Florian Müllner,
|
||||
Jasper St. Pierre, Rico Tzschichholz
|
||||
|
||||
Translations:
|
||||
Pau Iranzo [ca], Daniel Mustieles [es]
|
||||
|
||||
3.13.1
|
||||
======
|
||||
* Fix opacity values from _NET_WM_WINDOW_OPACITY [Nirbheek; #727874]
|
||||
|
@@ -5,7 +5,7 @@ srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
PKG_NAME="mutter"
|
||||
REQUIRED_AUTOMAKE_VERSION=1.10
|
||||
REQUIRED_AUTOMAKE_VERSION=1.11
|
||||
|
||||
(test -f $srcdir/configure.ac \
|
||||
&& test -d $srcdir/src) || {
|
||||
|
115
configure.ac
115
configure.ac
@@ -1,9 +1,8 @@
|
||||
AC_PREREQ(2.50)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_PREREQ(2.62)
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [13])
|
||||
m4_define([mutter_micro_version], [1])
|
||||
m4_define([mutter_minor_version], [14])
|
||||
m4_define([mutter_micro_version], [0])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@@ -14,6 +13,7 @@ AC_INIT([mutter], [mutter_version],
|
||||
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_SRCDIR(src/core/display.c)
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
||||
@@ -40,12 +40,14 @@ GETTEXT_PACKAGE=mutter
|
||||
AC_SUBST(GETTEXT_PACKAGE)
|
||||
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
|
||||
|
||||
IT_PROG_INTLTOOL([0.34.90])
|
||||
LT_PREREQ([2.2.6])
|
||||
LT_INIT([disable-static])
|
||||
IT_PROG_INTLTOOL([0.41])
|
||||
AC_PROG_CC
|
||||
AC_ISC_POSIX
|
||||
AC_PROG_CC_C_O
|
||||
AC_PROG_INSTALL
|
||||
AC_HEADER_STDC
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AM_PROG_LIBTOOL
|
||||
PKG_PROG_PKG_CONFIG([0.21])
|
||||
|
||||
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
|
||||
AM_PATH_GLIB_2_0()
|
||||
@@ -70,15 +72,28 @@ CLUTTER_PACKAGE=clutter-1.0
|
||||
|
||||
MUTTER_PC_MODULES="
|
||||
gtk+-3.0 >= 3.9.11
|
||||
gio-2.0 >= 2.25.10
|
||||
gio-unix-2.0 >= 2.25.10
|
||||
pango >= 1.2.0
|
||||
cairo >= 1.10.0
|
||||
gsettings-desktop-schemas >= 3.7.3
|
||||
xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0
|
||||
$CLUTTER_PACKAGE >= 1.17.5
|
||||
$CLUTTER_PACKAGE >= 1.19.5
|
||||
clutter-egl-1.0
|
||||
cogl-1.0 >= 1.17.1
|
||||
gbm
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
xcomposite >= 0.2
|
||||
xcursor
|
||||
xdamage
|
||||
xext
|
||||
xfixes
|
||||
xi >= 1.6.0
|
||||
xkbfile
|
||||
xkeyboard-config
|
||||
xkbcommon >= 0.4.3
|
||||
xkbcommon-x11
|
||||
x11-xcb
|
||||
xcb-randr
|
||||
"
|
||||
|
||||
GLIB_GSETTINGS
|
||||
@@ -107,37 +122,18 @@ AC_ARG_WITH(libcanberra,
|
||||
[disable the use of libcanberra for playing sounds]),,
|
||||
with_libcanberra=auto)
|
||||
|
||||
AC_ARG_ENABLE(xsync,
|
||||
AC_HELP_STRING([--disable-xsync],
|
||||
[disable mutter's use of the XSync extension]),,
|
||||
enable_xsync=auto)
|
||||
|
||||
AC_ARG_ENABLE(shape,
|
||||
AC_HELP_STRING([--disable-shape],
|
||||
[disable mutter's use of the shaped window extension]),,
|
||||
enable_shape=auto)
|
||||
|
||||
## Wayland support requires the xserver.xml protocol extension found in the weston
|
||||
## repository but since there aren't currently established conventions for
|
||||
## installing and discovering these we simply require a location to be given
|
||||
## explicitly...
|
||||
AC_ARG_WITH([wayland-protocols],
|
||||
[AS_HELP_STRING([--with-wayland-protocols], [Location for wayland extension protocol specs])],
|
||||
[
|
||||
],
|
||||
[])
|
||||
|
||||
AC_ARG_WITH([xwayland-path],
|
||||
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
|
||||
[XWAYLAND_PATH="$withval"],
|
||||
[XWAYLAND_PATH="$bindir/Xwayland"])
|
||||
|
||||
AM_GLIB_GNU_GETTEXT
|
||||
AC_ARG_ENABLE(installed_tests,
|
||||
AS_HELP_STRING([--enable-installed-tests],
|
||||
[Install test programs (default: no)]),,
|
||||
[enable_installed_tests=no])
|
||||
AM_CONDITIONAL(BUILDOPT_INSTALL_TESTS, test x$enable_installed_tests = xyes)
|
||||
|
||||
## here we get the flags we'll actually use
|
||||
# GRegex requires Glib-2.14.0
|
||||
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
|
||||
PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login)
|
||||
|
||||
# Unconditionally use this dir to avoid a circular dep with gnomecc
|
||||
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
|
||||
@@ -202,17 +198,27 @@ if test x$found_introspection != xno; then
|
||||
AC_SUBST(META_GIR)
|
||||
fi
|
||||
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor"
|
||||
|
||||
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
|
||||
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
|
||||
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
|
||||
AC_SUBST([WAYLAND_SCANNER])
|
||||
AC_SUBST(XWAYLAND_PATH)
|
||||
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 wayland-server libdrm"
|
||||
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
|
||||
|
||||
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd libinput], [have_native_backend=yes], [have_native_backend=no])
|
||||
if test $have_native_backend = yes; then
|
||||
AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd])
|
||||
fi
|
||||
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test $have_native_backend = yes])
|
||||
|
||||
PKG_CHECK_MODULES(MUTTER_WAYLAND, [clutter-wayland-1.0 clutter-wayland-compositor-1.0 wayland-server >= 1.5.90], [have_wayland=yes], [have_wayland=no])
|
||||
if test $have_wayland = yes; then
|
||||
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
|
||||
AS_IF([test $WAYLAND_SCANNER = "no"],
|
||||
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
|
||||
AC_SUBST([WAYLAND_SCANNER])
|
||||
|
||||
AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support])
|
||||
fi
|
||||
AM_CONDITIONAL([HAVE_WAYLAND],[test $have_wayland = yes])
|
||||
|
||||
PKG_CHECK_EXISTS([xi >= 1.6.99.1],
|
||||
AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater]))
|
||||
|
||||
@@ -249,16 +255,8 @@ if test x$have_xinerama = xno; then
|
||||
AC_MSG_ERROR([Xinerama extension was not found])
|
||||
fi
|
||||
|
||||
found_xkb=no
|
||||
AC_CHECK_LIB(X11, XkbQueryExtension,
|
||||
[AC_CHECK_HEADER(X11/XKBlib.h,
|
||||
found_xkb=yes)],
|
||||
, $ALL_X_LIBS)
|
||||
|
||||
if test "x$found_xkb" = "xyes"; then
|
||||
AC_DEFINE(HAVE_XKB, , [Have keyboard extension library])
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED([XKB_BASE], ["`$PKG_CONFIG --variable xkb_base xkeyboard-config`"],
|
||||
[XKB base dir])
|
||||
|
||||
RANDR_LIBS=
|
||||
found_randr=no
|
||||
@@ -304,17 +302,6 @@ fi
|
||||
|
||||
AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "yes")
|
||||
|
||||
HOST_ALIAS=$host_alias
|
||||
AC_SUBST(HOST_ALIAS)
|
||||
|
||||
AC_PATH_PROG(GDK_PIXBUF_CSOURCE, gdk-pixbuf-csource, no)
|
||||
|
||||
if test x"$GDK_PIXBUF_CSOURCE" = xno; then
|
||||
AC_MSG_ERROR([gdk-pixbuf-csource executable not found in your path - should be installed with GTK])
|
||||
fi
|
||||
|
||||
AC_SUBST(GDK_PIXBUF_CSOURCE)
|
||||
|
||||
AC_PATH_PROG(ZENITY, zenity, no)
|
||||
if test x"$ZENITY" = xno; then
|
||||
AC_MSG_ERROR([zenity not found in your path - needed for dialogs])
|
||||
@@ -397,6 +384,7 @@ changequote([,])dnl
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
data/Makefile
|
||||
doc/Makefile
|
||||
doc/man/Makefile
|
||||
doc/reference/Makefile
|
||||
@@ -404,6 +392,7 @@ doc/reference/meta-docs.sgml
|
||||
src/Makefile
|
||||
src/libmutter.pc
|
||||
src/compositor/plugins/Makefile
|
||||
src/meta/meta-version.h
|
||||
po/Makefile.in
|
||||
])
|
||||
|
||||
|
@@ -45,26 +45,68 @@
|
||||
_description="Move window one monitor down" />
|
||||
|
||||
<KeyListEntry name="switch-applications"
|
||||
reverse-entry="switch-applications-backward"
|
||||
_description="Switch applications"/>
|
||||
|
||||
<KeyListEntry name="switch-applications-backward"
|
||||
reverse-entry="switch-applications"
|
||||
hidden="true"
|
||||
_description="Switch to previous application"/>
|
||||
|
||||
<KeyListEntry name="switch-windows"
|
||||
reverse-entry="switch-windows-backward"
|
||||
_description="Switch windows"/>
|
||||
|
||||
<KeyListEntry name="switch-windows-backward"
|
||||
reverse-entry="switch-windows"
|
||||
hidden="true"
|
||||
_description="Switch to previous window"/>
|
||||
|
||||
<KeyListEntry name="switch-group"
|
||||
reverse-entry="switch-group-backward"
|
||||
_description="Switch windows of an application"/>
|
||||
|
||||
<KeyListEntry name="switch-group-backward"
|
||||
reverse-entry="switch-group"
|
||||
hidden="true"
|
||||
_description="Switch to previous window of an application"/>
|
||||
|
||||
<KeyListEntry name="switch-panels"
|
||||
reverse-entry="switch-panels-backward"
|
||||
_description="Switch system controls"/>
|
||||
|
||||
<KeyListEntry name="switch-panels-backward"
|
||||
reverse-entry="switch-panels"
|
||||
hidden="true"
|
||||
_description="Switch to previous system control"/>
|
||||
|
||||
<KeyListEntry name="cycle-windows"
|
||||
reverse-entry="cycle-windows-backward"
|
||||
_description="Switch windows directly"/>
|
||||
|
||||
<KeyListEntry name="cycle-windows-backward"
|
||||
reverse-entry="cycle-windows"
|
||||
hidden="true"
|
||||
_description="Switch directly to previous window"/>
|
||||
|
||||
<KeyListEntry name="cycle-group"
|
||||
reverse-entry="cycle-group-backward"
|
||||
_description="Switch windows of an app directly"/>
|
||||
|
||||
<KeyListEntry name="cycle-group-backward"
|
||||
reverse-entry="cycle-group"
|
||||
hidden="true"
|
||||
_description="Switch directly to previous window of an app"/>
|
||||
|
||||
<KeyListEntry name="cycle-panels"
|
||||
reverse-entry="cycle-panels-backward"
|
||||
_description="Switch system controls directly"/>
|
||||
|
||||
<KeyListEntry name="cycle-panels-backward"
|
||||
reverse-entry="cycle-panels"
|
||||
hidden="true"
|
||||
_description="Switch directly to previous system control"/>
|
||||
|
||||
<KeyListEntry name="show-desktop"
|
||||
_description="Hide all normal windows"/>
|
||||
|
@@ -1,3 +1,36 @@
|
||||
defaultcursordir = $(datadir)/mutter/cursors
|
||||
desktopfiles_in_files = \
|
||||
mutter.desktop.in \
|
||||
mutter-wayland.desktop.in
|
||||
desktopfilesdir = $(datadir)/applications
|
||||
desktopfiles_DATA = $(desktopfiles_in_files:.desktop.in=.desktop)
|
||||
|
||||
dist_defaultcursor_DATA = left_ptr.png
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
xml_in_files = \
|
||||
50-mutter-navigation.xml.in \
|
||||
50-mutter-system.xml.in \
|
||||
50-mutter-windows.xml.in
|
||||
xmldir = $(GNOME_KEYBINDINGS_KEYSDIR)
|
||||
xml_DATA = $(xml_in_files:.xml.in=.xml)
|
||||
|
||||
gschema_in_files = \
|
||||
org.gnome.mutter.gschema.xml.in \
|
||||
org.gnome.mutter.wayland.gschema.xml.in
|
||||
gsettings_SCHEMAS = $(gschema_in_files:.xml.in=.xml)
|
||||
|
||||
@INTLTOOL_XML_NOMERGE_RULE@
|
||||
@GSETTINGS_RULES@
|
||||
|
||||
convertdir = $(datadir)/GConf/gsettings
|
||||
convert_DATA = mutter-schemas.convert
|
||||
|
||||
CLEANFILES = \
|
||||
$(desktopfiles_DATA) \
|
||||
$(gsettings_SCHEMAS) \
|
||||
$(xml_DATA)
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(convert_DATA) \
|
||||
$(desktopfiles_in_files) \
|
||||
$(gschema_in_files) \
|
||||
$(xml_in_files)
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,7 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
_Name=Mutter (wayland compositor)
|
||||
Exec=mutter-launch -- mutter --wayland --display-server
|
||||
Exec=mutter --wayland --display-server
|
||||
NoDisplay=true
|
||||
# name of loadable control center module
|
||||
X-GNOME-WMSettingsModule=metacity
|
@@ -79,8 +79,6 @@ IGNORE_HFILES= \
|
||||
iconcache.h \
|
||||
inlinepixbufs.h \
|
||||
keybindings-private.h \
|
||||
menu.h \
|
||||
metaaccellabel.h \
|
||||
meta-background-actor-private.h \
|
||||
meta-background-group-private.h \
|
||||
meta-module.h \
|
||||
@@ -113,6 +111,13 @@ IGNORE_HFILES= \
|
||||
xprops.h \
|
||||
$(NULL)
|
||||
|
||||
if !HAVE_WAYLAND
|
||||
IGNORE_HFILES += \
|
||||
meta-surface-actor-wayland.h \
|
||||
wayland \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
MKDB_OPTIONS+=--ignore-files="$(IGNORE_HFILES)"
|
||||
|
||||
# Images to copy into HTML directory.
|
||||
|
@@ -300,6 +300,7 @@ MetaPluginVersion
|
||||
META_PLUGIN_DECLARE
|
||||
meta_plugin_switch_workspace_completed
|
||||
meta_plugin_minimize_completed
|
||||
meta_plugin_unminimize_completed
|
||||
meta_plugin_maximize_completed
|
||||
meta_plugin_unmaximize_completed
|
||||
meta_plugin_map_completed
|
||||
@@ -555,7 +556,7 @@ meta_window_is_monitor_sized
|
||||
meta_window_is_override_redirect
|
||||
meta_window_is_skip_taskbar
|
||||
meta_window_get_rect
|
||||
meta_window_get_input_rect
|
||||
meta_window_get_buffer_rect
|
||||
meta_window_get_frame_rect
|
||||
meta_window_get_outer_rect
|
||||
meta_window_client_rect_to_frame_rect
|
||||
|
@@ -23,7 +23,8 @@ environment.</description>
|
||||
<download-page rdf:resource="http://download.gnome.org/sources/mutter/" />
|
||||
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
|
||||
|
||||
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
|
||||
<category rdf:resource="http://api.gnome.org/doap-extensions#core" />
|
||||
<programming-language>C</programming-language>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
|
@@ -1,8 +1,11 @@
|
||||
# List of source files containing translatable strings.
|
||||
# Please keep this file sorted alphabetically.
|
||||
src/50-mutter-navigation.xml.in
|
||||
src/50-mutter-system.xml.in
|
||||
src/50-mutter-windows.xml.in
|
||||
data/50-mutter-navigation.xml.in
|
||||
data/50-mutter-system.xml.in
|
||||
data/50-mutter-windows.xml.in
|
||||
data/mutter.desktop.in
|
||||
data/org.gnome.mutter.gschema.xml.in
|
||||
data/org.gnome.mutter.wayland.gschema.xml.in
|
||||
src/backends/meta-monitor-manager.c
|
||||
src/compositor/compositor.c
|
||||
src/compositor/meta-background.c
|
||||
@@ -18,12 +21,7 @@ src/core/prefs.c
|
||||
src/core/screen.c
|
||||
src/core/util.c
|
||||
src/core/window.c
|
||||
src/mutter.desktop.in
|
||||
src/org.gnome.mutter.gschema.xml.in
|
||||
src/org.gnome.mutter.wayland.gschema.xml.in
|
||||
src/ui/frames.c
|
||||
src/ui/menu.c
|
||||
src/ui/metaaccellabel.c
|
||||
src/ui/resizepopup.c
|
||||
src/ui/theme.c
|
||||
src/ui/theme-parser.c
|
||||
|
@@ -1,2 +1 @@
|
||||
src/metacity.schemas.in
|
||||
|
||||
data/mutter-wayland.desktop.in
|
||||
|
1645
po/bn_IN.po
1645
po/bn_IN.po
File diff suppressed because it is too large
Load Diff
1275
po/ca@valencia.po
1275
po/ca@valencia.po
File diff suppressed because it is too large
Load Diff
1308
po/pt_BR.po
1308
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1306
po/zh_CN.po
1306
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
1267
po/zh_HK.po
1267
po/zh_HK.po
File diff suppressed because it is too large
Load Diff
1295
po/zh_TW.po
1295
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
50
src/Makefile-tests.am
Normal file
50
src/Makefile-tests.am
Normal file
@@ -0,0 +1,50 @@
|
||||
# A framework for running scripted tests
|
||||
|
||||
if HAVE_WAYLAND
|
||||
|
||||
if BUILDOPT_INSTALL_TESTS
|
||||
stackingdir = $(pkgdatadir)/tests/stacking
|
||||
dist_stacking_DATA = \
|
||||
tests/stacking/basic-x11.metatest \
|
||||
tests/stacking/basic-wayland.metatest \
|
||||
tests/stacking/mixed-windows.metatest \
|
||||
tests/stacking/override-redirect.metatest
|
||||
|
||||
mutter-all.test: tests/mutter-all.test.in
|
||||
$(AM_V_GEN) sed -e "s|@libexecdir[@]|$(libexecdir)|g" $< > $@.tmp && mv $@.tmp $@
|
||||
|
||||
installedtestsdir = $(datadir)/installed-tests/mutter
|
||||
installedtests_DATA = mutter-all.test
|
||||
|
||||
installedtestsbindir = $(libexecdir)/installed-tests/mutter
|
||||
installedtestsbin_PROGRAMS = mutter-test-client mutter-test-runner
|
||||
else
|
||||
noinst_PROGRAMS += mutter-test-client mutter-test-runner
|
||||
endif
|
||||
|
||||
EXTRA_DIST += tests/mutter-all.test.in
|
||||
|
||||
mutter_test_client_SOURCES = tests/test-client.c
|
||||
mutter_test_client_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
|
||||
mutter_test_runner_SOURCES = tests/test-runner.c
|
||||
mutter_test_runner_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
|
||||
.PHONY: run-tests
|
||||
|
||||
run-tests: mutter-test-client mutter-test-runner
|
||||
./mutter-test-runner $(dist_stacking_DATA)
|
||||
|
||||
endif
|
||||
|
||||
# Some random test programs for bits of the code
|
||||
|
||||
testboxes_SOURCES = core/testboxes.c
|
||||
testgradient_SOURCES = ui/testgradient.c
|
||||
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
|
||||
|
||||
noinst_PROGRAMS+=testboxes testgradient testasyncgetprop
|
||||
|
||||
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
|
189
src/Makefile.am
189
src/Makefile.am
@@ -5,42 +5,48 @@ lib_LTLIBRARIES = libmutter.la
|
||||
|
||||
SUBDIRS=compositor/plugins
|
||||
|
||||
INCLUDES= \
|
||||
EXTRA_DIST =
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-DCLUTTER_ENABLE_COMPOSITOR_API \
|
||||
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
|
||||
-DCLUTTER_DISABLE_DEPRECATION_WARNINGS \
|
||||
-DCOGL_DISABLE_DEPRECATION_WARNINGS \
|
||||
$(MUTTER_CFLAGS) \
|
||||
$(MUTTER_NATIVE_BACKEND_CFLAGS) \
|
||||
-I$(builddir) \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/backends \
|
||||
-I$(srcdir)/core \
|
||||
-I$(srcdir)/ui \
|
||||
-I$(srcdir)/compositor \
|
||||
-DMUTTER_LIBEXECDIR=\"$(libexecdir)\" \
|
||||
-DHOST_ALIAS=\"@HOST_ALIAS@\" \
|
||||
-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" \
|
||||
-DMUTTER_LOCALEDIR=\"$(localedir)\" \
|
||||
-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \
|
||||
-DMUTTER_DATADIR=\"$(datadir)\" \
|
||||
-DG_LOG_DOMAIN=\"mutter\" \
|
||||
-DSN_API_NOT_YET_FROZEN=1 \
|
||||
-DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) \
|
||||
-DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) \
|
||||
-DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) \
|
||||
-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) \
|
||||
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
|
||||
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
|
||||
-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\" \
|
||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
|
||||
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
|
||||
-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\"
|
||||
|
||||
mutter_built_sources = \
|
||||
$(dbus_idle_built_sources) \
|
||||
$(dbus_display_config_built_sources) \
|
||||
$(dbus_login1_built_sources) \
|
||||
mutter-enum-types.h \
|
||||
mutter-enum-types.c \
|
||||
mutter-enum-types.c
|
||||
|
||||
if HAVE_WAYLAND
|
||||
mutter_built_sources += \
|
||||
gtk-shell-protocol.c \
|
||||
gtk-shell-server-protocol.h \
|
||||
xdg-shell-protocol.c \
|
||||
xdg-shell-server-protocol.h
|
||||
endif
|
||||
|
||||
wayland_protocols = \
|
||||
wayland/protocol/gtk-shell.xml \
|
||||
@@ -48,7 +54,7 @@ wayland_protocols = \
|
||||
|
||||
libmutter_la_SOURCES = \
|
||||
backends/meta-backend.c \
|
||||
backends/meta-backend.h \
|
||||
meta/meta-backend.h \
|
||||
backends/meta-backend-private.h \
|
||||
backends/meta-cursor.c \
|
||||
backends/meta-cursor.h \
|
||||
@@ -68,20 +74,14 @@ libmutter_la_SOURCES = \
|
||||
backends/meta-monitor-manager.h \
|
||||
backends/meta-monitor-manager-dummy.c \
|
||||
backends/meta-monitor-manager-dummy.h \
|
||||
backends/meta-stage.h \
|
||||
backends/meta-stage.c \
|
||||
backends/edid-parse.c \
|
||||
backends/edid.h \
|
||||
backends/native/meta-backend-native.c \
|
||||
backends/native/meta-backend-native.h \
|
||||
backends/native/meta-cursor-renderer-native.c \
|
||||
backends/native/meta-cursor-renderer-native.h \
|
||||
backends/native/meta-idle-monitor-native.c \
|
||||
backends/native/meta-idle-monitor-native.h \
|
||||
backends/native/meta-monitor-manager-kms.c \
|
||||
backends/native/meta-monitor-manager-kms.h \
|
||||
backends/native/meta-launcher.c \
|
||||
backends/native/meta-launcher.h \
|
||||
backends/x11/meta-backend-x11.c \
|
||||
backends/x11/meta-backend-x11.h \
|
||||
backends/x11/meta-cursor-renderer-x11.c \
|
||||
backends/x11/meta-cursor-renderer-x11.h \
|
||||
backends/x11/meta-idle-monitor-xsync.c \
|
||||
backends/x11/meta-idle-monitor-xsync.h \
|
||||
backends/x11/meta-monitor-manager-xrandr.c \
|
||||
@@ -102,8 +102,10 @@ libmutter_la_SOURCES = \
|
||||
compositor/compositor.c \
|
||||
compositor/compositor-private.h \
|
||||
compositor/meta-background.c \
|
||||
compositor/meta-background-private.h \
|
||||
compositor/meta-background-actor.c \
|
||||
compositor/meta-background-actor-private.h \
|
||||
compositor/meta-background-image.c \
|
||||
compositor/meta-background-group.c \
|
||||
compositor/meta-cullable.c \
|
||||
compositor/meta-cullable.h \
|
||||
@@ -120,10 +122,6 @@ libmutter_la_SOURCES = \
|
||||
compositor/meta-surface-actor.h \
|
||||
compositor/meta-surface-actor-x11.c \
|
||||
compositor/meta-surface-actor-x11.h \
|
||||
compositor/meta-surface-actor-wayland.c \
|
||||
compositor/meta-surface-actor-wayland.h \
|
||||
compositor/meta-stage.h \
|
||||
compositor/meta-stage.c \
|
||||
compositor/meta-texture-rectangle.c \
|
||||
compositor/meta-texture-rectangle.h \
|
||||
compositor/meta-texture-tower.c \
|
||||
@@ -139,6 +137,7 @@ libmutter_la_SOURCES = \
|
||||
meta/compositor.h \
|
||||
meta/meta-background.h \
|
||||
meta/meta-background-actor.h \
|
||||
meta/meta-background-image.h \
|
||||
meta/meta-background-group.h \
|
||||
meta/meta-plugin.h \
|
||||
meta/meta-shadow-factory.h \
|
||||
@@ -161,6 +160,8 @@ libmutter_la_SOURCES = \
|
||||
core/frame.h \
|
||||
ui/gradient.c \
|
||||
meta/gradient.h \
|
||||
core/meta-gesture-tracker.c \
|
||||
core/meta-gesture-tracker-private.h \
|
||||
core/keybindings.c \
|
||||
core/keybindings-private.h \
|
||||
core/main.c \
|
||||
@@ -172,6 +173,7 @@ libmutter_la_SOURCES = \
|
||||
core/screen-private.h \
|
||||
meta/screen.h \
|
||||
meta/types.h \
|
||||
core/restart.c \
|
||||
core/stack.c \
|
||||
core/stack.h \
|
||||
core/stack-tracker.c \
|
||||
@@ -189,10 +191,6 @@ libmutter_la_SOURCES = \
|
||||
ui/ui.h \
|
||||
ui/frames.c \
|
||||
ui/frames.h \
|
||||
ui/menu.c \
|
||||
ui/menu.h \
|
||||
ui/metaaccellabel.c \
|
||||
ui/metaaccellabel.h \
|
||||
ui/resizepopup.c \
|
||||
ui/resizepopup.h \
|
||||
ui/theme-parser.c \
|
||||
@@ -204,6 +202,8 @@ libmutter_la_SOURCES = \
|
||||
x11/iconcache.h \
|
||||
x11/async-getprop.c \
|
||||
x11/async-getprop.h \
|
||||
x11/events.c \
|
||||
x11/events.h \
|
||||
x11/group-private.h \
|
||||
x11/group-props.c \
|
||||
x11/group-props.h \
|
||||
@@ -218,7 +218,12 @@ libmutter_la_SOURCES = \
|
||||
x11/window-x11-private.h \
|
||||
x11/xprops.c \
|
||||
x11/xprops.h \
|
||||
x11/mutter-Xatomtype.h \
|
||||
x11/mutter-Xatomtype.h
|
||||
|
||||
if HAVE_WAYLAND
|
||||
libmutter_la_SOURCES += \
|
||||
compositor/meta-surface-actor-wayland.c \
|
||||
compositor/meta-surface-actor-wayland.h \
|
||||
wayland/meta-wayland.c \
|
||||
wayland/meta-wayland.h \
|
||||
wayland/meta-wayland-private.h \
|
||||
@@ -233,6 +238,8 @@ libmutter_la_SOURCES = \
|
||||
wayland/meta-wayland-pointer.h \
|
||||
wayland/meta-wayland-seat.c \
|
||||
wayland/meta-wayland-seat.h \
|
||||
wayland/meta-wayland-touch.c \
|
||||
wayland/meta-wayland-touch.h \
|
||||
wayland/meta-wayland-surface.c \
|
||||
wayland/meta-wayland-surface.h \
|
||||
wayland/meta-wayland-types.h \
|
||||
@@ -241,16 +248,33 @@ libmutter_la_SOURCES = \
|
||||
wayland/meta-wayland-outputs.h \
|
||||
wayland/window-wayland.c \
|
||||
wayland/window-wayland.h
|
||||
endif
|
||||
|
||||
if HAVE_NATIVE_BACKEND
|
||||
libmutter_la_SOURCES += \
|
||||
backends/native/meta-backend-native.c \
|
||||
backends/native/meta-backend-native.h \
|
||||
backends/native/meta-cursor-renderer-native.c \
|
||||
backends/native/meta-cursor-renderer-native.h \
|
||||
backends/native/meta-idle-monitor-native.c \
|
||||
backends/native/meta-idle-monitor-native.h \
|
||||
backends/native/meta-monitor-manager-kms.c \
|
||||
backends/native/meta-monitor-manager-kms.h \
|
||||
backends/native/meta-launcher.c \
|
||||
backends/native/meta-launcher.h \
|
||||
backends/native/dbus-utils.c \
|
||||
backends/native/dbus-utils.h
|
||||
endif
|
||||
|
||||
nodist_libmutter_la_SOURCES = \
|
||||
$(mutter_built_sources)
|
||||
|
||||
libmutter_la_LDFLAGS = -no-undefined
|
||||
libmutter_la_LIBADD = $(MUTTER_LIBS)
|
||||
libmutter_la_LIBADD = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS)
|
||||
|
||||
# Headers installed for plugins; introspected information will
|
||||
# be extracted into Mutter-<version>.gir
|
||||
libmutterinclude_base_headers = \
|
||||
libmutterinclude_headers = \
|
||||
meta/barrier.h \
|
||||
meta/boxes.h \
|
||||
meta/common.h \
|
||||
@@ -262,9 +286,11 @@ libmutterinclude_base_headers = \
|
||||
meta/group.h \
|
||||
meta/keybindings.h \
|
||||
meta/main.h \
|
||||
meta/meta-background-actor.h \
|
||||
meta/meta-background-group.h \
|
||||
meta/meta-backend.h \
|
||||
meta/meta-background.h \
|
||||
meta/meta-background-actor.h \
|
||||
meta/meta-background-image.h \
|
||||
meta/meta-background-group.h \
|
||||
meta/meta-cursor-tracker.h \
|
||||
meta/meta-idle-monitor.h \
|
||||
meta/meta-plugin.h \
|
||||
@@ -279,6 +305,13 @@ libmutterinclude_base_headers = \
|
||||
meta/window.h \
|
||||
meta/workspace.h
|
||||
|
||||
libmutterinclude_built_headers = \
|
||||
meta/meta-version.h
|
||||
|
||||
libmutterinclude_base_headers = \
|
||||
$(libmutterinclude_headers) \
|
||||
$(libmutterinclude_built_headers)
|
||||
|
||||
# Excluded from scanning for introspection but installed
|
||||
# atomnames.h: macros cause problems for scanning process
|
||||
libmutterinclude_extra_headers = \
|
||||
@@ -287,26 +320,23 @@ libmutterinclude_extra_headers = \
|
||||
libmutterincludedir = $(includedir)/mutter/meta
|
||||
|
||||
libmutterinclude_HEADERS = \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(libmutterinclude_headers) \
|
||||
$(libmutterinclude_extra_headers)
|
||||
|
||||
nodist_libmutterinclude_HEADERS = \
|
||||
$(libmutterinclude_built_headers)
|
||||
|
||||
bin_PROGRAMS=mutter
|
||||
noinst_PROGRAMS=
|
||||
|
||||
mutter_SOURCES = core/mutter.c
|
||||
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
|
||||
bin_PROGRAMS+=mutter-launch
|
||||
libexec_PROGRAMS = mutter-restart-helper
|
||||
mutter_restart_helper_SOURCES = core/restart-helper.c
|
||||
mutter_restart_helper_LDADD = $(MUTTER_LIBS)
|
||||
|
||||
mutter_launch_SOURCES = \
|
||||
backends/native/weston-launch.c \
|
||||
backends/native/weston-launch.h
|
||||
|
||||
mutter_launch_CFLAGS = $(MUTTER_LAUNCH_CFLAGS) -DLIBDIR=\"$(libdir)\"
|
||||
mutter_launch_LDFLAGS = $(MUTTER_LAUNCH_LIBS) -lpam
|
||||
|
||||
install-exec-hook:
|
||||
-chown root $(DESTDIR)$(bindir)/mutter-launch
|
||||
-chmod u+s $(DESTDIR)$(bindir)/mutter-launch
|
||||
include Makefile-tests.am
|
||||
|
||||
if HAVE_INTROSPECTION
|
||||
include $(INTROSPECTION_MAKEFILE)
|
||||
@@ -331,7 +361,7 @@ INTROSPECTION_GIRS = Meta-$(api_version).gir
|
||||
Meta-$(api_version).gir: libmutter.la
|
||||
@META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0
|
||||
@META_GIR@_EXPORT_PACKAGES = libmutter
|
||||
@META_GIR@_CFLAGS = $(INCLUDES)
|
||||
@META_GIR@_CFLAGS = $(AM_CPPFLAGS)
|
||||
@META_GIR@_LIBS = libmutter.la
|
||||
@META_GIR@_FILES = \
|
||||
mutter-enum-types.h \
|
||||
@@ -341,70 +371,32 @@ Meta-$(api_version).gir: libmutter.la
|
||||
|
||||
endif
|
||||
|
||||
testboxes_SOURCES = core/testboxes.c
|
||||
testgradient_SOURCES = ui/testgradient.c
|
||||
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
|
||||
|
||||
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
|
||||
|
||||
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
desktopfilesdir=$(datadir)/applications
|
||||
desktopfiles_in_files=mutter.desktop.in
|
||||
desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop)
|
||||
desktopfiles_DATA = $(desktopfiles_files)
|
||||
|
||||
xmldir = @GNOME_KEYBINDINGS_KEYSDIR@
|
||||
xml_in_files = \
|
||||
50-mutter-navigation.xml.in \
|
||||
50-mutter-system.xml.in \
|
||||
50-mutter-windows.xml.in
|
||||
xml_DATA = $(xml_in_files:.xml.in=.xml)
|
||||
|
||||
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
|
||||
|
||||
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml org.gnome.mutter.wayland.gschema.xml
|
||||
@INTLTOOL_XML_NOMERGE_RULE@
|
||||
@GSETTINGS_RULES@
|
||||
|
||||
convertdir = $(datadir)/GConf/gsettings
|
||||
convert_DATA = mutter-schemas.convert
|
||||
|
||||
CLEANFILES = \
|
||||
mutter.desktop \
|
||||
mutter-wm.desktop \
|
||||
org.gnome.mutter.gschema.xml \
|
||||
org.gnome.mutter.wayland.gschema.xml \
|
||||
$(xml_DATA) \
|
||||
$(mutter_built_sources) \
|
||||
$(typelib_DATA) \
|
||||
$(gir_DATA)
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
DISTCLEANFILES = \
|
||||
$(libmutterinclude_built_headers)
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libmutter.pc
|
||||
|
||||
EXTRA_DIST=$(desktopfiles_files) \
|
||||
$(wmproperties_files) \
|
||||
$(IMAGES) \
|
||||
$(desktopfiles_in_files) \
|
||||
$(wmproperties_in_files) \
|
||||
$(xml_in_files) \
|
||||
EXTRA_DIST += \
|
||||
$(wayland_protocols) \
|
||||
org.gnome.mutter.gschema.xml.in \
|
||||
org.gnome.mutter.wayland.gschema.xml.in \
|
||||
mutter-schemas.convert \
|
||||
libmutter.pc.in \
|
||||
mutter-enum-types.h.in \
|
||||
mutter-enum-types.c.in \
|
||||
org.freedesktop.login1.xml \
|
||||
org.gnome.Mutter.DisplayConfig.xml \
|
||||
org.gnome.Mutter.IdleMonitor.xml
|
||||
|
||||
BUILT_SOURCES = $(mutter_built_sources)
|
||||
BUILT_SOURCES = \
|
||||
$(mutter_built_sources) \
|
||||
$(libmutterinclude_built_headers)
|
||||
|
||||
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
|
||||
CLEANFILES += $(MUTTER_STAMP_FILES)
|
||||
|
||||
@@ -444,6 +436,15 @@ $(dbus_idle_built_sources) : Makefile.am org.gnome.Mutter.IdleMonitor.xml
|
||||
--c-generate-object-manager \
|
||||
$(srcdir)/org.gnome.Mutter.IdleMonitor.xml
|
||||
|
||||
dbus_login1_built_sources = meta-dbus-login1.c meta-dbus-login1.h
|
||||
|
||||
$(dbus_login1_built_sources) : Makefile.am org.freedesktop.login1.xml
|
||||
$(AM_V_GEN)gdbus-codegen \
|
||||
--interface-prefix org.freedesktop.login1 \
|
||||
--c-namespace Login1 \
|
||||
--generate-c-code meta-dbus-login1 \
|
||||
$(srcdir)/org.freedesktop.login1.xml
|
||||
|
||||
%-protocol.c : $(srcdir)/wayland/protocol/%.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
|
||||
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
|
||||
|
@@ -179,7 +179,7 @@ decode_display_parameters (const uchar *edid, MonitorInfo *info)
|
||||
else if (edid[0x16] == 0)
|
||||
{
|
||||
info->width_mm = -1;
|
||||
info->height_mm = -1;
|
||||
info->height_mm = -1;
|
||||
info->aspect_ratio = 100.0 / (edid[0x15] + 99);
|
||||
}
|
||||
else if (edid[0x15] == 0)
|
||||
@@ -267,7 +267,7 @@ decode_color_characteristics (const uchar *edid, MonitorInfo *info)
|
||||
static int
|
||||
decode_established_timings (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
static const Timing established[][8] =
|
||||
static const Timing established[][8] =
|
||||
{
|
||||
{
|
||||
{ 800, 600, 60 },
|
||||
|
@@ -1,9 +1,9 @@
|
||||
/* edid.h
|
||||
*
|
||||
* Copyright 2007, 2008, Red Hat, Inc.
|
||||
*
|
||||
*
|
||||
* This file is part of the Gnome Library.
|
||||
*
|
||||
*
|
||||
* The Gnome Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
@@ -13,12 +13,12 @@
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with the Gnome Library; see the file COPYING.LIB. If not,
|
||||
* write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
* Author: Soren Sandmann <sandmann@redhat.com>
|
||||
*/
|
||||
|
||||
@@ -177,7 +177,7 @@ struct MonitorInfo
|
||||
DetailedTiming detailed_timings[4]; /* If monitor has a preferred
|
||||
* mode, it is the first one
|
||||
* (whether it has, is
|
||||
* determined by the
|
||||
* determined by the
|
||||
* preferred_timing_includes
|
||||
* bit.
|
||||
*/
|
||||
@@ -189,7 +189,5 @@ struct MonitorInfo
|
||||
};
|
||||
|
||||
MonitorInfo *decode_edid (const uchar *data);
|
||||
char *make_display_name (const MonitorInfo *info);
|
||||
char *make_display_size_string (int width_mm, int height_mm);
|
||||
|
||||
#endif
|
||||
|
@@ -28,7 +28,15 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "meta-backend.h"
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
#include <meta/meta-backend.h>
|
||||
#include <meta/meta-idle-monitor.h>
|
||||
#include "meta-cursor-renderer.h"
|
||||
#include "meta-monitor-manager.h"
|
||||
|
||||
#define DEFAULT_XKB_RULES_FILE "evdev"
|
||||
#define DEFAULT_XKB_MODEL "pc105+inet"
|
||||
|
||||
#define META_TYPE_BACKEND (meta_backend_get_type ())
|
||||
#define META_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND, MetaBackend))
|
||||
@@ -62,6 +70,41 @@ struct _MetaBackendClass
|
||||
gboolean (* ungrab_device) (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp);
|
||||
|
||||
void (* warp_pointer) (MetaBackend *backend,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
void (* set_keymap) (MetaBackend *backend,
|
||||
const char *layouts,
|
||||
const char *variants,
|
||||
const char *options);
|
||||
|
||||
struct xkb_keymap * (* get_keymap) (MetaBackend *backend);
|
||||
|
||||
void (* lock_layout_group) (MetaBackend *backend,
|
||||
guint idx);
|
||||
|
||||
void (* update_screen_size) (MetaBackend *backend, int width, int height);
|
||||
void (* select_stage_events) (MetaBackend *backend);
|
||||
};
|
||||
|
||||
MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,
|
||||
int device_id);
|
||||
MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend);
|
||||
MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend);
|
||||
|
||||
gboolean meta_backend_grab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp);
|
||||
gboolean meta_backend_ungrab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp);
|
||||
|
||||
void meta_backend_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
struct xkb_keymap * meta_backend_get_keymap (MetaBackend *backend);
|
||||
|
||||
#endif /* META_BACKEND_PRIVATE_H */
|
||||
|
@@ -24,16 +24,25 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-backend.h"
|
||||
#include <meta/meta-backend.h>
|
||||
#include "meta-backend-private.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include "meta-stage.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#endif
|
||||
|
||||
static MetaBackend *_backend;
|
||||
|
||||
/**
|
||||
* meta_get_backend:
|
||||
*
|
||||
* Accessor for the singleton MetaBackend.
|
||||
*
|
||||
* Returns: (transfer none): The only #MetaBackend there is.
|
||||
*/
|
||||
MetaBackend *
|
||||
meta_get_backend (void)
|
||||
{
|
||||
@@ -44,6 +53,8 @@ struct _MetaBackendPrivate
|
||||
{
|
||||
MetaMonitorManager *monitor_manager;
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
|
||||
ClutterActor *stage;
|
||||
};
|
||||
typedef struct _MetaBackendPrivate MetaBackendPrivate;
|
||||
|
||||
@@ -67,13 +78,121 @@ meta_backend_finalize (GObject *object)
|
||||
G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_sync_screen_size (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
int width, height;
|
||||
|
||||
meta_monitor_manager_get_screen_size (priv->monitor_manager, &width, &height);
|
||||
|
||||
META_BACKEND_GET_CLASS (backend)->update_screen_size (backend, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
on_monitors_changed (MetaMonitorManager *monitors,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaBackend *backend = META_BACKEND (user_data);
|
||||
meta_backend_sync_screen_size (backend);
|
||||
}
|
||||
|
||||
static MetaIdleMonitor *
|
||||
meta_backend_create_idle_monitor (MetaBackend *backend,
|
||||
int device_id)
|
||||
{
|
||||
return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id);
|
||||
}
|
||||
|
||||
static void
|
||||
create_device_monitor (MetaBackend *backend,
|
||||
int device_id)
|
||||
{
|
||||
g_assert (backend->device_monitors[device_id] == NULL);
|
||||
|
||||
backend->device_monitors[device_id] = meta_backend_create_idle_monitor (backend, device_id);
|
||||
backend->device_id_max = MAX (backend->device_id_max, device_id);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_device_monitor (MetaBackend *backend,
|
||||
int device_id)
|
||||
{
|
||||
g_clear_object (&backend->device_monitors[device_id]);
|
||||
|
||||
if (device_id == backend->device_id_max)
|
||||
{
|
||||
/* Reset the max device ID */
|
||||
int i, new_max = 0;
|
||||
for (i = 0; i < backend->device_id_max; i++)
|
||||
if (backend->device_monitors[i] != NULL)
|
||||
new_max = i;
|
||||
backend->device_id_max = new_max;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_device_added (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDevice *device,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaBackend *backend = META_BACKEND (user_data);
|
||||
int device_id = clutter_input_device_get_device_id (device);
|
||||
|
||||
create_device_monitor (backend, device_id);
|
||||
}
|
||||
|
||||
static void
|
||||
on_device_removed (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDevice *device,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaBackend *backend = META_BACKEND (user_data);
|
||||
int device_id = clutter_input_device_get_device_id (device);
|
||||
|
||||
destroy_device_monitor (backend, device_id);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_real_post_init (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend);
|
||||
priv->stage = meta_stage_new ();
|
||||
clutter_actor_realize (priv->stage);
|
||||
META_BACKEND_GET_CLASS (backend)->select_stage_events (backend);
|
||||
|
||||
priv->monitor_manager = META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend);
|
||||
|
||||
g_signal_connect (priv->monitor_manager, "monitors-changed",
|
||||
G_CALLBACK (on_monitors_changed), backend);
|
||||
meta_backend_sync_screen_size (backend);
|
||||
|
||||
priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend);
|
||||
|
||||
{
|
||||
ClutterDeviceManager *manager;
|
||||
GSList *devices, *l;
|
||||
|
||||
/* Create the core device monitor. */
|
||||
create_device_monitor (backend, 0);
|
||||
|
||||
manager = clutter_device_manager_get_default ();
|
||||
g_signal_connect_object (manager, "device-added",
|
||||
G_CALLBACK (on_device_added), backend, 0);
|
||||
g_signal_connect_object (manager, "device-removed",
|
||||
G_CALLBACK (on_device_removed), backend, 0);
|
||||
|
||||
devices = clutter_device_manager_list_devices (manager);
|
||||
|
||||
for (l = devices; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterInputDevice *device = l->data;
|
||||
on_device_added (manager, device, backend);
|
||||
}
|
||||
|
||||
g_slist_free (devices);
|
||||
}
|
||||
}
|
||||
|
||||
static MetaCursorRenderer *
|
||||
@@ -100,6 +219,21 @@ meta_backend_real_ungrab_device (MetaBackend *backend,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_real_update_screen_size (MetaBackend *backend,
|
||||
int width, int height)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
clutter_actor_set_size (priv->stage, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_real_select_stage_events (MetaBackend *backend)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_class_init (MetaBackendClass *klass)
|
||||
{
|
||||
@@ -111,6 +245,21 @@ meta_backend_class_init (MetaBackendClass *klass)
|
||||
klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer;
|
||||
klass->grab_device = meta_backend_real_grab_device;
|
||||
klass->ungrab_device = meta_backend_real_ungrab_device;
|
||||
klass->update_screen_size = meta_backend_real_update_screen_size;
|
||||
klass->select_stage_events = meta_backend_real_select_stage_events;
|
||||
|
||||
g_signal_new ("keymap-changed",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
g_signal_new ("keymap-layout-group-changed",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, G_TYPE_UINT);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -119,44 +268,27 @@ meta_backend_init (MetaBackend *backend)
|
||||
_backend = backend;
|
||||
}
|
||||
|
||||
/* FIXME -- destroy device monitors at some point */
|
||||
G_GNUC_UNUSED static void
|
||||
destroy_device_monitor (MetaBackend *backend,
|
||||
int device_id)
|
||||
{
|
||||
g_clear_object (&backend->device_monitors[device_id]);
|
||||
if (device_id == backend->device_id_max)
|
||||
backend->device_id_max--;
|
||||
}
|
||||
|
||||
static MetaIdleMonitor *
|
||||
meta_backend_create_idle_monitor (MetaBackend *backend,
|
||||
int device_id)
|
||||
{
|
||||
return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_post_init (MetaBackend *backend)
|
||||
{
|
||||
META_BACKEND_GET_CLASS (backend)->post_init (backend);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_get_idle_monitor: (skip)
|
||||
*/
|
||||
MetaIdleMonitor *
|
||||
meta_backend_get_idle_monitor (MetaBackend *backend,
|
||||
int device_id)
|
||||
{
|
||||
g_return_val_if_fail (device_id >= 0 && device_id < 256, NULL);
|
||||
|
||||
if (!backend->device_monitors[device_id])
|
||||
{
|
||||
backend->device_monitors[device_id] = meta_backend_create_idle_monitor (backend, device_id);
|
||||
backend->device_id_max = MAX (backend->device_id_max, device_id);
|
||||
}
|
||||
|
||||
return backend->device_monitors[device_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_get_monitor_manager: (skip)
|
||||
*/
|
||||
MetaMonitorManager *
|
||||
meta_backend_get_monitor_manager (MetaBackend *backend)
|
||||
{
|
||||
@@ -165,6 +297,9 @@ meta_backend_get_monitor_manager (MetaBackend *backend)
|
||||
return priv->monitor_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_get_cursor_renderer: (skip)
|
||||
*/
|
||||
MetaCursorRenderer *
|
||||
meta_backend_get_cursor_renderer (MetaBackend *backend)
|
||||
{
|
||||
@@ -173,6 +308,9 @@ meta_backend_get_cursor_renderer (MetaBackend *backend)
|
||||
return priv->cursor_renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_grab_device: (skip)
|
||||
*/
|
||||
gboolean
|
||||
meta_backend_grab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
@@ -181,6 +319,9 @@ meta_backend_grab_device (MetaBackend *backend,
|
||||
return META_BACKEND_GET_CLASS (backend)->grab_device (backend, device_id, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_ungrab_device: (skip)
|
||||
*/
|
||||
gboolean
|
||||
meta_backend_ungrab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
@@ -189,6 +330,58 @@ meta_backend_ungrab_device (MetaBackend *backend,
|
||||
return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_warp_pointer: (skip)
|
||||
*/
|
||||
void
|
||||
meta_backend_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
META_BACKEND_GET_CLASS (backend)->warp_pointer (backend, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_backend_set_keymap (MetaBackend *backend,
|
||||
const char *layouts,
|
||||
const char *variants,
|
||||
const char *options)
|
||||
{
|
||||
META_BACKEND_GET_CLASS (backend)->set_keymap (backend, layouts, variants, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_get_keymap: (skip)
|
||||
*/
|
||||
struct xkb_keymap *
|
||||
meta_backend_get_keymap (MetaBackend *backend)
|
||||
|
||||
{
|
||||
return META_BACKEND_GET_CLASS (backend)->get_keymap (backend);
|
||||
}
|
||||
|
||||
void
|
||||
meta_backend_lock_layout_group (MetaBackend *backend,
|
||||
guint idx)
|
||||
{
|
||||
META_BACKEND_GET_CLASS (backend)->lock_layout_group (backend, idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_get_stage:
|
||||
* @backend: A #MetaBackend
|
||||
*
|
||||
* Gets the global #ClutterStage that's managed by this backend.
|
||||
*
|
||||
* Returns: (transfer none): the #ClutterStage
|
||||
*/
|
||||
ClutterActor *
|
||||
meta_backend_get_stage (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
return priv->stage;
|
||||
}
|
||||
|
||||
static GType
|
||||
get_backend_type (void)
|
||||
{
|
||||
@@ -197,7 +390,7 @@ get_backend_type (void)
|
||||
return META_TYPE_BACKEND_X11;
|
||||
#endif
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
return META_TYPE_BACKEND_NATIVE;
|
||||
#endif
|
||||
@@ -261,9 +454,13 @@ static GSourceFuncs event_funcs = {
|
||||
event_dispatch
|
||||
};
|
||||
|
||||
/**
|
||||
* meta_clutter_init: (skip)
|
||||
*/
|
||||
void
|
||||
meta_clutter_init (void)
|
||||
{
|
||||
ClutterSettings *clutter_settings;
|
||||
GSource *source;
|
||||
|
||||
meta_create_backend ();
|
||||
@@ -271,6 +468,13 @@ meta_clutter_init (void)
|
||||
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
|
||||
g_error ("Unable to initialize Clutter.\n");
|
||||
|
||||
/*
|
||||
* XXX: We cannot handle high dpi scaling yet, so fix the scale to 1
|
||||
* for now.
|
||||
*/
|
||||
clutter_settings = clutter_settings_get_default ();
|
||||
g_object_set (clutter_settings, "window-scaling-factor", 1, NULL);
|
||||
|
||||
source = g_source_new (&event_funcs, sizeof (GSource));
|
||||
g_source_attach (source, NULL);
|
||||
g_source_unref (source);
|
||||
|
@@ -27,20 +27,21 @@
|
||||
#include "meta-cursor-renderer.h"
|
||||
#include "meta-cursor-private.h"
|
||||
|
||||
#include <meta/meta-backend.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "meta-stage.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
struct _MetaCursorRendererPrivate
|
||||
{
|
||||
int current_x, current_y;
|
||||
MetaRectangle current_rect;
|
||||
|
||||
MetaCursorReference *displayed_cursor;
|
||||
gboolean handled_by_backend;
|
||||
};
|
||||
typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
|
||||
|
||||
@@ -50,26 +51,26 @@ static void
|
||||
queue_redraw (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
ClutterActor *stage = compositor->stage;
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
ClutterActor *stage = meta_backend_get_stage (backend);
|
||||
CoglTexture *texture;
|
||||
|
||||
/* During early initialization, we can have no stage */
|
||||
if (!stage)
|
||||
return;
|
||||
|
||||
/* If we're not using a MetaStage, quit early */
|
||||
if (!META_IS_STAGE (stage))
|
||||
return;
|
||||
if (priv->displayed_cursor && !priv->handled_by_backend)
|
||||
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, NULL, NULL);
|
||||
else
|
||||
texture = NULL;
|
||||
|
||||
meta_stage_set_cursor (META_STAGE (stage),
|
||||
priv->displayed_cursor,
|
||||
&priv->current_rect);
|
||||
meta_stage_set_cursor (META_STAGE (stage), texture, &priv->current_rect);
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
queue_redraw (renderer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -87,6 +88,8 @@ static void
|
||||
update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
gboolean handled_by_backend;
|
||||
gboolean should_redraw = FALSE;
|
||||
|
||||
if (priv->displayed_cursor)
|
||||
{
|
||||
@@ -108,7 +111,18 @@ update_cursor (MetaCursorRenderer *renderer)
|
||||
priv->current_rect.height = 0;
|
||||
}
|
||||
|
||||
META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer);
|
||||
handled_by_backend = META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer);
|
||||
if (handled_by_backend != priv->handled_by_backend)
|
||||
{
|
||||
priv->handled_by_backend = handled_by_backend;
|
||||
should_redraw = TRUE;
|
||||
}
|
||||
|
||||
if (!handled_by_backend)
|
||||
should_redraw = TRUE;
|
||||
|
||||
if (should_redraw)
|
||||
queue_redraw (renderer);
|
||||
}
|
||||
|
||||
MetaCursorRenderer *
|
||||
|
@@ -51,7 +51,7 @@ struct _MetaCursorRendererClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* update_cursor) (MetaCursorRenderer *renderer);
|
||||
gboolean (* update_cursor) (MetaCursorRenderer *renderer);
|
||||
};
|
||||
|
||||
GType meta_cursor_renderer_get_type (void) G_GNUC_CONST;
|
||||
|
@@ -23,8 +23,6 @@
|
||||
#define META_CURSOR_TRACKER_PRIVATE_H
|
||||
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
#include <wayland-server.h>
|
||||
#include <gbm.h>
|
||||
|
||||
#include "meta-cursor.h"
|
||||
#include "meta-cursor-renderer.h"
|
||||
@@ -32,28 +30,13 @@
|
||||
struct _MetaCursorTracker {
|
||||
GObject parent_instance;
|
||||
|
||||
MetaScreen *screen;
|
||||
MetaCursorRenderer *renderer;
|
||||
|
||||
gboolean is_showing;
|
||||
|
||||
/* The cursor tracker stores the cursor for the current grab
|
||||
* operation, the cursor for the window with pointer focus, and
|
||||
* the cursor for the root window, which contains either the
|
||||
* default arrow cursor or the 'busy' hourglass if we're launching
|
||||
* an app.
|
||||
*
|
||||
* We choose the first one available -- if there's a grab cursor,
|
||||
* we choose that cursor, if there's window cursor, we choose that,
|
||||
* otherwise we choose the root cursor.
|
||||
*
|
||||
* The displayed_cursor contains the chosen cursor.
|
||||
*/
|
||||
MetaCursorReference *displayed_cursor;
|
||||
|
||||
MetaCursorReference *grab_cursor;
|
||||
|
||||
/* Wayland clients can set a NULL buffer as their cursor
|
||||
/* Wayland clients can set a NULL buffer as their cursor
|
||||
* explicitly, which means that we shouldn't display anything.
|
||||
* So, we can't simply store a NULL in window_cursor to
|
||||
* determine an unset window cursor; we need an extra boolean.
|
||||
@@ -62,6 +45,9 @@ struct _MetaCursorTracker {
|
||||
MetaCursorReference *window_cursor;
|
||||
|
||||
MetaCursorReference *root_cursor;
|
||||
|
||||
/* The cursor from the X11 server. */
|
||||
MetaCursorReference *xfixes_cursor;
|
||||
};
|
||||
|
||||
struct _MetaCursorTrackerClass {
|
||||
@@ -71,8 +57,6 @@ struct _MetaCursorTrackerClass {
|
||||
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||
XEvent *xevent);
|
||||
|
||||
void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor);
|
||||
void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor);
|
||||
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
|
||||
|
@@ -1,8 +1,8 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
/*
|
||||
* Copyright 2013 Red Hat, Inc.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@@ -12,7 +12,7 @@
|
||||
* 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/>.
|
||||
*
|
||||
@@ -34,25 +34,21 @@
|
||||
#include <meta/errors.h>
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include "meta-backend.h"
|
||||
#include "meta-backend-private.h"
|
||||
|
||||
#include "meta-cursor-private.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "screen-private.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
|
||||
|
||||
enum {
|
||||
CURSOR_CHANGED,
|
||||
LAST_SIGNAL
|
||||
CURSOR_CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
@@ -60,14 +56,16 @@ static guint signals[LAST_SIGNAL];
|
||||
static MetaCursorReference *
|
||||
get_displayed_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
if (!tracker->is_showing)
|
||||
return NULL;
|
||||
|
||||
if (tracker->grab_cursor)
|
||||
return tracker->grab_cursor;
|
||||
|
||||
if (tracker->has_window_cursor)
|
||||
return tracker->window_cursor;
|
||||
if (meta_display_windows_are_interactable (display))
|
||||
{
|
||||
if (tracker->has_window_cursor)
|
||||
return tracker->window_cursor;
|
||||
}
|
||||
|
||||
return tracker->root_cursor;
|
||||
}
|
||||
@@ -97,11 +95,9 @@ sync_cursor (MetaCursorTracker *tracker)
|
||||
static void
|
||||
meta_cursor_tracker_init (MetaCursorTracker *self)
|
||||
{
|
||||
/* (JS) Best (?) that can be assumed since XFixes doesn't provide a way of
|
||||
detecting if the system mouse cursor is showing or not.
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
On wayland we start with the cursor showing
|
||||
*/
|
||||
self->renderer = meta_backend_get_cursor_renderer (backend);
|
||||
self->is_showing = TRUE;
|
||||
}
|
||||
|
||||
@@ -134,47 +130,9 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
make_wayland_cursor_tracker (MetaScreen *screen)
|
||||
meta_cursor_tracker_new (void)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaWaylandCompositor *compositor;
|
||||
MetaCursorTracker *self;
|
||||
|
||||
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||
self->screen = screen;
|
||||
self->renderer = meta_backend_get_cursor_renderer (backend);
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
compositor->seat->pointer.cursor_tracker = self;
|
||||
meta_cursor_tracker_update_position (self, 0, 0);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
make_x11_cursor_tracker (MetaScreen *screen)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaCursorTracker *self;
|
||||
|
||||
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||
self->screen = screen;
|
||||
self->renderer = meta_backend_get_cursor_renderer (backend);
|
||||
|
||||
XFixesSelectCursorInput (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
XFixesDisplayCursorNotifyMask);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
meta_cursor_tracker_new (MetaScreen *screen)
|
||||
{
|
||||
if (meta_is_wayland_compositor ())
|
||||
return make_wayland_cursor_tracker (screen);
|
||||
else
|
||||
return make_x11_cursor_tracker (screen);
|
||||
return g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||
}
|
||||
|
||||
static MetaCursorTracker *_cursor_tracker;
|
||||
@@ -191,7 +149,7 @@ MetaCursorTracker *
|
||||
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
|
||||
{
|
||||
if (!_cursor_tracker)
|
||||
_cursor_tracker = meta_cursor_tracker_new (screen);
|
||||
_cursor_tracker = meta_cursor_tracker_new ();
|
||||
|
||||
return _cursor_tracker;
|
||||
}
|
||||
@@ -212,19 +170,20 @@ gboolean
|
||||
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||
XEvent *xevent)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
XFixesCursorNotifyEvent *notify_event;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
return FALSE;
|
||||
|
||||
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
|
||||
if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify)
|
||||
return FALSE;
|
||||
|
||||
notify_event = (XFixesCursorNotifyEvent *)xevent;
|
||||
if (notify_event->subtype != XFixesDisplayCursorNotify)
|
||||
return FALSE;
|
||||
|
||||
set_window_cursor (tracker, FALSE, NULL);
|
||||
g_clear_pointer (&tracker->xfixes_cursor, meta_cursor_reference_unref);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -248,16 +207,17 @@ meta_cursor_reference_take_texture (CoglTexture2D *texture,
|
||||
static void
|
||||
ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
XFixesCursorImage *cursor_image;
|
||||
CoglTexture2D *sprite;
|
||||
guint8 *cursor_data;
|
||||
gboolean free_cursor_data;
|
||||
CoglContext *ctx;
|
||||
|
||||
if (tracker->has_window_cursor)
|
||||
if (tracker->xfixes_cursor)
|
||||
return;
|
||||
|
||||
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
|
||||
cursor_image = XFixesGetCursorImage (display->xdisplay);
|
||||
if (!cursor_image)
|
||||
return;
|
||||
|
||||
@@ -304,7 +264,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||
MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite,
|
||||
cursor_image->xhot,
|
||||
cursor_image->yhot);
|
||||
set_window_cursor (tracker, TRUE, cursor);
|
||||
tracker->xfixes_cursor = cursor;
|
||||
}
|
||||
XFree (cursor_image);
|
||||
}
|
||||
@@ -317,13 +277,22 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||
CoglTexture *
|
||||
meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaCursorReference *cursor;
|
||||
|
||||
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
ensure_xfixes_cursor (tracker);
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
cursor = tracker->displayed_cursor;
|
||||
}
|
||||
else
|
||||
{
|
||||
ensure_xfixes_cursor (tracker);
|
||||
cursor = tracker->xfixes_cursor;
|
||||
}
|
||||
|
||||
if (tracker->displayed_cursor)
|
||||
return meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL);
|
||||
if (cursor)
|
||||
return meta_cursor_reference_get_cogl_texture (cursor, NULL, NULL);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
@@ -340,13 +309,22 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
||||
int *x,
|
||||
int *y)
|
||||
{
|
||||
MetaCursorReference *cursor;
|
||||
|
||||
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
ensure_xfixes_cursor (tracker);
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
cursor = tracker->displayed_cursor;
|
||||
}
|
||||
else
|
||||
{
|
||||
ensure_xfixes_cursor (tracker);
|
||||
cursor = tracker->xfixes_cursor;
|
||||
}
|
||||
|
||||
if (tracker->displayed_cursor)
|
||||
meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, x, y);
|
||||
if (cursor)
|
||||
meta_cursor_reference_get_cogl_texture (cursor, x, y);
|
||||
else
|
||||
{
|
||||
if (x)
|
||||
@@ -356,17 +334,6 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor)
|
||||
{
|
||||
g_clear_pointer (&tracker->grab_cursor, meta_cursor_reference_unref);
|
||||
if (cursor)
|
||||
tracker->grab_cursor = meta_cursor_reference_ref (cursor);
|
||||
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor)
|
||||
@@ -466,19 +433,7 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
|
||||
return;
|
||||
tracker->is_showing = visible;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (visible)
|
||||
XFixesShowCursor (tracker->screen->display->xdisplay,
|
||||
tracker->screen->xroot);
|
||||
else
|
||||
XFixesHideCursor (tracker->screen->display->xdisplay,
|
||||
tracker->screen->xroot);
|
||||
}
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
|
@@ -27,8 +27,11 @@
|
||||
|
||||
#include "display-private.h"
|
||||
#include "screen-private.h"
|
||||
#include "meta-backend.h"
|
||||
#include "meta-backend-private.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include "backends/native/meta-cursor-renderer-native.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -36,7 +39,9 @@
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#endif
|
||||
|
||||
MetaCursorReference *
|
||||
meta_cursor_reference_ref (MetaCursorReference *self)
|
||||
@@ -171,13 +176,15 @@ meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
|
||||
static struct gbm_device *
|
||||
get_gbm_device (void)
|
||||
{
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *meta_backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
|
||||
|
||||
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
|
||||
return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
|
||||
else
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -242,6 +249,7 @@ meta_cursor_reference_from_theme (MetaCursor cursor)
|
||||
return self;
|
||||
}
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
static void
|
||||
meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
struct wl_resource *buffer,
|
||||
@@ -340,6 +348,7 @@ meta_cursor_reference_from_buffer (struct wl_resource *buffer,
|
||||
|
||||
return self;
|
||||
}
|
||||
#endif
|
||||
|
||||
CoglTexture *
|
||||
meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
|
||||
|
@@ -28,13 +28,15 @@ MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
|
||||
void meta_cursor_reference_unref (MetaCursorReference *cursor);
|
||||
|
||||
#include <meta/common.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
MetaCursorReference * meta_cursor_reference_from_theme (MetaCursor cursor);
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include <wayland-server.h>
|
||||
MetaCursorReference * meta_cursor_reference_from_buffer (struct wl_resource *buffer,
|
||||
int hot_x,
|
||||
int hot_y);
|
||||
#endif
|
||||
|
||||
MetaCursor meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor);
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat Inc.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@@ -11,7 +11,7 @@
|
||||
* 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/>.
|
||||
*/
|
||||
|
@@ -180,6 +180,9 @@ create_monitor_skeleton (GDBusObjectManagerServer *manager,
|
||||
meta_dbus_object_skeleton_set_idle_monitor (object, skeleton);
|
||||
|
||||
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
|
||||
|
||||
g_object_unref (skeleton);
|
||||
g_object_unref (object);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -1,8 +1,8 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
/*
|
||||
* Copyright 2013 Red Hat, Inc.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@@ -12,7 +12,7 @@
|
||||
* 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/>.
|
||||
*
|
||||
|
@@ -1,8 +1,8 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
/*
|
||||
* Copyright 2013 Red Hat, Inc.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@@ -12,7 +12,7 @@
|
||||
* 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/>.
|
||||
*
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <meta/meta-idle-monitor.h>
|
||||
#include "meta-idle-monitor-private.h"
|
||||
#include "meta-idle-monitor-dbus.h"
|
||||
#include "meta-backend.h"
|
||||
#include "meta-backend-private.h"
|
||||
|
||||
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
|
||||
|
||||
@@ -210,9 +210,9 @@ make_watch (MetaIdleMonitor *monitor,
|
||||
* meta_idle_monitor_add_idle_watch:
|
||||
* @monitor: A #MetaIdleMonitor
|
||||
* @interval_msec: The idletime interval, in milliseconds
|
||||
* @callback: (allow-none): The callback to call when the user has
|
||||
* @callback: (nullable): The callback to call when the user has
|
||||
* accumulated @interval_msec milliseconds of idle time.
|
||||
* @user_data: (allow-none): The user data to pass to the callback
|
||||
* @user_data: (nullable): The user data to pass to the callback
|
||||
* @notify: A #GDestroyNotify
|
||||
*
|
||||
* Returns: a watch id
|
||||
@@ -252,9 +252,9 @@ meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
|
||||
/**
|
||||
* meta_idle_monitor_add_user_active_watch:
|
||||
* @monitor: A #MetaIdleMonitor
|
||||
* @callback: (allow-none): The callback to call when the user is
|
||||
* @callback: (nullable): The callback to call when the user is
|
||||
* active again.
|
||||
* @user_data: (allow-none): The user data to pass to the callback
|
||||
* @user_data: (nullable): The user data to pass to the callback
|
||||
* @notify: A #GDestroyNotify
|
||||
*
|
||||
* Returns: a watch id
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2001, 2002 Havoc Pennington
|
||||
* Copyright (C) 2002, 2003 Red Hat Inc.
|
||||
* Some ICCCM manager selection code derived from fvwm2,
|
||||
@@ -8,7 +8,7 @@
|
||||
* Copyright (C) 2003 Rob Adams
|
||||
* Copyright (C) 2004-2006 Elijah Newren
|
||||
* Copyright (C) 2013 Red Hat Inc.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@@ -18,7 +18,7 @@
|
||||
* 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/>.
|
||||
*/
|
||||
@@ -60,7 +60,7 @@ typedef struct {
|
||||
gboolean enabled;
|
||||
MetaRectangle rect;
|
||||
float refresh_rate;
|
||||
enum wl_output_transform transform;
|
||||
MetaMonitorTransform transform;
|
||||
|
||||
gboolean is_primary;
|
||||
gboolean is_presentation;
|
||||
@@ -78,6 +78,7 @@ struct _MetaMonitorConfig {
|
||||
GHashTable *configs;
|
||||
MetaConfiguration *current;
|
||||
gboolean current_is_stored;
|
||||
gboolean current_is_for_laptop_lid;
|
||||
MetaConfiguration *previous;
|
||||
|
||||
GFile *file;
|
||||
@@ -570,7 +571,7 @@ is_all_whitespace (const char *text,
|
||||
gsize text_len)
|
||||
{
|
||||
gsize i;
|
||||
|
||||
|
||||
for (i = 0; i < text_len; i++)
|
||||
if (!g_ascii_isspace (text[i]))
|
||||
return FALSE;
|
||||
@@ -655,20 +656,20 @@ handle_text (GMarkupParseContext *context,
|
||||
else if (strcmp (parser->output_field, "rotation") == 0)
|
||||
{
|
||||
if (strncmp (text, "normal", text_len) == 0)
|
||||
parser->output.transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
parser->output.transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
else if (strncmp (text, "left", text_len) == 0)
|
||||
parser->output.transform = WL_OUTPUT_TRANSFORM_90;
|
||||
parser->output.transform = META_MONITOR_TRANSFORM_90;
|
||||
else if (strncmp (text, "upside_down", text_len) == 0)
|
||||
parser->output.transform = WL_OUTPUT_TRANSFORM_180;
|
||||
parser->output.transform = META_MONITOR_TRANSFORM_180;
|
||||
else if (strncmp (text, "right", text_len) == 0)
|
||||
parser->output.transform = WL_OUTPUT_TRANSFORM_270;
|
||||
parser->output.transform = META_MONITOR_TRANSFORM_270;
|
||||
else
|
||||
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
|
||||
"Invalid rotation type %.*s", (int)text_len, text);
|
||||
}
|
||||
else if (strcmp (parser->output_field, "reflect_x") == 0)
|
||||
parser->output.transform += read_bool (text, text_len, error) ?
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED : 0;
|
||||
META_MONITOR_TRANSFORM_FLIPPED : 0;
|
||||
else if (strcmp (parser->output_field, "reflect_y") == 0)
|
||||
{
|
||||
/* FIXME (look at the rotation map in monitor.c) */
|
||||
@@ -877,7 +878,8 @@ apply_configuration (MetaMonitorConfig *self,
|
||||
|
||||
/* Stored (persistent) configurations override the previous one always.
|
||||
Also, we clear the previous configuration if the current one (which is
|
||||
about to become previous) is stored.
|
||||
about to become previous) is stored, or if the current one has
|
||||
different outputs.
|
||||
*/
|
||||
if (stored ||
|
||||
(self->current && self->current_is_stored))
|
||||
@@ -888,11 +890,27 @@ apply_configuration (MetaMonitorConfig *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
self->previous = self->current;
|
||||
/* Despite the name, config_equal() only checks the set of outputs,
|
||||
not their modes
|
||||
*/
|
||||
if (self->current && config_equal (self->current, config))
|
||||
{
|
||||
self->previous = self->current;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self->current)
|
||||
config_free (self->current);
|
||||
self->previous = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
self->current = config;
|
||||
self->current_is_stored = stored;
|
||||
/* If true, we'll be overridden at the end of this call
|
||||
inside turn_off_laptop_display()
|
||||
*/
|
||||
self->current_is_for_laptop_lid = FALSE;
|
||||
|
||||
if (self->current == self->previous)
|
||||
self->previous = NULL;
|
||||
@@ -1009,8 +1027,16 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
|
||||
if (self->lid_is_closed &&
|
||||
stored->n_outputs > 1 &&
|
||||
laptop_display_is_on (stored))
|
||||
return apply_configuration (self, make_laptop_lid_config (stored),
|
||||
manager, FALSE);
|
||||
{
|
||||
if (apply_configuration (self, make_laptop_lid_config (stored),
|
||||
manager, FALSE))
|
||||
{
|
||||
self->current_is_for_laptop_lid = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
return apply_configuration (self, stored, manager, TRUE);
|
||||
}
|
||||
@@ -1089,7 +1115,7 @@ make_default_config (MetaMonitorConfig *self,
|
||||
ret->outputs[0].rect.width = outputs[0].preferred_mode->width;
|
||||
ret->outputs[0].rect.height = outputs[0].preferred_mode->height;
|
||||
ret->outputs[0].refresh_rate = outputs[0].preferred_mode->refresh_rate;
|
||||
ret->outputs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret->outputs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[0].is_primary = TRUE;
|
||||
|
||||
return ret;
|
||||
@@ -1141,7 +1167,7 @@ make_default_config (MetaMonitorConfig *self,
|
||||
ret->outputs[j].rect.width = outputs[0].preferred_mode->width;
|
||||
ret->outputs[j].rect.height = outputs[0].preferred_mode->height;
|
||||
ret->outputs[j].refresh_rate = outputs[0].preferred_mode->refresh_rate;
|
||||
ret->outputs[j].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret->outputs[j].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[j].is_primary = FALSE;
|
||||
ret->outputs[j].is_presentation = FALSE;
|
||||
}
|
||||
@@ -1176,7 +1202,7 @@ make_default_config (MetaMonitorConfig *self,
|
||||
ret->outputs[i].rect.width = output->preferred_mode->width;
|
||||
ret->outputs[i].rect.height = output->preferred_mode->height;
|
||||
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
|
||||
ret->outputs[i].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[i].is_primary = (output == primary);
|
||||
|
||||
/* Disable outputs that would go beyond framebuffer limits */
|
||||
@@ -1224,7 +1250,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
|
||||
ret->outputs[i].rect.width = output->preferred_mode->width;
|
||||
ret->outputs[i].rect.height = output->preferred_mode->height;
|
||||
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
|
||||
ret->outputs[i].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[i].is_primary = TRUE;
|
||||
}
|
||||
else
|
||||
@@ -1357,6 +1383,7 @@ turn_off_laptop_display (MetaMonitorConfig *self,
|
||||
|
||||
new = make_laptop_lid_config (self->current);
|
||||
apply_configuration (self, new, manager, FALSE);
|
||||
self->current_is_for_laptop_lid = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1376,7 +1403,7 @@ power_client_changed_cb (UpClient *client,
|
||||
|
||||
if (is_closed)
|
||||
turn_off_laptop_display (self, manager);
|
||||
else
|
||||
else if (self->current_is_for_laptop_lid)
|
||||
meta_monitor_config_restore_previous (self, manager);
|
||||
}
|
||||
}
|
||||
@@ -1485,7 +1512,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
|
||||
output->rect.x,
|
||||
output->rect.y,
|
||||
rotation_map[output->transform & 0x3],
|
||||
output->transform >= WL_OUTPUT_TRANSFORM_FLIPPED ? "yes" : "no",
|
||||
output->transform >= META_MONITOR_TRANSFORM_FLIPPED ? "yes" : "no",
|
||||
output->is_primary ? "yes" : "no",
|
||||
output->is_presentation ? "yes" : "no");
|
||||
}
|
||||
@@ -1594,13 +1621,13 @@ output_supports_mode (MetaOutput *output,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
crtc_assignment_assign (CrtcAssignment *assign,
|
||||
MetaCRTC *crtc,
|
||||
MetaMonitorMode *mode,
|
||||
int x,
|
||||
int y,
|
||||
enum wl_output_transform transform,
|
||||
MetaOutput *output)
|
||||
crtc_assignment_assign (CrtcAssignment *assign,
|
||||
MetaCRTC *crtc,
|
||||
MetaMonitorMode *mode,
|
||||
int x,
|
||||
int y,
|
||||
MetaMonitorTransform transform,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc);
|
||||
|
||||
@@ -1762,7 +1789,6 @@ real_assign_crtcs (CrtcAssignment *assignment,
|
||||
output_config->transform,
|
||||
pass);
|
||||
|
||||
|
||||
if (crtc_assignment_assign (assignment, crtc, &modes[j],
|
||||
output_config->rect.x, output_config->rect.y,
|
||||
output_config->transform,
|
||||
|
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "meta-monitor-manager-dummy.h"
|
||||
|
||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
|
||||
struct _MetaMonitorManagerDummy
|
||||
{
|
||||
@@ -66,8 +66,8 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
|
||||
manager->crtcs[0].rect.width = manager->modes[0].width;
|
||||
manager->crtcs[0].rect.height = manager->modes[0].height;
|
||||
manager->crtcs[0].current_mode = &manager->modes[0];
|
||||
manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
|
||||
manager->crtcs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
manager->crtcs[0].all_transforms = ALL_TRANSFORMS;
|
||||
manager->crtcs[0].is_dirty = FALSE;
|
||||
manager->crtcs[0].logical_monitor = NULL;
|
||||
|
||||
@@ -75,7 +75,7 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
|
||||
manager->n_outputs = 1;
|
||||
|
||||
manager->outputs[0].crtc = &manager->crtcs[0];
|
||||
manager->outputs[0].output_id = 1;
|
||||
manager->outputs[0].winsys_id = 1;
|
||||
manager->outputs[0].name = g_strdup ("LVDS");
|
||||
manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
|
||||
manager->outputs[0].product = g_strdup ("unknown");
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2001, 2002 Havoc Pennington
|
||||
* Copyright (C) 2002, 2003 Red Hat Inc.
|
||||
* Some ICCCM manager selection code derived from fvwm2,
|
||||
@@ -8,7 +8,7 @@
|
||||
* Copyright (C) 2003 Rob Adams
|
||||
* Copyright (C) 2004-2006 Elijah Newren
|
||||
* Copyright (C) 2013 Red Hat Inc.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@@ -18,7 +18,7 @@
|
||||
* 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/>.
|
||||
*/
|
||||
@@ -37,7 +37,7 @@
|
||||
#include <meta/errors.h>
|
||||
#include "meta-monitor-config.h"
|
||||
#include "backends/x11/meta-monitor-manager-xrandr.h"
|
||||
#include "meta-backend.h"
|
||||
#include "meta-backend-private.h"
|
||||
|
||||
enum {
|
||||
CONFIRM_DISPLAY_CHANGE,
|
||||
@@ -125,7 +125,7 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
*/
|
||||
info.is_presentation = TRUE;
|
||||
info.in_fullscreen = -1;
|
||||
info.output_id = 0;
|
||||
info.winsys_id = 0;
|
||||
|
||||
g_array_append_val (monitor_infos, info);
|
||||
|
||||
@@ -156,8 +156,8 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
info->is_primary = info->is_primary || output->is_primary;
|
||||
info->is_presentation = info->is_presentation && output->is_presentation;
|
||||
|
||||
if (output->is_primary || info->output_id == 0)
|
||||
info->output_id = output->output_id;
|
||||
if (output->is_primary || info->winsys_id == 0)
|
||||
info->winsys_id = output->winsys_id;
|
||||
|
||||
if (info->is_primary)
|
||||
manager->primary_monitor_index = info->number;
|
||||
@@ -477,7 +477,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
GVariantBuilder transforms;
|
||||
|
||||
g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au"));
|
||||
for (j = 0; j <= WL_OUTPUT_TRANSFORM_FLIPPED_270; j++)
|
||||
for (j = 0; j <= META_MONITOR_TRANSFORM_FLIPPED_270; j++)
|
||||
if (crtc->all_transforms & (1 << j))
|
||||
g_variant_builder_add (&transforms, "u", j);
|
||||
|
||||
@@ -560,7 +560,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
|
||||
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
|
||||
i, /* ID */
|
||||
(gint64)output->output_id,
|
||||
(gint64)output->winsys_id,
|
||||
(int)(output->crtc ? output->crtc - manager->crtcs : -1),
|
||||
&crtcs,
|
||||
output->name,
|
||||
@@ -667,7 +667,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
int new_mode, x, y;
|
||||
int new_screen_width, new_screen_height;
|
||||
guint transform;
|
||||
guint output_id;
|
||||
guint output_index;
|
||||
GPtrArray *crtc_infos, *output_infos;
|
||||
|
||||
if (serial != manager->serial)
|
||||
@@ -694,7 +694,6 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
MetaOutput *first_output;
|
||||
MetaCRTC *crtc;
|
||||
MetaMonitorMode *mode;
|
||||
guint output_id;
|
||||
|
||||
crtc_info = g_slice_new (MetaCRTCInfo);
|
||||
crtc_info->outputs = g_ptr_array_new ();
|
||||
@@ -756,8 +755,8 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
crtc_info->y = 0;
|
||||
}
|
||||
|
||||
if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
|
||||
transform > WL_OUTPUT_TRANSFORM_FLIPPED_270 ||
|
||||
if (transform < META_MONITOR_TRANSFORM_NORMAL ||
|
||||
transform > META_MONITOR_TRANSFORM_FLIPPED_270 ||
|
||||
((crtc->all_transforms & (1 << transform)) == 0))
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
@@ -768,18 +767,18 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
crtc_info->transform = transform;
|
||||
|
||||
first_output = NULL;
|
||||
while (g_variant_iter_loop (nested_outputs, "u", &output_id))
|
||||
while (g_variant_iter_loop (nested_outputs, "u", &output_index))
|
||||
{
|
||||
MetaOutput *output;
|
||||
|
||||
if (output_id >= manager->n_outputs)
|
||||
if (output_index >= manager->n_outputs)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid output id");
|
||||
return TRUE;
|
||||
}
|
||||
output = &manager->outputs[output_id];
|
||||
output = &manager->outputs[output_index];
|
||||
|
||||
if (!output_can_config (output, crtc, mode))
|
||||
{
|
||||
@@ -824,12 +823,12 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
}
|
||||
|
||||
g_variant_iter_init (&output_iter, outputs);
|
||||
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_id, &properties))
|
||||
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_index, &properties))
|
||||
{
|
||||
MetaOutputInfo *output_info;
|
||||
gboolean primary, presentation;
|
||||
|
||||
if (output_id >= manager->n_outputs)
|
||||
if (output_index >= manager->n_outputs)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_INVALID_ARGS,
|
||||
@@ -838,7 +837,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
}
|
||||
|
||||
output_info = g_slice_new0 (MetaOutputInfo);
|
||||
output_info->output = &manager->outputs[output_id];
|
||||
output_info->output = &manager->outputs[output_index];
|
||||
|
||||
if (g_variant_lookup (properties, "primary", "b", &primary))
|
||||
output_info->is_primary = primary;
|
||||
@@ -852,7 +851,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
/* If we were in progress of making a persistent change and we see a
|
||||
new request, it's likely that the old one failed in some way, so
|
||||
don't save it, but also don't queue for restoring it.
|
||||
*/
|
||||
*/
|
||||
if (manager->persistent_timeout_id && persistent)
|
||||
{
|
||||
g_source_remove (manager->persistent_timeout_id);
|
||||
@@ -909,7 +908,7 @@ static gboolean
|
||||
meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
|
||||
GDBusMethodInvocation *invocation,
|
||||
guint serial,
|
||||
guint output_id,
|
||||
guint output_index,
|
||||
gint value)
|
||||
{
|
||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
|
||||
@@ -923,14 +922,14 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (output_id >= manager->n_outputs)
|
||||
if (output_index >= manager->n_outputs)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid output id");
|
||||
return TRUE;
|
||||
}
|
||||
output = &manager->outputs[output_id];
|
||||
output = &manager->outputs[output_index];
|
||||
|
||||
if (value < 0 || value > 100)
|
||||
{
|
||||
|
@@ -12,12 +12,12 @@
|
||||
* at MetaScreen instead.
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
* Copyright (C) 2003 Rob Adams
|
||||
* Copyright (C) 2004-2006 Elijah Newren
|
||||
* Copyright (C) 2013 Red Hat Inc.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@@ -27,7 +27,7 @@
|
||||
* 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/>.
|
||||
*/
|
||||
@@ -41,8 +41,6 @@
|
||||
#include "display-private.h"
|
||||
#include <meta/screen.h>
|
||||
#include "stack-tracker.h"
|
||||
#include "ui.h"
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "meta-display-config-shared.h"
|
||||
#include "meta-dbus-display-config.h"
|
||||
@@ -60,12 +58,23 @@ typedef struct _MetaMonitorInfo MetaMonitorInfo;
|
||||
typedef struct _MetaCRTCInfo MetaCRTCInfo;
|
||||
typedef struct _MetaOutputInfo MetaOutputInfo;
|
||||
|
||||
typedef enum {
|
||||
META_MONITOR_TRANSFORM_NORMAL,
|
||||
META_MONITOR_TRANSFORM_90,
|
||||
META_MONITOR_TRANSFORM_180,
|
||||
META_MONITOR_TRANSFORM_270,
|
||||
META_MONITOR_TRANSFORM_FLIPPED,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_90,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_180,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_270,
|
||||
} MetaMonitorTransform;
|
||||
|
||||
struct _MetaOutput
|
||||
{
|
||||
/* The CRTC driving this output, NULL if the output is not enabled */
|
||||
MetaCRTC *crtc;
|
||||
/* The low-level ID of this output, used to apply back configuration */
|
||||
glong output_id;
|
||||
glong winsys_id;
|
||||
char *name;
|
||||
char *vendor;
|
||||
char *product;
|
||||
@@ -73,6 +82,7 @@ struct _MetaOutput
|
||||
int width_mm;
|
||||
int height_mm;
|
||||
CoglSubpixelOrder subpixel_order;
|
||||
int scale;
|
||||
|
||||
MetaMonitorMode *preferred_mode;
|
||||
MetaMonitorMode **modes;
|
||||
@@ -113,7 +123,7 @@ struct _MetaCRTC
|
||||
glong crtc_id;
|
||||
MetaRectangle rect;
|
||||
MetaMonitorMode *current_mode;
|
||||
enum wl_output_transform transform;
|
||||
MetaMonitorTransform transform;
|
||||
unsigned int all_transforms;
|
||||
|
||||
/* Only used to build the logical configuration
|
||||
@@ -161,14 +171,14 @@ struct _MetaMonitorInfo
|
||||
gboolean in_fullscreen;
|
||||
|
||||
/* The primary or first output for this monitor, 0 if we can't figure out.
|
||||
It can be matched to an output_id of a MetaOutput.
|
||||
It can be matched to a winsys_id of a MetaOutput.
|
||||
|
||||
This is used as an opaque token on reconfiguration when switching from
|
||||
clone to extened, to decide on what output the windows should go next
|
||||
(it's an attempt to keep windows on the same monitor, and preferably on
|
||||
the primary one).
|
||||
*/
|
||||
glong output_id;
|
||||
glong winsys_id;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -184,7 +194,7 @@ struct _MetaCRTCInfo {
|
||||
MetaMonitorMode *mode;
|
||||
int x;
|
||||
int y;
|
||||
enum wl_output_transform transform;
|
||||
MetaMonitorTransform transform;
|
||||
GPtrArray *outputs;
|
||||
};
|
||||
|
||||
@@ -338,7 +348,7 @@ gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorMana
|
||||
/* Returns true if transform causes width and height to be inverted
|
||||
This is true for the odd transforms in the enum */
|
||||
static inline gboolean
|
||||
meta_monitor_transform_is_rotated (enum wl_output_transform transform)
|
||||
meta_monitor_transform_is_rotated (MetaMonitorTransform transform)
|
||||
{
|
||||
return (transform % 2);
|
||||
}
|
||||
|
@@ -25,35 +25,85 @@
|
||||
#include "meta-stage.h"
|
||||
|
||||
#include "meta-cursor-private.h"
|
||||
#include "meta-backend.h"
|
||||
#include <meta/meta-backend.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
struct _MetaStagePrivate {
|
||||
CoglPipeline *pipeline;
|
||||
gboolean should_paint_cursor;
|
||||
typedef struct {
|
||||
gboolean enabled;
|
||||
|
||||
MetaCursorReference *cursor;
|
||||
CoglPipeline *pipeline;
|
||||
CoglTexture *texture;
|
||||
|
||||
MetaRectangle current_rect;
|
||||
MetaRectangle previous_rect;
|
||||
gboolean previous_is_valid;
|
||||
} MetaOverlay;
|
||||
|
||||
struct _MetaStagePrivate {
|
||||
MetaOverlay cursor_overlay;
|
||||
};
|
||||
typedef struct _MetaStagePrivate MetaStagePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE);
|
||||
|
||||
static void
|
||||
update_pipeline (MetaStage *stage)
|
||||
meta_overlay_init (MetaOverlay *overlay)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
|
||||
if (priv->cursor)
|
||||
overlay->pipeline = cogl_pipeline_new (ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_overlay_free (MetaOverlay *overlay)
|
||||
{
|
||||
if (overlay->pipeline)
|
||||
cogl_object_unref (overlay->pipeline);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_overlay_set (MetaOverlay *overlay,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
if (overlay->texture != texture)
|
||||
{
|
||||
CoglTexture *texture = meta_cursor_reference_get_cogl_texture (priv->cursor, NULL, NULL);
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
|
||||
overlay->texture = texture;
|
||||
|
||||
if (texture)
|
||||
{
|
||||
cogl_pipeline_set_layer_texture (overlay->pipeline, 0, texture);
|
||||
overlay->enabled = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
cogl_pipeline_set_layer_texture (overlay->pipeline, 0, NULL);
|
||||
overlay->enabled = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, NULL);
|
||||
|
||||
overlay->current_rect = *rect;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_overlay_paint (MetaOverlay *overlay)
|
||||
{
|
||||
if (!overlay->enabled)
|
||||
return;
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
|
||||
overlay->pipeline,
|
||||
overlay->current_rect.x,
|
||||
overlay->current_rect.y,
|
||||
overlay->current_rect.x +
|
||||
overlay->current_rect.width,
|
||||
overlay->current_rect.y +
|
||||
overlay->current_rect.height);
|
||||
|
||||
overlay->previous_rect = overlay->current_rect;
|
||||
overlay->previous_is_valid = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -62,42 +112,18 @@ meta_stage_finalize (GObject *object)
|
||||
MetaStage *stage = META_STAGE (object);
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
if (priv->pipeline)
|
||||
cogl_object_unref (priv->pipeline);
|
||||
}
|
||||
|
||||
static void
|
||||
paint_cursor (MetaStage *stage)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
if (!priv->cursor)
|
||||
return;
|
||||
|
||||
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
|
||||
priv->pipeline,
|
||||
priv->current_rect.x,
|
||||
priv->current_rect.y,
|
||||
priv->current_rect.x +
|
||||
priv->current_rect.width,
|
||||
priv->current_rect.y +
|
||||
priv->current_rect.height);
|
||||
|
||||
priv->previous_rect = priv->current_rect;
|
||||
priv->previous_is_valid = TRUE;
|
||||
meta_overlay_free (&priv->cursor_overlay);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaStage *stage = META_STAGE (actor);
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
paint_cursor (stage);
|
||||
meta_overlay_paint (&priv->cursor_overlay);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -114,10 +140,9 @@ meta_stage_class_init (MetaStageClass *klass)
|
||||
static void
|
||||
meta_stage_init (MetaStage *stage)
|
||||
{
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
priv->pipeline = cogl_pipeline_new (ctx);
|
||||
meta_overlay_init (&priv->cursor_overlay);
|
||||
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
|
||||
}
|
||||
@@ -131,46 +156,42 @@ meta_stage_new (void)
|
||||
}
|
||||
|
||||
static void
|
||||
queue_redraw (MetaStage *stage)
|
||||
queue_redraw_for_overlay (MetaStage *stage,
|
||||
MetaOverlay *overlay)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
cairo_rectangle_int_t clip;
|
||||
|
||||
/* Clear the location the cursor was at before, if we need to. */
|
||||
if (priv->previous_is_valid)
|
||||
/* Clear the location the overlay was at before, if we need to. */
|
||||
if (overlay->previous_is_valid)
|
||||
{
|
||||
clip.x = priv->previous_rect.x;
|
||||
clip.y = priv->previous_rect.y;
|
||||
clip.width = priv->previous_rect.width;
|
||||
clip.height = priv->previous_rect.height;
|
||||
clip.x = overlay->previous_rect.x;
|
||||
clip.y = overlay->previous_rect.y;
|
||||
clip.width = overlay->previous_rect.width;
|
||||
clip.height = overlay->previous_rect.height;
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
|
||||
priv->previous_is_valid = FALSE;
|
||||
overlay->previous_is_valid = FALSE;
|
||||
}
|
||||
|
||||
/* And queue a redraw for the current cursor location. */
|
||||
if (priv->cursor)
|
||||
/* Draw the overlay at the new position */
|
||||
if (overlay->enabled)
|
||||
{
|
||||
clip.x = priv->current_rect.x;
|
||||
clip.y = priv->current_rect.y;
|
||||
clip.width = priv->current_rect.width;
|
||||
clip.height = priv->current_rect.height;
|
||||
clip.x = overlay->current_rect.x;
|
||||
clip.y = overlay->current_rect.y;
|
||||
clip.width = overlay->current_rect.width;
|
||||
clip.height = overlay->current_rect.height;
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_set_cursor (MetaStage *stage,
|
||||
MetaCursorReference *cursor,
|
||||
MetaRectangle *rect)
|
||||
meta_stage_set_cursor (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
if (priv->cursor != cursor)
|
||||
{
|
||||
priv->cursor = cursor;
|
||||
update_pipeline (stage);
|
||||
}
|
||||
g_assert (meta_is_wayland_compositor () || texture == NULL);
|
||||
|
||||
priv->current_rect = *rect;
|
||||
queue_redraw (stage);
|
||||
meta_overlay_set (&priv->cursor_overlay, texture, rect);
|
||||
queue_redraw_for_overlay (stage, &priv->cursor_overlay);
|
||||
}
|
@@ -51,9 +51,9 @@ GType meta_stage_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *meta_stage_new (void);
|
||||
|
||||
void meta_stage_set_cursor (MetaStage *stage,
|
||||
MetaCursorReference *cursor,
|
||||
MetaRectangle *rect);
|
||||
void meta_stage_set_cursor (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* META_STAGE_H */
|
107
src/backends/native/dbus-utils.c
Normal file
107
src/backends/native/dbus-utils.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "dbus-utils.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/* Stolen from tp_escape_as_identifier, from tp-glib,
|
||||
* which follows the same escaping convention as systemd.
|
||||
*/
|
||||
static inline gboolean
|
||||
_esc_ident_bad (gchar c, gboolean is_first)
|
||||
{
|
||||
return ((c < 'a' || c > 'z') &&
|
||||
(c < 'A' || c > 'Z') &&
|
||||
(c < '0' || c > '9' || is_first));
|
||||
}
|
||||
|
||||
static gchar *
|
||||
escape_dbus_component (const gchar *name)
|
||||
{
|
||||
gboolean bad = FALSE;
|
||||
size_t len = 0;
|
||||
GString *op;
|
||||
const gchar *ptr, *first_ok;
|
||||
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
/* fast path for empty name */
|
||||
if (name[0] == '\0')
|
||||
return g_strdup ("_");
|
||||
|
||||
for (ptr = name; *ptr; ptr++)
|
||||
{
|
||||
if (_esc_ident_bad (*ptr, ptr == name))
|
||||
{
|
||||
bad = TRUE;
|
||||
len += 3;
|
||||
}
|
||||
else
|
||||
len++;
|
||||
}
|
||||
|
||||
/* fast path if it's clean */
|
||||
if (!bad)
|
||||
return g_strdup (name);
|
||||
|
||||
/* If strictly less than ptr, first_ok is the first uncopied safe character.
|
||||
*/
|
||||
first_ok = name;
|
||||
op = g_string_sized_new (len);
|
||||
for (ptr = name; *ptr; ptr++)
|
||||
{
|
||||
if (_esc_ident_bad (*ptr, ptr == name))
|
||||
{
|
||||
/* copy preceding safe characters if any */
|
||||
if (first_ok < ptr)
|
||||
{
|
||||
g_string_append_len (op, first_ok, ptr - first_ok);
|
||||
}
|
||||
/* escape the unsafe character */
|
||||
g_string_append_printf (op, "_%02x", (unsigned char)(*ptr));
|
||||
/* restart after it */
|
||||
first_ok = ptr + 1;
|
||||
}
|
||||
}
|
||||
/* copy trailing safe characters if any */
|
||||
if (first_ok < ptr)
|
||||
{
|
||||
g_string_append_len (op, first_ok, ptr - first_ok);
|
||||
}
|
||||
return g_string_free (op, FALSE);
|
||||
}
|
||||
|
||||
char *
|
||||
get_escaped_dbus_path (const char *prefix,
|
||||
const char *component)
|
||||
{
|
||||
char *escaped_component = escape_dbus_component (component);
|
||||
char *path = g_strconcat (prefix, "/", escaped_component, NULL);
|
||||
|
||||
g_free (escaped_component);
|
||||
return path;
|
||||
}
|
32
src/backends/native/dbus-utils.h
Normal file
32
src/backends/native/dbus-utils.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef DBUS_UTILS_H
|
||||
#define DBUS_UTILS_H
|
||||
|
||||
char *
|
||||
get_escaped_dbus_path (const char *prefix,
|
||||
const char *component);
|
||||
|
||||
#endif /* DBUS_UTILS_H */
|
@@ -174,6 +174,64 @@ meta_backend_native_create_cursor_renderer (MetaBackend *backend)
|
||||
return g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||
ClutterInputDevice *device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
/* XXX */
|
||||
guint32 time_ = 0;
|
||||
|
||||
clutter_evdev_warp_pointer (device, time_, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_set_keymap (MetaBackend *backend,
|
||||
const char *layouts,
|
||||
const char *variants,
|
||||
const char *options)
|
||||
{
|
||||
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||
struct xkb_rule_names names;
|
||||
struct xkb_keymap *keymap;
|
||||
struct xkb_context *context;
|
||||
|
||||
names.rules = DEFAULT_XKB_RULES_FILE;
|
||||
names.model = DEFAULT_XKB_MODEL;
|
||||
names.layout = layouts;
|
||||
names.variant = variants;
|
||||
names.options = options;
|
||||
|
||||
context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
|
||||
keymap = xkb_keymap_new_from_names (context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
xkb_context_unref (context);
|
||||
|
||||
clutter_evdev_set_keyboard_map (manager, keymap);
|
||||
|
||||
g_signal_emit_by_name (backend, "keymap-changed", 0);
|
||||
|
||||
xkb_keymap_unref (keymap);
|
||||
}
|
||||
|
||||
static struct xkb_keymap *
|
||||
meta_backend_native_get_keymap (MetaBackend *backend)
|
||||
{
|
||||
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||
return clutter_evdev_get_keyboard_map (manager);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_lock_layout_group (MetaBackend *backend,
|
||||
guint idx)
|
||||
{
|
||||
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||
clutter_evdev_set_keyboard_layout_index (manager, idx);
|
||||
g_signal_emit_by_name (backend, "keymap-layout-group-changed", idx, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
||||
{
|
||||
@@ -183,6 +241,11 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
||||
backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor;
|
||||
backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager;
|
||||
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
|
||||
|
||||
backend_class->warp_pointer = meta_backend_native_warp_pointer;
|
||||
backend_class->set_keymap = meta_backend_native_set_keymap;
|
||||
backend_class->get_keymap = meta_backend_native_get_keymap;
|
||||
backend_class->lock_layout_group = meta_backend_native_lock_layout_group;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -120,7 +120,7 @@ update_hw_cursor (MetaCursorRendererNative *native,
|
||||
|
||||
set_crtc_cursor (native, &crtcs[i], crtc_cursor, force);
|
||||
|
||||
if (cursor)
|
||||
if (crtc_cursor)
|
||||
{
|
||||
drmModeMoveCursor (priv->drm_fd, crtcs[i].crtc_id,
|
||||
cursor_rect->x - crtc_rect->x,
|
||||
@@ -140,7 +140,7 @@ should_have_hw_cursor (MetaCursorRenderer *renderer)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
||||
@@ -148,10 +148,7 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer)
|
||||
|
||||
priv->has_hw_cursor = should_have_hw_cursor (renderer);
|
||||
update_hw_cursor (native, FALSE);
|
||||
|
||||
/* Fall back to the stage-based cursor if we don't have HW cursors. */
|
||||
if (!priv->has_hw_cursor)
|
||||
META_CURSOR_RENDERER_CLASS (meta_cursor_renderer_native_parent_class)->update_cursor (renderer);
|
||||
return priv->has_hw_cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -20,9 +20,8 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-launcher.h"
|
||||
#include "weston-launch.h"
|
||||
|
||||
#include <gio/gunixfdmessage.h>
|
||||
#include <gio/gunixfdlist.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/egl/clutter-egl.h>
|
||||
@@ -30,167 +29,59 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <malloc.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#include "backends/meta-backend.h"
|
||||
#include <systemd/sd-login.h>
|
||||
|
||||
#include "dbus-utils.h"
|
||||
#include "meta-dbus-login1.h"
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "meta-cursor-renderer-native.h"
|
||||
|
||||
struct _MetaLauncher
|
||||
{
|
||||
GSocket *weston_launch;
|
||||
Login1Session *session_proxy;
|
||||
Login1Seat *seat_proxy;
|
||||
|
||||
gboolean vt_switched;
|
||||
|
||||
GMainContext *nested_context;
|
||||
GMainLoop *nested_loop;
|
||||
|
||||
GSource *inner_source;
|
||||
GSource *outer_source;
|
||||
gboolean session_active;
|
||||
};
|
||||
|
||||
static void handle_request_vt_switch (MetaLauncher *self);
|
||||
|
||||
static gboolean
|
||||
request_vt_switch_idle (gpointer user_data)
|
||||
static Login1Session *
|
||||
get_session_proxy (GCancellable *cancellable)
|
||||
{
|
||||
handle_request_vt_switch (user_data);
|
||||
char *proxy_path;
|
||||
char *session_id;
|
||||
Login1Session *session_proxy;
|
||||
|
||||
return FALSE;
|
||||
if (sd_pid_get_session (getpid (), &session_id) < 0)
|
||||
return NULL;
|
||||
|
||||
proxy_path = get_escaped_dbus_path ("/org/freedesktop/login1/session", session_id);
|
||||
|
||||
session_proxy = login1_session_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
"org.freedesktop.login1",
|
||||
proxy_path,
|
||||
cancellable, NULL);
|
||||
free (proxy_path);
|
||||
|
||||
return session_proxy;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
send_message_to_wl (MetaLauncher *self,
|
||||
void *message,
|
||||
gsize size,
|
||||
GSocketControlMessage *out_cmsg,
|
||||
GSocketControlMessage **in_cmsg,
|
||||
GError **error)
|
||||
static Login1Seat *
|
||||
get_seat_proxy (GCancellable *cancellable)
|
||||
{
|
||||
struct weston_launcher_reply reply;
|
||||
GInputVector in_iov = { &reply, sizeof (reply) };
|
||||
GOutputVector out_iov = { message, size };
|
||||
GSocketControlMessage *out_all_cmsg[2];
|
||||
GSocketControlMessage **in_all_cmsg;
|
||||
int flags = 0;
|
||||
int i;
|
||||
|
||||
out_all_cmsg[0] = out_cmsg;
|
||||
out_all_cmsg[1] = NULL;
|
||||
if (g_socket_send_message (self->weston_launch, NULL,
|
||||
&out_iov, 1,
|
||||
out_all_cmsg, -1,
|
||||
flags, NULL, error) != (gssize)size)
|
||||
return FALSE;
|
||||
|
||||
if (g_socket_receive_message (self->weston_launch, NULL,
|
||||
&in_iov, 1,
|
||||
&in_all_cmsg, NULL,
|
||||
&flags, NULL, error) != sizeof (reply))
|
||||
return FALSE;
|
||||
|
||||
while (reply.header.opcode != ((struct weston_launcher_message*)message)->opcode)
|
||||
{
|
||||
guint id;
|
||||
|
||||
/* There were events queued */
|
||||
g_assert ((reply.header.opcode & WESTON_LAUNCHER_EVENT) == WESTON_LAUNCHER_EVENT);
|
||||
|
||||
/* This can never happen, because the only time mutter-launch can queue
|
||||
this event is after confirming a VT switch, and we don't make requests
|
||||
during that time.
|
||||
|
||||
Note that getting this event would be really bad, because we would be
|
||||
in the wrong loop/context.
|
||||
*/
|
||||
g_assert (reply.header.opcode != WESTON_LAUNCHER_SERVER_VT_ENTER);
|
||||
|
||||
switch (reply.header.opcode)
|
||||
{
|
||||
case WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH:
|
||||
id = g_idle_add (request_vt_switch_idle, self);
|
||||
g_source_set_name_by_id (id, "[mutter] request_vt_switch_idle");
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
if (g_socket_receive_message (self->weston_launch, NULL,
|
||||
&in_iov, 1,
|
||||
NULL, NULL,
|
||||
&flags, NULL, error) != sizeof (reply))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (reply.ret != 0)
|
||||
{
|
||||
if (reply.ret == -1)
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Got failure from weston-launch");
|
||||
else
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-reply.ret),
|
||||
"Got failure from weston-launch: %s", strerror (-reply.ret));
|
||||
|
||||
for (i = 0; in_all_cmsg && in_all_cmsg[i]; i++)
|
||||
g_object_unref (in_all_cmsg[i]);
|
||||
g_free (in_all_cmsg);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (in_all_cmsg && in_all_cmsg[0])
|
||||
{
|
||||
for (i = 1; in_all_cmsg[i]; i++)
|
||||
g_object_unref (in_all_cmsg[i]);
|
||||
*in_cmsg = in_all_cmsg[0];
|
||||
}
|
||||
|
||||
g_free (in_all_cmsg);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
meta_launcher_open_device (MetaLauncher *self,
|
||||
const char *name,
|
||||
int flags,
|
||||
GError **error)
|
||||
{
|
||||
struct weston_launcher_open *message;
|
||||
GSocketControlMessage *cmsg;
|
||||
gboolean ok;
|
||||
gsize size;
|
||||
int *fds, n_fd;
|
||||
int ret;
|
||||
|
||||
size = sizeof (struct weston_launcher_open) + strlen (name) + 1;
|
||||
message = g_malloc (size);
|
||||
message->header.opcode = WESTON_LAUNCHER_OPEN;
|
||||
message->flags = flags;
|
||||
strcpy (message->path, name);
|
||||
message->path[strlen(name)] = 0;
|
||||
|
||||
ok = send_message_to_wl (self, message, size, NULL, &cmsg, error);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
g_assert (G_IS_UNIX_FD_MESSAGE (cmsg));
|
||||
|
||||
fds = g_unix_fd_message_steal_fds (G_UNIX_FD_MESSAGE (cmsg), &n_fd);
|
||||
g_assert (n_fd == 1);
|
||||
|
||||
ret = fds[0];
|
||||
g_free (fds);
|
||||
g_object_unref (cmsg);
|
||||
}
|
||||
else
|
||||
ret = -1;
|
||||
|
||||
g_free (message);
|
||||
return ret;
|
||||
return login1_seat_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
"org.freedesktop.login1",
|
||||
"/org/freedesktop/login1/seat/self",
|
||||
cancellable, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -206,17 +97,18 @@ session_unpause (void)
|
||||
cogl_kms_display_queue_modes_reset (cogl_display);
|
||||
|
||||
clutter_evdev_reclaim_devices ();
|
||||
clutter_egl_thaw_master_clock ();
|
||||
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (backend);
|
||||
ClutterActor *stage = meta_backend_get_stage (backend);
|
||||
|
||||
/* When we mode-switch back, we need to immediately queue a redraw
|
||||
* in case nothing else queued one for us, and force the cursor to
|
||||
* update. */
|
||||
|
||||
clutter_actor_queue_redraw (compositor->stage);
|
||||
clutter_actor_queue_redraw (stage);
|
||||
meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer));
|
||||
}
|
||||
}
|
||||
@@ -225,6 +117,92 @@ static void
|
||||
session_pause (void)
|
||||
{
|
||||
clutter_evdev_release_devices ();
|
||||
clutter_egl_freeze_master_clock ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
take_device (Login1Session *session_proxy,
|
||||
int dev_major,
|
||||
int dev_minor,
|
||||
int *out_fd,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GVariant *fd_variant = NULL;
|
||||
int fd = -1;
|
||||
GUnixFDList *fd_list;
|
||||
|
||||
if (!login1_session_call_take_device_sync (session_proxy,
|
||||
dev_major,
|
||||
dev_minor,
|
||||
NULL,
|
||||
&fd_variant,
|
||||
NULL, /* paused */
|
||||
&fd_list,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (fd_variant), error);
|
||||
if (fd == -1)
|
||||
goto out;
|
||||
|
||||
*out_fd = fd;
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
if (fd_variant)
|
||||
g_variant_unref (fd_variant);
|
||||
if (fd_list)
|
||||
g_object_unref (fd_list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_device_info_from_path (const char *path,
|
||||
int *out_major,
|
||||
int *out_minor)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int r;
|
||||
struct stat st;
|
||||
|
||||
r = stat (path, &st);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (!S_ISCHR (st.st_mode))
|
||||
goto out;
|
||||
|
||||
*out_major = major (st.st_rdev);
|
||||
*out_minor = minor (st.st_rdev);
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_device_info_from_fd (int fd,
|
||||
int *out_major,
|
||||
int *out_minor)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int r;
|
||||
struct stat st;
|
||||
|
||||
r = fstat (fd, &st);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (!S_ISCHR (st.st_mode))
|
||||
goto out;
|
||||
|
||||
*out_major = major (st.st_rdev);
|
||||
*out_minor = minor (st.st_rdev);
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -233,169 +211,151 @@ on_evdev_device_open (const char *path,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
MetaLauncher *launcher = user_data;
|
||||
MetaLauncher *self = user_data;
|
||||
int fd;
|
||||
int major, minor;
|
||||
|
||||
return meta_launcher_open_device (launcher, path, flags, error);
|
||||
if (!get_device_info_from_path (path, &major, &minor))
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_NOT_FOUND,
|
||||
"Could not get device info for path %s: %m", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!take_device (self->session_proxy, major, minor, &fd, NULL, error))
|
||||
return -1;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void
|
||||
on_evdev_device_close (int fd,
|
||||
gpointer user_data)
|
||||
{
|
||||
close (fd);
|
||||
MetaLauncher *self = user_data;
|
||||
int major, minor;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!get_device_info_from_fd (fd, &major, &minor))
|
||||
{
|
||||
g_warning ("Could not get device info for fd %d: %m", fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!login1_session_call_release_device_sync (self->session_proxy,
|
||||
major, minor,
|
||||
NULL, &error))
|
||||
{
|
||||
g_warning ("Could not release device %d,%d: %s", major, minor, error->message);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_vt_enter (MetaLauncher *launcher)
|
||||
sync_active (MetaLauncher *self)
|
||||
{
|
||||
g_assert (launcher->vt_switched);
|
||||
|
||||
g_main_loop_quit (launcher->nested_loop);
|
||||
|
||||
session_unpause ();
|
||||
}
|
||||
|
||||
static void
|
||||
handle_request_vt_switch (MetaLauncher *launcher)
|
||||
{
|
||||
struct weston_launcher_message message;
|
||||
GError *error;
|
||||
gboolean ok;
|
||||
|
||||
session_pause ();
|
||||
|
||||
message.opcode = WESTON_LAUNCHER_CONFIRM_VT_SWITCH;
|
||||
|
||||
error = NULL;
|
||||
ok = send_message_to_wl (launcher, &message, sizeof (message), NULL, NULL, &error);
|
||||
if (!ok) {
|
||||
g_warning ("Failed to acknowledge VT switch: %s", error->message);
|
||||
g_error_free (error);
|
||||
gboolean active = login1_session_get_active (LOGIN1_SESSION (self->session_proxy));
|
||||
|
||||
if (active == self->session_active)
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert (!launcher->vt_switched);
|
||||
launcher->vt_switched = TRUE;
|
||||
self->session_active = active;
|
||||
|
||||
/* We can't do anything at this point, because we don't
|
||||
have input devices and we don't have the DRM master,
|
||||
so let's run a nested busy loop until the VT is reentered */
|
||||
g_main_loop_run (launcher->nested_loop);
|
||||
if (active)
|
||||
session_unpause ();
|
||||
else
|
||||
session_pause ();
|
||||
}
|
||||
|
||||
g_assert (launcher->vt_switched);
|
||||
launcher->vt_switched = FALSE;
|
||||
|
||||
session_unpause ();
|
||||
static void
|
||||
on_active_changed (Login1Session *session,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaLauncher *self = user_data;
|
||||
sync_active (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_socket_readable (GSocket *socket,
|
||||
GIOCondition condition,
|
||||
gpointer user_data)
|
||||
get_kms_fd (Login1Session *session_proxy,
|
||||
int *fd_out)
|
||||
{
|
||||
MetaLauncher *launcher = user_data;
|
||||
struct weston_launcher_event event;
|
||||
gssize read;
|
||||
GError *error;
|
||||
int major, minor;
|
||||
int fd;
|
||||
GError *error = NULL;
|
||||
|
||||
if ((condition & G_IO_IN) == 0)
|
||||
return TRUE;
|
||||
|
||||
error = NULL;
|
||||
read = g_socket_receive (socket, (char*)&event, sizeof(event), NULL, &error);
|
||||
if (read < (gssize)sizeof(event))
|
||||
/* XXX -- use udev to find the DRM master device */
|
||||
if (!get_device_info_from_path ("/dev/dri/card0", &major, &minor))
|
||||
{
|
||||
g_warning ("Error reading from weston-launcher socket: %s", error->message);
|
||||
g_warning ("Could not stat /dev/dri/card0: %m");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!take_device (session_proxy, major, minor, &fd, NULL, &error))
|
||||
{
|
||||
g_warning ("Could not open DRM device: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (event.header.opcode)
|
||||
{
|
||||
case WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH:
|
||||
handle_request_vt_switch (launcher);
|
||||
break;
|
||||
|
||||
case WESTON_LAUNCHER_SERVER_VT_ENTER:
|
||||
handle_vt_enter (launcher);
|
||||
break;
|
||||
}
|
||||
*fd_out = fd;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
env_get_fd (const char *env)
|
||||
{
|
||||
const char *value;
|
||||
|
||||
value = g_getenv (env);
|
||||
|
||||
if (value == NULL)
|
||||
return -1;
|
||||
else
|
||||
return g_ascii_strtoll (value, NULL, 10);
|
||||
}
|
||||
|
||||
MetaLauncher *
|
||||
meta_launcher_new (void)
|
||||
{
|
||||
MetaLauncher *self = g_slice_new0 (MetaLauncher);
|
||||
MetaLauncher *self;
|
||||
Login1Session *session_proxy;
|
||||
GError *error = NULL;
|
||||
int launch_fd;
|
||||
int kms_fd;
|
||||
|
||||
launch_fd = env_get_fd ("WESTON_LAUNCHER_SOCK");
|
||||
if (launch_fd < 0)
|
||||
g_error ("Invalid mutter-launch socket");
|
||||
session_proxy = get_session_proxy (NULL);
|
||||
if (!login1_session_call_take_control_sync (session_proxy, FALSE, NULL, &error))
|
||||
{
|
||||
g_warning ("Could not take control: %s", error->message);
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->weston_launch = g_socket_new_from_fd (launch_fd, NULL);
|
||||
if (!get_kms_fd (session_proxy, &kms_fd))
|
||||
return NULL;
|
||||
|
||||
self->nested_context = g_main_context_new ();
|
||||
self->nested_loop = g_main_loop_new (self->nested_context, FALSE);
|
||||
self = g_slice_new0 (MetaLauncher);
|
||||
self->session_proxy = session_proxy;
|
||||
self->seat_proxy = get_seat_proxy (NULL);
|
||||
|
||||
self->outer_source = g_socket_create_source (self->weston_launch, G_IO_IN, NULL);
|
||||
g_source_set_callback (self->outer_source, (GSourceFunc)on_socket_readable, self, NULL);
|
||||
g_source_attach (self->outer_source, NULL);
|
||||
g_source_unref (self->outer_source);
|
||||
|
||||
self->inner_source = g_socket_create_source (self->weston_launch, G_IO_IN, NULL);
|
||||
g_source_set_callback (self->inner_source, (GSourceFunc)on_socket_readable, self, NULL);
|
||||
g_source_attach (self->inner_source, self->nested_context);
|
||||
g_source_unref (self->inner_source);
|
||||
|
||||
kms_fd = meta_launcher_open_device (self, "/dev/dri/card0", O_RDWR, &error);
|
||||
if (error)
|
||||
g_error ("Failed to open /dev/dri/card0: %s", error->message);
|
||||
self->session_active = TRUE;
|
||||
|
||||
clutter_egl_set_kms_fd (kms_fd);
|
||||
clutter_evdev_set_device_callbacks (on_evdev_device_open,
|
||||
on_evdev_device_close,
|
||||
self);
|
||||
|
||||
g_signal_connect (self->session_proxy, "notify::active", G_CALLBACK (on_active_changed), self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
meta_launcher_free (MetaLauncher *launcher)
|
||||
meta_launcher_free (MetaLauncher *self)
|
||||
{
|
||||
g_source_destroy (launcher->outer_source);
|
||||
g_source_destroy (launcher->inner_source);
|
||||
|
||||
g_main_loop_unref (launcher->nested_loop);
|
||||
g_main_context_unref (launcher->nested_context);
|
||||
|
||||
g_object_unref (launcher->weston_launch);
|
||||
|
||||
g_slice_free (MetaLauncher, launcher);
|
||||
g_object_unref (self->seat_proxy);
|
||||
g_object_unref (self->session_proxy);
|
||||
g_slice_free (MetaLauncher, self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_launcher_activate_session (MetaLauncher *launcher,
|
||||
GError **error)
|
||||
{
|
||||
return meta_launcher_activate_vt (launcher, -1, error);
|
||||
if (!login1_session_call_activate_sync (launcher->session_proxy, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
sync_active (launcher);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -403,10 +363,5 @@ meta_launcher_activate_vt (MetaLauncher *launcher,
|
||||
signed char vt,
|
||||
GError **error)
|
||||
{
|
||||
struct weston_launcher_activate_vt message;
|
||||
|
||||
message.header.opcode = WESTON_LAUNCHER_ACTIVATE_VT;
|
||||
message.vt = vt;
|
||||
|
||||
return send_message_to_wl (launcher, &message, sizeof (message), NULL, NULL, error);
|
||||
return login1_seat_call_switch_to_sync (launcher->seat_proxy, vt, NULL, error);
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat Inc.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@@ -12,7 +12,7 @@
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
@@ -40,8 +40,6 @@
|
||||
#include <meta/errors.h>
|
||||
#include "edid.h"
|
||||
|
||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
|
||||
typedef struct {
|
||||
drmModeConnector *connector;
|
||||
|
||||
@@ -259,7 +257,7 @@ find_output_by_id (MetaOutput *outputs,
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
if (outputs[i].output_id == id)
|
||||
if (outputs[i].winsys_id == id)
|
||||
return &outputs[i];
|
||||
|
||||
return NULL;
|
||||
@@ -363,9 +361,9 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
meta_crtc->rect.width = crtc->width;
|
||||
meta_crtc->rect.height = crtc->height;
|
||||
meta_crtc->is_dirty = FALSE;
|
||||
meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
meta_crtc->transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
/* FIXME: implement! */
|
||||
meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
meta_crtc->all_transforms = 1 << META_MONITOR_TRANSFORM_NORMAL;
|
||||
|
||||
if (crtc->mode_valid)
|
||||
{
|
||||
@@ -408,7 +406,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
|
||||
meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
|
||||
|
||||
meta_output->output_id = connector->connector_id;
|
||||
meta_output->winsys_id = connector->connector_id;
|
||||
meta_output->name = make_output_name (connector);
|
||||
meta_output->width_mm = connector->mmWidth;
|
||||
meta_output->height_mm = connector->mmHeight;
|
||||
@@ -491,7 +489,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
meta_output->crtc = NULL;
|
||||
|
||||
old_output = find_output_by_id (old_outputs, n_old_outputs,
|
||||
meta_output->output_id);
|
||||
meta_output->winsys_id);
|
||||
if (old_output)
|
||||
{
|
||||
meta_output->is_primary = old_output->is_primary;
|
||||
@@ -667,7 +665,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
||||
|
||||
if (output_kms->dpms_prop_id != 0)
|
||||
{
|
||||
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->output_id,
|
||||
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id,
|
||||
output_kms->dpms_prop_id, state);
|
||||
|
||||
if (ok < 0)
|
||||
@@ -748,7 +746,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
||||
{
|
||||
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
|
||||
|
||||
connectors[j] = output->output_id;
|
||||
connectors[j] = output->winsys_id;
|
||||
|
||||
output->is_dirty = TRUE;
|
||||
output->crtc = crtc;
|
||||
|
@@ -1,711 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2012 Benjamin Franzke
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <error.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <termios.h>
|
||||
#include <linux/vt.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/kd.h>
|
||||
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include <xf86drm.h>
|
||||
|
||||
#include <systemd/sd-login.h>
|
||||
|
||||
#include "weston-launch.h"
|
||||
|
||||
#define MAX_ARGV_SIZE 256
|
||||
#define DRM_MAJOR 226
|
||||
|
||||
enum vt_state {
|
||||
VT_HAS_VT,
|
||||
VT_PENDING_CONFIRM,
|
||||
VT_NOT_HAVE_VT,
|
||||
};
|
||||
|
||||
struct weston_launch {
|
||||
int tty;
|
||||
int ttynr;
|
||||
int sock[2];
|
||||
struct passwd *pw;
|
||||
|
||||
int signalfd;
|
||||
|
||||
pid_t child;
|
||||
int verbose;
|
||||
|
||||
struct termios terminal_attributes;
|
||||
int kb_mode;
|
||||
enum vt_state vt_state;
|
||||
unsigned vt;
|
||||
|
||||
int drm_fd;
|
||||
};
|
||||
|
||||
union cmsg_data { unsigned char b[4]; int fd; };
|
||||
|
||||
static void quit (struct weston_launch *wl, int status);
|
||||
|
||||
static int
|
||||
weston_launch_allowed(struct weston_launch *wl)
|
||||
{
|
||||
char *session, *seat;
|
||||
int err;
|
||||
|
||||
if (getuid() == 0)
|
||||
return 1;
|
||||
|
||||
err = sd_pid_get_session(getpid(), &session);
|
||||
if (err == 0 && session) {
|
||||
if (sd_session_is_active(session) &&
|
||||
sd_session_get_seat(session, &seat) == 0) {
|
||||
free(seat);
|
||||
free(session);
|
||||
return 1;
|
||||
}
|
||||
free(session);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setup_launcher_socket(struct weston_launch *wl)
|
||||
{
|
||||
if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, wl->sock) < 0)
|
||||
error(1, errno, "socketpair failed");
|
||||
|
||||
fcntl(wl->sock[0], F_SETFD, O_CLOEXEC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setup_signals(struct weston_launch *wl)
|
||||
{
|
||||
int ret;
|
||||
sigset_t mask;
|
||||
struct sigaction sa;
|
||||
|
||||
memset(&sa, 0, sizeof sa);
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
|
||||
ret = sigaction(SIGCHLD, &sa, NULL);
|
||||
assert(ret == 0);
|
||||
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGHUP, &sa, NULL);
|
||||
|
||||
ret = sigemptyset(&mask);
|
||||
assert(ret == 0);
|
||||
sigaddset(&mask, SIGCHLD);
|
||||
sigaddset(&mask, SIGINT);
|
||||
sigaddset(&mask, SIGTERM);
|
||||
sigaddset(&mask, SIGUSR1);
|
||||
ret = sigprocmask(SIG_BLOCK, &mask, NULL);
|
||||
assert(ret == 0);
|
||||
|
||||
wl->signalfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
|
||||
if (wl->signalfd < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
setenv_fd(const char *env, int fd)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
snprintf(buf, sizeof buf, "%d", fd);
|
||||
setenv(env, buf, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_confirm_vt_switch(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
|
||||
{
|
||||
struct weston_launcher_reply reply;
|
||||
|
||||
reply.header.opcode = WESTON_LAUNCHER_CONFIRM_VT_SWITCH;
|
||||
reply.ret = -1;
|
||||
|
||||
if (wl->vt_state != VT_PENDING_CONFIRM) {
|
||||
error(0, 0, "unexpected CONFIRM_VT_SWITCH");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (wl->drm_fd != -1) {
|
||||
int ret;
|
||||
|
||||
ret = drmDropMaster(wl->drm_fd);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "failed to drop DRM master: %m\n");
|
||||
} else if (wl->verbose) {
|
||||
fprintf(stderr, "dropped DRM master for VT switch\n");
|
||||
}
|
||||
}
|
||||
|
||||
wl->vt_state = VT_NOT_HAVE_VT;
|
||||
ioctl(wl->tty, VT_RELDISP, 1);
|
||||
|
||||
if (wl->verbose)
|
||||
fprintf(stderr, "mutter-launcher: confirmed VT switch\n");
|
||||
|
||||
reply.ret = 0;
|
||||
|
||||
out:
|
||||
do {
|
||||
len = send(wl->sock[0], &reply, sizeof reply, 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_activate_vt(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
|
||||
{
|
||||
struct weston_launcher_reply reply;
|
||||
struct weston_launcher_activate_vt *message;
|
||||
unsigned vt;
|
||||
|
||||
reply.header.opcode = WESTON_LAUNCHER_ACTIVATE_VT;
|
||||
reply.ret = -1;
|
||||
|
||||
if (len != sizeof(*message)) {
|
||||
error(0, 0, "missing value in activate_vt request");
|
||||
goto out;
|
||||
}
|
||||
|
||||
message = msg->msg_iov->iov_base;
|
||||
|
||||
/* Negative values mean that we're activating our own VT */
|
||||
if (message->vt > 0)
|
||||
vt = message->vt;
|
||||
else
|
||||
vt = wl->vt;
|
||||
|
||||
reply.ret = ioctl(wl->tty, VT_ACTIVATE, vt);
|
||||
if (reply.ret < 0)
|
||||
reply.ret = -errno;
|
||||
|
||||
if (wl->verbose)
|
||||
fprintf(stderr, "mutter-launch: activate VT, ret: %d\n", reply.ret);
|
||||
|
||||
out:
|
||||
do {
|
||||
len = send(wl->sock[0], &reply, sizeof reply, 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
|
||||
{
|
||||
struct weston_launcher_reply reply;
|
||||
int fd = -1;
|
||||
char control[CMSG_SPACE(sizeof(fd))];
|
||||
struct cmsghdr *cmsg;
|
||||
struct stat s;
|
||||
struct msghdr nmsg;
|
||||
struct iovec iov;
|
||||
struct weston_launcher_open *message;
|
||||
union cmsg_data *data;
|
||||
int dev_major;
|
||||
|
||||
reply.header.opcode = WESTON_LAUNCHER_OPEN;
|
||||
reply.ret = -1;
|
||||
|
||||
message = msg->msg_iov->iov_base;
|
||||
if ((size_t)len < sizeof(*message))
|
||||
goto err0;
|
||||
|
||||
/* Ensure path is null-terminated */
|
||||
((char *) message)[len-1] = '\0';
|
||||
|
||||
if (stat(message->path, &s) < 0) {
|
||||
reply.ret = -errno;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
dev_major = major(s.st_rdev);
|
||||
|
||||
if (dev_major != INPUT_MAJOR &&
|
||||
dev_major != DRM_MAJOR) {
|
||||
fprintf(stderr, "Device %s is not an input or DRM device\n",
|
||||
message->path);
|
||||
reply.ret = -EPERM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
if (dev_major == DRM_MAJOR && wl->drm_fd != -1) {
|
||||
fprintf(stderr, "Already have a DRM device open\n");
|
||||
reply.ret = -EPERM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
fd = open(message->path, message->flags);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Error opening device %s: %m\n",
|
||||
message->path);
|
||||
reply.ret = -errno;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
if (dev_major == DRM_MAJOR) {
|
||||
wl->drm_fd = fd;
|
||||
}
|
||||
|
||||
err0:
|
||||
memset(&nmsg, 0, sizeof nmsg);
|
||||
nmsg.msg_iov = &iov;
|
||||
nmsg.msg_iovlen = 1;
|
||||
if (fd != -1) {
|
||||
nmsg.msg_control = control;
|
||||
nmsg.msg_controllen = sizeof control;
|
||||
cmsg = CMSG_FIRSTHDR(&nmsg);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
|
||||
data = (union cmsg_data *) CMSG_DATA(cmsg);
|
||||
data->fd = fd;
|
||||
nmsg.msg_controllen = cmsg->cmsg_len;
|
||||
reply.ret = 0;
|
||||
}
|
||||
iov.iov_base = &reply;
|
||||
iov.iov_len = sizeof reply;
|
||||
|
||||
if (wl->verbose)
|
||||
fprintf(stderr, "mutter-launch: opened %s: ret: %d, fd: %d\n",
|
||||
message->path, reply.ret, fd);
|
||||
do {
|
||||
len = sendmsg(wl->sock[0], &nmsg, 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
|
||||
close(fd);
|
||||
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_socket_msg(struct weston_launch *wl)
|
||||
{
|
||||
char control[CMSG_SPACE(sizeof(int))];
|
||||
char buf[BUFSIZ];
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
int ret = -1;
|
||||
ssize_t len;
|
||||
struct weston_launcher_message *message;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = sizeof buf;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = control;
|
||||
msg.msg_controllen = sizeof control;
|
||||
|
||||
do {
|
||||
len = recvmsg(wl->sock[0], &msg, 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
|
||||
if (len < 1)
|
||||
return -1;
|
||||
|
||||
message = (void *) buf;
|
||||
switch (message->opcode) {
|
||||
case WESTON_LAUNCHER_OPEN:
|
||||
ret = handle_open(wl, &msg, len);
|
||||
break;
|
||||
case WESTON_LAUNCHER_CONFIRM_VT_SWITCH:
|
||||
ret = handle_confirm_vt_switch(wl, &msg, len);
|
||||
break;
|
||||
case WESTON_LAUNCHER_ACTIVATE_VT:
|
||||
ret = handle_activate_vt(wl, &msg, len);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
tty_reset(struct weston_launch *wl)
|
||||
{
|
||||
struct vt_mode mode = { 0 };
|
||||
|
||||
if (ioctl(wl->tty, KDSKBMODE, wl->kb_mode))
|
||||
fprintf(stderr, "failed to restore keyboard mode: %m\n");
|
||||
|
||||
if (ioctl(wl->tty, KDSETMODE, KD_TEXT))
|
||||
fprintf(stderr, "failed to set KD_TEXT mode on tty: %m\n");
|
||||
|
||||
if (tcsetattr(wl->tty, TCSANOW, &wl->terminal_attributes) < 0)
|
||||
fprintf(stderr, "could not restore terminal to canonical mode\n");
|
||||
|
||||
mode.mode = VT_AUTO;
|
||||
if (ioctl(wl->tty, VT_SETMODE, &mode) < 0)
|
||||
fprintf(stderr, "could not reset vt handling\n");
|
||||
}
|
||||
|
||||
static void
|
||||
quit(struct weston_launch *wl, int status)
|
||||
{
|
||||
if (wl->child > 0)
|
||||
kill(wl->child, SIGKILL);
|
||||
|
||||
close(wl->signalfd);
|
||||
close(wl->sock[0]);
|
||||
|
||||
if (wl->drm_fd > 0)
|
||||
close(wl->drm_fd);
|
||||
|
||||
tty_reset(wl);
|
||||
|
||||
exit(status);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_vt_switch(struct weston_launch *wl)
|
||||
{
|
||||
struct weston_launcher_event message;
|
||||
ssize_t len;
|
||||
|
||||
if (wl->vt_state == VT_HAS_VT) {
|
||||
wl->vt_state = VT_PENDING_CONFIRM;
|
||||
message.header.opcode = WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH;
|
||||
} else if (wl->vt_state == VT_NOT_HAVE_VT) {
|
||||
wl->vt_state = VT_HAS_VT;
|
||||
ioctl(wl->tty, VT_RELDISP, VT_ACKACQ);
|
||||
|
||||
if (wl->drm_fd != -1) {
|
||||
int ret;
|
||||
|
||||
ret = drmSetMaster(wl->drm_fd);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "failed to become DRM master: %m\n");
|
||||
/* This is very, very bad, and the compositor will crash soon,
|
||||
but oh well... */
|
||||
} else if (wl->verbose) {
|
||||
fprintf(stderr, "became DRM master after VT switch\n");
|
||||
}
|
||||
}
|
||||
|
||||
message.header.opcode = WESTON_LAUNCHER_SERVER_VT_ENTER;
|
||||
} else
|
||||
return -1;
|
||||
|
||||
message.detail = 0;
|
||||
|
||||
do {
|
||||
len = send(wl->sock[0], &message, sizeof(message), 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
handle_signal(struct weston_launch *wl)
|
||||
{
|
||||
struct signalfd_siginfo sig;
|
||||
int pid, status, ret;
|
||||
|
||||
if (read(wl->signalfd, &sig, sizeof sig) != sizeof sig) {
|
||||
error(0, errno, "reading signalfd failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (sig.ssi_signo) {
|
||||
case SIGCHLD:
|
||||
pid = waitpid(-1, &status, 0);
|
||||
if (pid == wl->child) {
|
||||
wl->child = 0;
|
||||
if (WIFEXITED(status))
|
||||
ret = WEXITSTATUS(status);
|
||||
else if (WIFSIGNALED(status))
|
||||
/*
|
||||
* If weston dies because of signal N, we
|
||||
* return 10+N. This is distinct from
|
||||
* weston-launch dying because of a signal
|
||||
* (128+N).
|
||||
*/
|
||||
ret = 10 + WTERMSIG(status);
|
||||
else
|
||||
ret = 0;
|
||||
quit(wl, ret);
|
||||
}
|
||||
break;
|
||||
case SIGTERM:
|
||||
case SIGINT:
|
||||
if (wl->child)
|
||||
kill(wl->child, sig.ssi_signo);
|
||||
break;
|
||||
case SIGUSR1:
|
||||
return handle_vt_switch(wl);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setup_tty(struct weston_launch *wl)
|
||||
{
|
||||
struct stat buf;
|
||||
struct termios raw_attributes;
|
||||
struct vt_mode mode = { 0 };
|
||||
char *session;
|
||||
char path[PATH_MAX];
|
||||
int ok;
|
||||
|
||||
ok = sd_pid_get_session(getpid(), &session);
|
||||
if (ok < 0)
|
||||
error(1, -ok, "could not determine current session");
|
||||
|
||||
ok = sd_session_get_vt(session, &wl->vt);
|
||||
if (ok < 0)
|
||||
error(1, -ok, "could not determine current TTY");
|
||||
|
||||
snprintf(path, PATH_MAX, "/dev/tty%u", wl->vt);
|
||||
wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC);
|
||||
|
||||
if (wl->tty < 0)
|
||||
error(1, errno, "failed to open tty");
|
||||
|
||||
if (fstat(wl->tty, &buf) < 0)
|
||||
error(1, errno, "stat %s failed", path);
|
||||
|
||||
if (major(buf.st_rdev) != TTY_MAJOR)
|
||||
error(1, 0, "invalid tty device: %s", path);
|
||||
|
||||
wl->ttynr = minor(buf.st_rdev);
|
||||
|
||||
if (tcgetattr(wl->tty, &wl->terminal_attributes) < 0)
|
||||
error(1, errno, "could not get terminal attributes");
|
||||
|
||||
/* Ignore control characters and disable echo */
|
||||
raw_attributes = wl->terminal_attributes;
|
||||
cfmakeraw(&raw_attributes);
|
||||
|
||||
/* Fix up line endings to be normal (cfmakeraw hoses them) */
|
||||
raw_attributes.c_oflag |= OPOST | OCRNL;
|
||||
/* Don't generate ttou signals */
|
||||
raw_attributes.c_oflag &= ~TOSTOP;
|
||||
|
||||
if (tcsetattr(wl->tty, TCSANOW, &raw_attributes) < 0)
|
||||
error(1, errno, "could not put terminal into raw mode");
|
||||
|
||||
ioctl(wl->tty, KDGKBMODE, &wl->kb_mode);
|
||||
ok = ioctl(wl->tty, KDSKBMODE, K_OFF);
|
||||
if (ok < 0) {
|
||||
ok = ioctl(wl->tty, KDSKBMODE, K_RAW);
|
||||
if (ok < 0)
|
||||
error(1, errno, "failed to set keyboard mode on tty");
|
||||
}
|
||||
|
||||
ok = ioctl(wl->tty, KDSETMODE, KD_GRAPHICS);
|
||||
if (ok < 0)
|
||||
error(1, errno, "failed to set KD_GRAPHICS mode on tty");
|
||||
|
||||
wl->vt_state = VT_HAS_VT;
|
||||
mode.mode = VT_PROCESS;
|
||||
mode.relsig = SIGUSR1;
|
||||
mode.acqsig = SIGUSR1;
|
||||
ok = ioctl(wl->tty, VT_SETMODE, &mode);
|
||||
if (ok < 0)
|
||||
error(1, errno, "failed to take control of vt handling");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
drop_privileges(struct weston_launch *wl)
|
||||
{
|
||||
if (setgid(wl->pw->pw_gid) < 0 ||
|
||||
#ifdef HAVE_INITGROUPS
|
||||
initgroups(wl->pw->pw_name, wl->pw->pw_gid) < 0 ||
|
||||
#endif
|
||||
setuid(wl->pw->pw_uid) < 0)
|
||||
error(1, errno, "dropping privileges failed");
|
||||
}
|
||||
|
||||
static void
|
||||
launch_compositor(struct weston_launch *wl, int argc, char *argv[])
|
||||
{
|
||||
char command[PATH_MAX];
|
||||
char *child_argv[MAX_ARGV_SIZE];
|
||||
sigset_t mask;
|
||||
int i;
|
||||
|
||||
if (wl->verbose)
|
||||
printf("weston-launch: spawned weston with pid: %d\n", getpid());
|
||||
|
||||
drop_privileges(wl);
|
||||
|
||||
setenv_fd("WESTON_LAUNCHER_SOCK", wl->sock[1]);
|
||||
setenv("LD_LIBRARY_PATH", LIBDIR, 1);
|
||||
unsetenv("DISPLAY");
|
||||
|
||||
/* Do not give our signal mask to the new process. */
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGTERM);
|
||||
sigaddset(&mask, SIGCHLD);
|
||||
sigaddset(&mask, SIGINT);
|
||||
sigaddset(&mask, SIGUSR1);
|
||||
sigprocmask(SIG_UNBLOCK, &mask, NULL);
|
||||
|
||||
snprintf (command, PATH_MAX, "%s \"$@\"", argv[0]);
|
||||
|
||||
child_argv[0] = wl->pw->pw_shell;
|
||||
child_argv[1] = "-l";
|
||||
child_argv[2] = "-c";
|
||||
child_argv[3] = command;
|
||||
for (i = 0; i < argc; ++i)
|
||||
child_argv[4 + i] = argv[i];
|
||||
child_argv[4 + i] = NULL;
|
||||
|
||||
execv(child_argv[0], child_argv);
|
||||
error(1, errno, "exec failed");
|
||||
}
|
||||
|
||||
static void
|
||||
help(const char *name)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [args...] [-- [weston args..]]\n", name);
|
||||
fprintf(stderr, " -u, --user Start session as specified username\n");
|
||||
fprintf(stderr, " -v, --verbose Be verbose\n");
|
||||
fprintf(stderr, " -h, --help Display this help message\n");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct weston_launch wl;
|
||||
int i, c;
|
||||
struct option opts[] = {
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ 0, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
memset(&wl, 0, sizeof wl);
|
||||
wl.drm_fd = -1;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "u:t::vh", opts, &i)) != -1) {
|
||||
switch (c) {
|
||||
case 'v':
|
||||
wl.verbose = 1;
|
||||
break;
|
||||
case 'h':
|
||||
help("mutter-launch");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if ((argc - optind) > (MAX_ARGV_SIZE - 6))
|
||||
error(1, E2BIG, "Too many arguments to pass to weston");
|
||||
|
||||
if (optind >= argc)
|
||||
error(1, 0, "Expected program argument");
|
||||
|
||||
wl.pw = getpwuid(getuid());
|
||||
if (wl.pw == NULL)
|
||||
error(1, errno, "failed to get username");
|
||||
|
||||
if (!weston_launch_allowed(&wl))
|
||||
error(1, 0, "Permission denied. You must run from an active and local (systemd) session.");
|
||||
|
||||
if (setup_tty(&wl) < 0)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if (setup_launcher_socket(&wl) < 0)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if (setup_signals(&wl) < 0)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
wl.child = fork();
|
||||
if (wl.child == -1) {
|
||||
error(1, errno, "fork failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (wl.child == 0)
|
||||
launch_compositor(&wl, argc - optind, argv + optind);
|
||||
|
||||
close(wl.sock[1]);
|
||||
|
||||
while (1) {
|
||||
struct pollfd fds[2];
|
||||
int n;
|
||||
|
||||
fds[0].fd = wl.sock[0];
|
||||
fds[0].events = POLLIN;
|
||||
fds[1].fd = wl.signalfd;
|
||||
fds[1].events = POLLIN;
|
||||
|
||||
n = poll(fds, 2, -1);
|
||||
if (n < 0)
|
||||
error(0, errno, "poll failed");
|
||||
if (fds[0].revents & POLLIN)
|
||||
handle_socket_msg(&wl);
|
||||
if (fds[1].revents)
|
||||
handle_signal(&wl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2012 Benjamin Franzke
|
||||
* 2013 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _WESTON_LAUNCH_H_
|
||||
#define _WESTON_LAUNCH_H_
|
||||
|
||||
enum weston_launcher_message_type {
|
||||
WESTON_LAUNCHER_REQUEST,
|
||||
WESTON_LAUNCHER_EVENT,
|
||||
};
|
||||
|
||||
enum weston_launcher_opcode {
|
||||
WESTON_LAUNCHER_OPEN = (1 << 1 | WESTON_LAUNCHER_REQUEST),
|
||||
WESTON_LAUNCHER_ACTIVATE_VT = (2 << 1 | WESTON_LAUNCHER_REQUEST),
|
||||
WESTON_LAUNCHER_CONFIRM_VT_SWITCH = (3 << 1 | WESTON_LAUNCHER_REQUEST),
|
||||
};
|
||||
|
||||
enum weston_launcher_server_opcode {
|
||||
WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH = (1 << 1 | WESTON_LAUNCHER_EVENT),
|
||||
WESTON_LAUNCHER_SERVER_VT_ENTER = (2 << 1 | WESTON_LAUNCHER_EVENT),
|
||||
};
|
||||
|
||||
struct weston_launcher_message {
|
||||
int opcode;
|
||||
};
|
||||
|
||||
struct weston_launcher_open {
|
||||
struct weston_launcher_message header;
|
||||
int flags;
|
||||
char path[0];
|
||||
};
|
||||
|
||||
struct weston_launcher_activate_vt {
|
||||
struct weston_launcher_message header;
|
||||
signed char vt;
|
||||
};
|
||||
|
||||
struct weston_launcher_reply {
|
||||
struct weston_launcher_message header;
|
||||
int ret;
|
||||
};
|
||||
|
||||
struct weston_launcher_event {
|
||||
struct weston_launcher_message header;
|
||||
int detail; /* unused, but makes sure replies and events are serialized the same */
|
||||
};
|
||||
|
||||
#endif
|
@@ -24,18 +24,24 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "meta-backend-x11.h"
|
||||
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
#include <X11/extensions/sync.h>
|
||||
#include <X11/XKBlib.h>
|
||||
#include <X11/extensions/XKBrules.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <xkbcommon/xkbcommon-x11.h>
|
||||
|
||||
#include "meta-idle-monitor-xsync.h"
|
||||
#include "meta-monitor-manager-xrandr.h"
|
||||
#include "backends/meta-monitor-manager-dummy.h"
|
||||
#include "meta-cursor-renderer-x11.h"
|
||||
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-cursor.h"
|
||||
#include <meta/util.h>
|
||||
#include "display-private.h"
|
||||
#include "compositor/compositor-private.h"
|
||||
@@ -44,6 +50,7 @@ struct _MetaBackendX11Private
|
||||
{
|
||||
/* The host X11 display */
|
||||
Display *xdisplay;
|
||||
xcb_connection_t *xcb;
|
||||
GSource *source;
|
||||
|
||||
int xsync_event_base;
|
||||
@@ -52,6 +59,12 @@ struct _MetaBackendX11Private
|
||||
int xinput_opcode;
|
||||
int xinput_event_base;
|
||||
int xinput_error_base;
|
||||
Time latest_evtime;
|
||||
|
||||
uint8_t xkb_event_base;
|
||||
uint8_t xkb_error_base;
|
||||
|
||||
struct xkb_keymap *keymap;
|
||||
};
|
||||
typedef struct _MetaBackendX11Private MetaBackendX11Private;
|
||||
|
||||
@@ -68,21 +81,12 @@ handle_alarm_notify (MetaBackend *backend,
|
||||
meta_idle_monitor_xsync_handle_xevent (backend->device_monitors[i], (XSyncAlarmNotifyEvent*) event);
|
||||
}
|
||||
|
||||
static Window
|
||||
get_stage_window (MetaBackendX11 *x11)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
ClutterStage *stage = CLUTTER_STAGE (compositor->stage);
|
||||
|
||||
return clutter_x11_get_stage_window (stage);
|
||||
}
|
||||
|
||||
static void
|
||||
translate_device_event (MetaBackendX11 *x11,
|
||||
XIDeviceEvent *device_event)
|
||||
{
|
||||
Window stage_window = get_stage_window (x11);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
Window stage_window = meta_backend_x11_get_xwindow (x11);
|
||||
|
||||
if (device_event->event != stage_window)
|
||||
{
|
||||
@@ -99,6 +103,21 @@ translate_device_event (MetaBackendX11 *x11,
|
||||
device_event->event_x = device_event->root_x;
|
||||
device_event->event_y = device_event->root_y;
|
||||
}
|
||||
|
||||
if (!device_event->send_event && device_event->time != CurrentTime)
|
||||
{
|
||||
if (device_event->time < priv->latest_evtime)
|
||||
{
|
||||
/* Emulated pointer events received after XIRejectTouch is received
|
||||
* on a passive touch grab will contain older timestamps, update those
|
||||
* so we dont get InvalidTime at grabs.
|
||||
*/
|
||||
device_event->time = priv->latest_evtime;
|
||||
}
|
||||
|
||||
/* Update the internal latest evtime, for any possible later use */
|
||||
priv->latest_evtime = device_event->time;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clutter makes the assumption that there is only one X window
|
||||
@@ -128,6 +147,9 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
|
||||
case XI_ButtonRelease:
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
case XI_TouchBegin:
|
||||
case XI_TouchUpdate:
|
||||
case XI_TouchEnd:
|
||||
translate_device_event (x11, (XIDeviceEvent *) input_event);
|
||||
break;
|
||||
default:
|
||||
@@ -136,6 +158,21 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
keymap_changed (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
if (priv->keymap)
|
||||
{
|
||||
xkb_keymap_unref (priv->keymap);
|
||||
priv->keymap = NULL;
|
||||
}
|
||||
|
||||
g_signal_emit_by_name (backend, "keymap-changed", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_host_xevent (MetaBackend *backend,
|
||||
XEvent *event)
|
||||
@@ -146,24 +183,49 @@ handle_host_xevent (MetaBackend *backend,
|
||||
|
||||
XGetEventData (priv->xdisplay, &event->xcookie);
|
||||
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
if (display)
|
||||
{
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
|
||||
bypass_clutter = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
|
||||
handle_alarm_notify (backend, event);
|
||||
|
||||
if (event->type == priv->xkb_event_base)
|
||||
{
|
||||
XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event;
|
||||
|
||||
if (xkb_ev->device == META_VIRTUAL_CORE_KEYBOARD_ID)
|
||||
{
|
||||
switch (xkb_ev->xkb_type)
|
||||
{
|
||||
case XkbNewKeyboardNotify:
|
||||
case XkbMapNotify:
|
||||
keymap_changed (backend);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend);
|
||||
if (META_IS_MONITOR_MANAGER_XRANDR (manager) &&
|
||||
meta_monitor_manager_xrandr_handle_xevent (META_MONITOR_MANAGER_XRANDR (manager), event))
|
||||
{
|
||||
bypass_clutter = TRUE;
|
||||
goto out;
|
||||
}
|
||||
bypass_clutter = TRUE;
|
||||
}
|
||||
|
||||
maybe_spoof_event_as_stage_event (x11, event);
|
||||
|
||||
out:
|
||||
if (!bypass_clutter)
|
||||
clutter_x11_handle_event (event);
|
||||
{
|
||||
maybe_spoof_event_as_stage_event (x11, event);
|
||||
clutter_x11_handle_event (event);
|
||||
}
|
||||
|
||||
XFreeEventData (priv->xdisplay, &event->xcookie);
|
||||
}
|
||||
@@ -246,6 +308,24 @@ x_event_source_new (MetaBackend *backend)
|
||||
return source;
|
||||
}
|
||||
|
||||
static void
|
||||
take_touch_grab (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits };
|
||||
XIGrabModifiers mods = { XIAnyModifier, 0 };
|
||||
|
||||
XISetMask (mask.mask, XI_TouchBegin);
|
||||
XISetMask (mask.mask, XI_TouchUpdate);
|
||||
XISetMask (mask.mask, XI_TouchEnd);
|
||||
|
||||
XIGrabTouchBegin (priv->xdisplay, META_VIRTUAL_CORE_POINTER_ID,
|
||||
DefaultRootWindow (priv->xdisplay),
|
||||
False, &mask, 1, &mods);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_post_init (MetaBackend *backend)
|
||||
{
|
||||
@@ -283,6 +363,19 @@ meta_backend_x11_post_init (MetaBackend *backend)
|
||||
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
|
||||
}
|
||||
|
||||
take_touch_grab (backend);
|
||||
|
||||
priv->xcb = XGetXCBConnection (priv->xdisplay);
|
||||
if (!xkb_x11_setup_xkb_extension (priv->xcb,
|
||||
XKB_X11_MIN_MAJOR_XKB_VERSION,
|
||||
XKB_X11_MIN_MINOR_XKB_VERSION,
|
||||
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS,
|
||||
NULL, NULL,
|
||||
&priv->xkb_event_base,
|
||||
&priv->xkb_error_base))
|
||||
meta_fatal ("X server doesn't have the XKB extension, version %d.%d or newer\n",
|
||||
XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION);
|
||||
|
||||
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
|
||||
}
|
||||
|
||||
@@ -307,6 +400,12 @@ meta_backend_x11_create_monitor_manager (MetaBackend *backend)
|
||||
return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
|
||||
}
|
||||
|
||||
static MetaCursorRenderer *
|
||||
meta_backend_x11_create_cursor_renderer (MetaBackend *backend)
|
||||
{
|
||||
return g_object_new (META_TYPE_CURSOR_RENDERER_X11, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_backend_x11_grab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
@@ -318,6 +417,9 @@ meta_backend_x11_grab_device (MetaBackend *backend,
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
int ret;
|
||||
|
||||
if (timestamp != CurrentTime)
|
||||
timestamp = MAX (timestamp, priv->latest_evtime);
|
||||
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
@@ -326,14 +428,10 @@ meta_backend_x11_grab_device (MetaBackend *backend,
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
|
||||
MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL);
|
||||
MetaCursorReference *cursor_ref = meta_cursor_tracker_get_displayed_cursor (tracker);
|
||||
MetaCursor cursor = meta_cursor_reference_get_meta_cursor (cursor_ref);
|
||||
|
||||
ret = XIGrabDevice (priv->xdisplay, device_id,
|
||||
get_stage_window (x11),
|
||||
meta_backend_x11_get_xwindow (x11),
|
||||
timestamp,
|
||||
meta_cursor_create_x_cursor (priv->xdisplay, cursor),
|
||||
None,
|
||||
XIGrabModeAsync, XIGrabModeAsync,
|
||||
False, /* owner_events */
|
||||
&mask);
|
||||
@@ -355,6 +453,224 @@ meta_backend_x11_ungrab_device (MetaBackend *backend,
|
||||
return (ret == Success);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
XIWarpPointer (priv->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
None,
|
||||
meta_backend_x11_get_xwindow (x11),
|
||||
0, 0, 0, 0,
|
||||
x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
get_xkbrf_var_defs (Display *xdisplay,
|
||||
const char *layouts,
|
||||
const char *variants,
|
||||
const char *options,
|
||||
char **rules_p,
|
||||
XkbRF_VarDefsRec *var_defs)
|
||||
{
|
||||
char *rules = NULL;
|
||||
|
||||
/* Get it from the X property or fallback on defaults */
|
||||
if (!XkbRF_GetNamesProp (xdisplay, &rules, var_defs) || !rules)
|
||||
{
|
||||
rules = strdup (DEFAULT_XKB_RULES_FILE);
|
||||
var_defs->model = strdup (DEFAULT_XKB_MODEL);
|
||||
var_defs->layout = NULL;
|
||||
var_defs->variant = NULL;
|
||||
var_defs->options = NULL;
|
||||
}
|
||||
|
||||
/* Swap in our new options... */
|
||||
free (var_defs->layout);
|
||||
var_defs->layout = strdup (layouts);
|
||||
free (var_defs->variant);
|
||||
var_defs->variant = strdup (variants);
|
||||
free (var_defs->options);
|
||||
var_defs->options = strdup (options);
|
||||
|
||||
/* Sometimes, the property is a file path, and sometimes it's
|
||||
not. Normalize it so it's always a file path. */
|
||||
if (rules[0] == '/')
|
||||
*rules_p = g_strdup (rules);
|
||||
else
|
||||
*rules_p = g_build_filename (XKB_BASE, "rules", rules, NULL);
|
||||
|
||||
free (rules);
|
||||
}
|
||||
|
||||
static void
|
||||
free_xkbrf_var_defs (XkbRF_VarDefsRec *var_defs)
|
||||
{
|
||||
free (var_defs->model);
|
||||
free (var_defs->layout);
|
||||
free (var_defs->variant);
|
||||
free (var_defs->options);
|
||||
}
|
||||
|
||||
static void
|
||||
free_xkb_component_names (XkbComponentNamesRec *p)
|
||||
{
|
||||
free (p->keymap);
|
||||
free (p->keycodes);
|
||||
free (p->types);
|
||||
free (p->compat);
|
||||
free (p->symbols);
|
||||
free (p->geometry);
|
||||
}
|
||||
|
||||
static void
|
||||
upload_xkb_description (Display *xdisplay,
|
||||
const gchar *rules_file_path,
|
||||
XkbRF_VarDefsRec *var_defs,
|
||||
XkbComponentNamesRec *comp_names)
|
||||
{
|
||||
XkbDescRec *xkb_desc;
|
||||
gchar *rules_file;
|
||||
|
||||
/* Upload it to the X server using the same method as setxkbmap */
|
||||
xkb_desc = XkbGetKeyboardByName (xdisplay,
|
||||
XkbUseCoreKbd,
|
||||
comp_names,
|
||||
XkbGBN_AllComponentsMask,
|
||||
XkbGBN_AllComponentsMask &
|
||||
(~XkbGBN_GeometryMask), True);
|
||||
if (!xkb_desc)
|
||||
{
|
||||
g_warning ("Couldn't upload new XKB keyboard description");
|
||||
return;
|
||||
}
|
||||
|
||||
XkbFreeKeyboard (xkb_desc, 0, True);
|
||||
|
||||
rules_file = g_path_get_basename (rules_file_path);
|
||||
|
||||
if (!XkbRF_SetNamesProp (xdisplay, rules_file, var_defs))
|
||||
g_warning ("Couldn't update the XKB root window property");
|
||||
|
||||
g_free (rules_file);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_set_keymap (MetaBackend *backend,
|
||||
const char *layouts,
|
||||
const char *variants,
|
||||
const char *options)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
XkbRF_RulesRec *xkb_rules;
|
||||
XkbRF_VarDefsRec xkb_var_defs = { 0 };
|
||||
gchar *rules_file_path;
|
||||
|
||||
get_xkbrf_var_defs (priv->xdisplay,
|
||||
layouts,
|
||||
variants,
|
||||
options,
|
||||
&rules_file_path,
|
||||
&xkb_var_defs);
|
||||
|
||||
xkb_rules = XkbRF_Load (rules_file_path, NULL, True, True);
|
||||
if (xkb_rules)
|
||||
{
|
||||
XkbComponentNamesRec xkb_comp_names = { 0 };
|
||||
|
||||
XkbRF_GetComponents (xkb_rules, &xkb_var_defs, &xkb_comp_names);
|
||||
upload_xkb_description (priv->xdisplay, rules_file_path, &xkb_var_defs, &xkb_comp_names);
|
||||
|
||||
free_xkb_component_names (&xkb_comp_names);
|
||||
XkbRF_Free (xkb_rules, True);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Couldn't load XKB rules");
|
||||
}
|
||||
|
||||
free_xkbrf_var_defs (&xkb_var_defs);
|
||||
g_free (rules_file_path);
|
||||
}
|
||||
|
||||
static struct xkb_keymap *
|
||||
meta_backend_x11_get_keymap (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
if (priv->keymap == NULL)
|
||||
{
|
||||
struct xkb_context *context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
|
||||
priv->keymap = xkb_x11_keymap_new_from_device (context,
|
||||
priv->xcb,
|
||||
xkb_x11_get_core_keyboard_device_id (priv->xcb),
|
||||
XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
xkb_context_unref (context);
|
||||
}
|
||||
|
||||
return priv->keymap;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_lock_layout_group (MetaBackend *backend,
|
||||
guint idx)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, idx);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_update_screen_size (MetaBackend *backend,
|
||||
int width, int height)
|
||||
{
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
/* For a nested wayland session, we want to go through Clutter to update the
|
||||
* toplevel window size, rather than doing it directly.
|
||||
*/
|
||||
META_BACKEND_CLASS (meta_backend_x11_parent_class)->update_screen_size (backend, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
Window xwin = meta_backend_x11_get_xwindow (x11);
|
||||
XResizeWindow (priv->xdisplay, xwin, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_select_stage_events (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
Window xwin = meta_backend_x11_get_xwindow (x11);
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
XISetMask (mask.mask, XI_FocusIn);
|
||||
XISetMask (mask.mask, XI_FocusOut);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
XIClearMask (mask.mask, XI_TouchBegin);
|
||||
XIClearMask (mask.mask, XI_TouchEnd);
|
||||
XIClearMask (mask.mask, XI_TouchUpdate);
|
||||
XISelectEvents (priv->xdisplay, xwin, &mask, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
||||
{
|
||||
@@ -363,9 +679,15 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
||||
backend_class->post_init = meta_backend_x11_post_init;
|
||||
backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor;
|
||||
backend_class->create_monitor_manager = meta_backend_x11_create_monitor_manager;
|
||||
|
||||
backend_class->create_cursor_renderer = meta_backend_x11_create_cursor_renderer;
|
||||
backend_class->grab_device = meta_backend_x11_grab_device;
|
||||
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
|
||||
backend_class->warp_pointer = meta_backend_x11_warp_pointer;
|
||||
backend_class->set_keymap = meta_backend_x11_set_keymap;
|
||||
backend_class->get_keymap = meta_backend_x11_get_keymap;
|
||||
backend_class->lock_layout_group = meta_backend_x11_lock_layout_group;
|
||||
backend_class->update_screen_size = meta_backend_x11_update_screen_size;
|
||||
backend_class->select_stage_events = meta_backend_x11_select_stage_events;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -383,3 +705,9 @@ meta_backend_x11_get_xdisplay (MetaBackendX11 *x11)
|
||||
return priv->xdisplay;
|
||||
}
|
||||
|
||||
Window
|
||||
meta_backend_x11_get_xwindow (MetaBackendX11 *x11)
|
||||
{
|
||||
ClutterActor *stage = meta_backend_get_stage (META_BACKEND (x11));
|
||||
return clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
|
||||
}
|
||||
|
@@ -53,4 +53,6 @@ GType meta_backend_x11_get_type (void) G_GNUC_CONST;
|
||||
|
||||
Display * meta_backend_x11_get_xdisplay (MetaBackendX11 *backend);
|
||||
|
||||
Window meta_backend_x11_get_xwindow (MetaBackendX11 *backend);
|
||||
|
||||
#endif /* META_BACKEND_X11_H */
|
||||
|
99
src/backends/x11/meta-cursor-renderer-x11.c
Normal file
99
src/backends/x11/meta-cursor-renderer-x11.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-cursor-renderer-x11.h"
|
||||
|
||||
#include "meta-backend-x11.h"
|
||||
#include "meta-stage.h"
|
||||
|
||||
struct _MetaCursorRendererX11Private
|
||||
{
|
||||
gboolean server_cursor_visible;
|
||||
};
|
||||
typedef struct _MetaCursorRendererX11Private MetaCursorRendererX11Private;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererX11, meta_cursor_renderer_x11, META_TYPE_CURSOR_RENDERER);
|
||||
|
||||
static gboolean
|
||||
meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererX11 *x11 = META_CURSOR_RENDERER_X11 (renderer);
|
||||
MetaCursorRendererX11Private *priv = meta_cursor_renderer_x11_get_instance_private (x11);
|
||||
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Window xwindow = meta_backend_x11_get_xwindow (backend);
|
||||
|
||||
if (xwindow == None)
|
||||
return FALSE;
|
||||
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
|
||||
MetaCursorReference *cursor_ref = meta_cursor_renderer_get_cursor (renderer);
|
||||
gboolean has_server_cursor = FALSE;
|
||||
|
||||
if (cursor_ref)
|
||||
{
|
||||
MetaCursor cursor = meta_cursor_reference_get_meta_cursor (cursor_ref);
|
||||
if (cursor != META_CURSOR_NONE)
|
||||
{
|
||||
Cursor xcursor = meta_cursor_create_x_cursor (xdisplay, cursor);
|
||||
XDefineCursor (xdisplay, xwindow, xcursor);
|
||||
XFlush (xdisplay);
|
||||
XFreeCursor (xdisplay, xcursor);
|
||||
|
||||
has_server_cursor = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_server_cursor != priv->server_cursor_visible)
|
||||
{
|
||||
if (has_server_cursor)
|
||||
XFixesShowCursor (xdisplay, xwindow);
|
||||
else
|
||||
XFixesHideCursor (xdisplay, xwindow);
|
||||
|
||||
priv->server_cursor_visible = has_server_cursor;
|
||||
}
|
||||
|
||||
return priv->server_cursor_visible;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_x11_class_init (MetaCursorRendererX11Class *klass)
|
||||
{
|
||||
MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass);
|
||||
|
||||
renderer_class->update_cursor = meta_cursor_renderer_x11_update_cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_x11_init (MetaCursorRendererX11 *x11)
|
||||
{
|
||||
MetaCursorRendererX11Private *priv = meta_cursor_renderer_x11_get_instance_private (x11);
|
||||
|
||||
/* XFixes has no way to retrieve the current cursor visibility. */
|
||||
priv->server_cursor_visible = TRUE;
|
||||
}
|
52
src/backends/x11/meta-cursor-renderer-x11.h
Normal file
52
src/backends/x11/meta-cursor-renderer-x11.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef META_CURSOR_RENDERER_X11_H
|
||||
#define META_CURSOR_RENDERER_X11_H
|
||||
|
||||
#include "meta-cursor-renderer.h"
|
||||
|
||||
#define META_TYPE_CURSOR_RENDERER_X11 (meta_cursor_renderer_x11_get_type ())
|
||||
#define META_CURSOR_RENDERER_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11))
|
||||
#define META_CURSOR_RENDERER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11Class))
|
||||
#define META_IS_CURSOR_RENDERER_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER_X11))
|
||||
#define META_IS_CURSOR_RENDERER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_RENDERER_X11))
|
||||
#define META_CURSOR_RENDERER_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11Class))
|
||||
|
||||
typedef struct _MetaCursorRendererX11 MetaCursorRendererX11;
|
||||
typedef struct _MetaCursorRendererX11Class MetaCursorRendererX11Class;
|
||||
|
||||
struct _MetaCursorRendererX11
|
||||
{
|
||||
MetaCursorRenderer parent;
|
||||
};
|
||||
|
||||
struct _MetaCursorRendererX11Class
|
||||
{
|
||||
MetaCursorRendererClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_cursor_renderer_x11_get_type (void) G_GNUC_CONST;
|
||||
|
||||
#endif /* META_CURSOR_RENDERER_X11_H */
|
@@ -1,6 +1,6 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2001, 2002 Havoc Pennington
|
||||
* Copyright (C) 2002, 2003 Red Hat Inc.
|
||||
* Some ICCCM manager selection code derived from fvwm2,
|
||||
@@ -8,7 +8,7 @@
|
||||
* Copyright (C) 2003 Rob Adams
|
||||
* Copyright (C) 2004-2006 Elijah Newren
|
||||
* Copyright (C) 2013 Red Hat Inc.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@@ -18,7 +18,7 @@
|
||||
* 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/>.
|
||||
*/
|
||||
@@ -35,6 +35,8 @@
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <X11/extensions/dpms.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <xcb/randr.h>
|
||||
|
||||
#include "meta-backend-x11.h"
|
||||
#include <meta/main.h>
|
||||
@@ -42,7 +44,7 @@
|
||||
#include "edid.h"
|
||||
#include "meta-monitor-config.h"
|
||||
|
||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
|
||||
/* Look for DPI_FALLBACK in:
|
||||
* http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
|
||||
@@ -67,31 +69,31 @@ struct _MetaMonitorManagerXrandrClass
|
||||
|
||||
G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER);
|
||||
|
||||
static enum wl_output_transform
|
||||
wl_transform_from_xrandr (Rotation rotation)
|
||||
static MetaMonitorTransform
|
||||
meta_monitor_transform_from_xrandr (Rotation rotation)
|
||||
{
|
||||
static const enum wl_output_transform y_reflected_map[4] = {
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_180,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_90,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_270
|
||||
static const MetaMonitorTransform y_reflected_map[4] = {
|
||||
META_MONITOR_TRANSFORM_FLIPPED_180,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_90,
|
||||
META_MONITOR_TRANSFORM_FLIPPED,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_270
|
||||
};
|
||||
enum wl_output_transform ret;
|
||||
MetaMonitorTransform ret;
|
||||
|
||||
switch (rotation & 0x7F)
|
||||
{
|
||||
default:
|
||||
case RR_Rotate_0:
|
||||
ret = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret = META_MONITOR_TRANSFORM_NORMAL;
|
||||
break;
|
||||
case RR_Rotate_90:
|
||||
ret = WL_OUTPUT_TRANSFORM_90;
|
||||
ret = META_MONITOR_TRANSFORM_90;
|
||||
break;
|
||||
case RR_Rotate_180:
|
||||
ret = WL_OUTPUT_TRANSFORM_180;
|
||||
ret = META_MONITOR_TRANSFORM_180;
|
||||
break;
|
||||
case RR_Rotate_270:
|
||||
ret = WL_OUTPUT_TRANSFORM_270;
|
||||
ret = META_MONITOR_TRANSFORM_270;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -105,42 +107,42 @@ wl_transform_from_xrandr (Rotation rotation)
|
||||
|
||||
#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
|
||||
|
||||
static unsigned int
|
||||
wl_transform_from_xrandr_all (Rotation rotation)
|
||||
static MetaMonitorTransform
|
||||
meta_monitor_transform_from_xrandr_all (Rotation rotation)
|
||||
{
|
||||
unsigned ret;
|
||||
|
||||
/* Handle the common cases first (none or all) */
|
||||
if (rotation == 0 || rotation == RR_Rotate_0)
|
||||
return (1 << WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
return (1 << META_MONITOR_TRANSFORM_NORMAL);
|
||||
|
||||
/* All rotations and one reflection -> all of them by composition */
|
||||
if ((rotation & ALL_ROTATIONS) &&
|
||||
((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y)))
|
||||
return ALL_WL_TRANSFORMS;
|
||||
return ALL_TRANSFORMS;
|
||||
|
||||
ret = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret = 1 << META_MONITOR_TRANSFORM_NORMAL;
|
||||
if (rotation & RR_Rotate_90)
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_90;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_90;
|
||||
if (rotation & RR_Rotate_180)
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_180;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_180;
|
||||
if (rotation & RR_Rotate_270)
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_270;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_270;
|
||||
if (rotation & (RR_Rotate_0 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED;
|
||||
if (rotation & (RR_Rotate_90 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_90;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_90;
|
||||
if (rotation & (RR_Rotate_180 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_180;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_180;
|
||||
if (rotation & (RR_Rotate_270 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_270;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output, const char *propname)
|
||||
{
|
||||
gboolean value;
|
||||
Atom atom, actual_type;
|
||||
@@ -148,9 +150,9 @@ output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *buffer;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
0, G_MAXLONG, False, False, XA_CARDINAL,
|
||||
&actual_type, &actual_format,
|
||||
@@ -166,6 +168,13 @@ output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
return value;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
return output_get_boolean_property (manager_xrandr, output, "_MUTTER_PRESENTATION_OUTPUT");
|
||||
}
|
||||
|
||||
static int
|
||||
normalize_backlight (MetaOutput *output,
|
||||
int hw_value)
|
||||
@@ -186,7 +195,7 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
0, G_MAXLONG, False, False, XA_INTEGER,
|
||||
&actual_type, &actual_format,
|
||||
@@ -207,30 +216,34 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
Atom atom;
|
||||
XRRPropertyInfo *info;
|
||||
xcb_connection_t *xcb_conn;
|
||||
xcb_randr_query_output_property_reply_t *reply;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
atom);
|
||||
|
||||
if (info == NULL)
|
||||
{
|
||||
meta_verbose ("could not get output property for %s\n", output->name);
|
||||
return;
|
||||
}
|
||||
xcb_conn = XGetXCBConnection (manager_xrandr->xdisplay);
|
||||
reply = xcb_randr_query_output_property_reply (xcb_conn,
|
||||
xcb_randr_query_output_property (xcb_conn,
|
||||
(xcb_randr_output_t) output->winsys_id,
|
||||
(xcb_atom_t) atom),
|
||||
NULL);
|
||||
|
||||
if (!info->range || info->num_values != 2)
|
||||
/* This can happen on systems without backlights. */
|
||||
if (reply == NULL)
|
||||
return;
|
||||
|
||||
if (!reply->range || reply->length != 2)
|
||||
{
|
||||
meta_verbose ("backlight %s was not range\n", output->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
output->backlight_min = info->values[0];
|
||||
output->backlight_max = info->values[1];
|
||||
int32_t *values = xcb_randr_query_output_property_valid_values (reply);
|
||||
output->backlight_min = values[0];
|
||||
output->backlight_max = values[1];
|
||||
|
||||
out:
|
||||
XFree (info);
|
||||
free (reply);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -272,31 +285,31 @@ get_edid_property (Display *dpy,
|
||||
}
|
||||
|
||||
XFree (prop);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
XID output_id)
|
||||
XID winsys_id)
|
||||
{
|
||||
Atom edid_atom;
|
||||
guint8 *result;
|
||||
gsize len;
|
||||
|
||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
|
||||
}
|
||||
|
||||
if (result)
|
||||
@@ -312,25 +325,25 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
|
||||
static gboolean
|
||||
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
XID output_id)
|
||||
MetaOutput *output)
|
||||
{
|
||||
Atom atom;
|
||||
XRRPropertyInfo *info;
|
||||
gboolean result = FALSE;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "hotplug_mode_update", False);
|
||||
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
|
||||
atom);
|
||||
|
||||
if (info)
|
||||
{
|
||||
result = TRUE;
|
||||
XFree (info);
|
||||
}
|
||||
|
||||
return result;
|
||||
return output_get_boolean_property (manager_xrandr, output, "hotplug_mode_update");
|
||||
}
|
||||
|
||||
static char *
|
||||
get_xmode_name (XRRModeInfo *xmode)
|
||||
{
|
||||
int width = xmode->width;
|
||||
int height = xmode->height;
|
||||
|
||||
if (xmode->hSkew != 0)
|
||||
{
|
||||
width += 2 * (xmode->hSkew >> 8);
|
||||
height += 2 * (xmode->hSkew & 0xff);
|
||||
}
|
||||
|
||||
return g_strdup_printf ("%dx%d", width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
@@ -417,6 +430,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
mode->height = xmode->height;
|
||||
mode->refresh_rate = (xmode->dotClock /
|
||||
((float)xmode->hTotal * xmode->vTotal));
|
||||
mode->name = get_xmode_name (xmode);
|
||||
}
|
||||
|
||||
for (i = 0; i < (unsigned)resources->ncrtc; i++)
|
||||
@@ -434,8 +448,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
meta_crtc->rect.width = crtc->width;
|
||||
meta_crtc->rect.height = crtc->height;
|
||||
meta_crtc->is_dirty = FALSE;
|
||||
meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
|
||||
meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
|
||||
meta_crtc->transform = meta_monitor_transform_from_xrandr (crtc->rotation);
|
||||
meta_crtc->all_transforms = meta_monitor_transform_from_xrandr_all (crtc->rotations);
|
||||
|
||||
for (j = 0; j < (unsigned)resources->nmode; j++)
|
||||
{
|
||||
@@ -467,10 +481,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
GBytes *edid;
|
||||
MonitorInfo *parsed_edid;
|
||||
|
||||
meta_output->output_id = resources->outputs[i];
|
||||
meta_output->winsys_id = resources->outputs[i];
|
||||
meta_output->name = g_strdup (output->name);
|
||||
|
||||
edid = read_output_edid (manager_xrandr, meta_output->output_id);
|
||||
edid = read_output_edid (manager_xrandr, meta_output->winsys_id);
|
||||
if (edid)
|
||||
{
|
||||
gsize len;
|
||||
@@ -503,8 +517,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
meta_output->width_mm = output->mm_width;
|
||||
meta_output->height_mm = output->mm_height;
|
||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
||||
meta_output->hotplug_mode_update =
|
||||
output_get_hotplug_mode_update (manager_xrandr, meta_output->output_id);
|
||||
meta_output->hotplug_mode_update = output_get_hotplug_mode_update (manager_xrandr, meta_output);
|
||||
|
||||
meta_output->n_modes = output->nmode;
|
||||
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
|
||||
@@ -556,7 +569,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
meta_output->possible_clones[j] = GINT_TO_POINTER (output->clones[j]);
|
||||
}
|
||||
|
||||
meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
|
||||
meta_output->is_primary = ((XID)meta_output->winsys_id == primary_output);
|
||||
meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
|
||||
output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
|
||||
|
||||
@@ -589,7 +602,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
|
||||
for (k = 0; k < manager->n_outputs; k++)
|
||||
{
|
||||
if (clone == (XID)manager->outputs[k].output_id)
|
||||
if (clone == (XID)manager->outputs[k].winsys_id)
|
||||
{
|
||||
meta_output->possible_clones[j] = &manager->outputs[k];
|
||||
break;
|
||||
@@ -605,7 +618,7 @@ meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
|
||||
return read_output_edid (manager_xrandr, output->output_id);
|
||||
return read_output_edid (manager_xrandr, output->winsys_id);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -637,25 +650,25 @@ meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
|
||||
}
|
||||
|
||||
static Rotation
|
||||
wl_transform_to_xrandr (enum wl_output_transform transform)
|
||||
meta_monitor_transform_to_xrandr (MetaMonitorTransform transform)
|
||||
{
|
||||
switch (transform)
|
||||
{
|
||||
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||
case META_MONITOR_TRANSFORM_NORMAL:
|
||||
return RR_Rotate_0;
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
case META_MONITOR_TRANSFORM_90:
|
||||
return RR_Rotate_90;
|
||||
case WL_OUTPUT_TRANSFORM_180:
|
||||
case META_MONITOR_TRANSFORM_180:
|
||||
return RR_Rotate_180;
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
case META_MONITOR_TRANSFORM_270:
|
||||
return RR_Rotate_270;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||
case META_MONITOR_TRANSFORM_FLIPPED:
|
||||
return RR_Reflect_X | RR_Rotate_0;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
case META_MONITOR_TRANSFORM_FLIPPED_90:
|
||||
return RR_Reflect_X | RR_Rotate_90;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||
case META_MONITOR_TRANSFORM_FLIPPED_180:
|
||||
return RR_Reflect_X | RR_Rotate_180;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||
case META_MONITOR_TRANSFORM_FLIPPED_270:
|
||||
return RR_Reflect_X | RR_Rotate_270;
|
||||
}
|
||||
|
||||
@@ -672,7 +685,7 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char*) &value, 1);
|
||||
@@ -828,7 +841,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
output->crtc = crtc;
|
||||
new_controlled_mask |= 1UL << j;
|
||||
|
||||
outputs[j] = output->output_id;
|
||||
outputs[j] = output->winsys_id;
|
||||
}
|
||||
|
||||
if (crtc->current_mode == mode &&
|
||||
@@ -847,7 +860,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
manager_xrandr->time,
|
||||
crtc_info->x, crtc_info->y,
|
||||
(XID)mode->mode_id,
|
||||
wl_transform_to_xrandr (crtc_info->transform),
|
||||
meta_monitor_transform_to_xrandr (crtc_info->transform),
|
||||
outputs, n_outputs);
|
||||
|
||||
if (ok != Success)
|
||||
@@ -891,7 +904,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
{
|
||||
XRRSetOutputPrimary (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
(XID)output_info->output->output_id);
|
||||
(XID)output_info->output->winsys_id);
|
||||
}
|
||||
|
||||
output_set_presentation_xrandr (manager_xrandr,
|
||||
@@ -918,6 +931,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
}
|
||||
|
||||
XUngrabServer (manager_xrandr->xdisplay);
|
||||
XFlush (manager_xrandr->xdisplay);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -933,7 +947,7 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
XA_INTEGER, 32, PropModeReplace,
|
||||
(unsigned char *) &hw_value, 1);
|
||||
|
@@ -51,6 +51,12 @@ round_to_fixed (float x)
|
||||
return roundf (x * 256);
|
||||
}
|
||||
|
||||
/* Help macros to scale from OpenGL <-1,1> coordinates system to
|
||||
* window coordinates ranging [0,window-size]. Borrowed from clutter-utils.c
|
||||
*/
|
||||
#define MTX_GL_SCALE_X(x,w,v1,v2) ((((((x) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2))
|
||||
#define MTX_GL_SCALE_Y(y,w,v1,v2) ((v1) - (((((y) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2))
|
||||
|
||||
/* This helper function checks if (according to our fixed point precision)
|
||||
* the vertices @verts form a box of width @widthf and height @heightf
|
||||
* located at integral coordinates. These coordinates are returned
|
||||
@@ -118,3 +124,67 @@ meta_actor_is_untransformed (ClutterActor *actor,
|
||||
return meta_actor_vertices_are_untransformed (verts, widthf, heightf, x_origin, y_origin);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_actor_painting_untransformed:
|
||||
* @paint_width: the width of the painted area
|
||||
* @paint_height: the height of the painted area
|
||||
* @x_origin: if the transform is only an integer translation
|
||||
* then the X coordinate of the location of the origin under the transformation
|
||||
* from drawing space to screen pixel space is returned here.
|
||||
* @y_origin: if the transform is only an integer translation
|
||||
* then the X coordinate of the location of the origin under the transformation
|
||||
* from drawing space to screen pixel space is returned here.
|
||||
*
|
||||
* Determines if the current painting transform is an integer translation.
|
||||
* This can differ from the result of meta_actor_is_untransformed() when
|
||||
* painting an actor if we're inside a inside a clone paint. @paint_width
|
||||
* and @paint_height are used to determine the vertices of the rectangle
|
||||
* we check to see if the painted area is "close enough" to the integer
|
||||
* transform.
|
||||
*/
|
||||
gboolean
|
||||
meta_actor_painting_untransformed (int paint_width,
|
||||
int paint_height,
|
||||
int *x_origin,
|
||||
int *y_origin)
|
||||
{
|
||||
CoglMatrix modelview, projection, modelview_projection;
|
||||
ClutterVertex vertices[4];
|
||||
float viewport[4];
|
||||
int i;
|
||||
|
||||
cogl_get_modelview_matrix (&modelview);
|
||||
cogl_get_projection_matrix (&projection);
|
||||
|
||||
cogl_matrix_multiply (&modelview_projection,
|
||||
&projection,
|
||||
&modelview);
|
||||
|
||||
vertices[0].x = 0;
|
||||
vertices[0].y = 0;
|
||||
vertices[0].z = 0;
|
||||
vertices[1].x = paint_width;
|
||||
vertices[1].y = 0;
|
||||
vertices[1].z = 0;
|
||||
vertices[2].x = 0;
|
||||
vertices[2].y = paint_height;
|
||||
vertices[2].z = 0;
|
||||
vertices[3].x = paint_width;
|
||||
vertices[3].y = paint_height;
|
||||
vertices[3].z = 0;
|
||||
|
||||
cogl_get_viewport (viewport);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
float w = 1;
|
||||
cogl_matrix_transform_point (&modelview_projection, &vertices[i].x, &vertices[i].y, &vertices[i].z, &w);
|
||||
vertices[i].x = MTX_GL_SCALE_X (vertices[i].x, w,
|
||||
viewport[2], viewport[0]);
|
||||
vertices[i].y = MTX_GL_SCALE_Y (vertices[i].y, w,
|
||||
viewport[3], viewport[1]);
|
||||
}
|
||||
|
||||
return meta_actor_vertices_are_untransformed (vertices, paint_width, paint_height, x_origin, y_origin);
|
||||
}
|
||||
|
||||
|
@@ -31,4 +31,9 @@ gboolean meta_actor_is_untransformed (ClutterActor *actor,
|
||||
int *x_origin,
|
||||
int *y_origin);
|
||||
|
||||
gboolean meta_actor_painting_untransformed (int paint_width,
|
||||
int paint_height,
|
||||
int *x_origin,
|
||||
int *y_origin);
|
||||
|
||||
#endif /* __META_CLUTTER_UTILS_H__ */
|
||||
|
@@ -22,53 +22,11 @@
|
||||
#include <clutter/clutter.h>
|
||||
#include "cogl-utils.h"
|
||||
|
||||
/**
|
||||
* meta_create_color_texture_4ub:
|
||||
* @red: red component
|
||||
* @green: green component
|
||||
* @blue: blue component
|
||||
* @alpha: alpha component
|
||||
* @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE;
|
||||
* %COGL_TEXTURE_NO_SLICING is useful if the texture will be
|
||||
* repeated to create a constant color fill, since hardware
|
||||
* repeat can't be used for a sliced texture.
|
||||
*
|
||||
* Creates a texture that is a single pixel with the specified
|
||||
* unpremultiplied color components.
|
||||
*
|
||||
* Return value: (transfer full): a newly created Cogl texture
|
||||
*/
|
||||
CoglTexture *
|
||||
meta_create_color_texture_4ub (guint8 red,
|
||||
guint8 green,
|
||||
guint8 blue,
|
||||
guint8 alpha,
|
||||
CoglTextureFlags flags)
|
||||
{
|
||||
CoglColor color;
|
||||
guint8 pixel[4];
|
||||
|
||||
cogl_color_init_from_4ub (&color, red, green, blue, alpha);
|
||||
cogl_color_premultiply (&color);
|
||||
|
||||
pixel[0] = cogl_color_get_red_byte (&color);
|
||||
pixel[1] = cogl_color_get_green_byte (&color);
|
||||
pixel[2] = cogl_color_get_blue_byte (&color);
|
||||
pixel[3] = cogl_color_get_alpha_byte (&color);
|
||||
|
||||
return cogl_texture_new_from_data (1, 1,
|
||||
flags,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
4, pixel);
|
||||
}
|
||||
|
||||
|
||||
/* Based on gnome-shell/src/st/st-private.c:_st_create_texture_material.c */
|
||||
|
||||
/**
|
||||
* meta_create_texture_pipeline:
|
||||
* @src_texture: (allow-none): texture to use initially for the layer
|
||||
* @src_texture: (nullable): texture to use initially for the layer
|
||||
*
|
||||
* Creates a pipeline with a single layer. Using a common template
|
||||
* makes it easier for Cogl to share a shader for different uses in
|
||||
@@ -106,3 +64,78 @@ meta_create_texture_pipeline (CoglTexture *src_texture)
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
static gboolean is_pot(int x)
|
||||
{
|
||||
return x > 0 && (x & (x - 1)) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_create_texture:
|
||||
* @width: width of the texture to create
|
||||
* @height: height of the texture to create
|
||||
* @components; components to store in the texture (color or alpha)
|
||||
* @flags: flags that affect the allocation behavior
|
||||
*
|
||||
* Creates a texture of the given size with the specified components
|
||||
* for use as a frame buffer object.
|
||||
*
|
||||
* If non-power-of-two textures are not supported on the system, then
|
||||
* the texture will be created as a texture rectangle; in this case,
|
||||
* hardware repeating isn't possible, and texture coordinates are also
|
||||
* different, but Cogl hides these issues from the application, except from
|
||||
* GLSL shaders. Since GLSL is never (or at least almost never)
|
||||
* present on such a system, this is not typically an issue.
|
||||
*
|
||||
* If %META_TEXTURE_ALLOW_SLICING is present in @flags, and the texture
|
||||
* is larger than the texture size limits of the system, then the texture
|
||||
* will be created as a sliced texture. This also will cause problems
|
||||
* with using the texture with GLSL, and is more likely to be an issue
|
||||
* since all GL implementations have texture size limits, and they can
|
||||
* be as small as 2048x2048 on reasonably current systems.
|
||||
*/
|
||||
CoglTexture *
|
||||
meta_create_texture (int width,
|
||||
int height,
|
||||
CoglTextureComponents components,
|
||||
MetaTextureFlags flags)
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
|
||||
CoglTexture *texture;
|
||||
|
||||
gboolean should_use_rectangle = FALSE;
|
||||
|
||||
if (!(is_pot (width) && is_pot (height)) &&
|
||||
!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT))
|
||||
{
|
||||
if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_RECTANGLE))
|
||||
should_use_rectangle = TRUE;
|
||||
else
|
||||
g_error ("Cannot create texture. Support for GL_ARB_texture_non_power_of_two or "
|
||||
"ARB_texture_rectangle is required");
|
||||
}
|
||||
|
||||
if (should_use_rectangle)
|
||||
texture = COGL_TEXTURE (cogl_texture_rectangle_new_with_size (ctx, width, height));
|
||||
else
|
||||
texture = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx, width, height));
|
||||
cogl_texture_set_components (texture, components);
|
||||
|
||||
if ((flags & META_TEXTURE_ALLOW_SLICING) != 0)
|
||||
{
|
||||
/* To find out if we need to slice the texture, we have to go ahead and force storage
|
||||
* to be allocated
|
||||
*/
|
||||
CoglError *catch_error = NULL;
|
||||
if (!cogl_texture_allocate (texture, &catch_error))
|
||||
{
|
||||
cogl_error_free (catch_error);
|
||||
cogl_object_unref (texture);
|
||||
texture = COGL_TEXTURE (cogl_texture_2d_sliced_new_with_size (ctx, width, height, COGL_TEXTURE_MAX_WASTE));
|
||||
cogl_texture_set_components (texture, components);
|
||||
}
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
@@ -23,11 +23,16 @@
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
CoglTexture * meta_create_color_texture_4ub (guint8 red,
|
||||
guint8 green,
|
||||
guint8 blue,
|
||||
guint8 alpha,
|
||||
CoglTextureFlags flags);
|
||||
CoglPipeline * meta_create_texture_pipeline (CoglTexture *texture);
|
||||
|
||||
typedef enum {
|
||||
META_TEXTURE_FLAGS_NONE = 0,
|
||||
META_TEXTURE_ALLOW_SLICING = 1 << 1
|
||||
} MetaTextureFlags;
|
||||
|
||||
CoglTexture *meta_create_texture (int width,
|
||||
int height,
|
||||
CoglTextureComponents components,
|
||||
MetaTextureFlags flags);
|
||||
|
||||
#endif /* __META_COGL_UTILS_H__ */
|
||||
|
@@ -38,6 +38,8 @@ struct _MetaCompositor
|
||||
gint switch_workspace_in_progress;
|
||||
|
||||
MetaPluginManager *plugin_mgr;
|
||||
|
||||
gboolean frame_has_updated_xsurfaces;
|
||||
};
|
||||
|
||||
/* Wait 2ms after vblank before starting to draw next frame */
|
||||
|
@@ -67,40 +67,29 @@
|
||||
#include <meta/compositor-mutter.h>
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/main.h>
|
||||
#include <meta/meta-backend.h>
|
||||
#include <meta/meta-background-actor.h>
|
||||
#include <meta/meta-background-group.h>
|
||||
#include <meta/meta-shadow-factory.h>
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-window-group.h"
|
||||
#include "meta-stage.h"
|
||||
#include "window-private.h" /* to check window->hidden */
|
||||
#include "display-private.h" /* for meta_display_lookup_x_window() */
|
||||
#include "display-private.h" /* for meta_display_lookup_x_window() and meta_display_cancel_touch() */
|
||||
#include "util-private.h"
|
||||
#include "frame.h"
|
||||
#include <X11/extensions/shape.h>
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
|
||||
#include "backends/meta-backend.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
is_modal (MetaDisplay *display)
|
||||
{
|
||||
return display->grab_op == META_GRAB_OP_COMPOSITOR;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
composite_at_least_version (MetaDisplay *display, int maj, int min)
|
||||
{
|
||||
static int major = -1;
|
||||
static int minor = -1;
|
||||
|
||||
if (major == -1)
|
||||
meta_display_get_compositor_version (display, &major, &minor);
|
||||
|
||||
return (major > maj || (major == maj && minor >= min));
|
||||
return display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB;
|
||||
}
|
||||
|
||||
static void sync_actor_stacking (MetaCompositor *compositor);
|
||||
@@ -146,33 +135,8 @@ process_damage (MetaCompositor *compositor,
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
meta_window_actor_process_x11_damage (window_actor, event);
|
||||
}
|
||||
|
||||
static Window
|
||||
get_output_window (MetaCompositor *compositor)
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
Window output;
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
output = XCompositeGetOverlayWindow (xdisplay, DefaultRootWindow (xdisplay));
|
||||
|
||||
meta_core_add_old_event_mask (xdisplay, output, &mask);
|
||||
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
XISetMask (mask.mask, XI_FocusIn);
|
||||
XISetMask (mask.mask, XI_FocusOut);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
XISelectEvents (xdisplay, output, &mask, 1);
|
||||
|
||||
return output;
|
||||
compositor->frame_has_updated_xsurfaces = TRUE;
|
||||
}
|
||||
|
||||
/* compat helper */
|
||||
@@ -381,12 +345,20 @@ meta_begin_modal_for_plugin (MetaCompositor *compositor,
|
||||
return FALSE;
|
||||
|
||||
display->grab_op = META_GRAB_OP_COMPOSITOR;
|
||||
display->event_route = META_EVENT_ROUTE_COMPOSITOR_GRAB;
|
||||
display->grab_window = NULL;
|
||||
display->grab_have_pointer = TRUE;
|
||||
display->grab_have_keyboard = TRUE;
|
||||
|
||||
g_signal_emit_by_name (display, "grab-op-begin",
|
||||
meta_plugin_get_screen (plugin),
|
||||
display->grab_window, display->grab_op);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
meta_display_sync_wayland_input_focus (display);
|
||||
{
|
||||
meta_display_sync_wayland_input_focus (display);
|
||||
meta_display_cancel_touch (display);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -401,7 +373,12 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
|
||||
|
||||
g_return_if_fail (is_modal (display));
|
||||
|
||||
g_signal_emit_by_name (display, "grab-op-end",
|
||||
meta_plugin_get_screen (plugin),
|
||||
display->grab_window, display->grab_op);
|
||||
|
||||
display->grab_op = META_GRAB_OP_NONE;
|
||||
display->event_route = META_EVENT_ROUTE_NORMAL;
|
||||
display->grab_window = NULL;
|
||||
display->grab_have_pointer = FALSE;
|
||||
display->grab_have_keyboard = FALSE;
|
||||
@@ -423,8 +400,10 @@ after_stage_paint (ClutterStage *stage,
|
||||
for (l = compositor->windows; l; l = l->next)
|
||||
meta_window_actor_post_paint (l->data);
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (meta_is_wayland_compositor ())
|
||||
meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ());
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -476,62 +455,24 @@ meta_compositor_manage (MetaCompositor *compositor)
|
||||
MetaDisplay *display = compositor->display;
|
||||
Display *xdisplay = display->xdisplay;
|
||||
MetaScreen *screen = display->screen;
|
||||
Window xwin = 0;
|
||||
gint width, height;
|
||||
|
||||
meta_screen_set_cm_selection (display->screen);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaWaylandCompositor *wayland_compositor = meta_wayland_compositor_get_default ();
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
compositor->stage = meta_backend_get_stage (backend);
|
||||
}
|
||||
|
||||
compositor->stage = meta_stage_new ();
|
||||
clutter_actor_show (compositor->stage);
|
||||
|
||||
wayland_compositor->stage = compositor->stage;
|
||||
|
||||
meta_screen_get_size (screen, &width, &height);
|
||||
clutter_actor_set_size (compositor->stage, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
compositor->stage = clutter_stage_new ();
|
||||
|
||||
meta_screen_get_size (screen, &width, &height);
|
||||
clutter_actor_realize (compositor->stage);
|
||||
|
||||
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
|
||||
|
||||
XResizeWindow (xdisplay, xwin, width, height);
|
||||
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
meta_core_add_old_event_mask (backend_xdisplay, xwin, &mask);
|
||||
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
XISetMask (mask.mask, XI_FocusIn);
|
||||
XISetMask (mask.mask, XI_FocusOut);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
XIClearMask (mask.mask, XI_TouchBegin);
|
||||
XIClearMask (mask.mask, XI_TouchEnd);
|
||||
XIClearMask (mask.mask, XI_TouchUpdate);
|
||||
XISelectEvents (backend_xdisplay, xwin, &mask, 1);
|
||||
}
|
||||
}
|
||||
|
||||
clutter_stage_set_paint_callback (CLUTTER_STAGE (compositor->stage),
|
||||
after_stage_paint,
|
||||
compositor,
|
||||
NULL);
|
||||
/* We use connect_after() here to accomodate code in GNOME Shell that,
|
||||
* when benchmarking drawing performance, connects to ::after-paint
|
||||
* and calls glFinish(). The timing information from that will be
|
||||
* more accurate if we hold off until that completes before we signal
|
||||
* apps to begin drawing the next frame. If there are no other
|
||||
* connections to ::after-paint, connect() vs. connect_after() doesn't
|
||||
* matter.
|
||||
*/
|
||||
g_signal_connect_after (CLUTTER_STAGE (compositor->stage), "after-paint",
|
||||
G_CALLBACK (after_stage_paint), compositor);
|
||||
|
||||
clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY);
|
||||
|
||||
@@ -550,15 +491,20 @@ meta_compositor_manage (MetaCompositor *compositor)
|
||||
}
|
||||
else
|
||||
{
|
||||
compositor->output = get_output_window (compositor);
|
||||
Window xwin;
|
||||
|
||||
compositor->output = screen->composite_overlay_window;
|
||||
|
||||
xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (meta_get_backend ()));
|
||||
|
||||
XReparentWindow (xdisplay, xwin, compositor->output, 0, 0);
|
||||
|
||||
meta_empty_stage_input_region (screen);
|
||||
|
||||
/* Make sure there isn't any left-over output shape on the
|
||||
/* Make sure there isn't any left-over output shape on the
|
||||
* overlay window by setting the whole screen to be an
|
||||
* output region.
|
||||
*
|
||||
*
|
||||
* Note: there doesn't seem to be any real chance of that
|
||||
* because the X server will destroy the overlay window
|
||||
* when the last client using it exits.
|
||||
@@ -595,7 +541,7 @@ meta_compositor_unmanage (MetaCompositor *compositor)
|
||||
/**
|
||||
* meta_shape_cow_for_window:
|
||||
* @compositor: A #MetaCompositor
|
||||
* @window: (allow-none): A #MetaWindow to shape the COW for
|
||||
* @window: (nullable): A #MetaWindow to shape the COW for
|
||||
*
|
||||
* Sets an bounding shape on the COW so that the given window
|
||||
* is exposed. If @window is %NULL it clears the shape again.
|
||||
@@ -691,12 +637,11 @@ meta_compositor_remove_window (MetaCompositor *compositor,
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_set_updates_frozen (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
gboolean updates_frozen)
|
||||
meta_compositor_sync_updates_frozen (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
meta_window_actor_set_updates_frozen (window_actor, updates_frozen);
|
||||
meta_window_actor_sync_updates_frozen (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -746,9 +691,9 @@ meta_compositor_window_surface_changed (MetaCompositor *compositor,
|
||||
|
||||
/**
|
||||
* meta_compositor_process_event: (skip)
|
||||
* @compositor:
|
||||
* @event:
|
||||
* @window:
|
||||
* @compositor:
|
||||
* @event:
|
||||
* @window:
|
||||
*
|
||||
*/
|
||||
gboolean
|
||||
@@ -756,9 +701,6 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
|
||||
return TRUE;
|
||||
|
||||
if (!meta_is_wayland_compositor () &&
|
||||
event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
|
||||
{
|
||||
@@ -978,7 +920,7 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
|
||||
old_actor = old_stack->data;
|
||||
old_window = meta_window_actor_get_meta_window (old_actor);
|
||||
|
||||
if (old_window->hidden &&
|
||||
if ((old_window->hidden || old_window->unmanaging) &&
|
||||
!meta_window_actor_effect_in_progress (old_actor))
|
||||
{
|
||||
old_stack = g_list_delete_link (old_stack, old_stack);
|
||||
@@ -1012,7 +954,7 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
|
||||
* filtered out non-animating hidden windows above.
|
||||
*/
|
||||
if (old_actor &&
|
||||
(!stack_actor || old_window->hidden))
|
||||
(!stack_actor || old_window->hidden || old_window->unmanaging))
|
||||
{
|
||||
actor = old_actor;
|
||||
window = old_window;
|
||||
@@ -1046,43 +988,6 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor,
|
||||
meta_window_actor_sync_actor_geometry (window_actor, did_placement);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_sync_screen_size (MetaCompositor *compositor,
|
||||
guint width,
|
||||
guint height)
|
||||
{
|
||||
MetaDisplay *display = compositor->display;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
/* FIXME: when we support a sliced stage, this is the place to do it
|
||||
But! This is not the place to apply KMS config, here we only
|
||||
notify Clutter/Cogl/GL that the framebuffer sizes changed.
|
||||
|
||||
And because for now clutter does not do sliced, we use one
|
||||
framebuffer the size of the whole screen, and when running on
|
||||
bare metal MetaMonitorManager will do the necessary tricks to
|
||||
show the right portions on the right screens.
|
||||
*/
|
||||
|
||||
clutter_actor_set_size (compositor->stage, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
Display *xdisplay;
|
||||
Window xwin;
|
||||
|
||||
xdisplay = meta_display_get_xdisplay (display);
|
||||
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
|
||||
|
||||
XResizeWindow (xdisplay, xwin, width, height);
|
||||
}
|
||||
|
||||
meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
|
||||
meta_screen_get_screen_number (display->screen),
|
||||
width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
frame_callback (CoglOnscreen *onscreen,
|
||||
CoglFrameEvent event,
|
||||
@@ -1153,6 +1058,33 @@ pre_paint_windows (MetaCompositor *compositor)
|
||||
|
||||
for (l = compositor->windows; l; l = l->next)
|
||||
meta_window_actor_pre_paint (l->data);
|
||||
|
||||
if (compositor->frame_has_updated_xsurfaces)
|
||||
{
|
||||
/* We need to make sure that any X drawing that happens before
|
||||
* the XDamageSubtract() for each window above is visible to
|
||||
* subsequent GL rendering; the only standardized way to do this
|
||||
* is EXT_x11_sync_object, which isn't yet widely available. For
|
||||
* now, we count on details of Xorg and the open source drivers,
|
||||
* and hope for the best otherwise.
|
||||
*
|
||||
* Xorg and open source driver specifics:
|
||||
*
|
||||
* The X server makes sure to flush drawing to the kernel before
|
||||
* sending out damage events, but since we use
|
||||
* DamageReportBoundingBox there may be drawing between the last
|
||||
* damage event and the XDamageSubtract() that needs to be
|
||||
* flushed as well.
|
||||
*
|
||||
* Xorg always makes sure that drawing is flushed to the kernel
|
||||
* before writing events or responses to the client, so any
|
||||
* round trip request at this point is sufficient to flush the
|
||||
* GLX buffers.
|
||||
*/
|
||||
XSync (compositor->display->xdisplay, False);
|
||||
|
||||
compositor->frame_has_updated_xsurfaces = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1183,11 +1115,7 @@ meta_compositor_new (MetaDisplay *display)
|
||||
{
|
||||
MetaCompositor *compositor;
|
||||
|
||||
if (!composite_at_least_version (display, 0, 3))
|
||||
return NULL;
|
||||
|
||||
compositor = g_new0 (MetaCompositor, 1);
|
||||
|
||||
compositor->display = display;
|
||||
|
||||
if (g_getenv("META_DISABLE_MIPMAPS"))
|
||||
@@ -1356,3 +1284,22 @@ meta_compositor_hide_tile_preview (MetaCompositor *compositor)
|
||||
{
|
||||
meta_plugin_manager_hide_tile_preview (compositor->plugin_mgr);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_show_window_menu (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
meta_plugin_manager_show_window_menu (compositor->plugin_mgr, window, menu, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_show_window_menu_for_rect (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
meta_plugin_manager_show_window_menu_for_rect (compositor->plugin_mgr, window, menu, rect);
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Copyright 2009 Sander Dijkhuis
|
||||
* Copyright 2010 Red Hat, Inc.
|
||||
* Copyright 2014 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@@ -26,23 +26,122 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
/*
|
||||
* The overall model drawing model of this widget is that we have one
|
||||
* texture, or two interpolated textures, possibly with alpha or
|
||||
* margins that let the underlying background show through, blended
|
||||
* over a solid color or a gradient. The result of that combination
|
||||
* can then be affected by a "vignette" that darkens the background
|
||||
* away from a central point (or as a no-GLSL fallback, simply darkens
|
||||
* the background) and by overall opacity.
|
||||
*
|
||||
* As of GNOME 3.14, GNOME is only using a fraction of this when the
|
||||
* user sets the background through the control center - what can be
|
||||
* set is:
|
||||
*
|
||||
* A single image without a border
|
||||
* An animation of images without a border that blend together,
|
||||
* with the blend changing every 4-5 minutes
|
||||
* A solid color with a repeated noise texture blended over it
|
||||
*
|
||||
* This all is pretty easy to do in a fragment shader, except when:
|
||||
*
|
||||
* A) We don't have GLSL - in this case, the operation of
|
||||
* interpolating the two textures and blending the result over the
|
||||
* background can't be expressed with Cogl's fixed-function layer
|
||||
* combining (which is confined to what GL's texture environment
|
||||
* combining can do) So we can only handle the above directly if
|
||||
* there are no margins or alpha.
|
||||
*
|
||||
* B) The image textures are sliced. Texture size limits on older
|
||||
* hardware (pre-965 intel hardware, r300, etc.) is often 2048,
|
||||
* and it would be common to use a texture larger than this for a
|
||||
* background and expect it to be scaled down. Cogl can compensate
|
||||
* for this by breaking the texture up into multiple textures, but
|
||||
* can't multitexture with sliced textures. So we can only handle
|
||||
* the above if there's a single texture.
|
||||
*
|
||||
* However, even when we *can* represent everything in a single pass,
|
||||
* it's not necessarily efficient. If we want to draw a 1024x768
|
||||
* background, it's pretty inefficient to bilinearly texture from
|
||||
* two 2560x1440 images and mix that. So the drawing model we take
|
||||
* here is that MetaBackground generates a single texture (which
|
||||
* might be a 1x1 texture for a solid color, or a 1x2 texture for a
|
||||
* gradient, or a repeated texture for wallpaper, or a pre-rendered
|
||||
* texture the size of the screen), and we draw with that, possibly
|
||||
* adding the vignette and opacity.
|
||||
*/
|
||||
|
||||
#include <cogl/cogl-texture-pixmap-x11.h>
|
||||
#include <config.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "cogl-utils.h"
|
||||
#include "compositor-private.h"
|
||||
#include "clutter-utils.h"
|
||||
#include <meta/errors.h>
|
||||
#include <meta/meta-background.h>
|
||||
#include "meta-background-actor-private.h"
|
||||
#include "meta-background-private.h"
|
||||
#include "meta-cullable.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_META_SCREEN = 1,
|
||||
PROP_MONITOR,
|
||||
PROP_BACKGROUND,
|
||||
PROP_VIGNETTE,
|
||||
PROP_VIGNETTE_SHARPNESS,
|
||||
PROP_BRIGHTNESS
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CHANGED_BACKGROUND = 1 << 0,
|
||||
CHANGED_EFFECTS = 1 << 2,
|
||||
CHANGED_VIGNETTE_PARAMETERS = 1 << 3,
|
||||
CHANGED_ALL = 0xFFFF
|
||||
} ChangedFlags;
|
||||
|
||||
#define VERTEX_SHADER_DECLARATIONS \
|
||||
"uniform vec2 scale;\n" \
|
||||
"uniform vec2 offset;\n" \
|
||||
"varying vec2 position;\n" \
|
||||
|
||||
#define VERTEX_SHADER_CODE \
|
||||
"position = cogl_tex_coord0_in.xy * scale + offset;\n" \
|
||||
|
||||
#define FRAGMENT_SHADER_DECLARATIONS \
|
||||
"uniform float vignette_sharpness;\n" \
|
||||
"varying vec2 position;\n" \
|
||||
|
||||
#define FRAGMENT_SHADER_CODE \
|
||||
"float t = 2.0 * length(position);\n" \
|
||||
"t = min(t, 1.0);\n" \
|
||||
"float pixel_brightness = 1 - t * vignette_sharpness;\n" \
|
||||
"cogl_color_out.rgb = cogl_color_out.rgb * pixel_brightness;\n" \
|
||||
|
||||
typedef struct _MetaBackgroundLayer MetaBackgroundLayer;
|
||||
|
||||
typedef enum {
|
||||
PIPELINE_VIGNETTE = (1 << 0),
|
||||
PIPELINE_BLEND = (1 << 1),
|
||||
} PipelineFlags;
|
||||
|
||||
struct _MetaBackgroundActorPrivate
|
||||
{
|
||||
MetaScreen *screen;
|
||||
int monitor;
|
||||
|
||||
MetaBackground *background;
|
||||
|
||||
gboolean vignette;
|
||||
double brightness;
|
||||
double vignette_sharpness;
|
||||
|
||||
ChangedFlags changed;
|
||||
CoglPipeline *pipeline;
|
||||
PipelineFlags pipeline_flags;
|
||||
cairo_rectangle_int_t texture_area;
|
||||
gboolean force_bilinear;
|
||||
|
||||
cairo_region_t *clip_region;
|
||||
};
|
||||
|
||||
@@ -66,27 +165,45 @@ static void
|
||||
meta_background_actor_dispose (GObject *object)
|
||||
{
|
||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
|
||||
set_clip_region (self, NULL);
|
||||
meta_background_actor_set_background (self, NULL);
|
||||
if (priv->pipeline)
|
||||
{
|
||||
cogl_object_unref (priv->pipeline);
|
||||
priv->pipeline = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
get_preferred_size (MetaBackgroundActor *self,
|
||||
gfloat *width,
|
||||
gfloat *height)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv = META_BACKGROUND_ACTOR (self)->priv;
|
||||
MetaRectangle monitor_geometry;
|
||||
|
||||
meta_screen_get_monitor_geometry (priv->screen, priv->monitor, &monitor_geometry);
|
||||
|
||||
if (width != NULL)
|
||||
*width = monitor_geometry.width;
|
||||
|
||||
if (height != NULL)
|
||||
*height = monitor_geometry.height;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_get_preferred_width (ClutterActor *actor,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
ClutterContent *content;
|
||||
gfloat width;
|
||||
|
||||
content = clutter_actor_get_content (actor);
|
||||
|
||||
if (content)
|
||||
clutter_content_get_preferred_size (content, &width, NULL);
|
||||
else
|
||||
width = 0;
|
||||
get_preferred_size (META_BACKGROUND_ACTOR (actor), &width, NULL);
|
||||
|
||||
if (min_width_p)
|
||||
*min_width_p = width;
|
||||
@@ -101,15 +218,9 @@ meta_background_actor_get_preferred_height (ClutterActor *actor,
|
||||
gfloat *natural_height_p)
|
||||
|
||||
{
|
||||
ClutterContent *content;
|
||||
gfloat height;
|
||||
|
||||
content = clutter_actor_get_content (actor);
|
||||
|
||||
if (content)
|
||||
clutter_content_get_preferred_size (content, NULL, &height);
|
||||
else
|
||||
height = 0;
|
||||
get_preferred_size (META_BACKGROUND_ACTOR (actor), NULL, &height);
|
||||
|
||||
if (min_height_p)
|
||||
*min_height_p = height;
|
||||
@@ -117,43 +228,430 @@ meta_background_actor_get_preferred_height (ClutterActor *actor,
|
||||
*natural_height_p = height;
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
make_pipeline (PipelineFlags pipeline_flags)
|
||||
{
|
||||
static CoglPipeline *templates[4];
|
||||
CoglPipeline **templatep;
|
||||
|
||||
templatep = &templates[pipeline_flags];
|
||||
if (*templatep == NULL)
|
||||
{
|
||||
/* Cogl automatically caches pipelines with no eviction policy,
|
||||
* so we need to prevent identical pipelines from getting cached
|
||||
* separately, by reusing the same shader snippets.
|
||||
*/
|
||||
*templatep = COGL_PIPELINE (meta_create_texture_pipeline (NULL));
|
||||
|
||||
if ((pipeline_flags & PIPELINE_VIGNETTE) != 0)
|
||||
{
|
||||
static CoglSnippet *vertex_snippet;
|
||||
static CoglSnippet *fragment_snippet;
|
||||
|
||||
if (!vertex_snippet)
|
||||
vertex_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX,
|
||||
VERTEX_SHADER_DECLARATIONS, VERTEX_SHADER_CODE);
|
||||
|
||||
cogl_pipeline_add_snippet (*templatep, vertex_snippet);
|
||||
|
||||
if (!fragment_snippet)
|
||||
fragment_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
|
||||
FRAGMENT_SHADER_DECLARATIONS, FRAGMENT_SHADER_CODE);
|
||||
|
||||
cogl_pipeline_add_snippet (*templatep, fragment_snippet);
|
||||
}
|
||||
|
||||
if ((pipeline_flags & PIPELINE_BLEND) == 0)
|
||||
cogl_pipeline_set_blend (*templatep, "RGBA = ADD (SRC_COLOR, 0)", NULL);
|
||||
}
|
||||
|
||||
return cogl_pipeline_copy (*templatep);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_pipeline (MetaBackgroundActor *self,
|
||||
cairo_rectangle_int_t *actor_pixel_rect)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
PipelineFlags pipeline_flags = 0;
|
||||
guint8 opacity;
|
||||
float color_component;
|
||||
CoglPipelineFilter filter;
|
||||
|
||||
opacity = clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self));
|
||||
if (opacity < 255)
|
||||
pipeline_flags |= PIPELINE_BLEND;
|
||||
if (priv->vignette && clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
pipeline_flags |= PIPELINE_VIGNETTE;
|
||||
|
||||
if (priv->pipeline &&
|
||||
pipeline_flags != priv->pipeline_flags)
|
||||
{
|
||||
cogl_object_unref (priv->pipeline);
|
||||
priv->pipeline = NULL;
|
||||
}
|
||||
|
||||
if (priv->pipeline == NULL)
|
||||
{
|
||||
priv->pipeline_flags = pipeline_flags;
|
||||
priv->pipeline = make_pipeline (pipeline_flags);
|
||||
priv->changed = CHANGED_ALL;
|
||||
}
|
||||
|
||||
if ((priv->changed & CHANGED_BACKGROUND) != 0)
|
||||
{
|
||||
CoglPipelineWrapMode wrap_mode;
|
||||
CoglTexture *texture = meta_background_get_texture (priv->background,
|
||||
priv->monitor,
|
||||
&priv->texture_area,
|
||||
&wrap_mode);
|
||||
priv->force_bilinear = texture &&
|
||||
(priv->texture_area.width != (int)cogl_texture_get_width (texture) ||
|
||||
priv->texture_area.height != (int)cogl_texture_get_height (texture));
|
||||
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
|
||||
cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0, wrap_mode);
|
||||
}
|
||||
|
||||
if ((priv->changed & CHANGED_VIGNETTE_PARAMETERS) != 0)
|
||||
{
|
||||
cogl_pipeline_set_uniform_1f (priv->pipeline,
|
||||
cogl_pipeline_get_uniform_location (priv->pipeline,
|
||||
"vignette_sharpness"),
|
||||
priv->vignette_sharpness);
|
||||
}
|
||||
|
||||
if (priv->vignette)
|
||||
{
|
||||
color_component = priv->brightness * opacity / 255.;
|
||||
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
{
|
||||
/* Darken everything to match the average brightness that would
|
||||
* be there if we were drawing the vignette, which is
|
||||
* (1 - (pi/12.) * vignette_sharpness) [exercise for the reader :]
|
||||
*/
|
||||
color_component *= (1 - 0.74 * priv->vignette_sharpness);
|
||||
}
|
||||
}
|
||||
else
|
||||
color_component = opacity / 255.;
|
||||
|
||||
cogl_pipeline_set_color4f (priv->pipeline,
|
||||
color_component,
|
||||
color_component,
|
||||
color_component,
|
||||
opacity / 255.);
|
||||
|
||||
if (!priv->force_bilinear &&
|
||||
meta_actor_painting_untransformed (actor_pixel_rect->width, actor_pixel_rect->height, NULL, NULL))
|
||||
filter = COGL_PIPELINE_FILTER_NEAREST;
|
||||
else
|
||||
filter = COGL_PIPELINE_FILTER_LINEAR;
|
||||
|
||||
cogl_pipeline_set_layer_filters (priv->pipeline, 0, filter, filter);
|
||||
}
|
||||
|
||||
static void
|
||||
set_glsl_parameters (MetaBackgroundActor *self,
|
||||
cairo_rectangle_int_t *actor_pixel_rect)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
float scale[2];
|
||||
float offset[2];
|
||||
|
||||
/* Compute a scale and offset for transforming texture coordinates to the
|
||||
* coordinate system from [-0.5 to 0.5] across the area of the actor
|
||||
*/
|
||||
scale[0] = priv->texture_area.width / (float)actor_pixel_rect->width;
|
||||
scale[1] = priv->texture_area.height / (float)actor_pixel_rect->height;
|
||||
offset[0] = priv->texture_area.x / (float)actor_pixel_rect->width - 0.5;
|
||||
offset[1] = priv->texture_area.y / (float)actor_pixel_rect->height - 0.5;
|
||||
|
||||
cogl_pipeline_set_uniform_float (priv->pipeline,
|
||||
cogl_pipeline_get_uniform_location (priv->pipeline,
|
||||
"scale"),
|
||||
2, 1, scale);
|
||||
|
||||
cogl_pipeline_set_uniform_float (priv->pipeline,
|
||||
cogl_pipeline_get_uniform_location (priv->pipeline,
|
||||
"offset"),
|
||||
2, 1, offset);
|
||||
}
|
||||
|
||||
static void
|
||||
paint_clipped_rectangle (CoglFramebuffer *fb,
|
||||
CoglPipeline *pipeline,
|
||||
cairo_rectangle_int_t *rect,
|
||||
cairo_rectangle_int_t *texture_area)
|
||||
{
|
||||
float x1, y1, x2, y2;
|
||||
float tx1, ty1, tx2, ty2;
|
||||
|
||||
x1 = rect->x;
|
||||
y1 = rect->y;
|
||||
x2 = rect->x + rect->width;
|
||||
y2 = rect->y + rect->height;
|
||||
|
||||
tx1 = (x1 - texture_area->x) / texture_area->width;
|
||||
ty1 = (y1 - texture_area->y) / texture_area->height;
|
||||
tx2 = (x2 - texture_area->x) / texture_area->width;
|
||||
ty2 = (y2 - texture_area->y) / texture_area->height;
|
||||
|
||||
cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
|
||||
x1, y1, x2, y2,
|
||||
tx1, ty1, tx2, ty2);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_background_actor_get_paint_volume (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
return clutter_paint_volume_set_from_allocation (volume, actor);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
ClutterActorBox actor_box;
|
||||
cairo_rectangle_int_t actor_pixel_rect;
|
||||
CoglFramebuffer *fb;
|
||||
int i;
|
||||
|
||||
if ((priv->clip_region && cairo_region_is_empty (priv->clip_region)))
|
||||
return;
|
||||
|
||||
clutter_actor_get_content_box (actor, &actor_box);
|
||||
actor_pixel_rect.x = actor_box.x1;
|
||||
actor_pixel_rect.y = actor_box.y1;
|
||||
actor_pixel_rect.width = actor_box.x2 - actor_box.x1;
|
||||
actor_pixel_rect.height = actor_box.y2 - actor_box.y1;
|
||||
|
||||
setup_pipeline (self, &actor_pixel_rect);
|
||||
set_glsl_parameters (self, &actor_pixel_rect);
|
||||
|
||||
/* Limit to how many separate rectangles we'll draw; beyond this just
|
||||
* fall back and draw the whole thing */
|
||||
#define MAX_RECTS 64
|
||||
|
||||
fb = cogl_get_draw_framebuffer ();
|
||||
|
||||
/* Now figure out what to actually paint.
|
||||
*/
|
||||
if (priv->clip_region != NULL)
|
||||
{
|
||||
int n_rects = cairo_region_num_rectangles (priv->clip_region);
|
||||
if (n_rects <= MAX_RECTS)
|
||||
{
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_region_get_rectangle (priv->clip_region, i, &rect);
|
||||
|
||||
if (!gdk_rectangle_intersect (&actor_pixel_rect, &rect, &rect))
|
||||
continue;
|
||||
|
||||
paint_clipped_rectangle (fb, priv->pipeline, &rect, &priv->texture_area);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
paint_clipped_rectangle (fb, priv->pipeline, &actor_pixel_rect, &priv->texture_area);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_META_SCREEN:
|
||||
priv->screen = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_MONITOR:
|
||||
priv->monitor = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_BACKGROUND:
|
||||
meta_background_actor_set_background (self, g_value_get_object (value));
|
||||
break;
|
||||
case PROP_VIGNETTE:
|
||||
meta_background_actor_set_vignette (self,
|
||||
g_value_get_boolean (value),
|
||||
priv->brightness,
|
||||
priv->vignette_sharpness);
|
||||
break;
|
||||
case PROP_VIGNETTE_SHARPNESS:
|
||||
meta_background_actor_set_vignette (self,
|
||||
priv->vignette,
|
||||
priv->brightness,
|
||||
g_value_get_double (value));
|
||||
break;
|
||||
case PROP_BRIGHTNESS:
|
||||
meta_background_actor_set_vignette (self,
|
||||
priv->vignette,
|
||||
g_value_get_double (value),
|
||||
priv->vignette_sharpness);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv = META_BACKGROUND_ACTOR (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_META_SCREEN:
|
||||
g_value_set_object (value, priv->screen);
|
||||
break;
|
||||
case PROP_MONITOR:
|
||||
g_value_set_int (value, priv->monitor);
|
||||
break;
|
||||
case PROP_BACKGROUND:
|
||||
g_value_set_object (value, priv->background);
|
||||
break;
|
||||
case PROP_VIGNETTE:
|
||||
g_value_set_boolean (value, priv->vignette);
|
||||
break;
|
||||
case PROP_BRIGHTNESS:
|
||||
g_value_set_double (value, priv->brightness);
|
||||
break;
|
||||
case PROP_VIGNETTE_SHARPNESS:
|
||||
g_value_set_double (value, priv->vignette_sharpness);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_class_init (MetaBackgroundActorClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
GParamSpec *param_spec;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaBackgroundActorPrivate));
|
||||
|
||||
object_class->dispose = meta_background_actor_dispose;
|
||||
object_class->set_property = meta_background_actor_set_property;
|
||||
object_class->get_property = meta_background_actor_get_property;
|
||||
|
||||
actor_class->get_preferred_width = meta_background_actor_get_preferred_width;
|
||||
actor_class->get_preferred_height = meta_background_actor_get_preferred_height;
|
||||
actor_class->get_paint_volume = meta_background_actor_get_paint_volume;
|
||||
actor_class->paint = meta_background_actor_paint;
|
||||
|
||||
param_spec = g_param_spec_object ("meta-screen",
|
||||
"MetaScreen",
|
||||
"MetaScreen",
|
||||
META_TYPE_SCREEN,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_META_SCREEN,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_int ("monitor",
|
||||
"monitor",
|
||||
"monitor",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_MONITOR,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_object ("background",
|
||||
"Background",
|
||||
"MetaBackground object holding background parameters",
|
||||
META_TYPE_BACKGROUND,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_BACKGROUND,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_boolean ("vignette",
|
||||
"Vignette",
|
||||
"Whether vignette effect is enabled",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_VIGNETTE,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_double ("brightness",
|
||||
"Brightness",
|
||||
"Brightness of vignette effect",
|
||||
0.0, 1.0, 1.0,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_BRIGHTNESS,
|
||||
param_spec);
|
||||
|
||||
param_spec = g_param_spec_double ("vignette-sharpness",
|
||||
"Vignette Sharpness",
|
||||
"Sharpness of vignette effect",
|
||||
0.0, G_MAXDOUBLE, 0.0,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_VIGNETTE_SHARPNESS,
|
||||
param_spec);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_init (MetaBackgroundActor *self)
|
||||
{
|
||||
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||
META_TYPE_BACKGROUND_ACTOR,
|
||||
MetaBackgroundActorPrivate);
|
||||
MetaBackgroundActorPrivate *priv;
|
||||
|
||||
priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||
META_TYPE_BACKGROUND_ACTOR,
|
||||
MetaBackgroundActorPrivate);
|
||||
|
||||
priv->vignette = FALSE;
|
||||
priv->brightness = 1.0;
|
||||
priv->vignette_sharpness = 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_background_actor_new:
|
||||
* @monitor: Index of the monitor for which to draw the background
|
||||
*
|
||||
* Creates a new actor to draw the background for the given monitor.
|
||||
* This actor should be associated with a #MetaBackground using
|
||||
* clutter_actor_set_content()
|
||||
*
|
||||
* Return value: the newly created background actor
|
||||
*/
|
||||
ClutterActor *
|
||||
meta_background_actor_new (void)
|
||||
meta_background_actor_new (MetaScreen *screen,
|
||||
int monitor)
|
||||
{
|
||||
MetaBackgroundActor *self;
|
||||
|
||||
self = g_object_new (META_TYPE_BACKGROUND_ACTOR, NULL);
|
||||
self = g_object_new (META_TYPE_BACKGROUND_ACTOR,
|
||||
"meta-screen", screen,
|
||||
"monitor", monitor,
|
||||
NULL);
|
||||
|
||||
return CLUTTER_ACTOR (self);
|
||||
}
|
||||
@@ -185,7 +683,7 @@ cullable_iface_init (MetaCullableInterface *iface)
|
||||
* meta_background_actor_get_clip_region:
|
||||
* @self: a #MetaBackgroundActor
|
||||
*
|
||||
* Return value (transfer full): a #cairo_region_t that represents the part of
|
||||
* Return value (transfer none): a #cairo_region_t that represents the part of
|
||||
* the background not obscured by other #MetaBackgroundActor or
|
||||
* #MetaWindowActor objects.
|
||||
*/
|
||||
@@ -193,24 +691,91 @@ cairo_region_t *
|
||||
meta_background_actor_get_clip_region (MetaBackgroundActor *self)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
ClutterActorBox content_box;
|
||||
cairo_rectangle_int_t content_area = { 0 };
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
g_return_val_if_fail (META_IS_BACKGROUND_ACTOR (self), NULL);
|
||||
|
||||
if (!priv->clip_region)
|
||||
return NULL;
|
||||
|
||||
clutter_actor_get_content_box (CLUTTER_ACTOR (self), &content_box);
|
||||
|
||||
content_area.x = content_box.x1;
|
||||
content_area.y = content_box.y1;
|
||||
content_area.width = content_box.x2 - content_box.x1;
|
||||
content_area.height = content_box.y2 - content_box.y1;
|
||||
|
||||
clip_region = cairo_region_create_rectangle (&content_area);
|
||||
cairo_region_intersect (clip_region, priv->clip_region);
|
||||
|
||||
return clip_region;
|
||||
return priv->clip_region;
|
||||
}
|
||||
|
||||
static void
|
||||
invalidate_pipeline (MetaBackgroundActor *self,
|
||||
ChangedFlags changed)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
|
||||
priv->changed |= changed;
|
||||
}
|
||||
|
||||
static void
|
||||
on_background_changed (MetaBackground *background,
|
||||
MetaBackgroundActor *self)
|
||||
{
|
||||
invalidate_pipeline (self, CHANGED_BACKGROUND);
|
||||
}
|
||||
|
||||
void
|
||||
meta_background_actor_set_background (MetaBackgroundActor *self,
|
||||
MetaBackground *background)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
|
||||
g_return_if_fail (background == NULL || META_IS_BACKGROUND (background));
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
if (background == priv->background)
|
||||
return;
|
||||
|
||||
if (priv->background)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (priv->background,
|
||||
(gpointer)on_background_changed,
|
||||
self);
|
||||
g_object_unref (priv->background);
|
||||
priv->background = NULL;
|
||||
}
|
||||
|
||||
if (background)
|
||||
{
|
||||
priv->background = g_object_ref (background);
|
||||
g_signal_connect (priv->background, "changed",
|
||||
G_CALLBACK (on_background_changed), self);
|
||||
}
|
||||
|
||||
invalidate_pipeline (self, CHANGED_BACKGROUND);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
void
|
||||
meta_background_actor_set_vignette (MetaBackgroundActor *self,
|
||||
gboolean enabled,
|
||||
double brightness,
|
||||
double sharpness)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv;
|
||||
gboolean changed = FALSE;
|
||||
|
||||
g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
|
||||
g_return_if_fail (brightness >= 0. && brightness <= 1.);
|
||||
g_return_if_fail (sharpness >= 0.);
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
enabled = enabled != FALSE;
|
||||
|
||||
if (enabled != priv->vignette)
|
||||
{
|
||||
priv->vignette = enabled;
|
||||
invalidate_pipeline (self, CHANGED_EFFECTS);
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (brightness != priv->brightness || sharpness != priv->vignette_sharpness)
|
||||
{
|
||||
priv->brightness = brightness;
|
||||
priv->vignette_sharpness = sharpness;
|
||||
invalidate_pipeline (self, CHANGED_VIGNETTE_PARAMETERS);
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
344
src/compositor/meta-background-image.c
Normal file
344
src/compositor/meta-background-image.c
Normal file
@@ -0,0 +1,344 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Copyright 2014 Red Hat, Inc.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:meta-background-image
|
||||
* @title: MetaBackgroundImage
|
||||
* @short_description: objects holding images loaded from files, used for backgrounds
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <meta/meta-background-image.h>
|
||||
#include "cogl-utils.h"
|
||||
|
||||
enum
|
||||
{
|
||||
LOADED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
struct _MetaBackgroundImageCache
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GHashTable *images;
|
||||
};
|
||||
|
||||
struct _MetaBackgroundImageCacheClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
struct _MetaBackgroundImage
|
||||
{
|
||||
GObject parent_instance;
|
||||
char *filename;
|
||||
MetaBackgroundImageCache *cache;
|
||||
gboolean in_cache;
|
||||
gboolean loaded;
|
||||
CoglTexture *texture;
|
||||
};
|
||||
|
||||
struct _MetaBackgroundImageClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaBackgroundImageCache, meta_background_image_cache, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
meta_background_image_cache_init (MetaBackgroundImageCache *cache)
|
||||
{
|
||||
cache->images = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_image_cache_finalize (GObject *object)
|
||||
{
|
||||
MetaBackgroundImageCache *cache = META_BACKGROUND_IMAGE_CACHE (object);
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
g_hash_table_iter_init (&iter, cache->images);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
MetaBackgroundImage *image = value;
|
||||
image->in_cache = FALSE;
|
||||
}
|
||||
|
||||
g_hash_table_destroy (cache->images);
|
||||
|
||||
G_OBJECT_CLASS (meta_background_image_cache_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_image_cache_class_init (MetaBackgroundImageCacheClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_background_image_cache_finalize;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_background_image_cache_get_default:
|
||||
*
|
||||
* Return value: (transfer none): the global singleton background cache
|
||||
*/
|
||||
MetaBackgroundImageCache *
|
||||
meta_background_image_cache_get_default (void)
|
||||
{
|
||||
static MetaBackgroundImageCache *cache;
|
||||
|
||||
if (cache == NULL)
|
||||
cache = g_object_new (META_TYPE_BACKGROUND_IMAGE_CACHE, NULL);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
static void
|
||||
load_file (GTask *task,
|
||||
MetaBackgroundImage *image,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_file (image->filename,
|
||||
&error);
|
||||
|
||||
if (pixbuf == NULL)
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_return_pointer (task, pixbuf, (GDestroyNotify) g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
file_loaded (GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaBackgroundImage *image = META_BACKGROUND_IMAGE (source_object);
|
||||
GError *error = NULL;
|
||||
GTask *task;
|
||||
CoglTexture *texture;
|
||||
GdkPixbuf *pixbuf;
|
||||
int width, height, row_stride;
|
||||
guchar *pixels;
|
||||
gboolean has_alpha;
|
||||
|
||||
task = G_TASK (result);
|
||||
pixbuf = g_task_propagate_pointer (task, &error);
|
||||
|
||||
if (pixbuf == NULL)
|
||||
{
|
||||
g_warning ("Failed to load background '%s': %s",
|
||||
image->filename, error->message);
|
||||
g_clear_error (&error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
width = gdk_pixbuf_get_width (pixbuf);
|
||||
height = gdk_pixbuf_get_height (pixbuf);
|
||||
row_stride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
|
||||
|
||||
texture = meta_create_texture (width, height,
|
||||
has_alpha ? COGL_TEXTURE_COMPONENTS_RGBA : COGL_TEXTURE_COMPONENTS_RGB,
|
||||
META_TEXTURE_ALLOW_SLICING);
|
||||
|
||||
if (!cogl_texture_set_data (texture,
|
||||
has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
|
||||
row_stride,
|
||||
pixels, 0,
|
||||
NULL))
|
||||
{
|
||||
g_warning ("Failed to create texture for background");
|
||||
cogl_object_unref (texture);
|
||||
}
|
||||
|
||||
image->texture = texture;
|
||||
|
||||
out:
|
||||
image->loaded = TRUE;
|
||||
g_signal_emit (image, signals[LOADED], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_background_image_cache_load:
|
||||
* @cache: a #MetaBackgroundImageCache
|
||||
* @filename: filename to load
|
||||
*
|
||||
* Loads an image to use as a background, or returns a reference to an
|
||||
* image that is already in the process of loading or loaded. In either
|
||||
* case, what is returned is a #MetaBackgroundImage which can be derefenced
|
||||
* to get a #CoglTexture. If meta_background_image_is_loaded() returns %TRUE,
|
||||
* the background is loaded, otherwise the MetaBackgroundImage::loaded
|
||||
* signal will be emitted exactly once. The 'loaded' state means that the
|
||||
* loading process finished, whether it succeeded or failed.
|
||||
*
|
||||
* Return value: (transfer full): a #MetaBackgroundImage to dereference to get the loaded texture
|
||||
*/
|
||||
MetaBackgroundImage *
|
||||
meta_background_image_cache_load (MetaBackgroundImageCache *cache,
|
||||
const char *filename)
|
||||
{
|
||||
MetaBackgroundImage *image;
|
||||
GTask *task;
|
||||
|
||||
g_return_val_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache), NULL);
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
|
||||
image = g_hash_table_lookup (cache->images, filename);
|
||||
if (image != NULL)
|
||||
return g_object_ref (image);
|
||||
|
||||
image = g_object_new (META_TYPE_BACKGROUND_IMAGE, NULL);
|
||||
image->cache = cache;
|
||||
image->in_cache = TRUE;
|
||||
image->filename = g_strdup (filename);
|
||||
g_hash_table_insert (cache->images, image->filename, image);
|
||||
|
||||
task = g_task_new (image, NULL, file_loaded, NULL);
|
||||
|
||||
g_task_run_in_thread (task, (GTaskThreadFunc) load_file);
|
||||
g_object_unref (task);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_background_image_cache_purge:
|
||||
* @cache: a #MetaBackgroundImageCache
|
||||
* @filename: filename to remove from the cache
|
||||
*
|
||||
* Remove an entry from the cache; this would be used if monitoring
|
||||
* showed that the file changed.
|
||||
*/
|
||||
void
|
||||
meta_background_image_cache_purge (MetaBackgroundImageCache *cache,
|
||||
const char *filename)
|
||||
{
|
||||
MetaBackgroundImage *image;
|
||||
|
||||
g_return_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache));
|
||||
g_return_if_fail (filename != NULL);
|
||||
|
||||
image = g_hash_table_lookup (cache->images, filename);
|
||||
if (image == NULL)
|
||||
return;
|
||||
|
||||
g_hash_table_remove (cache->images, image->filename);
|
||||
image->in_cache = FALSE;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE (MetaBackgroundImage, meta_background_image, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
meta_background_image_init (MetaBackgroundImage *image)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_image_finalize (GObject *object)
|
||||
{
|
||||
MetaBackgroundImage *image = META_BACKGROUND_IMAGE (object);
|
||||
|
||||
if (image->in_cache)
|
||||
g_hash_table_remove (image->cache->images, image->filename);
|
||||
|
||||
if (image->texture)
|
||||
cogl_object_unref (image->texture);
|
||||
if (image->filename)
|
||||
g_free (image->filename);
|
||||
|
||||
G_OBJECT_CLASS (meta_background_image_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_image_class_init (MetaBackgroundImageClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_background_image_finalize;
|
||||
|
||||
signals[LOADED] =
|
||||
g_signal_new ("loaded",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_background_image_is_loaded:
|
||||
* @image: a #MetaBackgroundImage
|
||||
*
|
||||
* Return value: %TRUE if loading has already completed, %FALSE otherwise
|
||||
*/
|
||||
gboolean
|
||||
meta_background_image_is_loaded (MetaBackgroundImage *image)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), FALSE);
|
||||
|
||||
return image->loaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_background_image_get_success:
|
||||
* @image: a #MetaBackgroundImage
|
||||
*
|
||||
* This function is a convenience function for checking for success,
|
||||
* without having to call meta_background_image_get_texture() and
|
||||
* handle the return of a Cogl type.
|
||||
*
|
||||
* Return value: %TRUE if loading completed successfully, otherwise %FALSE
|
||||
*/
|
||||
gboolean
|
||||
meta_background_image_get_success (MetaBackgroundImage *image)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), FALSE);
|
||||
|
||||
return image->texture != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_background_image_get_texture:
|
||||
* @image: a #MetaBackgroundImage
|
||||
*
|
||||
* Return value: (transfer none): a #CoglTexture if loading succeeded; if
|
||||
* loading failed or has not yet finished, %NULL.
|
||||
*/
|
||||
CoglTexture *
|
||||
meta_background_image_get_texture (MetaBackgroundImage *image)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), NULL);
|
||||
|
||||
return image->texture;
|
||||
}
|
15
src/compositor/meta-background-private.h
Normal file
15
src/compositor/meta-background-private.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#ifndef META_BACKGROUND_PRIVATE_H
|
||||
#define META_BACKGROUND_PRIVATE_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "meta-background-private.h"
|
||||
|
||||
CoglTexture *meta_background_get_texture (MetaBackground *self,
|
||||
int monitor_index,
|
||||
cairo_rectangle_int_t *texture_area,
|
||||
CoglPipelineWrapMode *wrap_mode);
|
||||
|
||||
#endif /* META_BACKGROUND_PRIVATE_H */
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user