Compare commits
714 Commits
3.12.2
...
3.11.92-wa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56e8c3b625 | ||
|
|
ce3d9fb89f | ||
|
|
27c018ab98 | ||
|
|
a1427c7130 | ||
|
|
91ad92c968 | ||
|
|
f0c7b518e6 | ||
|
|
5fa5ace5e6 | ||
|
|
044c06bff3 | ||
|
|
a3ccc4fd1c | ||
|
|
0a20f7458c | ||
|
|
9c94f8ae47 | ||
|
|
f940292cfe | ||
|
|
48a36356dd | ||
|
|
f05983be42 | ||
|
|
dfcefd3315 | ||
|
|
3fe755e684 | ||
|
|
0eb86de807 | ||
|
|
ff635bad3b | ||
|
|
43a409dec4 | ||
|
|
b087fce062 | ||
|
|
420f322910 | ||
|
|
4bf6e0ae8c | ||
|
|
97872e70a5 | ||
|
|
be57308663 | ||
|
|
33f1bd96f5 | ||
|
|
9ba49358e5 | ||
|
|
8b2b65246a | ||
|
|
4fdbb466e1 | ||
|
|
da48b18188 | ||
|
|
a5f1790828 | ||
|
|
6efcf2526d | ||
|
|
d6a27195d3 | ||
|
|
8f151842fb | ||
|
|
6f7023bc6b | ||
|
|
63b158e4da | ||
|
|
b3364cad3e | ||
|
|
3502cfba34 | ||
|
|
5cc6becb63 | ||
|
|
ae8f21a3dc | ||
|
|
0cdf3bd383 | ||
|
|
3de58189c0 | ||
|
|
5270c469a3 | ||
|
|
7504f16e59 | ||
|
|
cdb7947dd1 | ||
|
|
cdfc6f5b53 | ||
|
|
fcb2ab41b2 | ||
|
|
f5bd7c5f50 | ||
|
|
cb549154aa | ||
|
|
ada9610e30 | ||
|
|
f11bf44525 | ||
|
|
1f15c85c00 | ||
|
|
8b4c5459c0 | ||
|
|
d07d5d1328 | ||
|
|
535685742a | ||
|
|
62e45b6d5e | ||
|
|
3c6dd5bf6d | ||
|
|
0f85986340 | ||
|
|
93ac0329db | ||
|
|
c539dfe0d7 | ||
|
|
1502d2a79f | ||
|
|
a9d8107c3d | ||
|
|
a5d2c51392 | ||
|
|
d1ea17e6a4 | ||
|
|
b37ad66e9d | ||
|
|
c1f15348a5 | ||
|
|
857561baed | ||
|
|
a44cc9ef47 | ||
|
|
d47b7ba038 | ||
|
|
f21312e2fd | ||
|
|
394af33607 | ||
|
|
7314cdac94 | ||
|
|
81025e37ea | ||
|
|
1bb9f1e333 | ||
|
|
b11c75c1c9 | ||
|
|
757b626aee | ||
|
|
fb3df5243f | ||
|
|
e34792d9f0 | ||
|
|
f397c32192 | ||
|
|
f79314d7b5 | ||
|
|
55c61259d8 | ||
|
|
5298cf0a3a | ||
|
|
f1dc1a0cbc | ||
|
|
2cf80bc647 | ||
|
|
40c15f6e2a | ||
|
|
a8849621c9 | ||
|
|
49c0be11d6 | ||
|
|
9df8e831be | ||
|
|
84c6b2a3fa | ||
|
|
06cd669ccb | ||
|
|
81eb7d9537 | ||
|
|
dd8d8e436d | ||
|
|
d6b6b363ad | ||
|
|
254e2e993c | ||
|
|
c595a9c29f | ||
|
|
dfc7f7222b | ||
|
|
ef278eb547 | ||
|
|
38e26e5cc3 | ||
|
|
9773a879c3 | ||
|
|
abd2abcde6 | ||
|
|
a8f4651c72 | ||
|
|
54df7934ea | ||
|
|
9052efb0d9 | ||
|
|
b346f98eb0 | ||
|
|
365af53797 | ||
|
|
bee59ec0e1 | ||
|
|
91384a32b4 | ||
|
|
72bd5fb814 | ||
|
|
46af3ef9f6 | ||
|
|
d417c615d5 | ||
|
|
46cbd0bf48 | ||
|
|
f3b6fead4d | ||
|
|
80de8ec643 | ||
|
|
4f7e2a9f3f | ||
|
|
701e06d55d | ||
|
|
94f39a493f | ||
|
|
ddc171220a | ||
|
|
0313b38dd6 | ||
|
|
d41fba6558 | ||
|
|
770b58b367 | ||
|
|
77838c2ca3 | ||
|
|
e56cbfbd0f | ||
|
|
a27fb19473 | ||
|
|
674bcef6da | ||
|
|
86c1c30245 | ||
|
|
283546b379 | ||
|
|
98e3e5e50f | ||
|
|
b6a0d4d368 | ||
|
|
28859c604f | ||
|
|
9e51d98f4a | ||
|
|
268a4c92ba | ||
|
|
71367e14d5 | ||
|
|
5c99eae8a9 | ||
|
|
89aa5df711 | ||
|
|
b9a5d710b7 | ||
|
|
65dd54a4db | ||
|
|
b00fa70d91 | ||
|
|
360d423faa | ||
|
|
394b44a2c2 | ||
|
|
ed6821a819 | ||
|
|
23b0f7be43 | ||
|
|
7f195aec7a | ||
|
|
da13e3d237 | ||
|
|
75184d4c55 | ||
|
|
eb75306f8a | ||
|
|
98c4b82907 | ||
|
|
640102c03b | ||
|
|
c0d791cd6e | ||
|
|
41d5e69de5 | ||
|
|
2dc7371944 | ||
|
|
ec2c3e1438 | ||
|
|
c5c3806a04 | ||
|
|
ac0c7df4a3 | ||
|
|
d85845426c | ||
|
|
060e60f2a0 | ||
|
|
26cf75d5a4 | ||
|
|
9f5087e97d | ||
|
|
45624f2edf | ||
|
|
153f843ea6 | ||
|
|
f0cd9b0687 | ||
|
|
1783bf20ec | ||
|
|
9b24ae2033 | ||
|
|
0be4622e14 | ||
|
|
bcd5446cdc | ||
|
|
04b5232960 | ||
|
|
f860df4b2d | ||
|
|
ff8c4b1bcf | ||
|
|
337c69e223 | ||
|
|
14841475b5 | ||
|
|
7283fb320f | ||
|
|
020cfa7283 | ||
|
|
83aca0b53d | ||
|
|
0b055fae2e | ||
|
|
bc79259398 | ||
|
|
7ebf5aa69a | ||
|
|
7499621ecb | ||
|
|
4de3f7ca29 | ||
|
|
17462c21e8 | ||
|
|
c964ef4e01 | ||
|
|
0dccc440b6 | ||
|
|
48f7232492 | ||
|
|
ff5867e4d3 | ||
|
|
a5d950f453 | ||
|
|
7615d17293 | ||
|
|
374e30043b | ||
|
|
f771bb88d6 | ||
|
|
7ef8d21e48 | ||
|
|
c251eb8ec0 | ||
|
|
1e6b3faa83 | ||
|
|
e62fe956fd | ||
|
|
24c5290d7f | ||
|
|
00c8d3c897 | ||
|
|
cc13f8f65e | ||
|
|
47f4c9db7b | ||
|
|
4c621cc30f | ||
|
|
756a412436 | ||
|
|
be16c2fe71 | ||
|
|
a364c2a96b | ||
|
|
414259a7f8 | ||
|
|
283a81eac0 | ||
|
|
2a145262c7 | ||
|
|
57728b4322 | ||
|
|
ef24fb6296 | ||
|
|
86f057a712 | ||
|
|
dcd628d289 | ||
|
|
6038877c4c | ||
|
|
4e6321c239 | ||
|
|
304a525744 | ||
|
|
f26de405dd | ||
|
|
ed18580118 | ||
|
|
b65649186d | ||
|
|
515dc08a97 | ||
|
|
2e7a56a28f | ||
|
|
c485637a61 | ||
|
|
f9f2a82e18 | ||
|
|
2f4563132a | ||
|
|
e3a0f2c546 | ||
|
|
d39baeb8ad | ||
|
|
f27f6aab78 | ||
|
|
a66060e21a | ||
|
|
11aa3c030b | ||
|
|
bd1bec5617 | ||
|
|
d9659d4b36 | ||
|
|
d043d9943b | ||
|
|
a0ef7c7142 | ||
|
|
4efe4483fb | ||
|
|
aec3edb1cc | ||
|
|
0c5a6ad775 | ||
|
|
2be5401b1e | ||
|
|
f16e9b2ee7 | ||
|
|
06380938d4 | ||
|
|
87b20d7f2a | ||
|
|
593db0baee | ||
|
|
6b66553493 | ||
|
|
ddaae9c923 | ||
|
|
0c7a7d7527 | ||
|
|
6561b53346 | ||
|
|
def5e86673 | ||
|
|
0c213c8fee | ||
|
|
912a0abd26 | ||
|
|
d694260ad2 | ||
|
|
8566566451 | ||
|
|
0ce64e46e8 | ||
|
|
a8336669a3 | ||
|
|
f6db756326 | ||
|
|
27ab516f41 | ||
|
|
9542b464bf | ||
|
|
1ebaaa1950 | ||
|
|
71efbf0330 | ||
|
|
a6539463be | ||
|
|
b8e096db82 | ||
|
|
3e98ffaf99 | ||
|
|
0a9754f305 | ||
|
|
965a784c8a | ||
|
|
2db9f55669 | ||
|
|
3e73babaf7 | ||
|
|
66c4555dc7 | ||
|
|
183ad75603 | ||
|
|
66fc32ee14 | ||
|
|
d6396cf2c4 | ||
|
|
c9b7104117 | ||
|
|
6bf1a66b7c | ||
|
|
7e7b671b8e | ||
|
|
e04a55d1a2 | ||
|
|
8905bd2280 | ||
|
|
b09e1399c0 | ||
|
|
59c8b949ad | ||
|
|
6dbb3fddce | ||
|
|
f166240225 | ||
|
|
91b789c707 | ||
|
|
14db280fab | ||
|
|
f7097e6f66 | ||
|
|
ff89f1e271 | ||
|
|
6a8a4bfdcd | ||
|
|
cd35982d4e | ||
|
|
2f6f0f252c | ||
|
|
13651949ed | ||
|
|
fdeb72224c | ||
|
|
92e36e7076 | ||
|
|
d74796ee80 | ||
|
|
3e35cac67a | ||
|
|
1f7a6bf845 | ||
|
|
365442c1ff | ||
|
|
c8d185fc74 | ||
|
|
9567fa9c6a | ||
|
|
7a8de0c0af | ||
|
|
10fead9ba1 | ||
|
|
d5d5c2167a | ||
|
|
b9755ea725 | ||
|
|
39fee9f5a2 | ||
|
|
d6282716b2 | ||
|
|
60d9bee3bf | ||
|
|
a09fa3b0e4 | ||
|
|
9edff6f250 | ||
|
|
7d3012fd67 | ||
|
|
225e20a898 | ||
|
|
1a62ac9276 | ||
|
|
45cb151443 | ||
|
|
55b18f9671 | ||
|
|
4f4b1bfc37 | ||
|
|
9348c9bd4b | ||
|
|
16de7f66fb | ||
|
|
799c27484d | ||
|
|
c3b0faec82 | ||
|
|
9c876722a0 | ||
|
|
96fc93d744 | ||
|
|
20545941fa | ||
|
|
59f79e8294 | ||
|
|
ac32b9ef95 | ||
|
|
ba484be754 | ||
|
|
a318198ab4 | ||
|
|
e6391c2896 | ||
|
|
7ea537fad7 | ||
|
|
03146c2967 | ||
|
|
0a81314337 | ||
|
|
fa7a5782c6 | ||
|
|
e3b64912b6 | ||
|
|
a0fe392665 | ||
|
|
0e5f365d55 | ||
|
|
bfc906cbc4 | ||
|
|
8e6f8087e8 | ||
|
|
56207ddb6a | ||
|
|
8cb9cfb7b8 | ||
|
|
be698b597b | ||
|
|
1d61a0f9b5 | ||
|
|
788bd59857 | ||
|
|
2391606cc5 | ||
|
|
7155d7e043 | ||
|
|
419dfd333a | ||
|
|
b4535f2622 | ||
|
|
9b21346427 | ||
|
|
7b15d21e40 | ||
|
|
7b597b8c62 | ||
|
|
7a4adce44f | ||
|
|
a5f0db5ecb | ||
|
|
577624adef | ||
|
|
af46ef3b96 | ||
|
|
39d26be941 | ||
|
|
7bfc9109f7 | ||
|
|
becbad56ef | ||
|
|
384a34c27d | ||
|
|
002c5b8f87 | ||
|
|
1d3dbea20c | ||
|
|
ebe6e3180e | ||
|
|
a3de799939 | ||
|
|
0caf7381bb | ||
|
|
a42305edab | ||
|
|
732c059235 | ||
|
|
ef2b6e7d00 | ||
|
|
9c1b972ca1 | ||
|
|
cb33e1942a | ||
|
|
7009d1e470 | ||
|
|
c54a19825b | ||
|
|
8131f34eb6 | ||
|
|
f29241d90e | ||
|
|
bad48ea815 | ||
|
|
66af41f4a9 | ||
|
|
e30be380dd | ||
|
|
65f2e29375 | ||
|
|
98dbba1e17 | ||
|
|
422648e2eb | ||
|
|
f0fa4d831a | ||
|
|
1b600f5867 | ||
|
|
fd8cc9b7a8 | ||
|
|
ca5b5e6bc4 | ||
|
|
ee683ff187 | ||
|
|
57602adfe7 | ||
|
|
1481836ed6 | ||
|
|
309f78ff52 | ||
|
|
6436459381 | ||
|
|
65b39212d5 | ||
|
|
283649b8d7 | ||
|
|
fa65c380db | ||
|
|
58b39233f5 | ||
|
|
82066e02c5 | ||
|
|
c36aa5e696 | ||
|
|
29197d40c6 | ||
|
|
8d5ab6b5b3 | ||
|
|
a796938b39 | ||
|
|
3813113f1a | ||
|
|
1be117e430 | ||
|
|
622c7a021b | ||
|
|
4d2d2f285b | ||
|
|
0924c7d61b | ||
|
|
2746608eb2 | ||
|
|
fe26cb5989 | ||
|
|
602307e694 | ||
|
|
b2c18c4a78 | ||
|
|
1e211722c7 | ||
|
|
461f74ef18 | ||
|
|
3f022ca963 | ||
|
|
20e92c5a72 | ||
|
|
0850da44d7 | ||
|
|
37ba264190 | ||
|
|
6c12c928df | ||
|
|
9c5733caf0 | ||
|
|
21d8b8310a | ||
|
|
c46af91d54 | ||
|
|
d44574f738 | ||
|
|
a9424255a5 | ||
|
|
5089a63d76 | ||
|
|
f9a2c64460 | ||
|
|
7841042a85 | ||
|
|
ea1b8cdc22 | ||
|
|
52b48cfbef | ||
|
|
644f3e1275 | ||
|
|
304005e04f | ||
|
|
025ab35af7 | ||
|
|
a27744503b | ||
|
|
1011331caf | ||
|
|
0ccef81789 | ||
|
|
4780f74a40 | ||
|
|
57866fb267 | ||
|
|
d3bc7570d0 | ||
|
|
74e43a4702 | ||
|
|
0764b2058a | ||
|
|
7a787d7946 | ||
|
|
eec0f5df47 | ||
|
|
ba3968a822 | ||
|
|
762fa0e116 | ||
|
|
0be57b621b | ||
|
|
7d88b3593b | ||
|
|
858db7081a | ||
|
|
5af7f619c8 | ||
|
|
e5e35e5a7f | ||
|
|
6d639ac528 | ||
|
|
aa3643cdde | ||
|
|
8a3501ffe1 | ||
|
|
5ea443eb4b | ||
|
|
a37a8c6497 | ||
|
|
ebf6862a10 | ||
|
|
6c0e16c482 | ||
|
|
40b1e7312d | ||
|
|
1c0e6f26e2 | ||
|
|
f4fc498e65 | ||
|
|
a8632c2546 | ||
|
|
600a0f836f | ||
|
|
0ac142d39e | ||
|
|
abd368be00 | ||
|
|
a8ac2cc275 | ||
|
|
2f14b5cc3f | ||
|
|
2930612e64 | ||
|
|
2952d3671d | ||
|
|
1b5ace8256 | ||
|
|
2ebecc5370 | ||
|
|
02144d17e9 | ||
|
|
71496c8909 | ||
|
|
594b15abf1 | ||
|
|
bbe3641844 | ||
|
|
0cc5cf940b | ||
|
|
153d8efcf5 | ||
|
|
be744775c1 | ||
|
|
5959457c73 | ||
|
|
0824eb7c96 | ||
|
|
d945501be6 | ||
|
|
ca342c4573 | ||
|
|
4326d0bf3a | ||
|
|
a6ebc70170 | ||
|
|
3025cb7c48 | ||
|
|
17f48baf3a | ||
|
|
333661a9d8 | ||
|
|
b9da43b753 | ||
|
|
097ee776c7 | ||
|
|
a4a8f1f863 | ||
|
|
f36a627330 | ||
|
|
a1087c3f30 | ||
|
|
aad275b9a2 | ||
|
|
f0397eab94 | ||
|
|
392e224831 | ||
|
|
6867d44573 | ||
|
|
a841fff2ac | ||
|
|
26aa10a974 | ||
|
|
f6144082b1 | ||
|
|
957513242c | ||
|
|
17fd25e216 | ||
|
|
e91268a250 | ||
|
|
82cb4e8267 | ||
|
|
68eb87cc58 | ||
|
|
f3e52d5b18 | ||
|
|
2b2b2d3191 | ||
|
|
9461c612de | ||
|
|
f0280a8868 | ||
|
|
c749f7b6fb | ||
|
|
74462133ca | ||
|
|
7c45d6594c | ||
|
|
ea916b6c49 | ||
|
|
a02d734243 | ||
|
|
735b736110 | ||
|
|
bbbb9ac53c | ||
|
|
8dd97b4998 | ||
|
|
73a9082062 | ||
|
|
4091f5493d | ||
|
|
d96b053c9d | ||
|
|
1f569bef76 | ||
|
|
1a88176cc0 | ||
|
|
662c9729bc | ||
|
|
56a0dd6b2c | ||
|
|
9dc6028b3d | ||
|
|
932e913d88 | ||
|
|
b72315e27a | ||
|
|
3c7cd1f38c | ||
|
|
1946c548bf | ||
|
|
cf181fe109 | ||
|
|
63b9110f93 | ||
|
|
ae44bff0b1 | ||
|
|
23ba3e527f | ||
|
|
08df9bf559 | ||
|
|
648639fffe | ||
|
|
6cc014a941 | ||
|
|
b7b95123ed | ||
|
|
153463790a | ||
|
|
875bbec949 | ||
|
|
666e5f1f98 | ||
|
|
e6790038dd | ||
|
|
e86c53230f | ||
|
|
4ea4658abf | ||
|
|
58f6ab0a27 | ||
|
|
9c0cc664d1 | ||
|
|
84d26e31f1 | ||
|
|
64a848fcb7 | ||
|
|
429583ae8b | ||
|
|
93ae868987 | ||
|
|
72a900787f | ||
|
|
7186841db0 | ||
|
|
ab080e3e6b | ||
|
|
ad84aef766 | ||
|
|
7908eca579 | ||
|
|
237d990dea | ||
|
|
78fcfec5c1 | ||
|
|
1bd3a162f8 | ||
|
|
918cfdcbda | ||
|
|
cd76313297 | ||
|
|
dc8231c2cf | ||
|
|
4d01eb3a23 | ||
|
|
35f47b211d | ||
|
|
77046edf21 | ||
|
|
488df061c7 | ||
|
|
21d511e50f | ||
|
|
15e83f0c2f | ||
|
|
a23830fd13 | ||
|
|
c8bf8c17be | ||
|
|
d82e24981b | ||
|
|
01b8ffac5d | ||
|
|
1fa56bd7e0 | ||
|
|
c3f28b9cdb | ||
|
|
dc4e1d4cd1 | ||
|
|
d69553e8f5 | ||
|
|
0ead0d945a | ||
|
|
c24d9bf142 | ||
|
|
a6bf340ff8 | ||
|
|
35ef7c95b2 | ||
|
|
348f3007d9 | ||
|
|
52e2a1226e | ||
|
|
58622c0515 | ||
|
|
cb5e1e2776 | ||
|
|
e965cf32d4 | ||
|
|
ce5e0b20b5 | ||
|
|
90854a0f80 | ||
|
|
2d9dc143fc | ||
|
|
1e52d2aa9c | ||
|
|
2734c8547f | ||
|
|
cc0b093f7a | ||
|
|
d25275fa8d | ||
|
|
389e04c715 | ||
|
|
24074a81d0 | ||
|
|
c0e7f6d9bf | ||
|
|
9a13b857f4 | ||
|
|
776a86a65f | ||
|
|
76e2455d1b | ||
|
|
81d9797544 | ||
|
|
12d6c70000 | ||
|
|
a7eaf43e18 | ||
|
|
514fec7275 | ||
|
|
42a5f4f479 | ||
|
|
6c1feedbdf | ||
|
|
2d21fbbd35 | ||
|
|
7baf687499 | ||
|
|
a3e44d13d1 | ||
|
|
65db8efbe8 | ||
|
|
e48a5cd5f2 | ||
|
|
698bb24848 | ||
|
|
67fff237e6 | ||
|
|
b9247b4b2f | ||
|
|
0394b4a82b | ||
|
|
ff7c85c599 | ||
|
|
c316ad17a4 | ||
|
|
fc108d5052 | ||
|
|
8c0d38a1a1 | ||
|
|
2f9c6c4146 | ||
|
|
72ca2b218d | ||
|
|
7360aece74 | ||
|
|
b5f3238f6f | ||
|
|
227fb56103 | ||
|
|
5ae52473c9 | ||
|
|
7b537d6b8f | ||
|
|
4494888b82 | ||
|
|
004ee2d3b5 | ||
|
|
168ea64a45 | ||
|
|
73ee491281 | ||
|
|
95a9655412 | ||
|
|
72b6699efb | ||
|
|
3e341e83d9 | ||
|
|
5b3340e585 | ||
|
|
6f4f611ba8 | ||
|
|
450afbaf51 | ||
|
|
28708e4317 | ||
|
|
9f64f2cf4f | ||
|
|
2b1eb206d3 | ||
|
|
a6dc454c49 | ||
|
|
c2bf44fa19 | ||
|
|
2d67b01c3a | ||
|
|
6014d31dea | ||
|
|
bf78f067a2 | ||
|
|
ddb9929dad | ||
|
|
2098ec2d16 | ||
|
|
97eece6607 | ||
|
|
7ac9a6e241 | ||
|
|
b53bf0e8c2 | ||
|
|
a26ded47d9 | ||
|
|
cad9e14463 | ||
|
|
806d5939e3 | ||
|
|
0f0c23fbab | ||
|
|
5d1fcc26c0 | ||
|
|
cbe5b6b3bc | ||
|
|
590cf4e832 | ||
|
|
22ca820c44 | ||
|
|
b1206ceb66 | ||
|
|
ad4053ab84 | ||
|
|
7bd4e6ecb0 | ||
|
|
deeb1db1ac | ||
|
|
7eb4bfbea3 | ||
|
|
59b274f12f | ||
|
|
e311cef013 | ||
|
|
e72f81c24f | ||
|
|
96fa518576 | ||
|
|
e263b3624c | ||
|
|
1c34f0b342 | ||
|
|
2d27873f98 | ||
|
|
fd40a12213 | ||
|
|
57406e0a9e | ||
|
|
1987cbb764 | ||
|
|
705978405b | ||
|
|
daba05f6a7 | ||
|
|
1a7984be43 | ||
|
|
1b3c77d53a | ||
|
|
5b0f0d9e5b | ||
|
|
9816659fa9 | ||
|
|
3b1b611634 | ||
|
|
f08921bd0c | ||
|
|
0089b5769c | ||
|
|
452be05ea0 | ||
|
|
69f038f7c7 | ||
|
|
2d35e07fae | ||
|
|
95e2d26d03 | ||
|
|
f506e090ea | ||
|
|
0697b53826 | ||
|
|
7d9141c56f | ||
|
|
519a06b93d | ||
|
|
0cceddab75 | ||
|
|
c9830c13b4 | ||
|
|
9a4783e364 | ||
|
|
aa15c09d54 | ||
|
|
62d908be42 | ||
|
|
6526e9882b | ||
|
|
ab72352c47 | ||
|
|
f09b9573f0 | ||
|
|
3d3ae40f79 | ||
|
|
ea3d2b4759 | ||
|
|
542a0886cf | ||
|
|
bd3d5df9ce | ||
|
|
91cdfab495 | ||
|
|
1617323dca | ||
|
|
bbf9358eba | ||
|
|
9682a2aea4 | ||
|
|
c9fbb51775 | ||
|
|
aa6d887214 | ||
|
|
13312527de | ||
|
|
9bd366f2a6 | ||
|
|
5de346bfef | ||
|
|
2af20b77b6 | ||
|
|
9affbf10a6 | ||
|
|
c0acf3ae6d | ||
|
|
2c1b20e15f | ||
|
|
77290b6736 | ||
|
|
876f81db12 | ||
|
|
75f3ae14b5 | ||
|
|
d26f248b0f | ||
|
|
eeb3dfc991 | ||
|
|
e66db2eab3 | ||
|
|
2ae7454f36 | ||
|
|
4fd3c63da9 | ||
|
|
bfc87d13cb | ||
|
|
24564c77d6 | ||
|
|
18a21b67c2 | ||
|
|
3803fd9511 | ||
|
|
152d896f75 | ||
|
|
2f3a5f2001 | ||
|
|
0e098249b1 | ||
|
|
9a5f243f73 | ||
|
|
03f55b9485 | ||
|
|
ef9ef87d91 | ||
|
|
0ee2c21da7 | ||
|
|
9b966561c4 | ||
|
|
8c0779a9db | ||
|
|
2c901cc015 | ||
|
|
85e66f69fa | ||
|
|
a5585327dc | ||
|
|
268ebb1b18 | ||
|
|
40e820f551 | ||
|
|
f9a11b3b18 | ||
|
|
bd3c357212 | ||
|
|
b4d108dac6 | ||
|
|
6585a5760b | ||
|
|
531be6c413 | ||
|
|
f0c503b5a9 |
25
.gitignore
vendored
25
.gitignore
vendored
@@ -23,7 +23,7 @@ src/50-mutter-navigation.xml
|
||||
src/50-mutter-system.xml
|
||||
src/50-mutter-windows.xml
|
||||
src/mutter-wm.desktop
|
||||
src/mutter.desktop
|
||||
src/mutter-wayland.desktop
|
||||
*.o
|
||||
*.a
|
||||
*.lo
|
||||
@@ -46,16 +46,16 @@ POTFILES
|
||||
po/*.pot
|
||||
50-metacity-desktop-key.xml
|
||||
50-metacity-key.xml
|
||||
libmutter.pc
|
||||
mutter
|
||||
mutter-theme-viewer
|
||||
mutter.desktop
|
||||
libmutter-wayland.pc
|
||||
mutter-wayland
|
||||
mutter-launch
|
||||
org.gnome.mutter.gschema.valid
|
||||
org.gnome.mutter.gschema.xml
|
||||
org.gnome.mutter.wayland.gschema.valid
|
||||
org.gnome.mutter.wayland.gschema.xml
|
||||
testasyncgetprop
|
||||
testboxes
|
||||
testgradient
|
||||
m4/*
|
||||
mutter-grayscale
|
||||
mutter-mag
|
||||
mutter-message
|
||||
@@ -78,6 +78,12 @@ src/stamp-mutter-marshal.h
|
||||
src/meta-dbus-xrandr.[ch]
|
||||
src/meta-dbus-idle-monitor.[ch]
|
||||
src/mutter-plugins.pc
|
||||
src/gtk-shell-protocol.c
|
||||
src/gtk-shell-server-protocol.h
|
||||
src/xdg-shell-protocol.c
|
||||
src/xdg-shell-server-protocol.h
|
||||
src/xserver-protocol.c
|
||||
src/xserver-server-protocol.h
|
||||
doc/reference/*.args
|
||||
doc/reference/*.bak
|
||||
doc/reference/*.hierarchy
|
||||
@@ -95,3 +101,10 @@ doc/reference/meta-undocumented.txt
|
||||
doc/reference/meta-unused.txt
|
||||
doc/reference/meta-docs.sgml
|
||||
doc/reference/meta.types
|
||||
gtk-doc.m4
|
||||
intltool.m4
|
||||
libtool.m4
|
||||
ltoptions.m4
|
||||
ltsugar.m4
|
||||
ltversion.m4
|
||||
lt~obsolete.m4
|
||||
|
||||
159
COMPLIANCE
159
COMPLIANCE
@@ -1,159 +0,0 @@
|
||||
Metacity Standards Compliance
|
||||
=============================
|
||||
$Id$
|
||||
|
||||
1) Introduction
|
||||
2) EWMH Compliance
|
||||
a. Root Window Properties
|
||||
b. Root Window Messages
|
||||
c. Application Window Properties
|
||||
d. Window Manager Protocols
|
||||
3) ICCCM Compliance
|
||||
|
||||
1) Introduction
|
||||
---------------
|
||||
|
||||
This document details metacity compliance with the relevent standards.
|
||||
The format of this document is as follows:
|
||||
|
||||
[-/+?] Hint Name/Feature Name (Version number)
|
||||
Errata/Comments
|
||||
|
||||
The first character indicates the level of compliance as follows:
|
||||
- none
|
||||
/ partial
|
||||
+ complete
|
||||
? unknown
|
||||
|
||||
The title indicates a feature or a hint in the specification, and the
|
||||
version number indicates the minimum version of the specification
|
||||
supported by metacity. Later versions may be supported if no
|
||||
incompatible changes have been made in the specification.
|
||||
|
||||
2) EWMH Compliance
|
||||
------------------
|
||||
|
||||
The EWMH, or Extended Window Manager Hints is a freedesktop.org-
|
||||
developed standard to support a number of conventions for
|
||||
communication between the window manager and clients. It builds on
|
||||
and extends the ICCCM (See Section 3). A copy of the current EWMH
|
||||
standard is available at http://freedesktop.org/Standards/wm-spec/
|
||||
|
||||
a. Root Window Properties
|
||||
-------------------------
|
||||
|
||||
+ _NET_SUPPORTED (1.3)
|
||||
|
||||
+ _NET_CLIENT_LIST (1.3)
|
||||
|
||||
+ _NET_NUMBER_OF_DESKTOPS (1.3)
|
||||
|
||||
+ _NET_DESKTOP_GEOMETRY (1.3)
|
||||
Metacity does not implement large desktops, so this is kept set to
|
||||
the screen size.
|
||||
|
||||
+ _NET_DESKTOP_VIEWPORT (1.3)
|
||||
Metacity does not implement viewports, so this is a constant (0,0).
|
||||
|
||||
+ _NET_CURRENT_DESKTOP (1.3)
|
||||
|
||||
+ _NET_DESKTOP_NAMES (1.3)
|
||||
|
||||
+ _NET_ACTIVE_WINDOW (1.3)
|
||||
|
||||
+ _NET_WORKAREA (1.3)
|
||||
|
||||
+ _NET_SUPPORTING_WM_CHECK (1.3)
|
||||
|
||||
+ _NET_VIRTUAL_ROOTS (1.3)
|
||||
Metacity does not read or set this property, but it does not use
|
||||
virtual roots to implement virtual desktops, so it complies with the
|
||||
specification.
|
||||
|
||||
+ _NET_DESKTOP_LAYOUT (1.3)
|
||||
|
||||
+ _NET_SHOWING_DESKTOP (1.3)
|
||||
|
||||
b. Root Window Messages
|
||||
-----------------------
|
||||
|
||||
+ _NET_CLOSE_WINDOW (1.3)
|
||||
|
||||
- _NET_MOVERESIZE_WINDOW (1.3)
|
||||
Metacity supports this message, but the specification is unclear on
|
||||
the layout of the detail value, and as such it is #if 0'd in the code
|
||||
|
||||
+ _NET_WM_MOVERESIZE (1.3)
|
||||
|
||||
- _NET_RESTACK_WINDOW (1.3)
|
||||
Metacity will raise or lower windows in response to this message,
|
||||
but the sibling restack modes are not supported, and it is currently
|
||||
#if 0'd in the code.
|
||||
|
||||
+ _NET_REQUEST_FRAME_EXTENTS (1.3)
|
||||
|
||||
c. Application Window Properties
|
||||
--------------------------------
|
||||
|
||||
+ _NET_WM_NAME (1.3)
|
||||
|
||||
+ _NET_WM_VISIBLE_NAME (1.3)
|
||||
Metacity does not set this property, but metacity will never display
|
||||
a name different from _NET_WM_NAME
|
||||
|
||||
+ _NET_WM_ICON_NAME (1.3)
|
||||
|
||||
+ _NET_WM_VISIBLE_ICON_NAME (1.3)
|
||||
Metacity does not set this property, but metacity will never display
|
||||
a name different from _NET_WM_NAME
|
||||
|
||||
+ _NET_WM_DESKTOP (1.3)
|
||||
|
||||
+ _NET_WM_WINDOW_TYPE (1.3)
|
||||
|
||||
/ _NET_WM_STATE (1.3)
|
||||
This property is read and updated according to the specification,
|
||||
but see caveat below.
|
||||
Metacity does not recognize separate vertical and horizontal
|
||||
maximization states. Currently metacity will do a two-dimensional
|
||||
maximization if either property is set.
|
||||
See: http://bugzilla.gnome.org/show_bug.cgi?id=113601
|
||||
Metacity doesn't implement viewports so _NET_WM_STATE_STICKY is
|
||||
unimplemented.
|
||||
|
||||
+ _NET_WM_ALLOWED_ACTIONS (1.3)
|
||||
Metacity keeps this hint up to date. The code is somewhat crufty
|
||||
and should be rewritten, though it is functional.
|
||||
See: http://bugzilla.gnome.org/show_bug.cgi?id=90420
|
||||
|
||||
+ _NET_WM_STRUT (1.3)
|
||||
|
||||
+ _NET_WM_STRUT_PARTIAL (1.3)
|
||||
|
||||
+ _NET_WM_ICON_GEOMETRY (1.3)
|
||||
Metacity uses this property to draw minimize/restore animations
|
||||
|
||||
+ _NET_WM_ICON (1.3)
|
||||
|
||||
+ _NET_WM_PID (1.3)
|
||||
|
||||
+ _NET_WM_HANDLED_ICONS (1.3)
|
||||
Metacity does not read or set this property. However, metacity
|
||||
never manages iconified windows, and so has no need to do so.
|
||||
|
||||
+ _NET_WM_USER_TIME (1.3)
|
||||
Metacity uses this property to prevent applications from stealing
|
||||
focus if supported by the toolkit.
|
||||
|
||||
+ _NET_FRAME_EXTENTS (1.3)
|
||||
If set in response to a _NET_REQUEST_FRAME_EXTENTS message received
|
||||
prior to the window being mapped, this may be an estimate. This is,
|
||||
however, expressly allowed by the specification.
|
||||
|
||||
d. Window Manager Protocols
|
||||
---------------------------
|
||||
+ _NET_WM_PING (1.3)
|
||||
|
||||
3) ICCCM Compliance
|
||||
-------------------
|
||||
TODO
|
||||
298
HACKING
298
HACKING
@@ -1,298 +0,0 @@
|
||||
Intro...
|
||||
|
||||
Window managers have a few ways in which they are significantly different
|
||||
from other applications. This file, combined with the code overview in
|
||||
doc/code-overview.txt, should hopefully provide a series of relatively
|
||||
quick pointers (hopefully only a few minutes each) to some of the places
|
||||
one can look to orient themselves and get started. Some of this will be
|
||||
general to window managers on X, much will be specific to Metacity, and
|
||||
there's probably some information that's common to programs in general but
|
||||
is nonetheless useful.
|
||||
|
||||
Overview
|
||||
Administrative issues
|
||||
Minimal Building/Testing Environment
|
||||
Relevant standards and X properties
|
||||
Debugging and testing
|
||||
Debugging logs
|
||||
Adding information to the log
|
||||
Valgrind
|
||||
Testing Utilities
|
||||
Technical gotchas to keep in mind
|
||||
Other important reading
|
||||
Extra reading
|
||||
Ideas for tasks to work on
|
||||
|
||||
|
||||
Administrative issues
|
||||
Don't commit substantive code in here without asking hp@redhat.com.
|
||||
Adding translations, no-brainer typo fixes, etc. is fine.
|
||||
|
||||
The code could use cleanup in a lot of places, feel free to do so.
|
||||
|
||||
See http://developer.gnome.org/dotplan/for_maintainers.html for
|
||||
information on how to make a release. The only difference from those
|
||||
instructions is that the minor version number of a Metacity release
|
||||
should always be a number from the Fibonacci sequence.
|
||||
|
||||
Minimal Building/Testing Environment
|
||||
You do not need to _install_ a development version of Metacity to
|
||||
build, run and test it; you can run it from some temporary
|
||||
directory. Also, you do not need to build all of Gnome in order to
|
||||
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+ >= 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,
|
||||
pkg-config, intltool, and libtool) and be ready to build and test
|
||||
Metacity. Steps to do so:
|
||||
|
||||
$ svn checkout http://svn.gnome.org/svn/metacity/trunk metacity
|
||||
$ cd metacity
|
||||
$ ./autogen.sh --prefix /usr
|
||||
$ make
|
||||
$ ./src/metacity --replace
|
||||
|
||||
Again, note that you do not need to run 'make install'.
|
||||
|
||||
Relevant standards and X properties
|
||||
There are two documents that describe some basics about how window
|
||||
managers should behave: the ICCCM (Inter-Client Communication Conventions
|
||||
Manual) and EWMH (Extended Window Manager Hints). You can find these at
|
||||
the following locations:
|
||||
ICCCM - http://tronche.com/gui/x/icccm/
|
||||
EWMH - :pserver:anoncvs@pdx.freedesktop.org:/cvs
|
||||
The ICCCM is usually available in RPM or DEB format as well. There is
|
||||
actually an online version of the EWMH, but it is almost always woefully
|
||||
out of date. Just get it from cvs with these commands (the backslash
|
||||
means include the stuff from the next line):
|
||||
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/icccm-extensions login
|
||||
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/icccm-extensions \
|
||||
checkout wm-spec
|
||||
|
||||
DO NOT GO AND READ THOSE THINGS. THEY ARE REALLY, REALLY BORING.
|
||||
|
||||
If you do, you'll probably end up catching up on your sleep instead of
|
||||
hacking on Metacity. ;-) Instead, just look at the table of contents and
|
||||
glance at a page or two to get an idea of what's in there. Then only
|
||||
refer to it if you see something weird in the code and you don't know
|
||||
what it is but has some funny looking name like you see in one of those
|
||||
two documents.
|
||||
|
||||
You can refer to the COMPLIANCE file for additional information on these
|
||||
specifications and Metacity's compliance therewith.
|
||||
|
||||
One of the major things those documents cover that are useful to learn
|
||||
about immediately are X properties. The right way to learn about those,
|
||||
though, is through hand on experimentation with the xprop command (and
|
||||
then look up things you find from xprop in those two manuals if you're
|
||||
curious enough). First, try running
|
||||
xprop
|
||||
in a terminal and click on one of the windows on your screen. That gives
|
||||
you the x properties for that window. Look through them and get a basic
|
||||
idea of what's there for kicks. Note that you can get rid of some of the
|
||||
verboseness by grepping out the _NET_WM_ICON stuff, i.e.
|
||||
xprop | grep -v _NET_WM_ICON
|
||||
Next, try running
|
||||
xprop -root
|
||||
in a terminal. There's all the properties of the root window (which you
|
||||
can think of as the "main" Xserver window). You can also manually
|
||||
specify individual windows that you want the properties of with
|
||||
xprop -id <id>
|
||||
if you know the id of the window in question. You can get the id of a
|
||||
given window by either running xwininfo, e.g.
|
||||
xwininfo | grep "Window id" | cut -f 4 -d ' '
|
||||
or by looking at the _NET_CLIENT_STACKING property of the root
|
||||
window. Finally, it can also be useful to add "-spy" (without the
|
||||
quotes) to the xprop command to get it to continually monitor that
|
||||
window and report any changes to you.
|
||||
|
||||
Debugging information
|
||||
Trying to run a window manager under a typical debugger, such as gdb,
|
||||
unfortunately just doesn't work very well. So, we have to resort to
|
||||
other methods.
|
||||
|
||||
Debugging logs
|
||||
|
||||
First, note that you can start a new version of metacity to replace the
|
||||
existing one by running
|
||||
metacity --replace
|
||||
(which also comes in handy in the form "./src/metacity --replace" when
|
||||
trying to quickly test a small change while hacking on metacity without
|
||||
doing a full "make install", though I'm going off topic...) This will
|
||||
allow you to see any warnings printed at the terminal. Sometimes it's
|
||||
useful to have these directed to a logfile instead, which you can do by
|
||||
running
|
||||
METACITY_USE_LOGFILE=1 metacity --replace
|
||||
The logfile it uses will be printed in the terminal. Sometimes, it's
|
||||
useful to get more information than just warnings. You can set
|
||||
METACITY_VERBOSE to do that, like so:
|
||||
METACITY_VERBOSE=1 METACITY_USE_LOGFILE=1 metacity --replace
|
||||
(note that METACITY_VERBOSE=1 can be problematic without
|
||||
METACITY_USE_LOGFILE=1; avoid it unless running in from something that
|
||||
won't be managed by the new Metacity--see bug 305091 for more details).
|
||||
There are also other flags, such as METACITY_DEBUG, most of which I
|
||||
haven't tried and don't know what they do. Go to the source code
|
||||
directory and run
|
||||
grep "METACITY_" * | grep getenv
|
||||
to find out what the other ones are.
|
||||
|
||||
Adding information to the log
|
||||
|
||||
Since we can't single step with a debugger, we often have to fall back to
|
||||
the primitive method of getting information we want to know: adding
|
||||
"print" statements. Metacity has a fairly structured way to do this,
|
||||
using the functions meta_warning, meta_topic, and meta_verbose. All
|
||||
three have the same basic format as printf, except that meta_topic also
|
||||
takes a leading enumeration parameter to specify the type of message
|
||||
being shown (makes it easier for grepping in a verbose log). You'll find
|
||||
tons of examples in the source code if you need them; just do a quick
|
||||
grep or look in most any file. Note that meta_topic and meta_verbose
|
||||
messages only appear if verbosity is turned on. I tend to frequently add
|
||||
temporary meta_warning statements (or switch meta_topic or meta_verbose
|
||||
ones to meta_warning ones) and then undo the changes once I've learned
|
||||
the info that I needed.
|
||||
|
||||
There is also a meta_print_backtrace (which again is only active if
|
||||
verbosity is turned on) that can also be useful if you want to learn how
|
||||
a particular line of code gets called. And, of course, there's always
|
||||
g_assert if you want to make sure some section isn't executed (or isn't
|
||||
executed under certain conditions).
|
||||
|
||||
Valgrind
|
||||
|
||||
Valgrind is awesome for finding memory leaks or corruption and
|
||||
uninitialized variables. But I also tend to use it in a non-traditional
|
||||
way as a partial substitute for a normal debugger: it can provide me with
|
||||
a stack trace of where metacity is crashing if I made a change that
|
||||
caused it to do so, which is one of the major uses of debuggers. (And,
|
||||
what makes it cooler than a debugger is that there will also often be
|
||||
warnings pinpointing the cause of the crash from either some kind of
|
||||
simple memory corruption or an uninitialized variable). Sometimes, when
|
||||
I merely want to know what is calling a particular function I'll just
|
||||
throw in an "int i; printf("%d\n", i);" just because valgrind will give
|
||||
me a full stacktrace whenever it sees that uninitialized variable being
|
||||
used (yes, I could use meta_print_backtrace, but that means I have to
|
||||
turn verbosity on).
|
||||
|
||||
To run metacity under valgrind, use options typical for any Gnome
|
||||
program, such as
|
||||
valgrind --log-file=metacity.log --tool=memcheck --num-callers=48 \
|
||||
--leak-check=yes --leak-resolution=high --show-reachable=yes \
|
||||
./src/metacity --replace
|
||||
where, again, the backslashes mean to join all the stuff on the following
|
||||
line with the previous one.
|
||||
|
||||
However, there is a downside. Things run a little bit slowly, and it
|
||||
appears that you'll need about 1.5GB of ram, which unfortunately prevents
|
||||
most people from trying this.
|
||||
|
||||
Testing Utilities
|
||||
|
||||
src/run-metacity.sh
|
||||
The script src/run-metacity.sh is useful to hack on the window manager.
|
||||
It runs metacity in an Xnest. e.g.:
|
||||
CLIENTS=3 ./run-metacity.sh
|
||||
or
|
||||
DEBUG=memprof ./run-metacity.sh
|
||||
or
|
||||
DEBUG_TEST=1 ./run-metacity-sh
|
||||
or whatever.
|
||||
|
||||
metacity-message
|
||||
The tool metacity-message can be used as follows:
|
||||
metacity-message reload-theme
|
||||
metacity-message restart
|
||||
metacity-message enable-keybindings
|
||||
metacity-message disable-keybindings
|
||||
The first of these is useful for testing themes, the second is just
|
||||
another way (besides the --restart flag to metacity itself) of
|
||||
restarting metacity, and the third is useful for testing Metacity when
|
||||
running it under an Xnest (typically, the Metacity under the Xnest
|
||||
wouldn't get keybinding notifications--making keyboard navigation not
|
||||
work--but if you disable the keybindings for the global Metacity then
|
||||
the Metacity under the Xnest can then get those keybinding notifications).
|
||||
|
||||
metacity-window-demo
|
||||
metacity-window-demo is good for trying behavior of various kinds
|
||||
of window without launching a full desktop.
|
||||
|
||||
Technical gotchas to keep in mind
|
||||
Files that include gdk.h or gtk.h are not supposed to include
|
||||
display.h or window.h or other core files. Files in the core
|
||||
(display.[hc], window.[hc]) are not supposed to include gdk.h or
|
||||
gtk.h. Reasons:
|
||||
|
||||
"Basically you don't want GDK most of the time. It adds
|
||||
abstractions that cause problems, because they aren't designed to
|
||||
be used in a WM where we do weird stuff (display grabs, and just
|
||||
being the WM). At best GDK adds inefficiency, at worst it breaks
|
||||
things in weird ways where you have to be a GDK guru to figure
|
||||
them out. Owen also told me that they didn't want to start adding
|
||||
a lot of hacks to GDK to let a WM use it; we both agreed back in
|
||||
the mists of time that metacity would only use it for the "UI"
|
||||
bits as it does.
|
||||
|
||||
Having the split in the source code contains and makes very clear
|
||||
the interface between the WM and GDK/GTK. This keeps people from
|
||||
introducing extra GDK/GTK usage when it isn't needed or
|
||||
appropriate. Also, it speeds up the compilation a bit, though this
|
||||
was perhaps more relevant 5 years ago than it is now.
|
||||
|
||||
There was also a very old worry that the GDK stuff might have to
|
||||
be in a separate process to work right; that turned out to be
|
||||
untrue. Though who knows what issues the CM will introduce."
|
||||
|
||||
Remember that strings stored in X properties are not in UTF-8, and they
|
||||
have to end up in UTF-8 before we try putting them through Pango.
|
||||
|
||||
If you make any X request involving a client window, you have to
|
||||
meta_error_trap_push() around the call; this is not necessary for X
|
||||
requests on the frame windows.
|
||||
|
||||
Remember that not all windows have frames, and window->frame can be NULL.
|
||||
|
||||
Other important reading & where to get started
|
||||
Extra reading
|
||||
|
||||
There are some other important things to read to get oriented as well.
|
||||
These are:
|
||||
http://pobox.com/~hp/features.html
|
||||
rationales.txt
|
||||
doc/code-overview.txt
|
||||
|
||||
It pays to read http://pobox.com/~hp/features.html in order
|
||||
to understand the philosophy of Metacity.
|
||||
|
||||
The rationales.txt file has two things: (1) a list of design choices with
|
||||
links in the form of bugzilla bugs that discuss the issue, and (2) a list
|
||||
outstanding bug categories, each of which is tracked by a particular
|
||||
tracker bug in bugzilla from which you can find several closely related
|
||||
bug reports.
|
||||
|
||||
doc/code-overview.txt provides a fairly good overview of the code,
|
||||
including coverage of the function of the various files, the main
|
||||
structures and their relationships, and places to start looking in the
|
||||
code tailored to general categories of tasks.
|
||||
|
||||
Ideas for tasks to work on
|
||||
|
||||
There are a variety of things you could work on in the code. You may
|
||||
have ideas of your own, but in case you don't, let me provide a list of
|
||||
ideas you could choose from:
|
||||
|
||||
If you're ambitious, there's a list of things Havoc made that he'd really
|
||||
like to see tackled, which you can find at
|
||||
http://log.ometer.com/2004-05.html. Be sure to double check with someone
|
||||
to make sure the item is still relevant if you're interested in one of
|
||||
these. Another place to look for ideas, of course, is bugzilla. One can
|
||||
just do queries and look for things that look fixable.
|
||||
|
||||
However, perhaps the best way of getting ideas of related tasks to work
|
||||
on, is to look at the second half of the rationales.txt file, which tries
|
||||
to group bugs by type.
|
||||
@@ -1,8 +0,0 @@
|
||||
Tomas Frydrych
|
||||
Email: tf linux intel com
|
||||
Userid: tomasf
|
||||
|
||||
Owen Taylor
|
||||
Email: otaylor redhat com
|
||||
Userid: otaylor
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
Currently active maintainers
|
||||
--------------------------------
|
||||
|
||||
Elijah Newren
|
||||
Email: newren gmail com
|
||||
Userid: newren
|
||||
|
||||
- Usually won't touch the theme bugs (isn't interested) or the
|
||||
compositor (until open source nvidia drivers are up to snuff).
|
||||
Tends to be most interested in libwnck/gtk interactions, focus
|
||||
issues, constraints problems, and raising/stacking, but works on
|
||||
just about anything other than themes and the compositor.
|
||||
|
||||
Thomas Thurman
|
||||
Email: thomas thurman org uk
|
||||
Userid: tthurman
|
||||
|
||||
- Responsible for all theme bugs and the compositor (thank goodness
|
||||
Thomas got involved, eh?). I'm sure he'll replace this sentence
|
||||
with his interests when he reads it. ;-)
|
||||
|
||||
|
||||
Semi-active maintainers
|
||||
--------------------------------
|
||||
|
||||
Havoc Pennington
|
||||
Email: hp redhat com
|
||||
Userid: hp
|
||||
- Original author. Doesn't patch metacity anymore, but is active in
|
||||
answering questions, responding to bugs, providing very helpful
|
||||
suggestions and insight, and even assisting with debugging.
|
||||
|
||||
|
||||
Important historical figureheads
|
||||
--------------------------------
|
||||
|
||||
Rob Adams (readams readams net)
|
||||
- Was the main maintainer of metacity for a while; particular areas
|
||||
of focus included xinerama, placement, and an older version of the
|
||||
constraints code. Still responds to bugs every once in a while.
|
||||
|
||||
Søren Sandmann (sandmann redhat com)
|
||||
- Wrote most of the current compositing manager code + libcm
|
||||
@@ -1,10 +1,6 @@
|
||||
|
||||
SUBDIRS=src po doc
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
|
||||
EXTRA_DIST = HACKING MAINTAINERS rationales.txt
|
||||
|
||||
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
|
||||
|
||||
187
NEWS
187
NEWS
@@ -1,46 +1,13 @@
|
||||
3.12.2
|
||||
======
|
||||
* Fix in-fullscreen state when moving between monitors [Florian; #728395]
|
||||
* Fix crash when monitors change during suspend [Giovanni; #725637]
|
||||
* Misc. bug fixes [Florian, Giovanni; #728423, #729732]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Florian Müllner
|
||||
|
||||
Translations:
|
||||
Christian Kirbach [de], Pau Iranzo [ca]
|
||||
|
||||
3.12.1
|
||||
======
|
||||
* Fix opacity values from _NET_WM_WINDOW_OPACITY [Nirbheek; #727874]
|
||||
* Misc. cleanups [Jasper; #720631]
|
||||
|
||||
Contributors:
|
||||
Nirbheek Chauhan, Jasper St. Pierre
|
||||
|
||||
Translations:
|
||||
Inaki Larranaga Murgoitio [eu], marablack3 [el]
|
||||
|
||||
3.12.0
|
||||
======
|
||||
|
||||
Translations:
|
||||
Ask H. Larsen [da], Мирослав Николић [sr, sr@latin], Andika Triwidada [id],
|
||||
Daniel Korostil [uk], Petr Kovar [cs]
|
||||
|
||||
3.11.92
|
||||
=======
|
||||
* Fix identification of CSD windows [Owen; #723029]
|
||||
* Add minimal handling of touch events [Carlos; #723552]
|
||||
* Misc bug fixes and cleanups [Owen, Adel, Jasper; #723580, #726352]
|
||||
* Update keyboard state unconditionally [Rui; #722847]
|
||||
* Misc bug fixes and cleanups [Owen, Rui, Giovanni, Matthias, Adel, Ryan,
|
||||
Jasper, Marek, Florian; #723580, #726123, #726683]
|
||||
|
||||
Contributors:
|
||||
Adel Gadllah, Carlos Garnacho, Rui Matos, Jasper St. Pierre, Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Changwoo Ryu [ko], Rūdolfs Mazurs [lv], Wylmer Wang [zh_CN],
|
||||
Chao-Hsiung Liao [zh_HK, zh_TW], Yuri Myasoedov [ru], Tiagosdot [pt],
|
||||
Claude Paroz [fr], Duarte Loreto [pt], A S Alam [pa]
|
||||
Giovanni Campagna, Marek Chalupa, Matthias Clasen, Adel Gadllah, Ryan Lortie,
|
||||
Rui Matos, Florian Müllner, Jasper St. Pierre, Owen W. Taylor
|
||||
|
||||
3.11.91
|
||||
=======
|
||||
@@ -49,125 +16,104 @@ Translations:
|
||||
* Improve keybinding lookups [Rui; #725588]
|
||||
* Fix dynamic updates of titlebar style properties [Owen; #725751]
|
||||
* Fix positioning of manually positioned windows [Owen; #724049]
|
||||
* Misc. bug fixes [Carlos, Giovanni, Florian, Jasper; #724969, #724402, #722266,
|
||||
#725338]
|
||||
* Misc bug fixes and cleanups [Jasper, Carlos, Adel, Giovanni, Florian; #720631,
|
||||
#724969, #725216, #724402, #722266, #725338, #725525]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
|
||||
Jasper St. Pierre
|
||||
|
||||
Translations:
|
||||
Aurimas Černius [lt], Milo Casagrande [it], Balázs Úr [hu],
|
||||
Matej Urbančič [sl], Enrico Nicoletto [pt_BR], Yosef Or Boczko [he],
|
||||
Piotr Drąg [pl], Fran Diéguez [gl]
|
||||
Jasper St. Pierre, Owen W. Taylor
|
||||
|
||||
3.11.90
|
||||
=======
|
||||
* Use correct output property for backlight control [Robert; #723606]
|
||||
* Fix double-scaling on high DPI resolutions [Adel; #723931]
|
||||
* Make tile previews a compositor effect [Stefano, Florian; #665758]
|
||||
* Misc. bug fixes and cleanups [Ryan, Giovanni, Jasper; #722530, #724257,
|
||||
#724258, #724364, #720631, #707851, #707897]
|
||||
* Misc. bug fixes and cleanups [Ryan, Giovanni, Jasper, Adel; #722530, #724257,
|
||||
#724258, #720631, #724364, #724472]
|
||||
|
||||
Contributors:
|
||||
Robert Ancell, Giovanni Campagna, Stefano Facchini, Adel Gadllah,
|
||||
Giovanni Campagna, Marek Chalupa, Stefano Facchini, Adel Gadllah,
|
||||
Ryan Lortie, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz
|
||||
|
||||
Translations:
|
||||
Shankar Prasad [kn], Khaled Hosny [ar], Marek Černocký [cs],
|
||||
Kjartan Maraas [nb], Daniel Korostil [uk]
|
||||
|
||||
3.11.5
|
||||
======
|
||||
* Fix CSD titlebars being placed off-screen [Jasper; #719772]
|
||||
* Add support for subsurfaces [Jonas; #705502]
|
||||
* Expose MetaWindow:skip-taskbar property [Florian; #723307]
|
||||
* Fix legacy tray icons showing up blank [Adel; #721596]
|
||||
* Fix configuration of cloned monitors [Adel; #710610]
|
||||
* Misc bug fixes and cleanups [Jasper, Adel, Jonas; #720631, #723468, #723563]
|
||||
* Misc bug fixes and cleanups [Jasper, Adel, Marek, Jonas; #720631, #723468,
|
||||
#720818, #723563, #723564]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Marek Ch, Adel Gadllah, Florian Müllner, Jasper St. Pierre
|
||||
|
||||
Translations:
|
||||
Rafael Ferreira [pt_BR], Enrico Nicoletto [pt_BR], Fran Diéguez [gl],
|
||||
Chao-Hsiung Liao [zh_HK, zh_TW]
|
||||
|
||||
3.11.4
|
||||
======
|
||||
* Don't leave focus on windows that are being unmanaged [Owen; #711618]
|
||||
* Reduce server grabs [Daniel Drake; #721345, #721709]
|
||||
* Improve heuristic to determine display output name [Cosimo Cecchi; #721674]
|
||||
* Atomically unmaximize both directions [Jasper; #722108]
|
||||
* Misc bug fixes [Debarshi, Andika; #721517, #721674]
|
||||
* Misc bug fixes [Debarshi, Andika, Florian; #721517, #721674, #722347]
|
||||
|
||||
Contributors:
|
||||
Cosimo Cecchi, Daniel Drake, Debarshi Ray, Jasper St. Pierre,
|
||||
Cosimo Cecchi, Daniel Drake, Florian Müllner, Debarshi Ray, Jasper St. Pierre,
|
||||
Andika Triwidada, Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Rafael Ferreira [pt_BR], Dimitris Spingos [el], Daniel Mustieles [es],
|
||||
Milo Casagrande [it], Yosef Or Boczko [he]
|
||||
|
||||
3.11.3
|
||||
======
|
||||
* xrandr: Use "hotplug_mode_update" property [Marc-André; #711216]
|
||||
* Fix position of attached dialogs for CSD windows [Giovanni, Owen; #707194]
|
||||
* Fix focus issues with external OSKs [Jasper; #715030]
|
||||
* Fix focus issues with external OSKs[Jasper; #715030]
|
||||
* Add a MetaCullable interface [Jasper; #714706]
|
||||
* Fix window keybindings [Rui; #719724]
|
||||
* Fix settings keyboard/pointer focus for new clients [Rui; #719725]
|
||||
* Fix window group paint volume [Owen; #719669]
|
||||
* Fix frame extents problems [Owen; #714707]
|
||||
* Add shortcut to move windows between monitors [Florian; #671054]
|
||||
* Fix problems with focus tracking [Owen; #720558]
|
||||
* Misc. bug fixes and cleanups [Rui, Jasper, Owen; #712833, #678989, #720106,
|
||||
#720417, #720630]
|
||||
* Misc. bug fixes and cleanups: [Rui, Colin, Lionel, Jasper, Owen; #712833,
|
||||
#719557, #719695, #719833, #678989, #720417, #720630]
|
||||
|
||||
Contributors:
|
||||
Robert Bragg, Giovanni Campagna, Marc-André Lureau, Rui Matos, Alberto Milone,
|
||||
Florian Müllner, Sindhu S, Jasper St. Pierre, Rico Tzschichholz,
|
||||
Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
甘露(Gan Lu) [zh_CN], Khaled Hosny [ar]
|
||||
Lionel Landwerlin, Rui Matos, Alberto Milone, Florian Müllner,
|
||||
Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor, Colin Walters
|
||||
|
||||
3.11.2
|
||||
======
|
||||
* Support setting a NULL opaque region [Andreas; #711518]
|
||||
* Sync keymap from X to wayland [Giovanni; #707446]
|
||||
* Implement support for subsurfaces [Jonas; #705502]
|
||||
* Don't focus the no-focus-window for globally active windows [Jasper; #710296]
|
||||
* Support "hotplug_mode_update" property [Marc-André; #711216]
|
||||
* Fix resize operations using mouse-button-modifier [Lionel; #710251]
|
||||
* Misc. fixes and cleanups [Jasper, Rico, Florian; #711731]
|
||||
* Fix position of attached modals for CSD windows [Giovanni, Owen; #707194]
|
||||
* Misc. bug fixes [Rui, Jasper, Neil, Florian; #712247, #711731]
|
||||
|
||||
Contributors:
|
||||
Lionel Landwerlin, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz
|
||||
Giovanni Campagna, Andreas Heider, Lionel Landwerlin, Marc-André Lureau,
|
||||
Rui Matos, Florian Müllner, Neil Roberts, Sindhu S, Jasper St. Pierre,
|
||||
Rico Tzschichholz, Owen W. Taylor, Jonas Ådahl
|
||||
|
||||
3.11.1
|
||||
======
|
||||
* Don't require at least one output device to be connected [Giovanni; #709009]
|
||||
* Name the guard window [Andrew; #710346]
|
||||
* Fix tile previews getting stuck on right click during drags [Lionel; #704759]
|
||||
* Use new UPower API [Bastien]
|
||||
* Set hot spot when cursor set from wl_buffer [Jonas; #709593]
|
||||
* Expose min-backlight-step [Asad; #710380]
|
||||
* Don't focus the no-focus-window for globally active windows [Jasper; #710296]
|
||||
* Misc. fixes and cleanups [Jasper, Rico, Olav, Magdalen; #709776]
|
||||
* Misc. bug fixes and cleanups [Jasper, Olav, Magdalen; #709776]
|
||||
|
||||
Contributors:
|
||||
Magdalen Berns, Giovanni Campagna, Asad Mehmood, Bastien Nocera,
|
||||
Jasper St. Pierre, Rico Tzschichholz, Olav Vitters, Andrew Walton
|
||||
|
||||
Translations:
|
||||
Reinout van Schouwen [nl]
|
||||
Magdalen Berns, Lionel Landwerlin, Asad Mehmood, Bastien Nocera,
|
||||
Jasper St. Pierre, Olav Vitters, Jonas Ådahl
|
||||
|
||||
3.10.1
|
||||
======
|
||||
* Don't apply fullscreen workarounds to CSD windows [Giovanni; #708718]
|
||||
* Fix hangs during DND operations [Adel; #709340]
|
||||
* Use nearest-pixel interpolation when possible [Hans; #708389]
|
||||
* Fix tile previews getting stuck on right click during drags [Lionel; #704759]
|
||||
* Misc bug fixes [Giovanni, Jasper; #708420]
|
||||
* Misc bug fixes [Dan, Giovanni, Jasper; #708813, #708420]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Adel Gadllah, Lionel Landwerlin, Hans Petter Jansson,
|
||||
Giovanni Campagna, Adel Gadllah, Dan Horák, Hans Petter Jansson,
|
||||
Jasper St. Pierre
|
||||
|
||||
Translations:
|
||||
Khaled Hosny [ar], Reinout van Schouwen [nl], Carles Ferrando [ca@valencia]
|
||||
|
||||
3.10.0.1
|
||||
========
|
||||
* Fix bug when a window changed size twice in a single frame - this
|
||||
@@ -178,24 +124,32 @@ Contributors:
|
||||
|
||||
3.10.0
|
||||
======
|
||||
|
||||
Translations:
|
||||
Ask H. Larsen [da], Gabor Kelemen [hu], Duarte Loreto [pt],
|
||||
Yosef Or Boczko [he]
|
||||
* Update dependencies [Giovanni; #708210]
|
||||
|
||||
3.9.92
|
||||
======
|
||||
* Don't create a dummy texture for the texture pipeline template [Neil; #707458]
|
||||
* Remove holes generated by disabling the laptop lid [Giovanni; #707473]
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=707474 [Giovanni; #707474]
|
||||
* Constrain the pointer position onto visible monitors [Giovanni; #706655]
|
||||
* Fix keyboard state handling in face of event compression [Giovanni; #706963]
|
||||
* Extend the MetaCursorTracker API with query pointer and cursor visibility [Giovanni; #707474]
|
||||
* Be stricter in checking and exposing the wayland protocol version [#707851]
|
||||
* Don't require plugins to pass event to Clutter [Giovanni; #707482]
|
||||
* Move the --wayland option from the binary to the library [Giovanni; #707897]
|
||||
* Implement running from gnome-session (environment variable setting, process group
|
||||
handling, Clutter backend variables) [Giovanni; #706421]
|
||||
* Add support for more cursor types [Giovanni; #707919]
|
||||
* Drop man pages for removed utilities [Kalev; #706579]
|
||||
* Implement monitor configuration on KMS [Giovanni; #706308]
|
||||
* Implement HW cursors [Giovanni; #707573]
|
||||
* Implement minimal support for resizing and maximizing wayland clients [Giovanni; #707401]
|
||||
* Implement transient hints for wayland clients [Giovanni; #707401]
|
||||
* Implement popup menu surfaces and grabs [Giovanni; #707863]
|
||||
* Immediately fire idle watches that are already expired [Giovanni; #707302]
|
||||
* Misc bug fixes [Giovanni, Colin, Pavel; #707649, #707563, #708070]
|
||||
* Remove holes generated by disabling the laptop lid [Giovanni; #707473]
|
||||
* Misc bug fixes [Giovanni, Pavel, Adel; #707649, #706124, #707584, #707851, #707929,
|
||||
#708070]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Adel Gadllah, Colin Guthrie, Neil Roberts,
|
||||
Jasper St. Pierre, Ray Strode, Pavel Vasin
|
||||
Adel Gadllah, Giovanni Campagna, Kalev Lember, Pavel Vasin
|
||||
|
||||
Translations:
|
||||
Мирослав Николић po/sr, sr@latin.po, Мирослав Николић [sr, sr@latin],
|
||||
@@ -208,19 +162,30 @@ Translations:
|
||||
3.9.91
|
||||
======
|
||||
* Drop man pages for removed utilities [Kalev; #706579]
|
||||
* Add support for idle tracking [Giovanni; #706005]
|
||||
* Add support for idle tracking [Giovanni, Cosimo; #706005, #707250]
|
||||
* Skip CRTC reconfigurations that have no effect [Giovanni; #706672]
|
||||
* Ignore skip-taskbar hints on parentless dialogs [Giovanni; #673399]
|
||||
* Don't save pixbuf data in user data [Tim; #706777]
|
||||
* Don't queue redraws for obscured regions [Adel; #703332]
|
||||
* Turn blending off when drawing entirely opaque regions [Jasper; #706930]
|
||||
* Suppor the opaque region hints for wayland clients [Jasper; #707019]
|
||||
* Turn blending off when drawing entirely opaque regions [Jasper; #707019]
|
||||
* Check event timestamps before reconfiguring [Giovanni; #706735]
|
||||
* Merge the DBus API for display configuration in the wayland branch [Giovanni]
|
||||
* Install an X IO error handler for XWayland [Giovanni; #706962]
|
||||
* Use the clutter xkbcommon integration for the wayland keyboard [Giovanni; #705862]
|
||||
* Add a setuid helper for running on KMS+evdev [Giovanni, Colin; #705861]
|
||||
* Add keybindings for switching VT [Giovanni; #705861]
|
||||
* Implement plugin modality when running as a wayland compositor [Giovanni; #705917]
|
||||
* Add support for the application menu for wayland clients [Giovanni; #707128]
|
||||
* Several Coverity spotted fixes [Jasper]
|
||||
* Don't create a dummy texture for the texture template [Neil; #707458]
|
||||
* Use a more conservative paint volume for obscured windows [Adel]
|
||||
* Misc bug fixes [Giovanni, Colin, Seán, Jasper, Cosimo; #706582, #706598,
|
||||
#706787, #706729, #706825, #707081, #707090, #707250, #707267]
|
||||
#706787, #706729, #706825, #707081, #707090, #707267, #706982, #706289]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Cosimo Cecchi, Adel Gadllah, Colin Guthrie, Kalev Lember,
|
||||
Tim Lunn, Jasper St. Pierre, Rico Tzschichholz, Seán de Búrca
|
||||
Tim Lunn, Jasper St. Pierre, Neil Roberts, Rico Tzschichholz, Seán de Búrca
|
||||
|
||||
Translations:
|
||||
Piotr Drąg [pl], Alexandre Franke [fr], Kjartan Maraas [nb],
|
||||
@@ -229,6 +194,8 @@ Translations:
|
||||
|
||||
3.9.90
|
||||
======
|
||||
* First release from the wayland branch, includes basic support for running
|
||||
as a wayland compositor [Robert, Neil, Giovanni]
|
||||
* Add support for _GTK_FRAME_EXTENTS [Jasper; #705766]
|
||||
* Fix quick consecutive <super> presses breaking keyboard input [Alban; #666101]
|
||||
* Work towards running as wayland compositor [Giovanni]
|
||||
@@ -243,8 +210,8 @@ Translations:
|
||||
|
||||
Contributors:
|
||||
Robert Bragg, Giovanni Campagna, Alban Crequy, Adel Gadllah,
|
||||
Alexander Larsson, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz,
|
||||
Colin Walters
|
||||
Alexander Larsson, Florian Müllner, Jasper St. Pierre, Neil Roberts,
|
||||
Rico Tzschichholz, Colin Walters
|
||||
|
||||
Translations:
|
||||
Jiro Matsuzawa [ja], Kjartan Maraas [nb], Matej Urbančič [sl],
|
||||
|
||||
416
README
416
README
@@ -1,416 +0,0 @@
|
||||
The original codebase named "Metacity" is not a meta-City as in an
|
||||
urban center, but rather Meta-ness as in the state of being
|
||||
meta. i.e. metacity : meta as opacity : opaque. Also it may have
|
||||
something to do with the Meta key on UNIX keyboards.
|
||||
|
||||
Since then, it has been renamed mutter after a rebase on top of
|
||||
clutter as a compositing manager.
|
||||
|
||||
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 need Clutter 1.0. You need gobject-introspection 0.6.3.
|
||||
|
||||
REPORTING BUGS AND SUBMITTING PATCHES
|
||||
===
|
||||
|
||||
Report new bugs on http://bugzilla.gnome.org. Please check for
|
||||
duplicates, *especially* if you are reporting a feature request.
|
||||
|
||||
Please do *not* add "me too!" or "yes I really want this!" comments to
|
||||
feature requests in bugzilla. Please read
|
||||
http://pobox.com/~hp/features.html prior to adding any kind of flame
|
||||
about missing features or misfeatures.
|
||||
|
||||
Feel free to send patches too; Metacity is relatively small and
|
||||
simple, so if you find a bug or want to add a feature it should be
|
||||
pretty easy. Send me mail, or put the patch in bugzilla.
|
||||
|
||||
See the HACKING file for some notes on hacking Mutter.
|
||||
|
||||
MUTTER FEATURES
|
||||
===
|
||||
|
||||
- Uses GTK+ 2.0 for drawing window frames. This means colors, fonts,
|
||||
etc. come from GTK+ theme.
|
||||
|
||||
- Does not expose the concept of "window manager" to the user. Some
|
||||
of the features in the GNOME control panel and other parts of the
|
||||
desktop happen to be implemented in metacity, such as changing your
|
||||
window border theme, or changing your window navigation shortcuts,
|
||||
but the user doesn't need to know this.
|
||||
|
||||
- Includes only the window manager; does not try to be a desktop
|
||||
environment. The pager, configuration, etc. are all separate and
|
||||
modular. The "libwnck" library (which I also wrote) is available
|
||||
for writing metacity extensions, pagers, and so on. (But libwnck
|
||||
isn't metacity specific, or GNOME-dependent; it requires only GTK,
|
||||
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 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 gsettings:
|
||||
gsettings set org.gnome.desktop.wm.preferences num-workspaces 5
|
||||
|
||||
Can also change workspaces from GNOME 2 pager.
|
||||
|
||||
- Change focus mode:
|
||||
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:
|
||||
|
||||
Alt-Tab forward cycle window focus
|
||||
Alt-Shift-Tab backward cycle focus
|
||||
Alt-Ctrl-Tab forward cycle focus among panels
|
||||
Alt-Ctrl-Shift-Tab backward cycle focus among panels
|
||||
Alt-Escape cycle window focus without a popup thingy
|
||||
Ctrl-Alt-Left Arrow previous workspace
|
||||
Ctrl-Alt-Right Arrow next workspace
|
||||
Ctrl-Alt-D minimize/unminimize all, to show desktop
|
||||
|
||||
Change keybindings for example:
|
||||
|
||||
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-1 '[<Alt>F1]'
|
||||
|
||||
Also try the GNOME keyboard shortcuts control panel.
|
||||
|
||||
- Window keybindings:
|
||||
|
||||
Alt-space window menu
|
||||
|
||||
Mnemonics work in the menu. That is, Alt-space then underlined
|
||||
letter in the menu item works.
|
||||
|
||||
Choose Move from menu, and arrow keys to move the window.
|
||||
|
||||
While moving, hold down Control to move slower, and
|
||||
Shift to snap to edges.
|
||||
|
||||
Choose Resize from menu, and nothing happens yet, but
|
||||
eventually I might implement something.
|
||||
|
||||
Keybindings for things like maximize window, vertical maximize,
|
||||
etc. can be bound, but may not all exist by default. See
|
||||
metacity.schemas.
|
||||
|
||||
- Window mouse bindings:
|
||||
|
||||
Clicking anywhere on frame with button 1 will raise/focus window
|
||||
|
||||
If you click a window control, such as the close button, then the
|
||||
control will activate on button release if you are still over it
|
||||
on release (as with most GUI toolkits)
|
||||
|
||||
If you click and drag borders with button 1 it resizes the window
|
||||
|
||||
If you click and drag the titlebar with button 1 it moves the
|
||||
window.
|
||||
|
||||
If you click anywhere on the frame with button 2 it lowers the
|
||||
window.
|
||||
|
||||
If you click anywhere on the frame with button 3 it shows the
|
||||
window menu.
|
||||
|
||||
If you hold down Super (windows key) and click inside a window, it
|
||||
will move the window (buttons 1 and 2) or show menu (button 3).
|
||||
Or you can configure a different modifier for this.
|
||||
|
||||
If you pick up a window with button 1 and then switch workspaces
|
||||
the window will come with you to the new workspace, this is
|
||||
a feature copied from Enlightenment.
|
||||
|
||||
If you hold down Shift while moving a window, the window snaps
|
||||
to edges of other windows and the screen.
|
||||
|
||||
- Session management:
|
||||
|
||||
Mutter connects to the session manager and will set itself up to
|
||||
be respawned. It theoretically restores sizes/positions/workspace
|
||||
for session-aware applications.
|
||||
|
||||
- Mutter implements much of the EWMH window manager specification
|
||||
from freedesktop.org, as well as the older ICCCM. Please refer to
|
||||
the COMPLIANCE file for information on mutter compliance with
|
||||
these standards.
|
||||
|
||||
- Uses Pango to render text, so has cool i18n capabilities.
|
||||
Supports UTF-8 window titles and such.
|
||||
|
||||
- There are simple animations for actions such as minimization,
|
||||
to help users see what is happening. Should probably
|
||||
have a few more of these and make them nicer.
|
||||
|
||||
- if you have the proper X setup, set the GDK_USE_XFT=1
|
||||
environment variable to get antialiased window titles.
|
||||
|
||||
- considers the panel when placing windows and maximizing
|
||||
them.
|
||||
|
||||
- handles the window manager selection from the ICCCM. Will exit if
|
||||
another WM claims it, and can claim it from another WM if you pass
|
||||
the --replace argument. So if you're running another
|
||||
ICCCM-compliant WM, you can run "mutter --replace" to replace it
|
||||
with Metacity.
|
||||
|
||||
- does basic colormap handling
|
||||
|
||||
- and much more! well, maybe not a lot more.
|
||||
|
||||
HOW TO ADD EXTERNAL FEATURES
|
||||
===
|
||||
|
||||
You can write a mutter "plugin" such as a pager, window list, icon
|
||||
box, task menu, or even things like "window matching" using the
|
||||
Extended Window Manager Hints. See http://www.freedesktop.org for the
|
||||
EWMH specification. An easy-to-use library called "libwnck" is
|
||||
available that uses the EWMH and is specifically designed for writing
|
||||
WM accessories.
|
||||
|
||||
You might be interested in existing accessories such as "Devil's Pie"
|
||||
by Ross Burton, which add features to Mutter (or other
|
||||
EWMH-compliant WMs).
|
||||
|
||||
MUTTER BUGS, NON-FEATURES, AND CAVEATS
|
||||
===
|
||||
|
||||
See bugzilla: http://bugzilla.gnome.org/query.cgi
|
||||
|
||||
FAQ
|
||||
===
|
||||
|
||||
Q: Will you add my feature?
|
||||
|
||||
A: If it makes sense to turn on unconditionally, or is genuinely a
|
||||
harmless preference that I would not be embarrassed to put in a
|
||||
simple, uncluttered, user-friendly configuration dialog.
|
||||
|
||||
If the only rationale for your feature is that other window
|
||||
managers have it, or that you are personally used to it, or
|
||||
something like that, then I will not be impressed. Metacity is
|
||||
firmly in the "choose good defaults" camp rather than the "offer 6
|
||||
equally broken ways to do it, and let the user pick one" camp.
|
||||
|
||||
This is part of a "no crackrock" policy, despite some exceptions
|
||||
I'm mildly embarrassed about. For example, multiple workspaces
|
||||
probably constitute crackrock, they confuse most users and really
|
||||
are not that useful if you have a decent tasklist and so on. But I
|
||||
am too used to them to turn them off. Or alternatively
|
||||
iconification/tasklist is crack, and workspaces/pager are good. But
|
||||
having both is certainly a bit wrong. Sloppy focus is probably
|
||||
crackrock too.
|
||||
|
||||
But don't think unlimited crack is OK just because I slipped up a
|
||||
little. No slippery slope here.
|
||||
|
||||
Don't let this discourage patches and fixes - I love those. ;-)
|
||||
Just be prepared to hear the above objections if your patch adds
|
||||
some crack-ridden configuration option.
|
||||
|
||||
http://pobox.com/~hp/free-software-ui.html
|
||||
http://pobox.com/~hp/features.html
|
||||
|
||||
Q: Will Mutter be part of GNOME?
|
||||
|
||||
A: It is not officially part of GNOME as of GNOME 2.27. We are
|
||||
hoping to have mutter officially included as of GNOME 2.28.
|
||||
|
||||
Q: Why does Mutter remember the workspace/position of some apps
|
||||
but not others across logout/login?
|
||||
|
||||
A: Mutter only stores sizes/positions for apps that are session
|
||||
managed. As far as I can determine, there is no way to attempt to
|
||||
remember workspace/position for non-session-aware apps without
|
||||
causing a lot of weird effects.
|
||||
|
||||
The reason is that you don't know which non-SM-aware apps were
|
||||
launched by the session. When you initially log in, Metacity sees a
|
||||
bunch of new windows appear. But it can't distinguish between
|
||||
windows that were stored in your session, or windows you just
|
||||
launched after logging in. If Metacity tried to guess that a window
|
||||
was from the session, it could e.g. end up maximizing a dialog, or
|
||||
put a window you just launched on another desktop or in a weird
|
||||
place. And in fact I see a lot of bugs like this in window managers
|
||||
that try to handle non-session-aware apps.
|
||||
|
||||
However, for session-aware apps, Mutter can tell that the
|
||||
application instance is from the session and thus restore it
|
||||
reliably, assuming the app properly restores the windows it had
|
||||
open on session save.
|
||||
|
||||
So the correct way to fix the situation is to make apps
|
||||
session-aware. libSM has come with X for years, it's very
|
||||
standardized, it's shared by GNOME and KDE - even twm is
|
||||
session-aware. So anyone who won't take a patch to add SM is more
|
||||
archaic than twm - and you should flame them. ;-)
|
||||
|
||||
Docs on session management:
|
||||
http://www.fifi.org/doc/xspecs/xsmp.txt.gz
|
||||
http://www.fifi.org/doc/xspecs/SMlib.txt.gz
|
||||
|
||||
See also the ICCCM section on SM. For GNOME apps, use the
|
||||
GnomeClient object. For a simple example of using libSM directly,
|
||||
twm/session.c in the twm source code is pretty easy to understand.
|
||||
|
||||
Q: How about adding viewports in addition to workspaces?
|
||||
|
||||
A: I could conceivably be convinced to use viewports _instead_ of
|
||||
workspaces, though currently I'm not thinking that. But I don't
|
||||
think it makes any sense to have both; it's just confusing. They
|
||||
are functionally equivalent.
|
||||
|
||||
You may think this means that you won't have certain keybindings,
|
||||
or something like that. This is a misconception. The only
|
||||
_fundamental_ difference between viewports and workspaces is that
|
||||
with viewports, windows can "overlap" and appear partially on
|
||||
one and partially on another. All other differences that
|
||||
traditionally exist in other window managers are accidental -
|
||||
the features commonly associated with viewports can be implemented
|
||||
for workspaces, and vice versa.
|
||||
|
||||
So I don't want to have two kinds of
|
||||
workspace/desktop/viewport/whatever, but I'm willing to add
|
||||
features traditionally associated with either kind if those
|
||||
features make sense.
|
||||
|
||||
Q: Why is the panel always on top?
|
||||
|
||||
A: Because it's a better user interface, and until we made this not
|
||||
configurable a bunch of apps were not getting fixed (the app
|
||||
authors were just saying "put your panel on the bottom" instead of
|
||||
properly supporting fullscreen mode, and such).
|
||||
|
||||
rationales.txt has the bugzilla URL for some flamefesting on this,
|
||||
if you want to go back and relive the glory.
|
||||
Read these and the bugzilla stuff before asking/commenting:
|
||||
http://pobox.com/~hp/free-software-ui.html
|
||||
http://pobox.com/~hp/features.html
|
||||
|
||||
Q: Why is there no edge flipping?
|
||||
|
||||
A: This one is also in rationales.txt. Because "ouija board" UI, where
|
||||
you just move the mouse around and the computer guesses what you
|
||||
mean, has a lot of issues. This includes mouse focus, shade-hover
|
||||
mode, edge flipping, autoraise, etc. Metacity has mouse focus and
|
||||
autoraise as a compromise, but these features are all confusing for
|
||||
many users, and cause problems with accessibility, fitt's law, and
|
||||
so on.
|
||||
|
||||
Read these and the bugzilla stuff before asking/commenting:
|
||||
http://pobox.com/~hp/free-software-ui.html
|
||||
http://pobox.com/~hp/features.html
|
||||
|
||||
Q: Why does wireframe move/resize suck?
|
||||
|
||||
A: You can turn it on with the reduced_resources setting.
|
||||
|
||||
But: it has low usability, and is a pain
|
||||
to implement, and there's no reason opaque move/resize should be a
|
||||
problem on any setup that can run a modern desktop worth a darn to
|
||||
begin with.
|
||||
|
||||
Read these and the bugzilla stuff before asking/commenting:
|
||||
http://pobox.com/~hp/free-software-ui.html
|
||||
http://pobox.com/~hp/features.html
|
||||
|
||||
The reason we had to add wireframe anyway was broken
|
||||
proprietary apps that can't handle lots of resize events.
|
||||
|
||||
Q: Why no XYZ?
|
||||
|
||||
A: You are probably getting the idea by now - check rationales.txt,
|
||||
query/search bugzilla, and read http://pobox.com/~hp/features.html
|
||||
and http://pobox.com/~hp/free-software-ui.html
|
||||
|
||||
Then sit down and answer the question for yourself. Is the feature
|
||||
good? What's the rationale for it? Answer "why" not just "why not."
|
||||
Justify in terms of users as a whole, not just users like
|
||||
yourself. How else can you solve the same problem? etc. If that
|
||||
leads you to a strong opinion, then please, post the rationale for
|
||||
discussion to an appropriate bugzilla bug, or to
|
||||
usability@gnome.org.
|
||||
|
||||
Please don't just "me too!" on bugzilla bugs, please don't think
|
||||
flames will get you anywhere, and please don't repeat rationale
|
||||
that's already been offered.
|
||||
|
||||
Q: Your dumb web pages you made me read talk about solving problems in
|
||||
fundamental ways instead of adding preferences or workarounds.
|
||||
What are some examples where metacity has done this?
|
||||
|
||||
A: There are quite a few, though many opportunities remain. Sometimes
|
||||
the real fix involves application changes. The metacity approach is
|
||||
that it's OK to require apps to change, though there are also
|
||||
plenty of workarounds in metacity for battles considered too hard
|
||||
to fight.
|
||||
|
||||
Here are some examples:
|
||||
|
||||
- fullscreen mode was introduced to allow position constraints,
|
||||
panel-on-top, and other such things to apply to normal windows
|
||||
while still allowing video players etc. to "just work"
|
||||
|
||||
- "whether to include minimized windows in Alt+Tab" was solved
|
||||
by putting minimized windows at the *end* of the tab order.
|
||||
|
||||
- Whether to pop up a feedback display during Alt+Tab was solved by
|
||||
having both Alt+Tab and Alt+Esc
|
||||
|
||||
- Whether to have a "kill" feature was solved by automatically
|
||||
detecting and offering to kill stuck apps. Better, metacity
|
||||
actually does "kill -9" on the process, it doesn't just
|
||||
disconnect the process from the X server. You'll appreciate this
|
||||
if you ever did a "kill" on Netscape 4, and watched it keep
|
||||
eating 100% CPU even though the X server had booted it.
|
||||
|
||||
- The workspaces vs. viewports mess was avoided by adding
|
||||
directional navigation and such to workspaces, see discussion
|
||||
earlier in this file.
|
||||
|
||||
- Instead of configurable placement algorithms, there's just one
|
||||
that works fairly well most of the time.
|
||||
|
||||
- To avoid excess CPU use during opaque move/resize, we rate limit
|
||||
the updates to the application window's size.
|
||||
|
||||
- Instead of configurable "show size of window while resizing,"
|
||||
it's only shown for windows where it matters, such as terminals.
|
||||
(Only use-case given for all windows is for web designers
|
||||
choosing their web browser size, but there are web sites and
|
||||
desktop backgrounds that do this for you.)
|
||||
|
||||
- Using startup notification, applications open on the workspace
|
||||
where you launched them, not the active workspace when their
|
||||
window is opened.
|
||||
|
||||
- and much more.
|
||||
|
||||
Q: I think mutter sucks.
|
||||
|
||||
A: Feel free to use any WM you like. The reason metacity follows the
|
||||
ICCCM and EWMH specifications is that it makes metacity a modular,
|
||||
interchangeable part in the desktop. libwnck-based apps such as the
|
||||
GNOME window list will work just fine with any EWMH-compliant WM.
|
||||
|
||||
Q: Did you spend a lot of time on this?
|
||||
|
||||
A: Originally the answer was no. Sadly the answer is now yes.
|
||||
|
||||
Q: How can you claim that you are anti-crack, while still
|
||||
writing a window manager?
|
||||
|
||||
A: I have no comment on that.
|
||||
57
configure.ac
57
configure.ac
@@ -2,8 +2,8 @@ AC_PREREQ(2.50)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [12])
|
||||
m4_define([mutter_micro_version], [2])
|
||||
m4_define([mutter_minor_version], [11])
|
||||
m4_define([mutter_micro_version], [92])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@@ -13,14 +13,17 @@ m4_define([mutter_plugin_api_version], [3])
|
||||
AC_INIT([mutter], [mutter_version],
|
||||
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_SRCDIR(src/core/display.c)
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
||||
AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz tar-ustar])
|
||||
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar])
|
||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
|
||||
AM_MAINTAINER_MODE([enable])
|
||||
|
||||
# Change pkglibdir and pkgdatadir to mutter-wayland instead of mutter
|
||||
PACKAGE="mutter-wayland"
|
||||
AC_SUBST([PACKAGE], [$PACKAGE])
|
||||
|
||||
MUTTER_MAJOR_VERSION=mutter_major_version
|
||||
MUTTER_MINOR_VERSION=mutter_minor_version
|
||||
MUTTER_MICRO_VERSION=mutter_micro_version
|
||||
@@ -36,7 +39,7 @@ AC_SUBST(MUTTER_PLUGIN_DIR)
|
||||
# Honor aclocal flags
|
||||
AC_SUBST(ACLOCAL_AMFLAGS, "\${ACLOCAL_FLAGS}")
|
||||
|
||||
GETTEXT_PACKAGE=mutter
|
||||
GETTEXT_PACKAGE=mutter-wayland
|
||||
AC_SUBST(GETTEXT_PACKAGE)
|
||||
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
|
||||
|
||||
@@ -69,13 +72,13 @@ CANBERRA_GTK_VERSION=0.26
|
||||
CLUTTER_PACKAGE=clutter-1.0
|
||||
|
||||
MUTTER_PC_MODULES="
|
||||
gtk+-3.0 >= 3.9.11
|
||||
gtk+-3.0 >= 3.3.7
|
||||
gio-2.0 >= 2.25.10
|
||||
pango >= 1.2.0
|
||||
cairo >= 1.10.0
|
||||
gsettings-desktop-schemas >= 3.7.3
|
||||
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
|
||||
$CLUTTER_PACKAGE >= 1.15.90
|
||||
$CLUTTER_PACKAGE >= 1.17.5
|
||||
cogl-1.0 >= 1.17.1
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
@@ -117,11 +120,27 @@ AC_ARG_ENABLE(shape,
|
||||
[disable mutter's use of the shaped window extension]),,
|
||||
enable_shape=auto)
|
||||
|
||||
## Wayland support requires the xserver.xml protocol extension found in the weston
|
||||
## repository but since there aren't currently established conventions for
|
||||
## installing and discovering these we simply require a location to be given
|
||||
## explicitly...
|
||||
AC_ARG_WITH([wayland-protocols],
|
||||
[AS_HELP_STRING([--with-wayland-protocols], [Location for wayland extension protocol specs])],
|
||||
[
|
||||
],
|
||||
[])
|
||||
|
||||
AC_ARG_WITH([xwayland-path],
|
||||
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
|
||||
[XWAYLAND_PATH="$withval"],
|
||||
[XWAYLAND_PATH="$bindir/Xorg"])
|
||||
|
||||
AM_GLIB_GNU_GETTEXT
|
||||
|
||||
## here we get the flags we'll actually use
|
||||
# GRegex requires Glib-2.14.0
|
||||
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
|
||||
PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login)
|
||||
|
||||
# Unconditionally use this dir to avoid a circular dep with gnomecc
|
||||
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
|
||||
@@ -186,20 +205,15 @@ if test x$found_introspection != xno; then
|
||||
AC_SUBST(META_GIR)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([Xcursor])
|
||||
if $PKG_CONFIG xcursor; then
|
||||
have_xcursor=yes
|
||||
else
|
||||
have_xcursor=no
|
||||
fi
|
||||
AC_MSG_RESULT($have_xcursor)
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor"
|
||||
|
||||
if test x$have_xcursor = xyes; then
|
||||
echo "Building with Xcursor"
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor"
|
||||
AC_DEFINE(HAVE_XCURSOR, , [Building with Xcursor support])
|
||||
fi
|
||||
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
|
||||
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
|
||||
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
|
||||
AC_SUBST([WAYLAND_SCANNER])
|
||||
AC_SUBST(XWAYLAND_PATH)
|
||||
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 wayland-server libdrm"
|
||||
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
|
||||
|
||||
PKG_CHECK_EXISTS([xi >= 1.6.99.1],
|
||||
@@ -437,8 +451,7 @@ doc/man/Makefile
|
||||
doc/reference/Makefile
|
||||
doc/reference/meta-docs.sgml
|
||||
src/Makefile
|
||||
src/libmutter.pc
|
||||
src/mutter-plugins.pc
|
||||
src/libmutter-wayland.pc
|
||||
src/compositor/plugins/Makefile
|
||||
po/Makefile.in
|
||||
])
|
||||
@@ -455,7 +468,7 @@ fi
|
||||
|
||||
dnl ==========================================================================
|
||||
echo "
|
||||
mutter-$VERSION
|
||||
mutter-wayland-$VERSION
|
||||
|
||||
prefix: ${prefix}
|
||||
source code location: ${srcdir}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SUBDIRS = man reference
|
||||
|
||||
EXTRA_DIST=theme-format.txt dialogs.txt code-overview.txt \
|
||||
how-to-get-focus-right.txt
|
||||
how-to-get-focus-right.txt rationales.txt
|
||||
|
||||
@@ -140,7 +140,7 @@ expand_content_files= \
|
||||
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
|
||||
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
|
||||
GTKDOC_CFLAGS=$(MUTTER_CFLAGS)
|
||||
GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter.la
|
||||
GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter-wayland.la
|
||||
|
||||
# This includes the standard gtk-doc make rules, copied by gtkdocize.
|
||||
include $(top_srcdir)/gtk-doc.make
|
||||
|
||||
@@ -16,14 +16,14 @@ src/core/monitor.c
|
||||
src/core/mutter.c
|
||||
src/core/prefs.c
|
||||
src/core/screen.c
|
||||
src/core/session.c
|
||||
src/x11/session.c
|
||||
src/core/util.c
|
||||
src/core/window.c
|
||||
src/core/window-props.c
|
||||
src/core/xprops.c
|
||||
src/mutter.desktop.in
|
||||
src/mutter-wm.desktop.in
|
||||
src/x11/window-props.c
|
||||
src/x11/xprops.c
|
||||
src/mutter-wayland.desktop.in
|
||||
src/org.gnome.mutter.gschema.xml.in
|
||||
src/org.gnome.mutter.wayland.gschema.xml.in
|
||||
src/ui/frames.c
|
||||
src/ui/menu.c
|
||||
src/ui/metaaccellabel.c
|
||||
|
||||
2834
po/ca@valencia.po
2834
po/ca@valencia.po
File diff suppressed because it is too large
Load Diff
805
po/pt_BR.po
805
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
417
po/sk.po
417
po/sk.po
@@ -13,9 +13,9 @@ msgstr ""
|
||||
"Project-Id-Version: mutter\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
|
||||
"product=mutter&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2013-08-21 17:41+0000\n"
|
||||
"PO-Revision-Date: 2013-08-02 14:46+0200\n"
|
||||
"Last-Translator: Ján Kyselica <kyselica.jan@gmail.com>\n"
|
||||
"POT-Creation-Date: 2013-05-24 21:44+0000\n"
|
||||
"PO-Revision-Date: 2013-05-18 16:53+0100\n"
|
||||
"Last-Translator: Jan Kyselica <kyselica.jan@gmail.com>\n"
|
||||
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
|
||||
"Language: sk\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -87,8 +87,9 @@ msgstr "Prepnúť okná aplikácie"
|
||||
# PK: zisti co to robi
|
||||
# description
|
||||
#: ../src/50-mutter-navigation.xml.in.h:13
|
||||
#, fuzzy
|
||||
msgid "Switch system controls"
|
||||
msgstr "Prepnúť medzi ovládacími prvkami systému"
|
||||
msgstr "Prepnúť medzi systémovými ovládacími prvkami"
|
||||
|
||||
# description
|
||||
#: ../src/50-mutter-navigation.xml.in.h:14
|
||||
@@ -103,8 +104,9 @@ msgstr "Prepnúť okná aplikácie priamo"
|
||||
# MČ: podobne ako vyššie: „cycle-panels“
|
||||
# description
|
||||
#: ../src/50-mutter-navigation.xml.in.h:16
|
||||
#, fuzzy
|
||||
msgid "Switch system controls directly"
|
||||
msgstr "Prepnúť medzi ovládacími prvkami systému priamo"
|
||||
msgstr "Prepnúť medzi systémovými ovládacími prvkami priamo"
|
||||
|
||||
# description
|
||||
#: ../src/50-mutter-navigation.xml.in.h:17
|
||||
@@ -265,13 +267,13 @@ msgstr "Zobraziť rozdelenie napravo"
|
||||
# PK: je %i cislo obrazovky? ak ano tak "č. %i"
|
||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||
#. * we have no way to get it to exit
|
||||
#: ../src/compositor/compositor.c:596
|
||||
#, c-format
|
||||
#: ../src/compositor/compositor.c:571
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Another compositing manager is already running on screen %i on display \"%s"
|
||||
"\"."
|
||||
msgstr ""
|
||||
"Pre obrazovku č. %i na displeji „%s“ je spustený už iný správca rozloženia."
|
||||
"Pre obrazovku %i na displeji „%s“ je spustený už iný správca rozloženia."
|
||||
|
||||
#: ../src/compositor/meta-background.c:1076
|
||||
msgid "background texture could not be created from file"
|
||||
@@ -311,18 +313,18 @@ msgstr "_Počkať"
|
||||
msgid "_Force Quit"
|
||||
msgstr "_Vynútiť ukončenie"
|
||||
|
||||
#: ../src/core/display.c:421
|
||||
#: ../src/core/display.c:401
|
||||
#, c-format
|
||||
msgid "Missing %s extension required for compositing"
|
||||
msgstr "Rozšírenie %s, potrebné pre kompozitné prostredie, chýba"
|
||||
|
||||
# X window system preloz, napr. system na spravu okien X
|
||||
#: ../src/core/display.c:513
|
||||
#: ../src/core/display.c:493
|
||||
#, c-format
|
||||
msgid "Failed to open X Window System display '%s'\n"
|
||||
msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n"
|
||||
|
||||
#: ../src/core/keybindings.c:1136
|
||||
#: ../src/core/keybindings.c:970
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Some other program is already using the key %s with modifiers %x as a "
|
||||
@@ -330,7 +332,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Iný program už používa kláves %s s modifikátormi %x ako klávesovú skratku\n"
|
||||
|
||||
#: ../src/core/keybindings.c:1333
|
||||
#: ../src/core/keybindings.c:1151
|
||||
#, c-format
|
||||
msgid "\"%s\" is not a valid accelerator\n"
|
||||
msgstr "„%s“ nie je platný akcelerátor\n"
|
||||
@@ -376,20 +378,6 @@ msgid ""
|
||||
msgstr ""
|
||||
"Nepodarilo sa nájsť tému! Overte, že %s existuje a obsahuje obvyklé témy.\n"
|
||||
|
||||
#: ../src/core/monitor.c:702
|
||||
msgid "Built-in display"
|
||||
msgstr "Vstavaný displej"
|
||||
|
||||
#. TRANSLATORS: this is a monitor name (in case we don't know
|
||||
#. the vendor), it's Unknown followed by a size in inches,
|
||||
#. like 'Unknown 15"'
|
||||
#.
|
||||
#: ../src/core/monitor.c:730
|
||||
#, c-format
|
||||
#| msgid "Unknown element %s"
|
||||
msgid "Unknown %s"
|
||||
msgstr "Neznámy %s"
|
||||
|
||||
#: ../src/core/mutter.c:40
|
||||
#, c-format
|
||||
msgid ""
|
||||
@@ -415,7 +403,7 @@ msgstr "Zobrazí verziu"
|
||||
msgid "Mutter plugin to use"
|
||||
msgstr "Použije zásuvný modul Mutter"
|
||||
|
||||
#: ../src/core/prefs.c:1202
|
||||
#: ../src/core/prefs.c:1193
|
||||
msgid ""
|
||||
"Workarounds for broken applications disabled. Some applications may not "
|
||||
"behave properly.\n"
|
||||
@@ -423,12 +411,12 @@ msgstr ""
|
||||
"Náhradné riešenia pre chybné aplikácie nie sú povolené. Niektoré aplikácie "
|
||||
"sa nemusia správať správne.\n"
|
||||
|
||||
#: ../src/core/prefs.c:1277
|
||||
#: ../src/core/prefs.c:1268
|
||||
#, c-format
|
||||
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
|
||||
msgstr "Nepodarilo sa spracovať popis písma „%s“ z kľúča GSettings %s\n"
|
||||
|
||||
#: ../src/core/prefs.c:1343
|
||||
#: ../src/core/prefs.c:1334
|
||||
#, c-format
|
||||
msgid ""
|
||||
"\"%s\" found in configuration database is not a valid value for mouse button "
|
||||
@@ -437,7 +425,7 @@ msgstr ""
|
||||
"V konfiguračnej databáze sa našlo „%s“, čo nie je platná hodnota pre "
|
||||
"modifikátor tlačidla myši\n"
|
||||
|
||||
#: ../src/core/prefs.c:1909
|
||||
#: ../src/core/prefs.c:1881
|
||||
#, c-format
|
||||
msgid ""
|
||||
"\"%s\" found in configuration database is not a valid value for keybinding "
|
||||
@@ -446,17 +434,17 @@ msgstr ""
|
||||
"V konfiguračnej databáze sa našlo „%s“, čo nie je platná hodnota pre "
|
||||
"klávesovú skratku „%s“\n"
|
||||
|
||||
#: ../src/core/prefs.c:1999
|
||||
#: ../src/core/prefs.c:1945
|
||||
#, c-format
|
||||
msgid "Workspace %d"
|
||||
msgstr "Pracovný priestor č. %d"
|
||||
|
||||
#: ../src/core/screen.c:537
|
||||
#: ../src/core/screen.c:691
|
||||
#, c-format
|
||||
msgid "Screen %d on display '%s' is invalid\n"
|
||||
msgstr "Obrazovka č. %d na displeji „%s“ nie je platná\n"
|
||||
|
||||
#: ../src/core/screen.c:553
|
||||
#: ../src/core/screen.c:707
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Screen %d on display \"%s\" already has a window manager; try using the --"
|
||||
@@ -465,7 +453,7 @@ msgstr ""
|
||||
"Obrazovka č. %d na displeji „%s“ už má správcu okien. Skúste použiť prepínač "
|
||||
"--replace, aby sa aktuálny správca nahradil.\n"
|
||||
|
||||
#: ../src/core/screen.c:580
|
||||
#: ../src/core/screen.c:734
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Could not acquire window manager selection on screen %d display \"%s\"\n"
|
||||
@@ -473,12 +461,12 @@ msgstr ""
|
||||
"Nepodarilo sa získať výber správcu okien pre obrazovku č. %d na displeji "
|
||||
"„%s“\n"
|
||||
|
||||
#: ../src/core/screen.c:658
|
||||
#: ../src/core/screen.c:812
|
||||
#, c-format
|
||||
msgid "Screen %d on display \"%s\" already has a window manager\n"
|
||||
msgstr "Obrazovka č. %d na displeji „%s“ už má správcu okien\n"
|
||||
|
||||
#: ../src/core/screen.c:850
|
||||
#: ../src/core/screen.c:998
|
||||
#, c-format
|
||||
msgid "Could not release screen %d on display \"%s\"\n"
|
||||
msgstr "Nepodarilo sa uvoľniť obrazovku č. %d na displeji „%s“\n"
|
||||
@@ -554,7 +542,8 @@ msgstr "Zlyhalo otvorenie súboru so záznamom pomocou fdopen() %s: %s\n"
|
||||
msgid "Opened log file %s\n"
|
||||
msgstr "Otvorený súbor so záznamom %s\n"
|
||||
|
||||
#: ../src/core/util.c:119
|
||||
#: ../src/core/util.c:119 ../src/tools/mutter-message.c:149
|
||||
#, c-format
|
||||
msgid "Mutter was compiled without support for verbose mode\n"
|
||||
msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n"
|
||||
|
||||
@@ -562,20 +551,20 @@ msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n"
|
||||
msgid "Window manager: "
|
||||
msgstr "Správca okien: "
|
||||
|
||||
#: ../src/core/util.c:414
|
||||
#: ../src/core/util.c:412
|
||||
msgid "Bug in window manager: "
|
||||
msgstr "Chyba v správcovi okien: "
|
||||
|
||||
#: ../src/core/util.c:445
|
||||
#: ../src/core/util.c:443
|
||||
msgid "Window manager warning: "
|
||||
msgstr "Varovanie správcu okien: "
|
||||
|
||||
#: ../src/core/util.c:473
|
||||
#: ../src/core/util.c:471
|
||||
msgid "Window manager error: "
|
||||
msgstr "Chyba správcu okien: "
|
||||
|
||||
#. first time through
|
||||
#: ../src/core/window.c:7533
|
||||
#: ../src/core/window.c:7505
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
|
||||
@@ -591,7 +580,7 @@ msgstr ""
|
||||
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
|
||||
#. * about these apps but make them work.
|
||||
#.
|
||||
#: ../src/core/window.c:8257
|
||||
#: ../src/core/window.c:8229
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
|
||||
@@ -601,7 +590,7 @@ msgstr ""
|
||||
"nastavuje minimálnu veľkosť %d x %d a maximálnu veľkosť %d x %d. To nedáva "
|
||||
"zmysel.\n"
|
||||
|
||||
#: ../src/core/window-props.c:347
|
||||
#: ../src/core/window-props.c:318
|
||||
#, c-format
|
||||
msgid "Application set a bogus _NET_WM_PID %lu\n"
|
||||
msgstr "Aplikácia nastavila neplatné _NET_WM_PID %lu\n"
|
||||
@@ -609,18 +598,18 @@ msgstr "Aplikácia nastavila neplatné _NET_WM_PID %lu\n"
|
||||
# PK: co je toto?
|
||||
# JK: nedokazem zistit
|
||||
# PM: vyžiadaj komentár od vývojárov, pomožeme aj ostatným prekladateľom
|
||||
#: ../src/core/window-props.c:463
|
||||
#: ../src/core/window-props.c:434
|
||||
#, fuzzy, c-format
|
||||
msgid "%s (on %s)"
|
||||
msgstr "%s (na %s)"
|
||||
|
||||
#: ../src/core/window-props.c:1546
|
||||
#: ../src/core/window-props.c:1517
|
||||
#, c-format
|
||||
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
|
||||
msgstr "Neplatné WM_TRANSIENT_FOR okno 0x%lx nastavené pre %s.\n"
|
||||
|
||||
# MČ: zacykliť sa, alebo vytvoriť slučku.
|
||||
#: ../src/core/window-props.c:1557
|
||||
#: ../src/core/window-props.c:1528
|
||||
#, c-format
|
||||
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
|
||||
msgstr "WM_TRANSIENT_FOR okno 0x%lx pre %s môže vytvoriť slučku.\n"
|
||||
@@ -708,9 +697,9 @@ msgid ""
|
||||
"vertically and resizes them horizontally to cover half of the available "
|
||||
"area. Dropping windows on the top screen edge maximizes them completely."
|
||||
msgstr ""
|
||||
"Ak je povolené, upustenie okien pri zvislých okrajoch obrazovky ich zvislo "
|
||||
"maximalizuje a vodorovná veľkosť sa zmení na polovicu dostupnej plochy. "
|
||||
"Upustenie okien pri vrchnom okraji obrazovky ich maximalizuje úplne."
|
||||
"Ak je povolené, upustenie okien pri zvislých okrajoch obrazovky ich "
|
||||
"zvislo maximalizuje a vodorovná veľkosť sa zmení na polovicu dostupnej "
|
||||
"plochy. Upustenie okien pri vrchnom okraji obrazovky ich maximalizuje úplne."
|
||||
|
||||
# summary
|
||||
#: ../src/org.gnome.mutter.gschema.xml.in.h:7
|
||||
@@ -746,8 +735,9 @@ msgstr ""
|
||||
# PM: ja by som dal Bez vyvovlávania tabulátorom
|
||||
# summary
|
||||
#: ../src/org.gnome.mutter.gschema.xml.in.h:11
|
||||
#, fuzzy
|
||||
msgid "No tab popup"
|
||||
msgstr "Bez vyvolávania tabulátorom"
|
||||
msgstr "Nepoužívať prekryvnú ponuku tabulátora"
|
||||
|
||||
# MČ: Neviem, čo to presne má robiť, ale popis som pochopil inak. „…či sa má používať rozbaľovacia ponuka a zvýraznenie rámikom sa má vypnúť…“
|
||||
# description
|
||||
@@ -816,104 +806,109 @@ msgstr "Vybrať okno z rozbaľovacej ponuky tabulátoru"
|
||||
msgid "Cancel tab popup"
|
||||
msgstr "Zrušit rozbaľovaciu ponuku tabulátoru"
|
||||
|
||||
#: ../src/tools/mutter-message.c:123
|
||||
#, c-format
|
||||
msgid "Usage: %s\n"
|
||||
msgstr "Použitie: %s\n"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:67
|
||||
#: ../src/ui/menu.c:69
|
||||
msgid "Mi_nimize"
|
||||
msgstr "Mi_nimalizovať"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:69
|
||||
#: ../src/ui/menu.c:71
|
||||
msgid "Ma_ximize"
|
||||
msgstr "Ma_ximalizovať"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:71
|
||||
#: ../src/ui/menu.c:73
|
||||
msgid "Unma_ximize"
|
||||
msgstr "Zrušiť ma_ximalizáciu"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:73
|
||||
#: ../src/ui/menu.c:75
|
||||
msgid "Roll _Up"
|
||||
msgstr "_Zabaliť"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:75
|
||||
#: ../src/ui/menu.c:77
|
||||
msgid "_Unroll"
|
||||
msgstr "_Rozbaliť"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:77
|
||||
#: ../src/ui/menu.c:79
|
||||
msgid "_Move"
|
||||
msgstr "Pre_miestniť"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:79
|
||||
#: ../src/ui/menu.c:81
|
||||
msgid "_Resize"
|
||||
msgstr "Zmeniť veľko_sť"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:81
|
||||
#: ../src/ui/menu.c:83
|
||||
msgid "Move Titlebar On_screen"
|
||||
msgstr "Presunúť titulok na _obrazovku"
|
||||
|
||||
#. separator
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
|
||||
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
|
||||
msgid "Always on _Top"
|
||||
msgstr "Vždy na_vrchu"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:88
|
||||
#: ../src/ui/menu.c:90
|
||||
msgid "_Always on Visible Workspace"
|
||||
msgstr "Vž_dy na viditeľnom pracovnom priestore"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:90
|
||||
#: ../src/ui/menu.c:92
|
||||
msgid "_Only on This Workspace"
|
||||
msgstr "_Len na tomto pracovnom priestore"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:92
|
||||
#: ../src/ui/menu.c:94
|
||||
msgid "Move to Workspace _Left"
|
||||
msgstr "Presunúť na pracovný priestor vľav_o"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:94
|
||||
#: ../src/ui/menu.c:96
|
||||
msgid "Move to Workspace R_ight"
|
||||
msgstr "Presunúť na pracovný priestor v_pravo"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:96
|
||||
#: ../src/ui/menu.c:98
|
||||
msgid "Move to Workspace _Up"
|
||||
msgstr "Presunúť na pracovný priestor _hore"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:98
|
||||
#: ../src/ui/menu.c:100
|
||||
msgid "Move to Workspace _Down"
|
||||
msgstr "Presunúť na pracovný priestor _dole"
|
||||
|
||||
#. separator
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:102
|
||||
#: ../src/ui/menu.c:104
|
||||
msgid "_Close"
|
||||
msgstr "_Zavrieť"
|
||||
|
||||
#: ../src/ui/menu.c:202
|
||||
#: ../src/ui/menu.c:204
|
||||
#, c-format
|
||||
msgid "Workspace %d%n"
|
||||
msgstr "Pracovná priestor %d%n"
|
||||
|
||||
#: ../src/ui/menu.c:212
|
||||
#: ../src/ui/menu.c:214
|
||||
#, c-format
|
||||
msgid "Workspace 1_0"
|
||||
msgstr "Pracovný priestor 1_0"
|
||||
|
||||
#: ../src/ui/menu.c:214
|
||||
#: ../src/ui/menu.c:216
|
||||
#, c-format
|
||||
msgid "Workspace %s%d"
|
||||
msgstr "Pracovný priestor %s%d"
|
||||
|
||||
#: ../src/ui/menu.c:384
|
||||
#: ../src/ui/menu.c:397
|
||||
msgid "Move to Another _Workspace"
|
||||
msgstr "P_resunúť na iný pracovný priestor"
|
||||
|
||||
@@ -1071,21 +1066,21 @@ msgstr ""
|
||||
# MČ: Preformuloval by som koniec: „platné sú len znaky A-Za-z0-9-_“
|
||||
# PK: color_name je asi nejaky atribut, to sa nepreklada, ked tak do zatvorky
|
||||
#: ../src/ui/theme.c:1219
|
||||
#, c-format
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
|
||||
"_ are valid"
|
||||
msgstr ""
|
||||
"V parametri color_name (názov farby) pre gtk:custom je neplatný znak „%c“, platné sú len "
|
||||
"V parametri názov_farby pre gtk:custom je neplatný znak „%c“, platné sú len "
|
||||
"znaky A-Za-z0-9-_"
|
||||
|
||||
#: ../src/ui/theme.c:1233
|
||||
#, c-format
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
|
||||
"fit the format"
|
||||
msgstr ""
|
||||
"Formát Gtk:custom je „gtk:custom(color_name,fallback)“, „%s“ tomu "
|
||||
"Formát Gtk:custom je „gtk:custom(názov_farby,fallback)“, „%s“ tomu "
|
||||
"nezodpovedá"
|
||||
|
||||
#: ../src/ui/theme.c:1278
|
||||
@@ -1271,20 +1266,20 @@ msgid ""
|
||||
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
|
||||
msgstr "Chýbajúce <frame state=„%s“ resize=„%s“ focus=„%s“ style=„whatever“/>"
|
||||
|
||||
#: ../src/ui/theme.c:5082
|
||||
#: ../src/ui/theme.c:5084
|
||||
#, c-format
|
||||
msgid "Failed to load theme \"%s\": %s\n"
|
||||
msgstr "Zlyhalo načítanie témy „%s“: %s\n"
|
||||
|
||||
# PK: prvok?
|
||||
# JK: XML značka (XML tag)
|
||||
#: ../src/ui/theme.c:5218 ../src/ui/theme.c:5225 ../src/ui/theme.c:5232
|
||||
#: ../src/ui/theme.c:5239 ../src/ui/theme.c:5246
|
||||
#: ../src/ui/theme.c:5220 ../src/ui/theme.c:5227 ../src/ui/theme.c:5234
|
||||
#: ../src/ui/theme.c:5241 ../src/ui/theme.c:5248
|
||||
#, c-format
|
||||
msgid "No <%s> set for theme \"%s\""
|
||||
msgstr "Pre tému „%s“ nie je nastavená <%s>"
|
||||
|
||||
#: ../src/ui/theme.c:5254
|
||||
#: ../src/ui/theme.c:5256
|
||||
#, c-format
|
||||
msgid ""
|
||||
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
|
||||
@@ -1293,13 +1288,13 @@ msgstr ""
|
||||
"Pre typ okna „%s“ nie je sada štýlov v téme „%s“, pridajte prvok <window "
|
||||
"type=„%s“ style_set=„whatever“/>"
|
||||
|
||||
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
|
||||
#: ../src/ui/theme.c:5663 ../src/ui/theme.c:5725 ../src/ui/theme.c:5788
|
||||
#, c-format
|
||||
msgid ""
|
||||
"User-defined constants must begin with a capital letter; \"%s\" does not"
|
||||
msgstr "Používateľské konštanty musia začínať veľkým písmenom, „%s“ nezačína"
|
||||
|
||||
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
|
||||
#: ../src/ui/theme.c:5671 ../src/ui/theme.c:5733 ../src/ui/theme.c:5796
|
||||
#, c-format
|
||||
msgid "Constant \"%s\" has already been defined"
|
||||
msgstr "Konštanta „%s“ už je definovaná"
|
||||
@@ -1402,7 +1397,7 @@ msgstr "<%s> musí uvádzať buď geometriu alebo rodiča, ktorý má geometriu"
|
||||
msgid "You must specify a background for an alpha value to be meaningful"
|
||||
msgstr "Ak má byť hodnota alpha zmysluplná, tak musíte vybrať nejaké pozadie"
|
||||
|
||||
# PM: asi atribút type
|
||||
# PM: asi atribút type
|
||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
|
||||
#: ../src/ui/theme-parser.c:1264
|
||||
#, fuzzy, c-format
|
||||
@@ -1564,7 +1559,6 @@ msgid "\"%s\" is not a valid value for resize attribute"
|
||||
msgstr "„%s“ nie je platná hodnota pre atribút zmeny veľkosti"
|
||||
|
||||
# PK: shaded states? to zatvorky daj popis co je resize
|
||||
# PM: skôr "pre stavy maximized (maximalizovaný)/shaded (zatienený)"
|
||||
#: ../src/ui/theme-parser.c:3147
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
@@ -1706,172 +1700,221 @@ msgstr "<%s> uvedený dvakrát pre túto tému"
|
||||
msgid "Failed to find a valid file for theme %s\n"
|
||||
msgstr "Zlyhalo nájdenie platného súboru pre tému%s\n"
|
||||
|
||||
#~ msgid "Usage: %s\n"
|
||||
#~ msgstr "Použitie: %s\n"
|
||||
#: ../src/ui/theme-viewer.c:99
|
||||
msgid "_Windows"
|
||||
msgstr "_Okná"
|
||||
|
||||
#~ msgid "_Windows"
|
||||
#~ msgstr "_Okná"
|
||||
#: ../src/ui/theme-viewer.c:100
|
||||
msgid "_Dialog"
|
||||
msgstr "_Dialógové okno"
|
||||
|
||||
#~ msgid "_Dialog"
|
||||
#~ msgstr "_Dialógové okno"
|
||||
#: ../src/ui/theme-viewer.c:101
|
||||
msgid "_Modal dialog"
|
||||
msgstr "_Modálne dialógové okno"
|
||||
|
||||
#~ msgid "_Modal dialog"
|
||||
#~ msgstr "_Modálne dialógové okno"
|
||||
#: ../src/ui/theme-viewer.c:102
|
||||
msgid "_Utility"
|
||||
msgstr "_Nástroje"
|
||||
|
||||
#~ msgid "_Utility"
|
||||
#~ msgstr "_Nástroje"
|
||||
|
||||
#~ msgid "_Splashscreen"
|
||||
#~ msgstr "Ú_vodná obrazovka"
|
||||
#: ../src/ui/theme-viewer.c:103
|
||||
msgid "_Splashscreen"
|
||||
msgstr "Ú_vodná obrazovka"
|
||||
|
||||
# MČ: nie som si istý prekladom „dok“, nemal by to byť „panel“?
|
||||
#~ msgid "_Top dock"
|
||||
#~ msgstr "_Horný panel"
|
||||
#: ../src/ui/theme-viewer.c:104
|
||||
msgid "_Top dock"
|
||||
msgstr "_Horný panel"
|
||||
|
||||
#~ msgid "_Bottom dock"
|
||||
#~ msgstr "_Spodný panel"
|
||||
#: ../src/ui/theme-viewer.c:105
|
||||
msgid "_Bottom dock"
|
||||
msgstr "_Spodný panel"
|
||||
|
||||
#~ msgid "_Left dock"
|
||||
#~ msgstr "Ľ_avý panel"
|
||||
#: ../src/ui/theme-viewer.c:106
|
||||
msgid "_Left dock"
|
||||
msgstr "Ľ_avý panel"
|
||||
|
||||
#~ msgid "_Right dock"
|
||||
#~ msgstr "_Pravý panel"
|
||||
#: ../src/ui/theme-viewer.c:107
|
||||
msgid "_Right dock"
|
||||
msgstr "_Pravý panel"
|
||||
|
||||
#~ msgid "_All docks"
|
||||
#~ msgstr "_Všetky panely"
|
||||
#: ../src/ui/theme-viewer.c:108
|
||||
msgid "_All docks"
|
||||
msgstr "_Všetky panely"
|
||||
|
||||
#~ msgid "Des_ktop"
|
||||
#~ msgstr "P_racovná plocha"
|
||||
#: ../src/ui/theme-viewer.c:109
|
||||
msgid "Des_ktop"
|
||||
msgstr "P_racovná plocha"
|
||||
|
||||
# tooltip
|
||||
#~ msgid "Open another one of these windows"
|
||||
#~ msgstr "Otvorí ďalšie z týchto okien"
|
||||
#: ../src/ui/theme-viewer.c:115
|
||||
msgid "Open another one of these windows"
|
||||
msgstr "Otvorí ďalšie z týchto okien"
|
||||
|
||||
# PK: prekladat to v uvodzovkach? nahlas bug
|
||||
# tooltip
|
||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
|
||||
#: ../src/ui/theme-viewer.c:117
|
||||
#, fuzzy
|
||||
#~ msgid "This is a demo button with an 'open' icon"
|
||||
#~ msgstr "Toto je ukážkové tlačidlo s ikonou „open“"
|
||||
msgid "This is a demo button with an 'open' icon"
|
||||
msgstr "Toto je ukážkové tlačidlo s ikonou „open“"
|
||||
|
||||
# tooltip
|
||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
|
||||
#: ../src/ui/theme-viewer.c:119
|
||||
#, fuzzy
|
||||
#~ msgid "This is a demo button with a 'quit' icon"
|
||||
#~ msgstr "Toto je ukážkové tlačidlo s ikonou „quit“"
|
||||
msgid "This is a demo button with a 'quit' icon"
|
||||
msgstr "Toto je ukážkové tlačidlo s ikonou „quit“"
|
||||
|
||||
# label
|
||||
#~ msgid "This is a sample message in a sample dialog"
|
||||
#~ msgstr "Toto je ukážková správa v ukážkovom dialógovom okne"
|
||||
#: ../src/ui/theme-viewer.c:248
|
||||
msgid "This is a sample message in a sample dialog"
|
||||
msgstr "Toto je ukážková správa v ukážkovom dialógovom okne"
|
||||
|
||||
# PK: falosna
|
||||
#~ msgid "Fake menu item %d\n"
|
||||
#~ msgstr "Falošná položka ponuky č. %d\n"
|
||||
#: ../src/ui/theme-viewer.c:328
|
||||
#, c-format
|
||||
msgid "Fake menu item %d\n"
|
||||
msgstr "Falošná položka ponuky č. %d\n"
|
||||
|
||||
#~ msgid "Border-only window"
|
||||
#~ msgstr "Okno len s okrajom"
|
||||
#: ../src/ui/theme-viewer.c:363
|
||||
msgid "Border-only window"
|
||||
msgstr "Okno len s okrajom"
|
||||
|
||||
#~ msgid "Bar"
|
||||
#~ msgstr "Lišta"
|
||||
#: ../src/ui/theme-viewer.c:365
|
||||
msgid "Bar"
|
||||
msgstr "Lišta"
|
||||
|
||||
#~ msgid "Normal Application Window"
|
||||
#~ msgstr "Normálne aplikačné okno"
|
||||
#: ../src/ui/theme-viewer.c:382
|
||||
msgid "Normal Application Window"
|
||||
msgstr "Normálne aplikačné okno"
|
||||
|
||||
#~ msgid "Dialog Box"
|
||||
#~ msgstr "Dialógové okno"
|
||||
#: ../src/ui/theme-viewer.c:386
|
||||
msgid "Dialog Box"
|
||||
msgstr "Dialógové okno"
|
||||
|
||||
#~ msgid "Modal Dialog Box"
|
||||
#~ msgstr "Modálne dialógové okno"
|
||||
#: ../src/ui/theme-viewer.c:390
|
||||
msgid "Modal Dialog Box"
|
||||
msgstr "Modálne dialógové okno"
|
||||
|
||||
#~ msgid "Utility Palette"
|
||||
#~ msgstr "Paleta nástrojov"
|
||||
#: ../src/ui/theme-viewer.c:394
|
||||
msgid "Utility Palette"
|
||||
msgstr "Paleta nástrojov"
|
||||
|
||||
#~ msgid "Torn-off Menu"
|
||||
#~ msgstr "Vypnúť ponuku"
|
||||
#: ../src/ui/theme-viewer.c:398
|
||||
msgid "Torn-off Menu"
|
||||
msgstr "Vypnúť ponuku"
|
||||
|
||||
#~ msgid "Border"
|
||||
#~ msgstr "Okraj"
|
||||
#: ../src/ui/theme-viewer.c:402
|
||||
msgid "Border"
|
||||
msgstr "Okraj"
|
||||
|
||||
#~ msgid "Attached Modal Dialog"
|
||||
#~ msgstr "Pričlenené modálne okno"
|
||||
#: ../src/ui/theme-viewer.c:406
|
||||
msgid "Attached Modal Dialog"
|
||||
msgstr "Pričlenené modálne okno"
|
||||
|
||||
#~ msgid "Button layout test %d"
|
||||
#~ msgstr "Test rozloženia tlačidiel č. %d"
|
||||
#: ../src/ui/theme-viewer.c:737
|
||||
#, c-format
|
||||
msgid "Button layout test %d"
|
||||
msgstr "Test rozloženia tlačidiel č. %d"
|
||||
|
||||
# PK: plural forms
|
||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
||||
#, fuzzy
|
||||
#~ msgid "%g milliseconds to draw one window frame"
|
||||
#~ msgstr "%g milisekúnd pre vykreslenie jedného rámca okna"
|
||||
#: ../src/ui/theme-viewer.c:766
|
||||
#, fuzzy, c-format
|
||||
msgid "%g milliseconds to draw one window frame"
|
||||
msgstr "%g milisekúnd pre vykreslenie jedného rámca okna"
|
||||
|
||||
#~ msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
|
||||
#~ msgstr "Použitie: metacity-theme-viewer [NÁZOVTÉMY]\n"
|
||||
#: ../src/ui/theme-viewer.c:811
|
||||
#, c-format
|
||||
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
|
||||
msgstr "Použitie: metacity-theme-viewer [NÁZOVTÉMY]\n"
|
||||
|
||||
#~ msgid "Error loading theme: %s\n"
|
||||
#~ msgstr "Chyba pri načítavaní témy: %s\n"
|
||||
#: ../src/ui/theme-viewer.c:818
|
||||
#, c-format
|
||||
msgid "Error loading theme: %s\n"
|
||||
msgstr "Chyba pri načítavaní témy: %s\n"
|
||||
|
||||
# PK: plural forms
|
||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
||||
#, fuzzy
|
||||
#~ msgid "Loaded theme \"%s\" in %g seconds\n"
|
||||
#~ msgstr "Téma „%s“ načítaná za %g sekúnd\n"
|
||||
#: ../src/ui/theme-viewer.c:824
|
||||
#, fuzzy, c-format
|
||||
msgid "Loaded theme \"%s\" in %g seconds\n"
|
||||
msgstr "Téma „%s“ načítaná za %g sekúnd\n"
|
||||
|
||||
# PK: inde titulku, aky je rozdiel
|
||||
#~ msgid "Normal Title Font"
|
||||
#~ msgstr "Obyčajné písmo titulku"
|
||||
#: ../src/ui/theme-viewer.c:869
|
||||
msgid "Normal Title Font"
|
||||
msgstr "Obyčajné písmo titulku"
|
||||
|
||||
#~ msgid "Small Title Font"
|
||||
#~ msgstr "Malé písmo titulku"
|
||||
#: ../src/ui/theme-viewer.c:875
|
||||
msgid "Small Title Font"
|
||||
msgstr "Malé písmo titulku"
|
||||
|
||||
#~ msgid "Large Title Font"
|
||||
#~ msgstr "Veľké písmo titulku"
|
||||
#: ../src/ui/theme-viewer.c:881
|
||||
msgid "Large Title Font"
|
||||
msgstr "Veľké písmo titulku"
|
||||
|
||||
#~ msgid "Button Layouts"
|
||||
#~ msgstr "Rozloženia tlačidiel"
|
||||
#: ../src/ui/theme-viewer.c:886
|
||||
msgid "Button Layouts"
|
||||
msgstr "Rozloženia tlačidiel"
|
||||
|
||||
#~ msgid "Benchmark"
|
||||
#~ msgstr "Test rýchlosti"
|
||||
#: ../src/ui/theme-viewer.c:891
|
||||
msgid "Benchmark"
|
||||
msgstr "Test rýchlosti"
|
||||
|
||||
#~ msgid "Window Title Goes Here"
|
||||
#~ msgstr "Sem príde názov okna"
|
||||
#: ../src/ui/theme-viewer.c:947
|
||||
msgid "Window Title Goes Here"
|
||||
msgstr "Sem príde názov okna"
|
||||
|
||||
# PK: plural forms
|
||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
||||
#, fuzzy
|
||||
#~ msgid ""
|
||||
#~ "Drew %d frames in %g client-side seconds (%g milliseconds per frame) and "
|
||||
#~ "%g seconds wall clock time including X server resources (%g milliseconds "
|
||||
#~ "per frame)\n"
|
||||
#~ msgstr ""
|
||||
#~ "Vykreslených %d rámcov za %g sekúnd na strane klienta (%g milisekúnd na "
|
||||
#~ "rámec) a %g sekúnd celkového času vrátane zdrojov servera X (%g "
|
||||
#~ "milisekúnd na rámec)\n"
|
||||
#: ../src/ui/theme-viewer.c:1053
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Drew %d frames in %g client-side seconds (%g milliseconds per frame) and %g "
|
||||
"seconds wall clock time including X server resources (%g milliseconds per "
|
||||
"frame)\n"
|
||||
msgstr ""
|
||||
"Vykreslených %d rámcov za %g sekúnd na strane klienta (%g milisekúnd na "
|
||||
"rámec) a %g sekúnd celkového času vrátane zdrojov servera X (%g milisekúnd "
|
||||
"na rámec)\n"
|
||||
|
||||
#~ msgid "position expression test returned TRUE but set error"
|
||||
#~ msgstr "test výrazu polohy vrátil TRUE, ale nastavil chybu"
|
||||
#: ../src/ui/theme-viewer.c:1273
|
||||
msgid "position expression test returned TRUE but set error"
|
||||
msgstr "test výrazu polohy vrátil TRUE, ale nastavil chybu"
|
||||
|
||||
#~ msgid "position expression test returned FALSE but didn't set error"
|
||||
#~ msgstr "test výrazu polohy vrátil FALSE, ale nenastavil chybu"
|
||||
#: ../src/ui/theme-viewer.c:1275
|
||||
msgid "position expression test returned FALSE but didn't set error"
|
||||
msgstr "test výrazu polohy vrátil FALSE, ale nenastavil chybu"
|
||||
|
||||
#~ msgid "Error was expected but none given"
|
||||
#~ msgstr "Bola očakávaná chyba, ale žiadna nenastala"
|
||||
#: ../src/ui/theme-viewer.c:1279
|
||||
msgid "Error was expected but none given"
|
||||
msgstr "Bola očakávaná chyba, ale žiadna nenastala"
|
||||
|
||||
#~ msgid "Error %d was expected but %d given"
|
||||
#~ msgstr "Bola očakávaná chyba %d, ale nastala %d"
|
||||
#: ../src/ui/theme-viewer.c:1281
|
||||
#, c-format
|
||||
msgid "Error %d was expected but %d given"
|
||||
msgstr "Bola očakávaná chyba %d, ale nastala %d"
|
||||
|
||||
#~ msgid "Error not expected but one was returned: %s"
|
||||
#~ msgstr "Chyba nebola očakávaná, ale bola vrátená: %s"
|
||||
#: ../src/ui/theme-viewer.c:1287
|
||||
#, c-format
|
||||
msgid "Error not expected but one was returned: %s"
|
||||
msgstr "Chyba nebola očakávaná, ale bola vrátená: %s"
|
||||
|
||||
#~ msgid "x value was %d, %d was expected"
|
||||
#~ msgstr "hodnota x bola %d, očakávaná bola %d"
|
||||
#: ../src/ui/theme-viewer.c:1291
|
||||
#, c-format
|
||||
msgid "x value was %d, %d was expected"
|
||||
msgstr "hodnota x bola %d, očakávaná bola %d"
|
||||
|
||||
#~ msgid "y value was %d, %d was expected"
|
||||
#~ msgstr "hodnota y bola %d, očakávaná bola %d"
|
||||
#: ../src/ui/theme-viewer.c:1294
|
||||
#, c-format
|
||||
msgid "y value was %d, %d was expected"
|
||||
msgstr "hodnota y bola %d, očakávaná bola %d"
|
||||
|
||||
# PK: plural forms
|
||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
||||
#, fuzzy
|
||||
#~ msgid ""
|
||||
#~ "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
|
||||
#~ msgstr ""
|
||||
#~ "%d výrazov pre súradnice analyzovaných za %g sekúnd (priemer %g sekúnd)\n"
|
||||
#: ../src/ui/theme-viewer.c:1359
|
||||
#, fuzzy, c-format
|
||||
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
|
||||
msgstr ""
|
||||
"%d výrazov pre súradnice analyzovaných za %g sekúnd (priemer %g sekúnd)\n"
|
||||
|
||||
758
po/sr@latin.po
758
po/sr@latin.po
File diff suppressed because it is too large
Load Diff
1228
po/zh_CN.po
1228
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
524
po/zh_HK.po
524
po/zh_HK.po
File diff suppressed because it is too large
Load Diff
524
po/zh_TW.po
524
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
168
src/Makefile.am
168
src/Makefile.am
@@ -1,15 +1,17 @@
|
||||
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
|
||||
.AUTOPARALLEL:
|
||||
|
||||
lib_LTLIBRARIES = libmutter.la
|
||||
lib_LTLIBRARIES = libmutter-wayland.la
|
||||
|
||||
SUBDIRS=compositor/plugins
|
||||
|
||||
INCLUDES= \
|
||||
-DCLUTTER_ENABLE_COMPOSITOR_API \
|
||||
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
|
||||
$(MUTTER_CFLAGS) \
|
||||
-I$(top_builddir) \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/core \
|
||||
-I$(srcdir)/ui \
|
||||
@@ -27,17 +29,28 @@ INCLUDES= \
|
||||
-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) \
|
||||
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
|
||||
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
|
||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
|
||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
|
||||
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
|
||||
|
||||
mutter_built_sources = \
|
||||
$(dbus_idle_built_sources) \
|
||||
$(dbus_xrandr_built_sources) \
|
||||
mutter-enum-types.h \
|
||||
mutter-enum-types.c
|
||||
$(dbus_idle_built_sources) \
|
||||
$(dbus_xrandr_built_sources) \
|
||||
mutter-enum-types.h \
|
||||
mutter-enum-types.c \
|
||||
gtk-shell-protocol.c \
|
||||
gtk-shell-server-protocol.h \
|
||||
xdg-shell-protocol.c \
|
||||
xdg-shell-server-protocol.h \
|
||||
xserver-protocol.c \
|
||||
xserver-server-protocol.h
|
||||
|
||||
libmutter_la_SOURCES = \
|
||||
core/async-getprop.c \
|
||||
core/async-getprop.h \
|
||||
wayland_protocols = \
|
||||
wayland/protocol/gtk-shell.xml \
|
||||
wayland/protocol/xdg-shell.xml \
|
||||
wayland/protocol/xserver.xml
|
||||
|
||||
libmutter_wayland_la_SOURCES = \
|
||||
core/above-tab-keycode.c \
|
||||
core/barrier.c \
|
||||
meta/barrier.h \
|
||||
core/bell.c \
|
||||
@@ -65,7 +78,13 @@ libmutter_la_SOURCES = \
|
||||
compositor/meta-shadow-factory.c \
|
||||
compositor/meta-shadow-factory-private.h \
|
||||
compositor/meta-shaped-texture.c \
|
||||
compositor/meta-shaped-texture-private.h \
|
||||
compositor/meta-shaped-texture-private.h \
|
||||
compositor/meta-surface-actor.c \
|
||||
compositor/meta-surface-actor.h \
|
||||
compositor/meta-surface-actor-x11.c \
|
||||
compositor/meta-surface-actor-x11.h \
|
||||
compositor/meta-surface-actor-wayland.c \
|
||||
compositor/meta-surface-actor-wayland.h \
|
||||
compositor/meta-texture-rectangle.c \
|
||||
compositor/meta-texture-rectangle.h \
|
||||
compositor/meta-texture-tower.c \
|
||||
@@ -86,7 +105,6 @@ libmutter_la_SOURCES = \
|
||||
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 \
|
||||
@@ -104,13 +122,6 @@ libmutter_la_SOURCES = \
|
||||
core/frame.h \
|
||||
ui/gradient.c \
|
||||
meta/gradient.h \
|
||||
core/group-private.h \
|
||||
core/group-props.c \
|
||||
core/group-props.h \
|
||||
core/group.c \
|
||||
meta/group.h \
|
||||
core/iconcache.c \
|
||||
core/iconcache.h \
|
||||
core/keybindings.c \
|
||||
core/keybindings-private.h \
|
||||
core/main.c \
|
||||
@@ -121,6 +132,7 @@ libmutter_la_SOURCES = \
|
||||
core/meta-xrandr-shared.h \
|
||||
core/monitor.c \
|
||||
core/monitor-config.c \
|
||||
core/monitor-kms.c \
|
||||
core/monitor-private.h \
|
||||
core/monitor-xrandr.c \
|
||||
core/mutter-Xatomtype.h \
|
||||
@@ -132,8 +144,6 @@ libmutter_la_SOURCES = \
|
||||
core/screen-private.h \
|
||||
meta/screen.h \
|
||||
meta/types.h \
|
||||
core/session.c \
|
||||
core/session.h \
|
||||
core/stack.c \
|
||||
core/stack.h \
|
||||
core/stack-tracker.c \
|
||||
@@ -141,15 +151,11 @@ libmutter_la_SOURCES = \
|
||||
core/util.c \
|
||||
meta/util.h \
|
||||
core/util-private.h \
|
||||
core/window-props.c \
|
||||
core/window-props.h \
|
||||
core/window.c \
|
||||
core/window-private.h \
|
||||
meta/window.h \
|
||||
core/workspace.c \
|
||||
core/workspace-private.h \
|
||||
core/xprops.c \
|
||||
core/xprops.h \
|
||||
meta/common.h \
|
||||
core/core.h \
|
||||
ui/ui.h \
|
||||
@@ -165,13 +171,52 @@ libmutter_la_SOURCES = \
|
||||
ui/theme.c \
|
||||
meta/theme.h \
|
||||
ui/theme-private.h \
|
||||
ui/ui.c
|
||||
ui/ui.c \
|
||||
x11/iconcache.c \
|
||||
x11/iconcache.h \
|
||||
x11/async-getprop.c \
|
||||
x11/async-getprop.h \
|
||||
x11/group-private.h \
|
||||
x11/group-props.c \
|
||||
x11/group-props.h \
|
||||
x11/group.c \
|
||||
meta/group.h \
|
||||
x11/session.c \
|
||||
x11/session.h \
|
||||
x11/window-props.c \
|
||||
x11/window-props.h \
|
||||
x11/window-x11.c \
|
||||
x11/window-x11.h \
|
||||
x11/window-x11-private.h \
|
||||
x11/xprops.c \
|
||||
x11/xprops.h \
|
||||
wayland/meta-wayland.c \
|
||||
wayland/meta-wayland.h \
|
||||
wayland/meta-wayland-private.h \
|
||||
wayland/meta-xwayland-private.h \
|
||||
wayland/meta-xwayland.c \
|
||||
wayland/meta-wayland-data-device.c \
|
||||
wayland/meta-wayland-data-device.h \
|
||||
wayland/meta-wayland-keyboard.c \
|
||||
wayland/meta-wayland-keyboard.h \
|
||||
wayland/meta-wayland-pointer.c \
|
||||
wayland/meta-wayland-pointer.h \
|
||||
wayland/meta-wayland-seat.c \
|
||||
wayland/meta-wayland-seat.h \
|
||||
wayland/meta-wayland-stage.h \
|
||||
wayland/meta-wayland-stage.c \
|
||||
wayland/meta-wayland-surface.c \
|
||||
wayland/meta-wayland-surface.h \
|
||||
wayland/meta-wayland-types.h \
|
||||
wayland/meta-wayland-versions.h \
|
||||
wayland/meta-weston-launch.c \
|
||||
wayland/meta-weston-launch.h
|
||||
|
||||
nodist_libmutter_la_SOURCES = \
|
||||
nodist_libmutter_wayland_la_SOURCES = \
|
||||
$(mutter_built_sources)
|
||||
|
||||
libmutter_la_LDFLAGS = -no-undefined
|
||||
libmutter_la_LIBADD = $(MUTTER_LIBS)
|
||||
libmutter_wayland_la_LDFLAGS = -no-undefined
|
||||
libmutter_wayland_la_LIBADD = $(MUTTER_LIBS)
|
||||
|
||||
# Headers installed for plugins; introspected information will
|
||||
# be extracted into Mutter-<version>.gir
|
||||
@@ -209,16 +254,27 @@ libmutterinclude_base_headers = \
|
||||
libmutterinclude_extra_headers = \
|
||||
meta/atomnames.h
|
||||
|
||||
libmutterincludedir = $(includedir)/mutter/meta
|
||||
libmutterincludedir = $(includedir)/mutter-wayland/meta
|
||||
|
||||
libmutterinclude_HEADERS = \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(libmutterinclude_extra_headers)
|
||||
|
||||
bin_PROGRAMS=mutter
|
||||
bin_PROGRAMS=mutter-wayland
|
||||
|
||||
mutter_SOURCES = core/mutter.c
|
||||
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
mutter_wayland_SOURCES = core/mutter.c
|
||||
mutter_wayland_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
|
||||
|
||||
bin_PROGRAMS+=mutter-launch
|
||||
|
||||
mutter_launch_SOURCES = wayland/weston-launch.c wayland/weston-launch.h
|
||||
|
||||
mutter_launch_CFLAGS = $(MUTTER_LAUNCH_CFLAGS) -DLIBDIR=\"$(libdir)\"
|
||||
mutter_launch_LDFLAGS = $(MUTTER_LAUNCH_LIBS) -lpam
|
||||
|
||||
install-exec-hook:
|
||||
-chown root $(DESTDIR)$(bindir)/mutter-launch
|
||||
-chmod u+s $(DESTDIR)$(bindir)/mutter-launch
|
||||
|
||||
if HAVE_INTROSPECTION
|
||||
include $(INTROSPECTION_MAKEFILE)
|
||||
@@ -240,41 +296,36 @@ typelib_DATA = Meta-$(api_version).typelib
|
||||
|
||||
INTROSPECTION_GIRS = Meta-$(api_version).gir
|
||||
|
||||
Meta-$(api_version).gir: libmutter.la
|
||||
Meta-$(api_version).gir: libmutter-wayland.la
|
||||
@META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0
|
||||
@META_GIR@_EXPORT_PACKAGES = libmutter
|
||||
@META_GIR@_EXPORT_PACKAGES = libmutter-wayland
|
||||
@META_GIR@_CFLAGS = $(INCLUDES)
|
||||
@META_GIR@_LIBS = libmutter.la
|
||||
@META_GIR@_LIBS = libmutter-wayland.la
|
||||
@META_GIR@_FILES = \
|
||||
mutter-enum-types.h \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(filter %.c,$(libmutter_la_SOURCES) $(nodist_libmutter_la_SOURCES))
|
||||
$(filter %.c,$(libmutter_wayland_la_SOURCES) $(nodist_libmutter_wayland_la_SOURCES))
|
||||
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
|
||||
|
||||
endif
|
||||
|
||||
testboxes_SOURCES = core/testboxes.c
|
||||
testgradient_SOURCES = ui/testgradient.c
|
||||
testasyncgetprop_SOURCES = core/testasyncgetprop.c
|
||||
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
|
||||
|
||||
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
|
||||
|
||||
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testboxes_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
|
||||
testgradient_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
|
||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
|
||||
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
desktopfilesdir=$(datadir)/applications
|
||||
desktopfiles_in_files=mutter.desktop.in
|
||||
desktopfiles_in_files=mutter-wayland.desktop.in
|
||||
desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop)
|
||||
desktopfiles_DATA = $(desktopfiles_files)
|
||||
|
||||
wmpropertiesdir=$(datadir)/gnome/wm-properties
|
||||
wmproperties_in_files=mutter-wm.desktop.in
|
||||
wmproperties_files=$(wmproperties_in_files:.desktop.in=.desktop)
|
||||
wmproperties_DATA = $(wmproperties_files)
|
||||
|
||||
xmldir = @GNOME_KEYBINDINGS_KEYSDIR@
|
||||
xml_in_files = \
|
||||
50-mutter-navigation.xml.in \
|
||||
@@ -282,7 +333,9 @@ xml_in_files = \
|
||||
50-mutter-windows.xml.in
|
||||
xml_DATA = $(xml_in_files:.xml.in=.xml)
|
||||
|
||||
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml
|
||||
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
|
||||
|
||||
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml org.gnome.mutter.wayland.gschema.xml
|
||||
@INTLTOOL_XML_NOMERGE_RULE@
|
||||
@GSETTINGS_RULES@
|
||||
|
||||
@@ -290,9 +343,10 @@ convertdir = $(datadir)/GConf/gsettings
|
||||
convert_DATA = mutter-schemas.convert
|
||||
|
||||
CLEANFILES = \
|
||||
mutter.desktop \
|
||||
mutter-wayland.desktop \
|
||||
mutter-wm.desktop \
|
||||
org.gnome.mutter.gschema.xml \
|
||||
org.gnome.mutter.wayland.gschema.xml \
|
||||
$(xml_DATA) \
|
||||
$(mutter_built_sources) \
|
||||
$(typelib_DATA) \
|
||||
@@ -300,7 +354,7 @@ CLEANFILES = \
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
|
||||
pkgconfig_DATA = libmutter.pc mutter-plugins.pc
|
||||
pkgconfig_DATA = libmutter-wayland.pc
|
||||
|
||||
EXTRA_DIST=$(desktopfiles_files) \
|
||||
$(wmproperties_files) \
|
||||
@@ -308,14 +362,14 @@ EXTRA_DIST=$(desktopfiles_files) \
|
||||
$(desktopfiles_in_files) \
|
||||
$(wmproperties_in_files) \
|
||||
$(xml_in_files) \
|
||||
$(wayland_protocols) \
|
||||
org.gnome.mutter.gschema.xml.in \
|
||||
idle-monitor.xml \
|
||||
xrandr.xml \
|
||||
org.gnome.mutter.wayland.gschema.xml.in \
|
||||
mutter-schemas.convert \
|
||||
libmutter.pc.in \
|
||||
mutter-plugins.pc.in \
|
||||
libmutter-wayland.pc.in \
|
||||
mutter-enum-types.h.in \
|
||||
mutter-enum-types.c.in
|
||||
mutter-enum-types.c.in \
|
||||
xrandr.xml idle-monitor.xml
|
||||
|
||||
BUILT_SOURCES = $(mutter_built_sources)
|
||||
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
|
||||
@@ -349,7 +403,6 @@ $(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
|
||||
--generate-c-code meta-dbus-xrandr \
|
||||
$(srcdir)/xrandr.xml
|
||||
|
||||
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
|
||||
|
||||
$(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
|
||||
$(AM_V_GEN)gdbus-codegen \
|
||||
@@ -358,3 +411,8 @@ $(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
|
||||
--generate-c-code meta-dbus-idle-monitor \
|
||||
--c-generate-object-manager \
|
||||
$(srcdir)/idle-monitor.xml
|
||||
|
||||
%-protocol.c : $(srcdir)/wayland/protocol/%.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
|
||||
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@
|
||||
|
||||
@@ -19,16 +19,10 @@ struct _MetaCompositor
|
||||
|
||||
guint repaint_func_id;
|
||||
|
||||
ClutterActor *shadow_src;
|
||||
|
||||
MetaPlugin *modal_plugin;
|
||||
|
||||
gint64 server_time_query_time;
|
||||
gint64 server_time_offset;
|
||||
|
||||
guint server_time_is_monotonic_time : 1;
|
||||
guint show_redraw : 1;
|
||||
guint debug : 1;
|
||||
guint no_mipmaps : 1;
|
||||
};
|
||||
|
||||
@@ -36,10 +30,9 @@ struct _MetaCompScreen
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
ClutterActor *stage, *window_group, *top_window_group, *overlay_group;
|
||||
ClutterActor *stage, *window_group, *top_window_group;
|
||||
ClutterActor *background_actor;
|
||||
GList *windows;
|
||||
GHashTable *windows_by_xid;
|
||||
Window output;
|
||||
|
||||
CoglOnscreen *onscreen;
|
||||
@@ -70,6 +63,4 @@ void meta_end_modal_for_plugin (MetaScreen *screen,
|
||||
gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
|
||||
gint64 monotonic_time);
|
||||
|
||||
void meta_check_end_modal (MetaScreen *screen);
|
||||
|
||||
#endif /* META_COMPOSITOR_PRIVATE_H */
|
||||
|
||||
@@ -65,7 +65,6 @@
|
||||
#include <meta/window.h>
|
||||
#include "compositor-private.h"
|
||||
#include <meta/compositor-mutter.h>
|
||||
#include "xprops.h"
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/main.h>
|
||||
#include <meta/meta-background-actor.h>
|
||||
@@ -76,11 +75,17 @@
|
||||
#include "window-private.h" /* to check window->hidden */
|
||||
#include "display-private.h" /* for meta_display_lookup_x_window() */
|
||||
#include "util-private.h"
|
||||
#include "frame.h"
|
||||
#include <X11/extensions/shape.h>
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
|
||||
/* #define DEBUG_TRACE g_print */
|
||||
#define DEBUG_TRACE(X)
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
static gboolean
|
||||
is_modal (MetaDisplay *display)
|
||||
{
|
||||
return display->grab_op == META_GRAB_OP_COMPOSITOR;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
composite_at_least_version (MetaDisplay *display, int maj, int min)
|
||||
@@ -105,13 +110,8 @@ meta_finish_workspace_switch (MetaCompScreen *info)
|
||||
for (l = info->windows; l; l = l->next)
|
||||
meta_window_actor_sync_visibility (l->data);
|
||||
|
||||
/*
|
||||
* Fix up stacking order in case the plugin messed it up.
|
||||
*/
|
||||
/* Fix up stacking order. */
|
||||
sync_actor_stacking (info);
|
||||
|
||||
/* printf ("... FINISHED DESKTOP SWITCH\n"); */
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@@ -137,34 +137,13 @@ meta_compositor_destroy (MetaCompositor *compositor)
|
||||
clutter_threads_remove_repaint_func (compositor->repaint_func_id);
|
||||
}
|
||||
|
||||
static void
|
||||
add_win (MetaWindow *window)
|
||||
{
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
g_return_if_fail (info != NULL);
|
||||
|
||||
meta_window_actor_new (window);
|
||||
|
||||
sync_actor_stacking (info);
|
||||
}
|
||||
|
||||
static void
|
||||
process_damage (MetaCompositor *compositor,
|
||||
XDamageNotifyEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
|
||||
if (window == NULL)
|
||||
return;
|
||||
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (window_actor == NULL)
|
||||
return;
|
||||
|
||||
meta_window_actor_process_damage (window_actor, event);
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
meta_window_actor_process_x11_damage (window_actor, event);
|
||||
}
|
||||
|
||||
static Window
|
||||
@@ -275,19 +254,27 @@ void
|
||||
meta_set_stage_input_region (MetaScreen *screen,
|
||||
XserverRegion region)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
||||
|
||||
XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
|
||||
|
||||
/* It's generally a good heuristic that when a crossing event is generated because
|
||||
* we reshape the overlay, we don't want it to affect focus-follows-mouse focus -
|
||||
* it's not the user doing something, it's the environment changing under the user.
|
||||
/* As a wayland compositor we can simply ignore all this trickery
|
||||
* for setting an input region on the stage for capturing events in
|
||||
* clutter since all input comes to us first and we get to choose
|
||||
* who else sees them.
|
||||
*/
|
||||
meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy));
|
||||
XFixesSetWindowShapeRegion (xdpy, info->output, ShapeInput, 0, 0, region);
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
||||
|
||||
XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
|
||||
|
||||
/* It's generally a good heuristic that when a crossing event is generated because
|
||||
* we reshape the overlay, we don't want it to affect focus-follows-mouse focus -
|
||||
* it's not the user doing something, it's the environment changing under the user.
|
||||
*/
|
||||
meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy));
|
||||
XFixesSetWindowShapeRegion (xdpy, info->output, ShapeInput, 0, 0, region);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -335,6 +322,9 @@ meta_stage_is_focused (MetaScreen *screen)
|
||||
ClutterStage *stage;
|
||||
Window window;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
return TRUE;
|
||||
|
||||
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
|
||||
if (!stage)
|
||||
return FALSE;
|
||||
@@ -347,34 +337,19 @@ meta_stage_is_focused (MetaScreen *screen)
|
||||
return (screen->display->focus_xwindow == window);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
static gboolean
|
||||
begin_modal_x11 (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
{
|
||||
/* To some extent this duplicates code in meta_display_begin_grab_op(), but there
|
||||
* are significant differences in how we handle grabs that make it difficult to
|
||||
* merge the two.
|
||||
*/
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
ClutterStage *stage;
|
||||
Window grab_window;
|
||||
Cursor cursor = None;
|
||||
gboolean pointer_grabbed = FALSE;
|
||||
gboolean keyboard_grabbed = FALSE;
|
||||
int result;
|
||||
|
||||
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
|
||||
if (!stage)
|
||||
return FALSE;
|
||||
|
||||
grab_window = clutter_x11_get_stage_window (stage);
|
||||
|
||||
if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
|
||||
return FALSE;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
Window grab_window = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
||||
int result;
|
||||
gboolean pointer_grabbed = FALSE;
|
||||
gboolean keyboard_grabbed = FALSE;
|
||||
|
||||
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
|
||||
{
|
||||
@@ -391,7 +366,7 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
grab_window,
|
||||
timestamp,
|
||||
cursor,
|
||||
None,
|
||||
XIGrabModeAsync, XIGrabModeAsync,
|
||||
False, /* owner_events */
|
||||
&mask);
|
||||
@@ -424,14 +399,6 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
keyboard_grabbed = TRUE;
|
||||
}
|
||||
|
||||
display->grab_op = META_GRAB_OP_COMPOSITOR;
|
||||
display->grab_window = NULL;
|
||||
display->grab_screen = screen;
|
||||
display->grab_have_pointer = TRUE;
|
||||
display->grab_have_keyboard = TRUE;
|
||||
|
||||
compositor->modal_plugin = plugin;
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
@@ -443,46 +410,59 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
{
|
||||
/* To some extent this duplicates code in meta_display_begin_grab_op(), but there
|
||||
* are significant differences in how we handle grabs that make it difficult to
|
||||
* merge the two.
|
||||
*/
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
gboolean ok;
|
||||
|
||||
if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE)
|
||||
return FALSE;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
ok = TRUE;
|
||||
else
|
||||
ok = begin_modal_x11 (screen, plugin, options, timestamp);
|
||||
if (!ok)
|
||||
return FALSE;
|
||||
|
||||
display->grab_op = META_GRAB_OP_COMPOSITOR;
|
||||
display->grab_window = NULL;
|
||||
display->grab_screen = screen;
|
||||
display->grab_have_pointer = TRUE;
|
||||
display->grab_have_keyboard = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_end_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
|
||||
g_return_if_fail (compositor->modal_plugin == plugin);
|
||||
g_return_if_fail (is_modal (display));
|
||||
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||
}
|
||||
|
||||
display->grab_op = META_GRAB_OP_NONE;
|
||||
display->grab_window = NULL;
|
||||
display->grab_screen = NULL;
|
||||
display->grab_have_pointer = FALSE;
|
||||
display->grab_have_keyboard = FALSE;
|
||||
|
||||
compositor->modal_plugin = NULL;
|
||||
}
|
||||
|
||||
/* This is used when reloading plugins to make sure we don't have
|
||||
* a left-over modal grab for this screen.
|
||||
*/
|
||||
void
|
||||
meta_check_end_modal (MetaScreen *screen)
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
|
||||
if (compositor->modal_plugin &&
|
||||
meta_plugin_get_screen (compositor->modal_plugin) == screen)
|
||||
{
|
||||
meta_end_modal_for_plugin (screen,
|
||||
compositor->modal_plugin,
|
||||
|
||||
CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -494,6 +474,9 @@ after_stage_paint (ClutterStage *stage,
|
||||
|
||||
for (l = info->windows; l; l = l->next)
|
||||
meta_window_actor_post_paint (l->data);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ());
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -547,8 +530,9 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
MetaCompScreen *info;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
Window xwin;
|
||||
Window xwin = None;
|
||||
gint width, height;
|
||||
MetaWaylandCompositor *wayland_compositor;
|
||||
|
||||
/* Check if the screen is already managed */
|
||||
if (meta_screen_get_compositor_data (screen))
|
||||
@@ -564,7 +548,56 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
|
||||
meta_screen_set_cm_selection (screen);
|
||||
|
||||
info->stage = clutter_stage_new ();
|
||||
/* We will have already created a stage if running as a wayland
|
||||
* compositor... */
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
wayland_compositor = meta_wayland_compositor_get_default ();
|
||||
info->stage = wayland_compositor->stage;
|
||||
|
||||
meta_screen_get_size (screen, &width, &height);
|
||||
clutter_actor_set_size (info->stage, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
info->stage = clutter_stage_new ();
|
||||
|
||||
meta_screen_get_size (screen, &width, &height);
|
||||
clutter_actor_realize (info->stage);
|
||||
|
||||
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
||||
|
||||
XResizeWindow (xdisplay, xwin, width, height);
|
||||
|
||||
{
|
||||
long event_mask;
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
XWindowAttributes attr;
|
||||
|
||||
meta_core_add_old_event_mask (xdisplay, xwin, &mask);
|
||||
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
XISetMask (mask.mask, XI_FocusIn);
|
||||
XISetMask (mask.mask, XI_FocusOut);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
XIClearMask (mask.mask, XI_TouchBegin);
|
||||
XIClearMask (mask.mask, XI_TouchEnd);
|
||||
XIClearMask (mask.mask, XI_TouchUpdate);
|
||||
XISelectEvents (xdisplay, xwin, &mask, 1);
|
||||
|
||||
event_mask = ExposureMask | PropertyChangeMask | StructureNotifyMask;
|
||||
if (XGetWindowAttributes (xdisplay, xwin, &attr))
|
||||
event_mask |= attr.your_event_mask;
|
||||
|
||||
XSelectInput (xdisplay, xwin, event_mask);
|
||||
}
|
||||
}
|
||||
|
||||
clutter_stage_set_paint_callback (CLUTTER_STAGE (info->stage),
|
||||
after_stage_paint,
|
||||
@@ -573,80 +606,41 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
|
||||
clutter_stage_set_sync_delay (CLUTTER_STAGE (info->stage), META_SYNC_DELAY);
|
||||
|
||||
meta_screen_get_size (screen, &width, &height);
|
||||
clutter_actor_realize (info->stage);
|
||||
|
||||
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
||||
|
||||
XResizeWindow (xdisplay, xwin, width, height);
|
||||
|
||||
{
|
||||
long event_mask;
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
XWindowAttributes attr;
|
||||
|
||||
meta_core_add_old_event_mask (xdisplay, xwin, &mask);
|
||||
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
XISetMask (mask.mask, XI_FocusIn);
|
||||
XISetMask (mask.mask, XI_FocusOut);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
XIClearMask (mask.mask, XI_TouchBegin);
|
||||
XIClearMask (mask.mask, XI_TouchEnd);
|
||||
XIClearMask (mask.mask, XI_TouchUpdate);
|
||||
XISelectEvents (xdisplay, xwin, &mask, 1);
|
||||
|
||||
event_mask = ExposureMask | PropertyChangeMask | StructureNotifyMask;
|
||||
if (XGetWindowAttributes (xdisplay, xwin, &attr))
|
||||
event_mask |= attr.your_event_mask;
|
||||
|
||||
XSelectInput (xdisplay, xwin, event_mask);
|
||||
}
|
||||
|
||||
info->window_group = meta_window_group_new (screen);
|
||||
info->top_window_group = meta_window_group_new (screen);
|
||||
|
||||
clutter_actor_add_child (info->stage, info->window_group);
|
||||
clutter_actor_add_child (info->stage, info->top_window_group);
|
||||
|
||||
info->output = get_output_window (screen);
|
||||
XReparentWindow (xdisplay, xwin, info->output, 0, 0);
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
/* NB: When running as a wayland compositor we don't need an X
|
||||
* composite overlay window, and we don't need to play any input
|
||||
* region tricks to redirect events into clutter. */
|
||||
info->output = None;
|
||||
}
|
||||
else
|
||||
{
|
||||
info->output = get_output_window (screen);
|
||||
XReparentWindow (xdisplay, xwin, info->output, 0, 0);
|
||||
|
||||
/* Make sure there isn't any left-over output shape on the
|
||||
* overlay window by setting the whole screen to be an
|
||||
* output region.
|
||||
*
|
||||
* Note: there doesn't seem to be any real chance of that
|
||||
* because the X server will destroy the overlay window
|
||||
* when the last client using it exits.
|
||||
*/
|
||||
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
|
||||
meta_empty_stage_input_region (screen);
|
||||
|
||||
info->output = get_output_window (screen);
|
||||
XReparentWindow (xdisplay, xwin, info->output, 0, 0);
|
||||
/* Make sure there isn't any left-over output shape on the
|
||||
* overlay window by setting the whole screen to be an
|
||||
* output region.
|
||||
*
|
||||
* Note: there doesn't seem to be any real chance of that
|
||||
* because the X server will destroy the overlay window
|
||||
* when the last client using it exits.
|
||||
*/
|
||||
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
|
||||
|
||||
meta_empty_stage_input_region (screen);
|
||||
|
||||
/* Make sure there isn't any left-over output shape on the
|
||||
* overlay window by setting the whole screen to be an
|
||||
* output region.
|
||||
*
|
||||
* Note: there doesn't seem to be any real chance of that
|
||||
* because the X server will destroy the overlay window
|
||||
* when the last client using it exits.
|
||||
*/
|
||||
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
|
||||
|
||||
/* Map overlay window before redirecting windows offscreen so we catch their
|
||||
* contents until we show the stage.
|
||||
*/
|
||||
XMapWindow (xdisplay, info->output);
|
||||
/* Map overlay window before redirecting windows offscreen so we catch their
|
||||
* contents until we show the stage.
|
||||
*/
|
||||
XMapWindow (xdisplay, info->output);
|
||||
}
|
||||
|
||||
redirect_windows (compositor, screen);
|
||||
|
||||
@@ -657,28 +651,38 @@ void
|
||||
meta_compositor_unmanage_screen (MetaCompositor *compositor,
|
||||
MetaScreen *screen)
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
Window xroot = meta_screen_get_xroot (screen);
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
Window xroot = meta_screen_get_xroot (screen);
|
||||
|
||||
/* This is the most important part of cleanup - we have to do this
|
||||
* before giving up the window manager selection or the next
|
||||
* window manager won't be able to redirect subwindows */
|
||||
XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
|
||||
/* This is the most important part of cleanup - we have to do this
|
||||
* before giving up the window manager selection or the next
|
||||
* window manager won't be able to redirect subwindows */
|
||||
XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Shapes the cow so that the given window is exposed,
|
||||
* when metaWindow is NULL it clears the shape again
|
||||
/**
|
||||
* meta_shape_cow_for_window:
|
||||
* @screen: A #MetaScreen
|
||||
* @window: (allow-none): A #MetaWindow to shape the COW for
|
||||
*
|
||||
* Sets an bounding shape on the COW so that the given window
|
||||
* is exposed. If @window is %NULL it clears the shape again.
|
||||
*
|
||||
* Used so we can unredirect windows, by shaping away the part
|
||||
* of the COW, letting the raw window be seen through below.
|
||||
*/
|
||||
static void
|
||||
meta_shape_cow_for_window (MetaScreen *screen,
|
||||
MetaWindow *metaWindow)
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (meta_screen_get_display (screen));
|
||||
|
||||
if (metaWindow == NULL)
|
||||
if (window == NULL)
|
||||
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
|
||||
else
|
||||
{
|
||||
@@ -687,7 +691,7 @@ meta_shape_cow_for_window (MetaScreen *screen,
|
||||
int width, height;
|
||||
MetaRectangle rect;
|
||||
|
||||
meta_window_get_frame_rect (metaWindow, &rect);
|
||||
meta_window_get_frame_rect (window, &rect);
|
||||
|
||||
window_bounds.x = rect.x;
|
||||
window_bounds.y = rect.y;
|
||||
@@ -738,11 +742,12 @@ meta_compositor_add_window (MetaCompositor *compositor,
|
||||
{
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_add_window\n");
|
||||
meta_error_trap_push (display);
|
||||
|
||||
add_win (window);
|
||||
meta_window_actor_new (window);
|
||||
sync_actor_stacking (info);
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
@@ -751,17 +756,9 @@ void
|
||||
meta_compositor_remove_window (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor = NULL;
|
||||
MetaScreen *screen;
|
||||
MetaCompScreen *info;
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_remove_window\n");
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
screen = meta_window_get_screen (window);
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (info->unredirected_window == window)
|
||||
set_unredirected_window (info, NULL);
|
||||
@@ -774,13 +771,7 @@ meta_compositor_set_updates_frozen (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
gboolean updates_frozen)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_set_updates_frozen\n");
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
meta_window_actor_set_updates_frozen (window_actor, updates_frozen);
|
||||
}
|
||||
|
||||
@@ -789,13 +780,7 @@ meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
gboolean no_delay_frame)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_queue_frame_drawn\n");
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
meta_window_actor_queue_frame_drawn (window_actor, no_delay_frame);
|
||||
}
|
||||
|
||||
@@ -846,23 +831,79 @@ meta_compositor_window_opacity_changed (MetaCompositor *compositor,
|
||||
meta_window_actor_update_opacity (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_window_surface_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_update_surface (window_actor);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
grab_op_is_clicking (MetaGrabOp grab_op)
|
||||
{
|
||||
switch (grab_op)
|
||||
{
|
||||
case META_GRAB_OP_CLICKING_MINIMIZE:
|
||||
case META_GRAB_OP_CLICKING_MAXIMIZE:
|
||||
case META_GRAB_OP_CLICKING_UNMAXIMIZE:
|
||||
case META_GRAB_OP_CLICKING_DELETE:
|
||||
case META_GRAB_OP_CLICKING_MENU:
|
||||
case META_GRAB_OP_CLICKING_SHADE:
|
||||
case META_GRAB_OP_CLICKING_UNSHADE:
|
||||
case META_GRAB_OP_CLICKING_ABOVE:
|
||||
case META_GRAB_OP_CLICKING_UNABOVE:
|
||||
case META_GRAB_OP_CLICKING_STICK:
|
||||
case META_GRAB_OP_CLICKING_UNSTICK:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
event_is_passive_button_grab (MetaDisplay *display,
|
||||
XIDeviceEvent *device_event)
|
||||
{
|
||||
/* see display.c for which events are passive button
|
||||
grabs (meta_display_grab_window_buttons() and
|
||||
meta_display_handle_events())
|
||||
we need to filter them here because normally they
|
||||
would be sent to gtk+ (they are on gtk+ frame xwindow),
|
||||
but we want to redirect them to clutter
|
||||
*/
|
||||
|
||||
if (device_event->evtype != XI_ButtonPress)
|
||||
return FALSE;
|
||||
|
||||
if (display->window_grab_modifiers == 0)
|
||||
return FALSE;
|
||||
|
||||
if ((device_event->mods.effective & display->window_grab_modifiers) !=
|
||||
display->window_grab_modifiers)
|
||||
return FALSE;
|
||||
|
||||
return device_event->detail < 4;
|
||||
}
|
||||
|
||||
/* Clutter makes the assumption that there is only one X window
|
||||
* per stage, which is a valid assumption to make for a generic
|
||||
* application toolkit. As such, it will ignore any events sent
|
||||
* to the a stage that isn't its X window.
|
||||
*
|
||||
* When a user clicks on what she thinks is the wallpaper, she
|
||||
* is actually clicking on the guard window, which is an entirely
|
||||
* separate top-level override-redirect window in the hierarchy.
|
||||
* We want to recieve events on this guard window so that users
|
||||
* can right-click on the background actor. We do this by telling
|
||||
* Clutter a little white lie, by transforming clicks on the guard
|
||||
* window to become clicks on the stage window, allowing Clutter
|
||||
* to process the event normally.
|
||||
* When running as an X window manager, we need to respond to
|
||||
* events from lots of windows. Trick Clutter into translating
|
||||
* these events by pretending we got an event on the stage window.
|
||||
*/
|
||||
static void
|
||||
maybe_spoof_guard_window_event_as_stage_event (MetaCompScreen *info,
|
||||
XEvent *event)
|
||||
maybe_spoof_event_as_stage_event (MetaCompScreen *info,
|
||||
MetaWindow *window,
|
||||
XEvent *event)
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (info->screen);
|
||||
|
||||
@@ -870,21 +911,30 @@ maybe_spoof_guard_window_event_as_stage_event (MetaCompScreen *info,
|
||||
event->xcookie.extension == display->xinput_opcode)
|
||||
{
|
||||
XIEvent *input_event = (XIEvent *) event->xcookie.data;
|
||||
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
|
||||
|
||||
/* Only care about pointer events for now. */
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
{
|
||||
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
|
||||
if (device_event->event == info->screen->guard_window)
|
||||
{
|
||||
Window xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
||||
device_event->event = xwin;
|
||||
}
|
||||
}
|
||||
/* If this is a window frame, and we think GTK+ needs to handle the event,
|
||||
let GTK+ handle it without mangling */
|
||||
if (window && window->frame && device_event->event == window->frame->xwindow &&
|
||||
(grab_op_is_clicking (display->grab_op) ||
|
||||
(display->grab_op == META_GRAB_OP_NONE && !event_is_passive_button_grab (display, device_event))))
|
||||
break;
|
||||
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
/* If this is a GTK+ widget, like a window menu, let GTK+ handle
|
||||
* it as-is without mangling. */
|
||||
if (meta_ui_window_is_widget (info->screen->ui, device_event->event))
|
||||
break;
|
||||
|
||||
device_event->event = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
||||
device_event->event_x = device_event->root_x;
|
||||
device_event->event_y = device_event->root_y;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -904,55 +954,29 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
if (compositor->modal_plugin && is_grabbed_event (compositor->display, event))
|
||||
MetaDisplay *display = compositor->display;
|
||||
MetaScreen *screen = display->screens->data;
|
||||
MetaCompScreen *info;
|
||||
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (is_modal (display) && is_grabbed_event (compositor->display, event))
|
||||
{
|
||||
_meta_plugin_xevent_filter (compositor->modal_plugin, event);
|
||||
meta_plugin_manager_xevent_filter (info->plugin_mgr, event);
|
||||
|
||||
/* We always consume events even if the plugin says it didn't handle them;
|
||||
* exclusive is exclusive */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (window)
|
||||
{
|
||||
MetaCompScreen *info;
|
||||
MetaScreen *screen;
|
||||
if (!meta_is_wayland_compositor ())
|
||||
maybe_spoof_event_as_stage_event (info, window, event);
|
||||
|
||||
screen = meta_window_get_screen (window);
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
return TRUE;
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
l = meta_display_get_screens (compositor->display);
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaScreen *screen = l->data;
|
||||
MetaCompScreen *info;
|
||||
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
maybe_spoof_guard_window_event_as_stage_event (info, event);
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
|
||||
if (!meta_is_wayland_compositor () &&
|
||||
event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
|
||||
{
|
||||
/* Core code doesn't handle damage events, so we need to extract the MetaWindow
|
||||
* ourselves
|
||||
@@ -963,13 +987,12 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
window = meta_display_lookup_x_window (compositor->display, xwin);
|
||||
}
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
|
||||
process_damage (compositor, (XDamageNotifyEvent *) event, window);
|
||||
}
|
||||
|
||||
/* Clutter needs to know about MapNotify events otherwise it will
|
||||
think the stage is invisible */
|
||||
if (event->type == MapNotify)
|
||||
if (!meta_is_wayland_compositor () && event->type == MapNotify)
|
||||
clutter_x11_handle_event (event);
|
||||
|
||||
/* The above handling is basically just "observing" the events, so we return
|
||||
@@ -985,11 +1008,7 @@ meta_compositor_filter_keybinding (MetaCompositor *compositor,
|
||||
MetaKeyBinding *binding)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (info->plugin_mgr)
|
||||
return meta_plugin_manager_filter_keybinding (info->plugin_mgr, binding);
|
||||
|
||||
return FALSE;
|
||||
return meta_plugin_manager_filter_keybinding (info->plugin_mgr, binding);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -998,11 +1017,7 @@ meta_compositor_show_window (MetaCompositor *compositor,
|
||||
MetaCompEffect effect)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_show_window\n");
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_show (window_actor, effect);
|
||||
meta_window_actor_show (window_actor, effect);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1011,10 +1026,6 @@ meta_compositor_hide_window (MetaCompositor *compositor,
|
||||
MetaCompEffect effect)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_hide_window\n");
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_hide (window_actor, effect);
|
||||
}
|
||||
|
||||
@@ -1025,10 +1036,6 @@ meta_compositor_maximize_window (MetaCompositor *compositor,
|
||||
MetaRectangle *new_rect)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_maximize_window\n");
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_maximize (window_actor, old_rect, new_rect);
|
||||
}
|
||||
|
||||
@@ -1039,10 +1046,6 @@ meta_compositor_unmaximize_window (MetaCompositor *compositor,
|
||||
MetaRectangle *new_rect)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_unmaximize_window\n");
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_unmaximize (window_actor, old_rect, new_rect);
|
||||
}
|
||||
|
||||
@@ -1060,18 +1063,14 @@ meta_compositor_switch_workspace (MetaCompositor *compositor,
|
||||
to_indx = meta_workspace_index (to);
|
||||
from_indx = meta_workspace_index (from);
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_switch_workspace\n");
|
||||
|
||||
if (!info) /* During startup before manage_screen() */
|
||||
return;
|
||||
|
||||
info->switch_workspace_in_progress++;
|
||||
|
||||
if (!info->plugin_mgr ||
|
||||
!meta_plugin_manager_switch_workspace (info->plugin_mgr,
|
||||
from_indx,
|
||||
to_indx,
|
||||
direction))
|
||||
if (!meta_plugin_manager_switch_workspace (info->plugin_mgr,
|
||||
from_indx, to_indx,
|
||||
direction))
|
||||
{
|
||||
info->switch_workspace_in_progress--;
|
||||
|
||||
@@ -1180,8 +1179,6 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
|
||||
GList *old_stack;
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_sync_stack\n");
|
||||
|
||||
/* This is painful because hidden windows that we are in the process
|
||||
* of animating out of existence. They'll be at the bottom of the
|
||||
* stack of X windows, but we want to leave them in their old position
|
||||
@@ -1270,15 +1267,6 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor,
|
||||
gboolean did_placement)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_sync_window_geometry\n");
|
||||
g_return_if_fail (info);
|
||||
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_sync_actor_geometry (window_actor, did_placement);
|
||||
}
|
||||
|
||||
@@ -1290,20 +1278,37 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
Display *xdisplay;
|
||||
Window xwin;
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_sync_screen_size\n");
|
||||
g_return_if_fail (info);
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
/* FIXME: when we support a sliced stage, this is the place to do it
|
||||
But! This is not the place to apply KMS config, here we only
|
||||
notify Clutter/Cogl/GL that the framebuffer sizes changed.
|
||||
|
||||
xdisplay = meta_display_get_xdisplay (display);
|
||||
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
||||
And because for now clutter does not do sliced, we use one
|
||||
framebuffer the size of the whole screen, and when running on
|
||||
bare metal MetaMonitorManager will do the necessary tricks to
|
||||
show the right portions on the right screens.
|
||||
*/
|
||||
|
||||
XResizeWindow (xdisplay, xwin, width, height);
|
||||
clutter_actor_set_size (info->stage, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
Display *xdisplay;
|
||||
Window xwin;
|
||||
|
||||
g_return_if_fail (info);
|
||||
|
||||
xdisplay = meta_display_get_xdisplay (display);
|
||||
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
||||
|
||||
XResizeWindow (xdisplay, xwin, width, height);
|
||||
}
|
||||
|
||||
meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
|
||||
meta_screen_get_screen_number (screen),
|
||||
width, height);
|
||||
meta_screen_get_screen_number (screen),
|
||||
width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1596,10 +1601,6 @@ meta_compositor_show_tile_preview (MetaCompositor *compositor,
|
||||
int tile_monitor_number)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (!info->plugin_mgr)
|
||||
return;
|
||||
|
||||
meta_plugin_manager_show_tile_preview (info->plugin_mgr,
|
||||
window, tile_rect, tile_monitor_number);
|
||||
}
|
||||
@@ -1609,9 +1610,5 @@ meta_compositor_hide_tile_preview (MetaCompositor *compositor,
|
||||
MetaScreen *screen)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (!info->plugin_mgr)
|
||||
return;
|
||||
|
||||
meta_plugin_manager_hide_tile_preview (info->plugin_mgr);
|
||||
}
|
||||
|
||||
@@ -100,7 +100,9 @@ meta_plugin_manager_new (MetaScreen *screen)
|
||||
|
||||
plugin_mgr = g_new0 (MetaPluginManager, 1);
|
||||
plugin_mgr->screen = screen;
|
||||
plugin_mgr->plugin = plugin = g_object_new (plugin_type, "screen", screen, NULL);
|
||||
plugin_mgr->plugin = plugin = g_object_new (plugin_type, NULL);
|
||||
|
||||
_meta_plugin_set_screen (plugin, screen);
|
||||
|
||||
klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
@@ -165,8 +167,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||
actor);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->minimize (plugin, actor);
|
||||
}
|
||||
break;
|
||||
@@ -176,8 +176,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||
actor);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->map (plugin, actor);
|
||||
}
|
||||
break;
|
||||
@@ -185,7 +183,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
||||
if (klass->destroy)
|
||||
{
|
||||
retval = TRUE;
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->destroy (plugin, actor);
|
||||
}
|
||||
break;
|
||||
@@ -230,8 +227,6 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
|
||||
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);
|
||||
@@ -243,8 +238,6 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
|
||||
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);
|
||||
@@ -283,8 +276,6 @@ meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr,
|
||||
{
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_switch_workspace (plugin_mgr);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->switch_workspace (plugin, from, to, direction);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "meta-plugin-manager.h"
|
||||
#include <meta/screen.h>
|
||||
#include <meta/display.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
@@ -46,91 +47,15 @@ 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;
|
||||
MetaScreen *screen;
|
||||
};
|
||||
|
||||
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));
|
||||
g_type_class_add_private (klass, sizeof (MetaPluginPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -139,22 +64,6 @@ meta_plugin_init (MetaPlugin *self)
|
||||
self->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)
|
||||
{
|
||||
@@ -166,46 +75,34 @@ meta_plugin_get_info (MetaPlugin *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++;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_meta_plugin_xevent_filter (MetaPlugin *plugin,
|
||||
XEvent *xev)
|
||||
{
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
/* When mutter is running as a wayland compositor, things like input
|
||||
* events just come directly from clutter so it won't have disabled
|
||||
* clutter's event retrieval and won't need to forward it events (if
|
||||
* it did it would lead to recursion). Also when running as a
|
||||
* wayland compositor we shouldn't be assuming that we're running
|
||||
* with the clutter x11 backend.
|
||||
*/
|
||||
|
||||
if (klass->xevent_filter && klass->xevent_filter (plugin, xev))
|
||||
return TRUE;
|
||||
else
|
||||
else if (!meta_is_wayland_compositor ())
|
||||
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -214,26 +111,6 @@ 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);
|
||||
}
|
||||
|
||||
@@ -328,9 +205,7 @@ meta_plugin_end_modal (MetaPlugin *plugin,
|
||||
* 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.
|
||||
* Gets the #MetaScreen corresponding to a plugin.
|
||||
*
|
||||
* Return value: (transfer none): the #MetaScreen for the plugin
|
||||
*/
|
||||
@@ -342,6 +217,15 @@ meta_plugin_get_screen (MetaPlugin *plugin)
|
||||
return priv->screen;
|
||||
}
|
||||
|
||||
void
|
||||
_meta_plugin_set_screen (MetaPlugin *plugin,
|
||||
MetaScreen *screen)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
priv->screen = screen;
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_complete_display_change (MetaPlugin *plugin,
|
||||
gboolean ok)
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include <meta/util.h>
|
||||
#include "clutter-utils.h"
|
||||
#include "meta-texture-tower.h"
|
||||
|
||||
@@ -42,8 +43,6 @@
|
||||
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,
|
||||
@@ -73,8 +72,6 @@ struct _MetaShapedTexturePrivate
|
||||
CoglTexture *texture;
|
||||
CoglTexture *mask_texture;
|
||||
|
||||
cairo_region_t *input_shape_region;
|
||||
|
||||
/* The region containing only fully opaque pixels */
|
||||
cairo_region_t *opaque_region;
|
||||
|
||||
@@ -98,7 +95,6 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
|
||||
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));
|
||||
@@ -232,6 +228,54 @@ paint_clipped_rectangle (CoglFramebuffer *fb,
|
||||
&coords[0], 8);
|
||||
}
|
||||
|
||||
static void
|
||||
set_cogl_texture (MetaShapedTexture *stex,
|
||||
CoglTexture *cogl_tex)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
guint width, height;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->texture)
|
||||
cogl_object_unref (priv->texture);
|
||||
|
||||
priv->texture = cogl_tex;
|
||||
|
||||
if (cogl_tex != NULL)
|
||||
{
|
||||
cogl_object_ref (cogl_tex);
|
||||
width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
|
||||
height = cogl_texture_get_height (COGL_TEXTURE (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));
|
||||
}
|
||||
|
||||
/* NB: We don't queue a redraw of the actor here because we don't
|
||||
* know how much of the buffer has changed with respect to the
|
||||
* previous buffer. We only queue a redraw in response to surface
|
||||
* damage. */
|
||||
|
||||
if (priv->create_mipmaps)
|
||||
meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_paint (ClutterActor *actor)
|
||||
{
|
||||
@@ -415,71 +459,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
cairo_region_destroy (blended_region);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
if (!clutter_actor_should_pick_paint (actor) ||
|
||||
(priv->clip_region && cairo_region_is_empty (priv->clip_region)))
|
||||
return;
|
||||
|
||||
/* If there is no region then use the regular pick */
|
||||
if (priv->input_shape_region == NULL)
|
||||
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)->pick (actor, color);
|
||||
else
|
||||
{
|
||||
int n_rects;
|
||||
float *rectangles;
|
||||
int i;
|
||||
CoglPipeline *pipeline;
|
||||
CoglContext *ctx;
|
||||
CoglFramebuffer *fb;
|
||||
CoglColor cogl_color;
|
||||
|
||||
/* Note: We don't bother trying to intersect the pick and clip regions
|
||||
* since needing to copy the region, do the intersection, and probably
|
||||
* increase the number of rectangles seems more likely to have a negative
|
||||
* effect.
|
||||
*
|
||||
* NB: Most of the time when just using rectangles for picking then
|
||||
* picking shouldn't involve any rendering, and minimizing the number of
|
||||
* rectangles has more benefit than reducing the area of the pick
|
||||
* region.
|
||||
*/
|
||||
|
||||
n_rects = cairo_region_num_rectangles (priv->input_shape_region);
|
||||
rectangles = g_alloca (sizeof (float) * 4 * n_rects);
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
int pos = i * 4;
|
||||
|
||||
cairo_region_get_rectangle (priv->input_shape_region, i, &rect);
|
||||
|
||||
rectangles[pos] = rect.x;
|
||||
rectangles[pos + 1] = rect.y;
|
||||
rectangles[pos + 2] = rect.x + rect.width;
|
||||
rectangles[pos + 3] = rect.y + rect.height;
|
||||
}
|
||||
|
||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
fb = cogl_get_draw_framebuffer ();
|
||||
|
||||
cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
|
||||
|
||||
pipeline = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_color (pipeline, &cogl_color);
|
||||
|
||||
cogl_framebuffer_draw_rectangles (fb, pipeline,
|
||||
rectangles, n_rects);
|
||||
cogl_object_unref (pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
@@ -699,53 +678,6 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_cogl_texture (MetaShapedTexture *stex,
|
||||
CoglTexture *cogl_tex)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
guint width, height;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->texture != NULL)
|
||||
cogl_object_unref (priv->texture);
|
||||
|
||||
priv->texture = cogl_tex;
|
||||
|
||||
if (cogl_tex != NULL)
|
||||
{
|
||||
width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
|
||||
height = cogl_texture_get_height (COGL_TEXTURE (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 texture */
|
||||
priv->tex_width = 0;
|
||||
priv->tex_height = 0;
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
/* NB: We don't queue a redraw of the actor here because we don't
|
||||
* know how much of the buffer has changed with respect to the
|
||||
* previous buffer. We only queue a redraw in response to surface
|
||||
* damage. */
|
||||
|
||||
if (priv->create_mipmaps)
|
||||
meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_texture:
|
||||
* @stex: The #MetaShapedTexture
|
||||
@@ -773,41 +705,6 @@ meta_shaped_texture_get_texture (MetaShapedTexture *stex)
|
||||
return COGL_TEXTURE (stex->priv->texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_input_shape_region:
|
||||
* @stex: a #MetaShapedTexture
|
||||
* @shape_region: the region of the texture that should respond to
|
||||
* input.
|
||||
*
|
||||
* Determines what region of the texture should accept input. For
|
||||
* X based windows this is defined by the ShapeInput region of the
|
||||
* window.
|
||||
*/
|
||||
void
|
||||
meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *shape_region)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->input_shape_region != NULL)
|
||||
{
|
||||
cairo_region_destroy (priv->input_shape_region);
|
||||
priv->input_shape_region = NULL;
|
||||
}
|
||||
|
||||
if (shape_region != NULL)
|
||||
{
|
||||
cairo_region_reference (shape_region);
|
||||
priv->input_shape_region = shape_region;
|
||||
}
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_opaque_region:
|
||||
* @stex: a #MetaShapedTexture
|
||||
|
||||
165
src/compositor/meta-surface-actor-wayland.c
Normal file
165
src/compositor/meta-surface-actor-wayland.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include "meta-shaped-texture-private.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
struct _MetaSurfaceActorWaylandPrivate
|
||||
{
|
||||
MetaWaylandSurface *surface;
|
||||
MetaWaylandBuffer *buffer;
|
||||
};
|
||||
typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR)
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
|
||||
struct wl_resource *resource = priv->buffer->resource;
|
||||
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
|
||||
|
||||
if (shm_buffer)
|
||||
{
|
||||
CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture);
|
||||
cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL);
|
||||
}
|
||||
|
||||
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_pre_paint (MetaSurfaceActor *actor)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_wayland_is_argb32 (MetaSurfaceActor *actor)
|
||||
{
|
||||
/* XXX -- look at the SHM buffer format. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor)
|
||||
{
|
||||
/* TODO: ensure that the buffer isn't NULL, implement
|
||||
* wayland mapping semantics */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_wayland_should_unredirect (MetaSurfaceActor *actor)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_set_unredirected (MetaSurfaceActor *actor,
|
||||
gboolean unredirected)
|
||||
{
|
||||
/* Do nothing. In the future, we'll use KMS to set this
|
||||
* up as a hardware overlay or something. */
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static MetaWindow *
|
||||
meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (META_SURFACE_ACTOR_WAYLAND (actor));
|
||||
|
||||
return priv->surface->window;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
|
||||
{
|
||||
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
|
||||
|
||||
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
|
||||
surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
|
||||
surface_actor_class->is_argb32 = meta_surface_actor_wayland_is_argb32;
|
||||
surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible;
|
||||
|
||||
surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect;
|
||||
surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected;
|
||||
surface_actor_class->is_unredirected = meta_surface_actor_wayland_is_unredirected;
|
||||
|
||||
surface_actor_class->get_window = meta_surface_actor_wayland_get_window;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self)
|
||||
{
|
||||
}
|
||||
|
||||
MetaSurfaceActor *
|
||||
meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaSurfaceActorWayland *self = g_object_new (META_TYPE_SURFACE_ACTOR_WAYLAND, NULL);
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
priv->surface = surface;
|
||||
|
||||
return META_SURFACE_ACTOR (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
|
||||
MetaWaylandBuffer *buffer)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
|
||||
priv->buffer = buffer;
|
||||
|
||||
if (buffer)
|
||||
meta_shaped_texture_set_texture (stex, buffer->texture);
|
||||
else
|
||||
meta_shaped_texture_set_texture (stex, NULL);
|
||||
}
|
||||
|
||||
MetaWaylandSurface *
|
||||
meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
return priv->surface;
|
||||
}
|
||||
66
src/compositor/meta-surface-actor-wayland.h
Normal file
66
src/compositor/meta-surface-actor-wayland.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef __META_SURFACE_ACTOR_WAYLAND_H__
|
||||
#define __META_SURFACE_ACTOR_WAYLAND_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
|
||||
#include "wayland/meta-wayland.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_SURFACE_ACTOR_WAYLAND (meta_surface_actor_wayland_get_type ())
|
||||
#define META_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWayland))
|
||||
#define META_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
|
||||
#define META_IS_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND))
|
||||
#define META_IS_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND))
|
||||
#define META_SURFACE_ACTOR_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
|
||||
|
||||
typedef struct _MetaSurfaceActorWayland MetaSurfaceActorWayland;
|
||||
typedef struct _MetaSurfaceActorWaylandClass MetaSurfaceActorWaylandClass;
|
||||
|
||||
struct _MetaSurfaceActorWayland
|
||||
{
|
||||
MetaSurfaceActor parent;
|
||||
};
|
||||
|
||||
struct _MetaSurfaceActorWaylandClass
|
||||
{
|
||||
MetaSurfaceActorClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_surface_actor_wayland_get_type (void);
|
||||
|
||||
MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface);
|
||||
MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self);
|
||||
|
||||
void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
|
||||
MetaWaylandBuffer *buffer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */
|
||||
486
src/compositor/meta-surface-actor-x11.c
Normal file
486
src/compositor/meta-surface-actor-x11.c
Normal file
@@ -0,0 +1,486 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Owen Taylor <otaylor@redhat.com>
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-surface-actor-x11.h"
|
||||
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#include <cogl/cogl-texture-pixmap-x11.h>
|
||||
|
||||
#include <meta/errors.h>
|
||||
#include "window-private.h"
|
||||
#include "meta-shaped-texture-private.h"
|
||||
#include "meta-cullable.h"
|
||||
|
||||
struct _MetaSurfaceActorX11Private
|
||||
{
|
||||
MetaWindow *window;
|
||||
|
||||
MetaDisplay *display;
|
||||
|
||||
CoglTexture *texture;
|
||||
Pixmap pixmap;
|
||||
Damage damage;
|
||||
|
||||
int last_width;
|
||||
int last_height;
|
||||
|
||||
/* This is used to detect fullscreen windows that need to be unredirected */
|
||||
guint full_damage_frames_count;
|
||||
guint does_full_damage : 1;
|
||||
|
||||
/* Other state... */
|
||||
guint argb32 : 1;
|
||||
guint received_damage : 1;
|
||||
guint size_changed : 1;
|
||||
|
||||
guint unredirected : 1;
|
||||
};
|
||||
typedef struct _MetaSurfaceActorX11Private MetaSurfaceActorX11Private;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorX11, meta_surface_actor_x11, META_TYPE_SURFACE_ACTOR)
|
||||
|
||||
static void
|
||||
free_damage (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
if (priv->damage == None)
|
||||
return;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XDamageDestroy (xdisplay, priv->damage);
|
||||
priv->damage = None;
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static void
|
||||
detach_pixmap (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
|
||||
if (priv->pixmap == None)
|
||||
return;
|
||||
|
||||
/* Get rid of all references to the pixmap before freeing it; it's unclear whether
|
||||
* you are supposed to be able to free a GLXPixmap after freeing the underlying
|
||||
* pixmap, but it certainly doesn't work with current DRI/Mesa
|
||||
*/
|
||||
meta_shaped_texture_set_texture (stex, NULL);
|
||||
cogl_flush ();
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XFreePixmap (xdisplay, priv->pixmap);
|
||||
priv->pixmap = None;
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
cogl_object_unref (priv->texture);
|
||||
priv->texture = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
set_pixmap (MetaSurfaceActorX11 *self,
|
||||
Pixmap pixmap)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
CoglTexture *texture;
|
||||
|
||||
g_assert (priv->pixmap == None);
|
||||
priv->pixmap = pixmap;
|
||||
|
||||
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->pixmap, FALSE, NULL));
|
||||
|
||||
if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
|
||||
g_warning ("NOTE: Not using GLX TFP!\n");
|
||||
|
||||
priv->texture = texture;
|
||||
meta_shaped_texture_set_texture (stex, texture);
|
||||
}
|
||||
|
||||
static void
|
||||
update_pixmap (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
if (priv->size_changed)
|
||||
{
|
||||
detach_pixmap (self);
|
||||
priv->size_changed = FALSE;
|
||||
}
|
||||
|
||||
if (priv->pixmap == None)
|
||||
{
|
||||
Pixmap new_pixmap;
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
|
||||
|
||||
if (meta_error_trap_pop_with_return (display) != Success)
|
||||
{
|
||||
/* Probably a BadMatch if the window isn't viewable; we could
|
||||
* GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync
|
||||
* to avoid this, but there's no reason to take two round trips
|
||||
* when one will do. (We need that Sync if we want to handle failures
|
||||
* for any reason other than !viewable. That's unlikely, but maybe
|
||||
* we'll BadAlloc or something.)
|
||||
*/
|
||||
new_pixmap = None;
|
||||
}
|
||||
|
||||
if (new_pixmap == None)
|
||||
{
|
||||
meta_verbose ("Unable to get named pixmap for %s\n",
|
||||
meta_window_get_description (priv->window));
|
||||
return;
|
||||
}
|
||||
|
||||
set_pixmap (self, new_pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_visible (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
return (priv->pixmap != None) && !priv->unredirected;
|
||||
}
|
||||
|
||||
static void
|
||||
damage_area (MetaSurfaceActorX11 *self,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
if (!is_visible (self))
|
||||
return;
|
||||
|
||||
cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height);
|
||||
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
priv->received_damage = TRUE;
|
||||
|
||||
if (meta_window_is_fullscreen (priv->window) && !priv->unredirected && !priv->does_full_damage)
|
||||
{
|
||||
MetaRectangle window_rect;
|
||||
meta_window_get_frame_rect (priv->window, &window_rect);
|
||||
|
||||
if (window_rect.x == x &&
|
||||
window_rect.y == y &&
|
||||
window_rect.width == width &&
|
||||
window_rect.height == height)
|
||||
priv->full_damage_frames_count++;
|
||||
else
|
||||
priv->full_damage_frames_count = 0;
|
||||
|
||||
if (priv->full_damage_frames_count >= 100)
|
||||
priv->does_full_damage = TRUE;
|
||||
}
|
||||
|
||||
/* Drop damage event for unredirected windows */
|
||||
if (priv->unredirected)
|
||||
return;
|
||||
|
||||
damage_area (self, x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
if (priv->received_damage)
|
||||
{
|
||||
meta_error_trap_push (display);
|
||||
XDamageSubtract (xdisplay, priv->damage, None, None);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
/* We need to make sure that any X drawing that happens before the
|
||||
* XDamageSubtract() above is visible to subsequent GL rendering;
|
||||
* the only standardized way to do this is EXT_x11_sync_object,
|
||||
* which isn't yet widely available. For now, we count on details
|
||||
* of Xorg and the open source drivers, and hope for the best
|
||||
* otherwise.
|
||||
*
|
||||
* Xorg and open source driver specifics:
|
||||
*
|
||||
* The X server makes sure to flush drawing to the kernel before
|
||||
* sending out damage events, but since we use DamageReportBoundingBox
|
||||
* there may be drawing between the last damage event and the
|
||||
* XDamageSubtract() that needs to be flushed as well.
|
||||
*
|
||||
* Xorg always makes sure that drawing is flushed to the kernel
|
||||
* before writing events or responses to the client, so any round trip
|
||||
* request at this point is sufficient to flush the GLX buffers.
|
||||
*/
|
||||
XSync (xdisplay, False);
|
||||
|
||||
priv->received_damage = FALSE;
|
||||
}
|
||||
|
||||
update_pixmap (self);
|
||||
}
|
||||
|
||||
static void
|
||||
update_is_argb32 (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
XRenderPictFormat *format;
|
||||
format = XRenderFindVisualFormat (xdisplay, priv->window->xvisual);
|
||||
|
||||
priv->argb32 = (format && format->type == PictTypeDirect && format->direct.alphaMask);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_x11_is_argb32 (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
return priv->argb32;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_x11_is_visible (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
return is_visible (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_x11_should_unredirect (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
MetaWindow *window = priv->window;
|
||||
|
||||
if (meta_window_requested_dont_bypass_compositor (window))
|
||||
return FALSE;
|
||||
|
||||
if (window->opacity != 0xFF)
|
||||
return FALSE;
|
||||
|
||||
if (window->shape_region != NULL)
|
||||
return FALSE;
|
||||
|
||||
if (priv->argb32 && !meta_window_requested_bypass_compositor (window))
|
||||
return FALSE;
|
||||
|
||||
if (!meta_window_is_monitor_sized (window))
|
||||
return FALSE;
|
||||
|
||||
if (meta_window_requested_bypass_compositor (window))
|
||||
return TRUE;
|
||||
|
||||
if (meta_window_is_override_redirect (window))
|
||||
return TRUE;
|
||||
|
||||
if (priv->does_full_damage)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_unredirected (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
|
||||
if (priv->unredirected)
|
||||
{
|
||||
detach_pixmap (self);
|
||||
XCompositeUnredirectWindow (xdisplay, xwindow, CompositeRedirectManual);
|
||||
}
|
||||
else
|
||||
{
|
||||
XCompositeRedirectWindow (xdisplay, xwindow, CompositeRedirectManual);
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_set_unredirected (MetaSurfaceActor *actor,
|
||||
gboolean unredirected)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
if (priv->unredirected == unredirected)
|
||||
return;
|
||||
|
||||
priv->unredirected = unredirected;
|
||||
sync_unredirected (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_x11_is_unredirected (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
return priv->unredirected;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_dispose (GObject *object)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (object);
|
||||
|
||||
detach_pixmap (self);
|
||||
free_damage (self);
|
||||
|
||||
G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static MetaWindow *
|
||||
meta_surface_actor_x11_get_window (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (META_SURFACE_ACTOR_X11 (actor));
|
||||
|
||||
return priv->window;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_surface_actor_x11_dispose;
|
||||
|
||||
surface_actor_class->process_damage = meta_surface_actor_x11_process_damage;
|
||||
surface_actor_class->pre_paint = meta_surface_actor_x11_pre_paint;
|
||||
surface_actor_class->is_argb32 = meta_surface_actor_x11_is_argb32;
|
||||
surface_actor_class->is_visible = meta_surface_actor_x11_is_visible;
|
||||
|
||||
surface_actor_class->should_unredirect = meta_surface_actor_x11_should_unredirect;
|
||||
surface_actor_class->set_unredirected = meta_surface_actor_x11_set_unredirected;
|
||||
surface_actor_class->is_unredirected = meta_surface_actor_x11_is_unredirected;
|
||||
|
||||
surface_actor_class->get_window = meta_surface_actor_x11_get_window;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_init (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
priv->last_width = -1;
|
||||
priv->last_height = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
create_damage (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
Display *xdisplay = meta_display_get_xdisplay (priv->display);
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
|
||||
priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
|
||||
}
|
||||
|
||||
static void
|
||||
window_decorated_notify (MetaWindow *window,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (user_data);
|
||||
|
||||
free_damage (self);
|
||||
create_damage (self);
|
||||
}
|
||||
|
||||
MetaSurfaceActor *
|
||||
meta_surface_actor_x11_new (MetaWindow *window)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = meta_window_get_display (window);
|
||||
|
||||
g_assert (!meta_is_wayland_compositor ());
|
||||
|
||||
priv->window = window;
|
||||
priv->display = display;
|
||||
|
||||
create_damage (self);
|
||||
g_signal_connect_object (priv->window, "notify::decorated",
|
||||
G_CALLBACK (window_decorated_notify), self, 0);
|
||||
|
||||
update_is_argb32 (self);
|
||||
|
||||
priv->unredirected = FALSE;
|
||||
sync_unredirected (self);
|
||||
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
|
||||
return META_SURFACE_ACTOR (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
|
||||
int width, int height)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
if (priv->last_width == width &&
|
||||
priv->last_height == height)
|
||||
return;
|
||||
|
||||
priv->size_changed = TRUE;
|
||||
priv->last_width = width;
|
||||
priv->last_height = height;
|
||||
}
|
||||
69
src/compositor/meta-surface-actor-x11.h
Normal file
69
src/compositor/meta-surface-actor-x11.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Owen Taylor <otaylor@redhat.com>
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef __META_SURFACE_ACTOR_X11_H__
|
||||
#define __META_SURFACE_ACTOR_X11_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
|
||||
#include <meta/display.h>
|
||||
#include <meta/window.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_SURFACE_ACTOR_X11 (meta_surface_actor_x11_get_type ())
|
||||
#define META_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11))
|
||||
#define META_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
|
||||
#define META_IS_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_X11))
|
||||
#define META_IS_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_X11))
|
||||
#define META_SURFACE_ACTOR_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
|
||||
|
||||
typedef struct _MetaSurfaceActorX11 MetaSurfaceActorX11;
|
||||
typedef struct _MetaSurfaceActorX11Class MetaSurfaceActorX11Class;
|
||||
|
||||
struct _MetaSurfaceActorX11
|
||||
{
|
||||
MetaSurfaceActor parent;
|
||||
};
|
||||
|
||||
struct _MetaSurfaceActorX11Class
|
||||
{
|
||||
MetaSurfaceActorClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_surface_actor_x11_get_type (void);
|
||||
|
||||
MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window);
|
||||
|
||||
void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
|
||||
int width, int height);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __META_SURFACE_ACTOR_X11_H__ */
|
||||
319
src/compositor/meta-surface-actor.c
Normal file
319
src/compositor/meta-surface-actor.c
Normal file
@@ -0,0 +1,319 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* SECTION:meta-surface-actor
|
||||
* @title: MetaSurfaceActor
|
||||
* @short_description: An actor representing a surface in the scene graph
|
||||
*
|
||||
* A surface can be either a shaped texture, or a group of shaped texture,
|
||||
* used to draw the content of a window.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include "meta-cullable.h"
|
||||
#include "meta-shaped-texture-private.h"
|
||||
|
||||
struct _MetaSurfaceActorPrivate
|
||||
{
|
||||
MetaShapedTexture *texture;
|
||||
|
||||
cairo_region_t *input_region;
|
||||
|
||||
/* Freeze/thaw accounting */
|
||||
guint needs_damage_all : 1;
|
||||
guint frozen : 1;
|
||||
};
|
||||
|
||||
static void cullable_iface_init (MetaCullableInterface *iface);
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
|
||||
|
||||
enum {
|
||||
REPAINT_SCHEDULED,
|
||||
|
||||
LAST_SIGNAL,
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
|
||||
cairo_rectangle_int_t *unobscured_bounds)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
return meta_shaped_texture_get_unobscured_bounds (priv->texture, unobscured_bounds);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
MetaSurfaceActor *self = META_SURFACE_ACTOR (actor);
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (!clutter_actor_should_pick_paint (actor))
|
||||
return;
|
||||
|
||||
/* If there is no region then use the regular pick */
|
||||
if (priv->input_region == NULL)
|
||||
CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->pick (actor, color);
|
||||
else
|
||||
{
|
||||
int n_rects;
|
||||
float *rectangles;
|
||||
int i;
|
||||
CoglPipeline *pipeline;
|
||||
CoglContext *ctx;
|
||||
CoglFramebuffer *fb;
|
||||
CoglColor cogl_color;
|
||||
|
||||
n_rects = cairo_region_num_rectangles (priv->input_region);
|
||||
rectangles = g_alloca (sizeof (float) * 4 * n_rects);
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
int pos = i * 4;
|
||||
|
||||
cairo_region_get_rectangle (priv->input_region, i, &rect);
|
||||
|
||||
rectangles[pos + 0] = rect.x;
|
||||
rectangles[pos + 1] = rect.y;
|
||||
rectangles[pos + 2] = rect.x + rect.width;
|
||||
rectangles[pos + 3] = rect.y + rect.height;
|
||||
}
|
||||
|
||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
fb = cogl_get_draw_framebuffer ();
|
||||
|
||||
cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
|
||||
|
||||
pipeline = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_color (pipeline, &cogl_color);
|
||||
cogl_framebuffer_draw_rectangles (fb, pipeline, rectangles, n_rects);
|
||||
cogl_object_unref (pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_dispose (GObject *object)
|
||||
{
|
||||
MetaSurfaceActor *self = META_SURFACE_ACTOR (object);
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
g_clear_pointer (&priv->input_region, cairo_region_destroy);
|
||||
|
||||
G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_surface_actor_dispose;
|
||||
actor_class->pick = meta_surface_actor_pick;
|
||||
|
||||
signals[REPAINT_SCHEDULED] = g_signal_new ("repaint-scheduled",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_cull_out (MetaCullable *cullable,
|
||||
cairo_region_t *unobscured_region,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_reset_culling (MetaCullable *cullable)
|
||||
{
|
||||
meta_cullable_reset_culling_children (cullable);
|
||||
}
|
||||
|
||||
static void
|
||||
cullable_iface_init (MetaCullableInterface *iface)
|
||||
{
|
||||
iface->cull_out = meta_surface_actor_cull_out;
|
||||
iface->reset_culling = meta_surface_actor_reset_culling;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_init (MetaSurfaceActor *self)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv;
|
||||
|
||||
priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||
META_TYPE_SURFACE_ACTOR,
|
||||
MetaSurfaceActorPrivate);
|
||||
|
||||
priv->texture = META_SHAPED_TEXTURE (meta_shaped_texture_new ());
|
||||
clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->texture));
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
meta_surface_actor_get_image (MetaSurfaceActor *self,
|
||||
cairo_rectangle_int_t *clip)
|
||||
{
|
||||
return meta_shaped_texture_get_image (self->priv->texture, clip);
|
||||
}
|
||||
|
||||
MetaShapedTexture *
|
||||
meta_surface_actor_get_texture (MetaSurfaceActor *self)
|
||||
{
|
||||
return self->priv->texture;
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_update_area (MetaSurfaceActor *self,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (meta_shaped_texture_update_area (priv->texture, x, y, width, height))
|
||||
g_signal_emit (self, signals[REPAINT_SCHEDULED], 0);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_is_obscured (MetaSurfaceActor *self)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
return meta_shaped_texture_is_obscured (priv->texture);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_set_input_region (MetaSurfaceActor *self,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->input_region)
|
||||
cairo_region_destroy (priv->input_region);
|
||||
|
||||
if (region)
|
||||
priv->input_region = cairo_region_reference (region);
|
||||
else
|
||||
priv->input_region = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
meta_shaped_texture_set_opaque_region (priv->texture, region);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_frozen (MetaSurfaceActor *self)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
return priv->frozen;
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_process_damage (MetaSurfaceActor *self,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (is_frozen (self))
|
||||
{
|
||||
/* The window is frozen due to an effect in progress: we ignore damage
|
||||
* here on the off chance that this will stop the corresponding
|
||||
* texture_from_pixmap from being update.
|
||||
*
|
||||
* needs_damage_all tracks that some unknown damage happened while the
|
||||
* window was frozen so that when the window becomes unfrozen we can
|
||||
* issue a full window update to cover any lost damage.
|
||||
*
|
||||
* It should be noted that this is an unreliable mechanism since it's
|
||||
* quite likely that drivers will aim to provide a zero-copy
|
||||
* implementation of the texture_from_pixmap extension and in those cases
|
||||
* any drawing done to the window is always immediately reflected in the
|
||||
* texture regardless of damage event handling.
|
||||
*/
|
||||
priv->needs_damage_all = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
META_SURFACE_ACTOR_GET_CLASS (self)->process_damage (self, x, y, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_pre_paint (MetaSurfaceActor *self)
|
||||
{
|
||||
META_SURFACE_ACTOR_GET_CLASS (self)->pre_paint (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_is_argb32 (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->is_argb32 (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_is_visible (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->is_visible (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_set_frozen (MetaSurfaceActor *self,
|
||||
gboolean frozen)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
priv->frozen = frozen;
|
||||
|
||||
if (!frozen && priv->needs_damage_all)
|
||||
{
|
||||
/* Since we ignore damage events while a window is frozen for certain effects
|
||||
* we may need to issue an update_area() covering the whole pixmap if we
|
||||
* don't know what real damage has happened. */
|
||||
|
||||
meta_surface_actor_process_damage (self, 0, 0,
|
||||
clutter_actor_get_width (CLUTTER_ACTOR (priv->texture)),
|
||||
clutter_actor_get_height (CLUTTER_ACTOR (priv->texture)));
|
||||
priv->needs_damage_all = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_should_unredirect (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->should_unredirect (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_set_unredirected (MetaSurfaceActor *self,
|
||||
gboolean unredirected)
|
||||
{
|
||||
META_SURFACE_ACTOR_GET_CLASS (self)->set_unredirected (self, unredirected);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_is_unredirected (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->is_unredirected (self);
|
||||
}
|
||||
|
||||
MetaWindow *
|
||||
meta_surface_actor_get_window (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->get_window (self);
|
||||
}
|
||||
86
src/compositor/meta-surface-actor.h
Normal file
86
src/compositor/meta-surface-actor.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#ifndef META_SURFACE_ACTOR_PRIVATE_H
|
||||
#define META_SURFACE_ACTOR_PRIVATE_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include <meta/window.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_SURFACE_ACTOR (meta_surface_actor_get_type())
|
||||
#define META_SURFACE_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR, MetaSurfaceActor))
|
||||
#define META_SURFACE_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR, MetaSurfaceActorClass))
|
||||
#define META_IS_SURFACE_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR))
|
||||
#define META_IS_SURFACE_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR))
|
||||
#define META_SURFACE_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR, MetaSurfaceActorClass))
|
||||
|
||||
typedef struct _MetaSurfaceActor MetaSurfaceActor;
|
||||
typedef struct _MetaSurfaceActorClass MetaSurfaceActorClass;
|
||||
typedef struct _MetaSurfaceActorPrivate MetaSurfaceActorPrivate;
|
||||
|
||||
struct _MetaSurfaceActorClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
void (* process_damage) (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height);
|
||||
void (* pre_paint) (MetaSurfaceActor *actor);
|
||||
gboolean (* is_argb32) (MetaSurfaceActor *actor);
|
||||
gboolean (* is_visible) (MetaSurfaceActor *actor);
|
||||
|
||||
gboolean (* should_unredirect) (MetaSurfaceActor *actor);
|
||||
void (* set_unredirected) (MetaSurfaceActor *actor,
|
||||
gboolean unredirected);
|
||||
gboolean (* is_unredirected) (MetaSurfaceActor *actor);
|
||||
|
||||
MetaWindow *(* get_window) (MetaSurfaceActor *actor);
|
||||
};
|
||||
|
||||
struct _MetaSurfaceActor
|
||||
{
|
||||
ClutterActor parent;
|
||||
|
||||
MetaSurfaceActorPrivate *priv;
|
||||
};
|
||||
|
||||
GType meta_surface_actor_get_type (void);
|
||||
|
||||
cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor *self,
|
||||
cairo_rectangle_int_t *clip);
|
||||
|
||||
MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self);
|
||||
MetaWindow *meta_surface_actor_get_window (MetaSurfaceActor *self);
|
||||
|
||||
gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self);
|
||||
gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
|
||||
cairo_rectangle_int_t *unobscured_bounds);
|
||||
|
||||
void meta_surface_actor_set_input_region (MetaSurfaceActor *self,
|
||||
cairo_region_t *region);
|
||||
void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
|
||||
cairo_region_t *region);
|
||||
|
||||
void meta_surface_actor_update_area (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
void meta_surface_actor_process_damage (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height);
|
||||
void meta_surface_actor_pre_paint (MetaSurfaceActor *actor);
|
||||
gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *actor);
|
||||
gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor);
|
||||
|
||||
void meta_surface_actor_set_frozen (MetaSurfaceActor *actor,
|
||||
gboolean frozen);
|
||||
|
||||
gboolean meta_surface_actor_should_unredirect (MetaSurfaceActor *actor);
|
||||
void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,
|
||||
gboolean unredirected);
|
||||
gboolean meta_surface_actor_is_unredirected (MetaSurfaceActor *actor);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* META_SURFACE_ACTOR_PRIVATE_H */
|
||||
@@ -60,7 +60,6 @@ struct _MetaTextureTower
|
||||
CoglTexture *textures[MAX_TEXTURE_LEVELS];
|
||||
CoglOffscreen *fbos[MAX_TEXTURE_LEVELS];
|
||||
Box invalid[MAX_TEXTURE_LEVELS];
|
||||
CoglPipeline *pipeline_template;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -92,9 +91,6 @@ meta_texture_tower_free (MetaTextureTower *tower)
|
||||
{
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
if (tower->pipeline_template != NULL)
|
||||
cogl_object_unref (tower->pipeline_template);
|
||||
|
||||
meta_texture_tower_set_base_texture (tower, NULL);
|
||||
|
||||
g_slice_free (MetaTextureTower, tower);
|
||||
@@ -377,7 +373,7 @@ texture_tower_create_texture (MetaTextureTower *tower,
|
||||
tower->invalid[level].y2 = height;
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
texture_tower_revalidate_fbo (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
@@ -388,50 +384,174 @@ texture_tower_revalidate_fbo (MetaTextureTower *tower,
|
||||
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];
|
||||
CoglFramebuffer *fb;
|
||||
CoglError *catch_error = NULL;
|
||||
CoglPipeline *pipeline;
|
||||
CoglMatrix modelview;
|
||||
|
||||
if (tower->fbos[level] == NULL)
|
||||
tower->fbos[level] = cogl_offscreen_new_with_texture (dest_texture);
|
||||
tower->fbos[level] = cogl_offscreen_new_to_texture (dest_texture);
|
||||
|
||||
fb = COGL_FRAMEBUFFER (tower->fbos[level]);
|
||||
if (tower->fbos[level] == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!cogl_framebuffer_allocate (fb, &catch_error))
|
||||
cogl_push_framebuffer (COGL_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)
|
||||
{
|
||||
cogl_error_free (catch_error);
|
||||
return;
|
||||
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;
|
||||
}
|
||||
|
||||
cogl_framebuffer_orthographic (fb, 0, 0, dest_texture_width, dest_texture_height, -1., 1.);
|
||||
|
||||
if (!tower->pipeline_template)
|
||||
if (width > 0)
|
||||
{
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
tower->pipeline_template = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL);
|
||||
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)
|
||||
{
|
||||
CoglTexture *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;
|
||||
CoglTexture *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);
|
||||
}
|
||||
|
||||
pipeline = cogl_pipeline_copy (tower->pipeline_template);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, tower->textures[level - 1]);
|
||||
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;
|
||||
|
||||
cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
cogl_object_unref (pipeline);
|
||||
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)
|
||||
{
|
||||
texture_tower_revalidate_fbo (tower, level);
|
||||
if (!texture_tower_revalidate_fbo (tower, level))
|
||||
texture_tower_revalidate_client (tower, level);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#include <meta/compositor-mutter.h>
|
||||
#include "meta-surface-actor.h"
|
||||
|
||||
MetaWindowActor *meta_window_actor_new (MetaWindow *window);
|
||||
|
||||
@@ -24,8 +25,8 @@ 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_process_x11_damage (MetaWindowActor *self,
|
||||
XDamageNotifyEvent *event);
|
||||
|
||||
void meta_window_actor_pre_paint (MetaWindowActor *self);
|
||||
void meta_window_actor_post_paint (MetaWindowActor *self);
|
||||
@@ -58,4 +59,7 @@ void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
|
||||
void meta_window_actor_effect_completed (MetaWindowActor *actor,
|
||||
gulong event);
|
||||
|
||||
MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self);
|
||||
void meta_window_actor_update_surface (MetaWindowActor *self);
|
||||
|
||||
#endif /* META_WINDOW_ACTOR_PRIVATE_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -122,7 +122,6 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
|
||||
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
|
||||
ClutterActor *stage = clutter_actor_get_stage (actor);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen);
|
||||
|
||||
/* Normally we expect an actor to be drawn at it's position on the screen.
|
||||
* However, if we're inside the paint of a ClutterClone, that won't be the
|
||||
@@ -165,15 +164,6 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
paint_y_offset = paint_y_origin - actor_y_origin;
|
||||
cairo_region_translate (clip_region, -paint_x_offset, -paint_y_offset);
|
||||
|
||||
if (info->unredirected_window != NULL)
|
||||
{
|
||||
cairo_rectangle_int_t unredirected_rect;
|
||||
|
||||
meta_window_get_frame_rect (info->unredirected_window, (MetaRectangle *)&unredirected_rect);
|
||||
cairo_region_subtract_rectangle (unobscured_region, &unredirected_rect);
|
||||
cairo_region_subtract_rectangle (clip_region, &unredirected_rect);
|
||||
}
|
||||
|
||||
meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region);
|
||||
|
||||
cairo_region_destroy (unobscured_region);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <gmodule.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DESTROY_TIMEOUT 250
|
||||
#define DESTROY_TIMEOUT 100
|
||||
#define MINIMIZE_TIMEOUT 250
|
||||
#define MAXIMIZE_TIMEOUT 250
|
||||
#define MAP_TIMEOUT 250
|
||||
@@ -488,8 +488,6 @@ on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
/* FIXME - we shouldn't assume the original scale, it should be saved
|
||||
* at the start of the effect */
|
||||
clutter_actor_set_scale (data->actor, 1.0, 1.0);
|
||||
clutter_actor_move_anchor_point_from_gravity (data->actor,
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
meta_plugin_minimize_completed (plugin, window_actor);
|
||||
@@ -526,9 +524,6 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
|
||||
apriv->is_minimized = TRUE;
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
|
||||
animation = clutter_actor_animate (actor,
|
||||
CLUTTER_EASE_IN_SINE,
|
||||
MINIMIZE_TIMEOUT,
|
||||
@@ -567,8 +562,6 @@ on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
|
||||
/* FIXME - don't assume the original scale was 1.0 */
|
||||
clutter_actor_set_scale (data->actor, 1.0, 1.0);
|
||||
clutter_actor_move_anchor_point_from_gravity (data->actor,
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
meta_plugin_maximize_completed (plugin, window_actor);
|
||||
@@ -593,10 +586,8 @@ maximize (MetaPlugin *plugin,
|
||||
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
|
||||
gdouble scale_x = 1.0;
|
||||
gdouble scale_y = 1.0;
|
||||
gfloat anchor_x = 0;
|
||||
gfloat anchor_y = 0;
|
||||
gdouble scale_x = 1.0;
|
||||
gdouble scale_y = 1.0;
|
||||
|
||||
type = meta_window_get_window_type (meta_window);
|
||||
|
||||
@@ -620,13 +611,6 @@ maximize (MetaPlugin *plugin,
|
||||
scale_x = (gdouble)end_width / (gdouble) width;
|
||||
scale_y = (gdouble)end_height / (gdouble) height;
|
||||
|
||||
anchor_x = (gdouble)(x - end_x)*(gdouble)width /
|
||||
((gdouble)(end_width - width));
|
||||
anchor_y = (gdouble)(y - end_y)*(gdouble)height /
|
||||
((gdouble)(end_height - height));
|
||||
|
||||
clutter_actor_move_anchor_point (actor, anchor_x, anchor_y);
|
||||
|
||||
animation = clutter_actor_animate (actor,
|
||||
CLUTTER_EASE_IN_SINE,
|
||||
MAXIMIZE_TIMEOUT,
|
||||
@@ -681,9 +665,6 @@ on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
||||
|
||||
apriv->tml_map = NULL;
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (data->actor,
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
meta_plugin_map_completed (plugin, window_actor);
|
||||
|
||||
@@ -769,14 +750,12 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
|
||||
animation = clutter_actor_animate (actor,
|
||||
CLUTTER_EASE_IN_SINE,
|
||||
CLUTTER_EASE_OUT_QUAD,
|
||||
DESTROY_TIMEOUT,
|
||||
"scale-x", 0.0,
|
||||
"scale-y", 1.0,
|
||||
"opacity", 0,
|
||||
"scale-x", 0.8,
|
||||
"scale-y", 0.8,
|
||||
NULL);
|
||||
apriv->tml_destroy = clutter_animation_get_timeline (animation);
|
||||
data->plugin = plugin;
|
||||
|
||||
@@ -366,11 +366,25 @@ meta_barrier_fire_event (MetaBarrier *barrier,
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_display_process_barrier_event (MetaDisplay *display,
|
||||
XIBarrierEvent *xev)
|
||||
meta_display_process_barrier_event (MetaDisplay *display,
|
||||
XIEvent *event)
|
||||
{
|
||||
MetaBarrier *barrier;
|
||||
XIBarrierEvent *xev;
|
||||
|
||||
if (event == NULL)
|
||||
return FALSE;
|
||||
|
||||
switch (event->evtype)
|
||||
{
|
||||
case XI_BarrierHit:
|
||||
case XI_BarrierLeave:
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
xev = (XIBarrierEvent *) event;
|
||||
barrier = g_hash_table_lookup (display->xids, &xev->barrier);
|
||||
if (barrier != NULL)
|
||||
{
|
||||
|
||||
@@ -58,88 +58,6 @@
|
||||
#include <canberra-gtk.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* bell_flash_screen:
|
||||
* @display: The display which owns the screen (rather redundant)
|
||||
* @screen: The screen to flash
|
||||
*
|
||||
* Flashes one entire screen. This is done by making a window the size of the
|
||||
* whole screen (or reusing the old one, if it's still around), mapping it,
|
||||
* painting it white and then black, and then unmapping it. We set saveunder so
|
||||
* that all the windows behind it come back immediately.
|
||||
*
|
||||
* Unlike frame flashes, we don't do fullscreen flashes with a timeout; rather,
|
||||
* we do them in one go, because we don't have to rely on the theme code
|
||||
* redrawing the frame for us in order to do the flash.
|
||||
*/
|
||||
/*
|
||||
* Bug: The way I read it, this appears not to do the flash
|
||||
* the first time we flash a particular display. Am I wrong?
|
||||
*
|
||||
* Bug: This appears to destroy our current XSync status.
|
||||
*/
|
||||
static void
|
||||
bell_flash_screen (MetaDisplay *display,
|
||||
MetaScreen *screen)
|
||||
{
|
||||
Window root = screen->xroot;
|
||||
int width = screen->rect.width;
|
||||
int height = screen->rect.height;
|
||||
|
||||
if (screen->flash_window == None)
|
||||
{
|
||||
Visual *visual = (Visual *)CopyFromParent;
|
||||
XSetWindowAttributes xswa;
|
||||
int depth = CopyFromParent;
|
||||
xswa.save_under = True;
|
||||
xswa.override_redirect = True;
|
||||
/*
|
||||
* TODO: use XGetVisualInfo and determine which is an
|
||||
* overlay, if one is present, and use the Overlay visual
|
||||
* for this window (for performance reasons).
|
||||
* Not sure how to tell this yet...
|
||||
*/
|
||||
screen->flash_window = XCreateWindow (display->xdisplay, root,
|
||||
0, 0, width, height,
|
||||
0, depth,
|
||||
InputOutput,
|
||||
visual,
|
||||
/* note: XSun doesn't like SaveUnder here */
|
||||
CWSaveUnder | CWOverrideRedirect,
|
||||
&xswa);
|
||||
XSelectInput (display->xdisplay, screen->flash_window, ExposureMask);
|
||||
XMapWindow (display->xdisplay, screen->flash_window);
|
||||
XSync (display->xdisplay, False);
|
||||
XFlush (display->xdisplay);
|
||||
XUnmapWindow (display->xdisplay, screen->flash_window);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* just draw something in the window */
|
||||
GC gc = XCreateGC (display->xdisplay, screen->flash_window, 0, NULL);
|
||||
XMapWindow (display->xdisplay, screen->flash_window);
|
||||
XSetForeground (display->xdisplay, gc,
|
||||
WhitePixel (display->xdisplay,
|
||||
XScreenNumberOfScreen (screen->xscreen)));
|
||||
XFillRectangle (display->xdisplay, screen->flash_window, gc,
|
||||
0, 0, width, height);
|
||||
XSetForeground (display->xdisplay, gc,
|
||||
BlackPixel (display->xdisplay,
|
||||
XScreenNumberOfScreen (screen->xscreen)));
|
||||
XFillRectangle (display->xdisplay, screen->flash_window, gc,
|
||||
0, 0, width, height);
|
||||
XFlush (display->xdisplay);
|
||||
XSync (display->xdisplay, False);
|
||||
XUnmapWindow (display->xdisplay, screen->flash_window);
|
||||
XFreeGC (display->xdisplay, gc);
|
||||
}
|
||||
|
||||
if (meta_prefs_get_focus_mode () != G_DESKTOP_FOCUS_MODE_CLICK &&
|
||||
!display->mouse_mode)
|
||||
meta_display_increment_focus_sentinel (display);
|
||||
XFlush (display->xdisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* bell_flash_fullscreen:
|
||||
* @display: The display the event came in on
|
||||
@@ -164,12 +82,7 @@ bell_flash_fullscreen (MetaDisplay *display,
|
||||
{
|
||||
screen = meta_display_screen_for_xwindow (display, xkb_bell_ev->window);
|
||||
if (screen)
|
||||
{
|
||||
if (display->compositor)
|
||||
meta_compositor_flash_screen (display->compositor, screen);
|
||||
else
|
||||
bell_flash_screen (display, screen);
|
||||
}
|
||||
meta_compositor_flash_screen (display->compositor, screen);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -177,10 +90,7 @@ bell_flash_fullscreen (MetaDisplay *display,
|
||||
while (screen_list)
|
||||
{
|
||||
screen = (MetaScreen *) screen_list->data;
|
||||
if (display->compositor)
|
||||
meta_compositor_flash_screen (display->compositor, screen);
|
||||
else
|
||||
bell_flash_screen (display, screen);
|
||||
meta_compositor_flash_screen (display->compositor, screen);
|
||||
screen_list = screen_list->next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,6 +425,7 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
* the monitor.
|
||||
*/
|
||||
if (meta_prefs_get_force_fullscreen() &&
|
||||
window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND &&
|
||||
!window->hide_titlebar_when_maximized &&
|
||||
(window->decorated || !meta_window_is_client_decorated (window)) &&
|
||||
meta_rectangle_equal (new, &monitor_info->rect) &&
|
||||
|
||||
@@ -33,7 +33,8 @@ typedef enum
|
||||
META_DO_GRAVITY_ADJUST = 1 << 1,
|
||||
META_IS_USER_ACTION = 1 << 2,
|
||||
META_IS_MOVE_ACTION = 1 << 3,
|
||||
META_IS_RESIZE_ACTION = 1 << 4
|
||||
META_IS_RESIZE_ACTION = 1 << 4,
|
||||
META_IS_WAYLAND_RESIZE = 1 << 5
|
||||
} MetaMoveResizeFlags;
|
||||
|
||||
void meta_window_constrain (MetaWindow *window,
|
||||
|
||||
@@ -153,7 +153,7 @@ meta_core_get (Display *xdisplay,
|
||||
break;
|
||||
|
||||
default:
|
||||
meta_warning(_("Unknown window information request: %d"), request);
|
||||
meta_warning("Unknown window information request: %d\n", request);
|
||||
}
|
||||
|
||||
request = va_arg (args, MetaCoreGetType);
|
||||
@@ -270,6 +270,8 @@ meta_core_lower_beneath_grab_window (Display *xdisplay,
|
||||
MetaDisplay *display;
|
||||
MetaScreen *screen;
|
||||
MetaWindow *grab_window;
|
||||
MetaStackWindow stack_window;
|
||||
MetaStackWindow stack_sibling;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
screen = meta_display_screen_for_xwindow (display, xwindow);
|
||||
@@ -281,9 +283,13 @@ meta_core_lower_beneath_grab_window (Display *xdisplay,
|
||||
changes.stack_mode = Below;
|
||||
changes.sibling = meta_window_get_toplevel_xwindow (grab_window);
|
||||
|
||||
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||
stack_window.x11.xwindow = xwindow;
|
||||
stack_sibling.any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||
stack_sibling.x11.xwindow = changes.sibling;
|
||||
meta_stack_tracker_record_lower_below (screen->stack_tracker,
|
||||
xwindow,
|
||||
changes.sibling,
|
||||
&stack_window,
|
||||
&stack_sibling,
|
||||
XNextRequest (screen->display->xdisplay));
|
||||
|
||||
meta_error_trap_push (display);
|
||||
@@ -712,16 +718,6 @@ meta_core_set_screen_cursor (Display *xdisplay,
|
||||
meta_frame_set_screen_cursor (window->frame, cursor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_increment_event_serial (Display *xdisplay)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
|
||||
meta_display_increment_event_serial (display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_invalidate_default_icons (void)
|
||||
{
|
||||
|
||||
@@ -193,12 +193,6 @@ void meta_core_set_screen_cursor (Display *xdisplay,
|
||||
Window frame_on_screen,
|
||||
MetaCursor cursor);
|
||||
|
||||
/* Used because we ignore EnterNotify when a window is unmapped that
|
||||
* really shouldn't cause focus changes, by comparing the event serial
|
||||
* of the EnterNotify and the UnmapNotify.
|
||||
*/
|
||||
void meta_core_increment_event_serial (Display *display);
|
||||
|
||||
void meta_invalidate_default_icons (void);
|
||||
|
||||
void meta_core_add_old_event_mask (Display *xdisplay,
|
||||
|
||||
@@ -37,18 +37,17 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "wayland/meta-wayland-surface.h"
|
||||
|
||||
static void meta_window_present_delete_dialog (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
|
||||
static void
|
||||
delete_ping_reply_func (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
delete_ping_reply_func (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
void *user_data)
|
||||
{
|
||||
meta_topic (META_DEBUG_PING,
|
||||
"Got reply to delete ping for %s\n",
|
||||
((MetaWindow*)user_data)->desc);
|
||||
meta_topic (META_DEBUG_PING, "Got reply to delete ping for %s\n", window->desc);
|
||||
|
||||
/* we do nothing */
|
||||
}
|
||||
@@ -66,12 +65,10 @@ dialog_exited (GPid pid, int status, gpointer user_data)
|
||||
}
|
||||
|
||||
static void
|
||||
delete_ping_timeout_func (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
delete_ping_timeout_func (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
void *user_data)
|
||||
{
|
||||
MetaWindow *window = user_data;
|
||||
char *window_title;
|
||||
gchar *window_content, *tmp;
|
||||
GPid dialog_pid;
|
||||
@@ -135,36 +132,42 @@ void
|
||||
meta_window_check_alive (MetaWindow *window,
|
||||
guint32 timestamp)
|
||||
{
|
||||
meta_display_ping_window (window->display,
|
||||
window,
|
||||
meta_display_ping_window (window,
|
||||
timestamp,
|
||||
delete_ping_reply_func,
|
||||
delete_ping_timeout_func,
|
||||
window);
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_delete (MetaWindow *window,
|
||||
guint32 timestamp)
|
||||
{
|
||||
meta_error_trap_push (window->display);
|
||||
if (window->delete_window)
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Deleting %s with delete_window request\n",
|
||||
window->desc);
|
||||
meta_window_send_icccm_message (window,
|
||||
window->display->atom_WM_DELETE_WINDOW,
|
||||
timestamp);
|
||||
meta_error_trap_push (window->display);
|
||||
if (window->delete_window)
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Deleting %s with delete_window request\n",
|
||||
window->desc);
|
||||
meta_window_send_icccm_message (window,
|
||||
window->display->atom_WM_DELETE_WINDOW,
|
||||
timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Deleting %s with explicit kill\n",
|
||||
window->desc);
|
||||
XKillClient (window->display->xdisplay, window->xwindow);
|
||||
}
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Deleting %s with explicit kill\n",
|
||||
window->desc);
|
||||
XKillClient (window->display->xdisplay, window->xwindow);
|
||||
meta_wayland_surface_delete (window->surface);
|
||||
}
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
meta_window_check_alive (window, timestamp);
|
||||
|
||||
@@ -258,8 +261,7 @@ meta_window_present_delete_dialog (MetaWindow *window, guint32 timestamp)
|
||||
{
|
||||
MetaWindow *w = tmp->data;
|
||||
|
||||
if (w->xtransient_for == window->xwindow &&
|
||||
w->res_class &&
|
||||
if (w->transient_for == window && w->res_class &&
|
||||
g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0)
|
||||
{
|
||||
meta_window_activate (w, timestamp);
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "keybindings-private.h"
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/barrier.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||
#include <libsn/sn.h>
|
||||
@@ -54,10 +55,9 @@ typedef struct _MetaWindowPropHooks MetaWindowPropHooks;
|
||||
|
||||
typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
|
||||
|
||||
typedef void (* MetaWindowPingFunc) (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
guint32 timestamp,
|
||||
gpointer user_data);
|
||||
typedef void (* MetaWindowPingFunc) (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
gpointer user_data);
|
||||
|
||||
typedef enum {
|
||||
META_LIST_DEFAULT = 0, /* normal windows */
|
||||
@@ -91,6 +91,8 @@ struct _MetaDisplay
|
||||
char *name;
|
||||
Display *xdisplay;
|
||||
|
||||
int clutter_event_filter;
|
||||
|
||||
Window leader_window;
|
||||
Window timestamp_pinging_window;
|
||||
|
||||
@@ -151,6 +153,7 @@ struct _MetaDisplay
|
||||
GSList *screens;
|
||||
MetaScreen *active_screen;
|
||||
GHashTable *xids;
|
||||
GHashTable *wayland_windows;
|
||||
int error_traps;
|
||||
int (* error_trap_handler) (Display *display,
|
||||
XErrorEvent *error);
|
||||
@@ -185,7 +188,7 @@ struct _MetaDisplay
|
||||
MetaWindow* autoraise_window;
|
||||
|
||||
/* Alt+click button grabs */
|
||||
unsigned int window_grab_modifiers;
|
||||
ClutterModifierType window_grab_modifiers;
|
||||
|
||||
/* current window operation */
|
||||
MetaGrabOp grab_op;
|
||||
@@ -212,7 +215,6 @@ struct _MetaDisplay
|
||||
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
||||
MetaResizePopup *grab_resize_popup;
|
||||
GTimeVal grab_last_moveresize_time;
|
||||
guint32 grab_motion_notify_time;
|
||||
GList* grab_old_window_stacking;
|
||||
MetaEdgeResistanceData *grab_edge_resistance_data;
|
||||
unsigned int grab_last_user_action_was_snap;
|
||||
@@ -377,6 +379,11 @@ void meta_display_register_x_window (MetaDisplay *display,
|
||||
void meta_display_unregister_x_window (MetaDisplay *display,
|
||||
Window xwindow);
|
||||
|
||||
void meta_display_register_wayland_window (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
void meta_display_unregister_wayland_window (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
MetaWindow* meta_display_lookup_sync_alarm (MetaDisplay *display,
|
||||
XSyncAlarm alarm);
|
||||
@@ -436,14 +443,13 @@ void meta_display_retheme_all (void);
|
||||
void meta_display_set_cursor_theme (const char *theme,
|
||||
int size);
|
||||
|
||||
void meta_display_ping_window (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
void meta_display_ping_window (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
MetaWindowPingFunc ping_reply_func,
|
||||
MetaWindowPingFunc ping_timeout_func,
|
||||
void *user_data);
|
||||
gboolean meta_display_window_has_pending_pings (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
void meta_display_pong_for_serial (MetaDisplay *display,
|
||||
guint32 serial);
|
||||
|
||||
int meta_resize_gravity_from_grab_op (MetaGrabOp op);
|
||||
|
||||
@@ -464,18 +470,17 @@ void meta_display_queue_autoraise_callback (MetaDisplay *display,
|
||||
void meta_display_remove_autoraise_callback (MetaDisplay *display);
|
||||
|
||||
void meta_display_overlay_key_activate (MetaDisplay *display);
|
||||
void meta_display_accelerator_activate (MetaDisplay *display,
|
||||
guint action,
|
||||
guint deviceid,
|
||||
guint timestamp);
|
||||
void meta_display_accelerator_activate (MetaDisplay *display,
|
||||
guint action,
|
||||
ClutterKeyEvent *event);
|
||||
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
|
||||
|
||||
/* In above-tab-keycode.c */
|
||||
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
|
||||
|
||||
#ifdef HAVE_XI23
|
||||
gboolean meta_display_process_barrier_event (MetaDisplay *display,
|
||||
XIBarrierEvent *event);
|
||||
gboolean meta_display_process_barrier_event (MetaDisplay *display,
|
||||
XIEvent *event);
|
||||
#endif /* HAVE_XI23 */
|
||||
|
||||
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
|
||||
|
||||
2599
src/core/display.c
2599
src/core/display.c
File diff suppressed because it is too large
Load Diff
@@ -45,6 +45,7 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
XSetWindowAttributes attrs;
|
||||
Visual *visual;
|
||||
gulong create_serial;
|
||||
MetaStackWindow stack_window;
|
||||
|
||||
if (window->frame)
|
||||
return;
|
||||
@@ -100,8 +101,10 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
frame->rect.height,
|
||||
frame->window->screen->number,
|
||||
&create_serial);
|
||||
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||
stack_window.x11.xwindow = frame->xwindow;
|
||||
meta_stack_tracker_record_add (window->screen->stack_tracker,
|
||||
frame->xwindow,
|
||||
&stack_window,
|
||||
create_serial);
|
||||
|
||||
meta_verbose ("Frame for %s is 0x%lx\n", frame->window->desc, frame->xwindow);
|
||||
@@ -125,8 +128,9 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
window->rect.x = 0;
|
||||
window->rect.y = 0;
|
||||
|
||||
stack_window.x11.xwindow = window->xwindow;
|
||||
meta_stack_tracker_record_remove (window->screen->stack_tracker,
|
||||
window->xwindow,
|
||||
&stack_window,
|
||||
XNextRequest (window->display->xdisplay));
|
||||
XReparentWindow (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
@@ -161,6 +165,7 @@ meta_window_destroy_frame (MetaWindow *window)
|
||||
{
|
||||
MetaFrame *frame;
|
||||
MetaFrameBorders borders;
|
||||
MetaStackWindow stack_window;
|
||||
|
||||
if (window->frame == NULL)
|
||||
return;
|
||||
@@ -187,8 +192,10 @@ meta_window_destroy_frame (MetaWindow *window)
|
||||
"Incrementing unmaps_pending on %s for reparent back to root\n", window->desc);
|
||||
window->unmaps_pending += 1;
|
||||
}
|
||||
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||
stack_window.x11.xwindow = window->xwindow;
|
||||
meta_stack_tracker_record_add (window->screen->stack_tracker,
|
||||
window->xwindow,
|
||||
&stack_window,
|
||||
XNextRequest (window->display->xdisplay));
|
||||
XReparentWindow (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
|
||||
@@ -104,9 +104,9 @@ gboolean meta_window_grab_all_keys (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
void meta_window_ungrab_all_keys (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
gboolean meta_display_process_key_event (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
XIDeviceEvent *event);
|
||||
gboolean meta_display_process_key_event (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
ClutterKeyEvent *event);
|
||||
void meta_display_process_mapping_event (MetaDisplay *display,
|
||||
XEvent *event);
|
||||
|
||||
@@ -122,7 +122,3 @@ void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
|
||||
const char *meta_prefs_get_iso_next_group_option (void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
139
src/core/main.c
139
src/core/main.c
@@ -50,11 +50,11 @@
|
||||
#include "display-private.h"
|
||||
#include <meta/errors.h>
|
||||
#include "ui.h"
|
||||
#include "session.h"
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/compositor.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <glib-unix.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -77,6 +77,10 @@
|
||||
#include <girepository.h>
|
||||
#endif
|
||||
|
||||
#include "x11/session.h"
|
||||
|
||||
#include "wayland/meta-wayland.h"
|
||||
|
||||
/*
|
||||
* The exit code we'll return to our parent process when we eventually die.
|
||||
*/
|
||||
@@ -187,6 +191,8 @@ static gchar *opt_client_id;
|
||||
static gboolean opt_replace_wm;
|
||||
static gboolean opt_disable_sm;
|
||||
static gboolean opt_sync;
|
||||
static gboolean opt_wayland;
|
||||
static gboolean opt_display_server;
|
||||
|
||||
static GOptionEntry meta_options[] = {
|
||||
{
|
||||
@@ -224,6 +230,17 @@ static GOptionEntry meta_options[] = {
|
||||
N_("Make X calls synchronous"),
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"wayland", 0, 0, G_OPTION_ARG_NONE,
|
||||
&opt_wayland,
|
||||
N_("Run as a wayland compositor"),
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"display-server", 0, 0, G_OPTION_ARG_NONE,
|
||||
&opt_display_server,
|
||||
N_("Run as a full display server, rather than nested")
|
||||
},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@@ -247,9 +264,6 @@ meta_get_option_context (void)
|
||||
|
||||
ctx = g_option_context_new (NULL);
|
||||
g_option_context_add_main_entries (ctx, meta_options, GETTEXT_PACKAGE);
|
||||
g_option_context_add_group (ctx, clutter_get_option_group_without_init ());
|
||||
g_option_context_add_group (ctx, cogl_get_option_group ());
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@@ -328,16 +342,17 @@ meta_clutter_init (void)
|
||||
* also is %NULL, use the default - :0.0
|
||||
*/
|
||||
static void
|
||||
meta_select_display (gchar *display_name)
|
||||
meta_select_display (char *display_arg)
|
||||
{
|
||||
gchar *envVar = "";
|
||||
const char *display_name;
|
||||
|
||||
if (display_arg)
|
||||
display_name = (const char *) display_arg;
|
||||
else
|
||||
display_name = g_getenv ("MUTTER_DISPLAY");
|
||||
|
||||
if (display_name)
|
||||
envVar = g_strconcat ("DISPLAY=", display_name, NULL);
|
||||
else if (g_getenv ("MUTTER_DISPLAY"))
|
||||
envVar = g_strconcat ("DISPLAY=",
|
||||
g_getenv ("MUTTER_DISPLAY"), NULL);
|
||||
/* DO NOT FREE envVar, putenv() sucks */
|
||||
putenv (envVar);
|
||||
g_setenv ("DISPLAY", display_name, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -348,28 +363,17 @@ meta_finalize (void)
|
||||
if (display)
|
||||
meta_display_close (display,
|
||||
CurrentTime); /* I doubt correct timestamps matter here */
|
||||
}
|
||||
|
||||
static int sigterm_pipe_fds[2] = { -1, -1 };
|
||||
|
||||
static void
|
||||
sigterm_handler (int signum)
|
||||
{
|
||||
if (sigterm_pipe_fds[1] >= 0)
|
||||
{
|
||||
int G_GNUC_UNUSED dummy;
|
||||
|
||||
dummy = write (sigterm_pipe_fds[1], "", 1);
|
||||
close (sigterm_pipe_fds[1]);
|
||||
sigterm_pipe_fds[1] = -1;
|
||||
}
|
||||
if (meta_is_wayland_compositor ())
|
||||
meta_wayland_finalize ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_sigterm (void)
|
||||
on_sigterm (gpointer user_data)
|
||||
{
|
||||
meta_quit (META_EXIT_SUCCESS);
|
||||
return FALSE;
|
||||
meta_quit (EXIT_SUCCESS);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,9 +387,8 @@ meta_init (void)
|
||||
{
|
||||
struct sigaction act;
|
||||
sigset_t empty_mask;
|
||||
GIOChannel *channel;
|
||||
ClutterSettings *clutter_settings;
|
||||
|
||||
|
||||
sigemptyset (&empty_mask);
|
||||
act.sa_handler = SIG_IGN;
|
||||
act.sa_mask = empty_mask;
|
||||
@@ -399,26 +402,18 @@ meta_init (void)
|
||||
g_strerror (errno));
|
||||
#endif
|
||||
|
||||
if (pipe (sigterm_pipe_fds) != 0)
|
||||
g_printerr ("Failed to create SIGTERM pipe: %s\n",
|
||||
g_strerror (errno));
|
||||
|
||||
channel = g_io_channel_unix_new (sigterm_pipe_fds[0]);
|
||||
g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
|
||||
g_io_add_watch (channel, G_IO_IN, (GIOFunc) on_sigterm, NULL);
|
||||
g_io_channel_set_close_on_unref (channel, TRUE);
|
||||
g_io_channel_unref (channel);
|
||||
|
||||
act.sa_handler = &sigterm_handler;
|
||||
if (sigaction (SIGTERM, &act, NULL) < 0)
|
||||
g_printerr ("Failed to register SIGTERM handler: %s\n",
|
||||
g_strerror (errno));
|
||||
g_unix_signal_add (SIGTERM, on_sigterm, NULL);
|
||||
|
||||
if (g_getenv ("MUTTER_VERBOSE"))
|
||||
meta_set_verbose (TRUE);
|
||||
if (g_getenv ("MUTTER_DEBUG"))
|
||||
meta_set_debugging (TRUE);
|
||||
|
||||
if (opt_display_server)
|
||||
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
|
||||
|
||||
meta_set_is_wayland_compositor (opt_wayland);
|
||||
|
||||
if (g_get_home_dir ())
|
||||
if (chdir (g_get_home_dir ()) < 0)
|
||||
meta_warning ("Could not change to home directory %s.\n",
|
||||
@@ -430,9 +425,16 @@ meta_init (void)
|
||||
g_irepository_prepend_search_path (MUTTER_PKGLIBDIR);
|
||||
#endif
|
||||
|
||||
meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL));
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
/* NB: When running as a hybrid wayland compositor we run our own headless X
|
||||
* server so the user can't control the X display to connect too. */
|
||||
meta_wayland_init ();
|
||||
}
|
||||
else
|
||||
meta_select_display (opt_display_name);
|
||||
|
||||
meta_select_display (opt_display_name);
|
||||
meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL));
|
||||
|
||||
if (opt_replace_wm)
|
||||
meta_set_replace_current_wm (TRUE);
|
||||
@@ -441,13 +443,20 @@ meta_init (void)
|
||||
meta_fatal ("Can't specify both SM save file and SM client id\n");
|
||||
|
||||
meta_main_loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
|
||||
meta_ui_init ();
|
||||
|
||||
/*
|
||||
* Clutter can only be initialized after the UI.
|
||||
*/
|
||||
meta_clutter_init ();
|
||||
/* If we are running with wayland then we don't wait until we have
|
||||
* an X connection before initializing clutter we instead initialize
|
||||
* it earlier since we need to initialize the GL driver so the driver
|
||||
* can register any needed wayland extensions. */
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
/*
|
||||
* Clutter can only be initialized after the UI.
|
||||
*/
|
||||
meta_clutter_init ();
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: We cannot handle high dpi scaling yet, so fix the scale to 1
|
||||
@@ -495,6 +504,32 @@ meta_register_with_session (void)
|
||||
g_free (opt_client_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_activate_session:
|
||||
*
|
||||
* Tells mutter to activate the session. When mutter is a
|
||||
* Wayland compositor, this tells logind to switch over to
|
||||
* the new session.
|
||||
*/
|
||||
gboolean
|
||||
meta_activate_session (void)
|
||||
{
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
GError *error = NULL;
|
||||
|
||||
if (!meta_wayland_compositor_activate_session (compositor, &error))
|
||||
{
|
||||
g_warning ("Could not activate session: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_run: (skip)
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
* Copyright 2013 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@@ -23,10 +23,27 @@
|
||||
#define META_CURSOR_TRACKER_PRIVATE_H
|
||||
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
#include <wayland-server.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||
XEvent *xevent);
|
||||
|
||||
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursor cursor);
|
||||
void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursor cursor);
|
||||
void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||
struct wl_resource *buffer,
|
||||
int hot_x,
|
||||
int hot_y);
|
||||
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
|
||||
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursor cursor);
|
||||
|
||||
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||
int new_x,
|
||||
int new_y);
|
||||
void meta_cursor_tracker_paint (MetaCursorTracker *tracker);
|
||||
|
||||
void meta_cursor_tracker_force_update (MetaCursorTracker *tracker);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,16 +22,21 @@
|
||||
/**
|
||||
* SECTION:cursor-tracker
|
||||
* @title: MetaCursorTracker
|
||||
* @short_description: Mutter cursor tracking helper
|
||||
* @short_description: Mutter cursor tracking helper. Originally only
|
||||
* tracking the cursor image, now more of a "core
|
||||
* pointer abstraction"
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <string.h>
|
||||
#include <meta/main.h>
|
||||
#include <meta/util.h>
|
||||
#include <meta/errors.h>
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <gbm.h>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
@@ -42,19 +47,65 @@
|
||||
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "screen-private.h"
|
||||
#include "monitor-private.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X 7
|
||||
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y 4
|
||||
|
||||
typedef struct {
|
||||
CoglTexture2D *texture;
|
||||
struct gbm_bo *bo;
|
||||
int hot_x, hot_y;
|
||||
|
||||
int ref_count;
|
||||
} MetaCursorReference;
|
||||
|
||||
struct _MetaCursorTracker {
|
||||
GObject parent_instance;
|
||||
|
||||
MetaScreen *screen;
|
||||
|
||||
gboolean is_showing;
|
||||
gboolean has_hw_cursor;
|
||||
|
||||
CoglTexture2D *sprite;
|
||||
int hot_x, hot_y;
|
||||
/* The cursor tracker stores the cursor for the current grab
|
||||
* operation, the cursor for the window with pointer focus, and
|
||||
* the cursor for the root window, which contains either the
|
||||
* default arrow cursor or the 'busy' hourglass if we're launching
|
||||
* an app.
|
||||
*
|
||||
* We choose the first one available -- if there's a grab cursor,
|
||||
* we choose that cursor, if there's window cursor, we choose that,
|
||||
* otherwise we choose the root cursor.
|
||||
*
|
||||
* The displayed_cursor contains the chosen cursor.
|
||||
*/
|
||||
MetaCursorReference *displayed_cursor;
|
||||
|
||||
MetaCursorReference *grab_cursor;
|
||||
|
||||
/* Wayland clients can set a NULL buffer as their cursor
|
||||
* explicitly, which means that we shouldn't display anything.
|
||||
* So, we can't simply store a NULL in window_cursor to
|
||||
* determine an unset window cursor; we need an extra boolean.
|
||||
*/
|
||||
gboolean has_window_cursor;
|
||||
MetaCursorReference *window_cursor;
|
||||
|
||||
MetaCursorReference *root_cursor;
|
||||
|
||||
MetaCursorReference *default_cursors[META_CURSOR_LAST];
|
||||
|
||||
int current_x, current_y;
|
||||
MetaRectangle current_rect;
|
||||
MetaRectangle previous_rect;
|
||||
gboolean previous_is_valid;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
int drm_fd;
|
||||
struct gbm_device *gbm;
|
||||
};
|
||||
|
||||
struct _MetaCursorTrackerClass {
|
||||
@@ -70,6 +121,35 @@ enum {
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
static void meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
|
||||
MetaCRTC *crtc,
|
||||
gboolean has_hw_cursor);
|
||||
static void sync_cursor (MetaCursorTracker *tracker);
|
||||
|
||||
static MetaCursorReference *
|
||||
meta_cursor_reference_ref (MetaCursorReference *self)
|
||||
{
|
||||
g_assert (self->ref_count > 0);
|
||||
self->ref_count++;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_reference_unref (MetaCursorReference *self)
|
||||
{
|
||||
self->ref_count--;
|
||||
|
||||
if (self->ref_count == 0)
|
||||
{
|
||||
cogl_object_unref (self->texture);
|
||||
if (self->bo)
|
||||
gbm_bo_destroy (self->bo);
|
||||
|
||||
g_slice_free (MetaCursorReference, self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
translate_meta_cursor (MetaCursor cursor,
|
||||
guint *glyph_out,
|
||||
@@ -170,14 +250,244 @@ meta_display_create_x_cursor (MetaDisplay *display,
|
||||
return load_cursor_on_server (display, cursor);
|
||||
}
|
||||
|
||||
static XcursorImage *
|
||||
load_cursor_on_client (MetaDisplay *display,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
XcursorImage *image;
|
||||
guint glyph;
|
||||
const char *name;
|
||||
const char *theme = XcursorGetTheme (display->xdisplay);
|
||||
int size = XcursorGetDefaultSize (display->xdisplay);
|
||||
|
||||
translate_meta_cursor (cursor, &glyph, &name);
|
||||
|
||||
if (name != NULL)
|
||||
image = XcursorLibraryLoadImage (name, theme, size);
|
||||
else
|
||||
image = XcursorShapeLoadImage (glyph, theme, size);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
static MetaCursorReference *
|
||||
meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
XcursorImage *image;
|
||||
int width, height, rowstride;
|
||||
CoglPixelFormat cogl_format;
|
||||
uint32_t gbm_format;
|
||||
ClutterBackend *clutter_backend;
|
||||
CoglContext *cogl_context;
|
||||
MetaCursorReference *self;
|
||||
|
||||
image = load_cursor_on_client (tracker->screen->display, cursor);
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
width = image->width;
|
||||
height = image->height;
|
||||
rowstride = width * 4;
|
||||
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
|
||||
#else
|
||||
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||
#endif
|
||||
|
||||
self = g_slice_new0 (MetaCursorReference);
|
||||
self->ref_count = 1;
|
||||
self->hot_x = image->xhot;
|
||||
self->hot_y = image->yhot;
|
||||
|
||||
clutter_backend = clutter_get_default_backend ();
|
||||
cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
self->texture = cogl_texture_2d_new_from_data (cogl_context,
|
||||
width, height,
|
||||
cogl_format,
|
||||
rowstride,
|
||||
(uint8_t*)image->pixels,
|
||||
NULL);
|
||||
|
||||
if (tracker->gbm)
|
||||
{
|
||||
if (width > 64 || height > 64)
|
||||
{
|
||||
meta_warning ("Invalid theme cursor size (must be at most 64x64)\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (gbm_device_is_format_supported (tracker->gbm, gbm_format,
|
||||
GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
|
||||
{
|
||||
uint32_t buf[64 * 64];
|
||||
int i;
|
||||
|
||||
self->bo = gbm_bo_create (tracker->gbm, 64, 64,
|
||||
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
|
||||
|
||||
memset (buf, 0, sizeof(buf));
|
||||
for (i = 0; i < height; i++)
|
||||
memcpy (buf + i * 64, image->pixels + i * width, width * 4);
|
||||
|
||||
gbm_bo_write (self->bo, buf, 64 * 64 * 4);
|
||||
}
|
||||
else
|
||||
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
|
||||
}
|
||||
|
||||
out:
|
||||
XcursorImageDestroy (image);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static MetaCursorReference *
|
||||
meta_cursor_reference_take_texture (CoglTexture2D *texture)
|
||||
{
|
||||
MetaCursorReference *self;
|
||||
|
||||
self = g_slice_new0 (MetaCursorReference);
|
||||
self->ref_count = 1;
|
||||
|
||||
self->texture = texture;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static MetaCursorReference *
|
||||
meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
|
||||
struct wl_resource *buffer,
|
||||
int hot_x,
|
||||
int hot_y)
|
||||
{
|
||||
ClutterBackend *backend;
|
||||
CoglContext *cogl_context;
|
||||
MetaCursorReference *self;
|
||||
CoglPixelFormat cogl_format;
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
uint32_t gbm_format;
|
||||
|
||||
self = g_slice_new0 (MetaCursorReference);
|
||||
self->ref_count = 1;
|
||||
self->hot_x = hot_x;
|
||||
self->hot_y = hot_y;
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
||||
|
||||
shm_buffer = wl_shm_buffer_get (buffer);
|
||||
if (shm_buffer)
|
||||
{
|
||||
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
int width = wl_shm_buffer_get_width (shm_buffer);
|
||||
int height = wl_shm_buffer_get_height (shm_buffer);
|
||||
|
||||
switch (wl_shm_buffer_get_format (shm_buffer))
|
||||
{
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||
gbm_format = GBM_FORMAT_XRGB8888;
|
||||
break;
|
||||
#else
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
|
||||
gbm_format = GBM_FORMAT_XRGB8888;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
}
|
||||
|
||||
self->texture = cogl_texture_2d_new_from_data (cogl_context,
|
||||
width, height,
|
||||
cogl_format,
|
||||
rowstride,
|
||||
wl_shm_buffer_get_data (shm_buffer),
|
||||
NULL);
|
||||
|
||||
if (width > 64 || height > 64)
|
||||
{
|
||||
meta_warning ("Invalid cursor size (must be at most 64x64), falling back to software (GL) cursors\n");
|
||||
return self;
|
||||
}
|
||||
|
||||
if (tracker->gbm)
|
||||
{
|
||||
if (gbm_device_is_format_supported (tracker->gbm, gbm_format,
|
||||
GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
|
||||
{
|
||||
uint8_t *data;
|
||||
uint8_t buf[4 * 64 * 64];
|
||||
int i;
|
||||
|
||||
self->bo = gbm_bo_create (tracker->gbm, 64, 64,
|
||||
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
|
||||
|
||||
data = wl_shm_buffer_get_data (shm_buffer);
|
||||
memset (buf, 0, sizeof(buf));
|
||||
for (i = 0; i < height; i++)
|
||||
memcpy (buf + i * 4 * 64, data + i * rowstride, 4 * width);
|
||||
|
||||
gbm_bo_write (self->bo, buf, 64 * 64 * 4);
|
||||
}
|
||||
else
|
||||
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int width, height;
|
||||
|
||||
self->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
|
||||
width = cogl_texture_get_width (COGL_TEXTURE (self->texture));
|
||||
height = cogl_texture_get_height (COGL_TEXTURE (self->texture));
|
||||
|
||||
/* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
|
||||
that, so themed cursors must be padded with transparent pixels to fill the
|
||||
overlay. This is trivial if we have CPU access to the data, but it's not
|
||||
possible if the buffer is in GPU memory (and possibly tiled too), so if we
|
||||
don't get the right size, we fallback to GL.
|
||||
*/
|
||||
if (width != 64 || height != 64)
|
||||
{
|
||||
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
|
||||
return self;
|
||||
}
|
||||
|
||||
if (tracker->gbm)
|
||||
{
|
||||
self->bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER,
|
||||
buffer, GBM_BO_USE_CURSOR_64X64);
|
||||
if (!self->bo)
|
||||
meta_warning ("Importing HW cursor from wl_buffer failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_init (MetaCursorTracker *self)
|
||||
{
|
||||
/* (JS) Best (?) that can be assumed since XFixes doesn't provide a way of
|
||||
* detecting if the system mouse cursor is showing or not.
|
||||
*
|
||||
* On wayland we start with the cursor showing
|
||||
*/
|
||||
detecting if the system mouse cursor is showing or not.
|
||||
|
||||
On wayland we start with the cursor showing
|
||||
*/
|
||||
self->is_showing = TRUE;
|
||||
}
|
||||
|
||||
@@ -185,9 +495,21 @@ static void
|
||||
meta_cursor_tracker_finalize (GObject *object)
|
||||
{
|
||||
MetaCursorTracker *self = META_CURSOR_TRACKER (object);
|
||||
int i;
|
||||
|
||||
if (self->sprite)
|
||||
cogl_object_unref (self->sprite);
|
||||
if (self->displayed_cursor)
|
||||
meta_cursor_reference_unref (self->displayed_cursor);
|
||||
if (self->root_cursor)
|
||||
meta_cursor_reference_unref (self->root_cursor);
|
||||
|
||||
for (i = 0; i < META_CURSOR_LAST; i++)
|
||||
if (self->default_cursors[i])
|
||||
meta_cursor_reference_unref (self->default_cursors[i]);
|
||||
|
||||
if (self->pipeline)
|
||||
cogl_object_unref (self->pipeline);
|
||||
if (self->gbm)
|
||||
gbm_device_destroy (self->gbm);
|
||||
|
||||
G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -207,6 +529,68 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
on_monitors_changed (MetaMonitorManager *monitors,
|
||||
MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaCRTC *crtcs;
|
||||
unsigned int i, n_crtcs;
|
||||
|
||||
if (!tracker->has_hw_cursor)
|
||||
return;
|
||||
|
||||
/* Go through the new list of monitors, find out where the cursor is */
|
||||
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
|
||||
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
MetaRectangle *rect = &crtcs[i].rect;
|
||||
gboolean has;
|
||||
|
||||
has = meta_rectangle_overlap (&tracker->current_rect, rect);
|
||||
|
||||
/* Need to do it unconditionally here, our tracking is
|
||||
wrong because we reloaded the CRTCs */
|
||||
meta_cursor_tracker_set_crtc_has_hw_cursor (tracker, &crtcs[i], has);
|
||||
}
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
make_wayland_cursor_tracker (MetaScreen *screen)
|
||||
{
|
||||
MetaWaylandCompositor *compositor;
|
||||
CoglContext *ctx;
|
||||
MetaMonitorManager *monitors;
|
||||
MetaCursorTracker *self;
|
||||
|
||||
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||
self->screen = screen;
|
||||
|
||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
self->pipeline = cogl_pipeline_new (ctx);
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
compositor->seat->cursor_tracker = self;
|
||||
meta_cursor_tracker_update_position (self,
|
||||
wl_fixed_to_int (compositor->seat->pointer.x),
|
||||
wl_fixed_to_int (compositor->seat->pointer.y));
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
{
|
||||
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
|
||||
self->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
|
||||
self->gbm = gbm_create_device (self->drm_fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
monitors = meta_monitor_manager_get ();
|
||||
g_signal_connect_object (monitors, "monitors-changed",
|
||||
G_CALLBACK (on_monitors_changed), self, 0);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
make_x11_cursor_tracker (MetaScreen *screen)
|
||||
{
|
||||
@@ -236,18 +620,36 @@ meta_cursor_tracker_get_for_screen (MetaScreen *screen)
|
||||
if (screen->cursor_tracker)
|
||||
return screen->cursor_tracker;
|
||||
|
||||
self = make_x11_cursor_tracker (screen);
|
||||
if (meta_is_wayland_compositor ())
|
||||
self = make_wayland_cursor_tracker (screen);
|
||||
else
|
||||
self = make_x11_cursor_tracker (screen);
|
||||
|
||||
screen->cursor_tracker = self;
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
set_window_cursor (MetaCursorTracker *tracker,
|
||||
gboolean has_cursor,
|
||||
MetaCursorReference *cursor)
|
||||
{
|
||||
g_clear_pointer (&tracker->window_cursor, meta_cursor_reference_unref);
|
||||
if (cursor)
|
||||
tracker->window_cursor = meta_cursor_reference_ref (cursor);
|
||||
tracker->has_window_cursor = has_cursor;
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||
XEvent *xevent)
|
||||
{
|
||||
XFixesCursorNotifyEvent *notify_event;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
return FALSE;
|
||||
|
||||
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
|
||||
return FALSE;
|
||||
|
||||
@@ -255,8 +657,7 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||
if (notify_event->subtype != XFixesDisplayCursorNotify)
|
||||
return FALSE;
|
||||
|
||||
g_clear_pointer (&tracker->sprite, cogl_object_unref);
|
||||
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
|
||||
set_window_cursor (tracker, FALSE, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -270,7 +671,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||
gboolean free_cursor_data;
|
||||
CoglContext *ctx;
|
||||
|
||||
if (tracker->sprite)
|
||||
if (tracker->has_window_cursor)
|
||||
return;
|
||||
|
||||
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
|
||||
@@ -317,9 +718,11 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||
|
||||
if (sprite != NULL)
|
||||
{
|
||||
tracker->sprite = sprite;
|
||||
tracker->hot_x = cursor_image->xhot;
|
||||
tracker->hot_y = cursor_image->yhot;
|
||||
MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite);
|
||||
cursor->hot_x = cursor_image->xhot;
|
||||
cursor->hot_y = cursor_image->yhot;
|
||||
|
||||
set_window_cursor (tracker, TRUE, cursor);
|
||||
}
|
||||
XFree (cursor_image);
|
||||
}
|
||||
@@ -334,9 +737,13 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
|
||||
|
||||
ensure_xfixes_cursor (tracker);
|
||||
if (!meta_is_wayland_compositor ())
|
||||
ensure_xfixes_cursor (tracker);
|
||||
|
||||
return COGL_TEXTURE (tracker->sprite);
|
||||
if (tracker->displayed_cursor)
|
||||
return COGL_TEXTURE (tracker->displayed_cursor->texture);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -353,12 +760,70 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
||||
{
|
||||
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
|
||||
|
||||
ensure_xfixes_cursor (tracker);
|
||||
if (!meta_is_wayland_compositor ())
|
||||
ensure_xfixes_cursor (tracker);
|
||||
|
||||
if (x)
|
||||
*x = tracker->hot_x;
|
||||
if (y)
|
||||
*y = tracker->hot_y;
|
||||
if (tracker->displayed_cursor)
|
||||
{
|
||||
MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
|
||||
if (x)
|
||||
*x = displayed_cursor->hot_x;
|
||||
if (y)
|
||||
*y = displayed_cursor->hot_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x)
|
||||
*x = 0;
|
||||
if (y)
|
||||
*y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static MetaCursorReference *
|
||||
ensure_wayland_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
if (!tracker->default_cursors[cursor])
|
||||
{
|
||||
tracker->default_cursors[cursor] = meta_cursor_reference_from_theme (tracker, cursor);
|
||||
if (!tracker->default_cursors[cursor])
|
||||
meta_warning ("Failed to load cursor from theme\n");
|
||||
}
|
||||
|
||||
return meta_cursor_reference_ref (tracker->default_cursors[cursor]);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
g_clear_pointer (&tracker->grab_cursor, meta_cursor_reference_unref);
|
||||
if (cursor != META_CURSOR_DEFAULT)
|
||||
tracker->grab_cursor = ensure_wayland_cursor (tracker, cursor);
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||
struct wl_resource *buffer,
|
||||
int hot_x,
|
||||
int hot_y)
|
||||
{
|
||||
MetaCursorReference *cursor;
|
||||
|
||||
if (buffer)
|
||||
cursor = meta_cursor_reference_from_buffer (tracker, buffer, hot_x, hot_y);
|
||||
else
|
||||
cursor = NULL;
|
||||
|
||||
set_window_cursor (tracker, TRUE, cursor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
set_window_cursor (tracker, FALSE, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -374,13 +839,240 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||
XDefineCursor (display->xdisplay, tracker->screen->xroot, xcursor);
|
||||
XFlush (display->xdisplay);
|
||||
XFreeCursor (display->xdisplay, xcursor);
|
||||
|
||||
/* Now update the real root cursor */
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref);
|
||||
tracker->root_cursor = ensure_wayland_cursor (tracker, cursor);
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_hw_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaMonitorManager *monitors;
|
||||
MetaCRTC *crtcs;
|
||||
unsigned int i, n_crtcs;
|
||||
gboolean enabled;
|
||||
|
||||
enabled = tracker->displayed_cursor && tracker->displayed_cursor->bo != NULL;
|
||||
tracker->has_hw_cursor = enabled;
|
||||
|
||||
monitors = meta_monitor_manager_get ();
|
||||
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
|
||||
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
MetaRectangle *rect = &crtcs[i].rect;
|
||||
gboolean has;
|
||||
|
||||
has = enabled && meta_rectangle_overlap (&tracker->current_rect, rect);
|
||||
|
||||
if (has || crtcs[i].has_hw_cursor)
|
||||
meta_cursor_tracker_set_crtc_has_hw_cursor (tracker, &crtcs[i], has);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
move_hw_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaMonitorManager *monitors;
|
||||
MetaCRTC *crtcs;
|
||||
unsigned int i, n_crtcs;
|
||||
|
||||
monitors = meta_monitor_manager_get ();
|
||||
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
|
||||
|
||||
g_assert (tracker->has_hw_cursor);
|
||||
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
MetaRectangle *rect = &crtcs[i].rect;
|
||||
gboolean has;
|
||||
|
||||
has = meta_rectangle_overlap (&tracker->current_rect, rect);
|
||||
|
||||
if (has != crtcs[i].has_hw_cursor)
|
||||
meta_cursor_tracker_set_crtc_has_hw_cursor (tracker, &crtcs[i], has);
|
||||
if (has)
|
||||
drmModeMoveCursor (tracker->drm_fd, crtcs[i].crtc_id,
|
||||
tracker->current_rect.x - rect->x,
|
||||
tracker->current_rect.y - rect->y);
|
||||
}
|
||||
}
|
||||
|
||||
static MetaCursorReference *
|
||||
get_displayed_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
if (!tracker->is_showing)
|
||||
return NULL;
|
||||
|
||||
if (tracker->grab_cursor)
|
||||
return tracker->grab_cursor;
|
||||
|
||||
if (tracker->has_window_cursor)
|
||||
return tracker->window_cursor;
|
||||
|
||||
return tracker->root_cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_displayed_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker);
|
||||
|
||||
if (tracker->displayed_cursor == displayed_cursor)
|
||||
return;
|
||||
|
||||
g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref);
|
||||
if (displayed_cursor)
|
||||
tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
if (displayed_cursor)
|
||||
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, COGL_TEXTURE (displayed_cursor->texture));
|
||||
else
|
||||
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, NULL);
|
||||
|
||||
update_hw_cursor (tracker);
|
||||
}
|
||||
|
||||
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
ClutterActor *stage = compositor->stage;
|
||||
cairo_rectangle_int_t clip;
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
if (tracker->previous_is_valid)
|
||||
{
|
||||
cairo_rectangle_int_t clip = {
|
||||
.x = tracker->previous_rect.x,
|
||||
.y = tracker->previous_rect.y,
|
||||
.width = tracker->previous_rect.width,
|
||||
.height = tracker->previous_rect.height
|
||||
};
|
||||
clutter_actor_queue_redraw_with_clip (stage, &clip);
|
||||
tracker->previous_is_valid = FALSE;
|
||||
}
|
||||
|
||||
if (tracker->has_hw_cursor || !tracker->displayed_cursor)
|
||||
return;
|
||||
|
||||
clip.x = tracker->current_rect.x;
|
||||
clip.y = tracker->current_rect.y;
|
||||
clip.width = tracker->current_rect.width;
|
||||
clip.height = tracker->current_rect.height;
|
||||
clutter_actor_queue_redraw_with_clip (stage, &clip);
|
||||
}
|
||||
|
||||
static void
|
||||
sync_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaCursorReference *displayed_cursor;
|
||||
|
||||
sync_displayed_cursor (tracker);
|
||||
displayed_cursor = tracker->displayed_cursor;
|
||||
|
||||
if (displayed_cursor)
|
||||
{
|
||||
tracker->current_rect.x = tracker->current_x - displayed_cursor->hot_x;
|
||||
tracker->current_rect.y = tracker->current_y - displayed_cursor->hot_y;
|
||||
tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (displayed_cursor->texture));
|
||||
tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (displayed_cursor->texture));
|
||||
}
|
||||
else
|
||||
{
|
||||
tracker->current_rect.x = 0;
|
||||
tracker->current_rect.y = 0;
|
||||
tracker->current_rect.width = 0;
|
||||
tracker->current_rect.height = 0;
|
||||
}
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
if (tracker->has_hw_cursor)
|
||||
move_hw_cursor (tracker);
|
||||
else
|
||||
meta_cursor_tracker_queue_redraw (tracker);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker,
|
||||
int *x,
|
||||
int *y,
|
||||
ClutterModifierType *mods)
|
||||
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||
int new_x,
|
||||
int new_y)
|
||||
{
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
tracker->current_x = new_x;
|
||||
tracker->current_y = new_y;
|
||||
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_paint (MetaCursorTracker *tracker)
|
||||
{
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
if (tracker->has_hw_cursor || !tracker->displayed_cursor)
|
||||
return;
|
||||
|
||||
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
|
||||
tracker->pipeline,
|
||||
tracker->current_rect.x,
|
||||
tracker->current_rect.y,
|
||||
tracker->current_rect.x +
|
||||
tracker->current_rect.width,
|
||||
tracker->current_rect.y +
|
||||
tracker->current_rect.height);
|
||||
|
||||
tracker->previous_rect = tracker->current_rect;
|
||||
tracker->previous_is_valid = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
|
||||
MetaCRTC *crtc,
|
||||
gboolean has)
|
||||
{
|
||||
if (has)
|
||||
{
|
||||
MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
|
||||
union gbm_bo_handle handle;
|
||||
int width, height;
|
||||
int hot_x, hot_y;
|
||||
|
||||
handle = gbm_bo_get_handle (displayed_cursor->bo);
|
||||
width = gbm_bo_get_width (displayed_cursor->bo);
|
||||
height = gbm_bo_get_height (displayed_cursor->bo);
|
||||
hot_x = displayed_cursor->hot_x;
|
||||
hot_y = displayed_cursor->hot_y;
|
||||
|
||||
drmModeSetCursor2 (tracker->drm_fd, crtc->crtc_id, handle.u32,
|
||||
width, height, hot_x, hot_y);
|
||||
crtc->has_hw_cursor = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
drmModeSetCursor2 (tracker->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0);
|
||||
crtc->has_hw_cursor = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
get_pointer_position_gdk (int *x,
|
||||
int *y,
|
||||
int *mods)
|
||||
{
|
||||
GdkDeviceManager *gmanager;
|
||||
GdkDevice *gdevice;
|
||||
@@ -390,9 +1082,48 @@ meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker,
|
||||
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
|
||||
|
||||
gdk_device_get_position (gdevice, &gscreen, x, y);
|
||||
gdk_device_get_state (gdevice,
|
||||
gdk_screen_get_root_window (gscreen),
|
||||
NULL, (GdkModifierType*)mods);
|
||||
if (mods)
|
||||
gdk_device_get_state (gdevice,
|
||||
gdk_screen_get_root_window (gscreen),
|
||||
NULL, (GdkModifierType*)mods);
|
||||
}
|
||||
|
||||
static void
|
||||
get_pointer_position_clutter (int *x,
|
||||
int *y,
|
||||
int *mods)
|
||||
{
|
||||
ClutterDeviceManager *cmanager;
|
||||
ClutterInputDevice *cdevice;
|
||||
ClutterPoint point;
|
||||
|
||||
cmanager = clutter_device_manager_get_default ();
|
||||
cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
clutter_input_device_get_coords (cdevice, NULL, &point);
|
||||
if (x)
|
||||
*x = point.x;
|
||||
if (y)
|
||||
*y = point.y;
|
||||
if (mods)
|
||||
*mods = clutter_input_device_get_modifier_state (cdevice);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker,
|
||||
int *x,
|
||||
int *y,
|
||||
ClutterModifierType *mods)
|
||||
{
|
||||
/* We can't use the clutter interface when not running as a wayland compositor,
|
||||
because we need to query the server, rather than using the last cached value.
|
||||
OTOH, on wayland we can't use GDK, because that only sees the events
|
||||
we forward to xwayland.
|
||||
*/
|
||||
if (meta_is_wayland_compositor ())
|
||||
get_pointer_position_clutter (x, y, (int*)mods);
|
||||
else
|
||||
get_pointer_position_gdk (x, y, (int*)mods);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -403,10 +1134,26 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
|
||||
return;
|
||||
tracker->is_showing = visible;
|
||||
|
||||
if (visible)
|
||||
XFixesShowCursor (tracker->screen->display->xdisplay,
|
||||
tracker->screen->xroot);
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
else
|
||||
XFixesHideCursor (tracker->screen->display->xdisplay,
|
||||
tracker->screen->xroot);
|
||||
{
|
||||
if (visible)
|
||||
XFixesShowCursor (tracker->screen->display->xdisplay,
|
||||
tracker->screen->xroot);
|
||||
else
|
||||
XFixesHideCursor (tracker->screen->display->xdisplay,
|
||||
tracker->screen->xroot);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_force_update (MetaCursorTracker *tracker)
|
||||
{
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
update_hw_cursor (tracker);
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
|
||||
@@ -24,5 +24,6 @@
|
||||
|
||||
void meta_idle_monitor_handle_xevent_all (XEvent *xevent);
|
||||
|
||||
void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor);
|
||||
|
||||
void meta_idle_monitor_init_dbus (void);
|
||||
|
||||
@@ -55,6 +55,9 @@ struct _MetaIdleMonitor
|
||||
int sync_event_base;
|
||||
XSyncCounter counter;
|
||||
XSyncAlarm user_active_alarm;
|
||||
|
||||
/* Wayland implementation */
|
||||
guint64 last_event_time;
|
||||
};
|
||||
|
||||
struct _MetaIdleMonitorClass
|
||||
@@ -74,6 +77,9 @@ typedef struct
|
||||
/* x11 */
|
||||
XSyncAlarm xalarm;
|
||||
int idle_source_id;
|
||||
|
||||
/* wayland */
|
||||
GSource *timeout_source;
|
||||
} MetaIdleMonitorWatch;
|
||||
|
||||
enum
|
||||
@@ -303,6 +309,9 @@ idle_monitor_watch_free (MetaIdleMonitorWatch *watch)
|
||||
g_hash_table_remove (monitor->alarms, (gpointer) watch->xalarm);
|
||||
}
|
||||
|
||||
if (watch->timeout_source != NULL)
|
||||
g_source_destroy (watch->timeout_source);
|
||||
|
||||
g_object_unref (monitor);
|
||||
g_slice_free (MetaIdleMonitorWatch, watch);
|
||||
}
|
||||
@@ -382,8 +391,11 @@ meta_idle_monitor_constructed (GObject *object)
|
||||
{
|
||||
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
|
||||
|
||||
monitor->display = meta_get_display ()->xdisplay;
|
||||
init_xsync (monitor);
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
monitor->display = meta_get_display ()->xdisplay;
|
||||
init_xsync (monitor);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -462,6 +474,25 @@ meta_idle_monitor_get_for_device (int device_id)
|
||||
return device_monitors[device_id];
|
||||
}
|
||||
|
||||
static gboolean
|
||||
wayland_dispatch_timeout (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaIdleMonitorWatch *watch = user_data;
|
||||
|
||||
fire_watch (watch);
|
||||
g_source_set_ready_time (watch->timeout_source, -1);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GSourceFuncs wayland_source_funcs = {
|
||||
NULL, /* prepare */
|
||||
NULL, /* check */
|
||||
wayland_dispatch_timeout,
|
||||
NULL, /* finalize */
|
||||
};
|
||||
|
||||
static gboolean
|
||||
fire_watch_idle (gpointer data)
|
||||
{
|
||||
@@ -490,20 +521,37 @@ make_watch (MetaIdleMonitor *monitor,
|
||||
watch->notify = notify;
|
||||
watch->timeout_msec = timeout_msec;
|
||||
|
||||
if (timeout_msec != 0)
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
watch->xalarm = _xsync_alarm_set (monitor, XSyncPositiveTransition, timeout_msec, TRUE);
|
||||
if (timeout_msec != 0)
|
||||
{
|
||||
GSource *source = g_source_new (&wayland_source_funcs, sizeof (GSource));
|
||||
|
||||
g_hash_table_add (monitor->alarms, (gpointer) watch->xalarm);
|
||||
g_source_set_callback (source, NULL, watch, NULL);
|
||||
g_source_set_ready_time (source, monitor->last_event_time + timeout_msec * 1000);
|
||||
g_source_attach (source, NULL);
|
||||
g_source_unref (source);
|
||||
|
||||
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
|
||||
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
|
||||
watch->timeout_source = source;
|
||||
}
|
||||
}
|
||||
else if (monitor->user_active_alarm != None)
|
||||
{
|
||||
watch->xalarm = monitor->user_active_alarm;
|
||||
if (timeout_msec != 0)
|
||||
{
|
||||
watch->xalarm = _xsync_alarm_set (monitor, XSyncPositiveTransition, timeout_msec, TRUE);
|
||||
|
||||
set_alarm_enabled (monitor->display, monitor->user_active_alarm, TRUE);
|
||||
g_hash_table_add (monitor->alarms, (gpointer) watch->xalarm);
|
||||
|
||||
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
|
||||
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
|
||||
}
|
||||
else
|
||||
{
|
||||
watch->xalarm = monitor->user_active_alarm;
|
||||
|
||||
set_alarm_enabled (monitor->display, monitor->user_active_alarm, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_insert (monitor->watches,
|
||||
@@ -622,10 +670,69 @@ meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
|
||||
{
|
||||
XSyncValue value;
|
||||
|
||||
if (!XSyncQueryCounter (monitor->display, monitor->counter, &value))
|
||||
return -1;
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
return (g_get_monotonic_time () - monitor->last_event_time) / 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!XSyncQueryCounter (monitor->display, monitor->counter, &value))
|
||||
return -1;
|
||||
|
||||
return _xsyncvalue_to_int64 (value);
|
||||
return _xsyncvalue_to_int64 (value);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
MetaIdleMonitor *monitor;
|
||||
GList *fired_watches;
|
||||
} CheckWaylandClosure;
|
||||
|
||||
static gboolean
|
||||
check_wayland_watch (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaIdleMonitorWatch *watch = value;
|
||||
CheckWaylandClosure *closure = user_data;
|
||||
gboolean steal;
|
||||
|
||||
if (watch->timeout_msec == 0)
|
||||
{
|
||||
closure->fired_watches = g_list_prepend (closure->fired_watches, watch);
|
||||
steal = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_source_set_ready_time (watch->timeout_source,
|
||||
closure->monitor->last_event_time +
|
||||
watch->timeout_msec * 1000);
|
||||
steal = FALSE;
|
||||
}
|
||||
|
||||
return steal;
|
||||
}
|
||||
|
||||
static void
|
||||
fire_wayland_watch (gpointer watch,
|
||||
gpointer data)
|
||||
{
|
||||
fire_watch (watch);
|
||||
}
|
||||
|
||||
void
|
||||
meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
|
||||
{
|
||||
CheckWaylandClosure closure;
|
||||
|
||||
monitor->last_event_time = g_get_monotonic_time ();
|
||||
|
||||
closure.monitor = monitor;
|
||||
closure.fired_watches = NULL;
|
||||
g_hash_table_foreach_steal (monitor->watches, check_wayland_watch, &closure);
|
||||
|
||||
g_list_foreach (closure.fired_watches, fire_wayland_watch, NULL);
|
||||
g_list_free (closure.fired_watches);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -778,9 +885,6 @@ create_monitor_skeleton (GDBusObjectManagerServer *manager,
|
||||
meta_dbus_object_skeleton_set_idle_monitor (object, skeleton);
|
||||
|
||||
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
|
||||
|
||||
g_object_unref (skeleton);
|
||||
g_object_unref (object);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -77,7 +77,6 @@ struct _MetaMonitorConfig {
|
||||
GHashTable *configs;
|
||||
MetaConfiguration *current;
|
||||
gboolean current_is_stored;
|
||||
gboolean current_is_for_laptop_lid;
|
||||
MetaConfiguration *previous;
|
||||
|
||||
GFile *file;
|
||||
@@ -840,9 +839,6 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self,
|
||||
MetaConfiguration key;
|
||||
MetaConfiguration *stored;
|
||||
|
||||
if (n_outputs == 0)
|
||||
return NULL;
|
||||
|
||||
make_config_key (&key, outputs, n_outputs, -1);
|
||||
stored = g_hash_table_lookup (self->configs, &key);
|
||||
|
||||
@@ -877,8 +873,7 @@ apply_configuration (MetaMonitorConfig *self,
|
||||
|
||||
/* Stored (persistent) configurations override the previous one always.
|
||||
Also, we clear the previous configuration if the current one (which is
|
||||
about to become previous) is stored, or if the current one has
|
||||
different outputs.
|
||||
about to become previous) is stored.
|
||||
*/
|
||||
if (stored ||
|
||||
(self->current && self->current_is_stored))
|
||||
@@ -889,27 +884,11 @@ apply_configuration (MetaMonitorConfig *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Despite the name, config_equal() only checks the set of outputs,
|
||||
not their modes
|
||||
*/
|
||||
if (self->current && config_equal (self->current, config))
|
||||
{
|
||||
self->previous = self->current;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self->current)
|
||||
config_free (self->current);
|
||||
self->previous = NULL;
|
||||
}
|
||||
self->previous = self->current;
|
||||
}
|
||||
|
||||
self->current = config;
|
||||
self->current_is_stored = stored;
|
||||
/* If true, we'll be overridden at the end of this call
|
||||
inside turn_off_laptop_display()
|
||||
*/
|
||||
self->current_is_for_laptop_lid = FALSE;
|
||||
|
||||
if (self->current == self->previous)
|
||||
self->previous = NULL;
|
||||
@@ -1026,16 +1005,8 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
|
||||
if (self->lid_is_closed &&
|
||||
stored->n_outputs > 1 &&
|
||||
laptop_display_is_on (stored))
|
||||
{
|
||||
if (apply_configuration (self, make_laptop_lid_config (stored),
|
||||
manager, FALSE))
|
||||
{
|
||||
self->current_is_for_laptop_lid = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
return apply_configuration (self, make_laptop_lid_config (stored),
|
||||
manager, FALSE);
|
||||
else
|
||||
return apply_configuration (self, stored, manager, TRUE);
|
||||
}
|
||||
@@ -1275,12 +1246,6 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
|
||||
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
|
||||
meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height);
|
||||
|
||||
if (n_outputs == 0)
|
||||
{
|
||||
meta_verbose ("No output connected, not applying configuration\n");
|
||||
return;
|
||||
}
|
||||
|
||||
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
|
||||
|
||||
if (default_config != NULL)
|
||||
@@ -1382,7 +1347,6 @@ turn_off_laptop_display (MetaMonitorConfig *self,
|
||||
|
||||
new = make_laptop_lid_config (self->current);
|
||||
apply_configuration (self, new, manager, FALSE);
|
||||
self->current_is_for_laptop_lid = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1402,7 +1366,7 @@ power_client_changed_cb (UpClient *client,
|
||||
|
||||
if (is_closed)
|
||||
turn_off_laptop_display (self, manager);
|
||||
else if (self->current_is_for_laptop_lid)
|
||||
else
|
||||
meta_monitor_config_restore_previous (self, manager);
|
||||
}
|
||||
}
|
||||
|
||||
938
src/core/monitor-kms.c
Normal file
938
src/core/monitor-kms.c
Normal file
@@ -0,0 +1,938 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* 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.
|
||||
*
|
||||
* Author: Giovanni Campagna <gcampagn@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#include <meta/main.h>
|
||||
#include <meta/errors.h>
|
||||
#include "monitor-private.h"
|
||||
#include "edid.h"
|
||||
|
||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
|
||||
typedef struct {
|
||||
drmModeConnector *connector;
|
||||
|
||||
unsigned n_encoders;
|
||||
drmModeEncoderPtr *encoders;
|
||||
drmModeEncoderPtr current_encoder;
|
||||
|
||||
/* bitmasks of encoder position in the resources array */
|
||||
uint32_t encoder_mask;
|
||||
uint32_t enc_clone_mask;
|
||||
|
||||
uint32_t dpms_prop_id;
|
||||
uint32_t edid_blob_id;
|
||||
} MetaOutputKms;
|
||||
|
||||
struct _MetaMonitorManagerKms
|
||||
{
|
||||
MetaMonitorManager parent_instance;
|
||||
|
||||
int fd;
|
||||
|
||||
drmModeConnector **connectors;
|
||||
unsigned int n_connectors;
|
||||
|
||||
drmModeEncoder **encoders;
|
||||
unsigned int n_encoders;
|
||||
|
||||
drmModeEncoder *current_encoder;
|
||||
};
|
||||
|
||||
struct _MetaMonitorManagerKmsClass
|
||||
{
|
||||
MetaMonitorManagerClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaMonitorManagerKms, meta_monitor_manager_kms, META_TYPE_MONITOR_MANAGER);
|
||||
|
||||
static void
|
||||
free_resources (MetaMonitorManagerKms *manager_kms)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < manager_kms->n_encoders; i++)
|
||||
drmModeFreeEncoder (manager_kms->encoders[i]);
|
||||
for (i = 0; i < manager_kms->n_connectors; i++)
|
||||
drmModeFreeConnector (manager_kms->connectors[i]);
|
||||
|
||||
g_free (manager_kms->encoders);
|
||||
g_free (manager_kms->connectors);
|
||||
}
|
||||
|
||||
static int
|
||||
compare_outputs (const void *one,
|
||||
const void *two)
|
||||
{
|
||||
const MetaOutput *o_one = one, *o_two = two;
|
||||
|
||||
return strcmp (o_one->name, o_two->name);
|
||||
}
|
||||
|
||||
static char *
|
||||
make_output_name (drmModeConnector *connector)
|
||||
{
|
||||
static const char * const connector_type_names[] = {
|
||||
"unknown", "VGA", "DVII", "DVID", "DVID", "Composite",
|
||||
"SVIDEO", "LVDS", "Component", "9PinDIN", "DisplayPort",
|
||||
"HDMIA", "HDMIB", "TV", "eDP"
|
||||
};
|
||||
const char *connector_type_name;
|
||||
|
||||
if (connector->connector_type < G_N_ELEMENTS (connector_type_names))
|
||||
connector_type_name = connector_type_names[connector->connector_type];
|
||||
else
|
||||
connector_type_name = "unknown";
|
||||
|
||||
return g_strdup_printf ("%s%d", connector_type_name, connector->connector_id);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_output_destroy_notify (MetaOutput *output)
|
||||
{
|
||||
MetaOutputKms *output_kms;
|
||||
unsigned i;
|
||||
|
||||
output_kms = output->driver_private;
|
||||
|
||||
for (i = 0; i < output_kms->n_encoders; i++)
|
||||
drmModeFreeEncoder (output_kms->encoders[i]);
|
||||
g_free (output_kms->encoders);
|
||||
|
||||
g_slice_free (MetaOutputKms, output_kms);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_mode_destroy_notify (MetaMonitorMode *output)
|
||||
{
|
||||
g_slice_free (drmModeModeInfo, output->driver_private);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
drm_mode_equal (gconstpointer one,
|
||||
gconstpointer two)
|
||||
{
|
||||
const drmModeModeInfo *m_one = one;
|
||||
const drmModeModeInfo *m_two = two;
|
||||
|
||||
return m_one->clock == m_two->clock &&
|
||||
m_one->hdisplay == m_two->hdisplay &&
|
||||
m_one->hsync_start == m_two->hsync_start &&
|
||||
m_one->hsync_end == m_two->hsync_end &&
|
||||
m_one->htotal == m_two->htotal &&
|
||||
m_one->hskew == m_two->hskew &&
|
||||
m_one->vdisplay == m_two->vdisplay &&
|
||||
m_one->vsync_start == m_two->vsync_start &&
|
||||
m_one->vsync_end == m_two->vsync_end &&
|
||||
m_one->vtotal == m_two->vtotal &&
|
||||
m_one->vscan == m_two->vscan &&
|
||||
m_one->vrefresh == m_two->vrefresh &&
|
||||
m_one->flags == m_two->flags &&
|
||||
m_one->type == m_two->type &&
|
||||
strncmp (m_one->name, m_two->name, DRM_DISPLAY_MODE_LEN) == 0;
|
||||
}
|
||||
|
||||
static guint
|
||||
drm_mode_hash (gconstpointer ptr)
|
||||
{
|
||||
const drmModeModeInfo *mode = ptr;
|
||||
guint hash = 0;
|
||||
|
||||
/* We don't include the name in the hash because it's generally
|
||||
derived from the other fields (hdisplay, vdisplay and flags)
|
||||
*/
|
||||
|
||||
hash ^= mode->clock;
|
||||
hash ^= mode->hdisplay ^ mode->hsync_start ^ mode->hsync_end;
|
||||
hash ^= mode->vdisplay ^ mode->vsync_start ^ mode->vsync_end;
|
||||
hash ^= mode->vrefresh;
|
||||
hash ^= mode->flags ^ mode->type;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
static void
|
||||
find_properties (MetaMonitorManagerKms *manager_kms,
|
||||
MetaOutputKms *output_kms)
|
||||
{
|
||||
drmModePropertyPtr prop;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < output_kms->connector->count_props; i++)
|
||||
{
|
||||
prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
|
||||
if (!prop)
|
||||
continue;
|
||||
|
||||
if ((prop->flags & DRM_MODE_PROP_ENUM) &&
|
||||
strcmp(prop->name, "DPMS") == 0)
|
||||
output_kms->dpms_prop_id = prop->prop_id;
|
||||
else if ((prop->flags & DRM_MODE_PROP_BLOB) &&
|
||||
strcmp (prop->name, "EDID") == 0)
|
||||
output_kms->edid_blob_id = output_kms->connector->prop_values[i];
|
||||
|
||||
drmModeFreeProperty(prop);
|
||||
}
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
read_output_edid (MetaMonitorManagerKms *manager_kms,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaOutputKms *output_kms = output->driver_private;
|
||||
drmModePropertyBlobPtr edid_blob = NULL;
|
||||
|
||||
if (output_kms->edid_blob_id == 0)
|
||||
return NULL;
|
||||
|
||||
edid_blob = drmModeGetPropertyBlob (manager_kms->fd, output_kms->edid_blob_id);
|
||||
if (!edid_blob)
|
||||
{
|
||||
meta_warning ("Failed to read EDID of output %s: %s\n", output->name, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (edid_blob->length > 0)
|
||||
return g_bytes_new_with_free_func (edid_blob->data, edid_blob->length,
|
||||
(GDestroyNotify)drmModeFreePropertyBlob, edid_blob);
|
||||
else
|
||||
{
|
||||
drmModeFreePropertyBlob (edid_blob);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static MetaMonitorMode *
|
||||
find_meta_mode (MetaMonitorManager *manager,
|
||||
const drmModeModeInfo *drm_mode)
|
||||
{
|
||||
unsigned k;
|
||||
|
||||
for (k = 0; k < manager->n_modes; k++)
|
||||
{
|
||||
if (drm_mode_equal (drm_mode, manager->modes[k].driver_private))
|
||||
return &manager->modes[k];
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static MetaOutput *
|
||||
find_output_by_id (MetaOutput *outputs,
|
||||
unsigned n_outputs,
|
||||
glong id)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
if (outputs[i].output_id == id)
|
||||
return &outputs[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
{
|
||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
||||
drmModeRes *resources;
|
||||
GHashTable *modes;
|
||||
GHashTableIter iter;
|
||||
drmModeModeInfo *mode;
|
||||
unsigned int i, j, k;
|
||||
unsigned int n_actual_outputs;
|
||||
int width, height;
|
||||
MetaOutput *old_outputs;
|
||||
unsigned int n_old_outputs;
|
||||
|
||||
resources = drmModeGetResources(manager_kms->fd);
|
||||
modes = g_hash_table_new (drm_mode_hash, drm_mode_equal);
|
||||
|
||||
manager->max_screen_width = resources->max_width;
|
||||
manager->max_screen_height = resources->max_height;
|
||||
|
||||
manager->power_save_mode = META_POWER_SAVE_ON;
|
||||
|
||||
old_outputs = manager->outputs;
|
||||
n_old_outputs = manager->n_outputs;
|
||||
|
||||
/* Note: we must not free the public structures (output, crtc, monitor
|
||||
mode and monitor info) here, they must be kept alive until the API
|
||||
users are done with them after we emit monitors-changed, and thus
|
||||
are freed by the platform-independent layer. */
|
||||
free_resources (manager_kms);
|
||||
|
||||
manager_kms->n_connectors = resources->count_connectors;
|
||||
manager_kms->connectors = g_new (drmModeConnector *, manager_kms->n_connectors);
|
||||
for (i = 0; i < manager_kms->n_connectors; i++)
|
||||
{
|
||||
drmModeConnector *connector;
|
||||
|
||||
connector = drmModeGetConnector (manager_kms->fd, resources->connectors[i]);
|
||||
manager_kms->connectors[i] = connector;
|
||||
|
||||
if (connector->connection == DRM_MODE_CONNECTED)
|
||||
{
|
||||
/* Collect all modes for this connector */
|
||||
for (j = 0; j < (unsigned)connector->count_modes; j++)
|
||||
g_hash_table_add (modes, &connector->modes[j]);
|
||||
}
|
||||
}
|
||||
|
||||
manager_kms->n_encoders = resources->count_encoders;
|
||||
manager_kms->encoders = g_new (drmModeEncoder *, manager_kms->n_encoders);
|
||||
for (i = 0; i < manager_kms->n_encoders; i++)
|
||||
{
|
||||
manager_kms->encoders[i] = drmModeGetEncoder (manager_kms->fd,
|
||||
resources->encoders[i]);
|
||||
}
|
||||
|
||||
manager->n_modes = g_hash_table_size (modes);
|
||||
manager->modes = g_new0 (MetaMonitorMode, manager->n_modes);
|
||||
g_hash_table_iter_init (&iter, modes);
|
||||
i = 0;
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer)&mode))
|
||||
{
|
||||
MetaMonitorMode *meta_mode;
|
||||
|
||||
meta_mode = &manager->modes[i];
|
||||
|
||||
meta_mode->mode_id = i;
|
||||
meta_mode->name = g_strndup (mode->name, DRM_DISPLAY_MODE_LEN);
|
||||
meta_mode->width = mode->hdisplay;
|
||||
meta_mode->height = mode->vdisplay;
|
||||
meta_mode->refresh_rate = (1000 * mode->clock /
|
||||
((float)mode->htotal * mode->vtotal));
|
||||
|
||||
meta_mode->driver_private = g_slice_dup (drmModeModeInfo, mode);
|
||||
meta_mode->driver_notify = (GDestroyNotify)meta_monitor_mode_destroy_notify;
|
||||
|
||||
i++;
|
||||
}
|
||||
g_hash_table_destroy (modes);
|
||||
|
||||
manager->n_crtcs = resources->count_crtcs;
|
||||
manager->crtcs = g_new0 (MetaCRTC, manager->n_crtcs);
|
||||
width = 0; height = 0;
|
||||
for (i = 0; i < (unsigned)resources->count_crtcs; i++)
|
||||
{
|
||||
drmModeCrtc *crtc;
|
||||
MetaCRTC *meta_crtc;
|
||||
|
||||
crtc = drmModeGetCrtc (manager_kms->fd, resources->crtcs[i]);
|
||||
|
||||
meta_crtc = &manager->crtcs[i];
|
||||
|
||||
meta_crtc->crtc_id = crtc->crtc_id;
|
||||
meta_crtc->rect.x = crtc->x;
|
||||
meta_crtc->rect.y = crtc->y;
|
||||
meta_crtc->rect.width = crtc->width;
|
||||
meta_crtc->rect.height = crtc->height;
|
||||
meta_crtc->is_dirty = FALSE;
|
||||
meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
/* FIXME: implement! */
|
||||
meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
|
||||
if (crtc->mode_valid)
|
||||
{
|
||||
for (j = 0; j < manager->n_modes; j++)
|
||||
{
|
||||
if (drm_mode_equal (&crtc->mode, manager->modes[j].driver_private))
|
||||
{
|
||||
meta_crtc->current_mode = &manager->modes[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
width = MAX (width, meta_crtc->rect.x + meta_crtc->rect.width);
|
||||
height = MAX (height, meta_crtc->rect.y + meta_crtc->rect.height);
|
||||
}
|
||||
|
||||
drmModeFreeCrtc (crtc);
|
||||
}
|
||||
|
||||
manager->screen_width = width;
|
||||
manager->screen_height = height;
|
||||
|
||||
manager->outputs = g_new0 (MetaOutput, manager_kms->n_connectors);
|
||||
n_actual_outputs = 0;
|
||||
|
||||
for (i = 0; i < manager_kms->n_connectors; i++)
|
||||
{
|
||||
MetaOutput *meta_output, *old_output;
|
||||
MetaOutputKms *output_kms;
|
||||
drmModeConnector *connector;
|
||||
GArray *crtcs;
|
||||
unsigned int crtc_mask;
|
||||
GBytes *edid;
|
||||
|
||||
connector = manager_kms->connectors[i];
|
||||
meta_output = &manager->outputs[n_actual_outputs];
|
||||
|
||||
if (connector->connection == DRM_MODE_CONNECTED)
|
||||
{
|
||||
meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
|
||||
meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
|
||||
|
||||
meta_output->output_id = connector->connector_id;
|
||||
meta_output->name = make_output_name (connector);
|
||||
meta_output->width_mm = connector->mmWidth;
|
||||
meta_output->height_mm = connector->mmHeight;
|
||||
|
||||
switch (connector->subpixel)
|
||||
{
|
||||
case DRM_MODE_SUBPIXEL_NONE:
|
||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_NONE;
|
||||
break;
|
||||
case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
|
||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB;
|
||||
break;
|
||||
case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
|
||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR;
|
||||
break;
|
||||
case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
|
||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_RGB;
|
||||
break;
|
||||
case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
|
||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_BGR;
|
||||
break;
|
||||
case DRM_MODE_SUBPIXEL_UNKNOWN:
|
||||
default:
|
||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
meta_output->n_modes = connector->count_modes;
|
||||
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
|
||||
for (j = 0; j < meta_output->n_modes; j++)
|
||||
meta_output->modes[j] = find_meta_mode (manager, &connector->modes[j]);
|
||||
meta_output->preferred_mode = meta_output->modes[0];
|
||||
|
||||
output_kms->connector = connector;
|
||||
output_kms->n_encoders = connector->count_encoders;
|
||||
output_kms->encoders = g_new0 (drmModeEncoderPtr, output_kms->n_encoders);
|
||||
|
||||
crtc_mask = ~(unsigned int)0;
|
||||
for (j = 0; j < output_kms->n_encoders; j++)
|
||||
{
|
||||
output_kms->encoders[j] = drmModeGetEncoder (manager_kms->fd, connector->encoders[j]);
|
||||
|
||||
/* We only list CRTCs as supported if they are supported by all encoders
|
||||
for this connectors.
|
||||
|
||||
This is what xf86-video-modesetting does (see drmmode_output_init())
|
||||
*/
|
||||
crtc_mask &= output_kms->encoders[j]->possible_crtcs;
|
||||
|
||||
if (output_kms->encoders[j]->encoder_id == connector->encoder_id)
|
||||
output_kms->current_encoder = output_kms->encoders[j];
|
||||
}
|
||||
|
||||
crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCRTC*));
|
||||
|
||||
for (j = 0; j < manager->n_crtcs; j++)
|
||||
{
|
||||
if (crtc_mask & (1 << j))
|
||||
{
|
||||
MetaCRTC *crtc = &manager->crtcs[j];
|
||||
g_array_append_val (crtcs, crtc);
|
||||
}
|
||||
}
|
||||
|
||||
meta_output->n_possible_crtcs = crtcs->len;
|
||||
meta_output->possible_crtcs = (void*)g_array_free (crtcs, FALSE);
|
||||
|
||||
if (output_kms->current_encoder && output_kms->current_encoder->crtc_id != 0)
|
||||
{
|
||||
for (j = 0; j < manager->n_crtcs; j++)
|
||||
{
|
||||
if (manager->crtcs[j].crtc_id == output_kms->current_encoder->crtc_id)
|
||||
{
|
||||
meta_output->crtc = &manager->crtcs[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
meta_output->crtc = NULL;
|
||||
|
||||
old_output = find_output_by_id (old_outputs, n_old_outputs,
|
||||
meta_output->output_id);
|
||||
if (old_output)
|
||||
{
|
||||
meta_output->is_primary = old_output->is_primary;
|
||||
meta_output->is_presentation = old_output->is_presentation;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_output->is_primary = FALSE;
|
||||
meta_output->is_presentation = FALSE;
|
||||
}
|
||||
|
||||
find_properties (manager_kms, output_kms);
|
||||
|
||||
edid = read_output_edid (manager_kms, meta_output);
|
||||
if (edid)
|
||||
{
|
||||
MonitorInfo *parsed_edid;
|
||||
gsize len;
|
||||
|
||||
parsed_edid = decode_edid (g_bytes_get_data (edid, &len));
|
||||
if (parsed_edid)
|
||||
{
|
||||
meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
|
||||
meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
|
||||
meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
|
||||
|
||||
g_free (parsed_edid);
|
||||
}
|
||||
|
||||
g_bytes_unref (edid);
|
||||
}
|
||||
if (!meta_output->vendor)
|
||||
{
|
||||
meta_output->vendor = g_strdup ("unknown");
|
||||
meta_output->product = g_strdup ("unknown");
|
||||
meta_output->serial = g_strdup ("unknown");
|
||||
}
|
||||
|
||||
/* FIXME: backlight is a very driver specific thing unfortunately,
|
||||
every DDX does its own thing, and the dumb KMS API does not include it.
|
||||
|
||||
For example, xf86-video-intel has a list of paths to probe in /sys/class/backlight
|
||||
(one for each major HW maker, and then some).
|
||||
We can't do the same because we're not root.
|
||||
It might be best to leave backlight out of the story and rely on the setuid
|
||||
helper in gnome-settings-daemon.
|
||||
*/
|
||||
meta_output->backlight_min = 0;
|
||||
meta_output->backlight_max = 0;
|
||||
meta_output->backlight = -1;
|
||||
|
||||
n_actual_outputs++;
|
||||
}
|
||||
}
|
||||
|
||||
manager->n_outputs = n_actual_outputs;
|
||||
manager->outputs = g_renew (MetaOutput, manager->outputs, manager->n_outputs);
|
||||
|
||||
/* Sort the outputs for easier handling in MetaMonitorConfig */
|
||||
qsort (manager->outputs, manager->n_outputs, sizeof (MetaOutput), compare_outputs);
|
||||
|
||||
/* Now fix the clones.
|
||||
Code mostly inspired by xf86-video-modesetting. */
|
||||
|
||||
/* XXX: intel hardware doesn't usually have clones, but I only have laptops with
|
||||
intel cards, so this code was never tested! */
|
||||
for (i = 0; i < manager->n_outputs; i++)
|
||||
{
|
||||
MetaOutput *meta_output;
|
||||
MetaOutputKms *output_kms;
|
||||
|
||||
meta_output = &manager->outputs[i];
|
||||
output_kms = meta_output->driver_private;
|
||||
|
||||
output_kms->enc_clone_mask = 0xff;
|
||||
output_kms->encoder_mask = 0;
|
||||
|
||||
for (j = 0; j < output_kms->n_encoders; j++)
|
||||
{
|
||||
for (k = 0; k < manager_kms->n_encoders; k++)
|
||||
{
|
||||
if (output_kms->encoders[j]->encoder_id == manager_kms->encoders[k]->encoder_id)
|
||||
{
|
||||
output_kms->encoder_mask |= (1 << k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
output_kms->enc_clone_mask &= output_kms->encoders[j]->possible_clones;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < manager->n_outputs; i++)
|
||||
{
|
||||
MetaOutput *meta_output;
|
||||
MetaOutputKms *output_kms;
|
||||
|
||||
meta_output = &manager->outputs[i];
|
||||
output_kms = meta_output->driver_private;
|
||||
|
||||
if (output_kms->enc_clone_mask == 0)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < manager->n_outputs; j++)
|
||||
{
|
||||
MetaOutput *meta_clone;
|
||||
MetaOutputKms *clone_kms;
|
||||
|
||||
meta_clone = &manager->outputs[i];
|
||||
clone_kms = meta_clone->driver_private;
|
||||
|
||||
if (meta_clone == meta_output)
|
||||
continue;
|
||||
|
||||
if (clone_kms->encoder_mask == 0)
|
||||
continue;
|
||||
|
||||
if (clone_kms->encoder_mask == output_kms->enc_clone_mask)
|
||||
{
|
||||
meta_output->n_possible_clones++;
|
||||
meta_output->possible_clones = g_renew (MetaOutput *,
|
||||
meta_output->possible_clones,
|
||||
meta_output->n_possible_clones);
|
||||
meta_output->possible_clones[meta_output->n_possible_clones - 1] = meta_clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drmModeFreeResources (resources);
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
meta_monitor_manager_kms_read_edid (MetaMonitorManager *manager,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
||||
|
||||
return read_output_edid (manager_kms, output);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
||||
MetaPowerSave mode)
|
||||
{
|
||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
||||
uint64_t state;
|
||||
unsigned i;
|
||||
|
||||
switch (mode) {
|
||||
case META_POWER_SAVE_ON:
|
||||
state = DRM_MODE_DPMS_ON;
|
||||
break;
|
||||
case META_POWER_SAVE_STANDBY:
|
||||
state = DRM_MODE_DPMS_STANDBY;
|
||||
break;
|
||||
case META_POWER_SAVE_SUSPEND:
|
||||
state = DRM_MODE_DPMS_SUSPEND;
|
||||
break;
|
||||
case META_POWER_SAVE_OFF:
|
||||
state = DRM_MODE_DPMS_OFF;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < manager->n_outputs; i++)
|
||||
{
|
||||
MetaOutput *meta_output;
|
||||
MetaOutputKms *output_kms;
|
||||
|
||||
meta_output = &manager->outputs[i];
|
||||
output_kms = meta_output->driver_private;
|
||||
|
||||
if (output_kms->dpms_prop_id != 0)
|
||||
{
|
||||
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->output_id,
|
||||
output_kms->dpms_prop_id, state);
|
||||
|
||||
if (ok < 0)
|
||||
meta_warning ("Failed to set power save mode for output %s: %s\n",
|
||||
meta_output->name, strerror (errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
crtc_free (CoglKmsCrtc *crtc)
|
||||
{
|
||||
g_free (crtc->connectors);
|
||||
g_slice_free (CoglKmsCrtc, crtc);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
||||
MetaCRTCInfo **crtcs,
|
||||
unsigned int n_crtcs,
|
||||
MetaOutputInfo **outputs,
|
||||
unsigned int n_outputs)
|
||||
{
|
||||
ClutterBackend *backend;
|
||||
CoglContext *cogl_context;
|
||||
CoglDisplay *cogl_display;
|
||||
unsigned i;
|
||||
GPtrArray *cogl_crtcs;
|
||||
int screen_width, screen_height;
|
||||
gboolean ok;
|
||||
GError *error;
|
||||
|
||||
cogl_crtcs = g_ptr_array_new_full (manager->n_crtcs, (GDestroyNotify)crtc_free);
|
||||
screen_width = 0; screen_height = 0;
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
MetaCRTCInfo *crtc_info = crtcs[i];
|
||||
MetaCRTC *crtc = crtc_info->crtc;
|
||||
CoglKmsCrtc *cogl_crtc;
|
||||
|
||||
crtc->is_dirty = TRUE;
|
||||
|
||||
cogl_crtc = g_slice_new0 (CoglKmsCrtc);
|
||||
g_ptr_array_add (cogl_crtcs, cogl_crtc);
|
||||
|
||||
if (crtc_info->mode == NULL)
|
||||
{
|
||||
cogl_crtc->id = crtc->crtc_id;
|
||||
cogl_crtc->x = 0;
|
||||
cogl_crtc->y = 0;
|
||||
cogl_crtc->count = 0;
|
||||
memset (&cogl_crtc->mode, 0, sizeof (drmModeModeInfo));
|
||||
cogl_crtc->connectors = NULL;
|
||||
cogl_crtc->count = 0;
|
||||
|
||||
crtc->rect.x = 0;
|
||||
crtc->rect.y = 0;
|
||||
crtc->rect.width = 0;
|
||||
crtc->rect.height = 0;
|
||||
crtc->current_mode = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaMonitorMode *mode;
|
||||
uint32_t *connectors;
|
||||
unsigned int j, n_connectors;
|
||||
int width, height;
|
||||
|
||||
mode = crtc_info->mode;
|
||||
|
||||
cogl_crtc->id = crtc->crtc_id;
|
||||
cogl_crtc->x = crtc_info->x;
|
||||
cogl_crtc->y = crtc_info->y;
|
||||
cogl_crtc->count = n_connectors = crtc_info->outputs->len;
|
||||
cogl_crtc->connectors = connectors = g_new (uint32_t, n_connectors);
|
||||
|
||||
for (j = 0; j < n_connectors; j++)
|
||||
{
|
||||
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
|
||||
|
||||
connectors[j] = output->output_id;
|
||||
|
||||
output->is_dirty = TRUE;
|
||||
output->crtc = crtc;
|
||||
}
|
||||
|
||||
memcpy (&cogl_crtc->mode, crtc_info->mode->driver_private,
|
||||
sizeof (drmModeModeInfo));
|
||||
|
||||
if (meta_monitor_transform_is_rotated (crtc_info->transform))
|
||||
{
|
||||
width = mode->height;
|
||||
height = mode->width;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = mode->width;
|
||||
height = mode->height;
|
||||
}
|
||||
|
||||
screen_width = MAX (screen_width, crtc_info->x + width);
|
||||
screen_height = MAX (screen_height, crtc_info->y + height);
|
||||
|
||||
crtc->rect.x = crtc_info->x;
|
||||
crtc->rect.y = crtc_info->y;
|
||||
crtc->rect.width = width;
|
||||
crtc->rect.height = height;
|
||||
crtc->current_mode = mode;
|
||||
crtc->transform = crtc_info->transform;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable CRTCs not mentioned in the list (they have is_dirty == FALSE,
|
||||
because they weren't seen in the first loop) */
|
||||
for (i = 0; i < manager->n_crtcs; i++)
|
||||
{
|
||||
MetaCRTC *crtc = &manager->crtcs[i];
|
||||
CoglKmsCrtc *cogl_crtc;
|
||||
|
||||
crtc->logical_monitor = NULL;
|
||||
|
||||
if (crtc->is_dirty)
|
||||
{
|
||||
crtc->is_dirty = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
cogl_crtc = g_slice_new0 (CoglKmsCrtc);
|
||||
g_ptr_array_add (cogl_crtcs, cogl_crtc);
|
||||
|
||||
cogl_crtc->id = crtc->crtc_id;
|
||||
cogl_crtc->x = 0;
|
||||
cogl_crtc->y = 0;
|
||||
cogl_crtc->count = 0;
|
||||
memset (&cogl_crtc->mode, 0, sizeof (drmModeModeInfo));
|
||||
cogl_crtc->connectors = NULL;
|
||||
cogl_crtc->count = 0;
|
||||
|
||||
crtc->rect.x = 0;
|
||||
crtc->rect.y = 0;
|
||||
crtc->rect.width = 0;
|
||||
crtc->rect.height = 0;
|
||||
crtc->current_mode = NULL;
|
||||
}
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
||||
cogl_display = cogl_context_get_display (cogl_context);
|
||||
|
||||
error = NULL;
|
||||
ok = cogl_kms_display_set_layout (cogl_display, screen_width, screen_height,
|
||||
(CoglKmsCrtc**)cogl_crtcs->pdata, cogl_crtcs->len, &error);
|
||||
g_ptr_array_unref (cogl_crtcs);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
meta_warning ("Applying display configuration failed: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
MetaOutputInfo *output_info = outputs[i];
|
||||
MetaOutput *output = output_info->output;
|
||||
|
||||
output->is_primary = output_info->is_primary;
|
||||
output->is_presentation = output_info->is_presentation;
|
||||
}
|
||||
|
||||
/* Disable outputs not mentioned in the list */
|
||||
for (i = 0; i < manager->n_outputs; i++)
|
||||
{
|
||||
MetaOutput *output = &manager->outputs[i];
|
||||
|
||||
if (output->is_dirty)
|
||||
{
|
||||
output->is_dirty = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
output->crtc = NULL;
|
||||
output->is_primary = FALSE;
|
||||
}
|
||||
|
||||
manager->screen_width = screen_width;
|
||||
manager->screen_height = screen_height;
|
||||
|
||||
meta_monitor_manager_rebuild_derived (manager);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_kms_get_crtc_gamma (MetaMonitorManager *manager,
|
||||
MetaCRTC *crtc,
|
||||
gsize *size,
|
||||
unsigned short **red,
|
||||
unsigned short **green,
|
||||
unsigned short **blue)
|
||||
{
|
||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
||||
drmModeCrtc *kms_crtc;
|
||||
|
||||
kms_crtc = drmModeGetCrtc (manager_kms->fd, crtc->crtc_id);
|
||||
|
||||
*size = kms_crtc->gamma_size;
|
||||
*red = g_new (unsigned short, *size);
|
||||
*green = g_new (unsigned short, *size);
|
||||
*blue = g_new (unsigned short, *size);
|
||||
|
||||
drmModeCrtcGetGamma (manager_kms->fd, crtc->crtc_id, *size, *red, *green, *blue);
|
||||
|
||||
drmModeFreeCrtc (kms_crtc);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
|
||||
MetaCRTC *crtc,
|
||||
gsize size,
|
||||
unsigned short *red,
|
||||
unsigned short *green,
|
||||
unsigned short *blue)
|
||||
{
|
||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
||||
|
||||
drmModeCrtcSetGamma (manager_kms->fd, crtc->crtc_id, size, red, green, blue);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
|
||||
{
|
||||
ClutterBackend *backend;
|
||||
CoglContext *cogl_context;
|
||||
CoglDisplay *cogl_display;
|
||||
CoglRenderer *cogl_renderer;
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
||||
cogl_display = cogl_context_get_display (cogl_context);
|
||||
cogl_renderer = cogl_display_get_renderer (cogl_display);
|
||||
|
||||
manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_kms_finalize (GObject *object)
|
||||
{
|
||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object);
|
||||
|
||||
free_resources (manager_kms);
|
||||
|
||||
G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
|
||||
{
|
||||
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_monitor_manager_kms_finalize;
|
||||
|
||||
manager_class->read_current = meta_monitor_manager_kms_read_current;
|
||||
manager_class->read_edid = meta_monitor_manager_kms_read_edid;
|
||||
manager_class->apply_configuration = meta_monitor_manager_kms_apply_configuration;
|
||||
manager_class->set_power_save_mode = meta_monitor_manager_kms_set_power_save_mode;
|
||||
manager_class->get_crtc_gamma = meta_monitor_manager_kms_get_crtc_gamma;
|
||||
manager_class->set_crtc_gamma = meta_monitor_manager_kms_set_crtc_gamma;
|
||||
}
|
||||
|
||||
@@ -42,9 +42,7 @@
|
||||
#include <meta/screen.h>
|
||||
#include "stack-tracker.h"
|
||||
#include "ui.h"
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include <wayland-server.h>
|
||||
#endif
|
||||
#include "meta-xrandr-shared.h"
|
||||
|
||||
#include "meta-dbus-xrandr.h"
|
||||
@@ -54,19 +52,6 @@ typedef struct _MetaMonitorManager MetaMonitorManager;
|
||||
typedef struct _MetaMonitorConfigClass MetaMonitorConfigClass;
|
||||
typedef struct _MetaMonitorConfig MetaMonitorConfig;
|
||||
|
||||
#ifndef HAVE_WAYLAND
|
||||
enum wl_output_transform {
|
||||
WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
WL_OUTPUT_TRANSFORM_90,
|
||||
WL_OUTPUT_TRANSFORM_180,
|
||||
WL_OUTPUT_TRANSFORM_270,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_90,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_180,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_270
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct _MetaOutput MetaOutput;
|
||||
typedef struct _MetaCRTC MetaCRTC;
|
||||
typedef struct _MetaMonitorMode MetaMonitorMode;
|
||||
@@ -115,6 +100,9 @@ struct _MetaOutput
|
||||
gboolean is_primary;
|
||||
gboolean is_presentation;
|
||||
|
||||
gpointer driver_private;
|
||||
GDestroyNotify driver_notify;
|
||||
|
||||
/* get a new preferred mode on hotplug events, to handle dynamic guest resizing */
|
||||
gboolean hotplug_mode_update;
|
||||
};
|
||||
@@ -134,16 +122,23 @@ struct _MetaCRTC
|
||||
|
||||
/* Used when changing configuration */
|
||||
gboolean is_dirty;
|
||||
|
||||
/* Updated by MetaCursorTracker */
|
||||
gboolean has_hw_cursor;
|
||||
};
|
||||
|
||||
struct _MetaMonitorMode
|
||||
{
|
||||
/* The low-level ID of this mode, used to apply back configuration */
|
||||
glong mode_id;
|
||||
char *name;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
float refresh_rate;
|
||||
|
||||
gpointer driver_private;
|
||||
GDestroyNotify driver_notify;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -352,6 +347,18 @@ typedef struct _MetaMonitorManagerXrandr MetaMonitorManagerXrandr;
|
||||
|
||||
GType meta_monitor_manager_xrandr_get_type (void);
|
||||
|
||||
#define META_TYPE_MONITOR_MANAGER_KMS (meta_monitor_manager_kms_get_type ())
|
||||
#define META_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKms))
|
||||
#define META_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
|
||||
#define META_IS_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_KMS))
|
||||
#define META_IS_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_KMS))
|
||||
#define META_MONITOR_MANAGER_KMS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
|
||||
|
||||
typedef struct _MetaMonitorManagerKmsClass MetaMonitorManagerKmsClass;
|
||||
typedef struct _MetaMonitorManagerKms MetaMonitorManagerKms;
|
||||
|
||||
GType meta_monitor_manager_kms_get_type (void);
|
||||
|
||||
#define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ())
|
||||
#define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
|
||||
#define META_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
|
||||
@@ -384,6 +391,8 @@ void meta_output_info_free (MetaOutputInfo *info);
|
||||
|
||||
void meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
|
||||
int n_old_outputs);
|
||||
void meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
|
||||
int n_old_modes);
|
||||
gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager);
|
||||
|
||||
/* Returns true if transform causes width and height to be inverted
|
||||
|
||||
@@ -185,7 +185,7 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
display->atom_Backlight,
|
||||
display->atom_BACKLIGHT,
|
||||
0, G_MAXLONG, False, False, XA_INTEGER,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
@@ -210,7 +210,7 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
meta_error_trap_push (display);
|
||||
info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
display->atom_Backlight);
|
||||
display->atom_BACKLIGHT);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
if (info == NULL)
|
||||
@@ -676,13 +676,11 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
int value = presentation;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
display->atom__MUTTER_PRESENTATION_OUTPUT,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char*) &value, 1);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -948,7 +946,7 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
|
||||
meta_error_trap_push (display);
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
display->atom_Backlight,
|
||||
display->atom_BACKLIGHT,
|
||||
XA_INTEGER, 32, PropModeReplace,
|
||||
(unsigned char *) &hw_value, 1);
|
||||
meta_error_trap_pop (display);
|
||||
@@ -1017,7 +1015,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
|
||||
MetaOutput *old_outputs;
|
||||
MetaCRTC *old_crtcs;
|
||||
MetaMonitorMode *old_modes;
|
||||
int n_old_outputs;
|
||||
unsigned int n_old_outputs, n_old_modes;
|
||||
gboolean new_config;
|
||||
|
||||
if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
|
||||
@@ -1029,6 +1027,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
|
||||
old_outputs = manager->outputs;
|
||||
n_old_outputs = manager->n_outputs;
|
||||
old_modes = manager->modes;
|
||||
n_old_modes = manager->n_modes;
|
||||
old_crtcs = manager->crtcs;
|
||||
|
||||
manager->serial++;
|
||||
@@ -1068,7 +1067,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
|
||||
}
|
||||
|
||||
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
|
||||
g_free (old_modes);
|
||||
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
|
||||
g_free (old_crtcs);
|
||||
|
||||
return TRUE;
|
||||
|
||||
@@ -62,59 +62,23 @@ static void initialize_dbus_interface (MetaMonitorManager *manager);
|
||||
static void
|
||||
read_current_dummy (MetaMonitorManager *manager)
|
||||
{
|
||||
/* The dummy monitor config has:
|
||||
- one enabled output, LVDS, primary, at 0x0 and 1024x768
|
||||
- one free CRTC
|
||||
- two disabled outputs
|
||||
- three modes, 1024x768, 800x600 and 640x480
|
||||
- no clones are possible (use different CRTCs)
|
||||
|
||||
Low-level IDs should be assigned sequentially, to
|
||||
mimick what XRandR and KMS do
|
||||
*/
|
||||
|
||||
manager->max_screen_width = 65535;
|
||||
manager->max_screen_height = 65535;
|
||||
manager->screen_width = 1024;
|
||||
manager->screen_height = 768;
|
||||
|
||||
manager->modes = g_new0 (MetaMonitorMode, 6);
|
||||
manager->n_modes = 6;
|
||||
manager->modes = g_new0 (MetaMonitorMode, 1);
|
||||
manager->n_modes = 1;
|
||||
|
||||
manager->modes[0].mode_id = 1;
|
||||
manager->modes[0].mode_id = 0;
|
||||
manager->modes[0].width = 1024;
|
||||
manager->modes[0].height = 768;
|
||||
manager->modes[0].refresh_rate = 60.0;
|
||||
|
||||
manager->modes[1].mode_id = 2;
|
||||
manager->modes[1].width = 800;
|
||||
manager->modes[1].height = 600;
|
||||
manager->modes[1].refresh_rate = 60.0;
|
||||
manager->crtcs = g_new0 (MetaCRTC, 1);
|
||||
manager->n_crtcs = 1;
|
||||
|
||||
manager->modes[2].mode_id = 3;
|
||||
manager->modes[2].width = 640;
|
||||
manager->modes[2].height = 480;
|
||||
manager->modes[2].refresh_rate = 60.0;
|
||||
|
||||
manager->modes[3].mode_id = 4;
|
||||
manager->modes[3].width = 1920;
|
||||
manager->modes[3].height = 1080;
|
||||
manager->modes[3].refresh_rate = 60.0;
|
||||
|
||||
manager->modes[4].mode_id = 5;
|
||||
manager->modes[4].width = 1920;
|
||||
manager->modes[4].height = 1080;
|
||||
manager->modes[4].refresh_rate = 55.0;
|
||||
|
||||
manager->modes[5].mode_id = 6;
|
||||
manager->modes[5].width = 1600;
|
||||
manager->modes[5].height = 900;
|
||||
manager->modes[5].refresh_rate = 60.0;
|
||||
|
||||
manager->crtcs = g_new0 (MetaCRTC, 3);
|
||||
manager->n_crtcs = 3;
|
||||
|
||||
manager->crtcs[0].crtc_id = 4;
|
||||
manager->crtcs[0].crtc_id = 1;
|
||||
manager->crtcs[0].rect.x = 0;
|
||||
manager->crtcs[0].rect.y = 0;
|
||||
manager->crtcs[0].rect.width = manager->modes[0].width;
|
||||
@@ -125,111 +89,30 @@ read_current_dummy (MetaMonitorManager *manager)
|
||||
manager->crtcs[0].is_dirty = FALSE;
|
||||
manager->crtcs[0].logical_monitor = NULL;
|
||||
|
||||
manager->crtcs[1].crtc_id = 5;
|
||||
manager->crtcs[1].rect.x = 0;
|
||||
manager->crtcs[1].rect.y = 0;
|
||||
manager->crtcs[1].rect.width = 0;
|
||||
manager->crtcs[1].rect.height = 0;
|
||||
manager->crtcs[1].current_mode = NULL;
|
||||
manager->crtcs[1].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
manager->crtcs[1].all_transforms = ALL_WL_TRANSFORMS;
|
||||
manager->crtcs[1].is_dirty = FALSE;
|
||||
manager->crtcs[1].logical_monitor = NULL;
|
||||
manager->outputs = g_new0 (MetaOutput, 1);
|
||||
manager->n_outputs = 1;
|
||||
|
||||
manager->crtcs[2].crtc_id = 5;
|
||||
manager->crtcs[2].rect.x = 0;
|
||||
manager->crtcs[2].rect.y = 0;
|
||||
manager->crtcs[2].rect.width = 0;
|
||||
manager->crtcs[2].rect.height = 0;
|
||||
manager->crtcs[2].current_mode = NULL;
|
||||
manager->crtcs[2].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
manager->crtcs[2].all_transforms = ALL_WL_TRANSFORMS;
|
||||
manager->crtcs[2].is_dirty = FALSE;
|
||||
manager->crtcs[2].logical_monitor = NULL;
|
||||
|
||||
manager->outputs = g_new0 (MetaOutput, 3);
|
||||
manager->n_outputs = 3;
|
||||
|
||||
manager->outputs[0].crtc = NULL;
|
||||
manager->outputs[0].output_id = 6;
|
||||
manager->outputs[0].name = g_strdup ("HDMI");
|
||||
manager->outputs[0].crtc = &manager->crtcs[0];
|
||||
manager->outputs[0].output_id = 1;
|
||||
manager->outputs[0].name = g_strdup ("LVDS");
|
||||
manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
|
||||
manager->outputs[0].product = g_strdup ("unknown");
|
||||
manager->outputs[0].serial = g_strdup ("0xC0F01A");
|
||||
manager->outputs[0].width_mm = 510;
|
||||
manager->outputs[0].height_mm = 287;
|
||||
manager->outputs[0].serial = g_strdup ("0xC0FFEE");
|
||||
manager->outputs[0].width_mm = 222;
|
||||
manager->outputs[0].height_mm = 125;
|
||||
manager->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
||||
manager->outputs[0].preferred_mode = &manager->modes[3];
|
||||
manager->outputs[0].n_modes = 5;
|
||||
manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 5);
|
||||
manager->outputs[0].preferred_mode = &manager->modes[0];
|
||||
manager->outputs[0].n_modes = 1;
|
||||
manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 1);
|
||||
manager->outputs[0].modes[0] = &manager->modes[0];
|
||||
manager->outputs[0].modes[1] = &manager->modes[1];
|
||||
manager->outputs[0].modes[2] = &manager->modes[2];
|
||||
manager->outputs[0].modes[3] = &manager->modes[3];
|
||||
manager->outputs[0].modes[4] = &manager->modes[4];
|
||||
manager->outputs[0].n_possible_crtcs = 3;
|
||||
manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 3);
|
||||
manager->outputs[0].n_possible_crtcs = 1;
|
||||
manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 1);
|
||||
manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0];
|
||||
manager->outputs[0].possible_crtcs[1] = &manager->crtcs[1];
|
||||
manager->outputs[0].possible_crtcs[2] = &manager->crtcs[2];
|
||||
manager->outputs[0].n_possible_clones = 0;
|
||||
manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0);
|
||||
manager->outputs[0].backlight = -1;
|
||||
manager->outputs[0].backlight_min = 0;
|
||||
manager->outputs[0].backlight_max = 0;
|
||||
|
||||
manager->outputs[1].crtc = &manager->crtcs[0];
|
||||
manager->outputs[1].output_id = 7;
|
||||
manager->outputs[1].name = g_strdup ("LVDS");
|
||||
manager->outputs[1].vendor = g_strdup ("MetaProducts Inc.");
|
||||
manager->outputs[1].product = g_strdup ("unknown");
|
||||
manager->outputs[1].serial = g_strdup ("0xC0FFEE");
|
||||
manager->outputs[1].width_mm = 222;
|
||||
manager->outputs[1].height_mm = 125;
|
||||
manager->outputs[1].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
||||
manager->outputs[1].preferred_mode = &manager->modes[5];
|
||||
manager->outputs[1].n_modes = 4;
|
||||
manager->outputs[1].modes = g_new0 (MetaMonitorMode *, 4);
|
||||
manager->outputs[1].modes[0] = &manager->modes[0];
|
||||
manager->outputs[1].modes[1] = &manager->modes[1];
|
||||
manager->outputs[1].modes[2] = &manager->modes[2];
|
||||
manager->outputs[1].modes[3] = &manager->modes[5];
|
||||
manager->outputs[1].n_possible_crtcs = 3;
|
||||
manager->outputs[1].possible_crtcs = g_new0 (MetaCRTC *, 3);
|
||||
manager->outputs[1].possible_crtcs[0] = &manager->crtcs[0];
|
||||
manager->outputs[1].possible_crtcs[1] = &manager->crtcs[1];
|
||||
manager->outputs[1].possible_crtcs[2] = &manager->crtcs[2];
|
||||
manager->outputs[1].n_possible_clones = 0;
|
||||
manager->outputs[1].possible_clones = g_new0 (MetaOutput *, 0);
|
||||
manager->outputs[1].backlight = -1;
|
||||
manager->outputs[1].backlight_min = 0;
|
||||
manager->outputs[1].backlight_max = 0;
|
||||
|
||||
manager->outputs[2].crtc = NULL;
|
||||
manager->outputs[2].output_id = 8;
|
||||
manager->outputs[2].name = g_strdup ("VGA");
|
||||
manager->outputs[2].vendor = g_strdup ("MetaProducts Inc.");
|
||||
manager->outputs[2].product = g_strdup ("unknown");
|
||||
manager->outputs[2].serial = g_strdup ("0xC4FE");
|
||||
manager->outputs[2].width_mm = 309;
|
||||
manager->outputs[2].height_mm = 174;
|
||||
manager->outputs[2].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
||||
manager->outputs[2].preferred_mode = &manager->modes[0];
|
||||
manager->outputs[2].n_modes = 3;
|
||||
manager->outputs[2].modes = g_new0 (MetaMonitorMode *, 3);
|
||||
manager->outputs[2].modes[0] = &manager->modes[0];
|
||||
manager->outputs[2].modes[1] = &manager->modes[1];
|
||||
manager->outputs[2].modes[2] = &manager->modes[2];
|
||||
manager->outputs[2].n_possible_crtcs = 3;
|
||||
manager->outputs[2].possible_crtcs = g_new0 (MetaCRTC *, 3);
|
||||
manager->outputs[2].possible_crtcs[0] = &manager->crtcs[0];
|
||||
manager->outputs[2].possible_crtcs[1] = &manager->crtcs[1];
|
||||
manager->outputs[2].possible_crtcs[2] = &manager->crtcs[2];
|
||||
manager->outputs[2].n_possible_clones = 0;
|
||||
manager->outputs[2].possible_clones = g_new0 (MetaOutput *, 0);
|
||||
manager->outputs[2].backlight = -1;
|
||||
manager->outputs[2].backlight_min = 0;
|
||||
manager->outputs[2].backlight_max = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -469,6 +352,40 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
|
||||
}
|
||||
|
||||
static GType
|
||||
get_default_backend (void)
|
||||
{
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
return META_TYPE_MONITOR_MANAGER_KMS;
|
||||
#endif
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_X11)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
|
||||
{
|
||||
/* If we're a Wayland compositor using the X11 backend,
|
||||
* we're a nested configuration, so return the dummy
|
||||
* monitor setup. */
|
||||
if (meta_is_wayland_compositor ())
|
||||
return META_TYPE_MONITOR_MANAGER;
|
||||
else
|
||||
return META_TYPE_MONITOR_MANAGER_XRANDR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_WAYLAND)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WAYLAND))
|
||||
{
|
||||
/* Use the dummy implementation on Wayland for now.
|
||||
* In the future, we should support wl_fullscreen_output
|
||||
* which will have CRTC management in the protocol. */
|
||||
return META_TYPE_MONITOR_MANAGER;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static MetaMonitorManager *
|
||||
meta_monitor_manager_new (void)
|
||||
{
|
||||
@@ -478,7 +395,7 @@ meta_monitor_manager_new (void)
|
||||
env = g_getenv ("META_DEBUG_MULTIMONITOR");
|
||||
|
||||
if (env == NULL)
|
||||
type = META_TYPE_MONITOR_MANAGER_XRANDR;
|
||||
type = get_default_backend ();
|
||||
else if (strcmp (env, "xrandr") == 0)
|
||||
type = META_TYPE_MONITOR_MANAGER_XRANDR;
|
||||
else
|
||||
@@ -513,17 +430,18 @@ meta_monitor_manager_constructed (GObject *object)
|
||||
MetaOutput *old_outputs;
|
||||
MetaCRTC *old_crtcs;
|
||||
MetaMonitorMode *old_modes;
|
||||
int n_old_outputs;
|
||||
unsigned int n_old_outputs, n_old_modes;
|
||||
|
||||
old_outputs = manager->outputs;
|
||||
n_old_outputs = manager->n_outputs;
|
||||
old_modes = manager->modes;
|
||||
n_old_modes = manager->n_modes;
|
||||
old_crtcs = manager->crtcs;
|
||||
|
||||
read_current_config (manager);
|
||||
|
||||
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
|
||||
g_free (old_modes);
|
||||
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
|
||||
g_free (old_crtcs);
|
||||
}
|
||||
|
||||
@@ -565,19 +483,39 @@ meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
|
||||
g_free (old_outputs[i].modes);
|
||||
g_free (old_outputs[i].possible_crtcs);
|
||||
g_free (old_outputs[i].possible_clones);
|
||||
|
||||
if (old_outputs[i].driver_notify)
|
||||
old_outputs[i].driver_notify (&old_outputs[i]);
|
||||
}
|
||||
|
||||
g_free (old_outputs);
|
||||
}
|
||||
|
||||
void
|
||||
meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
|
||||
int n_old_modes)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_old_modes; i++)
|
||||
{
|
||||
g_free (old_modes[i].name);
|
||||
|
||||
if (old_modes[i].driver_notify)
|
||||
old_modes[i].driver_notify (&old_modes[i]);
|
||||
}
|
||||
|
||||
g_free (old_modes);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_finalize (GObject *object)
|
||||
{
|
||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (object);
|
||||
|
||||
meta_monitor_manager_free_output_array (manager->outputs, manager->n_outputs);
|
||||
meta_monitor_manager_free_mode_array (manager->modes, manager->n_modes);
|
||||
g_free (manager->monitor_infos);
|
||||
g_free (manager->modes);
|
||||
g_free (manager->crtcs);
|
||||
|
||||
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->finalize (object);
|
||||
@@ -770,13 +708,13 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
|
||||
g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})",
|
||||
i, /* ID */
|
||||
(gint64)crtc->crtc_id,
|
||||
crtc->crtc_id,
|
||||
(int)crtc->rect.x,
|
||||
(int)crtc->rect.y,
|
||||
(int)crtc->rect.width,
|
||||
(int)crtc->rect.height,
|
||||
(int)(crtc->current_mode ? crtc->current_mode - manager->modes : -1),
|
||||
(guint32)crtc->transform,
|
||||
crtc->transform,
|
||||
&transforms,
|
||||
NULL /* properties */);
|
||||
}
|
||||
@@ -847,7 +785,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
|
||||
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
|
||||
i, /* ID */
|
||||
(gint64)output->output_id,
|
||||
output->output_id,
|
||||
(int)(output->crtc ? output->crtc - manager->crtcs : -1),
|
||||
&crtcs,
|
||||
output->name,
|
||||
@@ -862,9 +800,9 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
|
||||
g_variant_builder_add (&mode_builder, "(uxuud)",
|
||||
i, /* ID */
|
||||
(gint64)mode->mode_id,
|
||||
(guint32)mode->width,
|
||||
(guint32)mode->height,
|
||||
mode->mode_id,
|
||||
mode->width,
|
||||
mode->height,
|
||||
(double)mode->refresh_rate);
|
||||
}
|
||||
|
||||
@@ -1453,12 +1391,21 @@ meta_monitor_manager_get_resources (MetaMonitorManager *manager,
|
||||
MetaOutput **outputs,
|
||||
unsigned int *n_outputs)
|
||||
{
|
||||
*modes = manager->modes;
|
||||
*n_modes = manager->n_modes;
|
||||
*crtcs = manager->crtcs;
|
||||
*n_crtcs = manager->n_crtcs;
|
||||
*outputs = manager->outputs;
|
||||
*n_outputs = manager->n_outputs;
|
||||
if (modes)
|
||||
{
|
||||
*modes = manager->modes;
|
||||
*n_modes = manager->n_modes;
|
||||
}
|
||||
if (crtcs)
|
||||
{
|
||||
*crtcs = manager->crtcs;
|
||||
*n_crtcs = manager->n_crtcs;
|
||||
}
|
||||
if (outputs)
|
||||
{
|
||||
*outputs = manager->outputs;
|
||||
*n_outputs = manager->n_outputs;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -75,7 +75,6 @@ main (int argc, char **argv)
|
||||
g_printerr ("mutter: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
g_option_context_free (ctx);
|
||||
|
||||
if (plugin)
|
||||
meta_plugin_manager_load (plugin);
|
||||
|
||||
@@ -344,7 +344,7 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
|
||||
/* denied_focus_and_not_transient is only set when focus_window != NULL */
|
||||
|
||||
if (window->denied_focus_and_not_transient &&
|
||||
window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
|
||||
window->type == META_WINDOW_MODAL_DIALOG &&
|
||||
meta_window_same_application (window, focus_window) &&
|
||||
window_overlaps_focus_window (window))
|
||||
{
|
||||
@@ -610,7 +610,7 @@ meta_window_place (MetaWindow *window,
|
||||
meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
|
||||
|
||||
windows = NULL;
|
||||
|
||||
|
||||
switch (window->type)
|
||||
{
|
||||
/* Run placement algorithm on these. */
|
||||
@@ -638,7 +638,7 @@ meta_window_place (MetaWindow *window,
|
||||
case META_WINDOW_OVERRIDE_OTHER:
|
||||
goto done_no_constraints;
|
||||
}
|
||||
|
||||
|
||||
if (meta_prefs_get_disable_workarounds ())
|
||||
{
|
||||
switch (window->type)
|
||||
@@ -699,18 +699,11 @@ meta_window_place (MetaWindow *window,
|
||||
goto done_no_constraints;
|
||||
}
|
||||
}
|
||||
|
||||
if ((window->type == META_WINDOW_DIALOG ||
|
||||
window->type == META_WINDOW_MODAL_DIALOG) &&
|
||||
window->xtransient_for != None)
|
||||
{
|
||||
/* Center horizontally, at top of parent vertically */
|
||||
|
||||
MetaWindow *parent;
|
||||
|
||||
parent =
|
||||
meta_display_lookup_x_window (window->display,
|
||||
window->xtransient_for);
|
||||
if (window->type == META_WINDOW_DIALOG ||
|
||||
window->type == META_WINDOW_MODAL_DIALOG)
|
||||
{
|
||||
MetaWindow *parent = meta_window_get_transient_for (window);
|
||||
|
||||
if (parent)
|
||||
{
|
||||
|
||||
@@ -1187,8 +1187,8 @@ maybe_give_disable_workarounds_warning (void)
|
||||
{
|
||||
first_disable = FALSE;
|
||||
|
||||
meta_warning (_("Workarounds for broken applications disabled. "
|
||||
"Some applications may not behave properly.\n"));
|
||||
meta_warning ("Workarounds for broken applications disabled. "
|
||||
"Some applications may not behave properly.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1262,8 +1262,8 @@ titlebar_handler (GVariant *value,
|
||||
|
||||
if (desc == NULL)
|
||||
{
|
||||
meta_warning (_("Could not parse font description "
|
||||
"\"%s\" from GSettings key %s\n"),
|
||||
meta_warning ("Could not parse font description "
|
||||
"\"%s\" from GSettings key %s\n",
|
||||
string_value ? string_value : "(null)",
|
||||
KEY_TITLEBAR_FONT);
|
||||
return FALSE;
|
||||
@@ -1328,8 +1328,8 @@ mouse_button_mods_handler (GVariant *value,
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Failed to parse new GSettings value\n");
|
||||
|
||||
meta_warning (_("\"%s\" found in configuration database is "
|
||||
"not a valid value for mouse button modifier\n"),
|
||||
meta_warning ("\"%s\" found in configuration database is "
|
||||
"not a valid value for mouse button modifier\n",
|
||||
string_value);
|
||||
|
||||
return FALSE;
|
||||
@@ -1891,7 +1891,7 @@ update_binding (MetaKeyPref *binding,
|
||||
{
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Failed to parse new GSettings value\n");
|
||||
meta_warning (_("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"),
|
||||
meta_warning ("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n",
|
||||
strokes[i], binding->name);
|
||||
|
||||
/* Value is kept and will thus be removed next time we save the key.
|
||||
|
||||
@@ -223,12 +223,14 @@ void meta_screen_workspace_switched (MetaScreen *screen,
|
||||
|
||||
void meta_screen_set_active_workspace_hint (MetaScreen *screen);
|
||||
|
||||
void meta_screen_create_guard_window (MetaScreen *screen);
|
||||
|
||||
gboolean meta_screen_handle_xevent (MetaScreen *screen,
|
||||
XEvent *xevent);
|
||||
|
||||
int meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
|
||||
int index);
|
||||
int meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
|
||||
int index);
|
||||
|
||||
gboolean meta_screen_handle_xevent (MetaScreen *screen,
|
||||
XEvent *xevent);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include "workspace-private.h"
|
||||
#include "keybindings-private.h"
|
||||
#include "stack.h"
|
||||
#include "xprops.h"
|
||||
#include <meta/compositor.h>
|
||||
#include "mutter-enum-types.h"
|
||||
#include "core.h"
|
||||
@@ -53,6 +52,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "x11/xprops.h"
|
||||
|
||||
static char* get_screen_name (MetaDisplay *display,
|
||||
int number);
|
||||
|
||||
@@ -454,6 +455,7 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
|
||||
XSetWindowAttributes attributes;
|
||||
Window guard_window;
|
||||
gulong create_serial;
|
||||
MetaStackWindow stack_window;
|
||||
|
||||
attributes.event_mask = NoEventMask;
|
||||
attributes.override_redirect = True;
|
||||
@@ -475,9 +477,6 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
|
||||
CWEventMask|CWOverrideRedirect,
|
||||
&attributes);
|
||||
|
||||
/* https://bugzilla.gnome.org/show_bug.cgi?id=710346 */
|
||||
XStoreName (xdisplay, guard_window, "mutter guard window");
|
||||
|
||||
{
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
@@ -488,12 +487,14 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
|
||||
XISelectEvents (xdisplay, guard_window, &mask, 1);
|
||||
}
|
||||
|
||||
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||
stack_window.x11.xwindow = guard_window;
|
||||
meta_stack_tracker_record_add (screen->stack_tracker,
|
||||
guard_window,
|
||||
&stack_window,
|
||||
create_serial);
|
||||
|
||||
meta_stack_tracker_record_lower (screen->stack_tracker,
|
||||
guard_window,
|
||||
&stack_window,
|
||||
XNextRequest (xdisplay));
|
||||
XLowerWindow (xdisplay, guard_window);
|
||||
XMapWindow (xdisplay, guard_window);
|
||||
@@ -579,7 +580,7 @@ meta_screen_new (MetaDisplay *display,
|
||||
|
||||
if (XGetSelectionOwner (xdisplay, wm_sn_atom) != new_wm_sn_owner)
|
||||
{
|
||||
meta_warning (_("Could not acquire window manager selection on screen %d display \"%s\"\n"),
|
||||
meta_warning ("Could not acquire window manager selection on screen %d display \"%s\"\n",
|
||||
number, display->name);
|
||||
|
||||
XDestroyWindow (xdisplay, new_wm_sn_owner);
|
||||
@@ -674,8 +675,9 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->xscreen = ScreenOfDisplay (xdisplay, number);
|
||||
screen->xroot = xroot;
|
||||
screen->rect.x = screen->rect.y = 0;
|
||||
|
||||
meta_monitor_manager_initialize ();
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
meta_monitor_manager_initialize ();
|
||||
|
||||
manager = meta_monitor_manager_get ();
|
||||
g_signal_connect (manager, "monitors-changed",
|
||||
@@ -807,11 +809,8 @@ meta_screen_free (MetaScreen *screen,
|
||||
|
||||
meta_display_grab (display);
|
||||
|
||||
if (screen->display->compositor)
|
||||
{
|
||||
meta_compositor_unmanage_screen (screen->display->compositor,
|
||||
screen);
|
||||
}
|
||||
meta_compositor_unmanage_screen (screen->display->compositor,
|
||||
screen);
|
||||
|
||||
meta_display_unmanage_windows_for_screen (display, screen, timestamp);
|
||||
|
||||
@@ -845,7 +844,7 @@ meta_screen_free (MetaScreen *screen,
|
||||
meta_error_trap_push_with_return (screen->display);
|
||||
XSelectInput (screen->display->xdisplay, screen->xroot, 0);
|
||||
if (meta_error_trap_pop_with_return (screen->display) != Success)
|
||||
meta_warning (_("Could not release screen %d on display \"%s\"\n"),
|
||||
meta_warning ("Could not release screen %d on display \"%s\"\n",
|
||||
screen->number, screen->display->name);
|
||||
|
||||
unset_wm_check_hint (screen);
|
||||
@@ -872,27 +871,30 @@ meta_screen_free (MetaScreen *screen,
|
||||
meta_display_ungrab (display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_create_guard_window (MetaScreen *screen)
|
||||
{
|
||||
if (screen->guard_window == None)
|
||||
screen->guard_window = create_guard_window (screen->display->xdisplay, screen);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_manage_all_windows (MetaScreen *screen)
|
||||
{
|
||||
Window *_children;
|
||||
Window *children;
|
||||
MetaStackWindow *_children;
|
||||
MetaStackWindow *children;
|
||||
int n_children, i;
|
||||
|
||||
if (screen->guard_window == None)
|
||||
screen->guard_window = create_guard_window (screen->display->xdisplay,
|
||||
screen);
|
||||
|
||||
meta_stack_freeze (screen->stack);
|
||||
meta_stack_tracker_get_stack (screen->stack_tracker, &_children, &n_children);
|
||||
|
||||
/* Copy the stack as it will be modified as part of the loop */
|
||||
children = g_memdup (_children, sizeof (Window) * n_children);
|
||||
children = g_memdup (_children, sizeof (MetaStackWindow) * n_children);
|
||||
|
||||
for (i = 0; i < n_children; ++i)
|
||||
{
|
||||
meta_window_new (screen->display, children[i], TRUE,
|
||||
META_COMP_EFFECT_NONE);
|
||||
meta_window_x11_new (screen->display, children[i].x11.xwindow, TRUE,
|
||||
META_COMP_EFFECT_NONE);
|
||||
}
|
||||
|
||||
g_free (children);
|
||||
@@ -1509,38 +1511,19 @@ meta_screen_get_mouse_window (MetaScreen *screen,
|
||||
MetaWindow *not_this_one)
|
||||
{
|
||||
MetaWindow *window;
|
||||
Window root_return, child_return;
|
||||
double root_x_return, root_y_return;
|
||||
double win_x_return, win_y_return;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
int x, y;
|
||||
|
||||
if (not_this_one)
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing mouse window excluding %s\n", not_this_one->desc);
|
||||
|
||||
meta_error_trap_push (screen->display);
|
||||
XIQueryPointer (screen->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
screen->xroot,
|
||||
&root_return,
|
||||
&child_return,
|
||||
&root_x_return,
|
||||
&root_y_return,
|
||||
&win_x_return,
|
||||
&win_y_return,
|
||||
&buttons,
|
||||
&mods,
|
||||
&group);
|
||||
meta_error_trap_pop (screen->display);
|
||||
free (buttons.mask);
|
||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
||||
&x, &y, NULL);
|
||||
|
||||
window = meta_stack_get_default_focus_window_at_point (screen->stack,
|
||||
screen->active_workspace,
|
||||
not_this_one,
|
||||
root_x_return,
|
||||
root_y_return);
|
||||
x, y);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -1822,28 +1805,11 @@ meta_screen_get_current_monitor (MetaScreen *screen)
|
||||
|
||||
if (screen->display->monitor_cache_invalidated)
|
||||
{
|
||||
Window root_return, child_return;
|
||||
double win_x_return, win_y_return;
|
||||
double root_x_return, root_y_return;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
int x, y;
|
||||
|
||||
XIQueryPointer (screen->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
screen->xroot,
|
||||
&root_return,
|
||||
&child_return,
|
||||
&root_x_return,
|
||||
&root_y_return,
|
||||
&win_x_return,
|
||||
&win_y_return,
|
||||
&buttons,
|
||||
&mods,
|
||||
&group);
|
||||
free (buttons.mask);
|
||||
|
||||
meta_screen_get_current_monitor_for_pos (screen, root_x_return, root_y_return);
|
||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
||||
&x, &y, NULL);
|
||||
meta_screen_get_current_monitor_for_pos (screen, x, y);
|
||||
}
|
||||
|
||||
return screen->last_monitor_index;
|
||||
@@ -2554,10 +2520,9 @@ on_monitors_changed (MetaMonitorManager *manager,
|
||||
&changes);
|
||||
}
|
||||
|
||||
if (screen->display->compositor)
|
||||
meta_compositor_sync_screen_size (screen->display->compositor,
|
||||
screen,
|
||||
screen->rect.width, screen->rect.height);
|
||||
meta_compositor_sync_screen_size (screen->display->compositor,
|
||||
screen,
|
||||
screen->rect.width, screen->rect.height);
|
||||
|
||||
/* Queue a resize on all the windows */
|
||||
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
|
||||
@@ -3373,10 +3338,6 @@ gboolean
|
||||
meta_screen_handle_xevent (MetaScreen *screen,
|
||||
XEvent *xevent)
|
||||
{
|
||||
/* Go through our helpers and see if they want this event.
|
||||
Currently, only MetaCursorTracker.
|
||||
*/
|
||||
|
||||
if (meta_cursor_tracker_handle_xevent (screen->cursor_tracker, xevent))
|
||||
return TRUE;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,36 +35,55 @@
|
||||
#define META_STACK_TRACKER_H
|
||||
|
||||
#include <meta/screen.h>
|
||||
#include <meta/window.h>
|
||||
|
||||
typedef struct _MetaStackTracker MetaStackTracker;
|
||||
|
||||
typedef union _MetaStackWindow
|
||||
{
|
||||
struct {
|
||||
MetaWindowClientType type;
|
||||
} any;
|
||||
struct {
|
||||
MetaWindowClientType type;
|
||||
Window xwindow;
|
||||
} x11;
|
||||
struct {
|
||||
MetaWindowClientType type;
|
||||
MetaWindow *meta_window;
|
||||
} wayland;
|
||||
} MetaStackWindow;
|
||||
|
||||
gboolean meta_stack_window_equal (const MetaStackWindow *a,
|
||||
const MetaStackWindow *b);
|
||||
|
||||
MetaStackTracker *meta_stack_tracker_new (MetaScreen *screen);
|
||||
void meta_stack_tracker_free (MetaStackTracker *tracker);
|
||||
|
||||
/* These functions are called when we make an X call that changes the
|
||||
* stacking order; this allows MetaStackTracker to predict stacking
|
||||
* order before it receives events back from the X server */
|
||||
void meta_stack_tracker_record_add (MetaStackTracker *tracker,
|
||||
Window window,
|
||||
gulong serial);
|
||||
void meta_stack_tracker_record_remove (MetaStackTracker *tracker,
|
||||
Window window,
|
||||
gulong serial);
|
||||
void meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker,
|
||||
Window *windows,
|
||||
int n_windows,
|
||||
gulong serial);
|
||||
void meta_stack_tracker_record_raise_above (MetaStackTracker *tracker,
|
||||
Window window,
|
||||
Window sibling,
|
||||
gulong serial);
|
||||
void meta_stack_tracker_record_lower_below (MetaStackTracker *tracker,
|
||||
Window window,
|
||||
Window sibling,
|
||||
gulong serial);
|
||||
void meta_stack_tracker_record_lower (MetaStackTracker *tracker,
|
||||
Window window,
|
||||
gulong serial);
|
||||
void meta_stack_tracker_record_add (MetaStackTracker *tracker,
|
||||
const MetaStackWindow *window,
|
||||
gulong serial);
|
||||
void meta_stack_tracker_record_remove (MetaStackTracker *tracker,
|
||||
const MetaStackWindow *window,
|
||||
gulong serial);
|
||||
void meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker,
|
||||
const MetaStackWindow *windows,
|
||||
int n_windows,
|
||||
gulong serial);
|
||||
void meta_stack_tracker_record_raise_above (MetaStackTracker *tracker,
|
||||
const MetaStackWindow *window,
|
||||
const MetaStackWindow *sibling,
|
||||
gulong serial);
|
||||
void meta_stack_tracker_record_lower_below (MetaStackTracker *tracker,
|
||||
const MetaStackWindow *window,
|
||||
const MetaStackWindow *sibling,
|
||||
gulong serial);
|
||||
void meta_stack_tracker_record_lower (MetaStackTracker *tracker,
|
||||
const MetaStackWindow *window,
|
||||
gulong serial);
|
||||
|
||||
/* These functions are used to update the stack when we get events
|
||||
* reflecting changes to the stacking order */
|
||||
@@ -77,9 +96,9 @@ void meta_stack_tracker_reparent_event (MetaStackTracker *tracker,
|
||||
void meta_stack_tracker_configure_event (MetaStackTracker *tracker,
|
||||
XConfigureEvent *event);
|
||||
|
||||
void meta_stack_tracker_get_stack (MetaStackTracker *tracker,
|
||||
Window **windows,
|
||||
int *n_windows);
|
||||
void meta_stack_tracker_get_stack (MetaStackTracker *tracker,
|
||||
MetaStackWindow **windows,
|
||||
int *n_entries);
|
||||
|
||||
void meta_stack_tracker_sync_stack (MetaStackTracker *tracker);
|
||||
void meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker);
|
||||
|
||||
593
src/core/stack.c
593
src/core/stack.c
@@ -36,6 +36,8 @@
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "x11/group-private.h"
|
||||
|
||||
#define WINDOW_HAS_TRANSIENT_TYPE(w) \
|
||||
(w->type == META_WINDOW_DIALOG || \
|
||||
w->type == META_WINDOW_MODAL_DIALOG || \
|
||||
@@ -50,7 +52,7 @@
|
||||
|
||||
#define WINDOW_IN_STACK(w) (w->stack_position >= 0)
|
||||
|
||||
static void stack_sync_to_server (MetaStack *stack);
|
||||
static void stack_sync_to_xserver (MetaStack *stack);
|
||||
static void meta_window_set_stack_position_no_sync (MetaWindow *window,
|
||||
int position);
|
||||
static void stack_do_window_deletions (MetaStack *stack);
|
||||
@@ -69,14 +71,14 @@ meta_stack_new (MetaScreen *screen)
|
||||
stack = g_new (MetaStack, 1);
|
||||
|
||||
stack->screen = screen;
|
||||
stack->windows = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
stack->xwindows = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
|
||||
stack->sorted = NULL;
|
||||
stack->added = NULL;
|
||||
stack->removed = NULL;
|
||||
|
||||
stack->freeze_count = 0;
|
||||
stack->last_root_children_stacked = NULL;
|
||||
stack->last_all_root_children_stacked = NULL;
|
||||
|
||||
stack->n_positions = 0;
|
||||
|
||||
@@ -87,17 +89,24 @@ meta_stack_new (MetaScreen *screen)
|
||||
return stack;
|
||||
}
|
||||
|
||||
static void
|
||||
free_last_all_root_children_stacked_cache (MetaStack *stack)
|
||||
{
|
||||
g_array_free (stack->last_all_root_children_stacked, TRUE);
|
||||
stack->last_all_root_children_stacked = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
meta_stack_free (MetaStack *stack)
|
||||
{
|
||||
g_array_free (stack->windows, TRUE);
|
||||
g_array_free (stack->xwindows, TRUE);
|
||||
|
||||
g_list_free (stack->sorted);
|
||||
g_list_free (stack->added);
|
||||
g_list_free (stack->removed);
|
||||
|
||||
if (stack->last_root_children_stacked)
|
||||
g_array_free (stack->last_root_children_stacked, TRUE);
|
||||
if (stack->last_all_root_children_stacked)
|
||||
free_last_all_root_children_stacked_cache (stack);
|
||||
|
||||
g_free (stack);
|
||||
}
|
||||
@@ -119,7 +128,7 @@ meta_stack_add (MetaStack *stack,
|
||||
"Window %s has stack_position initialized to %d\n",
|
||||
window->desc, window->stack_position);
|
||||
|
||||
stack_sync_to_server (stack);
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
|
||||
}
|
||||
|
||||
@@ -155,7 +164,7 @@ meta_stack_remove (MetaStack *stack,
|
||||
stack->removed = g_list_prepend (stack->removed,
|
||||
GUINT_TO_POINTER (window->frame->xwindow));
|
||||
|
||||
stack_sync_to_server (stack);
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
|
||||
}
|
||||
|
||||
@@ -165,7 +174,7 @@ meta_stack_update_layer (MetaStack *stack,
|
||||
{
|
||||
stack->need_relayer = TRUE;
|
||||
|
||||
stack_sync_to_server (stack);
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
|
||||
}
|
||||
|
||||
@@ -175,7 +184,7 @@ meta_stack_update_transient (MetaStack *stack,
|
||||
{
|
||||
stack->need_constrain = TRUE;
|
||||
|
||||
stack_sync_to_server (stack);
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
|
||||
}
|
||||
|
||||
@@ -204,7 +213,7 @@ meta_stack_raise (MetaStack *stack,
|
||||
|
||||
meta_window_set_stack_position_no_sync (window, max_stack_position);
|
||||
|
||||
stack_sync_to_server (stack);
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
|
||||
}
|
||||
|
||||
@@ -232,7 +241,7 @@ meta_stack_lower (MetaStack *stack,
|
||||
|
||||
meta_window_set_stack_position_no_sync (window, min_stack_position);
|
||||
|
||||
stack_sync_to_server (stack);
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
|
||||
}
|
||||
|
||||
@@ -248,7 +257,7 @@ meta_stack_thaw (MetaStack *stack)
|
||||
g_return_if_fail (stack->freeze_count > 0);
|
||||
|
||||
stack->freeze_count -= 1;
|
||||
stack_sync_to_server (stack);
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_update_window_tile_matches (stack, NULL);
|
||||
}
|
||||
|
||||
@@ -827,7 +836,7 @@ stack_do_window_deletions (MetaStack *stack)
|
||||
/* We go from the end figuring removals are more
|
||||
* likely to be recent.
|
||||
*/
|
||||
i = stack->windows->len;
|
||||
i = stack->xwindows->len;
|
||||
while (i > 0)
|
||||
{
|
||||
--i;
|
||||
@@ -838,9 +847,9 @@ stack_do_window_deletions (MetaStack *stack)
|
||||
* both the window->xwindow and window->frame->xwindow
|
||||
* in the removal list.
|
||||
*/
|
||||
if (xwindow == g_array_index (stack->windows, Window, i))
|
||||
if (xwindow == g_array_index (stack->xwindows, Window, i))
|
||||
{
|
||||
g_array_remove_index (stack->windows, i);
|
||||
g_array_remove_index (stack->xwindows, i);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
@@ -869,10 +878,10 @@ stack_do_window_additions (MetaStack *stack)
|
||||
"Adding %d windows to sorted list\n",
|
||||
n_added);
|
||||
|
||||
old_size = stack->windows->len;
|
||||
g_array_set_size (stack->windows, old_size + n_added);
|
||||
old_size = stack->xwindows->len;
|
||||
g_array_set_size (stack->xwindows, old_size + n_added);
|
||||
|
||||
end = &g_array_index (stack->windows, Window, old_size);
|
||||
end = &g_array_index (stack->xwindows, Window, old_size);
|
||||
|
||||
/* stack->added has the most recent additions at the
|
||||
* front of the list, so we need to reverse it
|
||||
@@ -1027,6 +1036,102 @@ stack_ensure_sorted (MetaStack *stack)
|
||||
stack_do_resort (stack);
|
||||
}
|
||||
|
||||
static MetaStackWindow *
|
||||
find_top_most_managed_window (MetaScreen *screen,
|
||||
const MetaStackWindow *ignore)
|
||||
{
|
||||
MetaStackTracker *stack_tracker = screen->stack_tracker;
|
||||
MetaStackWindow *windows;
|
||||
int n_windows;
|
||||
int i;
|
||||
|
||||
meta_stack_tracker_get_stack (stack_tracker,
|
||||
&windows, &n_windows);
|
||||
|
||||
/* Children are in order from bottom to top. We want to
|
||||
* find the topmost managed child, then configure
|
||||
* our window to be above it.
|
||||
*/
|
||||
for (i = n_windows -1; i >= 0; i--)
|
||||
{
|
||||
MetaStackWindow *other_window = &windows[i];
|
||||
|
||||
if (other_window->any.type == ignore->any.type &&
|
||||
((other_window->any.type == META_WINDOW_CLIENT_TYPE_X11 &&
|
||||
other_window->x11.xwindow == ignore->x11.xwindow) ||
|
||||
other_window->wayland.meta_window == ignore->wayland.meta_window))
|
||||
{
|
||||
/* Do nothing. This means we're already the topmost managed
|
||||
* window, but it DOES NOT mean we are already just above
|
||||
* the topmost managed window. This is important because if
|
||||
* an override redirect window is up, and we map a new
|
||||
* managed window, the new window is probably above the old
|
||||
* popup by default, and we want to push it below that
|
||||
* popup. So keep looking for a sibling managed window
|
||||
* to be moved below.
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if (other_window->any.type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
MetaWindow *other = meta_display_lookup_x_window (screen->display,
|
||||
other_window->x11.xwindow);
|
||||
|
||||
if (other != NULL && !other->override_redirect)
|
||||
return other_window;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All wayland windows are currently considered "managed"
|
||||
* TODO: consider wayland pop-up windows like override
|
||||
* redirect windows here. */
|
||||
return other_window;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* When moving an X window we sometimes need an X based sibling.
|
||||
*
|
||||
* If the given sibling is X based this function returns it back
|
||||
* otherwise it searches downwards looking for the nearest X window.
|
||||
*
|
||||
* If no X based sibling could be found return NULL. */
|
||||
static MetaStackWindow *
|
||||
find_x11_sibling_downwards (MetaScreen *screen,
|
||||
MetaStackWindow *sibling)
|
||||
{
|
||||
MetaStackTracker *stack_tracker = screen->stack_tracker;
|
||||
MetaStackWindow *windows;
|
||||
int n_windows;
|
||||
int i;
|
||||
|
||||
if (sibling->any.type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
return sibling;
|
||||
|
||||
meta_stack_tracker_get_stack (stack_tracker,
|
||||
&windows, &n_windows);
|
||||
|
||||
/* NB: Children are in order from bottom to top and we
|
||||
* want to search downwards for the nearest X window.
|
||||
*/
|
||||
|
||||
for (i = n_windows - 1; i >= 0; i--)
|
||||
if (meta_stack_window_equal (&windows[i], sibling))
|
||||
break;
|
||||
|
||||
for (; i >= 0; i--)
|
||||
{
|
||||
if (windows[i].any.type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
return &windows[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* raise_window_relative_to_managed_windows:
|
||||
*
|
||||
@@ -1051,84 +1156,74 @@ stack_ensure_sorted (MetaStack *stack)
|
||||
*/
|
||||
static void
|
||||
raise_window_relative_to_managed_windows (MetaScreen *screen,
|
||||
Window xwindow)
|
||||
const MetaStackWindow *window)
|
||||
{
|
||||
gulong serial = 0;
|
||||
MetaStackWindow *sibling;
|
||||
|
||||
Window *children;
|
||||
int n_children;
|
||||
int i;
|
||||
|
||||
meta_stack_tracker_get_stack (screen->stack_tracker,
|
||||
&children, &n_children);
|
||||
|
||||
/* Children are in order from bottom to top. We want to
|
||||
* find the topmost managed child, then configure
|
||||
* our window to be above it.
|
||||
*/
|
||||
i = n_children - 1;
|
||||
while (i >= 0)
|
||||
sibling = find_top_most_managed_window (screen, window);
|
||||
if (!sibling)
|
||||
{
|
||||
if (children[i] == xwindow)
|
||||
if (window->any.type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
/* Do nothing. This means we're already the topmost managed
|
||||
* window, but it DOES NOT mean we are already just above
|
||||
* the topmost managed window. This is important because if
|
||||
* an override redirect window is up, and we map a new
|
||||
* managed window, the new window is probably above the old
|
||||
* popup by default, and we want to push it below that
|
||||
* popup. So keep looking for a sibling managed window
|
||||
* to be moved below.
|
||||
*/
|
||||
serial = XNextRequest (screen->display->xdisplay);
|
||||
meta_error_trap_push (screen->display);
|
||||
XLowerWindow (screen->display->xdisplay,
|
||||
window->x11.xwindow);
|
||||
meta_error_trap_pop (screen->display);
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaWindow *other = meta_display_lookup_x_window (screen->display,
|
||||
children[i]);
|
||||
if (other != NULL && !other->override_redirect)
|
||||
{
|
||||
XWindowChanges changes;
|
||||
|
||||
/* children[i] is the topmost managed child */
|
||||
/* No sibling to use, just lower ourselves to the bottom
|
||||
* to be sure we're below any override redirect windows.
|
||||
*/
|
||||
meta_stack_tracker_record_lower (screen->stack_tracker,
|
||||
window,
|
||||
serial);
|
||||
return;
|
||||
}
|
||||
|
||||
/* window is the topmost managed child */
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Moving 0x%lx above topmost managed child window 0x%lx\n",
|
||||
xwindow, children[i]);
|
||||
window->any.type == META_WINDOW_CLIENT_TYPE_X11 ? window->x11.xwindow: 0,
|
||||
sibling->any.type == META_WINDOW_CLIENT_TYPE_X11 ? sibling->x11.xwindow: 0);
|
||||
|
||||
changes.sibling = children[i];
|
||||
if (window->any.type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
XWindowChanges changes;
|
||||
MetaStackWindow *x11_sibling = find_x11_sibling_downwards (screen, sibling);
|
||||
serial = XNextRequest (screen->display->xdisplay);
|
||||
|
||||
if (x11_sibling)
|
||||
{
|
||||
changes.sibling = x11_sibling->x11.xwindow;
|
||||
changes.stack_mode = Above;
|
||||
|
||||
meta_error_trap_push (screen->display);
|
||||
meta_stack_tracker_record_raise_above (screen->stack_tracker,
|
||||
xwindow,
|
||||
children[i],
|
||||
XNextRequest (screen->display->xdisplay));
|
||||
XConfigureWindow (screen->display->xdisplay,
|
||||
xwindow,
|
||||
window->x11.xwindow,
|
||||
CWSibling | CWStackMode,
|
||||
&changes);
|
||||
meta_error_trap_pop (screen->display);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
--i;
|
||||
}
|
||||
|
||||
if (i < 0)
|
||||
else
|
||||
{
|
||||
/* No sibling to use, just lower ourselves to the bottom
|
||||
* to be sure we're below any override redirect windows.
|
||||
*/
|
||||
meta_error_trap_push (screen->display);
|
||||
meta_stack_tracker_record_lower (screen->stack_tracker,
|
||||
xwindow,
|
||||
XNextRequest (screen->display->xdisplay));
|
||||
XLowerWindow (screen->display->xdisplay,
|
||||
xwindow);
|
||||
window->x11.xwindow);
|
||||
meta_error_trap_pop (screen->display);
|
||||
}
|
||||
}
|
||||
|
||||
meta_stack_tracker_record_raise_above (screen->stack_tracker,
|
||||
window,
|
||||
sibling,
|
||||
serial);
|
||||
}
|
||||
|
||||
/**
|
||||
* stack_sync_to_server:
|
||||
*
|
||||
@@ -1143,13 +1238,16 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
|
||||
* job of computing the minimal set of stacking requests needed.
|
||||
*/
|
||||
static void
|
||||
stack_sync_to_server (MetaStack *stack)
|
||||
stack_sync_to_xserver (MetaStack *stack)
|
||||
{
|
||||
GArray *stacked;
|
||||
GArray *root_children_stacked;
|
||||
GArray *x11_stacked;
|
||||
GArray *x11_root_children_stacked;
|
||||
GArray *all_root_children_stacked; /* wayland OR x11 */
|
||||
GList *tmp;
|
||||
GArray *all_hidden;
|
||||
GArray *x11_hidden;
|
||||
GArray *x11_hidden_stack_windows;
|
||||
int n_override_redirect = 0;
|
||||
MetaStackWindow guard_stack_window;
|
||||
|
||||
/* Bail out if frozen */
|
||||
if (stack->freeze_count > 0)
|
||||
@@ -1164,13 +1262,17 @@ stack_sync_to_server (MetaStack *stack)
|
||||
* _NET hints, and "root_children_stacked" is in top-to-bottom
|
||||
* order for XRestackWindows()
|
||||
*/
|
||||
stacked = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
root_children_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
all_hidden = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
x11_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
|
||||
all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (MetaStackWindow));
|
||||
x11_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
|
||||
x11_hidden_stack_windows = g_array_new (FALSE, FALSE, sizeof (MetaStackWindow));
|
||||
x11_hidden = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
|
||||
/* The screen guard window sits above all hidden windows and acts as
|
||||
* a barrier to input reaching these windows. */
|
||||
g_array_append_val (all_hidden, stack->screen->guard_window);
|
||||
g_array_append_val (x11_hidden, stack->screen->guard_window);
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Top to bottom: ");
|
||||
meta_push_no_msg_prefix ();
|
||||
@@ -1179,6 +1281,9 @@ stack_sync_to_server (MetaStack *stack)
|
||||
{
|
||||
MetaWindow *w = tmp->data;
|
||||
Window top_level_window;
|
||||
MetaStackWindow stack_window;
|
||||
|
||||
stack_window.any.type = w->client_type;
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "%u:%d - %s ",
|
||||
w->layer, w->stack_position, w->desc);
|
||||
@@ -1187,60 +1292,82 @@ stack_sync_to_server (MetaStack *stack)
|
||||
if (w->override_redirect)
|
||||
n_override_redirect++;
|
||||
else
|
||||
g_array_prepend_val (stacked, w->xwindow);
|
||||
g_array_prepend_val (x11_stacked, w->xwindow);
|
||||
|
||||
if (w->frame)
|
||||
top_level_window = w->frame->xwindow;
|
||||
else
|
||||
top_level_window = w->xwindow;
|
||||
|
||||
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
stack_window.x11.xwindow = top_level_window;
|
||||
else
|
||||
stack_window.wayland.meta_window = w;
|
||||
|
||||
/* We don't restack hidden windows along with the rest, though they are
|
||||
* reflected in the _NET hints. Hidden windows all get pushed below
|
||||
* the screens fullscreen guard_window. */
|
||||
if (w->hidden)
|
||||
{
|
||||
g_array_append_val (all_hidden, top_level_window);
|
||||
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
MetaStackWindow stack_window;
|
||||
|
||||
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||
stack_window.x11.xwindow = top_level_window;
|
||||
|
||||
g_array_append_val (x11_hidden_stack_windows, stack_window);
|
||||
g_array_append_val (x11_hidden, top_level_window);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
g_array_append_val (all_root_children_stacked, stack_window);
|
||||
|
||||
/* build XRestackWindows() array from top to bottom */
|
||||
g_array_append_val (root_children_stacked, top_level_window);
|
||||
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
g_array_append_val (x11_root_children_stacked, top_level_window);
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "\n");
|
||||
meta_pop_no_msg_prefix ();
|
||||
|
||||
/* All windows should be in some stacking order */
|
||||
if (stacked->len != stack->windows->len - n_override_redirect)
|
||||
/* All X windows should be in some stacking order */
|
||||
if (x11_stacked->len != stack->xwindows->len - n_override_redirect)
|
||||
meta_bug ("%u windows stacked, %u windows exist in stack\n",
|
||||
stacked->len, stack->windows->len);
|
||||
x11_stacked->len, stack->xwindows->len);
|
||||
|
||||
/* Sync to server */
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Restacking %u windows\n",
|
||||
root_children_stacked->len);
|
||||
all_root_children_stacked->len);
|
||||
|
||||
meta_error_trap_push (stack->screen->display);
|
||||
|
||||
if (stack->last_root_children_stacked == NULL)
|
||||
if (stack->last_all_root_children_stacked == NULL)
|
||||
{
|
||||
/* Just impose our stack, we don't know the previous state.
|
||||
* This involves a ton of circulate requests and may flicker.
|
||||
*/
|
||||
meta_topic (META_DEBUG_STACK, "Don't know last stack state, restacking everything\n");
|
||||
|
||||
if (root_children_stacked->len > 0)
|
||||
if (all_root_children_stacked->len > 1)
|
||||
{
|
||||
meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
|
||||
(Window *) root_children_stacked->data,
|
||||
root_children_stacked->len,
|
||||
XNextRequest (stack->screen->display->xdisplay));
|
||||
gulong serial = 0;
|
||||
if (x11_root_children_stacked->len > 1)
|
||||
{
|
||||
serial = XNextRequest (stack->screen->display->xdisplay);
|
||||
XRestackWindows (stack->screen->display->xdisplay,
|
||||
(Window *) root_children_stacked->data,
|
||||
root_children_stacked->len);
|
||||
(Window *) x11_root_children_stacked->data,
|
||||
x11_root_children_stacked->len);
|
||||
}
|
||||
meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
|
||||
(MetaStackWindow *) all_root_children_stacked->data,
|
||||
all_root_children_stacked->len,
|
||||
serial);
|
||||
}
|
||||
}
|
||||
else if (root_children_stacked->len > 0)
|
||||
else if (all_root_children_stacked->len > 0)
|
||||
{
|
||||
/* Try to do minimal window moves to get the stack in order */
|
||||
/* A point of note: these arrays include frames not client windows,
|
||||
@@ -1248,28 +1375,34 @@ stack_sync_to_server (MetaStack *stack)
|
||||
* was saved, then we may have inefficiency, but I don't think things
|
||||
* break...
|
||||
*/
|
||||
const Window *old_stack = (Window *) stack->last_root_children_stacked->data;
|
||||
const Window *new_stack = (Window *) root_children_stacked->data;
|
||||
const int old_len = stack->last_root_children_stacked->len;
|
||||
const int new_len = root_children_stacked->len;
|
||||
const Window *oldp = old_stack;
|
||||
const Window *newp = new_stack;
|
||||
const Window *old_end = old_stack + old_len;
|
||||
const Window *new_end = new_stack + new_len;
|
||||
Window last_window = None;
|
||||
|
||||
const MetaStackWindow *old_stack = (MetaStackWindow *) stack->last_all_root_children_stacked->data;
|
||||
const MetaStackWindow *new_stack = (MetaStackWindow *) all_root_children_stacked->data;
|
||||
const int old_len = stack->last_all_root_children_stacked->len;
|
||||
const int new_len = all_root_children_stacked->len;
|
||||
const MetaStackWindow *oldp = old_stack;
|
||||
const MetaStackWindow *newp = new_stack;
|
||||
const MetaStackWindow *old_end = old_stack + old_len;
|
||||
const MetaStackWindow *new_end = new_stack + new_len;
|
||||
Window last_xwindow = None;
|
||||
const MetaStackWindow *last_window = NULL;
|
||||
|
||||
while (oldp != old_end &&
|
||||
newp != new_end)
|
||||
{
|
||||
if (*oldp == *newp)
|
||||
if (meta_stack_window_equal (oldp, newp))
|
||||
{
|
||||
/* Stacks are the same here, move on */
|
||||
++oldp;
|
||||
last_window = *newp;
|
||||
if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
last_xwindow = newp->x11.xwindow;
|
||||
last_window = newp;
|
||||
++newp;
|
||||
}
|
||||
else if (meta_display_lookup_x_window (stack->screen->display,
|
||||
*oldp) == NULL)
|
||||
else if ((oldp->any.type == META_WINDOW_CLIENT_TYPE_X11 &&
|
||||
meta_display_lookup_x_window (stack->screen->display,
|
||||
oldp->x11.xwindow) == NULL) ||
|
||||
(oldp->any.type == META_WINDOW_CLIENT_TYPE_WAYLAND &&
|
||||
oldp->wayland.meta_window == NULL))
|
||||
{
|
||||
/* *oldp is no longer known to us (probably destroyed),
|
||||
* so we can just skip it
|
||||
@@ -1278,75 +1411,161 @@ stack_sync_to_server (MetaStack *stack)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Move *newp below last_window */
|
||||
if (last_window == None)
|
||||
/* Move *newp below the last_window */
|
||||
if (!last_window)
|
||||
{
|
||||
meta_topic (META_DEBUG_STACK, "Using window 0x%lx as topmost (but leaving it in-place)\n", *newp);
|
||||
meta_topic (META_DEBUG_STACK, "Using window 0x%lx as topmost (but leaving it in-place)\n",
|
||||
newp->x11.xwindow);
|
||||
|
||||
raise_window_relative_to_managed_windows (stack->screen,
|
||||
*newp);
|
||||
raise_window_relative_to_managed_windows (stack->screen, newp);
|
||||
}
|
||||
else if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11 &&
|
||||
last_xwindow == None)
|
||||
{
|
||||
/* In this case we have an X window that we need to
|
||||
* put below a wayland window and this is the
|
||||
* topmost X window. */
|
||||
|
||||
/* In X terms (because this is the topmost X window)
|
||||
* we want to
|
||||
* raise_window_relative_to_managed_windows() to
|
||||
* ensure the X window is below override-redirect
|
||||
* pop-up windows.
|
||||
*
|
||||
* In Wayland terms we just want to ensure
|
||||
* newp is lowered below last_window (which
|
||||
* notably doesn't require an X request because we
|
||||
* know last_window isn't an X window).
|
||||
*/
|
||||
|
||||
raise_window_relative_to_managed_windows (stack->screen, newp);
|
||||
|
||||
meta_stack_tracker_record_lower_below (stack->screen->stack_tracker,
|
||||
newp, last_window,
|
||||
0); /* no x request serial */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This means that if last_window is dead, but not
|
||||
gulong serial = 0;
|
||||
|
||||
/* This means that if last_xwindow is dead, but not
|
||||
* *newp, then we fail to restack *newp; but on
|
||||
* unmanaging last_window, we'll fix it up.
|
||||
* unmanaging last_xwindow, we'll fix it up.
|
||||
*/
|
||||
|
||||
XWindowChanges changes;
|
||||
meta_topic (META_DEBUG_STACK, "Placing window 0x%lx below 0x%lx\n",
|
||||
newp->any.type == META_WINDOW_CLIENT_TYPE_X11 ? newp->x11.xwindow : 0,
|
||||
last_xwindow);
|
||||
|
||||
changes.sibling = last_window;
|
||||
if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
XWindowChanges changes;
|
||||
serial = XNextRequest (stack->screen->display->xdisplay);
|
||||
|
||||
changes.sibling = last_xwindow;
|
||||
changes.stack_mode = Below;
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Placing window 0x%lx below 0x%lx\n",
|
||||
*newp, last_window);
|
||||
|
||||
meta_stack_tracker_record_lower_below (stack->screen->stack_tracker,
|
||||
*newp, last_window,
|
||||
XNextRequest (stack->screen->display->xdisplay));
|
||||
XConfigureWindow (stack->screen->display->xdisplay,
|
||||
*newp,
|
||||
newp->x11.xwindow,
|
||||
CWSibling | CWStackMode,
|
||||
&changes);
|
||||
}
|
||||
|
||||
last_window = *newp;
|
||||
meta_stack_tracker_record_lower_below (stack->screen->stack_tracker,
|
||||
newp, last_window,
|
||||
serial);
|
||||
}
|
||||
|
||||
if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
last_xwindow = newp->x11.xwindow;
|
||||
last_window = newp;
|
||||
++newp;
|
||||
}
|
||||
}
|
||||
|
||||
if (newp != new_end)
|
||||
{
|
||||
const MetaStackWindow *x_ref;
|
||||
unsigned long serial = 0;
|
||||
|
||||
/* Restack remaining windows */
|
||||
meta_topic (META_DEBUG_STACK, "Restacking remaining %d windows\n",
|
||||
(int) (new_end - newp));
|
||||
|
||||
/* rewind until we find the last stacked X window that we can use
|
||||
* as a reference point for re-stacking remaining X windows */
|
||||
if (newp != new_stack)
|
||||
for (x_ref = newp - 1;
|
||||
x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11 && x_ref > new_stack;
|
||||
x_ref--)
|
||||
;
|
||||
else
|
||||
x_ref = new_stack;
|
||||
|
||||
/* If we didn't find an X window looking backwards then walk forwards
|
||||
* through the remaining windows to find the first remaining X window
|
||||
* instead. */
|
||||
if (x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
for (x_ref = newp;
|
||||
x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11 && x_ref > new_stack;
|
||||
x_ref++)
|
||||
;
|
||||
}
|
||||
|
||||
/* If there are any X windows remaining unstacked then restack them */
|
||||
if (x_ref->any.type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = x11_root_children_stacked->len - 1; i; i--)
|
||||
{
|
||||
Window *reference = &g_array_index (x11_root_children_stacked, Window, i);
|
||||
|
||||
if (*reference == x_ref->x11.xwindow)
|
||||
{
|
||||
int n = x11_root_children_stacked->len - i;
|
||||
|
||||
/* There's no point restacking if there's only one X window */
|
||||
if (n == 1)
|
||||
break;
|
||||
|
||||
serial = XNextRequest (stack->screen->display->xdisplay);
|
||||
XRestackWindows (stack->screen->display->xdisplay,
|
||||
reference, n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We need to include an already-stacked window
|
||||
* in the restack call, so we get in the proper position
|
||||
* with respect to it.
|
||||
*/
|
||||
if (newp != new_stack)
|
||||
--newp;
|
||||
newp = MIN (newp - 1, x_ref);
|
||||
meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
|
||||
(Window *) newp, new_end - newp,
|
||||
XNextRequest (stack->screen->display->xdisplay));
|
||||
XRestackWindows (stack->screen->display->xdisplay,
|
||||
(Window *) newp, new_end - newp);
|
||||
newp, new_end - newp,
|
||||
serial);
|
||||
}
|
||||
}
|
||||
|
||||
/* Push hidden windows to the bottom of the stack under the guard window */
|
||||
/* Push hidden X windows to the bottom of the stack under the guard window */
|
||||
guard_stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||
guard_stack_window.x11.xwindow = stack->screen->guard_window;
|
||||
meta_stack_tracker_record_lower (stack->screen->stack_tracker,
|
||||
stack->screen->guard_window,
|
||||
&guard_stack_window,
|
||||
XNextRequest (stack->screen->display->xdisplay));
|
||||
XLowerWindow (stack->screen->display->xdisplay, stack->screen->guard_window);
|
||||
meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
|
||||
(Window *)all_hidden->data,
|
||||
all_hidden->len,
|
||||
(MetaStackWindow *)x11_hidden_stack_windows->data,
|
||||
x11_hidden_stack_windows->len,
|
||||
XNextRequest (stack->screen->display->xdisplay));
|
||||
XRestackWindows (stack->screen->display->xdisplay,
|
||||
(Window *)all_hidden->data,
|
||||
all_hidden->len);
|
||||
g_array_free (all_hidden, TRUE);
|
||||
(Window *)x11_hidden->data,
|
||||
x11_hidden->len);
|
||||
g_array_free (x11_hidden, TRUE);
|
||||
g_array_free (x11_hidden_stack_windows, TRUE);
|
||||
|
||||
meta_error_trap_pop (stack->screen->display);
|
||||
/* on error, a window was destroyed; it should eventually
|
||||
@@ -1361,21 +1580,23 @@ stack_sync_to_server (MetaStack *stack)
|
||||
stack->screen->display->atom__NET_CLIENT_LIST,
|
||||
XA_WINDOW,
|
||||
32, PropModeReplace,
|
||||
(unsigned char *)stack->windows->data,
|
||||
stack->windows->len);
|
||||
(unsigned char *)stack->xwindows->data,
|
||||
stack->xwindows->len);
|
||||
XChangeProperty (stack->screen->display->xdisplay,
|
||||
stack->screen->xroot,
|
||||
stack->screen->display->atom__NET_CLIENT_LIST_STACKING,
|
||||
XA_WINDOW,
|
||||
32, PropModeReplace,
|
||||
(unsigned char *)stacked->data,
|
||||
stacked->len);
|
||||
(unsigned char *)x11_stacked->data,
|
||||
x11_stacked->len);
|
||||
|
||||
g_array_free (stacked, TRUE);
|
||||
g_array_free (x11_stacked, TRUE);
|
||||
|
||||
if (stack->last_root_children_stacked)
|
||||
g_array_free (stack->last_root_children_stacked, TRUE);
|
||||
stack->last_root_children_stacked = root_children_stacked;
|
||||
if (stack->last_all_root_children_stacked)
|
||||
free_last_all_root_children_stacked_cache (stack);
|
||||
stack->last_all_root_children_stacked = all_root_children_stacked;
|
||||
|
||||
g_array_free (x11_root_children_stacked, TRUE);
|
||||
|
||||
/* That was scary... */
|
||||
}
|
||||
@@ -1486,8 +1707,8 @@ get_default_focus_window (MetaStack *stack,
|
||||
MetaWindow *topmost_in_group;
|
||||
MetaWindow *topmost_overall;
|
||||
MetaGroup *not_this_one_group;
|
||||
GList *link;
|
||||
|
||||
GList *l;
|
||||
|
||||
transient_parent = NULL;
|
||||
topmost_in_group = NULL;
|
||||
topmost_overall = NULL;
|
||||
@@ -1499,49 +1720,49 @@ get_default_focus_window (MetaStack *stack,
|
||||
stack_ensure_sorted (stack);
|
||||
|
||||
/* top of this layer is at the front of the list */
|
||||
link = stack->sorted;
|
||||
|
||||
while (link)
|
||||
for (l = stack->sorted; l != NULL; l = l->next)
|
||||
{
|
||||
MetaWindow *window = link->data;
|
||||
MetaWindow *window = l->data;
|
||||
|
||||
if (window &&
|
||||
window != not_this_one &&
|
||||
(window->unmaps_pending == 0) &&
|
||||
!window->minimized &&
|
||||
(window->input || window->take_focus) &&
|
||||
(workspace == NULL ||
|
||||
meta_window_located_on_workspace (window, workspace)))
|
||||
if (!window)
|
||||
continue;
|
||||
|
||||
if (window == not_this_one)
|
||||
continue;
|
||||
|
||||
if (window->unmaps_pending > 0)
|
||||
continue;
|
||||
|
||||
if (window->minimized)
|
||||
continue;
|
||||
|
||||
if (!(window->input || window->take_focus))
|
||||
continue;
|
||||
|
||||
if (workspace != NULL && !meta_window_located_on_workspace (window, workspace))
|
||||
continue;
|
||||
|
||||
if (must_be_at_point && !window_contains_point (window, root_x, root_y))
|
||||
continue;
|
||||
|
||||
if (not_this_one != NULL)
|
||||
{
|
||||
if (not_this_one != NULL)
|
||||
{
|
||||
if (transient_parent == NULL &&
|
||||
not_this_one->xtransient_for != None &&
|
||||
not_this_one->xtransient_for == window->xwindow &&
|
||||
(!must_be_at_point ||
|
||||
window_contains_point (window, root_x, root_y)))
|
||||
transient_parent = window;
|
||||
if (transient_parent == NULL &&
|
||||
meta_window_get_transient_for (not_this_one) == window)
|
||||
transient_parent = window;
|
||||
|
||||
if (topmost_in_group == NULL &&
|
||||
not_this_one_group != NULL &&
|
||||
not_this_one_group == meta_window_get_group (window) &&
|
||||
(!must_be_at_point ||
|
||||
window_contains_point (window, root_x, root_y)))
|
||||
topmost_in_group = window;
|
||||
}
|
||||
|
||||
if (topmost_overall == NULL &&
|
||||
window->type != META_WINDOW_DOCK &&
|
||||
(!must_be_at_point ||
|
||||
window_contains_point (window, root_x, root_y)))
|
||||
topmost_overall = window;
|
||||
|
||||
/* We could try to bail out early here for efficiency in
|
||||
* some cases, but it's just not worth the code.
|
||||
*/
|
||||
if (topmost_in_group == NULL &&
|
||||
not_this_one_group != NULL &&
|
||||
not_this_one_group == meta_window_get_group (window))
|
||||
topmost_in_group = window;
|
||||
}
|
||||
|
||||
link = link->next;
|
||||
if (topmost_overall == NULL && window->type != META_WINDOW_DOCK)
|
||||
topmost_overall = window;
|
||||
|
||||
/* We could try to bail out early here for efficiency in
|
||||
* some cases, but it's just not worth the code.
|
||||
*/
|
||||
}
|
||||
|
||||
if (transient_parent)
|
||||
@@ -1726,7 +1947,7 @@ meta_stack_set_positions (MetaStack *stack,
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Reset the stack positions of (nearly) all windows\n");
|
||||
|
||||
stack_sync_to_server (stack);
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_update_window_tile_matches (stack, NULL);
|
||||
}
|
||||
|
||||
@@ -1789,7 +2010,7 @@ meta_window_set_stack_position (MetaWindow *window,
|
||||
int position)
|
||||
{
|
||||
meta_window_set_stack_position_no_sync (window, position);
|
||||
stack_sync_to_server (window->screen->stack);
|
||||
stack_sync_to_xserver (window->screen->stack);
|
||||
meta_stack_update_window_tile_matches (window->screen->stack,
|
||||
window->screen->active_workspace);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ struct _MetaStack
|
||||
* A sequence of all the Windows (X handles, not MetaWindows) of the windows
|
||||
* we manage, sorted in order. Suitable to be passed into _NET_CLIENT_LIST.
|
||||
*/
|
||||
GArray *windows;
|
||||
GArray *xwindows;
|
||||
|
||||
/** The MetaWindows of the windows we manage, sorted in order. */
|
||||
GList *sorted;
|
||||
@@ -97,7 +97,7 @@ struct _MetaStack
|
||||
* The last-known stack of all windows, bottom to top. We cache it here
|
||||
* so that subsequent times we'll be able to do incremental moves.
|
||||
*/
|
||||
GArray *last_root_children_stacked;
|
||||
GArray *last_all_root_children_stacked;
|
||||
|
||||
/**
|
||||
* Number of stack positions; same as the length of added, but
|
||||
|
||||
@@ -32,5 +32,6 @@ void meta_set_verbose (gboolean setting);
|
||||
void meta_set_debugging (gboolean setting);
|
||||
void meta_set_syncing (gboolean setting);
|
||||
void meta_set_replace_current_wm (gboolean setting);
|
||||
void meta_set_is_wayland_compositor (gboolean setting);
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user