Compare commits
1281 Commits
2.27.5
...
wip/messag
Author | SHA1 | Date | |
---|---|---|---|
2d02f6cc78 | |||
b5d5934e5a | |||
64b1c0f953 | |||
10d53fc7d2 | |||
eb1292ea99 | |||
e257580b94 | |||
42261156ec | |||
89e31f0d9d | |||
c805e397fd | |||
760a36aeee | |||
5d57a2594d | |||
1a5132d391 | |||
0fe0534c85 | |||
fe942049da | |||
e6ed29f0e2 | |||
15f11f879d | |||
f517eaf81e | |||
255347f876 | |||
e4ae7d7b1b | |||
2be943d1d9 | |||
0a50488bef | |||
78c966321a | |||
f65b7c59d3 | |||
e31f55e146 | |||
dc232b6cad | |||
a2f2e07e9b | |||
f5e48223c9 | |||
1478510392 | |||
18b38320a6 | |||
16be31b514 | |||
accc183474 | |||
81699619e8 | |||
75c87e5876 | |||
50bc4ad0e1 | |||
277e8bdad9 | |||
dc50ccf9b7 | |||
4595209346 | |||
50cf3dd1a5 | |||
66eac7824a | |||
4041f96ed3 | |||
3a15d637da | |||
5c3c7df948 | |||
f9454e29db | |||
574c0c3287 | |||
9fa5aa9889 | |||
80a70a4ad1 | |||
7c1b734053 | |||
33e1017403 | |||
f143fe3710 | |||
66406b3035 | |||
042ddc5637 | |||
5b04ab4473 | |||
16b86ae7f7 | |||
49400657ca | |||
30bc8bc6ce | |||
ac18f41ed1 | |||
60c05a0dac | |||
c47de98c88 | |||
f1aada0fae | |||
4de492eb20 | |||
9ca00d5cce | |||
b98e4e37ad | |||
8b64a951c9 | |||
c2a0719e44 | |||
8cb7a450ae | |||
6fb857cb23 | |||
fc87a635b2 | |||
81930ca76e | |||
da65738901 | |||
4528e1216a | |||
d56ecde39b | |||
4148a5cc6a | |||
8a6a568aca | |||
12cc0cee29 | |||
878b1012b4 | |||
a78fec7951 | |||
a24c512caa | |||
c669a3892e | |||
ba4f008d40 | |||
b0a099935b | |||
aba39ef953 | |||
ebf8c460e1 | |||
25d3432eee | |||
cd7a74fbcd | |||
c64188c67f | |||
4c2371f2e7 | |||
ff6c31dcc0 | |||
1b649c18ed | |||
93037e4c6b | |||
ed358c8f4b | |||
a22859a64a | |||
c44438b19f | |||
b58366d3ad | |||
6900128b2f | |||
c0b4d68390 | |||
0d794f28f0 | |||
e389eff79d | |||
41adbdda12 | |||
2d6555ca4d | |||
044d58951e | |||
9c97e8999e | |||
e97b38b38e | |||
8809673a74 | |||
68321d9bf4 | |||
65390e50a4 | |||
f8d32661b5 | |||
d84911fdf9 | |||
4147ea4660 | |||
2dd7c98641 | |||
3aad30143c | |||
93d06d4368 | |||
b19c061db5 | |||
497258f6e5 | |||
977e6388ad | |||
0879cf0d8d | |||
4aab7fb7b9 | |||
839fee19ef | |||
46a56bafbd | |||
c8b4939c7e | |||
fc3e82421a | |||
23046f6e28 | |||
823208120d | |||
d12c507b12 | |||
2157c238b6 | |||
423bda908e | |||
98d427ddba | |||
7a35579c3f | |||
adc89fbb2c | |||
a6ca3f768f | |||
9362fbdcde | |||
47099f4a87 | |||
2e6e5b068c | |||
ee840bc832 | |||
6333c174dc | |||
a3bf9b01aa | |||
402b477458 | |||
6b273ca713 | |||
c3ec6b34a3 | |||
78dc480e86 | |||
53364f986c | |||
5770b5b3c3 | |||
f16f47bd38 | |||
58a57185b7 | |||
8fb361cb26 | |||
335d211204 | |||
7f64d6b92e | |||
8c1b2d5eda | |||
578b1c06c7 | |||
6dfde43786 | |||
a8ead4d447 | |||
2926323a9a | |||
13bc8f7a76 | |||
ad516492d2 | |||
6677c61db3 | |||
f26f61ed7d | |||
8ca86fa8bf | |||
f2f500836e | |||
c39998efee | |||
3b811f33c7 | |||
beea2f7acd | |||
fb4c50478d | |||
ac0602a02e | |||
5361e0259f | |||
04bf73ff6d | |||
047b9de1c6 | |||
39b3244a3e | |||
63f982eb72 | |||
c689306dae | |||
0b7f2f8cd3 | |||
efc90173b1 | |||
9e439a22b5 | |||
848c1f52f3 | |||
1b84be7031 | |||
eb08a65b4c | |||
43ba596a0e | |||
2e1de1a037 | |||
81ede6abf8 | |||
1d98f1fee8 | |||
f0582d1a86 | |||
607dbf0f43 | |||
584cd3e684 | |||
90ec5b05f3 | |||
7253a75b18 | |||
cdbe3b274f | |||
3f3e3ce37e | |||
5e3d93da87 | |||
82b1d0d7e5 | |||
3583e57ec3 | |||
2ddde04678 | |||
feda493fbf | |||
fc72309b71 | |||
860c2a6282 | |||
e6b4a34daf | |||
3319cdfec0 | |||
fc5594faad | |||
7c9e0c2ebc | |||
9157cc2b70 | |||
69e7b32b54 | |||
04835eccb5 | |||
01c363bb6a | |||
7649772394 | |||
ca3dc2e876 | |||
70d85049b1 | |||
29f6f5e0ad | |||
d249cfd040 | |||
3cb912aee2 | |||
7df823132c | |||
41353d642b | |||
c47039db82 | |||
0dab6df25a | |||
c844bab232 | |||
848f9d1399 | |||
2e63de5c0a | |||
7319b10d72 | |||
1265efcf78 | |||
3e0ef03fd9 | |||
37076941ad | |||
25e43618a4 | |||
fd404bafc8 | |||
3b3b26b000 | |||
33498f6b84 | |||
c0a440b852 | |||
1772a2a59c | |||
44f362ad87 | |||
478f1020a4 | |||
e8209e7b22 | |||
2d20c9ecad | |||
f35160c30f | |||
7fad591d6e | |||
a364cea779 | |||
2eb3ff4bfb | |||
796ca6746d | |||
0a79fb8d62 | |||
ac7ec585c8 | |||
264c555af0 | |||
bbbb0e6002 | |||
41ae760454 | |||
9729a99ec5 | |||
d64c5bfc11 | |||
e4ed433e18 | |||
8ab5cc8f19 | |||
35261808a9 | |||
3a4512cd91 | |||
eb0185c1b1 | |||
34f6ffd1ad | |||
baeb9fbc4b | |||
c3d76aead6 | |||
bed9cb1648 | |||
4ca552785f | |||
b26b11c74d | |||
b3114bb9e5 | |||
497f9be61e | |||
a88365df9b | |||
47f98c5528 | |||
0e50287aea | |||
d42a2a3c27 | |||
78849bef04 | |||
b1a69d1e89 | |||
c5468ee391 | |||
7ce7feeb2b | |||
c0432ebb39 | |||
1a51d307c8 | |||
d0910da036 | |||
a2726f41c9 | |||
162213be0d | |||
1596d1af10 | |||
441287dc64 | |||
6e47f0e846 | |||
4fb2fab7f7 | |||
3beb33bb44 | |||
1b04a40dce | |||
8087872130 | |||
3ad25a62cd | |||
7ecd673d23 | |||
331c9aaee4 | |||
ec1979f9f5 | |||
4b411ea241 | |||
70db187c36 | |||
4de3f1d147 | |||
821d4458ea | |||
7f9472a58f | |||
3599917123 | |||
d624e85bc1 | |||
6aa4bfd060 | |||
a26e72c452 | |||
acc4e03482 | |||
e176a9e891 | |||
0b36663ff1 | |||
bb035fe6e0 | |||
6d0c1f08d2 | |||
f700a7be07 | |||
138eb1e3b4 | |||
c39129b6e8 | |||
bf175e72ad | |||
ba31ba4615 | |||
f94f008ed6 | |||
9d4f3c5842 | |||
0b2a9d58e0 | |||
28deea44d4 | |||
f82966adb5 | |||
9f54f1d75d | |||
be9f7d7729 | |||
1b4dce6f84 | |||
3bb17f0671 | |||
19d111a27b | |||
289561ddf3 | |||
d2ca160ea3 | |||
cd19f9239c | |||
16157ad522 | |||
d37a692392 | |||
f78f33d848 | |||
c4692b8d51 | |||
764569eb7a | |||
aab0d2f54e | |||
24678de261 | |||
1b71eeb02a | |||
bfc6a2b078 | |||
9c9da8f575 | |||
d1a87288a4 | |||
e7c65d9404 | |||
00e49b330c | |||
7c6bc73031 | |||
c1368155fc | |||
d305174ecc | |||
6b7391bca9 | |||
4e99c38491 | |||
6087a71951 | |||
5f1c3de29a | |||
abde64cb0c | |||
6923973c8a | |||
d7f1b95349 | |||
4a5c7ee4cc | |||
f3bb16f301 | |||
d6b528a955 | |||
7ba6503e9b | |||
9ee7783759 | |||
2dc5693c60 | |||
a1ef22e0d7 | |||
19b6888ea5 | |||
9520eaa970 | |||
088e0c1ee7 | |||
de704386a1 | |||
766799ec6d | |||
7c50db5bf5 | |||
7223c4e184 | |||
b0a9c391a1 | |||
5c7158792f | |||
9c71d23884 | |||
e1362562b4 | |||
1ab6abc044 | |||
bf4f3a8a99 | |||
f9626d2db6 | |||
28b59589ca | |||
fb10910e66 | |||
6d2efe9460 | |||
f587595765 | |||
5e6e8728c3 | |||
f620f1b466 | |||
818320e748 | |||
fc2e7e94a5 | |||
a47e35ba2e | |||
07d8b2d510 | |||
6329aeac11 | |||
af1fef03f4 | |||
f778cf0ea3 | |||
7af6aa9739 | |||
faae2daae8 | |||
0b4cc14aa6 | |||
622583a0d5 | |||
2f33d85a41 | |||
3abb651325 | |||
ada8882b61 | |||
d3831729a0 | |||
05fee9beea | |||
e4da6495d3 | |||
8c74ad1992 | |||
88064fd534 | |||
b28c6533f8 | |||
53e70b3e99 | |||
c630046858 | |||
a75c4d2cc9 | |||
368a90c82a | |||
2be1574e55 | |||
7f8c59614e | |||
3650e9b074 | |||
978e601217 | |||
dcfa6986c6 | |||
49a3fd53b0 | |||
d33d113746 | |||
f83568fc4e | |||
46415bb248 | |||
5123a1fb03 | |||
19f4a5c819 | |||
69e9b70829 | |||
443ca1cc02 | |||
9a5f4a3346 | |||
16a40dde7b | |||
36e6e65778 | |||
b3bf2e08f3 | |||
3ec500937f | |||
c45c4af5da | |||
a485685867 | |||
08363f4d9b | |||
2f254e5aa3 | |||
e0e78993f6 | |||
eeb2efe010 | |||
be4ef9b43d | |||
a133d8b42e | |||
a1a2527c75 | |||
6f5882302f | |||
ce9c7a210d | |||
e0fb83c691 | |||
7e0a56fb80 | |||
65e1b416ef | |||
183bcd6fc7 | |||
f76372dd7d | |||
9c493ab56a | |||
a17f73a020 | |||
6ff9cae2b1 | |||
d3edcbc11e | |||
779ef582f1 | |||
385887c55b | |||
f396a7aeb4 | |||
ffa2310a34 | |||
fccd626604 | |||
5237b2aa65 | |||
b1ae599c39 | |||
3f694c7335 | |||
3da2f876bd | |||
a6d08fcd71 | |||
73d22a273e | |||
24843f277f | |||
4167ef870c | |||
cd7a968093 | |||
12f71c9795 | |||
b369c75e1b | |||
739eade4fa | |||
d2b63eaf1f | |||
47b432bf89 | |||
b70ccd2a56 | |||
be8df20675 | |||
4a10c95e76 | |||
54b2fab849 | |||
8033184134 | |||
d95da2dfbe | |||
03457029f7 | |||
f8d900c3ea | |||
e16beba111 | |||
60ee25d8d5 | |||
ce1369609f | |||
8199699e7c | |||
48cabd1364 | |||
6dc79ce60a | |||
a8cfdc19e2 | |||
db4ae415e3 | |||
7842d92995 | |||
b34c01a95a | |||
e4546829e3 | |||
8dc3de87ad | |||
e3094ace05 | |||
6f49a00bbe | |||
b5f277bd7b | |||
f798144bea | |||
699fb0d0f1 | |||
5b84f62a89 | |||
3209e88c6f | |||
0202a0837d | |||
2b93c19328 | |||
66a830fd46 | |||
d752096cdf | |||
fe12294b92 | |||
61b5cfece4 | |||
ec5fb2a4ad | |||
cdabd517fa | |||
ebfe9a0355 | |||
c1a5261e2f | |||
c18940a5a2 | |||
b533ad2669 | |||
526bc34bba | |||
35d300b916 | |||
c70087db0c | |||
9804841adb | |||
aa92aa08bd | |||
15e55b2ca1 | |||
4257b8deff | |||
e21e2c892a | |||
05662b678e | |||
64f37a3769 | |||
7c9f492584 | |||
7577437167 | |||
be6775767c | |||
0d9a9b8d3b | |||
4affd22817 | |||
eb17cd9ba9 | |||
0cdac78bd5 | |||
4f3b03e13b | |||
da4486b833 | |||
37aeb5baf1 | |||
a2cb38b382 | |||
c573523c4d | |||
64e6b77dc3 | |||
d0414a3ea6 | |||
6596374886 | |||
7d70343c6d | |||
cb87908dca | |||
95f33b36a7 | |||
d246d1c971 | |||
89dbef9eb3 | |||
60dd31ed48 | |||
40f51114b5 | |||
d9007a08c9 | |||
3d05405a78 | |||
1ca697a130 | |||
c248c57b6e | |||
67c3c93b8f | |||
c3a04bf394 | |||
c30c29b8c3 | |||
5eb8aa655b | |||
3543782f39 | |||
4ff4ebebb6 | |||
a3c96c12d6 | |||
eb0e658c99 | |||
4d069650ae | |||
d176755926 | |||
eb2a6946b2 | |||
d067ba4431 | |||
fdf11f10fb | |||
8fd1835d1a | |||
c77075833a | |||
b2a7ab270c | |||
7503d4812c | |||
1fd8b0b4c5 | |||
8615cf88ab | |||
f73a13dc4a | |||
f973e2effa | |||
f9fed16608 | |||
0578ed0c86 | |||
61520f5bd6 | |||
be853ec931 | |||
440b92adf0 | |||
8fa4d22937 | |||
397ae90d5c | |||
7f97d0bdc5 | |||
14956abb6e | |||
61cea18ff0 | |||
83a449df95 | |||
9c683aaea9 | |||
634b76b82c | |||
a3ea43da52 | |||
f464b85ffc | |||
db055c6029 | |||
eedc74943b | |||
82b134ed46 | |||
cc1de7e7d0 | |||
a199d74069 | |||
7a23d3024a | |||
734888406c | |||
e0ce24b3f5 | |||
c13e62f72c | |||
3d958de33e | |||
4689688af3 | |||
d402a68c73 | |||
66d1dd3679 | |||
43e48fc962 | |||
1fea2a5101 | |||
92e317ec2a | |||
c5d1d2db62 | |||
b1725bc18c | |||
5500c2b3a8 | |||
82db52aaf4 | |||
654d966e6c | |||
92663c81f5 | |||
e3ebcc004d | |||
26e41bc24a | |||
c9e9412540 | |||
14d6d63ad0 | |||
2134213f92 | |||
1935e508f7 | |||
83b6ec7899 | |||
9c0ffc26c1 | |||
39b28a7e42 | |||
09799c6617 | |||
9fad2246ae | |||
585da56118 | |||
cccb482cd9 | |||
eb79c75266 | |||
19171122ca | |||
a4665b1a14 | |||
829f9ac61f | |||
24b846328f | |||
96c43866b1 | |||
9043191927 | |||
6e6ed81c19 | |||
3597035f67 | |||
9f39a18fc5 | |||
ab2de9dccd | |||
d66c6cf55e | |||
4f24f7e5fc | |||
3cd0e86bdd | |||
4d230daf09 | |||
9dd642f4af | |||
a9f9176ba5 | |||
637cce0f91 | |||
74b97dcd14 | |||
4e28a4d654 | |||
9d62d13f88 | |||
eeca838778 | |||
d6f0d2c64c | |||
44cfceba00 | |||
349fb7c297 | |||
f9b5cdfeb1 | |||
de8eb1f8ee | |||
0ff602be06 | |||
7246d0ede2 | |||
50468b6563 | |||
6793236642 | |||
d8ccc7896f | |||
defd9aed32 | |||
6ee1d4348d | |||
27dbd12d7b | |||
93fc5c5561 | |||
b48d290064 | |||
6bdb3cf115 | |||
3b39026ba2 | |||
70ffb564ff | |||
4760d043d3 | |||
8405e75931 | |||
6c4a283b4c | |||
7c6b55e79e | |||
d8c4b22b88 | |||
bbd98e7b86 | |||
0536438317 | |||
e2151a5fd7 | |||
c84da3ce1b | |||
bb50f65532 | |||
28752718c5 | |||
4c76791d4c | |||
a66ae4ad55 | |||
7841e80496 | |||
27626d14b7 | |||
f75e96cd3c | |||
9bc1521615 | |||
f2158218be | |||
183190d089 | |||
ebc3775f19 | |||
97d7e84a04 | |||
2b2b728b64 | |||
46fa843b0e | |||
e7d336ab0e | |||
6e23b0af3b | |||
735c33bd9f | |||
47626a17d7 | |||
ce86d3f230 | |||
31878239c3 | |||
1133a4ff9c | |||
5822443b20 | |||
cf05167c55 | |||
a9504f1495 | |||
3716c30264 | |||
c1bf1ec718 | |||
8b220079d0 | |||
2df95970d9 | |||
a4569974a1 | |||
c9d3ab772c | |||
1a276a2ee5 | |||
4c4c720dc1 | |||
ad707be01e | |||
19d1f97600 | |||
4f079affea | |||
b4888103a6 | |||
e2364b82ef | |||
ba92645044 | |||
2eb8b09b1a | |||
bca610ed50 | |||
53d6938b55 | |||
286160646b | |||
58068260a5 | |||
57e8ce0d42 | |||
4ed1e8b3e2 | |||
8181454af5 | |||
aa482e6d4f | |||
0c9b2c6757 | |||
bbfc435a5c | |||
7e53094044 | |||
565f002bc4 | |||
42fdd4f4d8 | |||
217aa2898e | |||
02e7c1bb2b | |||
bb57a8b6f3 | |||
65d0f1a213 | |||
4344b7ba69 | |||
b0072add05 | |||
4ea00e102b | |||
ed99d12e8b | |||
0a2bb1b71c | |||
4bc8c70c75 | |||
9f2581318a | |||
48b9807c86 | |||
0a821d2341 | |||
78092a404f | |||
d3df33ecdb | |||
1160744830 | |||
e884fc784e | |||
c16788f481 | |||
a1790fb6a8 | |||
cbce4fd39d | |||
93c0620151 | |||
2faf56947b | |||
53777b133b | |||
594a69317a | |||
3f9c375f1c | |||
544c8edd9e | |||
654bd15319 | |||
b85171007e | |||
f6ec33fa0c | |||
7d0ff87cbe | |||
8994e621f7 | |||
d746591894 | |||
161c1088f9 | |||
07c0471902 | |||
5f4ee1b6e7 | |||
aa3a4a48e4 | |||
0d27c9600f | |||
1986b20499 | |||
e7a10b0d6a | |||
6b98644c58 | |||
5397335ae8 | |||
0b6d6e517d | |||
b031543f5a | |||
c6be05f9d7 | |||
cb88e0d052 | |||
54e82daae2 | |||
1394c566eb | |||
3183d954a0 | |||
67b89e5c86 | |||
c88c94886b | |||
c1f6902cb9 | |||
8817e68926 | |||
b1868fb213 | |||
6260814285 | |||
07e6c5aac2 | |||
0477a3066d | |||
59639909b1 | |||
64c37852b1 | |||
bac668d287 | |||
f372fa29b2 | |||
8b24711bba | |||
d4c28fc5f5 | |||
ca5f2ac3ec | |||
15f9590427 | |||
21a246eb42 | |||
1bbaec81ce | |||
7952feb48b | |||
52aebdf223 | |||
6b16604c26 | |||
3c4d52732e | |||
d56d267f7d | |||
8eb31944a5 | |||
ed2fbcd13a | |||
9f4942e9a7 | |||
982a10ac44 | |||
e59a9872b4 | |||
9aedd32e01 | |||
dd0ca4dd60 | |||
3e7d2df6f3 | |||
02e709e89e | |||
1114e5effa | |||
c40fab214d | |||
441c050808 | |||
85425f64a5 | |||
b445ee3763 | |||
95a7f0269a | |||
db63764e22 | |||
03578b69f3 | |||
8cbaee47a0 | |||
bcded5ae25 | |||
7227b636c6 | |||
af715f71e7 | |||
52bc675fcb | |||
1920f211b0 | |||
804117c456 | |||
9a4d1686a6 | |||
e8dda03441 | |||
4b214b4710 | |||
6ed34976c9 | |||
069092eb9d | |||
dc7d323295 | |||
cbedfd680f | |||
a1e2e2a13d | |||
a53a40c43e | |||
33489c8cb8 | |||
c382d8f7ea | |||
f2ccf70f8d | |||
ff04e38326 | |||
1123fca3f2 | |||
33e2d15495 | |||
b265e8099a | |||
a2b3f9aeb0 | |||
d19295a68e | |||
9f5d8d1a2a | |||
e75abacec6 | |||
1c31e8ffc2 | |||
1083a4c0b7 | |||
d212be799a | |||
84986c7695 | |||
aa65f94c67 | |||
dc80242e51 | |||
f2c63e5eec | |||
1fc91dc459 | |||
a2e4789b3e | |||
7d58524185 | |||
635e20d057 | |||
1c3f7c4088 | |||
5c3b0cda2e | |||
a3c6486e52 | |||
741d2b761a | |||
a0ffe71db3 | |||
ecf812db83 | |||
afd3b96e2e | |||
b79e6c0b3e | |||
c6f8ad24bd | |||
d4d05e496a | |||
0a88329526 | |||
b4344b5ab5 | |||
4ac836fde4 | |||
7897448a5b | |||
94f4011844 | |||
3f8e6020f7 | |||
beb65f011d | |||
c2f894963a | |||
dacea8edf9 | |||
3fed2ab64d | |||
476652da0a | |||
35289050e4 | |||
ed9d7f18a6 | |||
a7d1053ff5 | |||
97e2b4666b | |||
7d8cc4f940 | |||
ee2f995fc7 | |||
7e852f8c14 | |||
b4c1692d14 | |||
c0858b247f | |||
0a956f56aa | |||
66105c6e7e | |||
bb1ab0afd9 | |||
0d51d9e4cf | |||
e3789e31ef | |||
8a6b583cdc | |||
86b8b9051f | |||
4c0763792d | |||
599eb5e3e4 | |||
31fe25aa78 | |||
252657905f | |||
77a5e817a5 | |||
2521e8103d | |||
47fcb998f5 | |||
455c40677b | |||
9ae8e4c006 | |||
d514516543 | |||
1024eae742 | |||
dad1f01c5b | |||
ce53f35974 | |||
3d19e800ab | |||
2a54baf60e | |||
4544fe7571 | |||
a125b0179a | |||
6b69acdf8b | |||
8c11a2e5a3 | |||
693c2bc175 | |||
8b34b4bd0b | |||
8cce57ba44 | |||
63f81ed027 | |||
c9ebc0ea25 | |||
15a214e435 | |||
0b3327f04d | |||
0839c100c0 | |||
08cfdcd802 | |||
a1bb3835cc | |||
e590cd2b99 | |||
77b620e50e | |||
9bc723d256 | |||
b9f9a230e6 | |||
ce1ffa4624 | |||
17aa36d343 | |||
cc0965f9f9 | |||
0e728d7751 | |||
3e6cf75d73 | |||
bbedba8b18 | |||
c8d756dde3 | |||
97a8dbb71e | |||
6835804dab | |||
1a2a374380 | |||
2b84afc1e3 | |||
bb3d23f7f6 | |||
7511ea27e2 | |||
adbe3a2312 | |||
eda50a91df | |||
7853bb8042 | |||
37de1b2d25 | |||
0c4ac0b48a | |||
c24cf44c6a | |||
11a8ab47fa | |||
7feeb72721 | |||
01447d94d1 | |||
e267a63330 | |||
c65a24486d | |||
42e786b15b | |||
7a04673dd7 | |||
c47d2da0cb | |||
fd12eddb5d | |||
0b56599d28 | |||
27de94b915 | |||
9e31f2b1de | |||
13ad103823 | |||
ff5a73de49 | |||
275a6ec63f | |||
604da0f6ea | |||
72a19dd448 | |||
3a73f6b8ec | |||
343474a570 | |||
91d82bf8c7 | |||
ed19060074 | |||
f230a67b94 | |||
849f101feb | |||
f45083ce82 | |||
4c143ae9af | |||
cd1a1d5778 | |||
e28e7a72aa | |||
fc9488211f | |||
28767c4d34 | |||
c6c7b05d7b | |||
5526e91b6e | |||
9e123695d0 | |||
092cc47afc | |||
fd20059f68 | |||
609aae684f | |||
49940877d1 | |||
22ae86104b | |||
f8dd4c160b | |||
11061a23b1 | |||
d8b0f213b2 | |||
e9fbe4b2c1 | |||
edcb351107 | |||
0c14640352 | |||
cfa30f9876 | |||
af60dd3634 | |||
ccabce1b34 | |||
9915a18810 | |||
a78373f324 | |||
1d7476a725 | |||
e8e78ebfdd | |||
b77b0a3d81 | |||
95b260f3a9 | |||
97a9726845 | |||
020aea033c | |||
0ac46316af | |||
94d47dc25e | |||
debf08cac0 | |||
ce1393d2d4 | |||
fac482c442 | |||
ee35540b6e | |||
f77507e825 | |||
0021efd593 | |||
0d955bb873 | |||
7fa2e8d2d3 | |||
713d94d881 | |||
4ecf8964b8 | |||
11d044fa6e | |||
a2104c5404 | |||
1abed05413 | |||
1465895ff7 | |||
452025e984 | |||
d537dd93d5 | |||
650a1e807c | |||
67f8a33cad | |||
ff4f096f1d | |||
b5cb353ab5 | |||
17a38dfbed | |||
f773683601 | |||
abeaf828a3 | |||
23a8a4201a | |||
2d409e5c09 | |||
2d57904bf4 | |||
8fa83e1be7 | |||
8875e73765 | |||
65766fcaac | |||
4cd4010a70 | |||
d21da5643b | |||
ba700e6387 | |||
bd90fd7033 | |||
fb3d352d3a | |||
690852e157 | |||
aa84d21bcf | |||
4d62977c7b | |||
cbac2e7bbb | |||
88ee4c5b30 | |||
12c46c5d8b | |||
ab7d4e0e60 | |||
708c6162c4 | |||
7834bba6f7 | |||
857c8aaaa2 | |||
1253e6c64e | |||
b610b2ecc7 | |||
11addbe9c8 | |||
709ef05714 | |||
c51767eef1 | |||
5aab9e878f | |||
e7751e170e | |||
776d345bc3 | |||
a8fc30a13f | |||
2d57b1b470 | |||
90f21fa5db | |||
6638d0e507 | |||
c6793d477a | |||
11e01ec074 | |||
1d827caaaf | |||
ba4db78ed9 | |||
a321f4c842 | |||
b1c465eab0 | |||
5134b05af9 | |||
dc3a93be99 | |||
49aabfec02 | |||
11d0d207fd | |||
eed3245b1b | |||
a7bbde1699 | |||
bacccafe3c | |||
3a80bd47cc | |||
152917d5e1 | |||
c588e173f8 | |||
c0d2ead351 | |||
6ffe5f8343 | |||
2a823ef3e4 | |||
5159c3f3ca | |||
d092924961 | |||
e14132b826 | |||
df36ff638e | |||
ad1fee8233 | |||
3883d511a9 | |||
10803b0d25 | |||
a570a57863 | |||
a7590f9717 | |||
35224ca8d4 | |||
40563e4f84 | |||
c30901e9be | |||
4fc0a91b31 | |||
576417648a | |||
0aace5230f | |||
8d5ba7a6d7 | |||
f8153b84de | |||
fac5b0c9e7 | |||
eb06413188 | |||
066c870271 | |||
1a92fa788d | |||
3a0ab1cc0c | |||
8a7d588bb0 | |||
4943d79d68 | |||
5de10c34b7 | |||
2fbe4c2388 | |||
767cb27f78 | |||
b8c75c3fc0 | |||
edeadf62ef | |||
5ac80057c4 | |||
210e30556e | |||
0487b4213f | |||
8f29c14ac4 | |||
9543d8be10 | |||
43e0003e79 | |||
30e63a7244 | |||
575f520461 | |||
df618c9e91 | |||
ebd13a4bae | |||
7aa54b5a23 | |||
b20cb36f5d | |||
86f8c1863e | |||
19d85c8566 | |||
4241f91a0a | |||
05624f099a | |||
920f4099b6 | |||
aa26750e01 | |||
bdb3be7084 | |||
14987f2b21 | |||
47af6a0bbf | |||
1487578ff4 | |||
5a03a5d578 | |||
2dd137329d | |||
db37deb589 | |||
ec7a3c516d | |||
988d2ffab6 | |||
5e2c66e241 | |||
0ccfb0d781 | |||
01ce961c00 | |||
7579b691df | |||
2a14deab0c | |||
1acefb9eac | |||
fb45b8f45c | |||
d59a9c2e8a | |||
a1c3d8723d | |||
c4bd65e97c | |||
eac3a2d7ac | |||
55bb584778 | |||
4584943531 | |||
55d2bc0e0b | |||
c0cc2fa1b8 | |||
c1ecbd4de1 | |||
0fb6b8a8ff | |||
78ba9adfed | |||
3f642ea34f | |||
1a3927b40c | |||
b09d73ab68 | |||
9311addca3 | |||
3c76478510 | |||
545551e2bc | |||
d5e0a95ff1 | |||
e811109566 | |||
0f805bfdfb | |||
200cd629df | |||
e8a29c1e82 | |||
8589e4f3d3 | |||
948e54772d | |||
2d4b05a71b | |||
a6433e84f5 | |||
083854e2de | |||
3508c4aa87 | |||
d04b15ee25 | |||
d6143e4c73 | |||
d8ffc3c187 | |||
2af788956e | |||
d399141d13 | |||
f6f899f103 | |||
5b8919a246 | |||
fe1989979c | |||
0895fa9331 | |||
b90fe0c52a | |||
ab0e22159c | |||
6ac0afbce0 | |||
9532527e52 | |||
defdf9f34c | |||
a7dce2dc4e | |||
ea8c51f8f3 | |||
1e66878447 | |||
6cfbdebf6a | |||
a4469dcc14 | |||
65ac9065fa | |||
5143e6763b | |||
5660a8e9f5 | |||
bc2b17df0b | |||
f9e7c95348 | |||
163057f521 | |||
d8ff1f9873 | |||
97b7760de8 | |||
acca0f6946 | |||
f3f6d67d46 | |||
63773d5226 | |||
4e4559fc8c | |||
44d540d36c | |||
c6253a6515 | |||
65a5ec2ef3 | |||
70e8b35944 | |||
ddba25a674 | |||
14e6cb6a8f | |||
d4619150f3 | |||
7cfa690aaf | |||
e127898312 | |||
f63b81c52a | |||
1fe673703f | |||
979298ce57 | |||
66e727e1b2 | |||
6925779f59 | |||
125d7daf4a | |||
cb1020b26d | |||
e1945506f3 | |||
3a798112f2 | |||
c5dd3e5542 | |||
2fa9cbfd9e | |||
23af4ee93e | |||
0317562605 | |||
1861e0b2cc | |||
e5974809e8 | |||
abfae17b9a | |||
84b1a62ad2 | |||
b6bcaec9bc | |||
f19ed84cc4 | |||
6c5a946fda | |||
c6ffc9427e | |||
0f1e64f3b2 | |||
1ce5ad3003 | |||
64694955c0 | |||
97a90d8122 | |||
3cd2c08277 | |||
c37a2ca1c8 | |||
80b38210b2 | |||
e5dffb0097 | |||
deaa897928 | |||
3f9758e706 | |||
3c25c265df | |||
a8529bd8d1 | |||
ba03ca76c4 | |||
71fd54ec9e | |||
a03343827e | |||
4fb7c642d5 | |||
8a892d47e5 | |||
73abacc20b | |||
aea24279ba | |||
5c5968e742 | |||
3813ed9c2e | |||
594897e9a5 | |||
40e9f6fa2c | |||
35afd2a8fb | |||
d9be1d7e32 | |||
b625ec30d9 | |||
f5313268d7 | |||
07dedee37b | |||
75f3127ba5 | |||
b13fae2556 | |||
2e9838699b | |||
ba9c3f41c9 | |||
e35fae8f32 | |||
b0d5f3bd64 | |||
ed640bb181 | |||
a3511ba9e2 | |||
4c9c903648 | |||
d12aaddc34 | |||
28955bb449 | |||
dcd7cae7cf | |||
c954bb9456 | |||
be0b298d81 | |||
409026044b | |||
0c311bdcf9 | |||
e81775e63d | |||
209d7ef613 | |||
a6c76a85ce | |||
265f9e5433 | |||
b86d988b3c | |||
c4148cec33 | |||
aa57becc41 | |||
7269c37c8f | |||
3093d7e95a | |||
4e0d8a0cbb | |||
523151ddf0 | |||
0a7cb94ea8 | |||
d4b7c0e633 | |||
3f76affbd2 | |||
a8f8970601 | |||
178b5ff626 | |||
c47f7c2806 | |||
ab6aa5463f | |||
42387bff6f | |||
3afd25691a | |||
a6a963bec1 | |||
d6ac4dc22a | |||
0b3f45bb1b | |||
24f2df926a | |||
f00e8655ac | |||
41395d9e00 | |||
3e00bcbf9f | |||
0b402b23f7 | |||
691fcaeee7 | |||
9f30910653 | |||
41a6c2e501 | |||
fbc7fc6645 | |||
573dbb431e | |||
7b2cba7a6c | |||
91ff5617ef | |||
f1782868f9 | |||
66ee22c3e6 | |||
2db1222e45 | |||
abbd057eb9 | |||
6da5b8ccc5 | |||
128e2b917d | |||
2f4173b267 | |||
3fea1e4df5 | |||
13d2552274 | |||
3d0bfbb4f4 | |||
b893e88e8b | |||
f2be9e4381 | |||
53b5d6d167 | |||
92bfe34716 | |||
5df096baf3 | |||
45cbaa2d13 | |||
720a17acd7 | |||
dab00ab036 |
39
.gitignore
vendored
39
.gitignore
vendored
@ -13,17 +13,23 @@ config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
intltool-extract.in
|
||||
intltool-merge.in
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
.deps
|
||||
src/metacity-wm.desktop
|
||||
src/50-mutter-windows.xml
|
||||
src/mutter-wm.desktop
|
||||
src/mutter.desktop
|
||||
*.o
|
||||
*.a
|
||||
*.lo
|
||||
*.la
|
||||
.libs
|
||||
*.swp
|
||||
*.gir
|
||||
*.typelib
|
||||
tidy-enum-types.[ch]
|
||||
tidy-marshal.[ch]
|
||||
stamp-tidy-enum-types.h
|
||||
@ -35,26 +41,35 @@ stamp-h1
|
||||
stamp-it
|
||||
.intltool-merge-cache
|
||||
POTFILES
|
||||
po/*.pot
|
||||
50-metacity-desktop-key.xml
|
||||
50-metacity-key.xml
|
||||
inlinepixbufs.h
|
||||
libmetacity-private.pc
|
||||
metacity
|
||||
metacity-dialog
|
||||
metacity-theme-viewer
|
||||
metacity.desktop
|
||||
metacity.schemas
|
||||
libmutter.pc
|
||||
mutter
|
||||
mutter-theme-viewer
|
||||
mutter.desktop
|
||||
org.gnome.mutter.gschema.valid
|
||||
org.gnome.mutter.gschema.xml
|
||||
testasyncgetprop
|
||||
testboxes
|
||||
testgradient
|
||||
metacity-grayscale
|
||||
metacity-mag
|
||||
metacity-message
|
||||
metacity-window-demo
|
||||
mutter-grayscale
|
||||
mutter-mag
|
||||
mutter-message
|
||||
mutter-window-demo
|
||||
focus-window
|
||||
test-attached
|
||||
test-gravity
|
||||
test-resizing
|
||||
test-size-hints
|
||||
wm-tester
|
||||
# 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]
|
||||
src/stamp-mutter-enum-types.h
|
||||
src/mutter-marshal.[ch]
|
||||
src/stamp-mutter-marshal.h
|
||||
src/mutter-plugins.pc
|
||||
|
8
HACKING
8
HACKING
@ -42,10 +42,10 @@ Minimal Building/Testing Environment
|
||||
build a development version of Metacity -- odds are, you may be able
|
||||
to build metacity from CVS without building any other modules.
|
||||
|
||||
As long as you have gtk+ >= 2.10 and GConf with your distro (gtk+ >=
|
||||
2.6 if you manually revert the change from bug 348633), you should
|
||||
be able to install your distro's development packages
|
||||
(e.g. gtk2-devel, GConf2-devel, startup-notification-devel on
|
||||
As long as you have gtk+ >= 3.0 and GIO >= 2.25.10 with your distro
|
||||
(gtk+ >= 2.6 if you manually revert the change from bug 348633), you
|
||||
should be able to install your distro's development packages
|
||||
(e.g. gtk2-devel, glib-devel, startup-notification-devel on
|
||||
Fedora; also, remember to install the gnome-common package which is
|
||||
needed for building cvs versions of Gnome modules like Metacity) as
|
||||
well as the standard development tools (gcc, autoconf, automake,
|
||||
|
29
README
29
README
@ -18,8 +18,7 @@ COMPILING MUTTER
|
||||
You need GTK+ 2.2. For startup notification to work you need
|
||||
libstartup-notification at
|
||||
http://www.freedesktop.org/software/startup-notification/ or on the
|
||||
GNOME ftp site. You also need GConf 1.2 (unless building a funky
|
||||
extra-small embedded metacity with --disable-gconf, see below).
|
||||
GNOME ftp site.
|
||||
You need Clutter 1.0. You need gobject-introspection 0.6.3.
|
||||
|
||||
REPORTING BUGS AND SUBMITTING PATCHES
|
||||
@ -59,25 +58,24 @@ MUTTER FEATURES
|
||||
and should work with KWin, fvwm2, and other EWMH-compliant WMs.)
|
||||
|
||||
- Has a simple theme system and a couple of extra themes come with it.
|
||||
Change themes via gconf-editor or gconftool or GNOME themes control
|
||||
panel:
|
||||
gconftool-2 --type=string --set /apps/metacity/general/theme Crux
|
||||
gconftool-2 --type=string --set /apps/metacity/general/theme Gorilla
|
||||
gconftool-2 --type=string --set /apps/metacity/general/theme Atlanta
|
||||
gconftool-2 --type=string --set /apps/metacity/general/theme Bright
|
||||
Change themes via gsettings:
|
||||
gsettings set org.gnome.desktop.wm.preferences theme Crux
|
||||
gsettings set org.gnome.desktop.wm.preferences theme Gorilla
|
||||
gsettings set org.gnome.desktop.wm.preferences theme Atlanta
|
||||
gsettings set org.gnome.desktop.wm.preferences theme Bright
|
||||
|
||||
See theme-format.txt for docs on the theme format. Use
|
||||
metacity-theme-viewer to preview themes.
|
||||
|
||||
- Change number of workspaces via gconf-editor or gconftool:
|
||||
gconftool-2 --type=int --set /apps/metacity/general/num_workspaces 5
|
||||
- Change number of workspaces via gsettings:
|
||||
gsettings set org.gnome.desktop.wm.preferences num-workspaces 5
|
||||
|
||||
Can also change workspaces from GNOME 2 pager.
|
||||
|
||||
- Change focus mode:
|
||||
gconftool-2 --type=string --set /apps/metacity/general/focus_mode mouse
|
||||
gconftool-2 --type=string --set /apps/metacity/general/focus_mode sloppy
|
||||
gconftool-2 --type=string --set /apps/metacity/general/focus_mode click
|
||||
gsettings set org.gnome.desktop.wm.preferences focus-mode mouse
|
||||
gsettings set org.gnome.desktop.wm.preferences focus-mode sloppy
|
||||
gsettings set org.gnome.desktop.wm.preferences focus-mode click
|
||||
|
||||
- Global keybinding defaults include:
|
||||
|
||||
@ -92,10 +90,9 @@ MUTTER FEATURES
|
||||
|
||||
Change keybindings for example:
|
||||
|
||||
unst gconftool-2 --type=string --set /apps/metacity/global_keybindings/switch_to_workspace_1 '<Alt>F1'
|
||||
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-1 '[<Alt>F1]'
|
||||
|
||||
Also try the GNOME keyboard shortcuts control panel, or
|
||||
gconf-editor.
|
||||
Also try the GNOME keyboard shortcuts control panel.
|
||||
|
||||
- Window keybindings:
|
||||
|
||||
|
376
configure.in
376
configure.in
@ -1,13 +1,13 @@
|
||||
AC_PREREQ(2.50)
|
||||
|
||||
m4_define([mutter_major_version], [2])
|
||||
m4_define([mutter_minor_version], [27])
|
||||
m4_define([mutter_micro_version], [5])
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [5])
|
||||
m4_define([mutter_micro_version], [4])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
|
||||
m4_define([mutter_plugin_api_version], [2])
|
||||
m4_define([mutter_plugin_api_version], [3])
|
||||
|
||||
AC_INIT([mutter], [mutter_version],
|
||||
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
|
||||
@ -15,9 +15,9 @@ AC_INIT([mutter], [mutter_version],
|
||||
AC_CONFIG_SRCDIR(src/core/display.c)
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
||||
AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip])
|
||||
AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz tar-ustar])
|
||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
|
||||
AM_MAINTAINER_MODE
|
||||
AM_MAINTAINER_MODE([enable])
|
||||
|
||||
MUTTER_MAJOR_VERSION=mutter_major_version
|
||||
MUTTER_MINOR_VERSION=mutter_minor_version
|
||||
@ -61,80 +61,23 @@ AC_CHECK_SIZEOF(__int64)
|
||||
## byte order
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
#### Warnings
|
||||
CANBERRA_GTK=libcanberra-gtk3
|
||||
CANBERRA_GTK_VERSION=0.26
|
||||
|
||||
changequote(,)dnl
|
||||
if test "x$GCC" = "xyes"; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wall[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wall" ;;
|
||||
esac
|
||||
CLUTTER_PACKAGE=clutter-1.0
|
||||
|
||||
# case " $CFLAGS " in
|
||||
# *[\ \ ]-Wshadow[\ \ ]*) ;;
|
||||
# *) CFLAGS="$CFLAGS -Wshadow" ;;
|
||||
# esac
|
||||
MUTTER_PC_MODULES="
|
||||
gtk+-3.0 >= 3.3.7
|
||||
gio-2.0 >= 2.25.10
|
||||
pango >= 1.2.0
|
||||
cairo >= 1.10.0
|
||||
gsettings-desktop-schemas >= 3.3.0
|
||||
xcomposite >= 0.2 xfixes xrender xdamage
|
||||
$CLUTTER_PACKAGE >= 1.9.10
|
||||
cogl-1.0 >= 1.9.6
|
||||
"
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wchar-subscripts[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wmissing-declarations[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wnested-externs[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wnested-externs" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wpointer-arith[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wpointer-arith" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wcast-align[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wcast-align" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wsign-compare[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wsign-compare" ;;
|
||||
esac
|
||||
|
||||
if test "x$enable_ansi" = "xyes"; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-ansi[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -ansi" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-pedantic[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -pedantic" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
changequote([,])dnl
|
||||
|
||||
MUTTER_PC_MODULES='gtk+-2.0 >= 2.10.0 pango >= 1.2.0'
|
||||
|
||||
AC_ARG_ENABLE(gconf,
|
||||
AC_HELP_STRING([--disable-gconf],
|
||||
[disable gconf usage, for embedded/size-sensitive non-GNOME builds]),,
|
||||
enable_gconf=yes)
|
||||
|
||||
if test x$enable_gconf = xyes; then
|
||||
AC_DEFINE(HAVE_GCONF,1,[Build with gconf support])
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES gconf-2.0 >= 1.2.0"
|
||||
fi
|
||||
GLIB_GSETTINGS
|
||||
|
||||
AC_ARG_ENABLE(verbose-mode,
|
||||
AC_HELP_STRING([--disable-verbose-mode],
|
||||
@ -155,10 +98,10 @@ AC_ARG_ENABLE(startup-notification,
|
||||
[disable mutter's startup notification support, for embedded/size-sensitive custom non-GNOME builds]),,
|
||||
enable_startup_notification=auto)
|
||||
|
||||
AC_ARG_WITH(introspection,
|
||||
AC_HELP_STRING([--without-introspection],
|
||||
[disable the use of GObject introspection]),,
|
||||
with_introspection=auto)
|
||||
AC_ARG_WITH(libcanberra,
|
||||
AC_HELP_STRING([--without-libcanberra],
|
||||
[disable the use of libcanberra for playing sounds]),,
|
||||
with_libcanberra=auto)
|
||||
|
||||
AC_ARG_ENABLE(xsync,
|
||||
AC_HELP_STRING([--disable-xsync],
|
||||
@ -170,17 +113,14 @@ AC_ARG_ENABLE(shape,
|
||||
[disable mutter's use of the shaped window extension]),,
|
||||
enable_shape=auto)
|
||||
|
||||
## try definining HAVE_BACKTRACE
|
||||
AC_CHECK_HEADERS(execinfo.h, [AC_CHECK_FUNCS(backtrace)])
|
||||
|
||||
AM_GLIB_GNU_GETTEXT
|
||||
|
||||
## here we get the flags we'll actually use
|
||||
# GOptionEntry requires glib-2.6.0
|
||||
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.6.0)
|
||||
# GRegex requires Glib-2.14.0
|
||||
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
|
||||
# gtk_window_set_icon_name requires gtk2+-2.6.0
|
||||
PKG_CHECK_MODULES(MUTTER_MESSAGE, gtk+-2.0 >= 2.6.0)
|
||||
PKG_CHECK_MODULES(MUTTER_WINDOW_DEMO, gtk+-2.0 >= 2.6.0)
|
||||
PKG_CHECK_MODULES(MUTTER_MESSAGE, gtk+-3.0)
|
||||
PKG_CHECK_MODULES(MUTTER_WINDOW_DEMO, gtk+-3.0)
|
||||
|
||||
# Unconditionally use this dir to avoid a circular dep with gnomecc
|
||||
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
|
||||
@ -212,62 +152,38 @@ else
|
||||
echo "Building without libstartup-notification"
|
||||
fi
|
||||
|
||||
XCOMPOSITE_VERSION=0.2
|
||||
|
||||
AC_MSG_CHECKING([Xcomposite >= $XCOMPOSITE_VERSION])
|
||||
if $PKG_CONFIG --atleast-version $XCOMPOSITE_VERSION xcomposite; then
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcomposite >= $XCOMPOSITE_VERSION xfixes xrender xdamage"
|
||||
AC_DEFINE(HAVE_COMPOSITE_EXTENSIONS, 1, [Building with compositing manager support])
|
||||
echo "Building with compositing manager"
|
||||
|
||||
## force on render also
|
||||
have_xrender=yes
|
||||
have_libcanberra=no
|
||||
AC_MSG_CHECKING([libcanberra-gtk])
|
||||
if test x$with_libcanberra = xno ; then
|
||||
AC_MSG_RESULT([disabled])
|
||||
else
|
||||
AC_MSG_ERROR([no. Mutter requires the Xcomposite extension to build.])
|
||||
fi
|
||||
|
||||
CLUTTER_VERSION=1.0.0
|
||||
CLUTTER_PACKAGE=clutter-1.0
|
||||
AC_SUBST(CLUTTER_PACKAGE)
|
||||
if $PKG_CONFIG --atleast-version $CLUTTER_VERSION $CLUTTER_PACKAGE ; then
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES $CLUTTER_PACKAGE "
|
||||
PKG_CHECK_MODULES(CLUTTER, $CLUTTER_PACKAGE)
|
||||
AC_DEFINE(WITH_CLUTTER, , [Building with Clutter compositor])
|
||||
|
||||
dnl Check for the clutter-glx-texture-pixmap header
|
||||
mutter_save_cppflags="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $CLUTTER_CFLAGS"
|
||||
AC_CHECK_HEADER([clutter/glx/clutter-glx-texture-pixmap.h],
|
||||
[have_glx_texture_pixmap=yes],
|
||||
[have_glx_texture_pixmap=no])
|
||||
CPPFLAGS="$mutter_save_cppflags"
|
||||
|
||||
if test x$have_glx_texture_pixmap = xyes; then
|
||||
AC_DEFINE(HAVE_GLX_TEXTURE_PIXMAP, ,
|
||||
[Is ClutterGLXTexturePixmap available?])
|
||||
fi
|
||||
else
|
||||
AC_MSG_ERROR([no. Mutter requires Clutter version $CLUTTER_VERSION.])
|
||||
fi
|
||||
|
||||
if test x$with_introspection != xno; then
|
||||
PKG_CHECK_MODULES(INTROSPECTION, gobject-introspection-1.0, have_introspection=yes, have_introspection=no)
|
||||
if test x$have_introspection=xyes; then
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES gobject-introspection-1.0"
|
||||
AC_DEFINE(HAVE_INTROSPECTION, 1, [Define if GObject introspection is available])
|
||||
G_IR_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
|
||||
AC_SUBST(G_IR_SCANNER)
|
||||
G_IR_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
|
||||
AC_SUBST(G_IR_COMPILER)
|
||||
G_IR_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
|
||||
AC_SUBST(G_IR_GENERATE)
|
||||
GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
|
||||
AC_SUBST(GIRDIR)
|
||||
TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
|
||||
AC_SUBST(TYPELIBDIR)
|
||||
if $PKG_CONFIG --exists $CANBERRA_GTK '>=' $CANBERRA_GTK_VERSION; then
|
||||
have_libcanberra=yes
|
||||
AC_MSG_RESULT(yes)
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES $CANBERRA_GTK"
|
||||
AC_DEFINE([HAVE_LIBCANBERRA], 1, [Building with libcanberra for playing sounds])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test x$with_libcanberra = xyes ; then
|
||||
AC_MSG_ERROR([libcanberra forced and libcanberra-gtk was not found])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL(WITH_INTROSPECTION, test "$have_introspection" = "yes")
|
||||
|
||||
INTROSPECTION_VERSION=0.9.5
|
||||
GOBJECT_INTROSPECTION_CHECK([$INTROSPECTION_VERSION])
|
||||
|
||||
if test x$found_introspection != xno; then
|
||||
AC_DEFINE(HAVE_INTROSPECTION, 1, [Define if GObject introspection is available])
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES gobject-introspection-1.0"
|
||||
# Since we don't make any guarantees about stability and we don't support
|
||||
# parallel install, there's no real reason to change directories, filenames,
|
||||
# etc. as we change the Mutter tarball version. Note that this must match
|
||||
# api_version in src/Makefile.am
|
||||
META_GIR=Meta_3_0_gir
|
||||
# META_GIR=[Meta_]mutter_major_version[_]mutter_minor_version[_gir]
|
||||
AC_SUBST(META_GIR)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([Xcursor])
|
||||
if $PKG_CONFIG xcursor; then
|
||||
@ -285,64 +201,39 @@ fi
|
||||
|
||||
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
|
||||
|
||||
# This is used for plugins
|
||||
AC_SUBST(CLUTTER_PACKAGE)
|
||||
PKG_CHECK_MODULES(CLUTTER, $CLUTTER_PACKAGE)
|
||||
|
||||
AC_PATH_XTRA
|
||||
|
||||
ALL_X_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
|
||||
# Check for Xinerama extension (Solaris impl or Xfree impl)
|
||||
# Check for Xinerama extension - we only support the "XFree86" style,
|
||||
# and not the older Solaris-only version; recent Solaris supports the
|
||||
# XFree86 style.
|
||||
mutter_save_cppflags="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $X_CFLAGS"
|
||||
|
||||
AC_ARG_ENABLE(xinerama,
|
||||
AC_HELP_STRING([--disable-xinerama],
|
||||
[disable mutter's use of the Xinerama extension]),
|
||||
try_xinerama=$enable_xinerama,try_xinerama=yes)
|
||||
|
||||
use_solaris_xinerama=no
|
||||
use_xfree_xinerama=no
|
||||
if test "${try_xinerama}" != no; then
|
||||
case "$host" in
|
||||
*-*-solaris*)
|
||||
# Check for solaris
|
||||
use_solaris_xinerama=yes
|
||||
AC_CHECK_LIB(Xext, XineramaGetInfo,
|
||||
use_solaris_xinerama=yes, use_solaris_xinerama=no,
|
||||
$ALL_X_LIBS)
|
||||
if test "x$use_solaris_xinerama" = "xyes"; then
|
||||
AC_CHECK_HEADER(X11/extensions/xinerama.h,
|
||||
if test -z "`echo $ALL_X_LIBS | grep "\-lXext" 2> /dev/null`"; then
|
||||
X_EXTRA_LIBS="-lXext $X_EXTRA_LIBS"
|
||||
fi
|
||||
AC_DEFINE(HAVE_SOLARIS_XINERAMA, , [Have Solaris-style Xinerama])
|
||||
AC_DEFINE(HAVE_XINERAMA, , [Have some version of Xinerama]),
|
||||
use_solaris_xinerama=no,
|
||||
[#include <X11/Xlib.h>])
|
||||
fi
|
||||
AC_MSG_CHECKING(for Xinerama support on Solaris)
|
||||
AC_MSG_RESULT($use_solaris_xinerama);
|
||||
;;
|
||||
*)
|
||||
# Check for XFree
|
||||
use_xfree_xinerama=yes
|
||||
AC_CHECK_LIB(Xinerama, XineramaQueryExtension,
|
||||
[AC_CHECK_HEADER(X11/extensions/Xinerama.h,
|
||||
X_EXTRA_LIBS="-lXinerama $X_EXTRA_LIBS"
|
||||
if test -z "`echo $ALL_X_LIBS | grep "\-lXext" 2> /dev/null`"; then
|
||||
X_EXTRA_LIBS="-lXext $X_EXTRA_LIBS"
|
||||
fi
|
||||
AC_DEFINE(HAVE_XFREE_XINERAMA, , [Have XFree86-style Xinerama])
|
||||
AC_DEFINE(HAVE_XINERAMA,, [Have some version of Xinerama]),
|
||||
use_xfree_xinerama=no,
|
||||
[#include <X11/Xlib.h>])],
|
||||
use_xfree_xinerama=no, -lXext $ALL_X_LIBS)
|
||||
AC_MSG_CHECKING(for Xinerama support on XFree86)
|
||||
AC_MSG_RESULT($use_xfree_xinerama);
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
have_xinerama=yes
|
||||
AC_CHECK_LIB(Xinerama, XineramaQueryExtension,
|
||||
[AC_CHECK_HEADER(X11/extensions/Xinerama.h,
|
||||
[X_EXTRA_LIBS="-lXinerama $X_EXTRA_LIBS"
|
||||
if test -z "`echo $ALL_X_LIBS | grep "\-lXext" 2> /dev/null`"; then
|
||||
X_EXTRA_LIBS="-lXext $X_EXTRA_LIBS"
|
||||
fi],
|
||||
have_xinerama=no,
|
||||
[#include <X11/Xlib.h>])],
|
||||
have_xinerama=no, -lXext $ALL_X_LIBS)
|
||||
AC_MSG_CHECKING(for Xinerama support)
|
||||
AC_MSG_RESULT($have_xinerama)
|
||||
|
||||
CPPFLAGS="$mutter_save_cppflags"
|
||||
|
||||
if test x$have_xinerama = xno; then
|
||||
AC_MSG_ERROR([Xinerama extension was not found])
|
||||
fi
|
||||
|
||||
SHAPE_LIBS=
|
||||
found_shape=no
|
||||
AC_CHECK_LIB(Xext, XShapeQueryExtension,
|
||||
@ -414,7 +305,7 @@ fi
|
||||
|
||||
MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
|
||||
MUTTER_MESSAGE_LIBS="$MUTTER_MESSAGE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
|
||||
MUTTER_PROPS_LIBS="$MUTTER_PROPS_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
|
||||
found_sm=no
|
||||
@ -458,18 +349,6 @@ fi
|
||||
|
||||
AC_SUBST(GDK_PIXBUF_CSOURCE)
|
||||
|
||||
if test x$enable_gconf = xyes; then
|
||||
AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
|
||||
if test x"$GCONFTOOL" = xno; then
|
||||
AC_MSG_ERROR([gconftool-2 executable not found in your path - should be installed with GConf])
|
||||
fi
|
||||
|
||||
AM_GCONF_SOURCE_2
|
||||
else
|
||||
GCONF_SCHEMAS_INSTALL_TRUE='#'
|
||||
GCONF_SCHEMAS_INSTALL_FALSE=
|
||||
fi
|
||||
|
||||
AC_PATH_PROG(ZENITY, zenity, no)
|
||||
if test x"$ZENITY" = xno; then
|
||||
AC_MSG_ERROR([zenity not found in your path - needed for dialogs])
|
||||
@ -482,21 +361,85 @@ if test "x$enable_debug" = "xyes"; then
|
||||
CFLAGS="$CFLAGS -g -O"
|
||||
fi
|
||||
|
||||
# Warnings are there for a reason
|
||||
if test "x$GCC" = "xyes"; then
|
||||
CFLAGS="$CFLAGS -Wall -Werror -ansi"
|
||||
fi
|
||||
# For fix-meta-rectangle.py
|
||||
AM_PATH_PYTHON([2.5])
|
||||
|
||||
# Use gnome-doc-utils:
|
||||
GNOME_DOC_INIT([0.8.0])
|
||||
|
||||
#### Warnings (last since -Werror can disturb other tests)
|
||||
|
||||
# Stay command-line compatible with the gnome-common configure option. Here
|
||||
# minimum/yes/maximum are the same, however.
|
||||
AC_ARG_ENABLE(compile_warnings,
|
||||
AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),,
|
||||
enable_compile_warnings=error)
|
||||
|
||||
changequote(,)dnl
|
||||
if test "$enable_compile_warnings" != no ; then
|
||||
if test "x$GCC" = "xyes"; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wall[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wall" ;;
|
||||
esac
|
||||
|
||||
# case " $CFLAGS " in
|
||||
# *[\ \ ]-Wshadow[\ \ ]*) ;;
|
||||
# *) CFLAGS="$CFLAGS -Wshadow" ;;
|
||||
# esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wchar-subscripts[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wmissing-declarations[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wnested-externs[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wnested-externs" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wpointer-arith[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wpointer-arith" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wcast-align[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wcast-align" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wsign-compare[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wsign-compare" ;;
|
||||
esac
|
||||
|
||||
if test "$enable_compile_warnings" = error; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Werror[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Werror -Wno-error=deprecated-declarations" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
changequote([,])dnl
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
doc/Makefile
|
||||
doc/man/Makefile
|
||||
src/Makefile
|
||||
src/wm-tester/Makefile
|
||||
src/libmutter-private.pc
|
||||
src/libmutter.pc
|
||||
src/mutter-plugins.pc
|
||||
src/tools/Makefile
|
||||
src/compositor/plugins/Makefile
|
||||
@ -505,13 +448,6 @@ po/Makefile.in
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
if test x$enable_gconf = xno; then
|
||||
echo "*** WARNING WARNING WARNING WARNING WARNING"
|
||||
echo "*** Building without GConf. This means there's no"
|
||||
echo "*** way to change prefs except hacking source code."
|
||||
echo "*** This is intended for embedded systems etc., not for normal use."
|
||||
fi
|
||||
|
||||
if test x$enable_verbose_mode = xno; then
|
||||
echo "*** WARNING WARNING WARNING WARNING WARNING"
|
||||
echo "*** Building without verbose mode"
|
||||
@ -522,17 +458,15 @@ fi
|
||||
|
||||
dnl ==========================================================================
|
||||
echo "
|
||||
mutter-$VERSION:
|
||||
mutter-$VERSION
|
||||
|
||||
prefix: ${prefix}
|
||||
source code location: ${srcdir}
|
||||
compiler: ${CC}
|
||||
|
||||
GConf: ${enable_gconf}
|
||||
XFree86 Xinerama: ${use_xfree_xinerama}
|
||||
Solaris Xinerama: ${use_solaris_xinerama}
|
||||
Startup notification: ${have_startup_notification}
|
||||
Introspection: ${have_introspection}
|
||||
libcanberra: ${have_libcanberra}
|
||||
Introspection: ${found_introspection}
|
||||
Session management: ${found_sm}
|
||||
Shape extension: ${found_shape}
|
||||
Xsync: ${found_xsync}
|
||||
@ -544,8 +478,8 @@ MUTTER_MINOR_VERSION=mutter_minor_version
|
||||
if expr $MUTTER_MINOR_VERSION % 2 > /dev/null ; then
|
||||
stable_version=`expr $MUTTER_MINOR_VERSION - 1`
|
||||
echo "This is the UNSTABLE branch of mutter"
|
||||
echo -n "Use 2.$stable_version.x for stable "
|
||||
echo "(gnome-2-$stable_version branch in Subversion)"
|
||||
echo -n "Use 3.$stable_version.x for stable "
|
||||
echo "(gnome-3-$stable_version branch in git)"
|
||||
else
|
||||
echo "This is the stable branch of mutter"
|
||||
fi
|
||||
|
@ -31,8 +31,7 @@ workspaces. In these cases, there needs to be a rule consistent with
|
||||
the above about the new window to choose.
|
||||
|
||||
Focus method Behavior
|
||||
click Focus the most recently used window (same as the window
|
||||
on top)
|
||||
click Focus the window on top
|
||||
sloppy Focus the window containing the pointer if there is such
|
||||
a window, otherwise focus the most recently used window.
|
||||
mouse Focus the non-DESKTOP window containing the pointer if
|
||||
|
@ -46,13 +46,13 @@ because the original program does not have a manual page.
|
||||
Restart \fBmutter\fP(1) which is running.
|
||||
.TP
|
||||
.B reload-theme
|
||||
Reload a theme which is specified on gconf database.
|
||||
Reload a theme which is specified on gsettings database.
|
||||
.TP
|
||||
.B enable-keybindings
|
||||
Enable all of keybindings which is specified on gconf database.
|
||||
Enable all of keybindings which is specified on gsettings database.
|
||||
.TP
|
||||
.B disable-keybindings
|
||||
Disable all of keybindings which is specified on gconf database.
|
||||
Disable all of keybindings which is specified on gsettings database.
|
||||
.SH SEE ALSO
|
||||
.BR mutter (1)
|
||||
.SH AUTHOR
|
||||
|
@ -51,7 +51,7 @@ Print the version number.
|
||||
.B \-?, \-\-help
|
||||
Show summary of options.
|
||||
.SH CONFIGURATION
|
||||
\fBmutter\fP configuration can be found under \fIPreferences\fP->\fIWindows\fP and \fIPreferences\fP->\fIKeyboard Shortcuts\fP on the menu-panel. Advanced configuration can be achieved directly through gconf editing (gconf-editor or gconftool-2).
|
||||
\fBmutter\fP configuration can be found under \fIPreferences\fP->\fIWindows\fP and \fIPreferences\fP->\fIKeyboard Shortcuts\fP on the menu-panel. Advanced configuration can be achieved directly through gsettings.
|
||||
.SH SEE ALSO
|
||||
.BR mutter-message (1)
|
||||
.SH AUTHOR
|
||||
|
@ -4,6 +4,7 @@ of the theme format, and a given theme can support more than one format.
|
||||
Version 1: THEMEDIR/metacity-1/metacity-theme-1.xml
|
||||
(original metacity format)
|
||||
Version 2: THEMEDIR/metacity-1/metacity-theme-2.xml
|
||||
Version 3: THEMEDIR/metacity-1/metacity-theme-3.xml
|
||||
|
||||
The subdirectory name is "metacity-1" in all versions.
|
||||
|
||||
@ -21,6 +22,71 @@ This document has separate sections for each format version. You may
|
||||
want to read the document in reverse order, since the base features
|
||||
are discussed under version 1.
|
||||
|
||||
New Features in Theme Format Version 3.4
|
||||
========================================
|
||||
|
||||
An additional color type is added to pick up custom colors defined
|
||||
in the GTK+ theme's CSS:
|
||||
|
||||
gtk:custom(name,fallback)
|
||||
|
||||
where <name> refers to a custom color defined with @define-color in
|
||||
the GTK+ theme, and <fallback> provides an alternative color definition
|
||||
in case the color referenced by <name> is not found.
|
||||
|
||||
New Features in Theme Format Version 3.3
|
||||
========================================
|
||||
|
||||
Add two additional button background functions - left_single_background and
|
||||
right_single_background - for button groups with just a single button.
|
||||
|
||||
There are now additional frame states to style left/right tiled windows
|
||||
differently ("tiled_left", "tiled_right", "tiled_left_and_shaded",
|
||||
"tiled_right_and_shaded").
|
||||
|
||||
New Features in Theme Format Version 3.2
|
||||
========================================
|
||||
|
||||
A new window type 'attached' is added for modal dialogs which are
|
||||
attached to their parent window. (When the attach_modal_dialogs preference
|
||||
is turned on.) If no style is defined for the 'attached' window type,
|
||||
the 'border' window type will be used instead.
|
||||
|
||||
New Features in Theme Format Version 3.1
|
||||
========================================
|
||||
|
||||
Additional predefined variables are added for positioning expressions:
|
||||
|
||||
frame_x_center: the X center of the entire frame, with respect to the
|
||||
piece currently being drawn.
|
||||
frame_y_center: the Y center of the entire frame, with respect to the
|
||||
piece currently being drawn.
|
||||
|
||||
The <title/> element now supports an "ellipsize_width" attribute. When
|
||||
specified, this gives a width at which to ellipsize the title. If not
|
||||
specified, the title will simply be clipped to the title area.
|
||||
|
||||
New Features in Theme Format Version 3
|
||||
======================================
|
||||
|
||||
Format version 3 has exactly one new feature; any element in the file
|
||||
can now have a version attribute:
|
||||
|
||||
version="[<|<=|=>|>] MAJOR.MINOR"
|
||||
|
||||
(< and > should be to be entity escaped as < and >). If this
|
||||
version check is not met, then the element and its children will be
|
||||
ignored. This allows having alternate sections of the theme file for
|
||||
older and newer version of the Metacity theme format.
|
||||
|
||||
When placed on the toplevel <metacity_theme> element, an unsatisfied
|
||||
version check will not just cause the contents of the file to be
|
||||
ignored, it will also cause the lookup of a theme file to proceed on
|
||||
and look for an older format 2 or format 1 file. This allows making a
|
||||
metacity-theme-3.xml file that is only used the format version 3.2 or
|
||||
newer is supported, and using metacity-theme-1.xml for older window
|
||||
managers.
|
||||
|
||||
New Features in Theme Format Version 2
|
||||
======================================
|
||||
|
||||
|
10
mutter.doap
10
mutter.doap
@ -6,6 +6,16 @@
|
||||
|
||||
<name xml:lang="en">mutter</name>
|
||||
<shortdesc xml:lang="en">Window and compositing manager based on Clutter</shortdesc>
|
||||
<description>Mutter is a window and compositing manager that displays and
|
||||
manages your desktop via OpenGL. Mutter combines a sophisticated display engine
|
||||
using the Clutter toolkit with solid window-management logic inherited from the
|
||||
Metacity window manager.
|
||||
|
||||
While Mutter can be used stand-alone, it is primarily intended to be used as
|
||||
the display core of a larger system such as GNOME Shell. For this reason,
|
||||
Mutter is very extensible via plugins, which are used both to add fancy visual
|
||||
effects and to rework the window management behaviors to meet the needs of the
|
||||
environment.</description>
|
||||
<!--
|
||||
<homepage rdf:resource="http://www.gnome.org/" />
|
||||
-->
|
||||
|
@ -22,6 +22,7 @@ dz
|
||||
el
|
||||
en_CA
|
||||
en_GB
|
||||
eo
|
||||
es
|
||||
et
|
||||
eu
|
||||
@ -57,6 +58,7 @@ mn
|
||||
mr
|
||||
ms
|
||||
nb
|
||||
nds
|
||||
ne
|
||||
nl
|
||||
nn
|
||||
@ -81,6 +83,7 @@ te
|
||||
th
|
||||
tk
|
||||
tr
|
||||
ug
|
||||
uk
|
||||
vi
|
||||
wa
|
||||
|
@ -1,11 +1,15 @@
|
||||
# List of source files containing translatable strings.
|
||||
# Please keep this file sorted alphabetically.
|
||||
src/50-mutter-windows.xml.in
|
||||
src/compositor/compositor.c
|
||||
src/core/bell.c
|
||||
src/core/core.c
|
||||
src/core/delete.c
|
||||
src/core/display.c
|
||||
src/core/errors.c
|
||||
src/core/keybindings.c
|
||||
src/core/main.c
|
||||
src/core/mutter.c
|
||||
src/core/prefs.c
|
||||
src/core/screen.c
|
||||
src/core/session.c
|
||||
@ -13,10 +17,9 @@ src/core/util.c
|
||||
src/core/window.c
|
||||
src/core/window-props.c
|
||||
src/core/xprops.c
|
||||
src/include/all-keybindings.h
|
||||
src/mutter.desktop.in
|
||||
src/mutter-wm.desktop.in
|
||||
src/mutter.schemas.in
|
||||
src/org.gnome.mutter.gschema.xml.in
|
||||
src/tools/mutter-message.c
|
||||
src/ui/frames.c
|
||||
src/ui/menu.c
|
||||
|
5743
po/ca@valencia.po
5743
po/ca@valencia.po
File diff suppressed because it is too large
Load Diff
2715
po/en_GB.po
2715
po/en_GB.po
File diff suppressed because it is too large
Load Diff
2805
po/pt_BR.po
2805
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
2859
po/sr@latin.po
2859
po/sr@latin.po
File diff suppressed because it is too large
Load Diff
2776
po/zh_CN.po
2776
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
1730
po/zh_HK.po
1730
po/zh_HK.po
File diff suppressed because it is too large
Load Diff
1834
po/zh_TW.po
1834
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
15
src/50-mutter-windows.xml.in
Normal file
15
src/50-mutter-windows.xml.in
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<KeyListEntries schema="org.gnome.mutter.keybindings"
|
||||
group="system"
|
||||
_name="Windows"
|
||||
wm_name="Mutter"
|
||||
package="mutter">
|
||||
|
||||
<KeyListEntry name="toggle-tiled-left"
|
||||
_description="View split on left"/>
|
||||
|
||||
<KeyListEntry name="toggle-tiled-right"
|
||||
_description="View split on right"/>
|
||||
|
||||
</KeyListEntries>
|
||||
|
330
src/Makefile.am
330
src/Makefile.am
@ -1,89 +1,114 @@
|
||||
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
|
||||
.AUTOPARALLEL:
|
||||
|
||||
lib_LTLIBRARIES = libmutter-private.la
|
||||
lib_LTLIBRARIES = libmutter.la
|
||||
|
||||
SUBDIRS=wm-tester tools compositor/plugins
|
||||
|
||||
INCLUDES=@MUTTER_CFLAGS@ -I $(srcdir)/include -I$(srcdir)/compositor -DMUTTER_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -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@\"
|
||||
INCLUDES= \
|
||||
$(MUTTER_CFLAGS) \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/core \
|
||||
-I$(srcdir)/ui \
|
||||
-I$(srcdir)/compositor \
|
||||
-DMUTTER_LIBEXECDIR=\"$(libexecdir)\" \
|
||||
-DHOST_ALIAS=\"@HOST_ALIAS@\" \
|
||||
-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" \
|
||||
-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@\" \
|
||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
|
||||
|
||||
mutter_built_sources = \
|
||||
mutter-marshal.h \
|
||||
mutter-marshal.c \
|
||||
mutter-enum-types.h \
|
||||
mutter-enum-types.c
|
||||
|
||||
mutter_SOURCES= \
|
||||
libmutter_la_SOURCES = \
|
||||
core/async-getprop.c \
|
||||
core/async-getprop.h \
|
||||
core/alttabhandler.c \
|
||||
include/alttabhandler.h \
|
||||
core/alttabhandlerdefault.c \
|
||||
include/alttabhandlerdefault.h \
|
||||
core/bell.c \
|
||||
core/bell.h \
|
||||
core/boxes.c \
|
||||
include/boxes.h \
|
||||
core/boxes-private.h \
|
||||
meta/boxes.h \
|
||||
compositor/cogl-utils.c \
|
||||
compositor/cogl-utils.h \
|
||||
compositor/compositor.c \
|
||||
compositor/compositor-private.h \
|
||||
compositor/mutter-module.c \
|
||||
compositor/mutter-module.h \
|
||||
compositor/mutter-plugin.c \
|
||||
compositor/mutter-plugin-manager.c \
|
||||
compositor/mutter-plugin-manager.h \
|
||||
compositor/mutter-shaped-texture.c \
|
||||
compositor/mutter-window.c \
|
||||
compositor/mutter-window-private.h \
|
||||
compositor/mutter-window-group.c \
|
||||
compositor/mutter-window-group.h \
|
||||
compositor/shadow.c \
|
||||
compositor/shadow.h \
|
||||
compositor/mutter-shaped-texture.h \
|
||||
compositor/tidy/tidy-texture-frame.c \
|
||||
compositor/tidy/tidy-texture-frame.h \
|
||||
include/compositor.h \
|
||||
include/mutter-plugin.h \
|
||||
include/mutter-window.h \
|
||||
include/compositor-mutter.h \
|
||||
compositor/meta-background-actor.c \
|
||||
compositor/meta-background-actor-private.h \
|
||||
compositor/meta-module.c \
|
||||
compositor/meta-module.h \
|
||||
compositor/meta-plugin.c \
|
||||
compositor/meta-plugin-manager.c \
|
||||
compositor/meta-plugin-manager.h \
|
||||
compositor/meta-shadow-factory.c \
|
||||
compositor/meta-shadow-factory-private.h \
|
||||
compositor/meta-shaped-texture.c \
|
||||
compositor/meta-texture-rectangle.c \
|
||||
compositor/meta-texture-rectangle.h \
|
||||
compositor/meta-texture-tower.c \
|
||||
compositor/meta-texture-tower.h \
|
||||
compositor/meta-window-actor.c \
|
||||
compositor/meta-window-actor-private.h \
|
||||
compositor/meta-window-group.c \
|
||||
compositor/meta-window-group.h \
|
||||
compositor/meta-window-shape.c \
|
||||
compositor/meta-window-shape.h \
|
||||
compositor/region-utils.c \
|
||||
compositor/region-utils.h \
|
||||
meta/compositor.h \
|
||||
meta/meta-background-actor.h \
|
||||
meta/meta-plugin.h \
|
||||
meta/meta-shadow-factory.h \
|
||||
meta/meta-window-actor.h \
|
||||
meta/compositor-mutter.h \
|
||||
core/above-tab-keycode.c \
|
||||
core/constraints.c \
|
||||
core/constraints.h \
|
||||
core/core.c \
|
||||
core/delete.c \
|
||||
core/display.c \
|
||||
core/display-private.h \
|
||||
include/display.h \
|
||||
meta/display.h \
|
||||
ui/draw-workspace.c \
|
||||
ui/draw-workspace.h \
|
||||
core/edge-resistance.c \
|
||||
core/edge-resistance.h \
|
||||
core/errors.c \
|
||||
include/errors.h \
|
||||
meta/errors.h \
|
||||
core/eventqueue.c \
|
||||
core/eventqueue.h \
|
||||
core/frame.c \
|
||||
core/frame-private.h \
|
||||
include/frame.h \
|
||||
core/frame.h \
|
||||
ui/gradient.c \
|
||||
ui/gradient.h \
|
||||
meta/gradient.h \
|
||||
core/group-private.h \
|
||||
core/group-props.c \
|
||||
core/group-props.h \
|
||||
core/group.c \
|
||||
include/group.h \
|
||||
meta/group.h \
|
||||
core/iconcache.c \
|
||||
core/iconcache.h \
|
||||
core/keybindings.c \
|
||||
core/keybindings-private.h \
|
||||
core/main.c \
|
||||
core/mutter-Xatomtype.h \
|
||||
core/mutter-Xatomtype.h \
|
||||
core/place.c \
|
||||
core/place.h \
|
||||
core/prefs.c \
|
||||
include/prefs.h \
|
||||
meta/prefs.h \
|
||||
core/screen.c \
|
||||
core/screen-private.h \
|
||||
include/screen.h \
|
||||
include/types.h \
|
||||
meta/screen.h \
|
||||
meta/types.h \
|
||||
core/session.c \
|
||||
core/session.h \
|
||||
core/stack.c \
|
||||
@ -91,22 +116,20 @@ mutter_SOURCES= \
|
||||
core/stack-tracker.c \
|
||||
core/stack-tracker.h \
|
||||
core/util.c \
|
||||
include/util.h \
|
||||
meta/util.h \
|
||||
core/window-props.c \
|
||||
core/window-props.h \
|
||||
core/window.c \
|
||||
core/window-private.h \
|
||||
include/window.h \
|
||||
meta/window.h \
|
||||
core/workspace.c \
|
||||
core/workspace-private.h \
|
||||
core/xprops.c \
|
||||
include/xprops.h \
|
||||
include/common.h \
|
||||
include/core.h \
|
||||
include/ui.h \
|
||||
core/xprops.h \
|
||||
meta/common.h \
|
||||
core/core.h \
|
||||
ui/ui.h \
|
||||
inlinepixbufs.h \
|
||||
ui/fixedtip.c \
|
||||
ui/fixedtip.h \
|
||||
ui/frames.c \
|
||||
ui/frames.h \
|
||||
ui/menu.c \
|
||||
@ -114,73 +137,56 @@ mutter_SOURCES= \
|
||||
ui/metaaccellabel.c \
|
||||
ui/metaaccellabel.h \
|
||||
ui/resizepopup.c \
|
||||
include/resizepopup.h \
|
||||
ui/resizepopup.h \
|
||||
ui/tabpopup.c \
|
||||
include/tabpopup.h \
|
||||
ui/tabpopup.h \
|
||||
ui/tile-preview.c \
|
||||
ui/tile-preview.h \
|
||||
ui/theme-parser.c \
|
||||
ui/theme-parser.h \
|
||||
ui/theme.c \
|
||||
ui/theme.h \
|
||||
ui/themewidget.c \
|
||||
ui/themewidget.h \
|
||||
meta/theme.h \
|
||||
ui/theme-private.h \
|
||||
ui/ui.c \
|
||||
include/all-keybindings.h \
|
||||
meta/preview-widget.h \
|
||||
ui/preview-widget.c \
|
||||
$(mutter_built_sources)
|
||||
|
||||
# by setting libmutter_private_la_CFLAGS, the files shared with
|
||||
# mutter proper will be compiled with different names.
|
||||
libmutter_private_la_CFLAGS =
|
||||
libmutter_private_la_SOURCES= \
|
||||
core/boxes.c \
|
||||
include/boxes.h \
|
||||
ui/gradient.c \
|
||||
ui/gradient.h \
|
||||
core/util.c \
|
||||
include/util.h \
|
||||
include/common.h \
|
||||
ui/preview-widget.c \
|
||||
ui/preview-widget.h \
|
||||
ui/theme-parser.c \
|
||||
ui/theme-parser.h \
|
||||
ui/theme.c \
|
||||
ui/theme.h
|
||||
|
||||
libmutter_private_la_LDFLAGS = -no-undefined
|
||||
libmutter_private_la_LIBADD = @MUTTER_LIBS@
|
||||
|
||||
libmutterincludedir = $(includedir)/mutter/mutter-private
|
||||
libmutter_la_LDFLAGS = -no-undefined
|
||||
libmutter_la_LIBADD = $(MUTTER_LIBS)
|
||||
|
||||
# Headers installed for plugins; introspected information will
|
||||
# be extracted into Mutter-<version>.gir
|
||||
libmutterinclude_base_headers = \
|
||||
include/alttabhandler.h \
|
||||
include/boxes.h \
|
||||
ui/gradient.h \
|
||||
include/main.h \
|
||||
include/util.h \
|
||||
include/common.h \
|
||||
ui/theme-parser.h \
|
||||
ui/theme.h \
|
||||
include/prefs.h \
|
||||
include/window.h \
|
||||
include/workspace.h \
|
||||
include/compositor.h \
|
||||
include/compositor-mutter.h \
|
||||
include/types.h \
|
||||
include/errors.h \
|
||||
include/screen.h \
|
||||
include/display.h \
|
||||
include/group.h \
|
||||
include/keybindings.h \
|
||||
include/mutter-plugin.h \
|
||||
include/mutter-window.h
|
||||
meta/boxes.h \
|
||||
meta/common.h \
|
||||
meta/compositor-mutter.h \
|
||||
meta/compositor.h \
|
||||
meta/display.h \
|
||||
meta/errors.h \
|
||||
meta/gradient.h \
|
||||
meta/group.h \
|
||||
meta/keybindings.h \
|
||||
meta/main.h \
|
||||
meta/meta-background-actor.h \
|
||||
meta/meta-plugin.h \
|
||||
meta/meta-shaped-texture.h \
|
||||
meta/meta-shadow-factory.h \
|
||||
meta/meta-window-actor.h \
|
||||
meta/prefs.h \
|
||||
meta/screen.h \
|
||||
meta/theme.h \
|
||||
meta/types.h \
|
||||
meta/util.h \
|
||||
meta/window.h \
|
||||
meta/workspace.h
|
||||
|
||||
# Excluded from scanning for introspection but installed
|
||||
# preview-widget.h: only part of libmutter-private
|
||||
# atomnames.h: macros cause problems for scanning process
|
||||
libmutterinclude_extra_headers = \
|
||||
ui/preview-widget.h \
|
||||
include/atomnames.h
|
||||
meta/preview-widget.h \
|
||||
meta/atomnames.h
|
||||
|
||||
libmutterincludedir = $(includedir)/mutter/meta
|
||||
|
||||
libmutterinclude_HEADERS = \
|
||||
$(libmutterinclude_base_headers) \
|
||||
@ -191,9 +197,18 @@ mutter_theme_viewer_SOURCES= \
|
||||
|
||||
bin_PROGRAMS=mutter mutter-theme-viewer
|
||||
|
||||
api_version = $(MUTTER_MAJOR_VERSION).$(MUTTER_MINOR_VERSION)
|
||||
mutter_SOURCES = core/mutter.c
|
||||
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
|
||||
if HAVE_INTROSPECTION
|
||||
include $(INTROSPECTION_MAKEFILE)
|
||||
|
||||
# Since we don't make any guarantees about stability and we don't support
|
||||
# parallel install, there's no real reason to change directories, filenames,
|
||||
# etc. as we change the Mutter tarball version.
|
||||
#api_version = $(MUTTER_MAJOR_VERSION).$(MUTTER_MINOR_VERSION)
|
||||
api_version = 3.0
|
||||
|
||||
if WITH_INTROSPECTION
|
||||
# These files are in package-private directories, even though they may be used
|
||||
# by plugins. If you're writing a plugin, use g-ir-compiler --add-include-path
|
||||
# and g-ir-compiler --includedir.
|
||||
@ -203,46 +218,32 @@ gir_DATA = Meta-$(api_version).gir
|
||||
typelibdir = $(pkglibdir)
|
||||
typelib_DATA = Meta-$(api_version).typelib
|
||||
|
||||
# We need to strip out the attribute that would point back to libmutter-introspect
|
||||
# so that libgirepository looks for symbols in the executable instead
|
||||
Meta-$(api_version).gir: $(G_IR_SCANNER) mutter $(libmutterinclude_HEADERS) $(mutter_SOURCES)
|
||||
$(AM_V_GEN) pwd=`pwd` ; \
|
||||
cd $(srcdir) && \
|
||||
$(G_IR_SCANNER) \
|
||||
--namespace=Meta \
|
||||
--nsversion=$(api_version) \
|
||||
--include=GObject-2.0 \
|
||||
--include=Gdk-2.0 \
|
||||
--include=Gtk-2.0 \
|
||||
--include=Clutter-1.0 \
|
||||
--pkg=clutter-1.0 \
|
||||
--pkg=gtk+-2.0 \
|
||||
--include=xfixes-4.0 \
|
||||
--program=$$pwd/mutter \
|
||||
$(filter %.c,$(mutter_SOURCES)) \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(INCLUDES) \
|
||||
-o $$pwd/$@
|
||||
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
|
||||
@META_GIR@_EXPORT_PACKAGES = libmutter
|
||||
@META_GIR@_CFLAGS = $(INCLUDES)
|
||||
@META_GIR@_LIBS = libmutter.la
|
||||
@META_GIR@_FILES = \
|
||||
mutter-enum-types.h \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(filter %.c,$(libmutter_la_SOURCES))
|
||||
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
|
||||
|
||||
Meta-$(api_version).typelib: $(G_IR_COMPILER) Meta-$(api_version).gir
|
||||
$(AM_V_GEN) LD_LIBRARY_PATH=$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}. $(G_IR_COMPILER) Meta-$(api_version).gir -o $@
|
||||
endif
|
||||
|
||||
EFENCE=
|
||||
mutter_LDADD=@MUTTER_LIBS@ $(EFENCE)
|
||||
mutter_LDFLAGS=-export-dynamic
|
||||
mutter_theme_viewer_LDADD= $(MUTTER_LIBS) libmutter.la
|
||||
|
||||
mutter_theme_viewer_LDADD= @MUTTER_LIBS@ libmutter-private.la
|
||||
|
||||
testboxes_SOURCES=include/util.h core/util.c include/boxes.h core/boxes.c core/testboxes.c
|
||||
testgradient_SOURCES=ui/gradient.h ui/gradient.c ui/testgradient.c
|
||||
testasyncgetprop_SOURCES=core/async-getprop.h core/async-getprop.c core/testasyncgetprop.c
|
||||
testboxes_SOURCES = core/testboxes.c
|
||||
testgradient_SOURCES = ui/testgradient.c
|
||||
testasyncgetprop_SOURCES = core/testasyncgetprop.c
|
||||
|
||||
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
|
||||
|
||||
testboxes_LDADD= @MUTTER_LIBS@
|
||||
testgradient_LDADD= @MUTTER_LIBS@
|
||||
testasyncgetprop_LDADD= @MUTTER_LIBS@
|
||||
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
@ -256,20 +257,17 @@ wmproperties_in_files=mutter-wm.desktop.in
|
||||
wmproperties_files=$(wmproperties_in_files:.desktop.in=.desktop)
|
||||
wmproperties_DATA = $(wmproperties_files)
|
||||
|
||||
schemadir = @GCONF_SCHEMA_FILE_DIR@
|
||||
schema_in_files = mutter.schemas.in
|
||||
schema_DATA = $(schema_in_files:.schemas.in=.schemas)
|
||||
xmldir = @GNOME_KEYBINDINGS_KEYSDIR@
|
||||
xml_in_files = \
|
||||
50-mutter-windows.xml.in
|
||||
xml_DATA = $(xml_in_files:.xml.in=.xml)
|
||||
|
||||
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml
|
||||
@INTLTOOL_XML_NOMERGE_RULE@
|
||||
@GSETTINGS_RULES@
|
||||
|
||||
@INTLTOOL_SCHEMAS_RULE@
|
||||
|
||||
if GCONF_SCHEMAS_INSTALL
|
||||
install-data-local:
|
||||
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(schema_DATA)
|
||||
else
|
||||
install-data-local:
|
||||
endif
|
||||
convertdir = $(datadir)/GConf/gsettings
|
||||
convert_DATA = mutter-schemas.convert
|
||||
|
||||
IMAGES=stock_maximize.png stock_minimize.png stock_delete.png
|
||||
VARIABLES=stock_maximize_data $(srcdir)/stock_maximize.png \
|
||||
@ -281,7 +279,8 @@ CLEANFILES = \
|
||||
inlinepixbufs.h \
|
||||
mutter.desktop \
|
||||
mutter-wm.desktop \
|
||||
mutter.schemas \
|
||||
org.gnome.mutter.gschema.xml \
|
||||
$(xml_DATA) \
|
||||
$(mutter_built_sources) \
|
||||
$(typelib_DATA) \
|
||||
$(gir_DATA)
|
||||
@ -291,50 +290,31 @@ inlinepixbufs.h: $(IMAGES)
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
|
||||
pkgconfig_DATA = libmutter-private.pc mutter-plugins.pc
|
||||
pkgconfig_DATA = libmutter.pc mutter-plugins.pc
|
||||
|
||||
EXTRA_DIST=$(desktopfiles_files) \
|
||||
$(wmproperties_files) \
|
||||
$(IMAGES) \
|
||||
$(desktopfiles_in_files) \
|
||||
$(wmproperties_in_files) \
|
||||
$(schema_in_files) \
|
||||
libmutter-private.pc.in \
|
||||
$(xml_in_files) \
|
||||
org.gnome.mutter.gschema.xml.in \
|
||||
mutter-schemas.convert \
|
||||
libmutter.pc.in \
|
||||
mutter-plugins.pc.in \
|
||||
mutter-enum-types.h.in \
|
||||
mutter-enum-types.c.in \
|
||||
mutter-marshal.list
|
||||
mutter-enum-types.c.in
|
||||
|
||||
BUILT_SOURCES += $(mutter_built_sources)
|
||||
MUTTER_STAMP_FILES = stamp-mutter-marshal.h stamp-mutter-enum-types.h
|
||||
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
|
||||
CLEANFILES += $(MUTTER_STAMP_FILES)
|
||||
|
||||
mutter-marshal.h: stamp-mutter-marshal.h
|
||||
@true
|
||||
stamp-mutter-marshal.h: Makefile mutter-marshal.list
|
||||
$(AM_V_GEN) $(GLIB_GENMARSHAL) \
|
||||
--prefix=_mutter_marshal \
|
||||
--header \
|
||||
$(srcdir)/mutter-marshal.list > xgen-tmh && \
|
||||
(cmp -s xgen-tmh mutter-marshal.h || cp -f xgen-tmh mutter-marshal.h) && \
|
||||
rm -f xgen-tmh && \
|
||||
echo timestamp > $(@F)
|
||||
|
||||
mutter-marshal.c: Makefile mutter-marshal.list
|
||||
$(AM_V_GEN) (echo "#include \"mutter-marshal.h\"" ; \
|
||||
$(GLIB_GENMARSHAL) \
|
||||
--prefix=_mutter_marshal \
|
||||
--body \
|
||||
$(srcdir)/mutter-marshal.list ) > xgen-tmc && \
|
||||
cp -f xgen-tmc mutter-marshal.c && \
|
||||
rm -f xgen-tmc
|
||||
|
||||
mutter-enum-types.h: stamp-mutter-enum-types.h Makefile
|
||||
@true
|
||||
stamp-mutter-enum-types.h: $(libmutterinclude_base_headers) mutter-enum-types.h.in
|
||||
$(AM_V_GEN) ( cd $(srcdir) && \
|
||||
$(GLIB_MKENUMS) \
|
||||
--template $(srcdir)/mutter-enum-types.h.in \
|
||||
--template mutter-enum-types.h.in \
|
||||
$(libmutterinclude_base_headers) ) >> xgen-teth && \
|
||||
(cmp -s xgen-teth mutter-enum-types.h || cp xgen-teth mutter-enum-types.h) && \
|
||||
rm -f xgen-teth && \
|
||||
@ -343,7 +323,7 @@ stamp-mutter-enum-types.h: $(libmutterinclude_base_headers) mutter-enum-types.h.
|
||||
mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
|
||||
$(AM_V_GEN) ( cd $(srcdir) && \
|
||||
$(GLIB_MKENUMS) \
|
||||
--template $(srcdir)/mutter-enum-types.c.in \
|
||||
--template mutter-enum-types.c.in \
|
||||
$(libmutterinclude_base_headers) ) >> xgen-tetc && \
|
||||
cp xgen-tetc mutter-enum-types.c && \
|
||||
rm -f xgen-tetc
|
||||
|
110
src/compositor/cogl-utils.c
Normal file
110
src/compositor/cogl-utils.c
Normal file
@ -0,0 +1,110 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Utilities for use with Cogl
|
||||
*
|
||||
* Copyright 2010 Red Hat, Inc.
|
||||
* Copyright 2010 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "cogl-utils.h"
|
||||
|
||||
/**
|
||||
* meta_create_color_texture_4ub:
|
||||
* @red:
|
||||
* @green:
|
||||
* @blue:
|
||||
* @alpha:
|
||||
* @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
|
||||
*/
|
||||
CoglHandle
|
||||
meta_create_color_texture_4ub (guint8 red,
|
||||
guint8 green,
|
||||
guint8 blue,
|
||||
guint8 alpha,
|
||||
CoglTextureFlags flags)
|
||||
{
|
||||
CoglColor color;
|
||||
guint8 pixel[4];
|
||||
|
||||
cogl_color_set_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_material:
|
||||
* @src_texture: (allow-none): texture to use initially for the layer
|
||||
*
|
||||
* Creates a material with a single layer. Using a common template
|
||||
* allows sharing a shader for different uses in Mutter. To share the same
|
||||
* shader with all other materials that are just texture plus opacity
|
||||
* would require Cogl fixes.
|
||||
* (See http://bugzilla.clutter-project.org/show_bug.cgi?id=2425)
|
||||
*
|
||||
* Return value: (transfer full): a newly created Cogl material
|
||||
*/
|
||||
CoglHandle
|
||||
meta_create_texture_material (CoglHandle src_texture)
|
||||
{
|
||||
static CoglHandle texture_material_template = COGL_INVALID_HANDLE;
|
||||
CoglHandle material;
|
||||
|
||||
/* We use a material that has a dummy texture as a base for all
|
||||
texture materials. The idea is that only the Cogl texture object
|
||||
would be different in the children so it is likely that Cogl will
|
||||
be able to share GL programs between all the textures. */
|
||||
if (G_UNLIKELY (texture_material_template == COGL_INVALID_HANDLE))
|
||||
{
|
||||
CoglHandle dummy_texture;
|
||||
|
||||
dummy_texture = meta_create_color_texture_4ub (0xff, 0xff, 0xff, 0xff,
|
||||
COGL_TEXTURE_NONE);
|
||||
|
||||
texture_material_template = cogl_material_new ();
|
||||
cogl_material_set_layer (texture_material_template, 0, dummy_texture);
|
||||
cogl_handle_unref (dummy_texture);
|
||||
}
|
||||
|
||||
material = cogl_material_copy (texture_material_template);
|
||||
|
||||
if (src_texture != COGL_INVALID_HANDLE)
|
||||
cogl_material_set_layer (material, 0, src_texture);
|
||||
|
||||
return material;
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008 Iain Holmes
|
||||
* Utilities for use with Cogl
|
||||
*
|
||||
* Copyright 2010 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
|
||||
@ -19,13 +20,16 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_FRAME_H
|
||||
#define META_FRAME_H
|
||||
#ifndef __META_COGL_UTILS_H__
|
||||
#define __META_COGL_UTILS_H__
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include "types.h"
|
||||
CoglHandle meta_create_color_texture_4ub (guint8 red,
|
||||
guint8 green,
|
||||
guint8 blue,
|
||||
guint8 alpha,
|
||||
CoglTextureFlags flags);
|
||||
CoglHandle meta_create_texture_material (CoglHandle src_texture);
|
||||
|
||||
Window meta_frame_get_xwindow (MetaFrame *frame);
|
||||
|
||||
#endif
|
||||
#endif /* __META_COGL_UTILS_H__ */
|
@ -5,9 +5,10 @@
|
||||
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
|
||||
#include "compositor.h"
|
||||
#include "display.h"
|
||||
#include "mutter-plugin-manager.h"
|
||||
#include <meta/compositor.h>
|
||||
#include <meta/display.h>
|
||||
#include "meta-plugin-manager.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
typedef struct _MetaCompScreen MetaCompScreen;
|
||||
@ -23,7 +24,7 @@ struct _MetaCompositor
|
||||
|
||||
ClutterActor *shadow_src;
|
||||
|
||||
MutterPlugin *modal_plugin;
|
||||
MetaPlugin *modal_plugin;
|
||||
|
||||
gboolean show_redraw : 1;
|
||||
gboolean debug : 1;
|
||||
@ -35,34 +36,36 @@ struct _MetaCompScreen
|
||||
MetaScreen *screen;
|
||||
|
||||
ClutterActor *stage, *window_group, *overlay_group;
|
||||
ClutterActor *background_actor;
|
||||
ClutterActor *hidden_group;
|
||||
GList *windows;
|
||||
GHashTable *windows_by_xid;
|
||||
Window output;
|
||||
|
||||
/* Used for unredirecting fullscreen windows */
|
||||
guint disable_unredirect_count;
|
||||
MetaWindowActor *unredirected_window;
|
||||
|
||||
/* Before we create the output window */
|
||||
XserverRegion pending_input_region;
|
||||
|
||||
gint switch_workspace_in_progress;
|
||||
|
||||
MutterPluginManager *plugin_mgr;
|
||||
MetaPluginManager *plugin_mgr;
|
||||
};
|
||||
|
||||
void mutter_switch_workspace_completed (MetaScreen *screen);
|
||||
void mutter_set_stage_input_region (MetaScreen *screen,
|
||||
XserverRegion region);
|
||||
void mutter_empty_stage_input_region (MetaScreen *screen);
|
||||
void meta_switch_workspace_completed (MetaScreen *screen);
|
||||
|
||||
gboolean mutter_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MutterPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp);
|
||||
void mutter_end_modal_for_plugin (MetaScreen *screen,
|
||||
MutterPlugin *plugin,
|
||||
guint32 timestamp);
|
||||
gboolean meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp);
|
||||
void meta_end_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
guint32 timestamp);
|
||||
|
||||
void mutter_check_end_modal (MetaScreen *screen);
|
||||
void meta_check_end_modal (MetaScreen *screen);
|
||||
|
||||
#endif /* META_COMPOSITOR_PRIVATE_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
15
src/compositor/meta-background-actor-private.h
Normal file
15
src/compositor/meta-background-actor-private.h
Normal file
@ -0,0 +1,15 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#ifndef META_BACKGROUND_ACTOR_PRIVATE_H
|
||||
#define META_BACKGROUND_ACTOR_PRIVATE_H
|
||||
|
||||
#include <meta/screen.h>
|
||||
#include <meta/meta-background-actor.h>
|
||||
|
||||
void meta_background_actor_set_visible_region (MetaBackgroundActor *self,
|
||||
cairo_region_t *visible_region);
|
||||
|
||||
void meta_background_actor_update (MetaScreen *screen);
|
||||
void meta_background_actor_screen_size_changed (MetaScreen *screen);
|
||||
|
||||
#endif /* META_BACKGROUND_ACTOR_PRIVATE_H */
|
627
src/compositor/meta-background-actor.c
Normal file
627
src/compositor/meta-background-actor.c
Normal file
@ -0,0 +1,627 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* meta-background-actor.c: Actor for painting the root window background
|
||||
*
|
||||
* Copyright 2009 Sander Dijkhuis
|
||||
* Copyright 2010 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Portions adapted from gnome-shell/src/shell-global.c
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#define COGL_ENABLE_EXPERIMENTAL_API
|
||||
#include <cogl/cogl-texture-pixmap-x11.h>
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "cogl-utils.h"
|
||||
#include "compositor-private.h"
|
||||
#include <meta/errors.h>
|
||||
#include "meta-background-actor-private.h"
|
||||
|
||||
/* We allow creating multiple MetaBackgroundActors for the same MetaScreen to
|
||||
* allow different rendering options to be set for different copies.
|
||||
* But we want to share the same underlying CoglTexture for efficiency and
|
||||
* to avoid driver bugs that might occur if we created multiple CoglTexturePixmaps
|
||||
* for the same pixmap.
|
||||
*
|
||||
* This structure holds common information.
|
||||
*/
|
||||
typedef struct _MetaScreenBackground MetaScreenBackground;
|
||||
|
||||
struct _MetaScreenBackground
|
||||
{
|
||||
MetaScreen *screen;
|
||||
GSList *actors;
|
||||
|
||||
float texture_width;
|
||||
float texture_height;
|
||||
CoglHandle texture;
|
||||
CoglMaterialWrapMode wrap_mode;
|
||||
guint have_pixmap : 1;
|
||||
};
|
||||
|
||||
struct _MetaBackgroundActorPrivate
|
||||
{
|
||||
MetaScreenBackground *background;
|
||||
CoglHandle material;
|
||||
cairo_region_t *visible_region;
|
||||
float dim_factor;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_DIM_FACTOR,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST];
|
||||
|
||||
G_DEFINE_TYPE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
static void set_texture (MetaScreenBackground *background,
|
||||
CoglHandle texture);
|
||||
static void set_texture_to_stage_color (MetaScreenBackground *background);
|
||||
|
||||
static void
|
||||
on_notify_stage_color (GObject *stage,
|
||||
GParamSpec *pspec,
|
||||
MetaScreenBackground *background)
|
||||
{
|
||||
if (!background->have_pixmap)
|
||||
set_texture_to_stage_color (background);
|
||||
}
|
||||
|
||||
static void
|
||||
free_screen_background (MetaScreenBackground *background)
|
||||
{
|
||||
set_texture (background, COGL_INVALID_HANDLE);
|
||||
|
||||
if (background->screen != NULL)
|
||||
{
|
||||
ClutterActor *stage = meta_get_stage_for_screen (background->screen);
|
||||
g_signal_handlers_disconnect_by_func (stage,
|
||||
(gpointer) on_notify_stage_color,
|
||||
background);
|
||||
background->screen = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static MetaScreenBackground *
|
||||
meta_screen_background_get (MetaScreen *screen)
|
||||
{
|
||||
MetaScreenBackground *background;
|
||||
|
||||
background = g_object_get_data (G_OBJECT (screen), "meta-screen-background");
|
||||
if (background == NULL)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
|
||||
background = g_new0 (MetaScreenBackground, 1);
|
||||
|
||||
background->screen = screen;
|
||||
g_object_set_data_full (G_OBJECT (screen), "meta-screen-background",
|
||||
background, (GDestroyNotify) free_screen_background);
|
||||
|
||||
stage = meta_get_stage_for_screen (screen);
|
||||
g_signal_connect (stage, "notify::color",
|
||||
G_CALLBACK (on_notify_stage_color), background);
|
||||
|
||||
meta_background_actor_update (screen);
|
||||
}
|
||||
|
||||
return background;
|
||||
}
|
||||
|
||||
static void
|
||||
update_wrap_mode_of_actor (MetaBackgroundActor *self)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
|
||||
cogl_material_set_layer_wrap_mode (priv->material, 0, priv->background->wrap_mode);
|
||||
}
|
||||
|
||||
static void
|
||||
update_wrap_mode (MetaScreenBackground *background)
|
||||
{
|
||||
GSList *l;
|
||||
int width, height;
|
||||
|
||||
meta_screen_get_size (background->screen, &width, &height);
|
||||
|
||||
/* We turn off repeating when we have a full-screen pixmap to keep from
|
||||
* getting artifacts from one side of the image sneaking into the other
|
||||
* side of the image via bilinear filtering.
|
||||
*/
|
||||
if (width == background->texture_width && height == background->texture_height)
|
||||
background->wrap_mode = COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE;
|
||||
else
|
||||
background->wrap_mode = COGL_MATERIAL_WRAP_MODE_REPEAT;
|
||||
|
||||
for (l = background->actors; l; l = l->next)
|
||||
update_wrap_mode_of_actor (l->data);
|
||||
}
|
||||
|
||||
static void
|
||||
set_texture_on_actor (MetaBackgroundActor *self)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
MetaDisplay *display = meta_screen_get_display (priv->background->screen);
|
||||
|
||||
/* This may trigger destruction of an old texture pixmap, which, if
|
||||
* the underlying X pixmap is already gone has the tendency to trigger
|
||||
* X errors inside DRI. For safety, trap errors */
|
||||
meta_error_trap_push (display);
|
||||
cogl_material_set_layer (priv->material, 0, priv->background->texture);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
static void
|
||||
set_texture (MetaScreenBackground *background,
|
||||
CoglHandle texture)
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (background->screen);
|
||||
GSList *l;
|
||||
|
||||
/* This may trigger destruction of an old texture pixmap, which, if
|
||||
* the underlying X pixmap is already gone has the tendency to trigger
|
||||
* X errors inside DRI. For safety, trap errors */
|
||||
meta_error_trap_push (display);
|
||||
if (background->texture != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (background->texture);
|
||||
background->texture = COGL_INVALID_HANDLE;
|
||||
}
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
if (texture != COGL_INVALID_HANDLE)
|
||||
background->texture = cogl_handle_ref (texture);
|
||||
|
||||
background->texture_width = cogl_texture_get_width (background->texture);
|
||||
background->texture_height = cogl_texture_get_height (background->texture);
|
||||
|
||||
for (l = background->actors; l; l = l->next)
|
||||
set_texture_on_actor (l->data);
|
||||
|
||||
update_wrap_mode (background);
|
||||
}
|
||||
|
||||
/* Sets our material to paint with a 1x1 texture of the stage's background
|
||||
* color; doing this when we have no pixmap allows the application to turn
|
||||
* off painting the stage. There might be a performance benefit to
|
||||
* painting in this case with a solid color, but the normal solid color
|
||||
* case is a 1x1 root pixmap, so we'd have to reverse-engineer that to
|
||||
* actually pick up the (small?) performance win. This is just a fallback.
|
||||
*/
|
||||
static void
|
||||
set_texture_to_stage_color (MetaScreenBackground *background)
|
||||
{
|
||||
ClutterActor *stage = meta_get_stage_for_screen (background->screen);
|
||||
ClutterColor color;
|
||||
CoglHandle texture;
|
||||
|
||||
clutter_stage_get_color (CLUTTER_STAGE (stage), &color);
|
||||
|
||||
/* Slicing will prevent COGL from using hardware texturing for
|
||||
* the tiled 1x1 pixmap, and will cause it to draw the window
|
||||
* background in millions of separate 1x1 rectangles */
|
||||
texture = meta_create_color_texture_4ub (color.red, color.green,
|
||||
color.blue, 0xff,
|
||||
COGL_TEXTURE_NO_SLICING);
|
||||
set_texture (background, texture);
|
||||
cogl_handle_unref (texture);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_dispose (GObject *object)
|
||||
{
|
||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
|
||||
meta_background_actor_set_visible_region (self, NULL);
|
||||
|
||||
if (priv->background != NULL)
|
||||
{
|
||||
priv->background->actors = g_slist_remove (priv->background->actors, self);
|
||||
priv->background = NULL;
|
||||
}
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (priv->material);
|
||||
priv->material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_get_preferred_width (ClutterActor *actor,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
int width, height;
|
||||
|
||||
meta_screen_get_size (priv->background->screen, &width, &height);
|
||||
|
||||
if (min_width_p)
|
||||
*min_width_p = width;
|
||||
if (natural_width_p)
|
||||
*natural_width_p = width;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_get_preferred_height (ClutterActor *actor,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
|
||||
{
|
||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
int width, height;
|
||||
|
||||
meta_screen_get_size (priv->background->screen, &width, &height);
|
||||
|
||||
if (min_height_p)
|
||||
*min_height_p = height;
|
||||
if (natural_height_p)
|
||||
*natural_height_p = height;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
guint8 opacity = clutter_actor_get_paint_opacity (actor);
|
||||
guint8 color_component;
|
||||
int width, height;
|
||||
|
||||
meta_screen_get_size (priv->background->screen, &width, &height);
|
||||
|
||||
color_component = (int)(0.5 + opacity * priv->dim_factor);
|
||||
|
||||
cogl_material_set_color4ub (priv->material,
|
||||
color_component,
|
||||
color_component,
|
||||
color_component,
|
||||
opacity);
|
||||
|
||||
cogl_set_source (priv->material);
|
||||
|
||||
if (priv->visible_region)
|
||||
{
|
||||
int n_rectangles = cairo_region_num_rectangles (priv->visible_region);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_rectangles; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_region_get_rectangle (priv->visible_region, i, &rect);
|
||||
|
||||
cogl_rectangle_with_texture_coords (rect.x, rect.y,
|
||||
rect.x + rect.width, rect.y + rect.height,
|
||||
rect.x / priv->background->texture_width,
|
||||
rect.y / priv->background->texture_height,
|
||||
(rect.x + rect.width) / priv->background->texture_width,
|
||||
(rect.y + rect.height) / priv->background->texture_height);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cogl_rectangle_with_texture_coords (0.0f, 0.0f,
|
||||
width, height,
|
||||
0.0f, 0.0f,
|
||||
width / priv->background->texture_width,
|
||||
height / priv->background->texture_height);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_background_actor_get_paint_volume (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
int width, height;
|
||||
|
||||
meta_screen_get_size (priv->background->screen, &width, &height);
|
||||
|
||||
clutter_paint_volume_set_width (volume, width);
|
||||
clutter_paint_volume_set_height (volume, height);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_set_dim_factor (MetaBackgroundActor *self,
|
||||
gfloat dim_factor)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->dim_factor == dim_factor)
|
||||
return;
|
||||
|
||||
priv->dim_factor = dim_factor;
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_DIM_FACTOR]);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_get_property(GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DIM_FACTOR:
|
||||
g_value_set_float (value, priv->dim_factor);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_set_property(GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DIM_FACTOR:
|
||||
meta_background_actor_set_dim_factor (self, g_value_get_float (value));
|
||||
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 *pspec;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaBackgroundActorPrivate));
|
||||
|
||||
object_class->dispose = meta_background_actor_dispose;
|
||||
object_class->get_property = meta_background_actor_get_property;
|
||||
object_class->set_property = meta_background_actor_set_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->paint = meta_background_actor_paint;
|
||||
actor_class->get_paint_volume = meta_background_actor_get_paint_volume;
|
||||
|
||||
/**
|
||||
* MetaBackgroundActor:dim-factor:
|
||||
*
|
||||
* Factor to dim the background by, between 0.0 (black) and 1.0 (original
|
||||
* colors)
|
||||
*/
|
||||
pspec = g_param_spec_float ("dim-factor",
|
||||
"Dim factor",
|
||||
"Factor to dim the background by",
|
||||
0.0, 1.0,
|
||||
1.0,
|
||||
G_PARAM_READWRITE);
|
||||
obj_props[PROP_DIM_FACTOR] = pspec;
|
||||
g_object_class_install_property (object_class, PROP_DIM_FACTOR, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_init (MetaBackgroundActor *self)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv;
|
||||
|
||||
priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||
META_TYPE_BACKGROUND_ACTOR,
|
||||
MetaBackgroundActorPrivate);
|
||||
priv->dim_factor = 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_background_actor_new:
|
||||
* @screen: the #MetaScreen
|
||||
*
|
||||
* Creates a new actor to draw the background for the given screen.
|
||||
*
|
||||
* Return value: the newly created background actor
|
||||
*/
|
||||
ClutterActor *
|
||||
meta_background_actor_new_for_screen (MetaScreen *screen)
|
||||
{
|
||||
MetaBackgroundActor *self;
|
||||
MetaBackgroundActorPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (META_IS_SCREEN (screen), NULL);
|
||||
|
||||
self = g_object_new (META_TYPE_BACKGROUND_ACTOR, NULL);
|
||||
priv = self->priv;
|
||||
|
||||
priv->background = meta_screen_background_get (screen);
|
||||
priv->background->actors = g_slist_prepend (priv->background->actors, self);
|
||||
|
||||
priv->material = meta_create_texture_material (NULL);
|
||||
|
||||
set_texture_on_actor (self);
|
||||
update_wrap_mode_of_actor (self);
|
||||
|
||||
return CLUTTER_ACTOR (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_background_actor_update:
|
||||
* @screen: a #MetaScreen
|
||||
*
|
||||
* Refetches the _XROOTPMAP_ID property for the root window and updates
|
||||
* the contents of the background actor based on that. There's no attempt
|
||||
* to optimize out pixmap values that don't change (since a root pixmap
|
||||
* could be replaced by with another pixmap with the same ID under some
|
||||
* circumstances), so this should only be called when we actually receive
|
||||
* a PropertyNotify event for the property.
|
||||
*/
|
||||
void
|
||||
meta_background_actor_update (MetaScreen *screen)
|
||||
{
|
||||
MetaScreenBackground *background;
|
||||
MetaDisplay *display;
|
||||
MetaCompositor *compositor;
|
||||
Atom type;
|
||||
int format;
|
||||
gulong nitems;
|
||||
gulong bytes_after;
|
||||
guchar *data;
|
||||
Pixmap root_pixmap_id;
|
||||
|
||||
background = meta_screen_background_get (screen);
|
||||
display = meta_screen_get_display (screen);
|
||||
compositor = meta_display_get_compositor (display);
|
||||
|
||||
root_pixmap_id = None;
|
||||
if (!XGetWindowProperty (meta_display_get_xdisplay (display),
|
||||
meta_screen_get_xroot (screen),
|
||||
compositor->atom_x_root_pixmap,
|
||||
0, LONG_MAX,
|
||||
False,
|
||||
AnyPropertyType,
|
||||
&type, &format, &nitems, &bytes_after, &data) &&
|
||||
type != None)
|
||||
{
|
||||
/* Got a property. */
|
||||
if (type == XA_PIXMAP && format == 32 && nitems == 1)
|
||||
{
|
||||
/* Was what we expected. */
|
||||
root_pixmap_id = *(Pixmap *)data;
|
||||
}
|
||||
|
||||
XFree(data);
|
||||
}
|
||||
|
||||
if (root_pixmap_id != None)
|
||||
{
|
||||
CoglHandle texture;
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
GError *error = NULL;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
texture = cogl_texture_pixmap_x11_new (ctx, root_pixmap_id, FALSE, &error);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
if (texture != COGL_INVALID_HANDLE)
|
||||
{
|
||||
set_texture (background, texture);
|
||||
cogl_handle_unref (texture);
|
||||
|
||||
background->have_pixmap = True;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Failed to create background texture from pixmap: %s",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
background->have_pixmap = False;
|
||||
set_texture_to_stage_color (background);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_background_actor_set_visible_region:
|
||||
* @self: a #MetaBackgroundActor
|
||||
* @visible_region: (allow-none): the area of the actor (in allocate-relative
|
||||
* coordinates) that is visible.
|
||||
*
|
||||
* Sets the area of the background that is unobscured by overlapping windows.
|
||||
* This is used to optimize and only paint the visible portions.
|
||||
*/
|
||||
void
|
||||
meta_background_actor_set_visible_region (MetaBackgroundActor *self,
|
||||
cairo_region_t *visible_region)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
if (priv->visible_region)
|
||||
{
|
||||
cairo_region_destroy (priv->visible_region);
|
||||
priv->visible_region = NULL;
|
||||
}
|
||||
|
||||
if (visible_region)
|
||||
{
|
||||
cairo_rectangle_int_t screen_rect = { 0 };
|
||||
meta_screen_get_size (priv->background->screen, &screen_rect.width, &screen_rect.height);
|
||||
|
||||
/* Doing the intersection here is probably unnecessary - MetaWindowGroup
|
||||
* should never compute a visible area that's larger than the root screen!
|
||||
* but it's not that expensive and adds some extra robustness.
|
||||
*/
|
||||
priv->visible_region = cairo_region_create_rectangle (&screen_rect);
|
||||
cairo_region_intersect (priv->visible_region, visible_region);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_background_actor_screen_size_changed:
|
||||
* @screen: a #MetaScreen
|
||||
*
|
||||
* Called by the compositor when the size of the #MetaScreen changes
|
||||
*/
|
||||
void
|
||||
meta_background_actor_screen_size_changed (MetaScreen *screen)
|
||||
{
|
||||
MetaScreenBackground *background = meta_screen_background_get (screen);
|
||||
GSList *l;
|
||||
|
||||
update_wrap_mode (background);
|
||||
|
||||
for (l = background->actors; l; l = l->next)
|
||||
clutter_actor_queue_relayout (l->data);
|
||||
}
|
@ -21,8 +21,8 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "mutter-plugin.h"
|
||||
#include "mutter-module.h"
|
||||
#include <meta/meta-plugin.h>
|
||||
#include "meta-module.h"
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
@ -32,23 +32,23 @@ enum
|
||||
PROP_PATH,
|
||||
};
|
||||
|
||||
struct _MutterModulePrivate
|
||||
struct _MetaModulePrivate
|
||||
{
|
||||
GModule *lib;
|
||||
gchar *path;
|
||||
GType plugin_type;
|
||||
};
|
||||
|
||||
#define MUTTER_MODULE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_MODULE, MutterModulePrivate))
|
||||
#define META_MODULE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_MODULE, MetaModulePrivate))
|
||||
|
||||
G_DEFINE_TYPE (MutterModule, mutter_module, G_TYPE_TYPE_MODULE);
|
||||
G_DEFINE_TYPE (MetaModule, meta_module, G_TYPE_TYPE_MODULE);
|
||||
|
||||
static gboolean
|
||||
mutter_module_load (GTypeModule *gmodule)
|
||||
meta_module_load (GTypeModule *gmodule)
|
||||
{
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (gmodule)->priv;
|
||||
MutterPluginVersion *info = NULL;
|
||||
MetaModulePrivate *priv = META_MODULE (gmodule)->priv;
|
||||
MetaPluginVersion *info = NULL;
|
||||
GType (*register_type) (GTypeModule *) = NULL;
|
||||
|
||||
if (priv->lib && priv->plugin_type)
|
||||
@ -64,9 +64,9 @@ mutter_module_load (GTypeModule *gmodule)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_module_symbol (priv->lib, "mutter_plugin_version",
|
||||
if (g_module_symbol (priv->lib, "meta_plugin_version",
|
||||
(gpointer *)(void *)&info) &&
|
||||
g_module_symbol (priv->lib, "mutter_plugin_register_type",
|
||||
g_module_symbol (priv->lib, "meta_plugin_register_type",
|
||||
(gpointer *)(void *)®ister_type) &&
|
||||
info && register_type)
|
||||
{
|
||||
@ -97,9 +97,9 @@ mutter_module_load (GTypeModule *gmodule)
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_module_unload (GTypeModule *gmodule)
|
||||
meta_module_unload (GTypeModule *gmodule)
|
||||
{
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (gmodule)->priv;
|
||||
MetaModulePrivate *priv = META_MODULE (gmodule)->priv;
|
||||
|
||||
g_module_close (priv->lib);
|
||||
|
||||
@ -108,29 +108,29 @@ mutter_module_unload (GTypeModule *gmodule)
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_module_dispose (GObject *object)
|
||||
meta_module_dispose (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (mutter_module_parent_class)->dispose (object);
|
||||
G_OBJECT_CLASS (meta_module_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_module_finalize (GObject *object)
|
||||
meta_module_finalize (GObject *object)
|
||||
{
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
|
||||
MetaModulePrivate *priv = META_MODULE (object)->priv;
|
||||
|
||||
g_free (priv->path);
|
||||
priv->path = NULL;
|
||||
|
||||
G_OBJECT_CLASS (mutter_module_parent_class)->finalize (object);
|
||||
G_OBJECT_CLASS (meta_module_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_module_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
meta_module_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
|
||||
MetaModulePrivate *priv = META_MODULE (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
@ -145,12 +145,12 @@ mutter_module_set_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_module_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
meta_module_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
|
||||
MetaModulePrivate *priv = META_MODULE (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
@ -164,18 +164,18 @@ mutter_module_get_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_module_class_init (MutterModuleClass *klass)
|
||||
meta_module_class_init (MetaModuleClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GTypeModuleClass *gmodule_class = G_TYPE_MODULE_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = mutter_module_finalize;
|
||||
gobject_class->dispose = mutter_module_dispose;
|
||||
gobject_class->set_property = mutter_module_set_property;
|
||||
gobject_class->get_property = mutter_module_get_property;
|
||||
gobject_class->finalize = meta_module_finalize;
|
||||
gobject_class->dispose = meta_module_dispose;
|
||||
gobject_class->set_property = meta_module_set_property;
|
||||
gobject_class->get_property = meta_module_get_property;
|
||||
|
||||
gmodule_class->load = mutter_module_load;
|
||||
gmodule_class->unload = mutter_module_unload;
|
||||
gmodule_class->load = meta_module_load;
|
||||
gmodule_class->unload = meta_module_unload;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_PATH,
|
||||
@ -186,22 +186,22 @@ mutter_module_class_init (MutterModuleClass *klass)
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (MutterModulePrivate));
|
||||
g_type_class_add_private (gobject_class, sizeof (MetaModulePrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_module_init (MutterModule *self)
|
||||
meta_module_init (MetaModule *self)
|
||||
{
|
||||
MutterModulePrivate *priv;
|
||||
MetaModulePrivate *priv;
|
||||
|
||||
self->priv = priv = MUTTER_MODULE_GET_PRIVATE (self);
|
||||
self->priv = priv = META_MODULE_GET_PRIVATE (self);
|
||||
|
||||
}
|
||||
|
||||
GType
|
||||
mutter_module_get_plugin_type (MutterModule *module)
|
||||
meta_module_get_plugin_type (MetaModule *module)
|
||||
{
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (module)->priv;
|
||||
MetaModulePrivate *priv = META_MODULE (module)->priv;
|
||||
|
||||
return priv->plugin_type;
|
||||
}
|
@ -21,37 +21,37 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MUTTER_MODULE_H_
|
||||
#define MUTTER_MODULE_H_
|
||||
#ifndef META_MODULE_H_
|
||||
#define META_MODULE_H_
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#define MUTTER_TYPE_MODULE (mutter_module_get_type ())
|
||||
#define MUTTER_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_MODULE, MutterModule))
|
||||
#define MUTTER_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_MODULE, MutterModuleClass))
|
||||
#define MUTTER_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_MODULE_TYPE))
|
||||
#define MUTTER_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_MODULE))
|
||||
#define MUTTER_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_MODULE, MutterModuleClass))
|
||||
#define META_TYPE_MODULE (meta_module_get_type ())
|
||||
#define META_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MODULE, MetaModule))
|
||||
#define META_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MODULE, MetaModuleClass))
|
||||
#define META_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_MODULE_TYPE))
|
||||
#define META_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MODULE))
|
||||
#define META_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MODULE, MetaModuleClass))
|
||||
|
||||
typedef struct _MutterModule MutterModule;
|
||||
typedef struct _MutterModuleClass MutterModuleClass;
|
||||
typedef struct _MutterModulePrivate MutterModulePrivate;
|
||||
typedef struct _MetaModule MetaModule;
|
||||
typedef struct _MetaModuleClass MetaModuleClass;
|
||||
typedef struct _MetaModulePrivate MetaModulePrivate;
|
||||
|
||||
struct _MutterModule
|
||||
struct _MetaModule
|
||||
{
|
||||
GTypeModule parent;
|
||||
|
||||
MutterModulePrivate *priv;
|
||||
MetaModulePrivate *priv;
|
||||
};
|
||||
|
||||
struct _MutterModuleClass
|
||||
struct _MetaModuleClass
|
||||
{
|
||||
GTypeModuleClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType mutter_module_get_type (void);
|
||||
GType meta_module_get_type (void);
|
||||
|
||||
GType mutter_module_get_plugin_type (MutterModule *module);
|
||||
GType meta_module_get_plugin_type (MetaModule *module);
|
||||
|
||||
#endif
|
312
src/compositor/meta-plugin-manager.c
Normal file
312
src/compositor/meta-plugin-manager.c
Normal file
@ -0,0 +1,312 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Intel Corp.
|
||||
*
|
||||
* Author: Tomas Frydrych <tf@linux.intel.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "compositor-private.h"
|
||||
#include "meta-plugin-manager.h"
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/errors.h>
|
||||
#include <meta/workspace.h>
|
||||
#include "meta-module.h"
|
||||
#include "window-private.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
static GType plugin_type = G_TYPE_NONE;
|
||||
|
||||
struct MetaPluginManager
|
||||
{
|
||||
MetaScreen *screen;
|
||||
MetaPlugin *plugin;
|
||||
};
|
||||
|
||||
void
|
||||
meta_plugin_manager_set_plugin_type (GType gtype)
|
||||
{
|
||||
if (plugin_type != G_TYPE_NONE)
|
||||
meta_fatal ("Mutter plugin already set: %s", g_type_name (plugin_type));
|
||||
|
||||
plugin_type = gtype;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads the given plugin.
|
||||
*/
|
||||
void
|
||||
meta_plugin_manager_load (const gchar *plugin_name)
|
||||
{
|
||||
const gchar *dpath = MUTTER_PLUGIN_DIR "/";
|
||||
gchar *path;
|
||||
MetaModule *module;
|
||||
|
||||
if (g_path_is_absolute (plugin_name))
|
||||
path = g_strdup (plugin_name);
|
||||
else
|
||||
path = g_strconcat (dpath, plugin_name, ".so", NULL);
|
||||
|
||||
module = g_object_new (META_TYPE_MODULE, "path", path, NULL);
|
||||
if (!module || !g_type_module_use (G_TYPE_MODULE (module)))
|
||||
{
|
||||
/* This is fatal under the assumption that a monitoring
|
||||
* process like gnome-session will take over and handle
|
||||
* our untimely exit.
|
||||
*/
|
||||
g_printerr ("Unable to load plugin module [%s]: %s",
|
||||
path, g_module_error());
|
||||
exit (1);
|
||||
}
|
||||
|
||||
meta_plugin_manager_set_plugin_type (meta_module_get_plugin_type (module));
|
||||
|
||||
g_type_module_unuse (G_TYPE_MODULE (module));
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
MetaPluginManager *
|
||||
meta_plugin_manager_new (MetaScreen *screen)
|
||||
{
|
||||
MetaPluginManager *plugin_mgr;
|
||||
MetaPluginClass *klass;
|
||||
MetaPlugin *plugin;
|
||||
|
||||
plugin_mgr = g_new0 (MetaPluginManager, 1);
|
||||
plugin_mgr->screen = screen;
|
||||
plugin_mgr->plugin = plugin = g_object_new (plugin_type, "screen", screen, NULL);
|
||||
|
||||
klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (klass->start)
|
||||
klass->start (plugin);
|
||||
|
||||
return plugin_mgr;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_manager_kill_window_effects (MetaPluginManager *plugin_mgr,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (klass->kill_window_effects)
|
||||
klass->kill_window_effects (plugin, actor);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_manager_kill_switch_workspace (MetaPluginManager *plugin_mgr)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (klass->kill_switch_workspace)
|
||||
klass->kill_switch_workspace (plugin);
|
||||
}
|
||||
|
||||
/*
|
||||
* Public method that the compositor hooks into for events that require
|
||||
* no additional parameters.
|
||||
*
|
||||
* Returns TRUE if the plugin handled the event type (i.e.,
|
||||
* if the return value is FALSE, there will be no subsequent call to the
|
||||
* manager completed() callback, and the compositor must ensure that any
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||
gboolean retval = FALSE;
|
||||
|
||||
if (display->display_opening)
|
||||
return FALSE;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case META_PLUGIN_MINIMIZE:
|
||||
if (klass->minimize)
|
||||
{
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||
actor);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->minimize (plugin, actor);
|
||||
}
|
||||
break;
|
||||
case META_PLUGIN_MAP:
|
||||
if (klass->map)
|
||||
{
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||
actor);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->map (plugin, actor);
|
||||
}
|
||||
break;
|
||||
case META_PLUGIN_DESTROY:
|
||||
if (klass->destroy)
|
||||
{
|
||||
retval = TRUE;
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->destroy (plugin, actor);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_warning ("Incorrect handler called for event %lu", event);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* The public method that the compositor hooks into for maximize and unmaximize
|
||||
* events.
|
||||
*
|
||||
* Returns TRUE if the plugin handled the event type (i.e.,
|
||||
* if the return value is FALSE, there will be no subsequent call to the
|
||||
* manager completed() callback, and the compositor must ensure that any
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event,
|
||||
gint target_x,
|
||||
gint target_y,
|
||||
gint target_width,
|
||||
gint target_height)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||
gboolean retval = FALSE;
|
||||
|
||||
if (display->display_opening)
|
||||
return FALSE;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case META_PLUGIN_MAXIMIZE:
|
||||
if (klass->maximize)
|
||||
{
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||
actor);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->maximize (plugin, actor,
|
||||
target_x, target_y,
|
||||
target_width, target_height);
|
||||
}
|
||||
break;
|
||||
case META_PLUGIN_UNMAXIMIZE:
|
||||
if (klass->unmaximize)
|
||||
{
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||
actor);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->unmaximize (plugin, actor,
|
||||
target_x, target_y,
|
||||
target_width, target_height);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_warning ("Incorrect handler called for event %lu", event);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* The public method that the compositor hooks into for desktop switching.
|
||||
*
|
||||
* Returns TRUE if the plugin handled the event type (i.e.,
|
||||
* if the return value is FALSE, there will be no subsequent call to the
|
||||
* manager completed() callback, and the compositor must ensure that any
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||
gboolean retval = FALSE;
|
||||
|
||||
if (display->display_opening)
|
||||
return FALSE;
|
||||
|
||||
if (klass->switch_workspace)
|
||||
{
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_switch_workspace (plugin_mgr);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->switch_workspace (plugin, from, to, direction);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* The public method that the compositor hooks into for desktop switching.
|
||||
*
|
||||
* Returns TRUE if the plugin handled the event type (i.e.,
|
||||
* if the return value is FALSE, there will be no subsequent call to the
|
||||
* manager completed() callback, and the compositor must ensure that any
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
|
||||
XEvent *xev)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!plugin_mgr)
|
||||
return FALSE;
|
||||
|
||||
/* We need to make sure that clutter gets certain events, like
|
||||
* ConfigureNotify on the stage window. If there is a plugin that
|
||||
* provides an xevent_filter function, then it's the responsibility
|
||||
* of that plugin to pass events to Clutter. Otherwise, we send the
|
||||
* event directly to Clutter ourselves.
|
||||
*/
|
||||
if (klass->xevent_filter && klass->xevent_filter (plugin, xev))
|
||||
return TRUE;
|
||||
else
|
||||
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
|
||||
}
|
73
src/compositor/meta-plugin-manager.h
Normal file
73
src/compositor/meta-plugin-manager.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Intel Corp.
|
||||
*
|
||||
* Author: Tomas Frydrych <tf@linux.intel.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef META_PLUGIN_MANAGER_H_
|
||||
#define META_PLUGIN_MANAGER_H_
|
||||
|
||||
#include <meta/types.h>
|
||||
#include <meta/screen.h>
|
||||
|
||||
#define META_PLUGIN_FROM_MANAGER_
|
||||
#include <meta/meta-plugin.h>
|
||||
#undef META_PLUGIN_FROM_MANAGER_
|
||||
|
||||
#define META_PLUGIN_MINIMIZE (1<<0)
|
||||
#define META_PLUGIN_MAXIMIZE (1<<1)
|
||||
#define META_PLUGIN_UNMAXIMIZE (1<<2)
|
||||
#define META_PLUGIN_MAP (1<<3)
|
||||
#define META_PLUGIN_DESTROY (1<<4)
|
||||
#define META_PLUGIN_SWITCH_WORKSPACE (1<<5)
|
||||
|
||||
#define META_PLUGIN_ALL_EFFECTS (~0)
|
||||
|
||||
/**
|
||||
* MetaPluginManager: (skip)
|
||||
*
|
||||
*/
|
||||
typedef struct MetaPluginManager MetaPluginManager;
|
||||
|
||||
MetaPluginManager * meta_plugin_manager_new (MetaScreen *screen);
|
||||
|
||||
void meta_plugin_manager_load (const gchar *plugin_name);
|
||||
|
||||
gboolean meta_plugin_manager_event_simple (MetaPluginManager *mgr,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event);
|
||||
|
||||
gboolean meta_plugin_manager_event_maximize (MetaPluginManager *mgr,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event,
|
||||
gint target_x,
|
||||
gint target_y,
|
||||
gint target_width,
|
||||
gint target_height);
|
||||
|
||||
gboolean meta_plugin_manager_switch_workspace (MetaPluginManager *mgr,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction);
|
||||
|
||||
gboolean meta_plugin_manager_xevent_filter (MetaPluginManager *mgr,
|
||||
XEvent *xev);
|
||||
|
||||
#endif
|
333
src/compositor/meta-plugin.c
Normal file
333
src/compositor/meta-plugin.c
Normal file
@ -0,0 +1,333 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Intel Corp.
|
||||
*
|
||||
* Author: Tomas Frydrych <tf@linux.intel.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <meta/meta-plugin.h>
|
||||
#include "meta-plugin-manager.h"
|
||||
#include <meta/screen.h>
|
||||
#include <meta/display.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/extensions/shape.h>
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
#include "compositor-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
|
||||
|
||||
#define META_PLUGIN_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_PLUGIN, MetaPluginPrivate))
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_SCREEN,
|
||||
PROP_DEBUG_MODE,
|
||||
};
|
||||
|
||||
struct _MetaPluginPrivate
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
gint running;
|
||||
gboolean debug : 1;
|
||||
};
|
||||
|
||||
static void
|
||||
meta_plugin_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SCREEN:
|
||||
priv->screen = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_DEBUG_MODE:
|
||||
priv->debug = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SCREEN:
|
||||
g_value_set_object (value, priv->screen);
|
||||
break;
|
||||
case PROP_DEBUG_MODE:
|
||||
g_value_set_boolean (value, priv->debug);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
meta_plugin_class_init (MetaPluginClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = meta_plugin_set_property;
|
||||
gobject_class->get_property = meta_plugin_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SCREEN,
|
||||
g_param_spec_object ("screen",
|
||||
"MetaScreen",
|
||||
"MetaScreen",
|
||||
META_TYPE_SCREEN,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DEBUG_MODE,
|
||||
g_param_spec_boolean ("debug-mode",
|
||||
"Debug Mode",
|
||||
"Debug Mode",
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (MetaPluginPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_init (MetaPlugin *self)
|
||||
{
|
||||
MetaPluginPrivate *priv;
|
||||
|
||||
self->priv = priv = META_PLUGIN_GET_PRIVATE (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_plugin_running (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return (priv->running > 0);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_plugin_debug_mode (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->debug;
|
||||
}
|
||||
|
||||
const MetaPluginInfo *
|
||||
meta_plugin_get_info (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (klass && klass->plugin_info)
|
||||
return klass->plugin_info (plugin);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* _meta_plugin_effect_started:
|
||||
* @plugin: the plugin
|
||||
*
|
||||
* Mark that an effect has started for the plugin. This is called
|
||||
* internally by MetaPluginManager.
|
||||
*/
|
||||
void
|
||||
_meta_plugin_effect_started (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
priv->running++;
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_switch_workspace_completed (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
MetaScreen *screen = priv->screen;
|
||||
|
||||
if (priv->running-- < 0)
|
||||
{
|
||||
g_warning ("Error in running effect accounting, adjusting.");
|
||||
priv->running = 0;
|
||||
}
|
||||
|
||||
meta_switch_workspace_completed (screen);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_window_effect_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
if (priv->running-- < 0)
|
||||
{
|
||||
g_warning ("Error in running effect accounting, adjusting.");
|
||||
priv->running = 0;
|
||||
}
|
||||
|
||||
if (!actor)
|
||||
{
|
||||
const MetaPluginInfo *info;
|
||||
const gchar *name = NULL;
|
||||
|
||||
if (plugin && (info = meta_plugin_get_info (plugin)))
|
||||
name = info->name;
|
||||
|
||||
g_warning ("Plugin [%s] passed NULL for actor!",
|
||||
name ? name : "unknown");
|
||||
}
|
||||
|
||||
meta_window_actor_effect_completed (actor, event);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_minimize_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MINIMIZE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_maximize_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MAXIMIZE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_unmaximize_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_UNMAXIMIZE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_map_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MAP);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_destroy_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_DESTROY);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_plugin_begin_modal:
|
||||
* @plugin: a #MetaPlugin
|
||||
* @grab_window: the X window to grab the keyboard and mouse on
|
||||
* @cursor: the cursor to use for the pointer grab, or None,
|
||||
* to use the normal cursor for the grab window and
|
||||
* its descendants.
|
||||
* @options: flags that modify the behavior of the modal grab
|
||||
* @timestamp: the timestamp used for establishing grabs
|
||||
*
|
||||
* This function is used to grab the keyboard and mouse for the exclusive
|
||||
* use of the plugin. Correct operation requires that both the keyboard
|
||||
* and mouse are grabbed, or thing will break. (In particular, other
|
||||
* passive X grabs in Meta can trigger but not be handled by the normal
|
||||
* keybinding handling code.) However, the plugin can establish the keyboard
|
||||
* and/or mouse grabs ahead of time and pass in the
|
||||
* %META_MODAL_POINTER_ALREADY_GRABBED and/or %META_MODAL_KEYBOARD_ALREADY_GRABBED
|
||||
* options. This facility is provided for two reasons: first to allow using
|
||||
* this function to establish modality after a passive grab, and second to
|
||||
* allow using obscure features of XGrabPointer() and XGrabKeyboard() without
|
||||
* having to add them to this API.
|
||||
*
|
||||
* Return value: whether we successfully grabbed the keyboard and
|
||||
* mouse and made the plugin modal.
|
||||
*/
|
||||
gboolean
|
||||
meta_plugin_begin_modal (MetaPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return meta_begin_modal_for_plugin (priv->screen, plugin,
|
||||
grab_window, cursor, options, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_plugin_end_modal:
|
||||
* @plugin: a #MetaPlugin
|
||||
* @timestamp: the time used for releasing grabs
|
||||
*
|
||||
* Ends the modal operation begun with meta_plugin_begin_modal(). This
|
||||
* ungrabs both the mouse and keyboard even when
|
||||
* %META_MODAL_POINTER_ALREADY_GRABBED or
|
||||
* %META_MODAL_KEYBOARD_ALREADY_GRABBED were provided as options
|
||||
* when beginnning the modal operation.
|
||||
*/
|
||||
void
|
||||
meta_plugin_end_modal (MetaPlugin *plugin,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
meta_end_modal_for_plugin (priv->screen, plugin, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_plugin_get_screen:
|
||||
* @plugin: a #MetaPlugin
|
||||
*
|
||||
* Gets the #MetaScreen corresponding to a plugin. Each plugin instance
|
||||
* is associated with exactly one screen; if Metacity is managing
|
||||
* multiple screens, multiple plugin instances will be created.
|
||||
*
|
||||
* Return value: (transfer none): the #MetaScreen for the plugin
|
||||
*/
|
||||
MetaScreen *
|
||||
meta_plugin_get_screen (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->screen;
|
||||
}
|
68
src/compositor/meta-shadow-factory-private.h
Normal file
68
src/compositor/meta-shadow-factory-private.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaShadowFactory:
|
||||
*
|
||||
* Create and cache shadow textures for arbitrary window shapes
|
||||
*
|
||||
* Copyright (C) 2010 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __META_SHADOW_FACTORY_PRIVATE_H__
|
||||
#define __META_SHADOW_FACTORY_PRIVATE_H__
|
||||
|
||||
#include <cairo.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include "meta-window-shape.h"
|
||||
#include <meta/meta-shadow-factory.h>
|
||||
|
||||
/**
|
||||
* MetaShadow:
|
||||
* #MetaShadow holds a shadow texture along with information about how to
|
||||
* apply that texture to draw a window texture. (E.g., it knows how big the
|
||||
* unscaled borders are on each side of the shadow texture.)
|
||||
*/
|
||||
typedef struct _MetaShadow MetaShadow;
|
||||
|
||||
MetaShadow *meta_shadow_ref (MetaShadow *shadow);
|
||||
void meta_shadow_unref (MetaShadow *shadow);
|
||||
CoglHandle meta_shadow_get_texture (MetaShadow *shadow);
|
||||
void meta_shadow_paint (MetaShadow *shadow,
|
||||
int window_x,
|
||||
int window_y,
|
||||
int window_width,
|
||||
int window_height,
|
||||
guint8 opacity,
|
||||
cairo_region_t *clip,
|
||||
gboolean clip_strictly);
|
||||
void meta_shadow_get_bounds (MetaShadow *shadow,
|
||||
int window_x,
|
||||
int window_y,
|
||||
int window_width,
|
||||
int window_height,
|
||||
cairo_rectangle_int_t *bounds);
|
||||
|
||||
MetaShadowFactory *meta_shadow_factory_new (void);
|
||||
|
||||
MetaShadow *meta_shadow_factory_get_shadow (MetaShadowFactory *factory,
|
||||
MetaWindowShape *shape,
|
||||
int width,
|
||||
int height,
|
||||
const char *class_name,
|
||||
gboolean focused);
|
||||
|
||||
#endif /* __META_SHADOW_FACTORY_PRIVATE_H__ */
|
1042
src/compositor/meta-shadow-factory.c
Normal file
1042
src/compositor/meta-shadow-factory.c
Normal file
File diff suppressed because it is too large
Load Diff
679
src/compositor/meta-shaped-texture.c
Normal file
679
src/compositor/meta-shaped-texture.c
Normal file
@ -0,0 +1,679 @@
|
||||
/*
|
||||
* shaped texture
|
||||
*
|
||||
* An actor to draw a masked texture.
|
||||
*
|
||||
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||
* and Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
* Copyright (C) 2012 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
#define COGL_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include "meta-texture-tower.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
#include <cogl/cogl-texture-pixmap-x11.h>
|
||||
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
|
||||
|
||||
static void meta_shaped_texture_dispose (GObject *object);
|
||||
|
||||
static void meta_shaped_texture_paint (ClutterActor *actor);
|
||||
static void meta_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color);
|
||||
|
||||
static void meta_shaped_texture_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p);
|
||||
|
||||
static void meta_shaped_texture_get_preferred_height (ClutterActor *self,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p);
|
||||
|
||||
static gboolean meta_shaped_texture_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume);
|
||||
|
||||
G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
|
||||
CLUTTER_TYPE_ACTOR);
|
||||
|
||||
#define META_SHAPED_TEXTURE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \
|
||||
MetaShapedTexturePrivate))
|
||||
|
||||
struct _MetaShapedTexturePrivate
|
||||
{
|
||||
MetaTextureTower *paint_tower;
|
||||
Pixmap pixmap;
|
||||
CoglHandle texture;
|
||||
CoglHandle mask_texture;
|
||||
CoglHandle material;
|
||||
CoglHandle material_unshaped;
|
||||
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
guint tex_width, tex_height;
|
||||
|
||||
guint create_mipmaps : 1;
|
||||
};
|
||||
|
||||
static void
|
||||
meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
||||
|
||||
gobject_class->dispose = meta_shaped_texture_dispose;
|
||||
|
||||
actor_class->get_preferred_width = meta_shaped_texture_get_preferred_width;
|
||||
actor_class->get_preferred_height = meta_shaped_texture_get_preferred_height;
|
||||
actor_class->paint = meta_shaped_texture_paint;
|
||||
actor_class->pick = meta_shaped_texture_pick;
|
||||
actor_class->get_paint_volume = meta_shaped_texture_get_paint_volume;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_init (MetaShapedTexture *self)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
priv = self->priv = META_SHAPED_TEXTURE_GET_PRIVATE (self);
|
||||
|
||||
priv->paint_tower = meta_texture_tower_new ();
|
||||
priv->texture = COGL_INVALID_HANDLE;
|
||||
priv->mask_texture = COGL_INVALID_HANDLE;
|
||||
priv->create_mipmaps = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_dispose (GObject *object)
|
||||
{
|
||||
MetaShapedTexture *self = (MetaShapedTexture *) object;
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
if (priv->paint_tower)
|
||||
meta_texture_tower_free (priv->paint_tower);
|
||||
priv->paint_tower = NULL;
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (priv->material);
|
||||
priv->material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
if (priv->material_unshaped != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (priv->material_unshaped);
|
||||
priv->material_unshaped = COGL_INVALID_HANDLE;
|
||||
}
|
||||
if (priv->texture != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (priv->texture);
|
||||
priv->texture = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
meta_shaped_texture_set_mask_texture (self, COGL_INVALID_HANDLE);
|
||||
meta_shaped_texture_set_clip_region (self, NULL);
|
||||
|
||||
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
CoglHandle paint_tex;
|
||||
guint tex_width, tex_height;
|
||||
ClutterActorBox alloc;
|
||||
|
||||
static CoglHandle material_template = COGL_INVALID_HANDLE;
|
||||
static CoglHandle material_unshaped_template = COGL_INVALID_HANDLE;
|
||||
|
||||
CoglHandle material;
|
||||
|
||||
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
||||
return;
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
|
||||
clutter_actor_realize (CLUTTER_ACTOR (stex));
|
||||
|
||||
/* The GL EXT_texture_from_pixmap extension does allow for it to be
|
||||
* used together with SGIS_generate_mipmap, however this is very
|
||||
* rarely supported. Also, even when it is supported there
|
||||
* are distinct performance implications from:
|
||||
*
|
||||
* - Updating mipmaps that we don't need
|
||||
* - Having to reallocate pixmaps on the server into larger buffers
|
||||
*
|
||||
* So, we just unconditionally use our mipmap emulation code. If we
|
||||
* wanted to use SGIS_generate_mipmap, we'd have to query COGL to
|
||||
* see if it was supported (no API currently), and then if and only
|
||||
* if that was the case, set the clutter texture quality to HIGH.
|
||||
* Setting the texture quality to high without SGIS_generate_mipmap
|
||||
* support for TFP textures will result in fallbacks to XGetImage.
|
||||
*/
|
||||
if (priv->create_mipmaps)
|
||||
paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
|
||||
else
|
||||
paint_tex = priv->texture;
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = priv->tex_width;
|
||||
tex_height = priv->tex_height;
|
||||
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
if (priv->mask_texture == COGL_INVALID_HANDLE)
|
||||
{
|
||||
/* Use a single-layer texture if we don't have a mask. */
|
||||
|
||||
if (priv->material_unshaped == COGL_INVALID_HANDLE)
|
||||
{
|
||||
if (G_UNLIKELY (material_unshaped_template == COGL_INVALID_HANDLE))
|
||||
material_unshaped_template = cogl_material_new ();
|
||||
|
||||
priv->material_unshaped = cogl_material_copy (material_unshaped_template);
|
||||
}
|
||||
material = priv->material_unshaped;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (priv->material == COGL_INVALID_HANDLE)
|
||||
{
|
||||
if (G_UNLIKELY (material_template == COGL_INVALID_HANDLE))
|
||||
{
|
||||
material_template = cogl_material_new ();
|
||||
cogl_material_set_layer_combine (material_template, 1,
|
||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
||||
NULL);
|
||||
}
|
||||
priv->material = cogl_material_copy (material_template);
|
||||
}
|
||||
material = priv->material;
|
||||
|
||||
cogl_material_set_layer (material, 1, priv->mask_texture);
|
||||
}
|
||||
|
||||
cogl_material_set_layer (material, 0, paint_tex);
|
||||
|
||||
{
|
||||
CoglColor color;
|
||||
guchar opacity = clutter_actor_get_paint_opacity (actor);
|
||||
cogl_color_set_from_4ub (&color, opacity, opacity, opacity, opacity);
|
||||
cogl_material_set_color (material, &color);
|
||||
}
|
||||
|
||||
cogl_set_source (material);
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &alloc);
|
||||
|
||||
if (priv->clip_region)
|
||||
{
|
||||
int n_rects;
|
||||
int i;
|
||||
cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
|
||||
|
||||
/* Limit to how many separate rectangles we'll draw; beyond this just
|
||||
* fall back and draw the whole thing */
|
||||
# define MAX_RECTS 16
|
||||
|
||||
n_rects = cairo_region_num_rectangles (priv->clip_region);
|
||||
if (n_rects <= MAX_RECTS)
|
||||
{
|
||||
float coords[8];
|
||||
float x1, y1, x2, y2;
|
||||
|
||||
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 (&tex_rect, &rect, &rect))
|
||||
continue;
|
||||
|
||||
x1 = rect.x;
|
||||
y1 = rect.y;
|
||||
x2 = rect.x + rect.width;
|
||||
y2 = rect.y + rect.height;
|
||||
|
||||
coords[0] = rect.x / (alloc.x2 - alloc.x1);
|
||||
coords[1] = rect.y / (alloc.y2 - alloc.y1);
|
||||
coords[2] = (rect.x + rect.width) / (alloc.x2 - alloc.x1);
|
||||
coords[3] = (rect.y + rect.height) / (alloc.y2 - alloc.y1);
|
||||
|
||||
coords[4] = coords[0];
|
||||
coords[5] = coords[1];
|
||||
coords[6] = coords[2];
|
||||
coords[7] = coords[3];
|
||||
|
||||
cogl_rectangle_with_multitexture_coords (x1, y1, x2, y2,
|
||||
&coords[0], 8);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cogl_rectangle (0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
/* If there is no region then use the regular pick */
|
||||
if (priv->mask_texture == COGL_INVALID_HANDLE)
|
||||
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)
|
||||
->pick (actor, color);
|
||||
else if (clutter_actor_should_pick_paint (actor))
|
||||
{
|
||||
CoglHandle paint_tex;
|
||||
ClutterActorBox alloc;
|
||||
guint tex_width, tex_height;
|
||||
|
||||
paint_tex = priv->texture;
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
cogl_set_source_color4ub (color->red, color->green, color->blue,
|
||||
color->alpha);
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &alloc);
|
||||
|
||||
/* Paint the mask rectangle in the given color */
|
||||
cogl_set_source_texture (priv->mask_texture);
|
||||
cogl_rectangle_with_texture_coords (0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1,
|
||||
0, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (self));
|
||||
|
||||
priv = META_SHAPED_TEXTURE (self)->priv;
|
||||
|
||||
if (min_width_p)
|
||||
*min_width_p = 0;
|
||||
|
||||
if (natural_width_p)
|
||||
*natural_width_p = priv->tex_width;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_get_preferred_height (ClutterActor *self,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (self));
|
||||
|
||||
priv = META_SHAPED_TEXTURE (self)->priv;
|
||||
|
||||
if (min_height_p)
|
||||
*min_height_p = 0;
|
||||
|
||||
if (natural_height_p)
|
||||
*natural_height_p = priv->tex_height;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_shaped_texture_get_paint_volume (ClutterActor *self,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
return clutter_paint_volume_set_from_allocation (volume, self);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
meta_shaped_texture_new (void)
|
||||
{
|
||||
ClutterActor *self = g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
|
||||
gboolean create_mipmaps)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
create_mipmaps = create_mipmaps != FALSE;
|
||||
|
||||
if (create_mipmaps != priv->create_mipmaps)
|
||||
{
|
||||
CoglHandle base_texture;
|
||||
priv->create_mipmaps = create_mipmaps;
|
||||
base_texture = create_mipmaps ?
|
||||
priv->texture : COGL_INVALID_HANDLE;
|
||||
meta_texture_tower_set_base_texture (priv->paint_tower, base_texture);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
|
||||
CoglHandle mask_texture)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->mask_texture != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (priv->mask_texture);
|
||||
priv->mask_texture = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (mask_texture != COGL_INVALID_HANDLE)
|
||||
{
|
||||
priv->mask_texture = mask_texture;
|
||||
cogl_handle_ref (priv->mask_texture);
|
||||
}
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
const cairo_rectangle_int_t clip = { x, y, width, height };
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->texture == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height);
|
||||
|
||||
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
|
||||
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
|
||||
}
|
||||
|
||||
static void
|
||||
set_cogl_texture (MetaShapedTexture *stex,
|
||||
CoglHandle cogl_tex)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
guint width, height;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->texture != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (priv->texture);
|
||||
|
||||
priv->texture = cogl_tex;
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
cogl_material_set_layer (priv->material, 0, cogl_tex);
|
||||
|
||||
if (priv->material_unshaped != COGL_INVALID_HANDLE)
|
||||
cogl_material_set_layer (priv->material_unshaped, 0, cogl_tex);
|
||||
|
||||
if (cogl_tex != COGL_INVALID_HANDLE)
|
||||
{
|
||||
width = cogl_texture_get_width (cogl_tex);
|
||||
height = cogl_texture_get_height (cogl_tex);
|
||||
|
||||
if (width != priv->tex_width ||
|
||||
height != priv->tex_height)
|
||||
{
|
||||
priv->tex_width = width;
|
||||
priv->tex_height = height;
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* size changed to 0 going to an invalid handle */
|
||||
priv->tex_width = 0;
|
||||
priv->tex_height = 0;
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_pixmap:
|
||||
* @stex: The #MetaShapedTexture
|
||||
* @pixmap: The pixmap you want the stex to assume
|
||||
*/
|
||||
void
|
||||
meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
|
||||
Pixmap pixmap)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->pixmap == pixmap)
|
||||
return;
|
||||
|
||||
priv->pixmap = pixmap;
|
||||
|
||||
if (pixmap != None)
|
||||
{
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
set_cogl_texture (stex, cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, NULL));
|
||||
}
|
||||
else
|
||||
set_cogl_texture (stex, COGL_INVALID_HANDLE);
|
||||
|
||||
if (priv->create_mipmaps)
|
||||
meta_texture_tower_set_base_texture (priv->paint_tower, priv->texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_get_texture:
|
||||
* @stex: The #MetaShapedTexture
|
||||
*
|
||||
* Returns: (transfer none): the unshaped texture
|
||||
*/
|
||||
CoglHandle
|
||||
meta_shaped_texture_get_texture (MetaShapedTexture *stex)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), COGL_INVALID_HANDLE);
|
||||
return stex->priv->texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_clip_region:
|
||||
* @stex: a #MetaShapedTexture
|
||||
* @clip_region: (transfer full): the region of the texture that
|
||||
* is visible and should be painted.
|
||||
*
|
||||
* Provides a hint to the texture about what areas of the texture
|
||||
* are not completely obscured and thus need to be painted. This
|
||||
* is an optimization and is not supposed to have any effect on
|
||||
* the output.
|
||||
*
|
||||
* Typically a parent container will set the clip region before
|
||||
* painting its children, and then unset it afterwards.
|
||||
*/
|
||||
void
|
||||
meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->clip_region)
|
||||
{
|
||||
cairo_region_destroy (priv->clip_region);
|
||||
priv->clip_region = NULL;
|
||||
}
|
||||
|
||||
if (clip_region)
|
||||
priv->clip_region = cairo_region_copy (clip_region);
|
||||
else
|
||||
priv->clip_region = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_get_image:
|
||||
* @stex: A #MetaShapedTexture
|
||||
* @clip: A clipping rectangle, to help prevent extra processing.
|
||||
* In the case that the clipping rectangle is partially or fully
|
||||
* outside the bounds of the texture, the rectangle will be clipped.
|
||||
*
|
||||
* Flattens the two layers of the shaped texture into one ARGB32
|
||||
* image by alpha blending the two images, and returns the flattened
|
||||
* image.
|
||||
*
|
||||
* Returns: (transfer full): a new cairo surface to be freed with
|
||||
* cairo_surface_destroy().
|
||||
*/
|
||||
cairo_surface_t *
|
||||
meta_shaped_texture_get_image (MetaShapedTexture *stex,
|
||||
cairo_rectangle_int_t *clip)
|
||||
{
|
||||
CoglHandle texture, mask_texture;
|
||||
cairo_rectangle_int_t texture_rect = { 0, 0, 0, 0 };
|
||||
cairo_surface_t *surface;
|
||||
|
||||
g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL);
|
||||
|
||||
texture = stex->priv->texture;
|
||||
|
||||
if (texture == NULL)
|
||||
return NULL;
|
||||
|
||||
texture_rect.width = cogl_texture_get_width (texture);
|
||||
texture_rect.height = cogl_texture_get_height (texture);
|
||||
|
||||
if (clip != NULL)
|
||||
{
|
||||
/* GdkRectangle is just a typedef of cairo_rectangle_int_t,
|
||||
* so we can use the gdk_rectangle_* APIs on these. */
|
||||
if (!gdk_rectangle_intersect (&texture_rect, clip, clip))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (clip != NULL)
|
||||
texture = cogl_texture_new_from_sub_texture (texture,
|
||||
clip->x,
|
||||
clip->y,
|
||||
clip->width,
|
||||
clip->height);
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
cogl_texture_get_width (texture),
|
||||
cogl_texture_get_height (texture));
|
||||
|
||||
cogl_texture_get_data (texture, CLUTTER_CAIRO_FORMAT_ARGB32,
|
||||
cairo_image_surface_get_stride (surface),
|
||||
cairo_image_surface_get_data (surface));
|
||||
|
||||
cairo_surface_mark_dirty (surface);
|
||||
|
||||
if (clip != NULL)
|
||||
cogl_object_unref (texture);
|
||||
|
||||
mask_texture = stex->priv->mask_texture;
|
||||
if (mask_texture != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cairo_t *cr;
|
||||
cairo_surface_t *mask_surface;
|
||||
|
||||
if (clip != NULL)
|
||||
mask_texture = cogl_texture_new_from_sub_texture (mask_texture,
|
||||
clip->x,
|
||||
clip->y,
|
||||
clip->width,
|
||||
clip->height);
|
||||
|
||||
mask_surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
|
||||
cogl_texture_get_width (mask_texture),
|
||||
cogl_texture_get_height (mask_texture));
|
||||
|
||||
cogl_texture_get_data (mask_texture, COGL_PIXEL_FORMAT_A_8,
|
||||
cairo_image_surface_get_stride (mask_surface),
|
||||
cairo_image_surface_get_data (mask_surface));
|
||||
|
||||
cairo_surface_mark_dirty (mask_surface);
|
||||
|
||||
cr = cairo_create (surface);
|
||||
cairo_set_source_surface (cr, mask_surface, 0, 0);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_DEST_IN);
|
||||
cairo_paint (cr);
|
||||
cairo_destroy (cr);
|
||||
|
||||
cairo_surface_destroy (mask_surface);
|
||||
|
||||
if (clip != NULL)
|
||||
cogl_object_unref (mask_texture);
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
101
src/compositor/meta-texture-rectangle.c
Normal file
101
src/compositor/meta-texture-rectangle.c
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* texture rectangle
|
||||
*
|
||||
* A small utility function to help create a rectangle texture
|
||||
*
|
||||
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2011, 2012 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
#define COGL_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include "meta-texture-rectangle.h"
|
||||
|
||||
CoglTexture *
|
||||
meta_texture_rectangle_new (unsigned int width,
|
||||
unsigned int height,
|
||||
CoglPixelFormat format,
|
||||
CoglPixelFormat internal_format,
|
||||
unsigned int rowstride,
|
||||
const guint8 *data,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackend *backend =
|
||||
clutter_get_default_backend ();
|
||||
CoglContext *context =
|
||||
clutter_backend_get_cogl_context (backend);
|
||||
CoglTextureRectangle *tex_rect;
|
||||
|
||||
tex_rect = cogl_texture_rectangle_new_with_size (context,
|
||||
width, height,
|
||||
internal_format,
|
||||
error);
|
||||
if (tex_rect == NULL)
|
||||
return NULL;
|
||||
|
||||
if (data)
|
||||
cogl_texture_set_region (COGL_TEXTURE (tex_rect),
|
||||
0, 0, /* src_x/y */
|
||||
0, 0, /* dst_x/y */
|
||||
width, height, /* dst_width/height */
|
||||
width, height, /* width/height */
|
||||
format,
|
||||
rowstride,
|
||||
data);
|
||||
|
||||
return COGL_TEXTURE (tex_rect);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_rectangle_check_cb (CoglTexture *sub_texture,
|
||||
const float *sub_texture_coords,
|
||||
const float *meta_coords,
|
||||
void *user_data)
|
||||
{
|
||||
gboolean *result = user_data;
|
||||
|
||||
if (cogl_is_texture_rectangle (sub_texture))
|
||||
*result = TRUE;
|
||||
}
|
||||
|
||||
/* Determines if the given texture is using a rectangle texture as its
|
||||
* primitive texture type. Eventually this function could be replaced
|
||||
* with cogl_texture_get_type if Cogl makes that public.
|
||||
*
|
||||
* http://git.gnome.org/browse/cogl/commit/?h=8012eee31
|
||||
*/
|
||||
gboolean
|
||||
meta_texture_rectangle_check (CoglTexture *texture)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
|
||||
cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (texture),
|
||||
0.0f, 0.0f, /* tx_1 / ty_1 */
|
||||
1.0f, 1.0f, /* tx_2 / ty_2 */
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
texture_rectangle_check_cb,
|
||||
&result);
|
||||
|
||||
return result;
|
||||
}
|
47
src/compositor/meta-texture-rectangle.h
Normal file
47
src/compositor/meta-texture-rectangle.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* texture rectangle
|
||||
*
|
||||
* A small utility function to help create a rectangle texture
|
||||
*
|
||||
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2011 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __META_TEXTURE_RECTANGLE_H__
|
||||
#define __META_TEXTURE_RECTANGLE_H__
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
CoglTexture *
|
||||
meta_texture_rectangle_new (unsigned int width,
|
||||
unsigned int height,
|
||||
CoglPixelFormat format,
|
||||
CoglPixelFormat internal_format,
|
||||
unsigned int rowstride,
|
||||
const guint8 *data,
|
||||
GError **error);
|
||||
|
||||
gboolean
|
||||
meta_texture_rectangle_check (CoglTexture *texture);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __META_TEXTURE_RECTANGLE_H__ */
|
624
src/compositor/meta-texture-tower.c
Normal file
624
src/compositor/meta-texture-tower.c
Normal file
@ -0,0 +1,624 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaTextureTower
|
||||
*
|
||||
* Mipmap emulation by creation of scaled down images
|
||||
*
|
||||
* Copyright (C) 2009 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "meta-texture-tower.h"
|
||||
#include "meta-texture-rectangle.h"
|
||||
|
||||
#ifndef M_LOG2E
|
||||
#define M_LOG2E 1.4426950408889634074
|
||||
#endif
|
||||
|
||||
#define MAX_TEXTURE_LEVELS 12
|
||||
|
||||
/* If the texture format in memory doesn't match this, then Mesa
|
||||
* will do the conversion, so things will still work, but it might
|
||||
* be slow depending on how efficient Mesa is. These should be the
|
||||
* native formats unless the display is 16bpp. If conversions
|
||||
* here are a bottleneck, investigate whether we are converting when
|
||||
* storing window data *into* the texture before adding extra code
|
||||
* to handle multiple texture formats.
|
||||
*/
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_BGRA_8888_PRE
|
||||
#else
|
||||
#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_ARGB_8888_PRE
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint16 x1;
|
||||
guint16 y1;
|
||||
guint16 x2;
|
||||
guint16 y2;
|
||||
} Box;
|
||||
|
||||
struct _MetaTextureTower
|
||||
{
|
||||
int n_levels;
|
||||
CoglHandle textures[MAX_TEXTURE_LEVELS];
|
||||
CoglHandle fbos[MAX_TEXTURE_LEVELS];
|
||||
Box invalid[MAX_TEXTURE_LEVELS];
|
||||
};
|
||||
|
||||
/**
|
||||
* meta_texture_tower_new:
|
||||
*
|
||||
* Creates a new texture tower. The base texture has to be set with
|
||||
* meta_texture_tower_set_base_texture() before use.
|
||||
*
|
||||
* Return value: the new texture tower. Free with meta_texture_tower_free()
|
||||
*/
|
||||
MetaTextureTower *
|
||||
meta_texture_tower_new (void)
|
||||
{
|
||||
MetaTextureTower *tower;
|
||||
|
||||
tower = g_slice_new0 (MetaTextureTower);
|
||||
|
||||
return tower;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_free:
|
||||
* @tower: a #MetaTextureTower
|
||||
*
|
||||
* Frees a texture tower created with meta_texture_tower_new().
|
||||
*/
|
||||
void
|
||||
meta_texture_tower_free (MetaTextureTower *tower)
|
||||
{
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
meta_texture_tower_set_base_texture (tower, COGL_INVALID_HANDLE);
|
||||
|
||||
g_slice_free (MetaTextureTower, tower);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_set_base_texture:
|
||||
* @tower: a #MetaTextureTower
|
||||
* @texture: the new texture used as a base for scaled down versions
|
||||
*
|
||||
* Sets the base texture that is the scaled texture that the
|
||||
* scaled textures of the tower are derived from. The texture itself
|
||||
* will be used as level 0 of the tower and will be referenced until
|
||||
* unset or until the tower is freed.
|
||||
*/
|
||||
void
|
||||
meta_texture_tower_set_base_texture (MetaTextureTower *tower,
|
||||
CoglHandle texture)
|
||||
{
|
||||
int i;
|
||||
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
if (texture == tower->textures[0])
|
||||
return;
|
||||
|
||||
if (tower->textures[0] != COGL_INVALID_HANDLE)
|
||||
{
|
||||
for (i = 1; i < tower->n_levels; i++)
|
||||
{
|
||||
if (tower->textures[i] != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (tower->textures[i]);
|
||||
tower->textures[i] = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (tower->fbos[i] != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (tower->fbos[i]);
|
||||
tower->fbos[i] = COGL_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
cogl_handle_unref (tower->textures[0]);
|
||||
}
|
||||
|
||||
tower->textures[0] = texture;
|
||||
|
||||
if (tower->textures[0] != COGL_INVALID_HANDLE)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
cogl_handle_ref (tower->textures[0]);
|
||||
|
||||
width = cogl_texture_get_width (tower->textures[0]);
|
||||
height = cogl_texture_get_height (tower->textures[0]);
|
||||
|
||||
tower->n_levels = 1 + MAX ((int)(M_LOG2E * log (width)), (int)(M_LOG2E * log (height)));
|
||||
tower->n_levels = MIN(tower->n_levels, MAX_TEXTURE_LEVELS);
|
||||
|
||||
meta_texture_tower_update_area (tower, 0, 0, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
tower->n_levels = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_update_area:
|
||||
* @tower: a #MetaTextureTower
|
||||
* @x: X coordinate of upper left of rectangle that changed
|
||||
* @y: Y coordinate of upper left of rectangle that changed
|
||||
* @width: width of rectangle that changed
|
||||
* @height: height rectangle that changed
|
||||
*
|
||||
* Mark a region of the base texture as having changed; the next
|
||||
* time a scaled down version of the base texture is retrieved,
|
||||
* the appropriate area of the scaled down texture will be updated.
|
||||
*/
|
||||
void
|
||||
meta_texture_tower_update_area (MetaTextureTower *tower,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
int texture_width, texture_height;
|
||||
Box invalid;
|
||||
int i;
|
||||
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
if (tower->textures[0] == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
texture_width = cogl_texture_get_width (tower->textures[0]);
|
||||
texture_height = cogl_texture_get_height (tower->textures[0]);
|
||||
|
||||
invalid.x1 = x;
|
||||
invalid.y1 = y;
|
||||
invalid.x2 = x + width;
|
||||
invalid.y2 = y + height;
|
||||
|
||||
for (i = 1; i < tower->n_levels; i++)
|
||||
{
|
||||
texture_width = MAX (1, texture_width / 2);
|
||||
texture_height = MAX (1, texture_height / 2);
|
||||
|
||||
invalid.x1 = invalid.x1 / 2;
|
||||
invalid.y1 = invalid.y1 / 2;
|
||||
invalid.x2 = MIN (texture_width, (invalid.x2 + 1) / 2);
|
||||
invalid.y2 = MIN (texture_height, (invalid.y2 + 1) / 2);
|
||||
|
||||
if (tower->invalid[i].x1 == tower->invalid[i].x2 ||
|
||||
tower->invalid[i].y1 == tower->invalid[i].y2)
|
||||
{
|
||||
tower->invalid[i] = invalid;
|
||||
}
|
||||
else
|
||||
{
|
||||
tower->invalid[i].x1 = MIN (tower->invalid[i].x1, invalid.x1);
|
||||
tower->invalid[i].y1 = MIN (tower->invalid[i].y1, invalid.y1);
|
||||
tower->invalid[i].x2 = MAX (tower->invalid[i].x2, invalid.x2);
|
||||
tower->invalid[i].y2 = MAX (tower->invalid[i].y2, invalid.y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* It generally looks worse if we scale up a window texture by even a
|
||||
* small amount than if we scale it down using bilinear filtering, so
|
||||
* we always pick the *larger* adjacent level. */
|
||||
#define LOD_BIAS (-0.49)
|
||||
|
||||
/* This determines the appropriate level of detail to use when drawing the
|
||||
* texture, in a way that corresponds to what the GL specification does
|
||||
* when mip-mapping. This is probably fancier and slower than what we need,
|
||||
* but we do the computation only once each time we paint a window, and
|
||||
* its easier to just use the equations from the specification than to
|
||||
* come up with something simpler.
|
||||
*
|
||||
* If window is being painted at an angle from the viewer, then we have to
|
||||
* pick a point in the texture; we use the middle of the texture (which is
|
||||
* why the width/height are passed in.) This is not the normal case for
|
||||
* Meta.
|
||||
*/
|
||||
static int
|
||||
get_paint_level (int width, int height)
|
||||
{
|
||||
CoglMatrix projection, modelview, pm;
|
||||
float v[4];
|
||||
double viewport_width, viewport_height;
|
||||
double u0, v0;
|
||||
double xc, yc, wc;
|
||||
double dxdu_, dxdv_, dydu_, dydv_;
|
||||
double det_, det_sq;
|
||||
double rho_sq;
|
||||
double lambda;
|
||||
|
||||
/* See
|
||||
* http://www.opengl.org/registry/doc/glspec32.core.20090803.pdf
|
||||
* Section 3.8.9, p. 1.6.2. Here we have
|
||||
*
|
||||
* u(x,y) = x_o;
|
||||
* v(x,y) = y_o;
|
||||
*
|
||||
* Since we are mapping 1:1 from object coordinates into pixel
|
||||
* texture coordinates, the clip coordinates are:
|
||||
*
|
||||
* (x_c) (x_o) (u)
|
||||
* (y_c) = (M_projection)(M_modelview) (y_o) = (PM) (v)
|
||||
* (z_c) (z_o) (0)
|
||||
* (w_c) (w_o) (1)
|
||||
*/
|
||||
|
||||
cogl_get_projection_matrix (&projection);
|
||||
cogl_get_modelview_matrix (&modelview);
|
||||
|
||||
cogl_matrix_multiply (&pm, &projection, &modelview);
|
||||
|
||||
cogl_get_viewport (v);
|
||||
viewport_width = v[2];
|
||||
viewport_height = v[3];
|
||||
|
||||
u0 = width / 2.;
|
||||
v0 = height / 2.;
|
||||
|
||||
xc = pm.xx * u0 + pm.xy * v0 + pm.xw;
|
||||
yc = pm.yx * u0 + pm.yy * v0 + pm.yw;
|
||||
wc = pm.wx * u0 + pm.wy * v0 + pm.ww;
|
||||
|
||||
/* We'll simplify the equations below for a bit of micro-optimization.
|
||||
* The commented out code is the unsimplified version.
|
||||
|
||||
// Partial derivates of window coordinates:
|
||||
//
|
||||
// x_w = 0.5 * viewport_width * x_c / w_c + viewport_center_x
|
||||
// y_w = 0.5 * viewport_height * y_c / w_c + viewport_center_y
|
||||
//
|
||||
// with respect to u, v, using
|
||||
// d(a/b)/dx = da/dx * (1/b) - a * db/dx / (b^2)
|
||||
|
||||
dxdu = 0.5 * viewport_width * (pm.xx - pm.wx * (xc/wc)) / wc;
|
||||
dxdv = 0.5 * viewport_width * (pm.xy - pm.wy * (xc/wc)) / wc;
|
||||
dydu = 0.5 * viewport_height * (pm.yx - pm.wx * (yc/wc)) / wc;
|
||||
dydv = 0.5 * viewport_height * (pm.yy - pm.wy * (yc/wc)) / wc;
|
||||
|
||||
// Compute the inverse partials as the matrix inverse
|
||||
det = dxdu * dydv - dxdv * dydu;
|
||||
|
||||
dudx = dydv / det;
|
||||
dudy = - dxdv / det;
|
||||
dvdx = - dydu / det;
|
||||
dvdy = dvdu / det;
|
||||
|
||||
// Scale factor; maximum of the distance in texels for a change of 1 pixel
|
||||
// in the X direction or 1 pixel in the Y direction
|
||||
rho = MAX (sqrt (dudx * dudx + dvdx * dvdx), sqrt(dudy * dudy + dvdy * dvdy));
|
||||
|
||||
// Level of detail
|
||||
lambda = log2 (rho) + LOD_BIAS;
|
||||
*/
|
||||
|
||||
/* dxdu * wc, etc */
|
||||
dxdu_ = 0.5 * viewport_width * (pm.xx - pm.wx * (xc/wc));
|
||||
dxdv_ = 0.5 * viewport_width * (pm.xy - pm.wy * (xc/wc));
|
||||
dydu_ = 0.5 * viewport_height * (pm.yx - pm.wx * (yc/wc));
|
||||
dydv_ = 0.5 * viewport_height * (pm.yy - pm.wy * (yc/wc));
|
||||
|
||||
/* det * wc^2 */
|
||||
det_ = dxdu_ * dydv_ - dxdv_ * dydu_;
|
||||
det_sq = det_ * det_;
|
||||
if (det_sq == 0.0)
|
||||
return -1;
|
||||
|
||||
/* (rho * det * wc)^2 */
|
||||
rho_sq = MAX (dydv_ * dydv_ + dydu_ * dydu_, dxdv_ * dxdv_ + dxdu_ * dxdu_);
|
||||
lambda = 0.5 * M_LOG2E * log (rho_sq * wc * wc / det_sq) + LOD_BIAS;
|
||||
|
||||
#if 0
|
||||
g_print ("%g %g %g\n", 0.5 * viewport_width * pm.xx / pm.ww, 0.5 * viewport_height * pm.yy / pm.ww, lambda);
|
||||
#endif
|
||||
|
||||
if (lambda <= 0.)
|
||||
return 0;
|
||||
else
|
||||
return (int)(0.5 + lambda);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_power_of_two (int x)
|
||||
{
|
||||
return (x & (x - 1)) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_create_texture (MetaTextureTower *tower,
|
||||
int level,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if ((!is_power_of_two (width) || !is_power_of_two (height)) &&
|
||||
meta_texture_rectangle_check (tower->textures[level - 1]))
|
||||
{
|
||||
tower->textures[level] =
|
||||
meta_texture_rectangle_new (width, height,
|
||||
/* data format */
|
||||
TEXTURE_FORMAT,
|
||||
/* internal cogl format */
|
||||
TEXTURE_FORMAT,
|
||||
/* rowstride */
|
||||
width * 4,
|
||||
/* data */
|
||||
NULL,
|
||||
/* error */
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
tower->textures[level] = cogl_texture_new_with_size (width, height,
|
||||
COGL_TEXTURE_NO_AUTO_MIPMAP,
|
||||
TEXTURE_FORMAT);
|
||||
}
|
||||
|
||||
tower->invalid[level].x1 = 0;
|
||||
tower->invalid[level].y1 = 0;
|
||||
tower->invalid[level].x2 = width;
|
||||
tower->invalid[level].y2 = height;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
texture_tower_revalidate_fbo (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
CoglHandle source_texture = tower->textures[level - 1];
|
||||
int source_texture_width = cogl_texture_get_width (source_texture);
|
||||
int source_texture_height = cogl_texture_get_height (source_texture);
|
||||
CoglHandle dest_texture = tower->textures[level];
|
||||
int dest_texture_width = cogl_texture_get_width (dest_texture);
|
||||
int dest_texture_height = cogl_texture_get_height (dest_texture);
|
||||
Box *invalid = &tower->invalid[level];
|
||||
CoglMatrix modelview;
|
||||
|
||||
if (tower->fbos[level] == COGL_INVALID_HANDLE)
|
||||
tower->fbos[level] = cogl_offscreen_new_to_texture (dest_texture);
|
||||
|
||||
if (tower->fbos[level] == COGL_INVALID_HANDLE)
|
||||
return FALSE;
|
||||
|
||||
cogl_push_framebuffer (tower->fbos[level]);
|
||||
|
||||
cogl_ortho (0, dest_texture_width, dest_texture_height, 0, -1., 1.);
|
||||
|
||||
cogl_matrix_init_identity (&modelview);
|
||||
cogl_set_modelview_matrix (&modelview);
|
||||
|
||||
cogl_set_source_texture (tower->textures[level - 1]);
|
||||
cogl_rectangle_with_texture_coords (invalid->x1, invalid->y1,
|
||||
invalid->x2, invalid->y2,
|
||||
(2. * invalid->x1) / source_texture_width,
|
||||
(2. * invalid->y1) / source_texture_height,
|
||||
(2. * invalid->x2) / source_texture_width,
|
||||
(2. * invalid->y2) / source_texture_height);
|
||||
|
||||
cogl_pop_framebuffer ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fill_copy (guchar *buf,
|
||||
const guchar *source,
|
||||
int width)
|
||||
{
|
||||
memcpy (buf, source, width * 4);
|
||||
}
|
||||
|
||||
static void
|
||||
fill_scale_down (guchar *buf,
|
||||
const guchar *source,
|
||||
int width)
|
||||
{
|
||||
while (width > 1)
|
||||
{
|
||||
buf[0] = (source[0] + source[4]) / 2;
|
||||
buf[1] = (source[1] + source[5]) / 2;
|
||||
buf[2] = (source[2] + source[6]) / 2;
|
||||
buf[3] = (source[3] + source[7]) / 2;
|
||||
|
||||
buf += 4;
|
||||
source += 8;
|
||||
width -= 2;
|
||||
}
|
||||
|
||||
if (width > 0)
|
||||
{
|
||||
buf[0] = source[0] / 2;
|
||||
buf[1] = source[1] / 2;
|
||||
buf[2] = source[2] / 2;
|
||||
buf[3] = source[3] / 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_revalidate_client (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
CoglHandle source_texture = tower->textures[level - 1];
|
||||
int source_texture_width = cogl_texture_get_width (source_texture);
|
||||
int source_texture_height = cogl_texture_get_height (source_texture);
|
||||
guint source_rowstride;
|
||||
guchar *source_data;
|
||||
CoglHandle dest_texture = tower->textures[level];
|
||||
int dest_texture_width = cogl_texture_get_width (dest_texture);
|
||||
int dest_texture_height = cogl_texture_get_height (dest_texture);
|
||||
int dest_x = tower->invalid[level].x1;
|
||||
int dest_y = tower->invalid[level].y1;
|
||||
int dest_width = tower->invalid[level].x2 - tower->invalid[level].x1;
|
||||
int dest_height = tower->invalid[level].y2 - tower->invalid[level].y1;
|
||||
guchar *dest_data;
|
||||
guchar *source_tmp1 = NULL, *source_tmp2 = NULL;
|
||||
int i, j;
|
||||
|
||||
source_rowstride = source_texture_width * 4;
|
||||
|
||||
source_data = g_malloc (source_texture_height * source_rowstride);
|
||||
cogl_texture_get_data (source_texture, TEXTURE_FORMAT, source_rowstride,
|
||||
source_data);
|
||||
|
||||
dest_data = g_malloc (dest_height * dest_width * 4);
|
||||
|
||||
if (dest_texture_height < source_texture_height)
|
||||
{
|
||||
source_tmp1 = g_malloc (dest_width * 4);
|
||||
source_tmp2 = g_malloc (dest_width * 4);
|
||||
}
|
||||
|
||||
for (i = 0; i < dest_height; i++)
|
||||
{
|
||||
guchar *dest_row = dest_data + i * dest_width * 4;
|
||||
if (dest_texture_height < source_texture_height)
|
||||
{
|
||||
guchar *source1, *source2;
|
||||
guchar *dest;
|
||||
|
||||
if (dest_texture_width < source_texture_width)
|
||||
{
|
||||
fill_scale_down (source_tmp1,
|
||||
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
fill_scale_down (source_tmp2,
|
||||
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
fill_copy (source_tmp1,
|
||||
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 4,
|
||||
dest_width);
|
||||
fill_copy (source_tmp2,
|
||||
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 4,
|
||||
dest_width);
|
||||
}
|
||||
|
||||
source1 = source_tmp1;
|
||||
source2 = source_tmp2;
|
||||
|
||||
dest = dest_row;
|
||||
for (j = 0; j < dest_width * 4; j++)
|
||||
*(dest++) = (*(source1++) + *(source2++)) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dest_texture_width < source_texture_width)
|
||||
fill_scale_down (dest_row,
|
||||
source_data + (i + dest_y) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
else
|
||||
fill_copy (dest_row,
|
||||
source_data + (i + dest_y) * source_rowstride,
|
||||
dest_width);
|
||||
}
|
||||
}
|
||||
|
||||
cogl_texture_set_region (dest_texture,
|
||||
0, 0,
|
||||
dest_x, dest_y,
|
||||
dest_width, dest_height,
|
||||
dest_width, dest_height,
|
||||
TEXTURE_FORMAT,
|
||||
4 * dest_width,
|
||||
dest_data);
|
||||
|
||||
if (dest_texture_height < source_texture_height)
|
||||
{
|
||||
g_free (source_tmp1);
|
||||
g_free (source_tmp2);
|
||||
}
|
||||
|
||||
g_free (source_data);
|
||||
g_free (dest_data);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_revalidate (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
if (!texture_tower_revalidate_fbo (tower, level))
|
||||
texture_tower_revalidate_client (tower, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_get_paint_texture:
|
||||
* @tower: a #MetaTextureTower
|
||||
*
|
||||
* Gets the texture from the tower that best matches the current
|
||||
* rendering scale. (On the assumption here the texture is going to
|
||||
* be rendered with vertex coordinates that correspond to its
|
||||
* size in pixels, so a 200x200 texture will be rendered on the
|
||||
* rectangle (0, 0, 200, 200).
|
||||
*
|
||||
* Return value: the COGL texture handle to use for painting, or
|
||||
* %COGL_INVALID_HANDLE if no base texture has yet been set.
|
||||
*/
|
||||
CoglHandle
|
||||
meta_texture_tower_get_paint_texture (MetaTextureTower *tower)
|
||||
{
|
||||
int texture_width, texture_height;
|
||||
int level;
|
||||
|
||||
g_return_val_if_fail (tower != NULL, COGL_INVALID_HANDLE);
|
||||
|
||||
if (tower->textures[0] == COGL_INVALID_HANDLE)
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
texture_width = cogl_texture_get_width (tower->textures[0]);
|
||||
texture_height = cogl_texture_get_height (tower->textures[0]);
|
||||
|
||||
level = get_paint_level(texture_width, texture_height);
|
||||
if (level < 0) /* singular paint matrix, scaled to nothing */
|
||||
return COGL_INVALID_HANDLE;
|
||||
level = MIN (level, tower->n_levels - 1);
|
||||
|
||||
if (tower->textures[level] == COGL_INVALID_HANDLE ||
|
||||
(tower->invalid[level].x2 != tower->invalid[level].x1 &&
|
||||
tower->invalid[level].y2 != tower->invalid[level].y1))
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= level; i++)
|
||||
{
|
||||
/* Use "floor" convention here to be consistent with the NPOT texture extension */
|
||||
texture_width = MAX (1, texture_width / 2);
|
||||
texture_height = MAX (1, texture_height / 2);
|
||||
|
||||
if (tower->textures[i] == COGL_INVALID_HANDLE)
|
||||
texture_tower_create_texture (tower, i, texture_width, texture_height);
|
||||
}
|
||||
|
||||
for (i = 1; i <= level; i++)
|
||||
{
|
||||
if (tower->invalid[level].x2 != tower->invalid[level].x1 &&
|
||||
tower->invalid[level].y2 != tower->invalid[level].y1)
|
||||
texture_tower_revalidate (tower, i);
|
||||
}
|
||||
}
|
||||
|
||||
return tower->textures[level];
|
||||
}
|
69
src/compositor/meta-texture-tower.h
Normal file
69
src/compositor/meta-texture-tower.h
Normal file
@ -0,0 +1,69 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaTextureTower
|
||||
*
|
||||
* Mipmap emulation by creation of scaled down images
|
||||
*
|
||||
* Copyright (C) 2009 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __META_TEXTURE_TOWER_H__
|
||||
#define __META_TEXTURE_TOWER_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* SECTION:MetaTextureTower
|
||||
* @short_description: mipmap emulation by creation of scaled down images
|
||||
*
|
||||
* A #MetaTextureTower is used to get good looking scaled down images when
|
||||
* we can't use the GL drivers mipmap support. There are two separate reasons
|
||||
*
|
||||
* - Some cards (including radeon cards <= r5xx) only support
|
||||
* TEXTURE_RECTANGLE_ARB and not NPOT textures. Rectangular textures
|
||||
* are defined not to support mipmapping.
|
||||
* - Even when NPOT textures are available, the combination of NPOT
|
||||
* textures, texture_from_pixmap, and mipmapping doesn't typically
|
||||
* work, since the X server doesn't allocate pixmaps in the right
|
||||
* layout for mipmapping.
|
||||
*
|
||||
* So, what we do is create the "mipmap" levels ourselves by successive
|
||||
* power-of-two scaledowns, and when rendering pick the single texture
|
||||
* that best matches the scale we are rendering at. (Since we aren't
|
||||
* typically using perspective transforms, we'll frequently have a single
|
||||
* scale for the entire texture.)
|
||||
*/
|
||||
|
||||
typedef struct _MetaTextureTower MetaTextureTower;
|
||||
|
||||
MetaTextureTower *meta_texture_tower_new (void);
|
||||
void meta_texture_tower_free (MetaTextureTower *tower);
|
||||
void meta_texture_tower_set_base_texture (MetaTextureTower *tower,
|
||||
CoglHandle texture);
|
||||
void meta_texture_tower_update_area (MetaTextureTower *tower,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
CoglHandle meta_texture_tower_get_paint_texture (MetaTextureTower *tower);
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#endif /* __META_TEXTURE_TOWER_H__ */
|
60
src/compositor/meta-window-actor-private.h
Normal file
60
src/compositor/meta-window-actor-private.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#ifndef META_WINDOW_ACTOR_PRIVATE_H
|
||||
#define META_WINDOW_ACTOR_PRIVATE_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#include <meta/compositor-mutter.h>
|
||||
|
||||
MetaWindowActor *meta_window_actor_new (MetaWindow *window);
|
||||
|
||||
void meta_window_actor_destroy (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_show (MetaWindowActor *self,
|
||||
MetaCompEffect effect);
|
||||
void meta_window_actor_hide (MetaWindowActor *self,
|
||||
MetaCompEffect effect);
|
||||
|
||||
void meta_window_actor_maximize (MetaWindowActor *self,
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
void meta_window_actor_unmaximize (MetaWindowActor *self,
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
|
||||
void meta_window_actor_process_damage (MetaWindowActor *self,
|
||||
XDamageNotifyEvent *event);
|
||||
|
||||
void meta_window_actor_pre_paint (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_invalidate_shadow (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_set_redirected (MetaWindowActor *self, gboolean state);
|
||||
|
||||
gboolean meta_window_actor_should_unredirect (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_get_shape_bounds (MetaWindowActor *self,
|
||||
cairo_rectangle_int_t *bounds);
|
||||
|
||||
gboolean meta_window_actor_effect_in_progress (MetaWindowActor *self);
|
||||
void meta_window_actor_sync_actor_position (MetaWindowActor *self);
|
||||
void meta_window_actor_sync_visibility (MetaWindowActor *self);
|
||||
void meta_window_actor_update_shape (MetaWindowActor *self);
|
||||
void meta_window_actor_update_opacity (MetaWindowActor *self);
|
||||
void meta_window_actor_mapped (MetaWindowActor *self);
|
||||
void meta_window_actor_unmapped (MetaWindowActor *self);
|
||||
|
||||
cairo_region_t *meta_window_actor_get_obscured_region (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_set_visible_region (MetaWindowActor *self,
|
||||
cairo_region_t *visible_region);
|
||||
void meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
|
||||
cairo_region_t *beneath_region);
|
||||
void meta_window_actor_reset_visible_regions (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_effect_completed (MetaWindowActor *actor,
|
||||
gulong event);
|
||||
|
||||
#endif /* META_WINDOW_ACTOR_PRIVATE_H */
|
2394
src/compositor/meta-window-actor.c
Normal file
2394
src/compositor/meta-window-actor.c
Normal file
File diff suppressed because it is too large
Load Diff
247
src/compositor/meta-window-group.c
Normal file
247
src/compositor/meta-window-group.c
Normal file
@ -0,0 +1,247 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#define _ISOC99_SOURCE /* for roundf */
|
||||
#include <math.h>
|
||||
|
||||
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
|
||||
|
||||
#include "compositor-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-window-group.h"
|
||||
#include "meta-background-actor-private.h"
|
||||
|
||||
struct _MetaWindowGroupClass
|
||||
{
|
||||
ClutterGroupClass parent_class;
|
||||
};
|
||||
|
||||
struct _MetaWindowGroup
|
||||
{
|
||||
ClutterGroup parent;
|
||||
|
||||
MetaScreen *screen;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_GROUP);
|
||||
|
||||
/* We want to find out if the window is "close enough" to
|
||||
* 1:1 transform. We do that by converting the transformed coordinates
|
||||
* to 24.8 fixed-point before checking if they look right.
|
||||
*/
|
||||
static inline int
|
||||
round_to_fixed (float x)
|
||||
{
|
||||
return roundf (x * 256);
|
||||
}
|
||||
|
||||
/* We can only (easily) apply our logic for figuring out what a window
|
||||
* obscures if is not transformed. This function does that check and
|
||||
* as a side effect gets the position of the upper-left corner of the
|
||||
* actors.
|
||||
*
|
||||
* (We actually could handle scaled and non-integrally positioned actors
|
||||
* too as long as they weren't shaped - no filtering is done at the
|
||||
* edges so a rectangle stays a rectangle. But the gain from that is
|
||||
* small, especally since most of our windows are shaped. The simple
|
||||
* case we handle here is the case that matters when the user is just
|
||||
* using the desktop normally.)
|
||||
*
|
||||
* If we assume that the window group is untransformed (it better not
|
||||
* be!) then we could also make this determination by checking directly
|
||||
* if the actor itself is rotated, scaled, or at a non-integral position.
|
||||
* However, the criterion for "close enough" in that case get trickier,
|
||||
* since, for example, the allowed rotation depends on the size of
|
||||
* actor. The approach we take here is to just require everything
|
||||
* to be within 1/256th of a pixel.
|
||||
*/
|
||||
static gboolean
|
||||
actor_is_untransformed (ClutterActor *actor,
|
||||
int *x_origin,
|
||||
int *y_origin)
|
||||
{
|
||||
gfloat widthf, heightf;
|
||||
int width, height;
|
||||
ClutterVertex verts[4];
|
||||
int v0x, v0y, v1x, v1y, v2x, v2y, v3x, v3y;
|
||||
int x, y;
|
||||
|
||||
clutter_actor_get_size (actor, &widthf, &heightf);
|
||||
width = round_to_fixed (widthf); height = round_to_fixed (heightf);
|
||||
|
||||
clutter_actor_get_abs_allocation_vertices (actor, verts);
|
||||
v0x = round_to_fixed (verts[0].x); v0y = round_to_fixed (verts[0].y);
|
||||
v1x = round_to_fixed (verts[1].x); v1y = round_to_fixed (verts[1].y);
|
||||
v2x = round_to_fixed (verts[2].x); v2y = round_to_fixed (verts[2].y);
|
||||
v3x = round_to_fixed (verts[3].x); v3y = round_to_fixed (verts[3].y);
|
||||
|
||||
/* Using shifting for converting fixed => int, gets things right for
|
||||
* negative values. / 256. wouldn't do the same
|
||||
*/
|
||||
x = v0x >> 8;
|
||||
y = v0y >> 8;
|
||||
|
||||
/* At integral coordinates? */
|
||||
if (x * 256 != v0x || y * 256 != v0y)
|
||||
return FALSE;
|
||||
|
||||
/* Not scaled? */
|
||||
if (v1x - v0x != width || v2y - v0y != height)
|
||||
return FALSE;
|
||||
|
||||
/* Not rotated/skewed? */
|
||||
if (v0x != v2x || v0y != v1y ||
|
||||
v3x != v1x || v3y != v2y)
|
||||
return FALSE;
|
||||
|
||||
*x_origin = x;
|
||||
*y_origin = y;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_group_paint (ClutterActor *actor)
|
||||
{
|
||||
cairo_region_t *visible_region;
|
||||
cairo_region_t *unredirected_window_region = NULL;
|
||||
ClutterActor *stage;
|
||||
cairo_rectangle_int_t visible_rect, unredirected_rect;
|
||||
GList *children, *l;
|
||||
|
||||
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen);
|
||||
if (info->unredirected_window != NULL)
|
||||
{
|
||||
meta_window_actor_get_shape_bounds (META_WINDOW_ACTOR (info->unredirected_window), &unredirected_rect);
|
||||
unredirected_window_region = cairo_region_create_rectangle (&unredirected_rect);
|
||||
}
|
||||
|
||||
/* We walk the list from top to bottom (opposite of painting order),
|
||||
* and subtract the opaque area of each window out of the visible
|
||||
* region that we pass to the windows below.
|
||||
*/
|
||||
children = clutter_container_get_children (CLUTTER_CONTAINER (actor));
|
||||
children = g_list_reverse (children);
|
||||
|
||||
/* Get the clipped redraw bounds from Clutter so that we can avoid
|
||||
* painting shadows on windows that don't need to be painted in this
|
||||
* frame. In the case of a multihead setup with mismatched monitor
|
||||
* sizes, we could intersect this with an accurate union of the
|
||||
* monitors to avoid painting shadows that are visible only in the
|
||||
* holes. */
|
||||
stage = clutter_actor_get_stage (actor);
|
||||
clutter_stage_get_redraw_clip_bounds (CLUTTER_STAGE (stage),
|
||||
&visible_rect);
|
||||
|
||||
visible_region = cairo_region_create_rectangle (&visible_rect);
|
||||
|
||||
if (unredirected_window_region)
|
||||
cairo_region_subtract (visible_region, unredirected_window_region);
|
||||
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
if (!CLUTTER_ACTOR_IS_VISIBLE (l->data))
|
||||
continue;
|
||||
|
||||
/* If an actor has effects applied, then that can change the area
|
||||
* it paints and the opacity, so we no longer can figure out what
|
||||
* portion of the actor is obscured and what portion of the screen
|
||||
* it obscures, so we skip the actor.
|
||||
*
|
||||
* This has a secondary beneficial effect: if a ClutterOffscreenEffect
|
||||
* is applied to an actor, then our clipped redraws interfere with the
|
||||
* caching of the FBO - even if we only need to draw a small portion
|
||||
* of the window right now, ClutterOffscreenEffect may use other portions
|
||||
* of the FBO later. So, skipping actors with effects applied also
|
||||
* prevents these bugs.
|
||||
*
|
||||
* Theoretically, we should check clutter_actor_get_offscreen_redirect()
|
||||
* as well for the same reason, but omitted for simplicity in the
|
||||
* hopes that no-one will do that.
|
||||
*/
|
||||
if (clutter_actor_has_effects (l->data))
|
||||
continue;
|
||||
|
||||
if (META_IS_WINDOW_ACTOR (l->data))
|
||||
{
|
||||
MetaWindowActor *window_actor = l->data;
|
||||
int x, y;
|
||||
|
||||
if (!actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
|
||||
continue;
|
||||
|
||||
/* Temporarily move to the coordinate system of the actor */
|
||||
cairo_region_translate (visible_region, - x, - y);
|
||||
|
||||
meta_window_actor_set_visible_region (window_actor, visible_region);
|
||||
|
||||
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
|
||||
{
|
||||
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
|
||||
if (obscured_region)
|
||||
cairo_region_subtract (visible_region, obscured_region);
|
||||
}
|
||||
|
||||
meta_window_actor_set_visible_region_beneath (window_actor, visible_region);
|
||||
cairo_region_translate (visible_region, x, y);
|
||||
}
|
||||
else if (META_IS_BACKGROUND_ACTOR (l->data))
|
||||
{
|
||||
MetaBackgroundActor *background_actor = l->data;
|
||||
meta_background_actor_set_visible_region (background_actor, visible_region);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_region_destroy (visible_region);
|
||||
|
||||
if (unredirected_window_region)
|
||||
cairo_region_destroy (unredirected_window_region);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
|
||||
|
||||
/* Now that we are done painting, unset the visible regions (they will
|
||||
* mess up painting clones of our actors)
|
||||
*/
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
if (META_IS_WINDOW_ACTOR (l->data))
|
||||
{
|
||||
MetaWindowActor *window_actor = l->data;
|
||||
meta_window_actor_reset_visible_regions (window_actor);
|
||||
}
|
||||
else if (META_IS_BACKGROUND_ACTOR (l->data))
|
||||
{
|
||||
MetaBackgroundActor *background_actor = l->data;
|
||||
meta_background_actor_set_visible_region (background_actor, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_group_class_init (MetaWindowGroupClass *klass)
|
||||
{
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
actor_class->paint = meta_window_group_paint;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_group_init (MetaWindowGroup *window_group)
|
||||
{
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
meta_window_group_new (MetaScreen *screen)
|
||||
{
|
||||
MetaWindowGroup *window_group;
|
||||
|
||||
window_group = g_object_new (META_TYPE_WINDOW_GROUP, NULL);
|
||||
|
||||
window_group->screen = screen;
|
||||
|
||||
return CLUTTER_ACTOR (window_group);
|
||||
}
|
@ -1,17 +1,17 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#ifndef MUTTER_WINDOW_GROUP_H
|
||||
#define MUTTER_WINDOW_GROUP_H
|
||||
#ifndef META_WINDOW_GROUP_H
|
||||
#define META_WINDOW_GROUP_H
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "screen.h"
|
||||
#include <meta/screen.h>
|
||||
|
||||
/**
|
||||
* MutterWindowGroup:
|
||||
* MetaWindowGroup:
|
||||
*
|
||||
* This class is a subclass of ClutterGroup with special handling for
|
||||
* MutterWindow when painting the group. When we are painting a stack
|
||||
* MetaWindowActor when painting the group. When we are painting a stack
|
||||
* of 5-10 maximized windows, the standard bottom-to-top method of
|
||||
* drawing every actor results in a tremendous amount of overdraw
|
||||
* and can easily max out the available memory bandwidth on a low-end
|
||||
@ -21,7 +21,7 @@
|
||||
* The basic technique applied here is to do a pre-pass before painting
|
||||
* where we walk window from top to bottom and compute the visible area
|
||||
* at each step by subtracting out the windows above it. The visible
|
||||
* area is passed to MutterWindow which uses it to clip the portion of
|
||||
* area is passed to MetaWindowActor which uses it to clip the portion of
|
||||
* the window which drawn and avoid redrawing the shadow if it is completely
|
||||
* obscured.
|
||||
*
|
||||
@ -34,19 +34,19 @@
|
||||
* we have lots of memory and bandwidth.)
|
||||
*/
|
||||
|
||||
#define MUTTER_TYPE_WINDOW_GROUP (mutter_window_group_get_type ())
|
||||
#define MUTTER_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_WINDOW_GROUP, MutterWindowGroup))
|
||||
#define MUTTER_WINDOW_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_WINDOW_GROUP, MutterWindowGroupClass))
|
||||
#define MUTTER_IS_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_TYPE_WINDOW_GROUP))
|
||||
#define MUTTER_IS_WINDOW_GROU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_WINDOW_GROUP))
|
||||
#define MUTTER_WINDOW_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_WINDOW_GROUP, MutterWindowGroupClass))
|
||||
#define META_TYPE_WINDOW_GROUP (meta_window_group_get_type ())
|
||||
#define META_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WINDOW_GROUP, MetaWindowGroup))
|
||||
#define META_WINDOW_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WINDOW_GROUP, MetaWindowGroupClass))
|
||||
#define META_IS_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WINDOW_GROUP))
|
||||
#define META_IS_WINDOW_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WINDOW_GROUP))
|
||||
#define META_WINDOW_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WINDOW_GROUP, MetaWindowGroupClass))
|
||||
|
||||
typedef struct _MutterWindowGroup MutterWindowGroup;
|
||||
typedef struct _MutterWindowGroupClass MutterWindowGroupClass;
|
||||
typedef struct _MutterWindowGroupPrivate MutterWindowGroupPrivate;
|
||||
typedef struct _MetaWindowGroup MetaWindowGroup;
|
||||
typedef struct _MetaWindowGroupClass MetaWindowGroupClass;
|
||||
typedef struct _MetaWindowGroupPrivate MetaWindowGroupPrivate;
|
||||
|
||||
GType mutter_window_group_get_type (void);
|
||||
GType meta_window_group_get_type (void);
|
||||
|
||||
ClutterActor *mutter_window_group_new (MetaScreen *screen);
|
||||
ClutterActor *meta_window_group_new (MetaScreen *screen);
|
||||
|
||||
#endif /* MUTTER_WINDOW_GROUP_H */
|
||||
#endif /* META_WINDOW_GROUP_H */
|
254
src/compositor/meta-window-shape.c
Normal file
254
src/compositor/meta-window-shape.c
Normal file
@ -0,0 +1,254 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaWindowShape
|
||||
*
|
||||
* Extracted invariant window shape
|
||||
*
|
||||
* Copyright (C) 2010 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "meta-window-shape.h"
|
||||
#include "region-utils.h"
|
||||
|
||||
struct _MetaWindowShape
|
||||
{
|
||||
guint ref_count;
|
||||
|
||||
int top, right, bottom, left;
|
||||
int n_rectangles;
|
||||
cairo_rectangle_int_t *rectangles;
|
||||
guint hash;
|
||||
};
|
||||
|
||||
MetaWindowShape *
|
||||
meta_window_shape_new (cairo_region_t *region)
|
||||
{
|
||||
MetaWindowShape *shape;
|
||||
MetaRegionIterator iter;
|
||||
cairo_rectangle_int_t extents;
|
||||
int max_yspan_y1 = 0;
|
||||
int max_yspan_y2 = 0;
|
||||
int max_xspan_x1 = -1;
|
||||
int max_xspan_x2 = -1;
|
||||
guint hash;
|
||||
|
||||
shape = g_slice_new0 (MetaWindowShape);
|
||||
shape->ref_count = 1;
|
||||
|
||||
cairo_region_get_extents (region, &extents);
|
||||
|
||||
shape->n_rectangles = cairo_region_num_rectangles (region);
|
||||
|
||||
if (shape->n_rectangles == 0)
|
||||
{
|
||||
shape->rectangles = NULL;
|
||||
shape->top = shape->right = shape->bottom = shape->left = 0;
|
||||
shape->hash = 0;
|
||||
return shape;
|
||||
}
|
||||
|
||||
for (meta_region_iterator_init (&iter, region);
|
||||
!meta_region_iterator_at_end (&iter);
|
||||
meta_region_iterator_next (&iter))
|
||||
{
|
||||
int max_line_xspan_x1 = -1;
|
||||
int max_line_xspan_x2 = -1;
|
||||
|
||||
if (iter.rectangle.width > max_line_xspan_x2 - max_line_xspan_x1)
|
||||
{
|
||||
max_line_xspan_x1 = iter.rectangle.x;
|
||||
max_line_xspan_x2 = iter.rectangle.x + iter.rectangle.width;
|
||||
}
|
||||
|
||||
if (iter.line_end)
|
||||
{
|
||||
if (iter.rectangle.height > max_yspan_y2 - max_yspan_y1)
|
||||
{
|
||||
max_yspan_y1 = iter.rectangle.y;
|
||||
max_yspan_y2 = iter.rectangle.y + iter.rectangle.height;
|
||||
}
|
||||
|
||||
if (max_xspan_x1 < 0) /* First line */
|
||||
{
|
||||
max_xspan_x1 = max_line_xspan_x1;
|
||||
max_xspan_x2 = max_line_xspan_x2;
|
||||
}
|
||||
else
|
||||
{
|
||||
max_xspan_x1 = MAX (max_xspan_x1, max_line_xspan_x1);
|
||||
max_xspan_x2 = MIN (max_xspan_x2, max_line_xspan_x2);
|
||||
|
||||
if (max_xspan_x2 < max_xspan_x1)
|
||||
max_xspan_x2 = max_xspan_x1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
g_print ("xspan: %d -> %d, yspan: %d -> %d\n",
|
||||
max_xspan_x1, max_xspan_x2,
|
||||
max_yspan_y1, max_yspan_y2);
|
||||
#endif
|
||||
|
||||
shape->top = max_yspan_y1 - extents.y;
|
||||
shape->right = extents.x + extents.width - max_xspan_x2;
|
||||
shape->bottom = extents.y + extents.height - max_yspan_y2;
|
||||
shape->left = max_xspan_x1 - extents.x;
|
||||
|
||||
shape->rectangles = g_new (cairo_rectangle_int_t, shape->n_rectangles);
|
||||
|
||||
hash = 0;
|
||||
for (meta_region_iterator_init (&iter, region);
|
||||
!meta_region_iterator_at_end (&iter);
|
||||
meta_region_iterator_next (&iter))
|
||||
{
|
||||
int x1, x2, y1, y2;
|
||||
|
||||
x1 = iter.rectangle.x;
|
||||
x2 = iter.rectangle.x + iter.rectangle.width;
|
||||
y1 = iter.rectangle.y;
|
||||
y2 = iter.rectangle.y + iter.rectangle.height;
|
||||
|
||||
if (x1 > max_xspan_x1)
|
||||
x1 -= MIN (x1, max_xspan_x2 - 1) - max_xspan_x1;
|
||||
if (x2 > max_xspan_x1)
|
||||
x2 -= MIN (x2, max_xspan_x2 - 1) - max_xspan_x1;
|
||||
if (y1 > max_yspan_y1)
|
||||
y1 -= MIN (y1, max_yspan_y2 - 1) - max_yspan_y1;
|
||||
if (y2 > max_yspan_y1)
|
||||
y2 -= MIN (y2, max_yspan_y2 - 1) - max_yspan_y1;
|
||||
|
||||
shape->rectangles[iter.i].x = x1 - extents.x;
|
||||
shape->rectangles[iter.i].y = y1 - extents.y;
|
||||
shape->rectangles[iter.i].width = x2 - x1;
|
||||
shape->rectangles[iter.i].height = y2 - y1;
|
||||
|
||||
#if 0
|
||||
g_print ("%d: +%d+%dx%dx%d => +%d+%dx%dx%d\n",
|
||||
iter.i, iter.rectangle.x, iter.rectangle.y, iter.rectangle.width, iter.rectangle.height,
|
||||
shape->rectangles[iter.i].x, shape->rectangles[iter.i].y,
|
||||
hape->rectangles[iter.i].width, shape->rectangles[iter.i].height);
|
||||
#endif
|
||||
|
||||
hash = hash * 31 + x1 * 17 + x2 * 27 + y1 * 37 + y2 * 43;
|
||||
}
|
||||
|
||||
shape->hash = hash;
|
||||
|
||||
#if 0
|
||||
g_print ("%d %d %d %d: %#x\n\n", shape->top, shape->right, shape->bottom, shape->left, shape->hash);
|
||||
#endif
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
MetaWindowShape *
|
||||
meta_window_shape_ref (MetaWindowShape *shape)
|
||||
{
|
||||
shape->ref_count++;
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_shape_unref (MetaWindowShape *shape)
|
||||
{
|
||||
shape->ref_count--;
|
||||
if (shape->ref_count == 0)
|
||||
{
|
||||
g_free (shape->rectangles);
|
||||
g_slice_free (MetaWindowShape, shape);
|
||||
}
|
||||
}
|
||||
|
||||
guint
|
||||
meta_window_shape_hash (MetaWindowShape *shape)
|
||||
{
|
||||
return shape->hash;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_window_shape_equal (MetaWindowShape *shape_a,
|
||||
MetaWindowShape *shape_b)
|
||||
{
|
||||
if (shape_a->n_rectangles != shape_b->n_rectangles)
|
||||
return FALSE;
|
||||
|
||||
return memcmp (shape_a->rectangles, shape_b->rectangles,
|
||||
sizeof (cairo_rectangle_int_t) * shape_a->n_rectangles) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_shape_get_borders (MetaWindowShape *shape,
|
||||
int *border_top,
|
||||
int *border_right,
|
||||
int *border_bottom,
|
||||
int *border_left)
|
||||
{
|
||||
if (border_top)
|
||||
*border_top = shape->top;
|
||||
if (border_right)
|
||||
*border_right = shape->right;
|
||||
if (border_bottom)
|
||||
*border_bottom = shape->bottom;
|
||||
if (border_left)
|
||||
*border_left = shape->left;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_shape_to_region:
|
||||
* @shape: a #MetaWindowShape
|
||||
* @center_width: size of the central region horizontally
|
||||
* @center_height: size of the central region vertically
|
||||
*
|
||||
* Converts the shape to to a cairo_region_t using the given width
|
||||
* and height for the central scaled region.
|
||||
*
|
||||
* Return value: a newly created region
|
||||
*/
|
||||
cairo_region_t *
|
||||
meta_window_shape_to_region (MetaWindowShape *shape,
|
||||
int center_width,
|
||||
int center_height)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
int i;
|
||||
|
||||
region = cairo_region_create ();
|
||||
|
||||
for (i = 0; i < shape->n_rectangles; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect = shape->rectangles[i];
|
||||
|
||||
if (rect.x <= shape->left && rect.x + rect.width >= shape->left + 1)
|
||||
rect.width += center_width;
|
||||
else if (rect.x >= shape->left + 1)
|
||||
rect.x += center_width;
|
||||
|
||||
if (rect.y <= shape->top && rect.y + rect.height >= shape->top + 1)
|
||||
rect.height += center_height;
|
||||
else if (rect.y >= shape->top + 1)
|
||||
rect.y += center_height;
|
||||
|
||||
cairo_region_union_rectangle (region, &rect);
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
60
src/compositor/meta-window-shape.h
Normal file
60
src/compositor/meta-window-shape.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaWindowShape
|
||||
*
|
||||
* Extracted invariant window shape
|
||||
*
|
||||
* Copyright (C) 2010 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __META_WINDOW_SHAPE_H__
|
||||
#define __META_WINDOW_SHAPE_H__
|
||||
|
||||
#include <cairo.h>
|
||||
#include <glib.h>
|
||||
|
||||
/**
|
||||
* MetaWindowShape:
|
||||
* #MetaWindowShape represents a 9-sliced region with borders on all sides that
|
||||
* are unscaled, and a constant central region that is scaled. For example,
|
||||
* the regions representing two windows that are rounded rectangles,
|
||||
* with the same corner radius but different sizes, have the
|
||||
* same MetaWindowShape.
|
||||
*
|
||||
* #MetaWindowShape is designed to be used as part of a hash table key, so has
|
||||
* efficient hash and equal functions.
|
||||
*/
|
||||
typedef struct _MetaWindowShape MetaWindowShape;
|
||||
|
||||
MetaWindowShape * meta_window_shape_new (cairo_region_t *region);
|
||||
MetaWindowShape * meta_window_shape_ref (MetaWindowShape *shape);
|
||||
void meta_window_shape_unref (MetaWindowShape *shape);
|
||||
guint meta_window_shape_hash (MetaWindowShape *shape);
|
||||
gboolean meta_window_shape_equal (MetaWindowShape *shape_a,
|
||||
MetaWindowShape *shape_b);
|
||||
void meta_window_shape_get_borders (MetaWindowShape *shape,
|
||||
int *border_top,
|
||||
int *border_right,
|
||||
int *border_bottom,
|
||||
int *border_left);
|
||||
cairo_region_t *meta_window_shape_to_region (MetaWindowShape *shape,
|
||||
int center_width,
|
||||
int center_height);
|
||||
|
||||
#endif /* __META_WINDOW_SHAPE_H __*/
|
||||
|
@ -1,652 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Intel Corp.
|
||||
*
|
||||
* Author: Tomas Frydrych <tf@linux.intel.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "compositor-private.h"
|
||||
#include "mutter-plugin-manager.h"
|
||||
#include "prefs.h"
|
||||
#include "errors.h"
|
||||
#include "workspace.h"
|
||||
#include "mutter-module.h"
|
||||
#include "../core/window-private.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
/*
|
||||
* There is only one instace of each module per the process.
|
||||
*/
|
||||
static GHashTable *plugin_modules = NULL;
|
||||
|
||||
static gboolean mutter_plugin_manager_reload (MutterPluginManager *plugin_mgr);
|
||||
|
||||
struct MutterPluginManager
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
GList /* MutterPluginPending */ *pending_plugin_modules; /* Plugins not yet fully loaded */
|
||||
GList /* MutterPlugin */ *plugins; /* TODO -- maybe use hash table */
|
||||
GList *unload; /* Plugins that are disabled and pending unload */
|
||||
|
||||
guint idle_unload_id;
|
||||
};
|
||||
|
||||
typedef struct MutterPluginPending
|
||||
{
|
||||
MutterModule *module;
|
||||
char *path;
|
||||
char *params;
|
||||
} MutterPluginPending;
|
||||
|
||||
/*
|
||||
* Checks that the plugin is compatible with the WM and sets up the plugin
|
||||
* struct.
|
||||
*/
|
||||
static MutterPlugin *
|
||||
mutter_plugin_load (MutterPluginManager *mgr,
|
||||
MutterModule *module,
|
||||
const gchar *params)
|
||||
{
|
||||
MutterPlugin *plugin = NULL;
|
||||
GType plugin_type = mutter_module_get_plugin_type (module);
|
||||
|
||||
if (!plugin_type)
|
||||
{
|
||||
g_warning ("Plugin type not registered !!!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
plugin = g_object_new (plugin_type,
|
||||
"screen", mgr->screen,
|
||||
"params", params,
|
||||
NULL);
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempst to unload a plugin; returns FALSE if plugin cannot be unloaded at
|
||||
* present (e.g., and effect is in progress) and should be scheduled for
|
||||
* removal later.
|
||||
*/
|
||||
static gboolean
|
||||
mutter_plugin_unload (MutterPlugin *plugin)
|
||||
{
|
||||
if (mutter_plugin_running (plugin))
|
||||
{
|
||||
g_object_set (plugin, "disabled", TRUE, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_unref (plugin);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iddle callback to remove plugins that could not be removed directly and are
|
||||
* pending for removal.
|
||||
*/
|
||||
static gboolean
|
||||
mutter_plugin_manager_idle_unload (MutterPluginManager *plugin_mgr)
|
||||
{
|
||||
GList *l = plugin_mgr->unload;
|
||||
gboolean dont_remove = TRUE;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MutterPlugin *plugin = l->data;
|
||||
|
||||
if (mutter_plugin_unload (plugin))
|
||||
{
|
||||
/* Remove from list */
|
||||
GList *p = l->prev;
|
||||
GList *n = l->next;
|
||||
|
||||
if (!p)
|
||||
plugin_mgr->unload = n;
|
||||
else
|
||||
p->next = n;
|
||||
|
||||
if (n)
|
||||
n->prev = p;
|
||||
|
||||
g_list_free_1 (l);
|
||||
|
||||
l = n;
|
||||
}
|
||||
else
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
if (!plugin_mgr->unload)
|
||||
{
|
||||
/* If no more unloads are pending, remove the handler as well */
|
||||
dont_remove = FALSE;
|
||||
plugin_mgr->idle_unload_id = 0;
|
||||
}
|
||||
|
||||
return dont_remove;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unloads all plugins
|
||||
*/
|
||||
static void
|
||||
mutter_plugin_manager_unload (MutterPluginManager *plugin_mgr)
|
||||
{
|
||||
GList *plugins = plugin_mgr->plugins;
|
||||
|
||||
while (plugins)
|
||||
{
|
||||
MutterPlugin *plugin = plugins->data;
|
||||
|
||||
/* If the plugin could not be removed, move it to the unload list */
|
||||
if (!mutter_plugin_unload (plugin))
|
||||
{
|
||||
plugin_mgr->unload = g_list_prepend (plugin_mgr->unload, plugin);
|
||||
|
||||
if (!plugin_mgr->idle_unload_id)
|
||||
{
|
||||
plugin_mgr->idle_unload_id = g_idle_add ((GSourceFunc)
|
||||
mutter_plugin_manager_idle_unload,
|
||||
plugin_mgr);
|
||||
}
|
||||
}
|
||||
|
||||
plugins = plugins->next;
|
||||
}
|
||||
|
||||
g_list_free (plugin_mgr->plugins);
|
||||
plugin_mgr->plugins = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
prefs_changed_callback (MetaPreference pref,
|
||||
void *data)
|
||||
{
|
||||
MutterPluginManager *plugin_mgr = data;
|
||||
|
||||
if (pref == META_PREF_CLUTTER_PLUGINS)
|
||||
{
|
||||
mutter_plugin_manager_reload (plugin_mgr);
|
||||
}
|
||||
}
|
||||
|
||||
static MutterModule *
|
||||
mutter_plugin_manager_get_module (const gchar *path)
|
||||
{
|
||||
MutterModule *module = g_hash_table_lookup (plugin_modules, path);
|
||||
|
||||
if (!module &&
|
||||
(module = g_object_new (MUTTER_TYPE_MODULE, "path", path, NULL)))
|
||||
{
|
||||
g_hash_table_insert (plugin_modules, g_strdup (path), module);
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads all plugins listed in gconf registry.
|
||||
*/
|
||||
gboolean
|
||||
mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
|
||||
{
|
||||
const gchar *dpath = MUTTER_PLUGIN_DIR "/";
|
||||
GSList *plugins, *fallback = NULL;
|
||||
|
||||
plugins = meta_prefs_get_clutter_plugins ();
|
||||
|
||||
if (!plugins)
|
||||
{
|
||||
/*
|
||||
* If no plugins are specified, try to load the default plugin.
|
||||
*/
|
||||
fallback = g_slist_append (fallback, "default");
|
||||
plugins = fallback;
|
||||
}
|
||||
|
||||
while (plugins)
|
||||
{
|
||||
gchar *plugin_string;
|
||||
gchar *params;
|
||||
|
||||
plugin_string = g_strdup (plugins->data);
|
||||
|
||||
if (plugin_string)
|
||||
{
|
||||
MutterModule *module;
|
||||
gchar *path;
|
||||
|
||||
params = strchr (plugin_string, ':');
|
||||
|
||||
if (params)
|
||||
{
|
||||
*params = 0;
|
||||
++params;
|
||||
}
|
||||
|
||||
if (g_path_is_absolute (plugin_string))
|
||||
path = g_strdup (plugin_string);
|
||||
else
|
||||
path = g_strconcat (dpath, plugin_string, ".so", NULL);
|
||||
|
||||
module = mutter_plugin_manager_get_module (path);
|
||||
|
||||
if (module)
|
||||
{
|
||||
gboolean use_succeeded;
|
||||
|
||||
/*
|
||||
* This dlopens the module and registers the plugin type with the
|
||||
* GType system, if the module is not already loaded. When we
|
||||
* create a plugin, the type system also calls g_type_module_use()
|
||||
* to guarantee the module will not be unloaded during the plugin
|
||||
* life time. Consequently we can unuse() the module again.
|
||||
*/
|
||||
use_succeeded = g_type_module_use (G_TYPE_MODULE (module));
|
||||
|
||||
if (use_succeeded)
|
||||
{
|
||||
MutterPluginPending *pending = g_new0 (MutterPluginPending, 1);
|
||||
pending->module = module;
|
||||
pending->path = g_strdup (path);
|
||||
pending->params = g_strdup (params);
|
||||
plugin_mgr->pending_plugin_modules =
|
||||
g_list_prepend (plugin_mgr->pending_plugin_modules, pending);
|
||||
}
|
||||
}
|
||||
else
|
||||
g_warning ("Unable to load plugin module [%s]: %s",
|
||||
path, g_module_error());
|
||||
|
||||
g_free (path);
|
||||
g_free (plugin_string);
|
||||
}
|
||||
|
||||
plugins = plugins->next;
|
||||
}
|
||||
|
||||
|
||||
if (fallback)
|
||||
g_slist_free (fallback);
|
||||
|
||||
if (plugin_mgr->pending_plugin_modules != NULL)
|
||||
{
|
||||
meta_prefs_add_listener (prefs_changed_callback, plugin_mgr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mutter_plugin_manager_initialize (MutterPluginManager *plugin_mgr)
|
||||
{
|
||||
GList *iter;
|
||||
|
||||
for (iter = plugin_mgr->pending_plugin_modules; iter; iter = iter->next)
|
||||
{
|
||||
MutterPluginPending *pending = (MutterPluginPending*) iter->data;
|
||||
MutterPlugin *p;
|
||||
|
||||
if ((p = mutter_plugin_load (plugin_mgr, pending->module, pending->params)))
|
||||
{
|
||||
plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Plugin load for [%s] failed", pending->path);
|
||||
}
|
||||
|
||||
g_type_module_unuse (G_TYPE_MODULE (pending->module));
|
||||
g_free (pending->path);
|
||||
g_free (pending->params);
|
||||
g_free (pending);
|
||||
}
|
||||
g_list_free (plugin_mgr->pending_plugin_modules);
|
||||
plugin_mgr->pending_plugin_modules = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reloads all plugins
|
||||
*/
|
||||
static gboolean
|
||||
mutter_plugin_manager_reload (MutterPluginManager *plugin_mgr)
|
||||
{
|
||||
/* TODO -- brute force; should we build a list of plugins to load and list of
|
||||
* plugins to unload? We are probably not going to have large numbers of
|
||||
* plugins loaded at the same time, so it might not be worth it.
|
||||
*/
|
||||
|
||||
/* Prevent stale grabs on unloaded plugins */
|
||||
mutter_check_end_modal (plugin_mgr->screen);
|
||||
|
||||
mutter_plugin_manager_unload (plugin_mgr);
|
||||
return mutter_plugin_manager_load (plugin_mgr);
|
||||
}
|
||||
|
||||
MutterPluginManager *
|
||||
mutter_plugin_manager_new (MetaScreen *screen)
|
||||
{
|
||||
MutterPluginManager *plugin_mgr;
|
||||
|
||||
if (!plugin_modules)
|
||||
{
|
||||
plugin_modules = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
|
||||
NULL);
|
||||
}
|
||||
|
||||
plugin_mgr = g_new0 (MutterPluginManager, 1);
|
||||
|
||||
plugin_mgr->screen = screen;
|
||||
|
||||
return plugin_mgr;
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_manager_kill_effect (MutterPluginManager *plugin_mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long events)
|
||||
{
|
||||
GList *l = plugin_mgr->plugins;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!mutter_plugin_disabled (plugin)
|
||||
&& (mutter_plugin_features (plugin) & events)
|
||||
&& klass->kill_effect)
|
||||
klass->kill_effect (plugin, actor, events);
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
#define ALL_BUT_SWITCH \
|
||||
MUTTER_PLUGIN_ALL_EFFECTS & \
|
||||
~MUTTER_PLUGIN_SWITCH_WORKSPACE
|
||||
/*
|
||||
* Public method that the compositor hooks into for events that require
|
||||
* no additional parameters.
|
||||
*
|
||||
* Returns TRUE if at least one of the plugins handled the event type (i.e.,
|
||||
* if the return value is FALSE, there will be no subsequent call to the
|
||||
* manager completed() callback, and the compositor must ensure that any
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
mutter_plugin_manager_event_simple (MutterPluginManager *plugin_mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long event)
|
||||
{
|
||||
GList *l = plugin_mgr->plugins;
|
||||
gboolean retval = FALSE;
|
||||
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||
|
||||
if (display->display_opening)
|
||||
return FALSE;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!mutter_plugin_disabled (plugin) &&
|
||||
(mutter_plugin_features (plugin) & event))
|
||||
{
|
||||
retval = TRUE;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case MUTTER_PLUGIN_MINIMIZE:
|
||||
if (klass->minimize)
|
||||
{
|
||||
mutter_plugin_manager_kill_effect (
|
||||
plugin_mgr,
|
||||
actor,
|
||||
ALL_BUT_SWITCH);
|
||||
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
klass->minimize (plugin, actor);
|
||||
}
|
||||
break;
|
||||
case MUTTER_PLUGIN_MAP:
|
||||
if (klass->map)
|
||||
{
|
||||
mutter_plugin_manager_kill_effect (
|
||||
plugin_mgr,
|
||||
actor,
|
||||
ALL_BUT_SWITCH);
|
||||
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
klass->map (plugin, actor);
|
||||
}
|
||||
break;
|
||||
case MUTTER_PLUGIN_DESTROY:
|
||||
if (klass->destroy)
|
||||
{
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
klass->destroy (plugin, actor);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_warning ("Incorrect handler called for event %lu", event);
|
||||
}
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* The public method that the compositor hooks into for maximize and unmaximize
|
||||
* events.
|
||||
*
|
||||
* Returns TRUE if at least one of the plugins handled the event type (i.e.,
|
||||
* if the return value is FALSE, there will be no subsequent call to the
|
||||
* manager completed() callback, and the compositor must ensure that any
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
mutter_plugin_manager_event_maximize (MutterPluginManager *plugin_mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long event,
|
||||
gint target_x,
|
||||
gint target_y,
|
||||
gint target_width,
|
||||
gint target_height)
|
||||
{
|
||||
GList *l = plugin_mgr->plugins;
|
||||
gboolean retval = FALSE;
|
||||
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||
|
||||
if (display->display_opening)
|
||||
return FALSE;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!mutter_plugin_disabled (plugin) &&
|
||||
(mutter_plugin_features (plugin) & event))
|
||||
{
|
||||
retval = TRUE;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case MUTTER_PLUGIN_MAXIMIZE:
|
||||
if (klass->maximize)
|
||||
{
|
||||
mutter_plugin_manager_kill_effect (
|
||||
plugin_mgr,
|
||||
actor,
|
||||
ALL_BUT_SWITCH);
|
||||
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
klass->maximize (plugin, actor,
|
||||
target_x, target_y,
|
||||
target_width, target_height);
|
||||
}
|
||||
break;
|
||||
case MUTTER_PLUGIN_UNMAXIMIZE:
|
||||
if (klass->unmaximize)
|
||||
{
|
||||
mutter_plugin_manager_kill_effect (
|
||||
plugin_mgr,
|
||||
actor,
|
||||
ALL_BUT_SWITCH);
|
||||
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
klass->unmaximize (plugin, actor,
|
||||
target_x, target_y,
|
||||
target_width, target_height);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_warning ("Incorrect handler called for event %lu", event);
|
||||
}
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* The public method that the compositor hooks into for desktop switching.
|
||||
*
|
||||
* Returns TRUE if at least one of the plugins handled the event type (i.e.,
|
||||
* if the return value is FALSE, there will be no subsequent call to the
|
||||
* manager completed() callback, and the compositor must ensure that any
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
mutter_plugin_manager_switch_workspace (MutterPluginManager *plugin_mgr,
|
||||
const GList **actors,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction)
|
||||
{
|
||||
GList *l = plugin_mgr->plugins;
|
||||
gboolean retval = FALSE;
|
||||
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||
|
||||
if (display->display_opening)
|
||||
return FALSE;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!mutter_plugin_disabled (plugin) &&
|
||||
(mutter_plugin_features (plugin) & MUTTER_PLUGIN_SWITCH_WORKSPACE) &&
|
||||
(actors && *actors))
|
||||
{
|
||||
if (klass->switch_workspace)
|
||||
{
|
||||
retval = TRUE;
|
||||
mutter_plugin_manager_kill_effect (
|
||||
plugin_mgr,
|
||||
MUTTER_WINDOW ((*actors)->data),
|
||||
MUTTER_PLUGIN_SWITCH_WORKSPACE);
|
||||
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
klass->switch_workspace (plugin, actors, from, to, direction);
|
||||
}
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* The public method that the compositor hooks into for desktop switching.
|
||||
*
|
||||
* Returns TRUE if at least one of the plugins handled the event type (i.e.,
|
||||
* if the return value is FALSE, there will be no subsequent call to the
|
||||
* manager completed() callback, and the compositor must ensure that any
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
mutter_plugin_manager_xevent_filter (MutterPluginManager *plugin_mgr,
|
||||
XEvent *xev)
|
||||
{
|
||||
GList *l;
|
||||
gboolean have_plugin_xevent_func;
|
||||
|
||||
if (!plugin_mgr)
|
||||
return FALSE;
|
||||
|
||||
l = plugin_mgr->plugins;
|
||||
|
||||
/* We need to make sure that clutter gets certain events, like
|
||||
* ConfigureNotify on the stage window. If there is a plugin that
|
||||
* provides an xevent_filter function, then it's the responsibility
|
||||
* of that plugin to pass events to Clutter. Otherwise, we send the
|
||||
* event directly to Clutter ourselves.
|
||||
*
|
||||
* What happens if there are two plugins with xevent_filter functions
|
||||
* is undefined; in general, multiple competing plugins are something
|
||||
* we don't support well or care much about.
|
||||
*
|
||||
* FIXME: Really, we should just always handle sending the event to
|
||||
* clutter if a plugin doesn't report the event as handled by
|
||||
* returning TRUE, but it doesn't seem worth breaking compatibility
|
||||
* of the plugin interface right now to achieve this; the way it is
|
||||
* now works fine in practice.
|
||||
*/
|
||||
have_plugin_xevent_func = FALSE;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (klass->xevent_filter)
|
||||
{
|
||||
have_plugin_xevent_func = TRUE;
|
||||
if (klass->xevent_filter (plugin, xev) == TRUE)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
if (!have_plugin_xevent_func)
|
||||
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Intel Corp.
|
||||
*
|
||||
* Author: Tomas Frydrych <tf@linux.intel.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MUTTER_PLUGIN_MANAGER_H_
|
||||
#define MUTTER_PLUGIN_MANAGER_H_
|
||||
|
||||
#include "types.h"
|
||||
#include "screen.h"
|
||||
|
||||
#define MUTTER_PLUGIN_FROM_MANAGER_
|
||||
#include "mutter-plugin.h"
|
||||
#undef MUTTER_PLUGIN_FROM_MANAGER_
|
||||
|
||||
typedef struct MutterPluginManager MutterPluginManager;
|
||||
|
||||
MutterPluginManager * mutter_plugin_manager_new (MetaScreen *screen);
|
||||
gboolean mutter_plugin_manager_load (MutterPluginManager *mgr);
|
||||
gboolean mutter_plugin_manager_initialize (MutterPluginManager *plugin_mgr);
|
||||
gboolean mutter_plugin_manager_event_simple (MutterPluginManager *mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long event);
|
||||
|
||||
gboolean mutter_plugin_manager_event_maximize (MutterPluginManager *mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long event,
|
||||
gint target_x,
|
||||
gint target_y,
|
||||
gint target_width,
|
||||
gint target_height);
|
||||
void mutter_plugin_manager_update_workspaces (MutterPluginManager *mgr);
|
||||
|
||||
void mutter_plugin_manager_update_workspace (MutterPluginManager *mgr, MetaWorkspace *w);
|
||||
|
||||
gboolean mutter_plugin_manager_switch_workspace (MutterPluginManager *mgr,
|
||||
const GList **actors,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction);
|
||||
|
||||
gboolean mutter_plugin_manager_xevent_filter (MutterPluginManager *mgr,
|
||||
XEvent *xev);
|
||||
|
||||
#endif
|
@ -1,555 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Intel Corp.
|
||||
*
|
||||
* Author: Tomas Frydrych <tf@linux.intel.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "mutter-plugin.h"
|
||||
#include "screen.h"
|
||||
#include "display.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/extensions/shape.h>
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
#include "compositor-private.h"
|
||||
#include "mutter-window-private.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (MutterPlugin, mutter_plugin, G_TYPE_OBJECT);
|
||||
|
||||
#define MUTTER_PLUGIN_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_PLUGIN, MutterPluginPrivate))
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_SCREEN,
|
||||
PROP_PARAMS,
|
||||
PROP_FEATURES,
|
||||
PROP_DISABLED,
|
||||
PROP_DEBUG_MODE,
|
||||
};
|
||||
|
||||
struct _MutterPluginPrivate
|
||||
{
|
||||
MetaScreen *screen;
|
||||
gchar *params;
|
||||
gulong features;
|
||||
|
||||
gint running;
|
||||
|
||||
gboolean disabled : 1;
|
||||
gboolean debug : 1;
|
||||
};
|
||||
|
||||
static void
|
||||
mutter_plugin_dispose (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (mutter_plugin_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_finalize (GObject *object)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
|
||||
|
||||
g_free (priv->params);
|
||||
priv->params = NULL;
|
||||
|
||||
G_OBJECT_CLASS (mutter_plugin_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_parse_params (MutterPlugin *plugin)
|
||||
{
|
||||
char *p;
|
||||
gulong features = 0;
|
||||
MutterPluginPrivate *priv = plugin->priv;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
/*
|
||||
* Feature flags: identify events that the plugin can handle; a plugin can
|
||||
* handle one or more events.
|
||||
*/
|
||||
if (klass->minimize)
|
||||
features |= MUTTER_PLUGIN_MINIMIZE;
|
||||
|
||||
if (klass->maximize)
|
||||
features |= MUTTER_PLUGIN_MAXIMIZE;
|
||||
|
||||
if (klass->unmaximize)
|
||||
features |= MUTTER_PLUGIN_UNMAXIMIZE;
|
||||
|
||||
if (klass->map)
|
||||
features |= MUTTER_PLUGIN_MAP;
|
||||
|
||||
if (klass->destroy)
|
||||
features |= MUTTER_PLUGIN_DESTROY;
|
||||
|
||||
if (klass->switch_workspace)
|
||||
features |= MUTTER_PLUGIN_SWITCH_WORKSPACE;
|
||||
|
||||
if (priv->params)
|
||||
{
|
||||
gboolean debug = FALSE;
|
||||
|
||||
if ((p = strstr (priv->params, "disable:")))
|
||||
{
|
||||
gchar *d = g_strdup (p+8);
|
||||
|
||||
p = strchr (d, ';');
|
||||
|
||||
if (p)
|
||||
*p = 0;
|
||||
|
||||
if (strstr (d, "minimize"))
|
||||
features &= ~ MUTTER_PLUGIN_MINIMIZE;
|
||||
|
||||
if (strstr (d, "maximize"))
|
||||
features &= ~ MUTTER_PLUGIN_MAXIMIZE;
|
||||
|
||||
if (strstr (d, "unmaximize"))
|
||||
features &= ~ MUTTER_PLUGIN_UNMAXIMIZE;
|
||||
|
||||
if (strstr (d, "map"))
|
||||
features &= ~ MUTTER_PLUGIN_MAP;
|
||||
|
||||
if (strstr (d, "destroy"))
|
||||
features &= ~ MUTTER_PLUGIN_DESTROY;
|
||||
|
||||
if (strstr (d, "switch-workspace"))
|
||||
features &= ~MUTTER_PLUGIN_SWITCH_WORKSPACE;
|
||||
|
||||
g_free (d);
|
||||
}
|
||||
|
||||
if (strstr (priv->params, "debug"))
|
||||
debug = TRUE;
|
||||
|
||||
if (debug != priv->debug)
|
||||
{
|
||||
priv->debug = debug;
|
||||
|
||||
g_object_notify (G_OBJECT (plugin), "debug-mode");
|
||||
}
|
||||
}
|
||||
|
||||
if (features != priv->features)
|
||||
{
|
||||
priv->features = features;
|
||||
|
||||
g_object_notify (G_OBJECT (plugin), "features");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SCREEN:
|
||||
priv->screen = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_PARAMS:
|
||||
priv->params = g_value_dup_string (value);
|
||||
mutter_plugin_parse_params (MUTTER_PLUGIN (object));
|
||||
break;
|
||||
case PROP_DISABLED:
|
||||
priv->disabled = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_DEBUG_MODE:
|
||||
priv->debug = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SCREEN:
|
||||
g_value_set_object (value, priv->screen);
|
||||
break;
|
||||
case PROP_PARAMS:
|
||||
g_value_set_string (value, priv->params);
|
||||
break;
|
||||
case PROP_DISABLED:
|
||||
g_value_set_boolean (value, priv->disabled);
|
||||
break;
|
||||
case PROP_DEBUG_MODE:
|
||||
g_value_set_boolean (value, priv->debug);
|
||||
break;
|
||||
case PROP_FEATURES:
|
||||
g_value_set_ulong (value, priv->features);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mutter_plugin_class_init (MutterPluginClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = mutter_plugin_finalize;
|
||||
gobject_class->dispose = mutter_plugin_dispose;
|
||||
gobject_class->set_property = mutter_plugin_set_property;
|
||||
gobject_class->get_property = mutter_plugin_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SCREEN,
|
||||
g_param_spec_object ("screen",
|
||||
"MetaScreen",
|
||||
"MetaScreen",
|
||||
META_TYPE_SCREEN,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_PARAMS,
|
||||
g_param_spec_string ("params",
|
||||
"Parameters",
|
||||
"Plugin Parameters",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_FEATURES,
|
||||
g_param_spec_ulong ("features",
|
||||
"Features",
|
||||
"Plugin Features",
|
||||
0 , G_MAXULONG, 0,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DISABLED,
|
||||
g_param_spec_boolean ("disabled",
|
||||
"Plugin disabled",
|
||||
"Plugin disabled",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DEBUG_MODE,
|
||||
g_param_spec_boolean ("debug-mode",
|
||||
"Debug Mode",
|
||||
"Debug Mode",
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (MutterPluginPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_init (MutterPlugin *self)
|
||||
{
|
||||
MutterPluginPrivate *priv;
|
||||
|
||||
self->priv = priv = MUTTER_PLUGIN_GET_PRIVATE (self);
|
||||
}
|
||||
|
||||
gulong
|
||||
mutter_plugin_features (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->features;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mutter_plugin_disabled (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->disabled;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mutter_plugin_running (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return (priv->running > 0);
|
||||
}
|
||||
|
||||
gboolean
|
||||
mutter_plugin_debug_mode (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->debug;
|
||||
}
|
||||
|
||||
const MutterPluginInfo *
|
||||
mutter_plugin_get_info (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (klass && klass->plugin_info)
|
||||
return klass->plugin_info (plugin);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_plugin_get_overlay_group (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return mutter_get_overlay_group_for_screen (priv->screen);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_plugin_get_stage (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return mutter_get_stage_for_screen (priv->screen);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_plugin_get_window_group (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return mutter_get_window_group_for_screen (priv->screen);
|
||||
}
|
||||
|
||||
/**
|
||||
* _mutter_plugin_effect_started:
|
||||
* @plugin: the plugin
|
||||
*
|
||||
* Mark that an effect has started for the plugin. This is called
|
||||
* internally by MutterPluginManager.
|
||||
*/
|
||||
void
|
||||
_mutter_plugin_effect_started (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
priv->running++;
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_effect_completed (MutterPlugin *plugin,
|
||||
MutterWindow *actor,
|
||||
unsigned long event)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
if (priv->running-- < 0)
|
||||
{
|
||||
g_warning ("Error in running effect accounting, adjusting.");
|
||||
priv->running = 0;
|
||||
}
|
||||
|
||||
if (!actor)
|
||||
{
|
||||
const MutterPluginInfo *info;
|
||||
const gchar *name = NULL;
|
||||
|
||||
if (plugin && (info = mutter_plugin_get_info (plugin)))
|
||||
name = info->name;
|
||||
|
||||
g_warning ("Plugin [%s] passed NULL for actor!",
|
||||
name ? name : "unknown");
|
||||
}
|
||||
|
||||
if (event == MUTTER_PLUGIN_SWITCH_WORKSPACE)
|
||||
{
|
||||
/* The window is just used to identify the screen */
|
||||
MetaWindow *window = mutter_window_get_meta_window (actor);
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
mutter_switch_workspace_completed (screen);
|
||||
}
|
||||
else
|
||||
{
|
||||
mutter_window_effect_completed (actor, event);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_query_screen_size (MutterPlugin *plugin,
|
||||
int *width,
|
||||
int *height)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
meta_screen_get_size (priv->screen, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_set_stage_reactive (MutterPlugin *plugin,
|
||||
gboolean reactive)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
|
||||
if (reactive)
|
||||
mutter_set_stage_input_region (screen, None);
|
||||
else
|
||||
mutter_empty_stage_input_region (screen);
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_set_stage_input_area (MutterPlugin *plugin,
|
||||
gint x, gint y, gint width, gint height)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
XRectangle rect;
|
||||
XserverRegion region;
|
||||
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
|
||||
region = XFixesCreateRegion (xdpy, &rect, 1);
|
||||
mutter_set_stage_input_region (screen, region);
|
||||
XFixesDestroyRegion (xdpy, region);
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_set_stage_input_region (MutterPlugin *plugin,
|
||||
XserverRegion region)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
|
||||
mutter_set_stage_input_region (screen, region);
|
||||
}
|
||||
|
||||
GList *
|
||||
mutter_plugin_get_windows (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return mutter_get_windows (priv->screen);
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_plugin_begin_modal:
|
||||
* @plugin: a #MutterPlugin
|
||||
* @grab_window: the X window to grab the keyboard and mouse on
|
||||
* @cursor: the cursor to use for the pointer grab, or None,
|
||||
* to use the normal cursor for the grab window and
|
||||
* its descendants.
|
||||
* @options: flags that modify the behavior of the modal grab
|
||||
* @timestamp: the timestamp used for establishing grabs
|
||||
*
|
||||
* This function is used to grab the keyboard and mouse for the exclusive
|
||||
* use of the plugin. Correct operation requires that both the keyboard
|
||||
* and mouse are grabbed, or thing will break. (In particular, other
|
||||
* passive X grabs in Mutter can trigger but not be handled by the normal
|
||||
* keybinding handling code.) However, the plugin can establish the keyboard
|
||||
* and/or mouse grabs ahead of time and pass in the
|
||||
* %META_MODAL_POINTER_ALREADY_GRABBED and/or %META_MODAL_KEYBOARD_ALREADY_GRABBED
|
||||
* options. This facility is provided for two reasons: first to allow using
|
||||
* this function to establish modality after a passive grab, and second to
|
||||
* allow using obscure features of XGrabPointer() and XGrabKeyboard() without
|
||||
* having to add them to this API.
|
||||
*
|
||||
* Return value: whether we successfully grabbed the keyboard and
|
||||
* mouse and made the plugin modal.
|
||||
*/
|
||||
gboolean
|
||||
mutter_plugin_begin_modal (MutterPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return mutter_begin_modal_for_plugin (priv->screen, plugin,
|
||||
grab_window, cursor, options, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_plugin_end_modal
|
||||
* @plugin: a #MutterPlugin
|
||||
* @timestamp: the time used for releasing grabs
|
||||
*
|
||||
* Ends the modal operation begun with meta_plugin_begin_modal(). This
|
||||
* ungrabs both the mouse and keyboard even when
|
||||
* %META_MODAL_POINTER_ALREADY_GRABBED or
|
||||
* %META_MODAL_KEYBOARD_ALREADY_GRABBED were provided as options
|
||||
* when beginnning the modal operation.
|
||||
*/
|
||||
void
|
||||
mutter_plugin_end_modal (MutterPlugin *plugin,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
mutter_end_modal_for_plugin (priv->screen, plugin, timestamp);
|
||||
}
|
||||
|
||||
Display *
|
||||
mutter_plugin_get_xdisplay (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaDisplay *display = meta_screen_get_display (priv->screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
|
||||
return xdpy;
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_plugin_get_screen:
|
||||
* @plugin: a #MutterPlugin
|
||||
*
|
||||
* Gets the #MetaScreen corresponding to a plugin. Each plugin instance
|
||||
* is associated with exactly one screen; if Metacity is managing
|
||||
* multiple screens, multiple plugin instances will be created.
|
||||
*
|
||||
* Return value: (transfer none): the #MetaScreen for the plugin
|
||||
*/
|
||||
MetaScreen *
|
||||
mutter_plugin_get_screen (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->screen;
|
||||
}
|
||||
|
@ -1,521 +0,0 @@
|
||||
/*
|
||||
* shaped texture
|
||||
*
|
||||
* An actor to draw a texture clipped to a list of rectangles
|
||||
*
|
||||
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "mutter-shaped-texture.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static void mutter_shaped_texture_dispose (GObject *object);
|
||||
static void mutter_shaped_texture_finalize (GObject *object);
|
||||
|
||||
static void mutter_shaped_texture_paint (ClutterActor *actor);
|
||||
static void mutter_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color);
|
||||
|
||||
static void mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex);
|
||||
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
G_DEFINE_TYPE (MutterShapedTexture, mutter_shaped_texture,
|
||||
CLUTTER_GLX_TYPE_TEXTURE_PIXMAP);
|
||||
#else /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
G_DEFINE_TYPE (MutterShapedTexture, mutter_shaped_texture,
|
||||
CLUTTER_X11_TYPE_TEXTURE_PIXMAP);
|
||||
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
|
||||
#define MUTTER_SHAPED_TEXTURE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_SHAPED_TEXTURE, \
|
||||
MutterShapedTexturePrivate))
|
||||
|
||||
struct _MutterShapedTexturePrivate
|
||||
{
|
||||
CoglHandle mask_texture;
|
||||
CoglHandle material;
|
||||
CoglHandle material_unshaped;
|
||||
#if 1 /* see workaround comment in mutter_shaped_texture_paint */
|
||||
CoglHandle material_workaround;
|
||||
#endif
|
||||
|
||||
GdkRegion *clip_region;
|
||||
|
||||
guint mask_width, mask_height;
|
||||
|
||||
GArray *rectangles;
|
||||
};
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_class_init (MutterShapedTextureClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
||||
|
||||
gobject_class->dispose = mutter_shaped_texture_dispose;
|
||||
gobject_class->finalize = mutter_shaped_texture_finalize;
|
||||
|
||||
actor_class->paint = mutter_shaped_texture_paint;
|
||||
actor_class->pick = mutter_shaped_texture_pick;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MutterShapedTexturePrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_init (MutterShapedTexture *self)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv;
|
||||
|
||||
priv = self->priv = MUTTER_SHAPED_TEXTURE_GET_PRIVATE (self);
|
||||
|
||||
priv->rectangles = g_array_new (FALSE, FALSE, sizeof (XRectangle));
|
||||
|
||||
priv->mask_texture = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_dispose (GObject *object)
|
||||
{
|
||||
MutterShapedTexture *self = (MutterShapedTexture *) object;
|
||||
MutterShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
mutter_shaped_texture_dirty_mask (self);
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_material_unref (priv->material);
|
||||
priv->material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
if (priv->material_unshaped != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_material_unref (priv->material_unshaped);
|
||||
priv->material_unshaped = COGL_INVALID_HANDLE;
|
||||
}
|
||||
#if 1 /* see comment in mutter_shaped_texture_paint */
|
||||
if (priv->material_workaround != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_material_unref (priv->material_workaround);
|
||||
priv->material_workaround = COGL_INVALID_HANDLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
mutter_shaped_texture_set_clip_region (self, NULL);
|
||||
|
||||
G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_finalize (GObject *object)
|
||||
{
|
||||
MutterShapedTexture *self = (MutterShapedTexture *) object;
|
||||
MutterShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
g_array_free (priv->rectangles, TRUE);
|
||||
|
||||
G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
if (priv->mask_texture != COGL_INVALID_HANDLE)
|
||||
{
|
||||
GLuint mask_gl_tex;
|
||||
GLenum mask_gl_target;
|
||||
|
||||
cogl_texture_get_gl_texture (priv->mask_texture,
|
||||
&mask_gl_tex, &mask_gl_target);
|
||||
|
||||
if (mask_gl_target == CGL_TEXTURE_RECTANGLE_ARB)
|
||||
glDeleteTextures (1, &mask_gl_tex);
|
||||
|
||||
cogl_texture_unref (priv->mask_texture);
|
||||
priv->mask_texture = COGL_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv = stex->priv;
|
||||
CoglHandle paint_tex;
|
||||
guint tex_width, tex_height;
|
||||
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
/* If the mask texture we have was created for a different size then
|
||||
recreate it */
|
||||
if (priv->mask_texture != COGL_INVALID_HANDLE
|
||||
&& (priv->mask_width != tex_width || priv->mask_height != tex_height))
|
||||
mutter_shaped_texture_dirty_mask (stex);
|
||||
|
||||
/* If we don't have a mask texture yet then create one */
|
||||
if (priv->mask_texture == COGL_INVALID_HANDLE)
|
||||
{
|
||||
guchar *mask_data;
|
||||
const XRectangle *rect;
|
||||
GLenum paint_gl_target;
|
||||
|
||||
/* Create data for an empty image */
|
||||
mask_data = g_malloc0 (tex_width * tex_height);
|
||||
|
||||
/* Cut out a hole for each rectangle */
|
||||
for (rect = (XRectangle *) priv->rectangles->data
|
||||
+ priv->rectangles->len;
|
||||
rect-- > (XRectangle *) priv->rectangles->data;)
|
||||
{
|
||||
gint x1 = rect->x, x2 = x1 + rect->width;
|
||||
gint y1 = rect->y, y2 = y1 + rect->height;
|
||||
guchar *p;
|
||||
|
||||
/* Clip the rectangle to the size of the texture */
|
||||
x1 = CLAMP (x1, 0, (gint) tex_width - 1);
|
||||
x2 = CLAMP (x2, x1, (gint) tex_width);
|
||||
y1 = CLAMP (y1, 0, (gint) tex_height - 1);
|
||||
y2 = CLAMP (y2, y1, (gint) tex_height);
|
||||
|
||||
/* Fill the rectangle */
|
||||
for (p = mask_data + y1 * tex_width + x1;
|
||||
y1 < y2;
|
||||
y1++, p += tex_width)
|
||||
memset (p, 255, x2 - x1);
|
||||
}
|
||||
|
||||
cogl_texture_get_gl_texture (paint_tex, NULL, &paint_gl_target);
|
||||
|
||||
if (paint_gl_target == CGL_TEXTURE_RECTANGLE_ARB)
|
||||
{
|
||||
GLuint tex;
|
||||
|
||||
glGenTextures (1, &tex);
|
||||
glBindTexture (CGL_TEXTURE_RECTANGLE_ARB, tex);
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, tex_width);
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
|
||||
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
|
||||
glTexImage2D (CGL_TEXTURE_RECTANGLE_ARB, 0,
|
||||
GL_ALPHA, tex_width, tex_height,
|
||||
0, GL_ALPHA, GL_UNSIGNED_BYTE, mask_data);
|
||||
|
||||
priv->mask_texture
|
||||
= cogl_texture_new_from_foreign (tex,
|
||||
CGL_TEXTURE_RECTANGLE_ARB,
|
||||
tex_width, tex_height,
|
||||
0, 0,
|
||||
COGL_PIXEL_FORMAT_A_8);
|
||||
}
|
||||
else
|
||||
priv->mask_texture = cogl_texture_new_from_data (tex_width, tex_height,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_A_8,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
tex_width,
|
||||
mask_data);
|
||||
|
||||
g_free (mask_data);
|
||||
|
||||
priv->mask_width = tex_width;
|
||||
priv->mask_height = tex_height;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_paint (ClutterActor *actor)
|
||||
{
|
||||
MutterShapedTexture *stex = (MutterShapedTexture *) actor;
|
||||
MutterShapedTexturePrivate *priv = stex->priv;
|
||||
CoglHandle paint_tex;
|
||||
guint tex_width, tex_height;
|
||||
ClutterActorBox alloc;
|
||||
CoglHandle material;
|
||||
#if 1 /* please see comment below about workaround */
|
||||
guint depth;
|
||||
#endif
|
||||
|
||||
if (priv->clip_region && gdk_region_empty (priv->clip_region))
|
||||
return;
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
|
||||
clutter_actor_realize (CLUTTER_ACTOR (stex));
|
||||
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
if (priv->rectangles->len < 1)
|
||||
{
|
||||
/* If there are no rectangles use a single-layer texture */
|
||||
|
||||
if (priv->material_unshaped == COGL_INVALID_HANDLE)
|
||||
priv->material_unshaped = cogl_material_new ();
|
||||
|
||||
material = priv->material_unshaped;
|
||||
}
|
||||
else
|
||||
{
|
||||
mutter_shaped_texture_ensure_mask (stex);
|
||||
|
||||
if (priv->material == COGL_INVALID_HANDLE)
|
||||
{
|
||||
priv->material = cogl_material_new ();
|
||||
|
||||
cogl_material_set_layer_combine (priv->material, 1,
|
||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
||||
NULL);
|
||||
}
|
||||
material = priv->material;
|
||||
|
||||
#if 1
|
||||
/* This was added as a workaround. It seems that with the intel
|
||||
* drivers when multi-texturing using an RGB TFP texture, the
|
||||
* texture is actually setup internally as an RGBA texture, where
|
||||
* the alpha channel is mostly 0.0 so you only see a shimmer of the
|
||||
* window. This workaround forcibly defines the alpha channel as
|
||||
* 1.0. Maybe there is some clutter/cogl state that is interacting
|
||||
* with this that is being overlooked, but for now this seems to
|
||||
* work. */
|
||||
g_object_get (stex, "pixmap-depth", &depth, NULL);
|
||||
if (depth == 24)
|
||||
{
|
||||
if (priv->material_workaround == COGL_INVALID_HANDLE)
|
||||
{
|
||||
material = priv->material_workaround = cogl_material_new ();
|
||||
|
||||
cogl_material_set_layer_combine (material, 0,
|
||||
"RGB = MODULATE (TEXTURE, PREVIOUS)"
|
||||
"A = REPLACE (PREVIOUS)",
|
||||
NULL);
|
||||
cogl_material_set_layer_combine (material, 1,
|
||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
||||
NULL);
|
||||
}
|
||||
|
||||
material = priv->material_workaround;
|
||||
}
|
||||
#endif
|
||||
|
||||
cogl_material_set_layer (material, 1, priv->mask_texture);
|
||||
}
|
||||
|
||||
cogl_material_set_layer (material, 0, paint_tex);
|
||||
|
||||
{
|
||||
CoglColor color;
|
||||
guchar opacity = clutter_actor_get_paint_opacity (actor);
|
||||
cogl_color_set_from_4ub (&color, opacity, opacity, opacity, opacity);
|
||||
cogl_material_set_color (material, &color);
|
||||
}
|
||||
|
||||
cogl_set_source (material);
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &alloc);
|
||||
|
||||
if (priv->clip_region)
|
||||
{
|
||||
GdkRectangle *rects;
|
||||
int n_rects;
|
||||
int i;
|
||||
|
||||
/* Limit to how many separate rectangles we'll draw; beyond this just
|
||||
* fall back and draw the whole thing */
|
||||
# define MAX_RECTS 16
|
||||
|
||||
/* Would be nice to be able to check the number of rects first */
|
||||
gdk_region_get_rectangles (priv->clip_region, &rects, &n_rects);
|
||||
if (n_rects > MAX_RECTS)
|
||||
{
|
||||
g_free (rects);
|
||||
/* Fall through to following code */
|
||||
}
|
||||
else
|
||||
{
|
||||
float coords[MAX_RECTS * 8];
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
GdkRectangle *rect = &rects[i];
|
||||
|
||||
coords[i * 8 + 0] = rect->x;
|
||||
coords[i * 8 + 1] = rect->y;
|
||||
coords[i * 8 + 2] = rect->x + rect->width;
|
||||
coords[i * 8 + 3] = rect->y + rect->height;
|
||||
coords[i * 8 + 4] = rect->x / (alloc.x2 - alloc.x1);
|
||||
coords[i * 8 + 5] = rect->y / (alloc.y2 - alloc.y1);
|
||||
coords[i * 8 + 6] = (rect->x + rect->width) / (alloc.x2 - alloc.x1);
|
||||
coords[i * 8 + 7] = (rect->y + rect->height) / (alloc.y2 - alloc.y1);
|
||||
}
|
||||
|
||||
g_free (rects);
|
||||
|
||||
cogl_rectangles_with_texture_coords (coords, n_rects);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cogl_rectangle (0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
MutterShapedTexture *stex = (MutterShapedTexture *) actor;
|
||||
MutterShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
/* If there are no rectangles then use the regular pick */
|
||||
if (priv->rectangles->len < 1)
|
||||
CLUTTER_ACTOR_CLASS (mutter_shaped_texture_parent_class)
|
||||
->pick (actor, color);
|
||||
else if (clutter_actor_should_pick_paint (actor))
|
||||
{
|
||||
CoglHandle paint_tex;
|
||||
ClutterActorBox alloc;
|
||||
guint tex_width, tex_height;
|
||||
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
mutter_shaped_texture_ensure_mask (stex);
|
||||
|
||||
cogl_set_source_color4ub (color->red, color->green, color->blue,
|
||||
color->alpha);
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &alloc);
|
||||
|
||||
/* Paint the mask rectangle in the given color */
|
||||
cogl_set_source_texture (priv->mask_texture);
|
||||
cogl_rectangle_with_texture_coords (0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1,
|
||||
0, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_shaped_texture_new (void)
|
||||
{
|
||||
ClutterActor *self = g_object_new (MUTTER_TYPE_SHAPED_TEXTURE, NULL);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
mutter_shaped_texture_clear_rectangles (MutterShapedTexture *stex)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
g_array_set_size (priv->rectangles, 0);
|
||||
mutter_shaped_texture_dirty_mask (stex);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
void
|
||||
mutter_shaped_texture_add_rectangle (MutterShapedTexture *stex,
|
||||
const XRectangle *rect)
|
||||
{
|
||||
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
mutter_shaped_texture_add_rectangles (stex, 1, rect);
|
||||
}
|
||||
|
||||
void
|
||||
mutter_shaped_texture_add_rectangles (MutterShapedTexture *stex,
|
||||
size_t num_rects,
|
||||
const XRectangle *rects)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
g_array_append_vals (priv->rectangles, rects, num_rects);
|
||||
|
||||
mutter_shaped_texture_dirty_mask (stex);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_shaped_texture_set_clip_region:
|
||||
* @frame: a #TidyTextureframe
|
||||
* @clip_region: (transfer full): the region of the texture that
|
||||
* is visible and should be painted. OWNERSHIP IS ASSUMED BY
|
||||
* THE FUNCTION (for efficiency to avoid a copy.)
|
||||
*
|
||||
* Provides a hint to the texture about what areas of the texture
|
||||
* are not completely obscured and thus need to be painted. This
|
||||
* is an optimization and is not supposed to have any effect on
|
||||
* the output.
|
||||
*
|
||||
* Typically a parent container will set the clip region before
|
||||
* painting its children, and then unset it afterwards.
|
||||
*/
|
||||
void
|
||||
mutter_shaped_texture_set_clip_region (MutterShapedTexture *stex,
|
||||
GdkRegion *clip_region)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->clip_region)
|
||||
{
|
||||
gdk_region_destroy (priv->clip_region);
|
||||
priv->clip_region = NULL;
|
||||
}
|
||||
|
||||
priv->clip_region = clip_region;
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* shaped texture
|
||||
*
|
||||
* An actor to draw a texture clipped to a list of rectangles
|
||||
*
|
||||
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __MUTTER_SHAPED_TEXTURE_H__
|
||||
#define __MUTTER_SHAPED_TEXTURE_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
#include <clutter/glx/clutter-glx.h>
|
||||
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
|
||||
#include <gdk/gdkregion.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define MUTTER_TYPE_SHAPED_TEXTURE \
|
||||
(mutter_shaped_texture_get_type())
|
||||
#define MUTTER_SHAPED_TEXTURE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE, \
|
||||
MutterShapedTexture))
|
||||
#define MUTTER_SHAPED_TEXTURE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE, \
|
||||
MutterShapedTextureClass))
|
||||
#define MUTTER_IS_SHAPED_TEXTURE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE))
|
||||
#define MUTTER_IS_SHAPED_TEXTURE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE))
|
||||
#define MUTTER_SHAPED_TEXTURE_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE, \
|
||||
MutterShapedTextureClass))
|
||||
|
||||
typedef struct _MutterShapedTexture MutterShapedTexture;
|
||||
typedef struct _MutterShapedTextureClass MutterShapedTextureClass;
|
||||
typedef struct _MutterShapedTexturePrivate MutterShapedTexturePrivate;
|
||||
|
||||
struct _MutterShapedTextureClass
|
||||
{
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
ClutterGLXTexturePixmapClass parent_class;
|
||||
#else
|
||||
ClutterX11TexturePixmapClass parent_class;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _MutterShapedTexture
|
||||
{
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
ClutterGLXTexturePixmap parent;
|
||||
#else
|
||||
ClutterX11TexturePixmap parent;
|
||||
#endif
|
||||
|
||||
MutterShapedTexturePrivate *priv;
|
||||
};
|
||||
|
||||
GType mutter_shaped_texture_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *mutter_shaped_texture_new (void);
|
||||
|
||||
void mutter_shaped_texture_clear_rectangles (MutterShapedTexture *stex);
|
||||
|
||||
void mutter_shaped_texture_add_rectangle (MutterShapedTexture *stex,
|
||||
const XRectangle *rect);
|
||||
void mutter_shaped_texture_add_rectangles (MutterShapedTexture *stex,
|
||||
size_t num_rects,
|
||||
const XRectangle *rects);
|
||||
|
||||
/* Assumes ownership of clip_region */
|
||||
void mutter_shaped_texture_set_clip_region (MutterShapedTexture *stex,
|
||||
GdkRegion *clip_region);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __MUTTER_SHAPED_TEXTURE_H__ */
|
@ -1,194 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#define _ISOC99_SOURCE /* for roundf */
|
||||
#include <math.h>
|
||||
|
||||
#include "mutter-window-private.h"
|
||||
#include "mutter-window-group.h"
|
||||
|
||||
struct _MutterWindowGroupClass
|
||||
{
|
||||
ClutterGroupClass parent_class;
|
||||
};
|
||||
|
||||
struct _MutterWindowGroup
|
||||
{
|
||||
ClutterGroup parent;
|
||||
|
||||
MetaScreen *screen;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MutterWindowGroup, mutter_window_group, CLUTTER_TYPE_GROUP);
|
||||
|
||||
/* We want to find out if the window is "close enough" to
|
||||
* 1:1 transform. We do that by converting the transformed coordinates
|
||||
* to 24.8 fixed-point before checking if they look right.
|
||||
*/
|
||||
static inline int
|
||||
round_to_fixed (float x)
|
||||
{
|
||||
return roundf (x * 256);
|
||||
}
|
||||
|
||||
/* We can only (easily) apply our logic for figuring out what a window
|
||||
* obscures if is not transformed. This function does that check and
|
||||
* as a side effect gets the position of the upper-left corner of the
|
||||
* actors.
|
||||
*
|
||||
* (We actually could handle scaled and non-integrally positioned actors
|
||||
* too as long as they weren't shaped - no filtering is done at the
|
||||
* edges so a rectangle stays a rectangle. But the gain from that is
|
||||
* small, especally since most of our windows are shaped. The simple
|
||||
* case we handle here is the case that matters when the user is just
|
||||
* using the desktop normally.)
|
||||
*
|
||||
* If we assume that the window group is untransformed (it better not
|
||||
* be!) then we could also make this determination by checking directly
|
||||
* if the actor itself is rotated, scaled, or at a non-integral position.
|
||||
* However, the criterion for "close enough" in that case get trickier,
|
||||
* since, for example, the allowed rotation depends on the size of
|
||||
* actor. The approach we take here is to just require everything
|
||||
* to be within 1/256th of a pixel.
|
||||
*/
|
||||
static gboolean
|
||||
actor_is_untransformed (ClutterActor *actor,
|
||||
int *x_origin,
|
||||
int *y_origin)
|
||||
{
|
||||
gfloat widthf, heightf;
|
||||
int width, height;
|
||||
ClutterVertex verts[4];
|
||||
int v0x, v0y, v1x, v1y, v2x, v2y, v3x, v3y;
|
||||
int x, y;
|
||||
|
||||
clutter_actor_get_size (actor, &widthf, &heightf);
|
||||
width = round_to_fixed (widthf); height = round_to_fixed (heightf);
|
||||
|
||||
clutter_actor_get_abs_allocation_vertices (actor, verts);
|
||||
v0x = round_to_fixed (verts[0].x); v0y = round_to_fixed (verts[0].y);
|
||||
v1x = round_to_fixed (verts[1].x); v1y = round_to_fixed (verts[1].y);
|
||||
v2x = round_to_fixed (verts[2].x); v2y = round_to_fixed (verts[2].y);
|
||||
v3x = round_to_fixed (verts[3].x); v3y = round_to_fixed (verts[3].y);
|
||||
|
||||
/* Using shifting for converting fixed => int, gets things right for
|
||||
* negative values. / 256. wouldn't do the same
|
||||
*/
|
||||
x = v0x >> 8;
|
||||
y = v0y >> 8;
|
||||
|
||||
/* At integral coordinates? */
|
||||
if (x * 256 != v0x || y * 256 != v0y)
|
||||
return FALSE;
|
||||
|
||||
/* Not scaled? */
|
||||
if (v1x - v0x != width || v2y - v0y != height)
|
||||
return FALSE;
|
||||
|
||||
/* Not rotated/skewed? */
|
||||
if (v0x != v2x || v0y != v1y ||
|
||||
v3x != v1x || v3y != v2y)
|
||||
return FALSE;
|
||||
|
||||
*x_origin = x;
|
||||
*y_origin = y;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_window_group_paint (ClutterActor *actor)
|
||||
{
|
||||
MutterWindowGroup *window_group = MUTTER_WINDOW_GROUP (actor);
|
||||
GdkRegion *visible_region;
|
||||
GdkRectangle screen_rect = { 0 };
|
||||
GList *children, *l;
|
||||
|
||||
/* We walk the list from top to bottom (opposite of painting order),
|
||||
* and subtract the opaque area of each window out of the visible
|
||||
* region that we pass to the windows below.
|
||||
*/
|
||||
children = clutter_container_get_children (CLUTTER_CONTAINER (actor));
|
||||
children = g_list_reverse (children);
|
||||
|
||||
/* Start off with the full screen area (for a multihead setup, we
|
||||
* might want to use a more accurate union of the monitors to avoid
|
||||
* painting in holes from mismatched monitor sizes. That's just an
|
||||
* optimization, however.)
|
||||
*/
|
||||
meta_screen_get_size (window_group->screen, &screen_rect.width, &screen_rect.height);
|
||||
visible_region = gdk_region_rectangle (&screen_rect);
|
||||
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
MutterWindow *cw;
|
||||
gboolean x, y;
|
||||
|
||||
if (!MUTTER_IS_WINDOW (l->data) || !CLUTTER_ACTOR_IS_VISIBLE (l->data))
|
||||
continue;
|
||||
|
||||
cw = l->data;
|
||||
|
||||
if (!actor_is_untransformed (CLUTTER_ACTOR (cw), &x, &y))
|
||||
continue;
|
||||
|
||||
/* Temporarily move to the coordinate system of the actor */
|
||||
gdk_region_offset (visible_region, - x, - y);
|
||||
|
||||
mutter_window_set_visible_region (cw, visible_region);
|
||||
|
||||
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (cw)) == 0xff)
|
||||
{
|
||||
GdkRegion *obscured_region = mutter_window_get_obscured_region (cw);
|
||||
if (obscured_region)
|
||||
gdk_region_subtract (visible_region, obscured_region);
|
||||
}
|
||||
|
||||
mutter_window_set_visible_region_beneath (cw, visible_region);
|
||||
gdk_region_offset (visible_region, x, y);
|
||||
}
|
||||
|
||||
gdk_region_destroy (visible_region);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (mutter_window_group_parent_class)->paint (actor);
|
||||
|
||||
/* Now that we are done painting, unset the visible regions (they will
|
||||
* mess up painting clones of our actors)
|
||||
*/
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
MutterWindow *cw;
|
||||
|
||||
if (!MUTTER_IS_WINDOW (l->data))
|
||||
continue;
|
||||
|
||||
cw = l->data;
|
||||
mutter_window_reset_visible_regions (cw);
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_window_group_class_init (MutterWindowGroupClass *klass)
|
||||
{
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
actor_class->paint = mutter_window_group_paint;
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_window_group_init (MutterWindowGroup *window_group)
|
||||
{
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_window_group_new (MetaScreen *screen)
|
||||
{
|
||||
MutterWindowGroup *window_group;
|
||||
|
||||
window_group = g_object_new (MUTTER_TYPE_WINDOW_GROUP, NULL);
|
||||
|
||||
window_group->screen = screen;
|
||||
|
||||
return CLUTTER_ACTOR (window_group);
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#ifndef MUTTER_WINDOW_PRIVATE_H
|
||||
#define MUTTER_WINDOW_PRIVATE_H
|
||||
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include "compositor-mutter.h"
|
||||
|
||||
MutterWindow *mutter_window_new (MetaWindow *window);
|
||||
|
||||
void mutter_window_destroy (MutterWindow *cw);
|
||||
|
||||
void mutter_window_show (MutterWindow *cw,
|
||||
MetaCompEffect effect);
|
||||
void mutter_window_hide (MutterWindow *cw,
|
||||
MetaCompEffect effect);
|
||||
|
||||
void mutter_window_maximize (MutterWindow *cw,
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
void mutter_window_unmaximize (MutterWindow *cw,
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
|
||||
void mutter_window_process_damage (MutterWindow *cw,
|
||||
XDamageNotifyEvent *event);
|
||||
void mutter_window_pre_paint (MutterWindow *self);
|
||||
|
||||
gboolean mutter_window_effect_in_progress (MutterWindow *cw);
|
||||
void mutter_window_sync_actor_position (MutterWindow *cw);
|
||||
void mutter_window_sync_visibility (MutterWindow *cw);
|
||||
void mutter_window_update_window_type (MutterWindow *cw);
|
||||
void mutter_window_update_shape (MutterWindow *cw,
|
||||
gboolean shaped);
|
||||
void mutter_window_update_opacity (MutterWindow *cw);
|
||||
void mutter_window_mapped (MutterWindow *cw);
|
||||
void mutter_window_unmapped (MutterWindow *cw);
|
||||
|
||||
GdkRegion *mutter_window_get_obscured_region (MutterWindow *cw);
|
||||
|
||||
void mutter_window_set_visible_region (MutterWindow *cw,
|
||||
GdkRegion *visible_region);
|
||||
void mutter_window_set_visible_region_beneath (MutterWindow *cw,
|
||||
GdkRegion *beneath_region);
|
||||
void mutter_window_reset_visible_regions (MutterWindow *cw);
|
||||
|
||||
void mutter_window_effect_completed (MutterWindow *actor,
|
||||
gulong event);
|
||||
|
||||
#endif /* MUTTER_WINDOW_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