Compare commits
552 Commits
2.27.3
...
configurab
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a4cfde4e2 | ||
|
|
c853d197e3 | ||
|
|
bf7ae3e4d3 | ||
|
|
2b21f1d48c | ||
|
|
4c91e05b86 | ||
|
|
bc91c328f3 | ||
|
|
5bbbac65d6 | ||
|
|
a0a0fc14d7 | ||
|
|
cc9efe1289 | ||
|
|
8825ded1ca | ||
|
|
b823ef0007 | ||
|
|
a846434bcf | ||
|
|
825fc2c0c8 | ||
|
|
4fbe547f16 | ||
|
|
fc2ba0afbe | ||
|
|
3e7d2df6f3 | ||
|
|
02e709e89e | ||
|
|
1114e5effa | ||
|
|
c40fab214d | ||
|
|
441c050808 | ||
|
|
85425f64a5 | ||
|
|
b445ee3763 | ||
|
|
95a7f0269a | ||
|
|
db63764e22 | ||
|
|
03578b69f3 | ||
|
|
8cbaee47a0 | ||
|
|
bcded5ae25 | ||
|
|
7227b636c6 | ||
|
|
af715f71e7 | ||
|
|
52bc675fcb | ||
|
|
1920f211b0 | ||
|
|
804117c456 | ||
|
|
9a4d1686a6 | ||
|
|
e8dda03441 | ||
|
|
4b214b4710 | ||
|
|
6ed34976c9 | ||
|
|
069092eb9d | ||
|
|
dc7d323295 | ||
|
|
cbedfd680f | ||
|
|
a1e2e2a13d | ||
|
|
a53a40c43e | ||
|
|
33489c8cb8 | ||
|
|
c382d8f7ea | ||
|
|
f2ccf70f8d | ||
|
|
ff04e38326 | ||
|
|
1123fca3f2 | ||
|
|
33e2d15495 | ||
|
|
b265e8099a | ||
|
|
a2b3f9aeb0 | ||
|
|
d19295a68e | ||
|
|
9f5d8d1a2a | ||
|
|
e75abacec6 | ||
|
|
1c31e8ffc2 | ||
|
|
1083a4c0b7 | ||
|
|
d212be799a | ||
|
|
84986c7695 | ||
|
|
aa65f94c67 | ||
|
|
dc80242e51 | ||
|
|
f2c63e5eec | ||
|
|
1fc91dc459 | ||
|
|
a2e4789b3e | ||
|
|
7d58524185 | ||
|
|
635e20d057 | ||
|
|
1c3f7c4088 | ||
|
|
5c3b0cda2e | ||
|
|
a3c6486e52 | ||
|
|
741d2b761a | ||
|
|
a0ffe71db3 | ||
|
|
ecf812db83 | ||
|
|
afd3b96e2e | ||
|
|
b79e6c0b3e | ||
|
|
c6f8ad24bd | ||
|
|
d4d05e496a | ||
|
|
0a88329526 | ||
|
|
b4344b5ab5 | ||
|
|
4ac836fde4 | ||
|
|
7897448a5b | ||
|
|
94f4011844 | ||
|
|
3f8e6020f7 | ||
|
|
beb65f011d | ||
|
|
c2f894963a | ||
|
|
dacea8edf9 | ||
|
|
3fed2ab64d | ||
|
|
476652da0a | ||
|
|
35289050e4 | ||
|
|
ed9d7f18a6 | ||
|
|
a7d1053ff5 | ||
|
|
97e2b4666b | ||
|
|
7d8cc4f940 | ||
|
|
ee2f995fc7 | ||
|
|
7e852f8c14 | ||
|
|
b4c1692d14 | ||
|
|
c0858b247f | ||
|
|
0a956f56aa | ||
|
|
66105c6e7e | ||
|
|
bb1ab0afd9 | ||
|
|
0d51d9e4cf | ||
|
|
e3789e31ef | ||
|
|
8a6b583cdc | ||
|
|
86b8b9051f | ||
|
|
4c0763792d | ||
|
|
599eb5e3e4 | ||
|
|
31fe25aa78 | ||
|
|
252657905f | ||
|
|
77a5e817a5 | ||
|
|
2521e8103d | ||
|
|
47fcb998f5 | ||
|
|
455c40677b | ||
|
|
9ae8e4c006 | ||
|
|
d514516543 | ||
|
|
1024eae742 | ||
|
|
dad1f01c5b | ||
|
|
ce53f35974 | ||
|
|
3d19e800ab | ||
|
|
2a54baf60e | ||
|
|
4544fe7571 | ||
|
|
a125b0179a | ||
|
|
6b69acdf8b | ||
|
|
8c11a2e5a3 | ||
|
|
693c2bc175 | ||
|
|
8b34b4bd0b | ||
|
|
8cce57ba44 | ||
|
|
63f81ed027 | ||
|
|
c9ebc0ea25 | ||
|
|
15a214e435 | ||
|
|
0b3327f04d | ||
|
|
0839c100c0 | ||
|
|
08cfdcd802 | ||
|
|
a1bb3835cc | ||
|
|
e590cd2b99 | ||
|
|
77b620e50e | ||
|
|
9bc723d256 | ||
|
|
b9f9a230e6 | ||
|
|
ce1ffa4624 | ||
|
|
17aa36d343 | ||
|
|
cc0965f9f9 | ||
|
|
0e728d7751 | ||
|
|
3e6cf75d73 | ||
|
|
bbedba8b18 | ||
|
|
c8d756dde3 | ||
|
|
97a8dbb71e | ||
|
|
6835804dab | ||
|
|
1a2a374380 | ||
|
|
2b84afc1e3 | ||
|
|
bb3d23f7f6 | ||
|
|
7511ea27e2 | ||
|
|
adbe3a2312 | ||
|
|
eda50a91df | ||
|
|
7853bb8042 | ||
|
|
37de1b2d25 | ||
|
|
0c4ac0b48a | ||
|
|
c24cf44c6a | ||
|
|
11a8ab47fa | ||
|
|
7feeb72721 | ||
|
|
01447d94d1 | ||
|
|
e267a63330 | ||
|
|
c65a24486d | ||
|
|
42e786b15b | ||
|
|
7a04673dd7 | ||
|
|
c47d2da0cb | ||
|
|
fd12eddb5d | ||
|
|
0b56599d28 | ||
|
|
27de94b915 | ||
|
|
9e31f2b1de | ||
|
|
13ad103823 | ||
|
|
ff5a73de49 | ||
|
|
275a6ec63f | ||
|
|
604da0f6ea | ||
|
|
72a19dd448 | ||
|
|
3a73f6b8ec | ||
|
|
343474a570 | ||
|
|
91d82bf8c7 | ||
|
|
ed19060074 | ||
|
|
f230a67b94 | ||
|
|
849f101feb | ||
|
|
f45083ce82 | ||
|
|
4c143ae9af | ||
|
|
cd1a1d5778 | ||
|
|
e28e7a72aa | ||
|
|
fc9488211f | ||
|
|
28767c4d34 | ||
|
|
c6c7b05d7b | ||
|
|
5526e91b6e | ||
|
|
9e123695d0 | ||
|
|
092cc47afc | ||
|
|
fd20059f68 | ||
|
|
609aae684f | ||
|
|
49940877d1 | ||
|
|
22ae86104b | ||
|
|
f8dd4c160b | ||
|
|
11061a23b1 | ||
|
|
d8b0f213b2 | ||
|
|
e9fbe4b2c1 | ||
|
|
edcb351107 | ||
|
|
0c14640352 | ||
|
|
cfa30f9876 | ||
|
|
af60dd3634 | ||
|
|
ccabce1b34 | ||
|
|
9915a18810 | ||
|
|
a78373f324 | ||
|
|
1d7476a725 | ||
|
|
e8e78ebfdd | ||
|
|
b77b0a3d81 | ||
|
|
95b260f3a9 | ||
|
|
97a9726845 | ||
|
|
020aea033c | ||
|
|
0ac46316af | ||
|
|
94d47dc25e | ||
|
|
debf08cac0 | ||
|
|
ce1393d2d4 | ||
|
|
fac482c442 | ||
|
|
ee35540b6e | ||
|
|
f77507e825 | ||
|
|
0021efd593 | ||
|
|
0d955bb873 | ||
|
|
7fa2e8d2d3 | ||
|
|
713d94d881 | ||
|
|
4ecf8964b8 | ||
|
|
11d044fa6e | ||
|
|
a2104c5404 | ||
|
|
1abed05413 | ||
|
|
1465895ff7 | ||
|
|
452025e984 | ||
|
|
d537dd93d5 | ||
|
|
650a1e807c | ||
|
|
67f8a33cad | ||
|
|
ff4f096f1d | ||
|
|
b5cb353ab5 | ||
|
|
17a38dfbed | ||
|
|
f773683601 | ||
|
|
abeaf828a3 | ||
|
|
23a8a4201a | ||
|
|
2d409e5c09 | ||
|
|
2d57904bf4 | ||
|
|
8fa83e1be7 | ||
|
|
8875e73765 | ||
|
|
65766fcaac | ||
|
|
4cd4010a70 | ||
|
|
d21da5643b | ||
|
|
ba700e6387 | ||
|
|
bd90fd7033 | ||
|
|
fb3d352d3a | ||
|
|
690852e157 | ||
|
|
aa84d21bcf | ||
|
|
4d62977c7b | ||
|
|
cbac2e7bbb | ||
|
|
88ee4c5b30 | ||
|
|
12c46c5d8b | ||
|
|
ab7d4e0e60 | ||
|
|
708c6162c4 | ||
|
|
7834bba6f7 | ||
|
|
857c8aaaa2 | ||
|
|
1253e6c64e | ||
|
|
b610b2ecc7 | ||
|
|
11addbe9c8 | ||
|
|
709ef05714 | ||
|
|
c51767eef1 | ||
|
|
5aab9e878f | ||
|
|
e7751e170e | ||
|
|
776d345bc3 | ||
|
|
a8fc30a13f | ||
|
|
2d57b1b470 | ||
|
|
90f21fa5db | ||
|
|
6638d0e507 | ||
|
|
c6793d477a | ||
|
|
11e01ec074 | ||
|
|
1d827caaaf | ||
|
|
ba4db78ed9 | ||
|
|
a321f4c842 | ||
|
|
b1c465eab0 | ||
|
|
5134b05af9 | ||
|
|
dc3a93be99 | ||
|
|
49aabfec02 | ||
|
|
11d0d207fd | ||
|
|
eed3245b1b | ||
|
|
a7bbde1699 | ||
|
|
bacccafe3c | ||
|
|
3a80bd47cc | ||
|
|
152917d5e1 | ||
|
|
c588e173f8 | ||
|
|
c0d2ead351 | ||
|
|
6ffe5f8343 | ||
|
|
2a823ef3e4 | ||
|
|
5159c3f3ca | ||
|
|
d092924961 | ||
|
|
e14132b826 | ||
|
|
df36ff638e | ||
|
|
ad1fee8233 | ||
|
|
3883d511a9 | ||
|
|
10803b0d25 | ||
|
|
a570a57863 | ||
|
|
a7590f9717 | ||
|
|
35224ca8d4 | ||
|
|
40563e4f84 | ||
|
|
c30901e9be | ||
|
|
4fc0a91b31 | ||
|
|
576417648a | ||
|
|
0aace5230f | ||
|
|
8d5ba7a6d7 | ||
|
|
f8153b84de | ||
|
|
fac5b0c9e7 | ||
|
|
eb06413188 | ||
|
|
066c870271 | ||
|
|
1a92fa788d | ||
|
|
3a0ab1cc0c | ||
|
|
8a7d588bb0 | ||
|
|
4943d79d68 | ||
|
|
5de10c34b7 | ||
|
|
2fbe4c2388 | ||
|
|
767cb27f78 | ||
|
|
b8c75c3fc0 | ||
|
|
edeadf62ef | ||
|
|
5ac80057c4 | ||
|
|
210e30556e | ||
|
|
0487b4213f | ||
|
|
8f29c14ac4 | ||
|
|
9543d8be10 | ||
|
|
43e0003e79 | ||
|
|
30e63a7244 | ||
|
|
575f520461 | ||
|
|
df618c9e91 | ||
|
|
ebd13a4bae | ||
|
|
7aa54b5a23 | ||
|
|
b20cb36f5d | ||
|
|
86f8c1863e | ||
|
|
19d85c8566 | ||
|
|
4241f91a0a | ||
|
|
05624f099a | ||
|
|
920f4099b6 | ||
|
|
aa26750e01 | ||
|
|
bdb3be7084 | ||
|
|
14987f2b21 | ||
|
|
47af6a0bbf | ||
|
|
1487578ff4 | ||
|
|
5a03a5d578 | ||
|
|
2dd137329d | ||
|
|
db37deb589 | ||
|
|
ec7a3c516d | ||
|
|
988d2ffab6 | ||
|
|
5e2c66e241 | ||
|
|
0ccfb0d781 | ||
|
|
01ce961c00 | ||
|
|
7579b691df | ||
|
|
2a14deab0c | ||
|
|
1acefb9eac | ||
|
|
fb45b8f45c | ||
|
|
d59a9c2e8a | ||
|
|
a1c3d8723d | ||
|
|
c4bd65e97c | ||
|
|
eac3a2d7ac | ||
|
|
55bb584778 | ||
|
|
4584943531 | ||
|
|
55d2bc0e0b | ||
|
|
c0cc2fa1b8 | ||
|
|
c1ecbd4de1 | ||
|
|
0fb6b8a8ff | ||
|
|
78ba9adfed | ||
|
|
3f642ea34f | ||
|
|
1a3927b40c | ||
|
|
b09d73ab68 | ||
|
|
9311addca3 | ||
|
|
3c76478510 | ||
|
|
545551e2bc | ||
|
|
d5e0a95ff1 | ||
|
|
e811109566 | ||
|
|
0f805bfdfb | ||
|
|
200cd629df | ||
|
|
e8a29c1e82 | ||
|
|
8589e4f3d3 | ||
|
|
948e54772d | ||
|
|
2d4b05a71b | ||
|
|
a6433e84f5 | ||
|
|
083854e2de | ||
|
|
3508c4aa87 | ||
|
|
d04b15ee25 | ||
|
|
d6143e4c73 | ||
|
|
d8ffc3c187 | ||
|
|
2af788956e | ||
|
|
d399141d13 | ||
|
|
f6f899f103 | ||
|
|
5b8919a246 | ||
|
|
fe1989979c | ||
|
|
0895fa9331 | ||
|
|
b90fe0c52a | ||
|
|
ab0e22159c | ||
|
|
6ac0afbce0 | ||
|
|
9532527e52 | ||
|
|
defdf9f34c | ||
|
|
a7dce2dc4e | ||
|
|
ea8c51f8f3 | ||
|
|
1e66878447 | ||
|
|
6cfbdebf6a | ||
|
|
a4469dcc14 | ||
|
|
ac3eac7154 | ||
|
|
65ac9065fa | ||
|
|
5143e6763b | ||
|
|
5660a8e9f5 | ||
|
|
bc2b17df0b | ||
|
|
f9e7c95348 | ||
|
|
c6afec4759 | ||
|
|
eb13498fff | ||
|
|
163057f521 | ||
|
|
d8ff1f9873 | ||
|
|
97b7760de8 | ||
|
|
acca0f6946 | ||
|
|
f3f6d67d46 | ||
|
|
63773d5226 | ||
|
|
4e4559fc8c | ||
|
|
44d540d36c | ||
|
|
c6253a6515 | ||
|
|
65a5ec2ef3 | ||
|
|
70e8b35944 | ||
|
|
ddba25a674 | ||
|
|
14e6cb6a8f | ||
|
|
d4619150f3 | ||
|
|
5c1a1a2dd5 | ||
|
|
7cfa690aaf | ||
|
|
8d663ff055 | ||
|
|
0b86343dd0 | ||
|
|
e127898312 | ||
|
|
51f83f25e6 | ||
|
|
8f3da9f68a | ||
|
|
4c1998f137 | ||
|
|
84dc1c1b85 | ||
|
|
326110e38d | ||
|
|
f63b81c52a | ||
|
|
bd2e221da3 | ||
|
|
1fe673703f | ||
|
|
c10467d22e | ||
|
|
e21ec0a271 | ||
|
|
3a1e492afc | ||
|
|
e83c24c91b | ||
|
|
81183c71c1 | ||
|
|
979298ce57 | ||
|
|
66e727e1b2 | ||
|
|
35b1dda3a3 | ||
|
|
6925779f59 | ||
|
|
125d7daf4a | ||
|
|
57c5ea4bd5 | ||
|
|
e75fbdb136 | ||
|
|
cb1020b26d | ||
|
|
e1945506f3 | ||
|
|
3a798112f2 | ||
|
|
c5dd3e5542 | ||
|
|
2fa9cbfd9e | ||
|
|
23af4ee93e | ||
|
|
0317562605 | ||
|
|
1861e0b2cc | ||
|
|
e5974809e8 | ||
|
|
abfae17b9a | ||
|
|
84b1a62ad2 | ||
|
|
b6bcaec9bc | ||
|
|
f19ed84cc4 | ||
|
|
6c5a946fda | ||
|
|
c6ffc9427e | ||
|
|
0f1e64f3b2 | ||
|
|
1ce5ad3003 | ||
|
|
64694955c0 | ||
|
|
97a90d8122 | ||
|
|
3cd2c08277 | ||
|
|
c37a2ca1c8 | ||
|
|
80b38210b2 | ||
|
|
e5dffb0097 | ||
|
|
deaa897928 | ||
|
|
3f9758e706 | ||
|
|
3c25c265df | ||
|
|
a8529bd8d1 | ||
|
|
ba03ca76c4 | ||
|
|
71fd54ec9e | ||
|
|
a03343827e | ||
|
|
4fb7c642d5 | ||
|
|
8a892d47e5 | ||
|
|
73abacc20b | ||
|
|
aea24279ba | ||
|
|
5c5968e742 | ||
|
|
3813ed9c2e | ||
|
|
594897e9a5 | ||
|
|
40e9f6fa2c | ||
|
|
35afd2a8fb | ||
|
|
d9be1d7e32 | ||
|
|
b625ec30d9 | ||
|
|
f5313268d7 | ||
|
|
07dedee37b | ||
|
|
75f3127ba5 | ||
|
|
b13fae2556 | ||
|
|
2e9838699b | ||
|
|
ba9c3f41c9 | ||
|
|
e35fae8f32 | ||
|
|
b0d5f3bd64 | ||
|
|
ed640bb181 | ||
|
|
a3511ba9e2 | ||
|
|
4c9c903648 | ||
|
|
d12aaddc34 | ||
|
|
28955bb449 | ||
|
|
dcd7cae7cf | ||
|
|
c954bb9456 | ||
|
|
be0b298d81 | ||
|
|
409026044b | ||
|
|
0c311bdcf9 | ||
|
|
e81775e63d | ||
|
|
209d7ef613 | ||
|
|
a6c76a85ce | ||
|
|
265f9e5433 | ||
|
|
b86d988b3c | ||
|
|
c4148cec33 | ||
|
|
aa57becc41 | ||
|
|
7269c37c8f | ||
|
|
3093d7e95a | ||
|
|
4e0d8a0cbb | ||
|
|
523151ddf0 | ||
|
|
0a7cb94ea8 | ||
|
|
d4b7c0e633 | ||
|
|
3f76affbd2 | ||
|
|
a8f8970601 | ||
|
|
178b5ff626 | ||
|
|
c47f7c2806 | ||
|
|
ab6aa5463f | ||
|
|
42387bff6f | ||
|
|
3afd25691a | ||
|
|
a6a963bec1 | ||
|
|
d6ac4dc22a | ||
|
|
0b3f45bb1b | ||
|
|
24f2df926a | ||
|
|
f00e8655ac | ||
|
|
41395d9e00 | ||
|
|
3e00bcbf9f | ||
|
|
0b402b23f7 | ||
|
|
691fcaeee7 | ||
|
|
9f30910653 | ||
|
|
41a6c2e501 | ||
|
|
fbc7fc6645 | ||
|
|
573dbb431e | ||
|
|
7b2cba7a6c | ||
|
|
91ff5617ef | ||
|
|
f1782868f9 | ||
|
|
66ee22c3e6 | ||
|
|
2db1222e45 | ||
|
|
abbd057eb9 | ||
|
|
6da5b8ccc5 | ||
|
|
128e2b917d | ||
|
|
2f4173b267 | ||
|
|
3fea1e4df5 | ||
|
|
13d2552274 | ||
|
|
3d0bfbb4f4 | ||
|
|
b893e88e8b | ||
|
|
f2be9e4381 | ||
|
|
53b5d6d167 | ||
|
|
92bfe34716 | ||
|
|
5df096baf3 | ||
|
|
45cbaa2d13 | ||
|
|
720a17acd7 | ||
|
|
dab00ab036 |
31
.gitignore
vendored
31
.gitignore
vendored
@@ -13,17 +13,22 @@ config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
intltool-extract.in
|
||||
intltool-merge.in
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
.deps
|
||||
src/metacity-wm.desktop
|
||||
src/mutter-wm.desktop
|
||||
src/mutter.desktop
|
||||
*.o
|
||||
*.a
|
||||
*.lo
|
||||
*.la
|
||||
.libs
|
||||
*.swp
|
||||
*.gir
|
||||
*.typelib
|
||||
tidy-enum-types.[ch]
|
||||
tidy-marshal.[ch]
|
||||
stamp-tidy-enum-types.h
|
||||
@@ -38,19 +43,18 @@ POTFILES
|
||||
50-metacity-desktop-key.xml
|
||||
50-metacity-key.xml
|
||||
inlinepixbufs.h
|
||||
libmetacity-private.pc
|
||||
metacity
|
||||
metacity-dialog
|
||||
metacity-theme-viewer
|
||||
metacity.desktop
|
||||
metacity.schemas
|
||||
libmutter-private.pc
|
||||
mutter
|
||||
mutter-theme-viewer
|
||||
mutter.desktop
|
||||
mutter.schemas
|
||||
testasyncgetprop
|
||||
testboxes
|
||||
testgradient
|
||||
metacity-grayscale
|
||||
metacity-mag
|
||||
metacity-message
|
||||
metacity-window-demo
|
||||
mutter-grayscale
|
||||
mutter-mag
|
||||
mutter-message
|
||||
mutter-window-demo
|
||||
focus-window
|
||||
test-gravity
|
||||
test-resizing
|
||||
@@ -58,3 +62,8 @@ test-size-hints
|
||||
wm-tester
|
||||
INSTALL
|
||||
mkinstalldirs
|
||||
src/mutter-enum-types.[ch]
|
||||
src/stamp-mutter-enum-types.h
|
||||
src/mutter-marshal.[ch]
|
||||
src/stamp-mutter-marshal.h
|
||||
src/mutter-plugins.pc
|
||||
|
||||
165
configure.in
165
configure.in
@@ -1,15 +1,13 @@
|
||||
AC_PREREQ(2.50)
|
||||
|
||||
m4_define([mutter_major_version], [2])
|
||||
m4_define([mutter_minor_version], [27])
|
||||
# Fibonacci sequence for micro version numbering:
|
||||
# 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987
|
||||
m4_define([mutter_micro_version], [3])
|
||||
m4_define([mutter_minor_version], [91])
|
||||
m4_define([mutter_micro_version], [2])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
|
||||
m4_define([mutter_plugin_api_version], [2])
|
||||
m4_define([mutter_plugin_api_version], [3])
|
||||
|
||||
AC_INIT([mutter], [mutter_version],
|
||||
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
|
||||
@@ -65,68 +63,75 @@ AC_C_BIGENDIAN
|
||||
|
||||
#### Warnings
|
||||
|
||||
# Stay command-line compatible with the gnome-common configure option. Here
|
||||
# minimum/yes/maximum are the same, however.
|
||||
AC_ARG_ENABLE(compile_warnings,
|
||||
AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),,
|
||||
enable_compile_warnings=error)
|
||||
|
||||
changequote(,)dnl
|
||||
if test "x$GCC" = "xyes"; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wall[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wall" ;;
|
||||
esac
|
||||
|
||||
# case " $CFLAGS " in
|
||||
# *[\ \ ]-Wshadow[\ \ ]*) ;;
|
||||
# *) CFLAGS="$CFLAGS -Wshadow" ;;
|
||||
# esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wchar-subscripts[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wmissing-declarations[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wnested-externs[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wnested-externs" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wpointer-arith[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wpointer-arith" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wcast-align[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wcast-align" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wsign-compare[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wsign-compare" ;;
|
||||
esac
|
||||
|
||||
if test "x$enable_ansi" = "xyes"; then
|
||||
if test "$enable_compile_warnings" != no ; then
|
||||
if test "x$GCC" = "xyes"; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-ansi[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -ansi" ;;
|
||||
*[\ \ ]-Wall[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wall" ;;
|
||||
esac
|
||||
|
||||
# case " $CFLAGS " in
|
||||
# *[\ \ ]-Wshadow[\ \ ]*) ;;
|
||||
# *) CFLAGS="$CFLAGS -Wshadow" ;;
|
||||
# esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wchar-subscripts[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-pedantic[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -pedantic" ;;
|
||||
*[\ \ ]-Wmissing-declarations[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wnested-externs[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wnested-externs" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wpointer-arith[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wpointer-arith" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wcast-align[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wcast-align" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wsign-compare[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wsign-compare" ;;
|
||||
esac
|
||||
|
||||
if test "$enable_compile_warnings" = error; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Werror[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Werror" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
changequote([,])dnl
|
||||
|
||||
MUTTER_PC_MODULES='gtk+-2.0 >= 2.10.0 pango >= 1.2.0'
|
||||
GTK_MIN_VERSION=2.90.7
|
||||
CANBERRA_GTK=libcanberra-gtk3
|
||||
CANBERRA_GTK_VERSION=0.26
|
||||
|
||||
MUTTER_PC_MODULES="gtk+-3.0 >= $GTK_MIN_VERSION pango >= 1.2.0 cairo >= 1.10.0"
|
||||
|
||||
AC_ARG_ENABLE(gconf,
|
||||
AC_HELP_STRING([--disable-gconf],
|
||||
@@ -162,6 +167,11 @@ AC_ARG_WITH(introspection,
|
||||
[disable the use of GObject introspection]),,
|
||||
with_introspection=auto)
|
||||
|
||||
AC_ARG_WITH(libcanberra,
|
||||
AC_HELP_STRING([--without-libcanberra],
|
||||
[disable the use of libcanberra for playing sounds]),,
|
||||
with_libcanberra=auto)
|
||||
|
||||
AC_ARG_ENABLE(xsync,
|
||||
AC_HELP_STRING([--disable-xsync],
|
||||
[disable mutter's use of the XSync extension]),,
|
||||
@@ -178,11 +188,11 @@ AC_CHECK_HEADERS(execinfo.h, [AC_CHECK_FUNCS(backtrace)])
|
||||
AM_GLIB_GNU_GETTEXT
|
||||
|
||||
## here we get the flags we'll actually use
|
||||
# GOptionEntry requires glib-2.6.0
|
||||
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.6.0)
|
||||
# GRegex requires Glib-2.14.0
|
||||
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
|
||||
# gtk_window_set_icon_name requires gtk2+-2.6.0
|
||||
PKG_CHECK_MODULES(MUTTER_MESSAGE, gtk+-2.0 >= 2.6.0)
|
||||
PKG_CHECK_MODULES(MUTTER_WINDOW_DEMO, gtk+-2.0 >= 2.6.0)
|
||||
PKG_CHECK_MODULES(MUTTER_MESSAGE, gtk+-3.0 >= $GTK_MIN_VERSION)
|
||||
PKG_CHECK_MODULES(MUTTER_WINDOW_DEMO, gtk+-3.0 >= $GTK_MIN_VERSION)
|
||||
|
||||
# Unconditionally use this dir to avoid a circular dep with gnomecc
|
||||
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
|
||||
@@ -214,6 +224,24 @@ else
|
||||
echo "Building without libstartup-notification"
|
||||
fi
|
||||
|
||||
have_libcanberra=no
|
||||
AC_MSG_CHECKING([libcanberra-gtk])
|
||||
if test x$with_libcanberra = xno ; then
|
||||
AC_MSG_RESULT([disabled])
|
||||
else
|
||||
if $PKG_CONFIG --exists $CANBERRA_GTK '>=' $CANBERRA_GTK_VERSION; then
|
||||
have_libcanberra=yes
|
||||
AC_MSG_RESULT(yes)
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES $CANBERRA_GTK"
|
||||
AC_DEFINE([HAVE_LIBCANBERRA], 1, [Building with libcanberra for playing sounds])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test x$with_libcanberra = xyes ; then
|
||||
AC_MSG_ERROR([libcanberra forced and libcanberra-gtk was not found])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
XCOMPOSITE_VERSION=0.2
|
||||
|
||||
AC_MSG_CHECKING([Xcomposite >= $XCOMPOSITE_VERSION])
|
||||
@@ -228,7 +256,7 @@ else
|
||||
AC_MSG_ERROR([no. Mutter requires the Xcomposite extension to build.])
|
||||
fi
|
||||
|
||||
CLUTTER_VERSION=1.0.0
|
||||
CLUTTER_VERSION=1.2.0
|
||||
CLUTTER_PACKAGE=clutter-1.0
|
||||
AC_SUBST(CLUTTER_PACKAGE)
|
||||
if $PKG_CONFIG --atleast-version $CLUTTER_VERSION $CLUTTER_PACKAGE ; then
|
||||
@@ -253,7 +281,7 @@ else
|
||||
fi
|
||||
|
||||
if test x$with_introspection != xno; then
|
||||
PKG_CHECK_MODULES(INTROSPECTION, gobject-introspection-1.0, have_introspection=yes, have_introspection=no)
|
||||
PKG_CHECK_MODULES(INTROSPECTION, gobject-introspection-1.0 >= 0.9.5, have_introspection=yes, have_introspection=no)
|
||||
if test x$have_introspection=xyes; then
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES gobject-introspection-1.0"
|
||||
AC_DEFINE(HAVE_INTROSPECTION, 1, [Define if GObject introspection is available])
|
||||
@@ -416,7 +444,7 @@ fi
|
||||
|
||||
MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
|
||||
MUTTER_MESSAGE_LIBS="$MUTTER_MESSAGE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
|
||||
MUTTER_PROPS_LIBS="$MUTTER_PROPS_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
|
||||
found_sm=no
|
||||
@@ -484,10 +512,8 @@ if test "x$enable_debug" = "xyes"; then
|
||||
CFLAGS="$CFLAGS -g -O"
|
||||
fi
|
||||
|
||||
# Warnings are there for a reason
|
||||
if test "x$GCC" = "xyes"; then
|
||||
CFLAGS="$CFLAGS -Wall -Werror -ansi"
|
||||
fi
|
||||
# For fix-meta-rectangle.py
|
||||
AM_PATH_PYTHON([2.5])
|
||||
|
||||
# Use gnome-doc-utils:
|
||||
GNOME_DOC_INIT([0.8.0])
|
||||
@@ -524,7 +550,7 @@ fi
|
||||
|
||||
dnl ==========================================================================
|
||||
echo "
|
||||
mutter-$VERSION:
|
||||
mutter-$VERSION
|
||||
|
||||
prefix: ${prefix}
|
||||
source code location: ${srcdir}
|
||||
@@ -534,6 +560,7 @@ mutter-$VERSION:
|
||||
XFree86 Xinerama: ${use_xfree_xinerama}
|
||||
Solaris Xinerama: ${use_solaris_xinerama}
|
||||
Startup notification: ${have_startup_notification}
|
||||
libcanberra: ${have_libcanberra}
|
||||
Introspection: ${have_introspection}
|
||||
Session management: ${found_sm}
|
||||
Shape extension: ${found_shape}
|
||||
|
||||
@@ -4,6 +4,7 @@ of the theme format, and a given theme can support more than one format.
|
||||
Version 1: THEMEDIR/metacity-1/metacity-theme-1.xml
|
||||
(original metacity format)
|
||||
Version 2: THEMEDIR/metacity-1/metacity-theme-2.xml
|
||||
Version 3: THEMEDIR/metacity-1/metacity-theme-3.xml
|
||||
|
||||
The subdirectory name is "metacity-1" in all versions.
|
||||
|
||||
@@ -21,6 +22,41 @@ This document has separate sections for each format version. You may
|
||||
want to read the document in reverse order, since the base features
|
||||
are discussed under version 1.
|
||||
|
||||
New Features in Theme Format Version 3.1
|
||||
========================================
|
||||
|
||||
Additional predefined variables are added for positioning expressions:
|
||||
|
||||
frame_x_center: the X center of the entire frame, with respect to the
|
||||
piece currently being drawn.
|
||||
frame_y_center: the Y center of the entire frame, with respect to the
|
||||
piece currently being drawn.
|
||||
|
||||
The <title/> element now supports an "ellipsize_width" attribute. When
|
||||
specified, this gives a width at which to ellipsize the title. If not
|
||||
specified, the title will simply be clipped to the title area.
|
||||
|
||||
New Features in Theme Format Version 3
|
||||
======================================
|
||||
|
||||
Format version 3 has exactly one new feature; any element in the file
|
||||
can now have a version attribute:
|
||||
|
||||
version="[<|<=|=>|>] MAJOR.MINOR"
|
||||
|
||||
(< and > should be to be entity escaped as < and >). If this
|
||||
version check is not met, then the element and its children will be
|
||||
ignored. This allows having alternate sections of the theme file for
|
||||
older and newer version of the Metacity theme format.
|
||||
|
||||
When placed on the toplevel <metacity_theme> element, an unsatisfied
|
||||
version check will not just cause the contents of the file to be
|
||||
ignored, it will also cause the lookup of a theme file to proceed on
|
||||
and look for an older format 2 or format 1 file. This allows making a
|
||||
metacity-theme-3.xml file that is only used the format version 3.2 or
|
||||
newer is supported, and using metacity-theme-1.xml for older window
|
||||
managers.
|
||||
|
||||
New Features in Theme Format Version 2
|
||||
======================================
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ be@latin
|
||||
bg
|
||||
bn
|
||||
bn_IN
|
||||
br
|
||||
bs
|
||||
ca
|
||||
ca@valencia
|
||||
@@ -56,6 +57,7 @@ mn
|
||||
mr
|
||||
ms
|
||||
nb
|
||||
nds
|
||||
ne
|
||||
nl
|
||||
nn
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# List of source files containing translatable strings.
|
||||
# Please keep this file sorted alphabetically.
|
||||
src/core/bell.c
|
||||
src/core/core.c
|
||||
src/core/delete.c
|
||||
src/core/display.c
|
||||
|
||||
1988
po/en_GB.po
1988
po/en_GB.po
File diff suppressed because it is too large
Load Diff
2004
po/pt_BR.po
2004
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1984
po/sr@latin.po
1984
po/sr@latin.po
File diff suppressed because it is too large
Load Diff
2028
po/zh_CN.po
2028
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
1692
po/zh_HK.po
1692
po/zh_HK.po
File diff suppressed because it is too large
Load Diff
1785
po/zh_TW.po
1785
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,6 @@
|
||||
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
|
||||
.AUTOPARALLEL:
|
||||
|
||||
lib_LTLIBRARIES = libmutter-private.la
|
||||
|
||||
SUBDIRS=wm-tester tools compositor/plugins
|
||||
@@ -13,34 +16,36 @@ mutter_built_sources = \
|
||||
mutter_SOURCES= \
|
||||
core/async-getprop.c \
|
||||
core/async-getprop.h \
|
||||
core/alttabhandler.c \
|
||||
include/alttabhandler.h \
|
||||
core/alttabhandlerdefault.c \
|
||||
include/alttabhandlerdefault.h \
|
||||
core/bell.c \
|
||||
core/bell.h \
|
||||
core/boxes.c \
|
||||
core/boxes-private.h \
|
||||
include/boxes.h \
|
||||
compositor/compositor.c \
|
||||
compositor/compositor-private.h \
|
||||
compositor/mutter-module.c \
|
||||
compositor/mutter-module.h \
|
||||
compositor/mutter-plugin.c \
|
||||
compositor/mutter-plugin-manager.c \
|
||||
compositor/mutter-plugin-manager.h \
|
||||
compositor/mutter-shaped-texture.c \
|
||||
compositor/mutter-window.c \
|
||||
compositor/mutter-window-private.h \
|
||||
compositor/mutter-window-group.c \
|
||||
compositor/mutter-window-group.h \
|
||||
compositor/shadow.c \
|
||||
compositor/shadow.h \
|
||||
compositor/mutter-shaped-texture.h \
|
||||
compositor/tidy/tidy-texture-frame.c \
|
||||
compositor/tidy/tidy-texture-frame.h \
|
||||
compositor/meta-module.c \
|
||||
compositor/meta-module.h \
|
||||
compositor/meta-plugin.c \
|
||||
compositor/meta-plugin-manager.c \
|
||||
compositor/meta-plugin-manager.h \
|
||||
compositor/meta-shadow-factory.c \
|
||||
compositor/meta-shadow-factory-private.h \
|
||||
compositor/meta-shaped-texture.c \
|
||||
compositor/meta-shaped-texture.h \
|
||||
compositor/meta-texture-tower.c \
|
||||
compositor/meta-texture-tower.h \
|
||||
compositor/meta-window-actor.c \
|
||||
compositor/meta-window-actor-private.h \
|
||||
compositor/meta-window-group.c \
|
||||
compositor/meta-window-group.h \
|
||||
compositor/meta-window-shape.c \
|
||||
compositor/meta-window-shape.h \
|
||||
compositor/region-utils.c \
|
||||
compositor/region-utils.h \
|
||||
include/compositor.h \
|
||||
include/mutter-plugin.h \
|
||||
include/mutter-window.h \
|
||||
include/meta-plugin.h \
|
||||
include/meta-shadow-factory.h \
|
||||
include/meta-window-actor.h \
|
||||
include/compositor-mutter.h \
|
||||
core/constraints.c \
|
||||
core/constraints.h \
|
||||
@@ -72,7 +77,7 @@ mutter_SOURCES= \
|
||||
core/keybindings.c \
|
||||
core/keybindings-private.h \
|
||||
core/main.c \
|
||||
core/mutter-Xatomtype.h \
|
||||
core/mutter-Xatomtype.h \
|
||||
core/place.c \
|
||||
core/place.h \
|
||||
core/prefs.c \
|
||||
@@ -114,12 +119,12 @@ mutter_SOURCES= \
|
||||
include/resizepopup.h \
|
||||
ui/tabpopup.c \
|
||||
include/tabpopup.h \
|
||||
ui/tile-preview.c \
|
||||
include/tile-preview.h \
|
||||
ui/theme-parser.c \
|
||||
ui/theme-parser.h \
|
||||
ui/theme.c \
|
||||
ui/theme.h \
|
||||
ui/themewidget.c \
|
||||
ui/themewidget.h \
|
||||
ui/theme-private.h \
|
||||
ui/ui.c \
|
||||
include/all-keybindings.h \
|
||||
$(mutter_built_sources)
|
||||
@@ -138,25 +143,20 @@ libmutter_private_la_SOURCES= \
|
||||
ui/preview-widget.c \
|
||||
ui/preview-widget.h \
|
||||
ui/theme-parser.c \
|
||||
ui/theme-parser.h \
|
||||
ui/theme.c \
|
||||
ui/theme.h
|
||||
|
||||
libmutter_private_la_LDFLAGS = -no-undefined
|
||||
libmutter_private_la_LIBADD = @MUTTER_LIBS@
|
||||
|
||||
libmutterincludedir = $(includedir)/mutter/mutter-private
|
||||
|
||||
# Headers installed for plugins; introspected information will
|
||||
# be extracted into Mutter-<version>.gir
|
||||
libmutterinclude_base_headers = \
|
||||
include/alttabhandler.h \
|
||||
include/boxes.h \
|
||||
ui/gradient.h \
|
||||
include/main.h \
|
||||
include/util.h \
|
||||
include/common.h \
|
||||
ui/theme-parser.h \
|
||||
ui/theme.h \
|
||||
include/prefs.h \
|
||||
include/window.h \
|
||||
@@ -169,8 +169,9 @@ libmutterinclude_base_headers = \
|
||||
include/display.h \
|
||||
include/group.h \
|
||||
include/keybindings.h \
|
||||
include/mutter-plugin.h \
|
||||
include/mutter-window.h
|
||||
include/meta-plugin.h \
|
||||
include/meta-shadow-factory.h \
|
||||
include/meta-window-actor.h
|
||||
|
||||
# Excluded from scanning for introspection but installed
|
||||
# preview-widget.h: only part of libmutter-private
|
||||
@@ -179,6 +180,8 @@ libmutterinclude_extra_headers = \
|
||||
ui/preview-widget.h \
|
||||
include/atomnames.h
|
||||
|
||||
libmutterincludedir = $(includedir)/mutter/mutter-private
|
||||
|
||||
libmutterinclude_HEADERS = \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(libmutterinclude_extra_headers)
|
||||
@@ -202,20 +205,24 @@ typelib_DATA = Meta-$(api_version).typelib
|
||||
|
||||
# We need to strip out the attribute that would point back to libmutter-introspect
|
||||
# so that libgirepository looks for symbols in the executable instead
|
||||
Meta-$(api_version).gir: $(G_IR_SCANNER) mutter $(libmutterinclude_HEADERS) $(mutter_SOURCES)
|
||||
Meta-$(api_version).gir: $(G_IR_SCANNER) mutter $(libmutterinclude_HEADERS) $(mutter_SOURCES) Makefile
|
||||
$(AM_V_GEN) pwd=`pwd` ; \
|
||||
cd $(srcdir) && \
|
||||
$(G_IR_SCANNER) \
|
||||
--namespace=Meta \
|
||||
--nsversion=$(api_version) \
|
||||
--warn-all \
|
||||
--warn-error \
|
||||
--include=GObject-2.0 \
|
||||
--include=Gdk-2.0 \
|
||||
--include=Gtk-2.0 \
|
||||
--include=Gdk-3.0 \
|
||||
--include=Gtk-3.0 \
|
||||
--include=Clutter-1.0 \
|
||||
--pkg=clutter-1.0 \
|
||||
--pkg=gtk+-2.0 \
|
||||
--pkg=gtk+-3.0 \
|
||||
--include=xlib-2.0 \
|
||||
--include=xfixes-4.0 \
|
||||
--program=$$pwd/mutter \
|
||||
mutter-enum-types.h \
|
||||
$(filter %.c,$(mutter_SOURCES)) \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(INCLUDES) \
|
||||
@@ -328,7 +335,7 @@ mutter-marshal.c: Makefile mutter-marshal.list
|
||||
|
||||
mutter-enum-types.h: stamp-mutter-enum-types.h Makefile
|
||||
@true
|
||||
stamp-mutter-enum-types.h: $(mutter_source_h) mutter-enum-types.h.in
|
||||
stamp-mutter-enum-types.h: $(libmutterinclude_base_headers) mutter-enum-types.h.in
|
||||
$(AM_V_GEN) ( cd $(srcdir) && \
|
||||
$(GLIB_MKENUMS) \
|
||||
--template $(srcdir)/mutter-enum-types.h.in \
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "compositor.h"
|
||||
#include "display.h"
|
||||
#include "mutter-plugin-manager.h"
|
||||
#include "meta-plugin-manager.h"
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
typedef struct _MetaCompScreen MetaCompScreen;
|
||||
@@ -23,7 +23,7 @@ struct _MetaCompositor
|
||||
|
||||
ClutterActor *shadow_src;
|
||||
|
||||
MutterPlugin *modal_plugin;
|
||||
MetaPlugin *modal_plugin;
|
||||
|
||||
gboolean show_redraw : 1;
|
||||
gboolean debug : 1;
|
||||
@@ -45,24 +45,24 @@ struct _MetaCompScreen
|
||||
|
||||
gint switch_workspace_in_progress;
|
||||
|
||||
MutterPluginManager *plugin_mgr;
|
||||
MetaPluginManager *plugin_mgr;
|
||||
};
|
||||
|
||||
void mutter_switch_workspace_completed (MetaScreen *screen);
|
||||
void mutter_set_stage_input_region (MetaScreen *screen,
|
||||
XserverRegion region);
|
||||
void mutter_empty_stage_input_region (MetaScreen *screen);
|
||||
void meta_switch_workspace_completed (MetaScreen *screen);
|
||||
void meta_set_stage_input_region (MetaScreen *screen,
|
||||
XserverRegion region);
|
||||
void meta_empty_stage_input_region (MetaScreen *screen);
|
||||
|
||||
gboolean mutter_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MutterPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp);
|
||||
void mutter_end_modal_for_plugin (MetaScreen *screen,
|
||||
MutterPlugin *plugin,
|
||||
guint32 timestamp);
|
||||
gboolean meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp);
|
||||
void meta_end_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
guint32 timestamp);
|
||||
|
||||
void mutter_check_end_modal (MetaScreen *screen);
|
||||
void meta_check_end_modal (MetaScreen *screen);
|
||||
|
||||
#endif /* META_COMPOSITOR_PRIVATE_H */
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
#include "compositor-mutter.h"
|
||||
#include "xprops.h"
|
||||
#include "prefs.h"
|
||||
#include "mutter-window-private.h"
|
||||
#include "mutter-window-group.h"
|
||||
#include "meta-shadow-factory.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-window-group.h"
|
||||
#include "../core/window-private.h" /* to check window->hidden */
|
||||
#include "../core/display-private.h" /* for meta_display_lookup_x_window() */
|
||||
#include <X11/extensions/shape.h>
|
||||
@@ -33,69 +34,16 @@ composite_at_least_version (MetaDisplay *display, int maj, int min)
|
||||
return (major > maj || (major == maj && minor >= min));
|
||||
}
|
||||
|
||||
static MutterWindow*
|
||||
find_window_for_screen (MetaScreen *screen, Window xwindow)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
|
||||
return g_hash_table_lookup (info->windows_by_xid,
|
||||
(gpointer) xwindow);
|
||||
}
|
||||
|
||||
static MutterWindow *
|
||||
find_window_in_display (MetaDisplay *display, Window xwindow)
|
||||
{
|
||||
GSList *index;
|
||||
MetaWindow *window = meta_display_lookup_x_window (display, xwindow);
|
||||
|
||||
if (window)
|
||||
{
|
||||
void *priv = meta_window_get_compositor_private (window);
|
||||
if (priv)
|
||||
return priv;
|
||||
}
|
||||
|
||||
for (index = meta_display_get_screens (display);
|
||||
index;
|
||||
index = index->next)
|
||||
{
|
||||
MutterWindow *cw = find_window_for_screen (index->data, xwindow);
|
||||
|
||||
if (cw != NULL)
|
||||
return cw;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static MutterWindow *
|
||||
find_window_for_child_window_in_display (MetaDisplay *display, Window xwindow)
|
||||
{
|
||||
Window ignored1, *ignored2, parent;
|
||||
guint ignored_children;
|
||||
|
||||
XQueryTree (meta_display_get_xdisplay (display), xwindow, &ignored1,
|
||||
&parent, &ignored2, &ignored_children);
|
||||
|
||||
if (parent != None)
|
||||
return find_window_in_display (display, parent);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sync_actor_stacking (GList *windows);
|
||||
|
||||
static void
|
||||
mutter_finish_workspace_switch (MetaCompScreen *info)
|
||||
meta_finish_workspace_switch (MetaCompScreen *info)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
/* Finish hiding and showing actors for the new workspace */
|
||||
for (l = info->windows; l; l = l->next)
|
||||
mutter_window_sync_visibility (l->data);
|
||||
meta_window_actor_sync_visibility (l->data);
|
||||
|
||||
/*
|
||||
* Fix up stacking order in case the plugin messed it up.
|
||||
@@ -107,7 +55,7 @@ mutter_finish_workspace_switch (MetaCompScreen *info)
|
||||
}
|
||||
|
||||
void
|
||||
mutter_switch_workspace_completed (MetaScreen *screen)
|
||||
meta_switch_workspace_completed (MetaScreen *screen)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
@@ -120,7 +68,7 @@ mutter_switch_workspace_completed (MetaScreen *screen)
|
||||
}
|
||||
|
||||
if (!info->switch_workspace_in_progress)
|
||||
mutter_finish_workspace_switch (info);
|
||||
meta_finish_workspace_switch (info);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -137,82 +85,72 @@ add_win (MetaWindow *window)
|
||||
|
||||
g_return_if_fail (info != NULL);
|
||||
|
||||
mutter_window_new (window);
|
||||
meta_window_actor_new (window);
|
||||
|
||||
sync_actor_stacking (info->windows);
|
||||
}
|
||||
|
||||
static void
|
||||
process_damage (MetaCompositor *compositor,
|
||||
XDamageNotifyEvent *event)
|
||||
XDamageNotifyEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MutterWindow *cw = find_window_in_display (compositor->display, event->drawable);
|
||||
if (cw == NULL)
|
||||
MetaWindowActor *window_actor;
|
||||
|
||||
if (window == NULL)
|
||||
return;
|
||||
|
||||
mutter_window_process_damage (cw, event);
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (window_actor == NULL)
|
||||
return;
|
||||
|
||||
meta_window_actor_process_damage (window_actor, event);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
static void
|
||||
process_shape (MetaCompositor *compositor,
|
||||
XShapeEvent *event)
|
||||
XShapeEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MutterWindow *cw = find_window_in_display (compositor->display,
|
||||
event->window);
|
||||
if (cw == NULL)
|
||||
MetaWindowActor *window_actor;
|
||||
|
||||
if (window == NULL)
|
||||
return;
|
||||
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (window_actor == NULL)
|
||||
return;
|
||||
|
||||
if (event->kind == ShapeBounding)
|
||||
{
|
||||
mutter_window_update_shape (cw, event->shaped);
|
||||
meta_window_actor_update_shape (window_actor, event->shaped);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
process_property_notify (MetaCompositor *compositor,
|
||||
XPropertyEvent *event)
|
||||
XPropertyEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaDisplay *display = compositor->display;
|
||||
MetaWindowActor *window_actor;
|
||||
|
||||
if (window == NULL)
|
||||
return;
|
||||
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (window_actor == NULL)
|
||||
return;
|
||||
|
||||
/* Check for the opacity changing */
|
||||
if (event->atom == compositor->atom_net_wm_window_opacity)
|
||||
{
|
||||
MutterWindow *cw = find_window_in_display (display, event->window);
|
||||
|
||||
if (!cw)
|
||||
{
|
||||
/* Applications can set this for their toplevel windows, so
|
||||
* this must be propagated to the window managed by the compositor
|
||||
*/
|
||||
cw = find_window_for_child_window_in_display (display,
|
||||
event->window);
|
||||
}
|
||||
|
||||
if (!cw)
|
||||
{
|
||||
DEBUG_TRACE ("process_property_notify: opacity, early exit\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mutter_window_update_opacity (cw);
|
||||
}
|
||||
else if (event->atom == meta_display_get_atom (display,
|
||||
META_ATOM__NET_WM_WINDOW_TYPE))
|
||||
{
|
||||
MutterWindow *cw = find_window_in_display (display, event->window);
|
||||
|
||||
if (!cw)
|
||||
{
|
||||
DEBUG_TRACE ("process_property_notify: net_wm_type, early exit\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mutter_window_update_window_type (cw);
|
||||
DEBUG_TRACE ("process_property_notify: net_wm_type\n");
|
||||
meta_window_actor_update_opacity (window_actor);
|
||||
DEBUG_TRACE ("process_property_notify: net_wm_window_opacity\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_TRACE ("process_property_notify: unknown\n");
|
||||
}
|
||||
|
||||
@@ -247,8 +185,14 @@ get_output_window (MetaScreen *screen)
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_get_stage_for_screen:
|
||||
* @screen: a #MetaScreen
|
||||
*
|
||||
* Returns: (transfer none): The #ClutterStage for the screen
|
||||
*/
|
||||
ClutterActor *
|
||||
mutter_get_stage_for_screen (MetaScreen *screen)
|
||||
meta_get_stage_for_screen (MetaScreen *screen)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
@@ -258,8 +202,14 @@ mutter_get_stage_for_screen (MetaScreen *screen)
|
||||
return info->stage;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_get_overlay_group_for_screen:
|
||||
* @screen: a #MetaScreen
|
||||
*
|
||||
* Returns: (transfer none): The overlay group corresponding to @screen
|
||||
*/
|
||||
ClutterActor *
|
||||
mutter_get_overlay_group_for_screen (MetaScreen *screen)
|
||||
meta_get_overlay_group_for_screen (MetaScreen *screen)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
@@ -269,8 +219,14 @@ mutter_get_overlay_group_for_screen (MetaScreen *screen)
|
||||
return info->overlay_group;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_get_window_group_for_screen:
|
||||
* @screen: a #MetaScreen
|
||||
*
|
||||
* Returns: (transfer none): The window group corresponding to @screen
|
||||
*/
|
||||
ClutterActor *
|
||||
mutter_get_window_group_for_screen (MetaScreen *screen)
|
||||
meta_get_window_group_for_screen (MetaScreen *screen)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
@@ -280,8 +236,14 @@ mutter_get_window_group_for_screen (MetaScreen *screen)
|
||||
return info->window_group;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_get_window_actors:
|
||||
* @screen: a #MetaScreen
|
||||
*
|
||||
* Returns: (transfer none) (element-type Clutter.Actor): The set of #MetaWindowActor on @screen
|
||||
*/
|
||||
GList *
|
||||
mutter_get_windows (MetaScreen *screen)
|
||||
meta_get_window_actors (MetaScreen *screen)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
@@ -292,7 +254,7 @@ mutter_get_windows (MetaScreen *screen)
|
||||
}
|
||||
|
||||
static void
|
||||
do_set_stage_input_region (MetaScreen *screen,
|
||||
do_set_stage_input_region (MetaScreen *screen,
|
||||
XserverRegion region)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
@@ -305,8 +267,8 @@ do_set_stage_input_region (MetaScreen *screen,
|
||||
}
|
||||
|
||||
void
|
||||
mutter_set_stage_input_region (MetaScreen *screen,
|
||||
XserverRegion region)
|
||||
meta_set_stage_input_region (MetaScreen *screen,
|
||||
XserverRegion region)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
@@ -334,7 +296,7 @@ mutter_set_stage_input_region (MetaScreen *screen,
|
||||
}
|
||||
|
||||
void
|
||||
mutter_empty_stage_input_region (MetaScreen *screen)
|
||||
meta_empty_stage_input_region (MetaScreen *screen)
|
||||
{
|
||||
/* Using a static region here is a bit hacky, but Metacity never opens more than
|
||||
* one XDisplay, so it works fine. */
|
||||
@@ -347,16 +309,16 @@ mutter_empty_stage_input_region (MetaScreen *screen)
|
||||
region = XFixesCreateRegion (xdpy, NULL, 0);
|
||||
}
|
||||
|
||||
mutter_set_stage_input_region (screen, region);
|
||||
meta_set_stage_input_region (screen, region);
|
||||
}
|
||||
|
||||
gboolean
|
||||
mutter_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MutterPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
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
|
||||
@@ -390,10 +352,10 @@ mutter_begin_modal_for_plugin (MetaScreen *screen,
|
||||
|
||||
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
|
||||
{
|
||||
XGrabKeyboard (xdpy, grab_window,
|
||||
False, /* owner_events */
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
timestamp);
|
||||
result = XGrabKeyboard (xdpy, grab_window,
|
||||
False, /* owner_events */
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
timestamp);
|
||||
|
||||
if (result != Success)
|
||||
goto fail;
|
||||
@@ -421,9 +383,9 @@ mutter_begin_modal_for_plugin (MetaScreen *screen,
|
||||
}
|
||||
|
||||
void
|
||||
mutter_end_modal_for_plugin (MetaScreen *screen,
|
||||
MutterPlugin *plugin,
|
||||
guint32 timestamp)
|
||||
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);
|
||||
@@ -447,15 +409,15 @@ mutter_end_modal_for_plugin (MetaScreen *screen,
|
||||
* a left-over modal grab for this screen.
|
||||
*/
|
||||
void
|
||||
mutter_check_end_modal (MetaScreen *screen)
|
||||
meta_check_end_modal (MetaScreen *screen)
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
|
||||
if (compositor->modal_plugin &&
|
||||
mutter_plugin_get_screen (compositor->modal_plugin) == screen)
|
||||
meta_plugin_get_screen (compositor->modal_plugin) == screen)
|
||||
{
|
||||
mutter_end_modal_for_plugin (screen,
|
||||
meta_end_modal_for_plugin (screen,
|
||||
compositor->modal_plugin,
|
||||
CurrentTime);
|
||||
}
|
||||
@@ -483,7 +445,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
|
||||
XSync (xdisplay, FALSE);
|
||||
|
||||
if (meta_error_trap_pop_with_return (display, FALSE))
|
||||
if (meta_error_trap_pop_with_return (display))
|
||||
{
|
||||
g_warning ("Another compositing manager is running on screen %i",
|
||||
screen_number);
|
||||
@@ -505,7 +467,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
|
||||
info->output = None;
|
||||
info->windows = NULL;
|
||||
info->windows_by_xid = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
|
||||
meta_screen_set_cm_selection (screen);
|
||||
|
||||
@@ -532,7 +493,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
|
||||
XSelectInput (xdisplay, xwin, event_mask);
|
||||
|
||||
info->window_group = mutter_window_group_new (screen);
|
||||
info->window_group = meta_window_group_new (screen);
|
||||
info->overlay_group = clutter_group_new ();
|
||||
info->hidden_group = clutter_group_new ();
|
||||
|
||||
@@ -545,10 +506,18 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
clutter_actor_hide (info->hidden_group);
|
||||
|
||||
info->plugin_mgr =
|
||||
mutter_plugin_manager_new (screen);
|
||||
if (!mutter_plugin_manager_load (info->plugin_mgr))
|
||||
g_critical ("failed to load plugins");
|
||||
if (!mutter_plugin_manager_initialize (info->plugin_mgr))
|
||||
meta_plugin_manager_get (screen);
|
||||
|
||||
if (info->plugin_mgr != meta_plugin_manager_get_default ())
|
||||
{
|
||||
/* The default plugin manager has been initialized during
|
||||
* global preferences load.
|
||||
*/
|
||||
if (!meta_plugin_manager_load (info->plugin_mgr))
|
||||
g_critical ("failed to load plugins");
|
||||
}
|
||||
|
||||
if (!meta_plugin_manager_initialize (info->plugin_mgr))
|
||||
g_critical ("failed to initialize plugins");
|
||||
|
||||
/*
|
||||
@@ -600,21 +569,21 @@ meta_compositor_add_window (MetaCompositor *compositor,
|
||||
|
||||
add_win (window);
|
||||
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_remove_window (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MutterWindow *cw = NULL;
|
||||
MetaWindowActor *window_actor = NULL;
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_remove_window\n");
|
||||
cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
|
||||
if (!cw)
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
mutter_window_destroy (cw);
|
||||
meta_window_actor_destroy (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -634,14 +603,17 @@ is_grabbed_event (XEvent *event)
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
case MotionNotify:
|
||||
case KeyPressMask:
|
||||
case KeyReleaseMask:
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_compositor_process_event: (skip)
|
||||
*
|
||||
*/
|
||||
gboolean
|
||||
meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
@@ -649,7 +621,7 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
{
|
||||
if (compositor->modal_plugin && is_grabbed_event (event))
|
||||
{
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (compositor->modal_plugin);
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (compositor->modal_plugin);
|
||||
|
||||
if (klass->xevent_filter)
|
||||
klass->xevent_filter (compositor->modal_plugin, event);
|
||||
@@ -667,7 +639,7 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
screen = meta_window_get_screen (window);
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (mutter_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
@@ -686,7 +658,7 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (mutter_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
@@ -696,38 +668,37 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This trap is so that none of the compositor functions cause
|
||||
* X errors. This is really a hack, but I'm afraid I don't understand
|
||||
* enough about Metacity/X to know how else you are supposed to do it
|
||||
*/
|
||||
|
||||
|
||||
meta_error_trap_push (compositor->display);
|
||||
switch (event->type)
|
||||
{
|
||||
case PropertyNotify:
|
||||
process_property_notify (compositor, (XPropertyEvent *) event);
|
||||
process_property_notify (compositor, (XPropertyEvent *) event, window);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (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
|
||||
*/
|
||||
if (window == NULL)
|
||||
{
|
||||
Window xwin = ((XDamageNotifyEvent *) event)->drawable;
|
||||
window = meta_display_lookup_x_window (compositor->display, xwin);
|
||||
}
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
|
||||
process_damage (compositor, (XDamageNotifyEvent *) event);
|
||||
process_damage (compositor, (XDamageNotifyEvent *) event, window);
|
||||
}
|
||||
#ifdef HAVE_SHAPE
|
||||
else if (event->type == meta_display_get_shape_event_base (compositor->display) + ShapeNotify)
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (process_shape)\n");
|
||||
process_shape (compositor, (XShapeEvent *) event);
|
||||
process_shape (compositor, (XShapeEvent *) event, window);
|
||||
}
|
||||
#endif /* HAVE_SHAPE */
|
||||
break;
|
||||
}
|
||||
|
||||
meta_error_trap_pop (compositor->display, FALSE);
|
||||
|
||||
/* Clutter needs to know about MapNotify events otherwise it will
|
||||
think the stage is invisible */
|
||||
if (event->type == MapNotify)
|
||||
@@ -745,12 +716,12 @@ meta_compositor_show_window (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaCompEffect effect)
|
||||
{
|
||||
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_show_window\n");
|
||||
if (!cw)
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
mutter_window_show (cw, effect);
|
||||
meta_window_actor_show (window_actor, effect);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -758,12 +729,12 @@ meta_compositor_hide_window (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaCompEffect effect)
|
||||
{
|
||||
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_hide_window\n");
|
||||
if (!cw)
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
mutter_window_hide (cw, effect);
|
||||
meta_window_actor_hide (window_actor, effect);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -772,12 +743,12 @@ meta_compositor_maximize_window (MetaCompositor *compositor,
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect)
|
||||
{
|
||||
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_maximize_window\n");
|
||||
if (!cw)
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
mutter_window_maximize (cw, old_rect, new_rect);
|
||||
meta_window_actor_maximize (window_actor, old_rect, new_rect);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -786,12 +757,12 @@ meta_compositor_unmaximize_window (MetaCompositor *compositor,
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect)
|
||||
{
|
||||
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_unmaximize_window\n");
|
||||
if (!cw)
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
mutter_window_unmaximize (cw, old_rect, new_rect);
|
||||
meta_window_actor_unmaximize (window_actor, old_rect, new_rect);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -804,7 +775,7 @@ meta_compositor_update_workspace_geometry (MetaCompositor *compositor,
|
||||
*/
|
||||
MetaScreen *screen = meta_workspace_get_screen (workspace);
|
||||
MetaCompScreen *info;
|
||||
MutterPluginManager *mgr;
|
||||
MetaPluginManager *mgr;
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_update_workspace_geometry\n");
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
@@ -813,7 +784,7 @@ meta_compositor_update_workspace_geometry (MetaCompositor *compositor,
|
||||
if (!mgr || !workspace)
|
||||
return;
|
||||
|
||||
mutter_plugin_manager_update_workspace (mgr, workspace);
|
||||
meta_plugin_manager_update_workspace (mgr, workspace);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -839,8 +810,7 @@ meta_compositor_switch_workspace (MetaCompositor *compositor,
|
||||
info->switch_workspace_in_progress++;
|
||||
|
||||
if (!info->plugin_mgr ||
|
||||
!mutter_plugin_manager_switch_workspace (info->plugin_mgr,
|
||||
(const GList **)&info->windows,
|
||||
!meta_plugin_manager_switch_workspace (info->plugin_mgr,
|
||||
from_indx,
|
||||
to_indx,
|
||||
direction))
|
||||
@@ -852,7 +822,7 @@ meta_compositor_switch_workspace (MetaCompositor *compositor,
|
||||
* necessarily change during the window hiding/unhiding, only their
|
||||
* relative position toward the destkop window.
|
||||
*/
|
||||
mutter_finish_workspace_switch (info);
|
||||
meta_finish_workspace_switch (info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -865,9 +835,9 @@ sync_actor_stacking (GList *windows)
|
||||
|
||||
for (tmp = g_list_last (windows); tmp != NULL; tmp = tmp->prev)
|
||||
{
|
||||
MutterWindow *cw = tmp->data;
|
||||
MetaWindowActor *window_actor = tmp->data;
|
||||
|
||||
clutter_actor_lower_bottom (CLUTTER_ACTOR (cw));
|
||||
clutter_actor_lower_bottom (CLUTTER_ACTOR (window_actor));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -889,12 +859,12 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
|
||||
|
||||
/* Sources: first window is the highest */
|
||||
stack = g_list_copy (stack); /* The new stack of MetaWindow */
|
||||
old_stack = g_list_reverse (info->windows); /* The old stack of MutterWindow */
|
||||
old_stack = g_list_reverse (info->windows); /* The old stack of MetaWindowActor */
|
||||
info->windows = NULL;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
MutterWindow *old_actor = NULL, *stack_actor = NULL, *actor;
|
||||
MetaWindowActor *old_actor = NULL, *stack_actor = NULL, *actor;
|
||||
MetaWindow *old_window = NULL, *stack_window = NULL, *window;
|
||||
|
||||
/* Find the remaining top actor in our existing stack (ignoring
|
||||
@@ -902,10 +872,10 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
|
||||
while (old_stack)
|
||||
{
|
||||
old_actor = old_stack->data;
|
||||
old_window = mutter_window_get_meta_window (old_actor);
|
||||
old_window = meta_window_actor_get_meta_window (old_actor);
|
||||
|
||||
if (old_window->hidden &&
|
||||
!mutter_window_effect_in_progress (old_actor))
|
||||
!meta_window_actor_effect_in_progress (old_actor))
|
||||
old_stack = g_list_delete_link (old_stack, old_stack);
|
||||
else
|
||||
break;
|
||||
@@ -915,10 +885,10 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
|
||||
while (stack)
|
||||
{
|
||||
stack_window = stack->data;
|
||||
stack_actor = MUTTER_WINDOW (meta_window_get_compositor_private (stack_window));
|
||||
stack_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (stack_window));
|
||||
if (!stack_actor)
|
||||
{
|
||||
meta_verbose ("Failed to find corresponding MutterWindow "
|
||||
meta_verbose ("Failed to find corresponding MetaWindowActor "
|
||||
"for window %s\n", meta_window_get_description (stack_window));
|
||||
stack = g_list_delete_link (stack, stack);
|
||||
}
|
||||
@@ -964,41 +934,41 @@ void
|
||||
meta_compositor_window_mapped (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_window_mapped\n");
|
||||
if (!cw)
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
mutter_window_mapped (cw);
|
||||
meta_window_actor_mapped (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_window_unmapped (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_window_unmapped\n");
|
||||
if (!cw)
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
mutter_window_unmapped (cw);
|
||||
meta_window_actor_unmapped (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_sync_window_geometry (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaCompScreen *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);
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_sync_window_geometry\n");
|
||||
g_return_if_fail (info);
|
||||
|
||||
if (!cw)
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
mutter_window_sync_actor_position (cw);
|
||||
meta_window_actor_sync_actor_position (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1025,11 +995,11 @@ pre_paint_windows (MetaCompScreen *info)
|
||||
GList *l;
|
||||
|
||||
for (l = info->windows; l; l = l->next)
|
||||
mutter_window_pre_paint (l->data);
|
||||
meta_window_actor_pre_paint (l->data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
mutter_repaint_func (gpointer data)
|
||||
meta_repaint_func (gpointer data)
|
||||
{
|
||||
MetaCompositor *compositor = data;
|
||||
GSList *screens = meta_display_get_screens (compositor->display);
|
||||
@@ -1048,6 +1018,30 @@ mutter_repaint_func (gpointer data)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_shadow_factory_changed (MetaShadowFactory *factory,
|
||||
MetaCompositor *compositor)
|
||||
{
|
||||
GSList *screens = meta_display_get_screens (compositor->display);
|
||||
GList *l;
|
||||
GSList *sl;
|
||||
|
||||
for (sl = screens; sl; sl = sl->next)
|
||||
{
|
||||
MetaScreen *screen = sl->data;
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
if (!info)
|
||||
continue;
|
||||
|
||||
for (l = info->windows; l; l = l->next)
|
||||
meta_window_actor_invalidate_shadow (l->data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_compositor_new: (skip)
|
||||
*
|
||||
*/
|
||||
MetaCompositor *
|
||||
meta_compositor_new (MetaDisplay *display)
|
||||
{
|
||||
@@ -1067,26 +1061,35 @@ meta_compositor_new (MetaDisplay *display)
|
||||
|
||||
compositor->display = display;
|
||||
|
||||
if (g_getenv("MUTTER_DISABLE_MIPMAPS"))
|
||||
if (g_getenv("META_DISABLE_MIPMAPS"))
|
||||
compositor->no_mipmaps = TRUE;
|
||||
|
||||
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
|
||||
XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
|
||||
False, atoms);
|
||||
|
||||
g_signal_connect (meta_shadow_factory_get_default (),
|
||||
"changed",
|
||||
G_CALLBACK (on_shadow_factory_changed),
|
||||
compositor);
|
||||
|
||||
compositor->atom_x_root_pixmap = atoms[0];
|
||||
compositor->atom_x_set_root = atoms[1];
|
||||
compositor->atom_net_wm_window_opacity = atoms[2];
|
||||
|
||||
compositor->repaint_func_id = clutter_threads_add_repaint_func (mutter_repaint_func,
|
||||
compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
|
||||
compositor,
|
||||
NULL);
|
||||
|
||||
return compositor;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_get_overlay_window: (skip)
|
||||
*
|
||||
*/
|
||||
Window
|
||||
mutter_get_overlay_window (MetaScreen *screen)
|
||||
meta_get_overlay_window (MetaScreen *screen)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "mutter-plugin.h"
|
||||
#include "mutter-module.h"
|
||||
#include "meta-plugin.h"
|
||||
#include "meta-module.h"
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
@@ -32,23 +32,23 @@ enum
|
||||
PROP_PATH,
|
||||
};
|
||||
|
||||
struct _MutterModulePrivate
|
||||
struct _MetaModulePrivate
|
||||
{
|
||||
GModule *lib;
|
||||
gchar *path;
|
||||
GType plugin_type;
|
||||
};
|
||||
|
||||
#define MUTTER_MODULE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_MODULE, MutterModulePrivate))
|
||||
#define META_MODULE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_MODULE, MetaModulePrivate))
|
||||
|
||||
G_DEFINE_TYPE (MutterModule, mutter_module, G_TYPE_TYPE_MODULE);
|
||||
G_DEFINE_TYPE (MetaModule, meta_module, G_TYPE_TYPE_MODULE);
|
||||
|
||||
static gboolean
|
||||
mutter_module_load (GTypeModule *gmodule)
|
||||
meta_module_load (GTypeModule *gmodule)
|
||||
{
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (gmodule)->priv;
|
||||
MutterPluginVersion *info = NULL;
|
||||
MetaModulePrivate *priv = META_MODULE (gmodule)->priv;
|
||||
MetaPluginVersion *info = NULL;
|
||||
GType (*register_type) (GTypeModule *) = NULL;
|
||||
|
||||
if (priv->lib && priv->plugin_type)
|
||||
@@ -64,9 +64,9 @@ mutter_module_load (GTypeModule *gmodule)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_module_symbol (priv->lib, "mutter_plugin_version",
|
||||
if (g_module_symbol (priv->lib, "meta_plugin_version",
|
||||
(gpointer *)(void *)&info) &&
|
||||
g_module_symbol (priv->lib, "mutter_plugin_register_type",
|
||||
g_module_symbol (priv->lib, "meta_plugin_register_type",
|
||||
(gpointer *)(void *)®ister_type) &&
|
||||
info && register_type)
|
||||
{
|
||||
@@ -97,9 +97,9 @@ mutter_module_load (GTypeModule *gmodule)
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_module_unload (GTypeModule *gmodule)
|
||||
meta_module_unload (GTypeModule *gmodule)
|
||||
{
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (gmodule)->priv;
|
||||
MetaModulePrivate *priv = META_MODULE (gmodule)->priv;
|
||||
|
||||
g_module_close (priv->lib);
|
||||
|
||||
@@ -108,29 +108,29 @@ mutter_module_unload (GTypeModule *gmodule)
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_module_dispose (GObject *object)
|
||||
meta_module_dispose (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (mutter_module_parent_class)->dispose (object);
|
||||
G_OBJECT_CLASS (meta_module_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_module_finalize (GObject *object)
|
||||
meta_module_finalize (GObject *object)
|
||||
{
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
|
||||
MetaModulePrivate *priv = META_MODULE (object)->priv;
|
||||
|
||||
g_free (priv->path);
|
||||
priv->path = NULL;
|
||||
|
||||
G_OBJECT_CLASS (mutter_module_parent_class)->finalize (object);
|
||||
G_OBJECT_CLASS (meta_module_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_module_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
meta_module_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
|
||||
MetaModulePrivate *priv = META_MODULE (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
@@ -145,12 +145,12 @@ mutter_module_set_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_module_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
meta_module_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
|
||||
MetaModulePrivate *priv = META_MODULE (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
@@ -164,18 +164,18 @@ mutter_module_get_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_module_class_init (MutterModuleClass *klass)
|
||||
meta_module_class_init (MetaModuleClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GTypeModuleClass *gmodule_class = G_TYPE_MODULE_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = mutter_module_finalize;
|
||||
gobject_class->dispose = mutter_module_dispose;
|
||||
gobject_class->set_property = mutter_module_set_property;
|
||||
gobject_class->get_property = mutter_module_get_property;
|
||||
gobject_class->finalize = meta_module_finalize;
|
||||
gobject_class->dispose = meta_module_dispose;
|
||||
gobject_class->set_property = meta_module_set_property;
|
||||
gobject_class->get_property = meta_module_get_property;
|
||||
|
||||
gmodule_class->load = mutter_module_load;
|
||||
gmodule_class->unload = mutter_module_unload;
|
||||
gmodule_class->load = meta_module_load;
|
||||
gmodule_class->unload = meta_module_unload;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_PATH,
|
||||
@@ -186,22 +186,22 @@ mutter_module_class_init (MutterModuleClass *klass)
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (MutterModulePrivate));
|
||||
g_type_class_add_private (gobject_class, sizeof (MetaModulePrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_module_init (MutterModule *self)
|
||||
meta_module_init (MetaModule *self)
|
||||
{
|
||||
MutterModulePrivate *priv;
|
||||
MetaModulePrivate *priv;
|
||||
|
||||
self->priv = priv = MUTTER_MODULE_GET_PRIVATE (self);
|
||||
self->priv = priv = META_MODULE_GET_PRIVATE (self);
|
||||
|
||||
}
|
||||
|
||||
GType
|
||||
mutter_module_get_plugin_type (MutterModule *module)
|
||||
meta_module_get_plugin_type (MetaModule *module)
|
||||
{
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (module)->priv;
|
||||
MetaModulePrivate *priv = META_MODULE (module)->priv;
|
||||
|
||||
return priv->plugin_type;
|
||||
}
|
||||
@@ -21,37 +21,37 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MUTTER_MODULE_H_
|
||||
#define MUTTER_MODULE_H_
|
||||
#ifndef META_MODULE_H_
|
||||
#define META_MODULE_H_
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#define MUTTER_TYPE_MODULE (mutter_module_get_type ())
|
||||
#define MUTTER_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_MODULE, MutterModule))
|
||||
#define MUTTER_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_MODULE, MutterModuleClass))
|
||||
#define MUTTER_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_MODULE_TYPE))
|
||||
#define MUTTER_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_MODULE))
|
||||
#define MUTTER_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_MODULE, MutterModuleClass))
|
||||
#define META_TYPE_MODULE (meta_module_get_type ())
|
||||
#define META_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MODULE, MetaModule))
|
||||
#define META_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MODULE, MetaModuleClass))
|
||||
#define META_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_MODULE_TYPE))
|
||||
#define META_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MODULE))
|
||||
#define META_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MODULE, MetaModuleClass))
|
||||
|
||||
typedef struct _MutterModule MutterModule;
|
||||
typedef struct _MutterModuleClass MutterModuleClass;
|
||||
typedef struct _MutterModulePrivate MutterModulePrivate;
|
||||
typedef struct _MetaModule MetaModule;
|
||||
typedef struct _MetaModuleClass MetaModuleClass;
|
||||
typedef struct _MetaModulePrivate MetaModulePrivate;
|
||||
|
||||
struct _MutterModule
|
||||
struct _MetaModule
|
||||
{
|
||||
GTypeModule parent;
|
||||
|
||||
MutterModulePrivate *priv;
|
||||
MetaModulePrivate *priv;
|
||||
};
|
||||
|
||||
struct _MutterModuleClass
|
||||
struct _MetaModuleClass
|
||||
{
|
||||
GTypeModuleClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType mutter_module_get_type (void);
|
||||
GType meta_module_get_type (void);
|
||||
|
||||
GType mutter_module_get_plugin_type (MutterModule *module);
|
||||
GType meta_module_get_plugin_type (MetaModule *module);
|
||||
|
||||
#endif
|
||||
@@ -23,11 +23,11 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "compositor-private.h"
|
||||
#include "mutter-plugin-manager.h"
|
||||
#include "meta-plugin-manager.h"
|
||||
#include "prefs.h"
|
||||
#include "errors.h"
|
||||
#include "workspace.h"
|
||||
#include "mutter-module.h"
|
||||
#include "meta-module.h"
|
||||
#include "../core/window-private.h"
|
||||
|
||||
#include <string.h>
|
||||
@@ -39,37 +39,38 @@
|
||||
*/
|
||||
static GHashTable *plugin_modules = NULL;
|
||||
|
||||
static gboolean mutter_plugin_manager_reload (MutterPluginManager *plugin_mgr);
|
||||
/*
|
||||
* We have one "default plugin manager" that acts for the first screen,
|
||||
* but also can be used before we open any screens, and additional
|
||||
* plugin managers for each screen. (This is ugly. Probably we should
|
||||
* have one plugin manager and only make the plugins per-screen.)
|
||||
*/
|
||||
|
||||
struct MutterPluginManager
|
||||
static MetaPluginManager *default_plugin_manager;
|
||||
|
||||
static gboolean meta_plugin_manager_reload (MetaPluginManager *plugin_mgr);
|
||||
|
||||
struct MetaPluginManager
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
GList /* MutterPluginPending */ *pending_plugin_modules; /* Plugins not yet fully loaded */
|
||||
GList /* MutterPlugin */ *plugins; /* TODO -- maybe use hash table */
|
||||
GList *unload; /* Plugins that are disabled and pending unload */
|
||||
GList /* MetaPlugin */ *plugins; /* TODO -- maybe use hash table */
|
||||
GList *unload; /* Plugins that are disabled and pending unload */
|
||||
|
||||
guint idle_unload_id;
|
||||
};
|
||||
|
||||
typedef struct MutterPluginPending
|
||||
{
|
||||
MutterModule *module;
|
||||
char *path;
|
||||
char *params;
|
||||
} MutterPluginPending;
|
||||
|
||||
/*
|
||||
* Checks that the plugin is compatible with the WM and sets up the plugin
|
||||
* struct.
|
||||
*/
|
||||
static MutterPlugin *
|
||||
mutter_plugin_load (MutterPluginManager *mgr,
|
||||
MutterModule *module,
|
||||
const gchar *params)
|
||||
static MetaPlugin *
|
||||
meta_plugin_load (MetaPluginManager *mgr,
|
||||
MetaModule *module,
|
||||
const gchar *params)
|
||||
{
|
||||
MutterPlugin *plugin = NULL;
|
||||
GType plugin_type = mutter_module_get_plugin_type (module);
|
||||
MetaPlugin *plugin = NULL;
|
||||
GType plugin_type = meta_module_get_plugin_type (module);
|
||||
|
||||
if (!plugin_type)
|
||||
{
|
||||
@@ -78,7 +79,6 @@ mutter_plugin_load (MutterPluginManager *mgr,
|
||||
}
|
||||
|
||||
plugin = g_object_new (plugin_type,
|
||||
"screen", mgr->screen,
|
||||
"params", params,
|
||||
NULL);
|
||||
|
||||
@@ -91,9 +91,9 @@ mutter_plugin_load (MutterPluginManager *mgr,
|
||||
* removal later.
|
||||
*/
|
||||
static gboolean
|
||||
mutter_plugin_unload (MutterPlugin *plugin)
|
||||
meta_plugin_unload (MetaPlugin *plugin)
|
||||
{
|
||||
if (mutter_plugin_running (plugin))
|
||||
if (meta_plugin_running (plugin))
|
||||
{
|
||||
g_object_set (plugin, "disabled", TRUE, NULL);
|
||||
return FALSE;
|
||||
@@ -109,16 +109,16 @@ mutter_plugin_unload (MutterPlugin *plugin)
|
||||
* pending for removal.
|
||||
*/
|
||||
static gboolean
|
||||
mutter_plugin_manager_idle_unload (MutterPluginManager *plugin_mgr)
|
||||
meta_plugin_manager_idle_unload (MetaPluginManager *plugin_mgr)
|
||||
{
|
||||
GList *l = plugin_mgr->unload;
|
||||
gboolean dont_remove = TRUE;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MutterPlugin *plugin = l->data;
|
||||
MetaPlugin *plugin = l->data;
|
||||
|
||||
if (mutter_plugin_unload (plugin))
|
||||
if (meta_plugin_unload (plugin))
|
||||
{
|
||||
/* Remove from list */
|
||||
GList *p = l->prev;
|
||||
@@ -154,23 +154,23 @@ mutter_plugin_manager_idle_unload (MutterPluginManager *plugin_mgr)
|
||||
* Unloads all plugins
|
||||
*/
|
||||
static void
|
||||
mutter_plugin_manager_unload (MutterPluginManager *plugin_mgr)
|
||||
meta_plugin_manager_unload (MetaPluginManager *plugin_mgr)
|
||||
{
|
||||
GList *plugins = plugin_mgr->plugins;
|
||||
|
||||
while (plugins)
|
||||
{
|
||||
MutterPlugin *plugin = plugins->data;
|
||||
MetaPlugin *plugin = plugins->data;
|
||||
|
||||
/* If the plugin could not be removed, move it to the unload list */
|
||||
if (!mutter_plugin_unload (plugin))
|
||||
if (!meta_plugin_unload (plugin))
|
||||
{
|
||||
plugin_mgr->unload = g_list_prepend (plugin_mgr->unload, plugin);
|
||||
|
||||
if (!plugin_mgr->idle_unload_id)
|
||||
{
|
||||
plugin_mgr->idle_unload_id = g_idle_add ((GSourceFunc)
|
||||
mutter_plugin_manager_idle_unload,
|
||||
meta_plugin_manager_idle_unload,
|
||||
plugin_mgr);
|
||||
}
|
||||
}
|
||||
@@ -186,21 +186,21 @@ static void
|
||||
prefs_changed_callback (MetaPreference pref,
|
||||
void *data)
|
||||
{
|
||||
MutterPluginManager *plugin_mgr = data;
|
||||
MetaPluginManager *plugin_mgr = data;
|
||||
|
||||
if (pref == META_PREF_CLUTTER_PLUGINS)
|
||||
{
|
||||
mutter_plugin_manager_reload (plugin_mgr);
|
||||
meta_plugin_manager_reload (plugin_mgr);
|
||||
}
|
||||
}
|
||||
|
||||
static MutterModule *
|
||||
mutter_plugin_manager_get_module (const gchar *path)
|
||||
static MetaModule *
|
||||
meta_plugin_manager_get_module (const gchar *path)
|
||||
{
|
||||
MutterModule *module = g_hash_table_lookup (plugin_modules, path);
|
||||
MetaModule *module = g_hash_table_lookup (plugin_modules, path);
|
||||
|
||||
if (!module &&
|
||||
(module = g_object_new (MUTTER_TYPE_MODULE, "path", path, NULL)))
|
||||
(module = g_object_new (META_TYPE_MODULE, "path", path, NULL)))
|
||||
{
|
||||
g_hash_table_insert (plugin_modules, g_strdup (path), module);
|
||||
}
|
||||
@@ -212,7 +212,7 @@ mutter_plugin_manager_get_module (const gchar *path)
|
||||
* Loads all plugins listed in gconf registry.
|
||||
*/
|
||||
gboolean
|
||||
mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
|
||||
meta_plugin_manager_load (MetaPluginManager *plugin_mgr)
|
||||
{
|
||||
const gchar *dpath = MUTTER_PLUGIN_DIR "/";
|
||||
GSList *plugins, *fallback = NULL;
|
||||
@@ -237,7 +237,7 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
|
||||
|
||||
if (plugin_string)
|
||||
{
|
||||
MutterModule *module;
|
||||
MetaModule *module;
|
||||
gchar *path;
|
||||
|
||||
params = strchr (plugin_string, ':');
|
||||
@@ -253,7 +253,7 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
|
||||
else
|
||||
path = g_strconcat (dpath, plugin_string, ".so", NULL);
|
||||
|
||||
module = mutter_plugin_manager_get_module (path);
|
||||
module = meta_plugin_manager_get_module (path);
|
||||
|
||||
if (module)
|
||||
{
|
||||
@@ -270,12 +270,14 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
|
||||
|
||||
if (use_succeeded)
|
||||
{
|
||||
MutterPluginPending *pending = g_new0 (MutterPluginPending, 1);
|
||||
pending->module = module;
|
||||
pending->path = g_strdup (path);
|
||||
pending->params = g_strdup (params);
|
||||
plugin_mgr->pending_plugin_modules =
|
||||
g_list_prepend (plugin_mgr->pending_plugin_modules, pending);
|
||||
MetaPlugin *plugin = meta_plugin_load (plugin_mgr, module, params);
|
||||
|
||||
if (plugin)
|
||||
plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, plugin);
|
||||
else
|
||||
g_warning ("Plugin load for [%s] failed", path);
|
||||
|
||||
g_type_module_unuse (G_TYPE_MODULE (module));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -293,7 +295,7 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
|
||||
if (fallback)
|
||||
g_slist_free (fallback);
|
||||
|
||||
if (plugin_mgr->pending_plugin_modules != NULL)
|
||||
if (plugin_mgr->plugins != NULL)
|
||||
{
|
||||
meta_prefs_add_listener (prefs_changed_callback, plugin_mgr);
|
||||
return TRUE;
|
||||
@@ -303,31 +305,23 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
|
||||
}
|
||||
|
||||
gboolean
|
||||
mutter_plugin_manager_initialize (MutterPluginManager *plugin_mgr)
|
||||
meta_plugin_manager_initialize (MetaPluginManager *plugin_mgr)
|
||||
{
|
||||
GList *iter;
|
||||
|
||||
for (iter = plugin_mgr->pending_plugin_modules; iter; iter = iter->next)
|
||||
for (iter = plugin_mgr->plugins; iter; iter = iter->next)
|
||||
{
|
||||
MutterPluginPending *pending = (MutterPluginPending*) iter->data;
|
||||
MutterPlugin *p;
|
||||
MetaPlugin *plugin = (MetaPlugin*) iter->data;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if ((p = mutter_plugin_load (plugin_mgr, pending->module, pending->params)))
|
||||
{
|
||||
plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Plugin load for [%s] failed", pending->path);
|
||||
}
|
||||
g_object_set (plugin,
|
||||
"screen", plugin_mgr->screen,
|
||||
NULL);
|
||||
|
||||
g_type_module_unuse (G_TYPE_MODULE (pending->module));
|
||||
g_free (pending->path);
|
||||
g_free (pending->params);
|
||||
g_free (pending);
|
||||
if (klass->start)
|
||||
klass->start (plugin);
|
||||
}
|
||||
g_list_free (plugin_mgr->pending_plugin_modules);
|
||||
plugin_mgr->pending_plugin_modules = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -335,7 +329,7 @@ mutter_plugin_manager_initialize (MutterPluginManager *plugin_mgr)
|
||||
* Reloads all plugins
|
||||
*/
|
||||
static gboolean
|
||||
mutter_plugin_manager_reload (MutterPluginManager *plugin_mgr)
|
||||
meta_plugin_manager_reload (MetaPluginManager *plugin_mgr)
|
||||
{
|
||||
/* TODO -- brute force; should we build a list of plugins to load and list of
|
||||
* plugins to unload? We are probably not going to have large numbers of
|
||||
@@ -343,16 +337,16 @@ mutter_plugin_manager_reload (MutterPluginManager *plugin_mgr)
|
||||
*/
|
||||
|
||||
/* Prevent stale grabs on unloaded plugins */
|
||||
mutter_check_end_modal (plugin_mgr->screen);
|
||||
meta_check_end_modal (plugin_mgr->screen);
|
||||
|
||||
mutter_plugin_manager_unload (plugin_mgr);
|
||||
return mutter_plugin_manager_load (plugin_mgr);
|
||||
meta_plugin_manager_unload (plugin_mgr);
|
||||
return meta_plugin_manager_load (plugin_mgr);
|
||||
}
|
||||
|
||||
MutterPluginManager *
|
||||
mutter_plugin_manager_new (MetaScreen *screen)
|
||||
static MetaPluginManager *
|
||||
meta_plugin_manager_new (MetaScreen *screen)
|
||||
{
|
||||
MutterPluginManager *plugin_mgr;
|
||||
MetaPluginManager *plugin_mgr;
|
||||
|
||||
if (!plugin_modules)
|
||||
{
|
||||
@@ -360,37 +354,91 @@ mutter_plugin_manager_new (MetaScreen *screen)
|
||||
NULL);
|
||||
}
|
||||
|
||||
plugin_mgr = g_new0 (MutterPluginManager, 1);
|
||||
plugin_mgr = g_new0 (MetaPluginManager, 1);
|
||||
|
||||
plugin_mgr->screen = screen;
|
||||
|
||||
if (screen)
|
||||
g_object_set_data (G_OBJECT (screen), "meta-plugin-manager", plugin_mgr);
|
||||
|
||||
return plugin_mgr;
|
||||
}
|
||||
|
||||
MetaPluginManager *
|
||||
meta_plugin_manager_get_default (void)
|
||||
{
|
||||
if (!default_plugin_manager)
|
||||
{
|
||||
default_plugin_manager = meta_plugin_manager_new (NULL);
|
||||
}
|
||||
|
||||
return default_plugin_manager;
|
||||
}
|
||||
|
||||
MetaPluginManager *
|
||||
meta_plugin_manager_get (MetaScreen *screen)
|
||||
{
|
||||
MetaPluginManager *plugin_mgr;
|
||||
|
||||
plugin_mgr = g_object_get_data (G_OBJECT (screen), "meta-plugin-manager");
|
||||
if (plugin_mgr)
|
||||
return plugin_mgr;
|
||||
|
||||
if (!default_plugin_manager)
|
||||
meta_plugin_manager_get_default ();
|
||||
|
||||
if (!default_plugin_manager->screen)
|
||||
{
|
||||
/* The default plugin manager is so far unused, we can recycle it */
|
||||
default_plugin_manager->screen = screen;
|
||||
g_object_set_data (G_OBJECT (screen), "meta-plugin-manager", default_plugin_manager);
|
||||
|
||||
return default_plugin_manager;
|
||||
}
|
||||
else
|
||||
{
|
||||
return meta_plugin_manager_new (screen);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_manager_kill_effect (MutterPluginManager *plugin_mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long events)
|
||||
meta_plugin_manager_kill_window_effects (MetaPluginManager *plugin_mgr,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
GList *l = plugin_mgr->plugins;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
MetaPlugin *plugin = l->data;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!mutter_plugin_disabled (plugin)
|
||||
&& (mutter_plugin_features (plugin) & events)
|
||||
&& klass->kill_effect)
|
||||
klass->kill_effect (plugin, actor, events);
|
||||
if (!meta_plugin_disabled (plugin)
|
||||
&& klass->kill_window_effects)
|
||||
klass->kill_window_effects (plugin, actor);
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_manager_kill_switch_workspace (MetaPluginManager *plugin_mgr)
|
||||
{
|
||||
GList *l = plugin_mgr->plugins;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaPlugin *plugin = l->data;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!meta_plugin_disabled (plugin)
|
||||
&& (meta_plugin_features (plugin) & META_PLUGIN_SWITCH_WORKSPACE)
|
||||
&& klass->kill_switch_workspace)
|
||||
klass->kill_switch_workspace (plugin);
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
#define ALL_BUT_SWITCH \
|
||||
MUTTER_PLUGIN_ALL_EFFECTS & \
|
||||
~MUTTER_PLUGIN_SWITCH_WORKSPACE
|
||||
/*
|
||||
* Public method that the compositor hooks into for events that require
|
||||
* no additional parameters.
|
||||
@@ -401,9 +449,9 @@ mutter_plugin_manager_kill_effect (MutterPluginManager *plugin_mgr,
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
mutter_plugin_manager_event_simple (MutterPluginManager *plugin_mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long event)
|
||||
meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event)
|
||||
{
|
||||
GList *l = plugin_mgr->plugins;
|
||||
gboolean retval = FALSE;
|
||||
@@ -414,44 +462,42 @@ mutter_plugin_manager_event_simple (MutterPluginManager *plugin_mgr,
|
||||
|
||||
while (l)
|
||||
{
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
MetaPlugin *plugin = l->data;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!mutter_plugin_disabled (plugin) &&
|
||||
(mutter_plugin_features (plugin) & event))
|
||||
if (!meta_plugin_disabled (plugin) &&
|
||||
(meta_plugin_features (plugin) & event))
|
||||
{
|
||||
retval = TRUE;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case MUTTER_PLUGIN_MINIMIZE:
|
||||
case META_PLUGIN_MINIMIZE:
|
||||
if (klass->minimize)
|
||||
{
|
||||
mutter_plugin_manager_kill_effect (
|
||||
meta_plugin_manager_kill_window_effects (
|
||||
plugin_mgr,
|
||||
actor,
|
||||
ALL_BUT_SWITCH);
|
||||
actor);
|
||||
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->minimize (plugin, actor);
|
||||
}
|
||||
break;
|
||||
case MUTTER_PLUGIN_MAP:
|
||||
case META_PLUGIN_MAP:
|
||||
if (klass->map)
|
||||
{
|
||||
mutter_plugin_manager_kill_effect (
|
||||
meta_plugin_manager_kill_window_effects (
|
||||
plugin_mgr,
|
||||
actor,
|
||||
ALL_BUT_SWITCH);
|
||||
actor);
|
||||
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->map (plugin, actor);
|
||||
}
|
||||
break;
|
||||
case MUTTER_PLUGIN_DESTROY:
|
||||
case META_PLUGIN_DESTROY:
|
||||
if (klass->destroy)
|
||||
{
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->destroy (plugin, actor);
|
||||
}
|
||||
break;
|
||||
@@ -476,13 +522,13 @@ mutter_plugin_manager_event_simple (MutterPluginManager *plugin_mgr,
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
mutter_plugin_manager_event_maximize (MutterPluginManager *plugin_mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long event,
|
||||
gint target_x,
|
||||
gint target_y,
|
||||
gint target_width,
|
||||
gint target_height)
|
||||
meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event,
|
||||
gint target_x,
|
||||
gint target_y,
|
||||
gint target_width,
|
||||
gint target_height)
|
||||
{
|
||||
GList *l = plugin_mgr->plugins;
|
||||
gboolean retval = FALSE;
|
||||
@@ -493,39 +539,37 @@ mutter_plugin_manager_event_maximize (MutterPluginManager *plugin_mgr,
|
||||
|
||||
while (l)
|
||||
{
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
MetaPlugin *plugin = l->data;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!mutter_plugin_disabled (plugin) &&
|
||||
(mutter_plugin_features (plugin) & event))
|
||||
if (!meta_plugin_disabled (plugin) &&
|
||||
(meta_plugin_features (plugin) & event))
|
||||
{
|
||||
retval = TRUE;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case MUTTER_PLUGIN_MAXIMIZE:
|
||||
case META_PLUGIN_MAXIMIZE:
|
||||
if (klass->maximize)
|
||||
{
|
||||
mutter_plugin_manager_kill_effect (
|
||||
meta_plugin_manager_kill_window_effects (
|
||||
plugin_mgr,
|
||||
actor,
|
||||
ALL_BUT_SWITCH);
|
||||
actor);
|
||||
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->maximize (plugin, actor,
|
||||
target_x, target_y,
|
||||
target_width, target_height);
|
||||
}
|
||||
break;
|
||||
case MUTTER_PLUGIN_UNMAXIMIZE:
|
||||
case META_PLUGIN_UNMAXIMIZE:
|
||||
if (klass->unmaximize)
|
||||
{
|
||||
mutter_plugin_manager_kill_effect (
|
||||
meta_plugin_manager_kill_window_effects (
|
||||
plugin_mgr,
|
||||
actor,
|
||||
ALL_BUT_SWITCH);
|
||||
actor);
|
||||
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->unmaximize (plugin, actor,
|
||||
target_x, target_y,
|
||||
target_width, target_height);
|
||||
@@ -551,11 +595,10 @@ mutter_plugin_manager_event_maximize (MutterPluginManager *plugin_mgr,
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
mutter_plugin_manager_switch_workspace (MutterPluginManager *plugin_mgr,
|
||||
const GList **actors,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction)
|
||||
meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction)
|
||||
{
|
||||
GList *l = plugin_mgr->plugins;
|
||||
gboolean retval = FALSE;
|
||||
@@ -566,23 +609,19 @@ mutter_plugin_manager_switch_workspace (MutterPluginManager *plugin_mgr,
|
||||
|
||||
while (l)
|
||||
{
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
MetaPlugin *plugin = l->data;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!mutter_plugin_disabled (plugin) &&
|
||||
(mutter_plugin_features (plugin) & MUTTER_PLUGIN_SWITCH_WORKSPACE) &&
|
||||
(actors && *actors))
|
||||
if (!meta_plugin_disabled (plugin) &&
|
||||
(meta_plugin_features (plugin) & META_PLUGIN_SWITCH_WORKSPACE))
|
||||
{
|
||||
if (klass->switch_workspace)
|
||||
{
|
||||
retval = TRUE;
|
||||
mutter_plugin_manager_kill_effect (
|
||||
plugin_mgr,
|
||||
MUTTER_WINDOW ((*actors)->data),
|
||||
MUTTER_PLUGIN_SWITCH_WORKSPACE);
|
||||
meta_plugin_manager_kill_switch_workspace (plugin_mgr);
|
||||
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
klass->switch_workspace (plugin, actors, from, to, direction);
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->switch_workspace (plugin, from, to, direction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,8 +640,8 @@ mutter_plugin_manager_switch_workspace (MutterPluginManager *plugin_mgr,
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
mutter_plugin_manager_xevent_filter (MutterPluginManager *plugin_mgr,
|
||||
XEvent *xev)
|
||||
meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
|
||||
XEvent *xev)
|
||||
{
|
||||
GList *l;
|
||||
gboolean have_plugin_xevent_func;
|
||||
@@ -632,8 +671,8 @@ mutter_plugin_manager_xevent_filter (MutterPluginManager *plugin_mgr,
|
||||
|
||||
while (l)
|
||||
{
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
MetaPlugin *plugin = l->data;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (klass->xevent_filter)
|
||||
{
|
||||
78
src/compositor/meta-plugin-manager.h
Normal file
78
src/compositor/meta-plugin-manager.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Intel Corp.
|
||||
*
|
||||
* Author: Tomas Frydrych <tf@linux.intel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_PLUGIN_MANAGER_H_
|
||||
#define META_PLUGIN_MANAGER_H_
|
||||
|
||||
#include "types.h"
|
||||
#include "screen.h"
|
||||
|
||||
#define META_PLUGIN_FROM_MANAGER_
|
||||
#include "meta-plugin.h"
|
||||
#undef META_PLUGIN_FROM_MANAGER_
|
||||
|
||||
#define META_PLUGIN_MINIMIZE (1<<0)
|
||||
#define META_PLUGIN_MAXIMIZE (1<<1)
|
||||
#define META_PLUGIN_UNMAXIMIZE (1<<2)
|
||||
#define META_PLUGIN_MAP (1<<3)
|
||||
#define META_PLUGIN_DESTROY (1<<4)
|
||||
#define META_PLUGIN_SWITCH_WORKSPACE (1<<5)
|
||||
|
||||
#define META_PLUGIN_ALL_EFFECTS (~0)
|
||||
|
||||
/**
|
||||
* MetaPluginManager: (skip)
|
||||
*
|
||||
*/
|
||||
typedef struct MetaPluginManager MetaPluginManager;
|
||||
|
||||
MetaPluginManager * meta_plugin_manager_get (MetaScreen *screen);
|
||||
MetaPluginManager * meta_plugin_manager_get_default (void);
|
||||
|
||||
gboolean meta_plugin_manager_load (MetaPluginManager *mgr);
|
||||
gboolean meta_plugin_manager_initialize (MetaPluginManager *plugin_mgr);
|
||||
gboolean meta_plugin_manager_event_simple (MetaPluginManager *mgr,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event);
|
||||
|
||||
gboolean meta_plugin_manager_event_maximize (MetaPluginManager *mgr,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event,
|
||||
gint target_x,
|
||||
gint target_y,
|
||||
gint target_width,
|
||||
gint target_height);
|
||||
void meta_plugin_manager_update_workspaces (MetaPluginManager *mgr);
|
||||
|
||||
void meta_plugin_manager_update_workspace (MetaPluginManager *mgr,
|
||||
MetaWorkspace *w);
|
||||
|
||||
gboolean meta_plugin_manager_switch_workspace (MetaPluginManager *mgr,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction);
|
||||
|
||||
gboolean meta_plugin_manager_xevent_filter (MetaPluginManager *mgr,
|
||||
XEvent *xev);
|
||||
|
||||
#endif
|
||||
@@ -21,7 +21,7 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "mutter-plugin.h"
|
||||
#include "meta-plugin.h"
|
||||
#include "screen.h"
|
||||
#include "display.h"
|
||||
|
||||
@@ -32,12 +32,12 @@
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
#include "compositor-private.h"
|
||||
#include "mutter-window-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (MutterPlugin, mutter_plugin, G_TYPE_OBJECT);
|
||||
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
|
||||
|
||||
#define MUTTER_PLUGIN_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_PLUGIN, MutterPluginPrivate))
|
||||
#define META_PLUGIN_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_PLUGIN, MetaPluginPrivate))
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -49,7 +49,7 @@ enum
|
||||
PROP_DEBUG_MODE,
|
||||
};
|
||||
|
||||
struct _MutterPluginPrivate
|
||||
struct _MetaPluginPrivate
|
||||
{
|
||||
MetaScreen *screen;
|
||||
gchar *params;
|
||||
@@ -62,51 +62,51 @@ struct _MutterPluginPrivate
|
||||
};
|
||||
|
||||
static void
|
||||
mutter_plugin_dispose (GObject *object)
|
||||
meta_plugin_dispose (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (mutter_plugin_parent_class)->dispose (object);
|
||||
G_OBJECT_CLASS (meta_plugin_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_finalize (GObject *object)
|
||||
meta_plugin_finalize (GObject *object)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
|
||||
|
||||
g_free (priv->params);
|
||||
priv->params = NULL;
|
||||
|
||||
G_OBJECT_CLASS (mutter_plugin_parent_class)->finalize (object);
|
||||
G_OBJECT_CLASS (meta_plugin_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_parse_params (MutterPlugin *plugin)
|
||||
meta_plugin_parse_params (MetaPlugin *plugin)
|
||||
{
|
||||
char *p;
|
||||
gulong features = 0;
|
||||
MutterPluginPrivate *priv = plugin->priv;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
MetaPluginPrivate *priv = plugin->priv;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
/*
|
||||
* Feature flags: identify events that the plugin can handle; a plugin can
|
||||
* handle one or more events.
|
||||
*/
|
||||
if (klass->minimize)
|
||||
features |= MUTTER_PLUGIN_MINIMIZE;
|
||||
features |= META_PLUGIN_MINIMIZE;
|
||||
|
||||
if (klass->maximize)
|
||||
features |= MUTTER_PLUGIN_MAXIMIZE;
|
||||
features |= META_PLUGIN_MAXIMIZE;
|
||||
|
||||
if (klass->unmaximize)
|
||||
features |= MUTTER_PLUGIN_UNMAXIMIZE;
|
||||
features |= META_PLUGIN_UNMAXIMIZE;
|
||||
|
||||
if (klass->map)
|
||||
features |= MUTTER_PLUGIN_MAP;
|
||||
features |= META_PLUGIN_MAP;
|
||||
|
||||
if (klass->destroy)
|
||||
features |= MUTTER_PLUGIN_DESTROY;
|
||||
features |= META_PLUGIN_DESTROY;
|
||||
|
||||
if (klass->switch_workspace)
|
||||
features |= MUTTER_PLUGIN_SWITCH_WORKSPACE;
|
||||
features |= META_PLUGIN_SWITCH_WORKSPACE;
|
||||
|
||||
if (priv->params)
|
||||
{
|
||||
@@ -122,22 +122,22 @@ mutter_plugin_parse_params (MutterPlugin *plugin)
|
||||
*p = 0;
|
||||
|
||||
if (strstr (d, "minimize"))
|
||||
features &= ~ MUTTER_PLUGIN_MINIMIZE;
|
||||
features &= ~ META_PLUGIN_MINIMIZE;
|
||||
|
||||
if (strstr (d, "maximize"))
|
||||
features &= ~ MUTTER_PLUGIN_MAXIMIZE;
|
||||
features &= ~ META_PLUGIN_MAXIMIZE;
|
||||
|
||||
if (strstr (d, "unmaximize"))
|
||||
features &= ~ MUTTER_PLUGIN_UNMAXIMIZE;
|
||||
features &= ~ META_PLUGIN_UNMAXIMIZE;
|
||||
|
||||
if (strstr (d, "map"))
|
||||
features &= ~ MUTTER_PLUGIN_MAP;
|
||||
features &= ~ META_PLUGIN_MAP;
|
||||
|
||||
if (strstr (d, "destroy"))
|
||||
features &= ~ MUTTER_PLUGIN_DESTROY;
|
||||
features &= ~ META_PLUGIN_DESTROY;
|
||||
|
||||
if (strstr (d, "switch-workspace"))
|
||||
features &= ~MUTTER_PLUGIN_SWITCH_WORKSPACE;
|
||||
features &= ~META_PLUGIN_SWITCH_WORKSPACE;
|
||||
|
||||
g_free (d);
|
||||
}
|
||||
@@ -162,12 +162,12 @@ mutter_plugin_parse_params (MutterPlugin *plugin)
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
meta_plugin_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
@@ -176,7 +176,7 @@ mutter_plugin_set_property (GObject *object,
|
||||
break;
|
||||
case PROP_PARAMS:
|
||||
priv->params = g_value_dup_string (value);
|
||||
mutter_plugin_parse_params (MUTTER_PLUGIN (object));
|
||||
meta_plugin_parse_params (META_PLUGIN (object));
|
||||
break;
|
||||
case PROP_DISABLED:
|
||||
priv->disabled = g_value_get_boolean (value);
|
||||
@@ -191,12 +191,12 @@ mutter_plugin_set_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
meta_plugin_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
@@ -223,14 +223,14 @@ mutter_plugin_get_property (GObject *object,
|
||||
|
||||
|
||||
static void
|
||||
mutter_plugin_class_init (MutterPluginClass *klass)
|
||||
meta_plugin_class_init (MetaPluginClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = mutter_plugin_finalize;
|
||||
gobject_class->dispose = mutter_plugin_dispose;
|
||||
gobject_class->set_property = mutter_plugin_set_property;
|
||||
gobject_class->get_property = mutter_plugin_get_property;
|
||||
gobject_class->finalize = meta_plugin_finalize;
|
||||
gobject_class->dispose = meta_plugin_dispose;
|
||||
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,
|
||||
@@ -238,8 +238,7 @@ mutter_plugin_class_init (MutterPluginClass *klass)
|
||||
"MetaScreen",
|
||||
"MetaScreen",
|
||||
META_TYPE_SCREEN,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_PARAMS,
|
||||
@@ -274,53 +273,53 @@ mutter_plugin_class_init (MutterPluginClass *klass)
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (MutterPluginPrivate));
|
||||
g_type_class_add_private (gobject_class, sizeof (MetaPluginPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_init (MutterPlugin *self)
|
||||
meta_plugin_init (MetaPlugin *self)
|
||||
{
|
||||
MutterPluginPrivate *priv;
|
||||
MetaPluginPrivate *priv;
|
||||
|
||||
self->priv = priv = MUTTER_PLUGIN_GET_PRIVATE (self);
|
||||
self->priv = priv = META_PLUGIN_GET_PRIVATE (self);
|
||||
}
|
||||
|
||||
gulong
|
||||
mutter_plugin_features (MutterPlugin *plugin)
|
||||
meta_plugin_features (MetaPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->features;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mutter_plugin_disabled (MutterPlugin *plugin)
|
||||
meta_plugin_disabled (MetaPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->disabled;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mutter_plugin_running (MutterPlugin *plugin)
|
||||
meta_plugin_running (MetaPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return (priv->running > 0);
|
||||
}
|
||||
|
||||
gboolean
|
||||
mutter_plugin_debug_mode (MutterPlugin *plugin)
|
||||
meta_plugin_debug_mode (MetaPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->debug;
|
||||
}
|
||||
|
||||
const MutterPluginInfo *
|
||||
mutter_plugin_get_info (MutterPlugin *plugin)
|
||||
const MetaPluginInfo *
|
||||
meta_plugin_get_info (MetaPlugin *plugin)
|
||||
{
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (klass && klass->plugin_info)
|
||||
return klass->plugin_info (plugin);
|
||||
@@ -329,50 +328,66 @@ mutter_plugin_get_info (MutterPlugin *plugin)
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_plugin_get_overlay_group (MutterPlugin *plugin)
|
||||
meta_plugin_get_overlay_group (MetaPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return mutter_get_overlay_group_for_screen (priv->screen);
|
||||
return meta_get_overlay_group_for_screen (priv->screen);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_plugin_get_stage (MutterPlugin *plugin)
|
||||
meta_plugin_get_stage (MetaPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return mutter_get_stage_for_screen (priv->screen);
|
||||
return meta_get_stage_for_screen (priv->screen);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_plugin_get_window_group (MutterPlugin *plugin)
|
||||
meta_plugin_get_window_group (MetaPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return mutter_get_window_group_for_screen (priv->screen);
|
||||
return meta_get_window_group_for_screen (priv->screen);
|
||||
}
|
||||
|
||||
/**
|
||||
* _mutter_plugin_effect_started:
|
||||
* _meta_plugin_effect_started:
|
||||
* @plugin: the plugin
|
||||
*
|
||||
* Mark that an effect has started for the plugin. This is called
|
||||
* internally by MutterPluginManager.
|
||||
* internally by MetaPluginManager.
|
||||
*/
|
||||
void
|
||||
_mutter_plugin_effect_started (MutterPlugin *plugin)
|
||||
_meta_plugin_effect_started (MetaPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
priv->running++;
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_effect_completed (MutterPlugin *plugin,
|
||||
MutterWindow *actor,
|
||||
unsigned long event)
|
||||
meta_plugin_switch_workspace_completed (MetaPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
MetaScreen *screen = meta_plugin_get_screen (plugin);
|
||||
|
||||
if (priv->running-- < 0)
|
||||
{
|
||||
g_warning ("Error in running effect accounting, adjusting.");
|
||||
priv->running = 0;
|
||||
}
|
||||
|
||||
meta_switch_workspace_completed (screen);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_window_effect_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
if (priv->running-- < 0)
|
||||
{
|
||||
@@ -382,57 +397,82 @@ mutter_plugin_effect_completed (MutterPlugin *plugin,
|
||||
|
||||
if (!actor)
|
||||
{
|
||||
const MutterPluginInfo *info;
|
||||
const MetaPluginInfo *info;
|
||||
const gchar *name = NULL;
|
||||
|
||||
if (plugin && (info = mutter_plugin_get_info (plugin)))
|
||||
if (plugin && (info = meta_plugin_get_info (plugin)))
|
||||
name = info->name;
|
||||
|
||||
g_warning ("Plugin [%s] passed NULL for actor!",
|
||||
name ? name : "unknown");
|
||||
}
|
||||
|
||||
if (event == MUTTER_PLUGIN_SWITCH_WORKSPACE)
|
||||
{
|
||||
/* The window is just used to identify the screen */
|
||||
MetaWindow *window = mutter_window_get_meta_window (actor);
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
mutter_switch_workspace_completed (screen);
|
||||
}
|
||||
else
|
||||
{
|
||||
mutter_window_effect_completed (actor, event);
|
||||
}
|
||||
meta_window_actor_effect_completed (actor, event);
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_query_screen_size (MutterPlugin *plugin,
|
||||
int *width,
|
||||
int *height)
|
||||
meta_plugin_minimize_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MINIMIZE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_maximize_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MAXIMIZE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_unmaximize_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_UNMAXIMIZE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_map_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MAP);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_destroy_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_DESTROY);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_query_screen_size (MetaPlugin *plugin,
|
||||
int *width,
|
||||
int *height)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
meta_screen_get_size (priv->screen, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_set_stage_reactive (MutterPlugin *plugin,
|
||||
gboolean reactive)
|
||||
meta_plugin_set_stage_reactive (MetaPlugin *plugin,
|
||||
gboolean reactive)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
|
||||
if (reactive)
|
||||
mutter_set_stage_input_region (screen, None);
|
||||
meta_set_stage_input_region (screen, None);
|
||||
else
|
||||
mutter_empty_stage_input_region (screen);
|
||||
meta_empty_stage_input_region (screen);
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_set_stage_input_area (MutterPlugin *plugin,
|
||||
gint x, gint y, gint width, gint height)
|
||||
meta_plugin_set_stage_input_area (MetaPlugin *plugin,
|
||||
gint x, gint y, gint width, gint height)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
@@ -445,31 +485,43 @@ mutter_plugin_set_stage_input_area (MutterPlugin *plugin,
|
||||
rect.height = height;
|
||||
|
||||
region = XFixesCreateRegion (xdpy, &rect, 1);
|
||||
mutter_set_stage_input_region (screen, region);
|
||||
meta_set_stage_input_region (screen, region);
|
||||
XFixesDestroyRegion (xdpy, region);
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_set_stage_input_region (MutterPlugin *plugin,
|
||||
XserverRegion region)
|
||||
meta_plugin_set_stage_input_region (MetaPlugin *plugin,
|
||||
XserverRegion region)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
|
||||
mutter_set_stage_input_region (screen, region);
|
||||
}
|
||||
|
||||
GList *
|
||||
mutter_plugin_get_windows (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return mutter_get_windows (priv->screen);
|
||||
meta_set_stage_input_region (screen, region);
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_plugin_begin_modal:
|
||||
* @plugin: a #MutterPlugin
|
||||
* meta_plugin_get_window_actors:
|
||||
* @plugin: A #MetaPlugin
|
||||
*
|
||||
* This function returns all of the #MetaWindowActor objects referenced by Mutter, including
|
||||
* override-redirect windows. The returned list is a snapshot of Mutter's current
|
||||
* stacking order, with the topmost window last.
|
||||
*
|
||||
* The 'restacked' signal of #MetaScreen signals when this value has changed.
|
||||
*
|
||||
* Returns: (transfer none) (element-type MetaWindowActor): Windows in stacking order, topmost last
|
||||
*/
|
||||
GList *
|
||||
meta_plugin_get_window_actors (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return meta_get_window_actors (priv->screen);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_plugin_begin_modal:
|
||||
* @plugin: a #MetaPlugin
|
||||
* @grab_window: the X window to grab the keyboard and mouse on
|
||||
* @cursor: the cursor to use for the pointer grab, or None,
|
||||
* to use the normal cursor for the grab window and
|
||||
@@ -480,7 +532,7 @@ mutter_plugin_get_windows (MutterPlugin *plugin)
|
||||
* This function is used to grab the keyboard and mouse for the exclusive
|
||||
* use of the plugin. Correct operation requires that both the keyboard
|
||||
* and mouse are grabbed, or thing will break. (In particular, other
|
||||
* passive X grabs in Mutter can trigger but not be handled by the normal
|
||||
* passive X grabs in Meta can trigger but not be handled by the normal
|
||||
* keybinding handling code.) However, the plugin can establish the keyboard
|
||||
* and/or mouse grabs ahead of time and pass in the
|
||||
* %META_MODAL_POINTER_ALREADY_GRABBED and/or %META_MODAL_KEYBOARD_ALREADY_GRABBED
|
||||
@@ -493,21 +545,21 @@ mutter_plugin_get_windows (MutterPlugin *plugin)
|
||||
* mouse and made the plugin modal.
|
||||
*/
|
||||
gboolean
|
||||
mutter_plugin_begin_modal (MutterPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
meta_plugin_begin_modal (MetaPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return mutter_begin_modal_for_plugin (priv->screen, plugin,
|
||||
grab_window, cursor, options, timestamp);
|
||||
return meta_begin_modal_for_plugin (priv->screen, plugin,
|
||||
grab_window, cursor, options, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_plugin_end_modal
|
||||
* @plugin: a #MutterPlugin
|
||||
* meta_plugin_end_modal
|
||||
* @plugin: a #MetaPlugin
|
||||
* @timestamp: the time used for releasing grabs
|
||||
*
|
||||
* Ends the modal operation begun with meta_plugin_begin_modal(). This
|
||||
@@ -517,27 +569,27 @@ mutter_plugin_begin_modal (MutterPlugin *plugin,
|
||||
* when beginnning the modal operation.
|
||||
*/
|
||||
void
|
||||
mutter_plugin_end_modal (MutterPlugin *plugin,
|
||||
guint32 timestamp)
|
||||
meta_plugin_end_modal (MetaPlugin *plugin,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
mutter_end_modal_for_plugin (priv->screen, plugin, timestamp);
|
||||
meta_end_modal_for_plugin (priv->screen, plugin, timestamp);
|
||||
}
|
||||
|
||||
Display *
|
||||
mutter_plugin_get_xdisplay (MutterPlugin *plugin)
|
||||
meta_plugin_get_xdisplay (MetaPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaDisplay *display = meta_screen_get_display (priv->screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
MetaDisplay *display = meta_screen_get_display (priv->screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
|
||||
return xdpy;
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_plugin_get_screen:
|
||||
* @plugin: a #MutterPlugin
|
||||
* 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
|
||||
@@ -546,9 +598,9 @@ mutter_plugin_get_xdisplay (MutterPlugin *plugin)
|
||||
* Return value: (transfer none): the #MetaScreen for the plugin
|
||||
*/
|
||||
MetaScreen *
|
||||
mutter_plugin_get_screen (MutterPlugin *plugin)
|
||||
meta_plugin_get_screen (MetaPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->screen;
|
||||
}
|
||||
65
src/compositor/meta-shadow-factory-private.h
Normal file
65
src/compositor/meta-shadow-factory-private.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaShadowFactory:
|
||||
*
|
||||
* Create and cache shadow textures for arbitrary window shapes
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __META_SHADOW_FACTORY_PRIVATE_H__
|
||||
#define __META_SHADOW_FACTORY_PRIVATE_H__
|
||||
|
||||
#include <cairo.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include "meta-window-shape.h"
|
||||
#include "meta-shadow-factory.h"
|
||||
|
||||
/**
|
||||
* MetaShadow:
|
||||
* #MetaShadow holds a shadow texture along with information about how to
|
||||
* apply that texture to draw a window texture. (E.g., it knows how big the
|
||||
* unscaled borders are on each side of the shadow texture.)
|
||||
*/
|
||||
typedef struct _MetaShadow MetaShadow;
|
||||
|
||||
MetaShadow *meta_shadow_ref (MetaShadow *shadow);
|
||||
void meta_shadow_unref (MetaShadow *shadow);
|
||||
CoglHandle meta_shadow_get_texture (MetaShadow *shadow);
|
||||
void meta_shadow_paint (MetaShadow *shadow,
|
||||
int window_x,
|
||||
int window_y,
|
||||
int window_width,
|
||||
int window_height,
|
||||
guint8 opacity,
|
||||
cairo_region_t *clip);
|
||||
void meta_shadow_get_bounds (MetaShadow *shadow,
|
||||
int window_x,
|
||||
int window_y,
|
||||
int window_width,
|
||||
int window_height,
|
||||
cairo_rectangle_int_t *bounds);
|
||||
|
||||
MetaShadow *meta_shadow_factory_get_shadow (MetaShadowFactory *factory,
|
||||
MetaWindowShape *shape,
|
||||
int width,
|
||||
int height,
|
||||
const char *class_name,
|
||||
gboolean focused);
|
||||
|
||||
#endif /* __META_SHADOW_FACTORY_PRIVATE_H__ */
|
||||
1032
src/compositor/meta-shadow-factory.c
Normal file
1032
src/compositor/meta-shadow-factory.c
Normal file
File diff suppressed because it is too large
Load Diff
635
src/compositor/meta-shaped-texture.c
Normal file
635
src/compositor/meta-shaped-texture.c
Normal file
@@ -0,0 +1,635 @@
|
||||
/*
|
||||
* shaped texture
|
||||
*
|
||||
* An actor to draw a texture clipped to a list of rectangles
|
||||
*
|
||||
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "meta-shaped-texture.h"
|
||||
#include "meta-texture-tower.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
#include <string.h>
|
||||
|
||||
static void meta_shaped_texture_dispose (GObject *object);
|
||||
static void meta_shaped_texture_finalize (GObject *object);
|
||||
static void meta_shaped_texture_notify (GObject *object,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static void meta_shaped_texture_paint (ClutterActor *actor);
|
||||
static void meta_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color);
|
||||
|
||||
static void meta_shaped_texture_update_area (ClutterX11TexturePixmap *texture,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
static void meta_shaped_texture_dirty_mask (MetaShapedTexture *stex);
|
||||
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
|
||||
CLUTTER_GLX_TYPE_TEXTURE_PIXMAP);
|
||||
#else /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
|
||||
CLUTTER_X11_TYPE_TEXTURE_PIXMAP);
|
||||
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
|
||||
#define META_SHAPED_TEXTURE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \
|
||||
MetaShapedTexturePrivate))
|
||||
|
||||
struct _MetaShapedTexturePrivate
|
||||
{
|
||||
MetaTextureTower *paint_tower;
|
||||
CoglHandle mask_texture;
|
||||
CoglHandle material;
|
||||
CoglHandle material_unshaped;
|
||||
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
guint mask_width, mask_height;
|
||||
|
||||
GArray *rectangles;
|
||||
|
||||
guint create_mipmaps : 1;
|
||||
};
|
||||
|
||||
static void
|
||||
meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
||||
ClutterX11TexturePixmapClass *x11_texture_class = (ClutterX11TexturePixmapClass *) klass;
|
||||
|
||||
gobject_class->dispose = meta_shaped_texture_dispose;
|
||||
gobject_class->finalize = meta_shaped_texture_finalize;
|
||||
gobject_class->notify = meta_shaped_texture_notify;
|
||||
|
||||
actor_class->paint = meta_shaped_texture_paint;
|
||||
actor_class->pick = meta_shaped_texture_pick;
|
||||
|
||||
x11_texture_class->update_area = meta_shaped_texture_update_area;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_init (MetaShapedTexture *self)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
priv = self->priv = META_SHAPED_TEXTURE_GET_PRIVATE (self);
|
||||
|
||||
priv->rectangles = g_array_new (FALSE, FALSE, sizeof (XRectangle));
|
||||
|
||||
priv->paint_tower = meta_texture_tower_new ();
|
||||
priv->mask_texture = COGL_INVALID_HANDLE;
|
||||
priv->create_mipmaps = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_dispose (GObject *object)
|
||||
{
|
||||
MetaShapedTexture *self = (MetaShapedTexture *) object;
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
if (priv->paint_tower)
|
||||
meta_texture_tower_free (priv->paint_tower);
|
||||
priv->paint_tower = NULL;
|
||||
|
||||
meta_shaped_texture_dirty_mask (self);
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (priv->material);
|
||||
priv->material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
if (priv->material_unshaped != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (priv->material_unshaped);
|
||||
priv->material_unshaped = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
meta_shaped_texture_set_clip_region (self, NULL);
|
||||
|
||||
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_finalize (GObject *object)
|
||||
{
|
||||
MetaShapedTexture *self = (MetaShapedTexture *) object;
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
g_array_free (priv->rectangles, TRUE);
|
||||
|
||||
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_notify (GObject *object,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
if (G_OBJECT_CLASS (meta_shaped_texture_parent_class)->notify)
|
||||
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->notify (object, pspec);
|
||||
|
||||
/* It seems like we could just do this out of update_area(), but unfortunately,
|
||||
* clutter_glx_texture_pixmap() doesn't call through the vtable on the
|
||||
* initial update_area, so we need to look for changes to the texture
|
||||
* explicitly.
|
||||
*/
|
||||
if (strcmp (pspec->name, "cogl-texture") == 0)
|
||||
{
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) object;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
meta_shaped_texture_clear (stex);
|
||||
|
||||
if (priv->create_mipmaps)
|
||||
meta_texture_tower_set_base_texture (priv->paint_tower,
|
||||
clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_dirty_mask (MetaShapedTexture *stex)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
if (priv->mask_texture != COGL_INVALID_HANDLE)
|
||||
{
|
||||
GLuint mask_gl_tex;
|
||||
GLenum mask_gl_target;
|
||||
|
||||
cogl_texture_get_gl_texture (priv->mask_texture,
|
||||
&mask_gl_tex, &mask_gl_target);
|
||||
|
||||
if (mask_gl_target == GL_TEXTURE_RECTANGLE_ARB)
|
||||
glDeleteTextures (1, &mask_gl_tex);
|
||||
|
||||
cogl_handle_unref (priv->mask_texture);
|
||||
priv->mask_texture = COGL_INVALID_HANDLE;
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
cogl_material_set_layer (priv->material, 1, COGL_INVALID_HANDLE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_ensure_mask (MetaShapedTexture *stex)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
CoglHandle paint_tex;
|
||||
guint tex_width, tex_height;
|
||||
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
/* If the mask texture we have was created for a different size then
|
||||
recreate it */
|
||||
if (priv->mask_texture != COGL_INVALID_HANDLE
|
||||
&& (priv->mask_width != tex_width || priv->mask_height != tex_height))
|
||||
meta_shaped_texture_dirty_mask (stex);
|
||||
|
||||
/* If we don't have a mask texture yet then create one */
|
||||
if (priv->mask_texture == COGL_INVALID_HANDLE)
|
||||
{
|
||||
guchar *mask_data;
|
||||
const XRectangle *rect;
|
||||
GLenum paint_gl_target;
|
||||
|
||||
/* Create data for an empty image */
|
||||
mask_data = g_malloc0 (tex_width * tex_height);
|
||||
|
||||
/* Cut out a hole for each rectangle */
|
||||
for (rect = (XRectangle *) priv->rectangles->data
|
||||
+ priv->rectangles->len;
|
||||
rect-- > (XRectangle *) priv->rectangles->data;)
|
||||
{
|
||||
gint x1 = rect->x, x2 = x1 + rect->width;
|
||||
gint y1 = rect->y, y2 = y1 + rect->height;
|
||||
guchar *p;
|
||||
|
||||
/* Clip the rectangle to the size of the texture */
|
||||
x1 = CLAMP (x1, 0, (gint) tex_width - 1);
|
||||
x2 = CLAMP (x2, x1, (gint) tex_width);
|
||||
y1 = CLAMP (y1, 0, (gint) tex_height - 1);
|
||||
y2 = CLAMP (y2, y1, (gint) tex_height);
|
||||
|
||||
/* Fill the rectangle */
|
||||
for (p = mask_data + y1 * tex_width + x1;
|
||||
y1 < y2;
|
||||
y1++, p += tex_width)
|
||||
memset (p, 255, x2 - x1);
|
||||
}
|
||||
|
||||
cogl_texture_get_gl_texture (paint_tex, NULL, &paint_gl_target);
|
||||
|
||||
if (paint_gl_target == GL_TEXTURE_RECTANGLE_ARB)
|
||||
{
|
||||
GLuint tex;
|
||||
|
||||
glGenTextures (1, &tex);
|
||||
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex);
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, tex_width);
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
|
||||
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
|
||||
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0,
|
||||
GL_ALPHA, tex_width, tex_height,
|
||||
0, GL_ALPHA, GL_UNSIGNED_BYTE, mask_data);
|
||||
|
||||
priv->mask_texture
|
||||
= cogl_texture_new_from_foreign (tex,
|
||||
GL_TEXTURE_RECTANGLE_ARB,
|
||||
tex_width, tex_height,
|
||||
0, 0,
|
||||
COGL_PIXEL_FORMAT_A_8);
|
||||
}
|
||||
else
|
||||
priv->mask_texture = cogl_texture_new_from_data (tex_width, tex_height,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_A_8,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
tex_width,
|
||||
mask_data);
|
||||
|
||||
g_free (mask_data);
|
||||
|
||||
priv->mask_width = tex_width;
|
||||
priv->mask_height = tex_height;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
CoglHandle paint_tex;
|
||||
guint tex_width, tex_height;
|
||||
ClutterActorBox alloc;
|
||||
|
||||
static CoglHandle material_template = COGL_INVALID_HANDLE;
|
||||
static CoglHandle material_unshaped_template = COGL_INVALID_HANDLE;
|
||||
|
||||
CoglHandle material;
|
||||
|
||||
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
||||
return;
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
|
||||
clutter_actor_realize (CLUTTER_ACTOR (stex));
|
||||
|
||||
/* The GL EXT_texture_from_pixmap extension does allow for it to be
|
||||
* used together with SGIS_generate_mipmap, however this is very
|
||||
* rarely supported. Also, even when it is supported there
|
||||
* are distinct performance implications from:
|
||||
*
|
||||
* - Updating mipmaps that we don't need
|
||||
* - Having to reallocate pixmaps on the server into larger buffers
|
||||
*
|
||||
* So, we just unconditionally use our mipmap emulation code. If we
|
||||
* wanted to use SGIS_generate_mipmap, we'd have to query COGL to
|
||||
* see if it was supported (no API currently), and then if and only
|
||||
* if that was the case, set the clutter texture quality to HIGH.
|
||||
* Setting the texture quality to high without SGIS_generate_mipmap
|
||||
* support for TFP textures will result in fallbacks to XGetImage.
|
||||
*/
|
||||
if (priv->create_mipmaps)
|
||||
paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
|
||||
else
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
if (priv->rectangles->len < 1)
|
||||
{
|
||||
/* If there are no rectangles use a single-layer texture */
|
||||
|
||||
if (priv->material_unshaped == COGL_INVALID_HANDLE)
|
||||
{
|
||||
if (G_UNLIKELY (material_unshaped_template == COGL_INVALID_HANDLE))
|
||||
material_unshaped_template = cogl_material_new ();
|
||||
|
||||
priv->material_unshaped = cogl_material_copy (material_unshaped_template);
|
||||
}
|
||||
material = priv->material_unshaped;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_shaped_texture_ensure_mask (stex);
|
||||
|
||||
if (priv->material == COGL_INVALID_HANDLE)
|
||||
{
|
||||
if (G_UNLIKELY (material_template == COGL_INVALID_HANDLE))
|
||||
{
|
||||
material_template = cogl_material_new ();
|
||||
cogl_material_set_layer_combine (material_template, 1,
|
||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
||||
NULL);
|
||||
}
|
||||
priv->material = cogl_material_copy (material_template);
|
||||
}
|
||||
material = priv->material;
|
||||
|
||||
cogl_material_set_layer (material, 1, priv->mask_texture);
|
||||
}
|
||||
|
||||
cogl_material_set_layer (material, 0, paint_tex);
|
||||
|
||||
{
|
||||
CoglColor color;
|
||||
guchar opacity = clutter_actor_get_paint_opacity (actor);
|
||||
cogl_color_set_from_4ub (&color, opacity, opacity, opacity, opacity);
|
||||
cogl_material_set_color (material, &color);
|
||||
}
|
||||
|
||||
cogl_set_source (material);
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &alloc);
|
||||
|
||||
if (priv->clip_region)
|
||||
{
|
||||
int n_rects;
|
||||
int i;
|
||||
|
||||
/* Limit to how many separate rectangles we'll draw; beyond this just
|
||||
* fall back and draw the whole thing */
|
||||
# define MAX_RECTS 16
|
||||
|
||||
n_rects = cairo_region_num_rectangles (priv->clip_region);
|
||||
if (n_rects <= MAX_RECTS)
|
||||
{
|
||||
float coords[8];
|
||||
float x1, y1, x2, y2;
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (priv->clip_region, i, &rect);
|
||||
|
||||
x1 = rect.x;
|
||||
y1 = rect.y;
|
||||
x2 = rect.x + rect.width;
|
||||
y2 = rect.y + rect.height;
|
||||
|
||||
coords[0] = rect.x / (alloc.x2 - alloc.x1);
|
||||
coords[1] = rect.y / (alloc.y2 - alloc.y1);
|
||||
coords[2] = (rect.x + rect.width) / (alloc.x2 - alloc.x1);
|
||||
coords[3] = (rect.y + rect.height) / (alloc.y2 - alloc.y1);
|
||||
|
||||
coords[4] = coords[0];
|
||||
coords[5] = coords[1];
|
||||
coords[6] = coords[2];
|
||||
coords[7] = coords[3];
|
||||
|
||||
cogl_rectangle_with_multitexture_coords (x1, y1, x2, y2,
|
||||
&coords[0], 8);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cogl_rectangle (0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
/* If there are no rectangles then use the regular pick */
|
||||
if (priv->rectangles->len < 1)
|
||||
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)
|
||||
->pick (actor, color);
|
||||
else if (clutter_actor_should_pick_paint (actor))
|
||||
{
|
||||
CoglHandle paint_tex;
|
||||
ClutterActorBox alloc;
|
||||
guint tex_width, tex_height;
|
||||
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
meta_shaped_texture_ensure_mask (stex);
|
||||
|
||||
cogl_set_source_color4ub (color->red, color->green, color->blue,
|
||||
color->alpha);
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &alloc);
|
||||
|
||||
/* Paint the mask rectangle in the given color */
|
||||
cogl_set_source_texture (priv->mask_texture);
|
||||
cogl_rectangle_with_texture_coords (0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1,
|
||||
0, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_update_area (ClutterX11TexturePixmap *texture,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) texture;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
CLUTTER_X11_TEXTURE_PIXMAP_CLASS (meta_shaped_texture_parent_class)->update_area (texture,
|
||||
x, y, width, height);
|
||||
|
||||
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
meta_shaped_texture_new (void)
|
||||
{
|
||||
ClutterActor *self = g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
|
||||
gboolean create_mipmaps)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
create_mipmaps = create_mipmaps != FALSE;
|
||||
|
||||
if (create_mipmaps != priv->create_mipmaps)
|
||||
{
|
||||
CoglHandle base_texture;
|
||||
|
||||
priv->create_mipmaps = create_mipmaps;
|
||||
|
||||
base_texture = create_mipmaps ?
|
||||
clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)) : COGL_INVALID_HANDLE;
|
||||
|
||||
meta_texture_tower_set_base_texture (priv->paint_tower, base_texture);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a workaround for deficiencies in the hack tower:
|
||||
*
|
||||
* When we call clutter_x11_texture_pixmap_set_pixmap(tp, None),
|
||||
* ClutterX11TexturePixmap knows that it has to get rid of the old texture, but
|
||||
* clutter_texture_set_cogl_texture(texture, COGL_INVALID_HANDLE) isn't allowed, so
|
||||
* it grabs the material for the texture and manually sets the texture in it. This means
|
||||
* that the "cogl-texture" property isn't notified, so we don't find out about it.
|
||||
*
|
||||
* And if we keep the CoglX11TexturePixmap around after the X pixmap is freed, then
|
||||
* we'll trigger X errors when we actually try to free it.
|
||||
*
|
||||
* The only correct thing to do here is to change our code to derive
|
||||
* from ClutterActor and get rid of the inheritance hack tower. Once
|
||||
* we want to depend on Clutter-1.4 (which has CoglTexturePixmapX11),
|
||||
* that will be very easy to do.
|
||||
*/
|
||||
void
|
||||
meta_shaped_texture_clear (MetaShapedTexture *stex)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
meta_texture_tower_set_base_texture (priv->paint_tower, COGL_INVALID_HANDLE);
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
cogl_material_set_layer (priv->material, 0, COGL_INVALID_HANDLE);
|
||||
|
||||
if (priv->material_unshaped != COGL_INVALID_HANDLE)
|
||||
cogl_material_set_layer (priv->material_unshaped, 0, COGL_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_clear_rectangles (MetaShapedTexture *stex)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
g_array_set_size (priv->rectangles, 0);
|
||||
meta_shaped_texture_dirty_mask (stex);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_add_rectangle (MetaShapedTexture *stex,
|
||||
const XRectangle *rect)
|
||||
{
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
meta_shaped_texture_add_rectangles (stex, 1, rect);
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_add_rectangles (MetaShapedTexture *stex,
|
||||
size_t num_rects,
|
||||
const XRectangle *rects)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
g_array_append_vals (priv->rectangles, rects, num_rects);
|
||||
|
||||
meta_shaped_texture_dirty_mask (stex);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_clip_region:
|
||||
* @frame: a #TidyTextureframe
|
||||
* @clip_region: (transfer full): the region of the texture that
|
||||
* is visible and should be painted. OWNERSHIP IS ASSUMED BY
|
||||
* THE FUNCTION (for efficiency to avoid a copy.)
|
||||
*
|
||||
* Provides a hint to the texture about what areas of the texture
|
||||
* are not completely obscured and thus need to be painted. This
|
||||
* is an optimization and is not supposed to have any effect on
|
||||
* the output.
|
||||
*
|
||||
* Typically a parent container will set the clip region before
|
||||
* painting its children, and then unset it afterwards.
|
||||
*/
|
||||
void
|
||||
meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->clip_region)
|
||||
{
|
||||
cairo_region_destroy (priv->clip_region);
|
||||
priv->clip_region = NULL;
|
||||
}
|
||||
|
||||
priv->clip_region = clip_region;
|
||||
}
|
||||
92
src/compositor/meta-shaped-texture.h
Normal file
92
src/compositor/meta-shaped-texture.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* shaped texture
|
||||
*
|
||||
* An actor to draw a texture clipped to a list of rectangles
|
||||
*
|
||||
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __META_SHAPED_TEXTURE_H__
|
||||
#define __META_SHAPED_TEXTURE_H__
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
#include <clutter/glx/clutter-glx.h>
|
||||
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_SHAPED_TEXTURE (meta_shaped_texture_get_type())
|
||||
#define META_SHAPED_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),META_TYPE_SHAPED_TEXTURE, MetaShapedTexture))
|
||||
#define META_SHAPED_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SHAPED_TEXTURE, MetaShapedTextureClass))
|
||||
#define META_IS_SHAPED_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SHAPED_TEXTURE))
|
||||
#define META_IS_SHAPED_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SHAPED_TEXTURE))
|
||||
#define META_SHAPED_TEXTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SHAPED_TEXTURE, MetaShapedTextureClass))
|
||||
|
||||
typedef struct _MetaShapedTexture MetaShapedTexture;
|
||||
typedef struct _MetaShapedTextureClass MetaShapedTextureClass;
|
||||
typedef struct _MetaShapedTexturePrivate MetaShapedTexturePrivate;
|
||||
|
||||
struct _MetaShapedTextureClass
|
||||
{
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
ClutterGLXTexturePixmapClass parent_class;
|
||||
#else
|
||||
ClutterX11TexturePixmapClass parent_class;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _MetaShapedTexture
|
||||
{
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
ClutterGLXTexturePixmap parent;
|
||||
#else
|
||||
ClutterX11TexturePixmap parent;
|
||||
#endif
|
||||
|
||||
MetaShapedTexturePrivate *priv;
|
||||
};
|
||||
|
||||
GType meta_shaped_texture_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *meta_shaped_texture_new (void);
|
||||
|
||||
void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
|
||||
gboolean create_mipmaps);
|
||||
|
||||
void meta_shaped_texture_clear (MetaShapedTexture *stex);
|
||||
|
||||
void meta_shaped_texture_clear_rectangles (MetaShapedTexture *stex);
|
||||
|
||||
void meta_shaped_texture_add_rectangle (MetaShapedTexture *stex,
|
||||
const XRectangle *rect);
|
||||
void meta_shaped_texture_add_rectangles (MetaShapedTexture *stex,
|
||||
size_t num_rects,
|
||||
const XRectangle *rects);
|
||||
|
||||
/* Assumes ownership of clip_region */
|
||||
void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __META_SHAPED_TEXTURE_H__ */
|
||||
654
src/compositor/meta-texture-tower.c
Normal file
654
src/compositor/meta-texture-tower.c
Normal file
@@ -0,0 +1,654 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaTextureTower
|
||||
*
|
||||
* Mipmap emulation by creation of scaled down images
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "meta-texture-tower.h"
|
||||
|
||||
#ifndef M_LOG2E
|
||||
#define M_LOG2E 1.4426950408889634074
|
||||
#endif
|
||||
|
||||
#define MAX_TEXTURE_LEVELS 12
|
||||
|
||||
/* If the texture format in memory doesn't match this, then Mesa
|
||||
* will do the conversion, so things will still work, but it might
|
||||
* be slow depending on how efficient Mesa is. These should be the
|
||||
* native formats unless the display is 16bpp. If conversions
|
||||
* here are a bottleneck, investigate whether we are converting when
|
||||
* storing window data *into* the texture before adding extra code
|
||||
* to handle multiple texture formats.
|
||||
*/
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_BGRA_8888_PRE
|
||||
#else
|
||||
#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_ARGB_8888_PRE
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint16 x1;
|
||||
guint16 y1;
|
||||
guint16 x2;
|
||||
guint16 y2;
|
||||
} Box;
|
||||
|
||||
struct _MetaTextureTower
|
||||
{
|
||||
int n_levels;
|
||||
CoglHandle textures[MAX_TEXTURE_LEVELS];
|
||||
CoglHandle fbos[MAX_TEXTURE_LEVELS];
|
||||
Box invalid[MAX_TEXTURE_LEVELS];
|
||||
};
|
||||
|
||||
/**
|
||||
* meta_texture_tower_new:
|
||||
*
|
||||
* Creates a new texture tower. The base texture has to be set with
|
||||
* meta_texture_tower_set_base_texture() before use.
|
||||
*
|
||||
* Return value: the new texture tower. Free with meta_texture_tower_free()
|
||||
*/
|
||||
MetaTextureTower *
|
||||
meta_texture_tower_new (void)
|
||||
{
|
||||
MetaTextureTower *tower;
|
||||
|
||||
tower = g_slice_new0 (MetaTextureTower);
|
||||
|
||||
return tower;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_free:
|
||||
* @tower: a #MetaTextureTower
|
||||
*
|
||||
* Frees a texture tower created with meta_texture_tower_new().
|
||||
*/
|
||||
void
|
||||
meta_texture_tower_free (MetaTextureTower *tower)
|
||||
{
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
meta_texture_tower_set_base_texture (tower, COGL_INVALID_HANDLE);
|
||||
|
||||
g_slice_free (MetaTextureTower, tower);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
texture_is_rectangle (CoglHandle texture)
|
||||
{
|
||||
GLuint gl_tex;
|
||||
GLenum gl_target;
|
||||
|
||||
cogl_texture_get_gl_texture (texture, &gl_tex, &gl_target);
|
||||
return gl_target == GL_TEXTURE_RECTANGLE_ARB;
|
||||
}
|
||||
|
||||
static void
|
||||
free_texture (CoglHandle texture)
|
||||
{
|
||||
GLuint gl_tex;
|
||||
GLenum gl_target;
|
||||
|
||||
cogl_texture_get_gl_texture (texture, &gl_tex, &gl_target);
|
||||
|
||||
if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
|
||||
glDeleteTextures (1, &gl_tex);
|
||||
|
||||
cogl_handle_unref (texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_update_area:
|
||||
* @tower: a MetaTextureTower
|
||||
* @texture: the new texture used as a base for scaled down versions
|
||||
*
|
||||
* Sets the base texture that is the scaled texture that the
|
||||
* scaled textures of the tower are derived from. The texture itself
|
||||
* will be used as level 0 of the tower and will be referenced until
|
||||
* unset or until the tower is freed.
|
||||
*/
|
||||
void
|
||||
meta_texture_tower_set_base_texture (MetaTextureTower *tower,
|
||||
CoglHandle texture)
|
||||
{
|
||||
int i;
|
||||
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
if (texture == tower->textures[0])
|
||||
return;
|
||||
|
||||
if (tower->textures[0] != COGL_INVALID_HANDLE)
|
||||
{
|
||||
for (i = 1; i < tower->n_levels; i++)
|
||||
{
|
||||
if (tower->textures[i] != COGL_INVALID_HANDLE)
|
||||
{
|
||||
free_texture (tower->textures[i]);
|
||||
tower->textures[i] = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (tower->fbos[i] != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (tower->fbos[i]);
|
||||
tower->fbos[i] = COGL_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
cogl_handle_unref (tower->textures[0]);
|
||||
}
|
||||
|
||||
tower->textures[0] = texture;
|
||||
|
||||
if (tower->textures[0] != COGL_INVALID_HANDLE)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
cogl_handle_ref (tower->textures[0]);
|
||||
|
||||
width = cogl_texture_get_width (tower->textures[0]);
|
||||
height = cogl_texture_get_height (tower->textures[0]);
|
||||
|
||||
tower->n_levels = 1 + MAX ((int)(M_LOG2E * log (width)), (int)(M_LOG2E * log (height)));
|
||||
tower->n_levels = MIN(tower->n_levels, MAX_TEXTURE_LEVELS);
|
||||
|
||||
meta_texture_tower_update_area (tower, 0, 0, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
tower->n_levels = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_update_area:
|
||||
* @tower: a MetaTextureTower
|
||||
* @x: X coordinate of upper left of rectangle that changed
|
||||
* @y: Y coordinate of upper left of rectangle that changed
|
||||
* @width: width of rectangle that changed
|
||||
* @height: height rectangle that changed
|
||||
*
|
||||
* Mark a region of the base texture as having changed; the next
|
||||
* time a scaled down version of the base texture is retrieved,
|
||||
* the appropriate area of the scaled down texture will be updated.
|
||||
*/
|
||||
void
|
||||
meta_texture_tower_update_area (MetaTextureTower *tower,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
int texture_width, texture_height;
|
||||
Box invalid;
|
||||
int i;
|
||||
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
texture_width = cogl_texture_get_width (tower->textures[0]);
|
||||
texture_height = cogl_texture_get_height (tower->textures[0]);
|
||||
|
||||
invalid.x1 = x;
|
||||
invalid.y1 = y;
|
||||
invalid.x2 = x + width;
|
||||
invalid.y2 = y + height;
|
||||
|
||||
for (i = 1; i < tower->n_levels; i++)
|
||||
{
|
||||
texture_width = MAX (1, texture_width / 2);
|
||||
texture_height = MAX (1, texture_height / 2);
|
||||
|
||||
invalid.x1 = invalid.x1 / 2;
|
||||
invalid.y1 = invalid.y1 / 2;
|
||||
invalid.x2 = MIN (texture_width, (invalid.x2 + 1) / 2);
|
||||
invalid.y2 = MIN (texture_height, (invalid.y2 + 1) / 2);
|
||||
|
||||
if (tower->invalid[i].x1 == tower->invalid[i].x2 ||
|
||||
tower->invalid[i].y1 == tower->invalid[i].y2)
|
||||
{
|
||||
tower->invalid[i] = invalid;
|
||||
}
|
||||
else
|
||||
{
|
||||
tower->invalid[i].x1 = MIN (tower->invalid[i].x1, invalid.x1);
|
||||
tower->invalid[i].y1 = MIN (tower->invalid[i].y1, invalid.y1);
|
||||
tower->invalid[i].x2 = MAX (tower->invalid[i].x2, invalid.x2);
|
||||
tower->invalid[i].y2 = MAX (tower->invalid[i].y2, invalid.y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* It generally looks worse if we scale up a window texture by even a
|
||||
* small amount than if we scale it down using bilinear filtering, so
|
||||
* we always pick the *larger* adjacent level. */
|
||||
#define LOD_BIAS (-0.49)
|
||||
|
||||
/* This determines the appropriate level of detail to use when drawing the
|
||||
* texture, in a way that corresponds to what the GL specification does
|
||||
* when mip-mapping. This is probably fancier and slower than what we need,
|
||||
* but we do the computation only once each time we paint a window, and
|
||||
* its easier to just use the equations from the specification than to
|
||||
* come up with something simpler.
|
||||
*
|
||||
* If window is being painted at an angle from the viewer, then we have to
|
||||
* pick a point in the texture; we use the middle of the texture (which is
|
||||
* why the width/height are passed in.) This is not the normal case for
|
||||
* Meta.
|
||||
*/
|
||||
static int
|
||||
get_paint_level (int width, int height)
|
||||
{
|
||||
CoglMatrix projection, modelview, pm;
|
||||
float v[4];
|
||||
double viewport_width, viewport_height;
|
||||
double u0, v0;
|
||||
double xc, yc, wc;
|
||||
double dxdu_, dxdv_, dydu_, dydv_;
|
||||
double det_, det_sq;
|
||||
double rho_sq;
|
||||
double lambda;
|
||||
|
||||
/* See
|
||||
* http://www.opengl.org/registry/doc/glspec32.core.20090803.pdf
|
||||
* Section 3.8.9, p. 1.6.2. Here we have
|
||||
*
|
||||
* u(x,y) = x_o;
|
||||
* v(x,y) = y_o;
|
||||
*
|
||||
* Since we are mapping 1:1 from object coordinates into pixel
|
||||
* texture coordinates, the clip coordinates are:
|
||||
*
|
||||
* (x_c) (x_o) (u)
|
||||
* (y_c) = (M_projection)(M_modelview) (y_o) = (PM) (v)
|
||||
* (z_c) (z_o) (0)
|
||||
* (w_c) (w_o) (1)
|
||||
*/
|
||||
|
||||
cogl_get_projection_matrix (&projection);
|
||||
cogl_get_modelview_matrix (&modelview);
|
||||
|
||||
cogl_matrix_multiply (&pm, &projection, &modelview);
|
||||
|
||||
cogl_get_viewport (v);
|
||||
viewport_width = v[2];
|
||||
viewport_height = v[3];
|
||||
|
||||
u0 = width / 2.;
|
||||
v0 = height / 2.;
|
||||
|
||||
xc = pm.xx * u0 + pm.xy * v0 + pm.xw;
|
||||
yc = pm.yx * u0 + pm.yy * v0 + pm.yw;
|
||||
wc = pm.wx * u0 + pm.wy * v0 + pm.ww;
|
||||
|
||||
/* We'll simplify the equations below for a bit of micro-optimization.
|
||||
* The commented out code is the unsimplified version.
|
||||
|
||||
// Partial derivates of window coordinates:
|
||||
//
|
||||
// x_w = 0.5 * viewport_width * x_c / w_c + viewport_center_x
|
||||
// y_w = 0.5 * viewport_height * y_c / w_c + viewport_center_y
|
||||
//
|
||||
// with respect to u, v, using
|
||||
// d(a/b)/dx = da/dx * (1/b) - a * db/dx / (b^2)
|
||||
|
||||
dxdu = 0.5 * viewport_width * (pm.xx - pm.wx * (xc/wc)) / wc;
|
||||
dxdv = 0.5 * viewport_width * (pm.xy - pm.wy * (xc/wc)) / wc;
|
||||
dydu = 0.5 * viewport_height * (pm.yx - pm.wx * (yc/wc)) / wc;
|
||||
dydv = 0.5 * viewport_height * (pm.yy - pm.wy * (yc/wc)) / wc;
|
||||
|
||||
// Compute the inverse partials as the matrix inverse
|
||||
det = dxdu * dydv - dxdv * dydu;
|
||||
|
||||
dudx = dydv / det;
|
||||
dudy = - dxdv / det;
|
||||
dvdx = - dydu / det;
|
||||
dvdy = dvdu / det;
|
||||
|
||||
// Scale factor; maximum of the distance in texels for a change of 1 pixel
|
||||
// in the X direction or 1 pixel in the Y direction
|
||||
rho = MAX (sqrt (dudx * dudx + dvdx * dvdx), sqrt(dudy * dudy + dvdy * dvdy));
|
||||
|
||||
// Level of detail
|
||||
lambda = log2 (rho) + LOD_BIAS;
|
||||
*/
|
||||
|
||||
/* dxdu * wc, etc */
|
||||
dxdu_ = 0.5 * viewport_width * (pm.xx - pm.wx * (xc/wc));
|
||||
dxdv_ = 0.5 * viewport_width * (pm.xy - pm.wy * (xc/wc));
|
||||
dydu_ = 0.5 * viewport_height * (pm.yx - pm.wx * (yc/wc));
|
||||
dydv_ = 0.5 * viewport_height * (pm.yy - pm.wy * (yc/wc));
|
||||
|
||||
/* det * wc^2 */
|
||||
det_ = dxdu_ * dydv_ - dxdv_ * dydu_;
|
||||
det_sq = det_ * det_;
|
||||
if (det_sq == 0.0)
|
||||
return -1;
|
||||
|
||||
/* (rho * det * wc)^2 */
|
||||
rho_sq = MAX (dydv_ * dydv_ + dydu_ * dydu_, dxdv_ * dxdv_ + dxdu_ * dxdu_);
|
||||
lambda = 0.5 * M_LOG2E * log (rho_sq * wc * wc / det_sq) + LOD_BIAS;
|
||||
|
||||
#if 0
|
||||
g_print ("%g %g %g\n", 0.5 * viewport_width * pm.xx / pm.ww, 0.5 * viewport_height * pm.yy / pm.ww, lambda);
|
||||
#endif
|
||||
|
||||
if (lambda <= 0.)
|
||||
return 0;
|
||||
else
|
||||
return (int)(0.5 + lambda);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_power_of_two (int x)
|
||||
{
|
||||
return (x & (x - 1)) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_create_texture (MetaTextureTower *tower,
|
||||
int level,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if ((!is_power_of_two (width) || !is_power_of_two (height)) &&
|
||||
texture_is_rectangle (tower->textures[level - 1]))
|
||||
{
|
||||
GLuint tex = 0;
|
||||
|
||||
glGenTextures (1, &tex);
|
||||
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex);
|
||||
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0,
|
||||
GL_RGBA, width,height,
|
||||
#if TEXTURE_FORMAT == COGL_PIXEL_FORMAT_BGRA_8888_PRE
|
||||
0, GL_BGRA, GL_UNSIGNED_BYTE,
|
||||
#else /* assume big endian */
|
||||
0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
#endif
|
||||
NULL);
|
||||
|
||||
tower->textures[level] = cogl_texture_new_from_foreign (tex, GL_TEXTURE_RECTANGLE_ARB,
|
||||
width, height,
|
||||
0, 0,
|
||||
TEXTURE_FORMAT);
|
||||
}
|
||||
else
|
||||
{
|
||||
tower->textures[level] = cogl_texture_new_with_size (width, height,
|
||||
COGL_TEXTURE_NO_AUTO_MIPMAP,
|
||||
TEXTURE_FORMAT);
|
||||
}
|
||||
|
||||
tower->invalid[level].x1 = 0;
|
||||
tower->invalid[level].y1 = 0;
|
||||
tower->invalid[level].x2 = width;
|
||||
tower->invalid[level].y2 = height;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
texture_tower_revalidate_fbo (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
CoglHandle source_texture = tower->textures[level - 1];
|
||||
int source_texture_width = cogl_texture_get_width (source_texture);
|
||||
int source_texture_height = cogl_texture_get_height (source_texture);
|
||||
CoglHandle dest_texture = tower->textures[level];
|
||||
int dest_texture_width = cogl_texture_get_width (dest_texture);
|
||||
int dest_texture_height = cogl_texture_get_height (dest_texture);
|
||||
Box *invalid = &tower->invalid[level];
|
||||
CoglMatrix modelview;
|
||||
|
||||
if (tower->fbos[level] == COGL_INVALID_HANDLE)
|
||||
{
|
||||
/* Work around http://bugzilla.openedhand.com/show_bug.cgi?id=2110 */
|
||||
cogl_flush();
|
||||
|
||||
tower->fbos[level] = cogl_offscreen_new_to_texture (dest_texture);
|
||||
}
|
||||
|
||||
if (tower->fbos[level] == COGL_INVALID_HANDLE)
|
||||
return FALSE;
|
||||
|
||||
cogl_push_framebuffer (tower->fbos[level]);
|
||||
|
||||
cogl_ortho (0, dest_texture_width, dest_texture_height, 0, -1., 1.);
|
||||
|
||||
cogl_matrix_init_identity (&modelview);
|
||||
cogl_set_modelview_matrix (&modelview);
|
||||
|
||||
cogl_set_source_texture (tower->textures[level - 1]);
|
||||
cogl_rectangle_with_texture_coords (invalid->x1, invalid->y1,
|
||||
invalid->x2, invalid->y2,
|
||||
(2. * invalid->x1) / source_texture_width,
|
||||
(2. * invalid->y1) / source_texture_height,
|
||||
(2. * invalid->x2) / source_texture_width,
|
||||
(2. * invalid->y2) / source_texture_height);
|
||||
|
||||
cogl_pop_framebuffer ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fill_copy (guchar *buf,
|
||||
const guchar *source,
|
||||
int width)
|
||||
{
|
||||
memcpy (buf, source, width * 4);
|
||||
}
|
||||
|
||||
static void
|
||||
fill_scale_down (guchar *buf,
|
||||
const guchar *source,
|
||||
int width)
|
||||
{
|
||||
while (width > 1)
|
||||
{
|
||||
buf[0] = (source[0] + source[4]) / 2;
|
||||
buf[1] = (source[1] + source[5]) / 2;
|
||||
buf[2] = (source[2] + source[6]) / 2;
|
||||
buf[3] = (source[3] + source[7]) / 2;
|
||||
|
||||
buf += 4;
|
||||
source += 8;
|
||||
width -= 2;
|
||||
}
|
||||
|
||||
if (width > 0)
|
||||
{
|
||||
buf[0] = source[0] / 2;
|
||||
buf[1] = source[1] / 2;
|
||||
buf[2] = source[2] / 2;
|
||||
buf[3] = source[3] / 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_revalidate_client (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
CoglHandle source_texture = tower->textures[level - 1];
|
||||
int source_texture_width = cogl_texture_get_width (source_texture);
|
||||
int source_texture_height = cogl_texture_get_height (source_texture);
|
||||
guint source_rowstride;
|
||||
guchar *source_data;
|
||||
CoglHandle dest_texture = tower->textures[level];
|
||||
int dest_texture_width = cogl_texture_get_width (dest_texture);
|
||||
int dest_texture_height = cogl_texture_get_height (dest_texture);
|
||||
int dest_x = tower->invalid[level].x1;
|
||||
int dest_y = tower->invalid[level].y1;
|
||||
int dest_width = tower->invalid[level].x2 - tower->invalid[level].x1;
|
||||
int dest_height = tower->invalid[level].y2 - tower->invalid[level].y1;
|
||||
guchar *dest_data;
|
||||
guchar *source_tmp1 = NULL, *source_tmp2 = NULL;
|
||||
int i, j;
|
||||
|
||||
source_rowstride = source_texture_width * 4;
|
||||
|
||||
source_data = g_malloc (source_texture_height * source_rowstride);
|
||||
cogl_texture_get_data (source_texture, TEXTURE_FORMAT, source_rowstride,
|
||||
source_data);
|
||||
|
||||
dest_data = g_malloc (dest_height * dest_width * 4);
|
||||
|
||||
if (dest_texture_height < source_texture_height)
|
||||
{
|
||||
source_tmp1 = g_malloc (dest_width * 4);
|
||||
source_tmp2 = g_malloc (dest_width * 4);
|
||||
}
|
||||
|
||||
for (i = 0; i < dest_height; i++)
|
||||
{
|
||||
guchar *dest_row = dest_data + i * dest_width * 4;
|
||||
if (dest_texture_height < source_texture_height)
|
||||
{
|
||||
guchar *source1, *source2;
|
||||
guchar *dest;
|
||||
|
||||
if (dest_texture_width < source_texture_width)
|
||||
{
|
||||
fill_scale_down (source_tmp1,
|
||||
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
fill_scale_down (source_tmp2,
|
||||
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
fill_copy (source_tmp1,
|
||||
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 4,
|
||||
dest_width);
|
||||
fill_copy (source_tmp2,
|
||||
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 4,
|
||||
dest_width);
|
||||
}
|
||||
|
||||
source1 = source_tmp1;
|
||||
source2 = source_tmp2;
|
||||
|
||||
dest = dest_row;
|
||||
for (j = 0; j < dest_width * 4; j++)
|
||||
*(dest++) = (*(source1++) + *(source2++)) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dest_texture_width < source_texture_width)
|
||||
fill_scale_down (dest_row,
|
||||
source_data + (i + dest_y) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
else
|
||||
fill_copy (dest_row,
|
||||
source_data + (i + dest_y) * source_rowstride,
|
||||
dest_width);
|
||||
}
|
||||
}
|
||||
|
||||
cogl_texture_set_region (dest_texture,
|
||||
0, 0,
|
||||
dest_x, dest_y,
|
||||
dest_width, dest_height,
|
||||
dest_width, dest_height,
|
||||
TEXTURE_FORMAT,
|
||||
4 * dest_width,
|
||||
dest_data);
|
||||
|
||||
if (dest_height < source_texture_height)
|
||||
{
|
||||
g_free (source_tmp1);
|
||||
g_free (source_tmp2);
|
||||
}
|
||||
|
||||
g_free (source_data);
|
||||
g_free (dest_data);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_revalidate (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
if (!texture_tower_revalidate_fbo (tower, level))
|
||||
texture_tower_revalidate_client (tower, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_get_paint_texture:
|
||||
* @tower: a MetaTextureTower
|
||||
*
|
||||
* Gets the texture from the tower that best matches the current
|
||||
* rendering scale. (On the assumption here the texture is going to
|
||||
* be rendered with vertex coordinates that correspond to its
|
||||
* size in pixels, so a 200x200 texture will be rendered on the
|
||||
* rectangle (0, 0, 200, 200).
|
||||
*
|
||||
* Return value: the COGL texture handle to use for painting, or
|
||||
* %COGL_INVALID_HANDLE if no base texture has yet been set.
|
||||
*/
|
||||
CoglHandle
|
||||
meta_texture_tower_get_paint_texture (MetaTextureTower *tower)
|
||||
{
|
||||
int texture_width, texture_height;
|
||||
int level;
|
||||
|
||||
g_return_val_if_fail (tower != NULL, COGL_INVALID_HANDLE);
|
||||
|
||||
if (tower->textures[0] == COGL_INVALID_HANDLE)
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
texture_width = cogl_texture_get_width (tower->textures[0]);
|
||||
texture_height = cogl_texture_get_height (tower->textures[0]);
|
||||
|
||||
level = get_paint_level(texture_width, texture_height);
|
||||
if (level < 0) /* singular paint matrix, scaled to nothing */
|
||||
return COGL_INVALID_HANDLE;
|
||||
level = MIN (level, tower->n_levels - 1);
|
||||
|
||||
if (tower->textures[level] == COGL_INVALID_HANDLE ||
|
||||
(tower->invalid[level].x2 != tower->invalid[level].x1 &&
|
||||
tower->invalid[level].y2 != tower->invalid[level].y1))
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= level; i++)
|
||||
{
|
||||
/* Use "floor" convention here to be consistent with the NPOT texture extension */
|
||||
texture_width = MAX (1, texture_width / 2);
|
||||
texture_height = MAX (1, texture_height / 2);
|
||||
|
||||
if (tower->textures[i] == COGL_INVALID_HANDLE)
|
||||
texture_tower_create_texture (tower, i, texture_width, texture_height);
|
||||
}
|
||||
|
||||
for (i = 1; i <= level; i++)
|
||||
{
|
||||
if (tower->invalid[level].x2 != tower->invalid[level].x1 &&
|
||||
tower->invalid[level].y2 != tower->invalid[level].y1)
|
||||
texture_tower_revalidate (tower, i);
|
||||
}
|
||||
}
|
||||
|
||||
return tower->textures[level];
|
||||
}
|
||||
69
src/compositor/meta-texture-tower.h
Normal file
69
src/compositor/meta-texture-tower.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaTextureTower
|
||||
*
|
||||
* Mipmap emulation by creation of scaled down images
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __META_TEXTURE_TOWER_H__
|
||||
#define __META_TEXTURE_TOWER_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* SECTION:MetaTextureTower
|
||||
* @short_description: mipmap emulation by creation of scaled down images
|
||||
*
|
||||
* A #MetaTextureTower is used to get good looking scaled down images when
|
||||
* we can't use the GL drivers mipmap support. There are two separate reasons
|
||||
*
|
||||
* - Some cards (including radeon cards <= r5xx) only support
|
||||
* TEXTURE_RECTANGLE_ARB and not NPOT textures. Rectangular textures
|
||||
* are defined not to support mipmapping.
|
||||
* - Even when NPOT textures are available, the combination of NPOT
|
||||
* textures, texture_from_pixmap, and mipmapping doesn't typically
|
||||
* work, since the X server doesn't allocate pixmaps in the right
|
||||
* layout for mipmapping.
|
||||
*
|
||||
* So, what we do is create the "mipmap" levels ourselves by successive
|
||||
* power-of-two scaledowns, and when rendering pick the single texture
|
||||
* that best matches the scale we are rendering at. (Since we aren't
|
||||
* typically using perspective transforms, we'll frequently have a single
|
||||
* scale for the entire texture.)
|
||||
*/
|
||||
|
||||
typedef struct _MetaTextureTower MetaTextureTower;
|
||||
|
||||
MetaTextureTower *meta_texture_tower_new (void);
|
||||
void meta_texture_tower_free (MetaTextureTower *tower);
|
||||
void meta_texture_tower_set_base_texture (MetaTextureTower *tower,
|
||||
CoglHandle texture);
|
||||
void meta_texture_tower_update_area (MetaTextureTower *tower,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
CoglHandle meta_texture_tower_get_paint_texture (MetaTextureTower *tower);
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#endif /* __META_TEXTURE_TOWER_H__ */
|
||||
53
src/compositor/meta-window-actor-private.h
Normal file
53
src/compositor/meta-window-actor-private.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#ifndef META_WINDOW_ACTOR_PRIVATE_H
|
||||
#define META_WINDOW_ACTOR_PRIVATE_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#include "compositor-mutter.h"
|
||||
|
||||
MetaWindowActor *meta_window_actor_new (MetaWindow *window);
|
||||
|
||||
void meta_window_actor_destroy (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_show (MetaWindowActor *self,
|
||||
MetaCompEffect effect);
|
||||
void meta_window_actor_hide (MetaWindowActor *self,
|
||||
MetaCompEffect effect);
|
||||
|
||||
void meta_window_actor_maximize (MetaWindowActor *self,
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
void meta_window_actor_unmaximize (MetaWindowActor *self,
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
|
||||
void meta_window_actor_process_damage (MetaWindowActor *self,
|
||||
XDamageNotifyEvent *event);
|
||||
void meta_window_actor_pre_paint (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_invalidate_shadow (MetaWindowActor *self);
|
||||
|
||||
gboolean meta_window_actor_effect_in_progress (MetaWindowActor *self);
|
||||
void meta_window_actor_sync_actor_position (MetaWindowActor *self);
|
||||
void meta_window_actor_sync_visibility (MetaWindowActor *self);
|
||||
void meta_window_actor_update_shape (MetaWindowActor *self,
|
||||
gboolean shaped);
|
||||
void meta_window_actor_update_opacity (MetaWindowActor *self);
|
||||
void meta_window_actor_mapped (MetaWindowActor *self);
|
||||
void meta_window_actor_unmapped (MetaWindowActor *self);
|
||||
|
||||
cairo_region_t *meta_window_actor_get_obscured_region (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_set_visible_region (MetaWindowActor *self,
|
||||
cairo_region_t *visible_region);
|
||||
void meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
|
||||
cairo_region_t *beneath_region);
|
||||
void meta_window_actor_reset_visible_regions (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_effect_completed (MetaWindowActor *actor,
|
||||
gulong event);
|
||||
|
||||
#endif /* META_WINDOW_ACTOR_PRIVATE_H */
|
||||
2091
src/compositor/meta-window-actor.c
Normal file
2091
src/compositor/meta-window-actor.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,24 +1,26 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#define _ISOC99_SOURCE /* for roundf */
|
||||
#include <math.h>
|
||||
|
||||
#include "mutter-window-private.h"
|
||||
#include "mutter-window-group.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-window-group.h"
|
||||
|
||||
struct _MutterWindowGroupClass
|
||||
struct _MetaWindowGroupClass
|
||||
{
|
||||
ClutterGroupClass parent_class;
|
||||
};
|
||||
|
||||
struct _MutterWindowGroup
|
||||
struct _MetaWindowGroup
|
||||
{
|
||||
ClutterGroup parent;
|
||||
|
||||
MetaScreen *screen;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MutterWindowGroup, mutter_window_group, CLUTTER_TYPE_GROUP);
|
||||
G_DEFINE_TYPE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_GROUP);
|
||||
|
||||
/* We want to find out if the window is "close enough" to
|
||||
* 1:1 transform. We do that by converting the transformed coordinates
|
||||
@@ -96,11 +98,11 @@ actor_is_untransformed (ClutterActor *actor,
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_window_group_paint (ClutterActor *actor)
|
||||
meta_window_group_paint (ClutterActor *actor)
|
||||
{
|
||||
MutterWindowGroup *window_group = MUTTER_WINDOW_GROUP (actor);
|
||||
GdkRegion *visible_region;
|
||||
GdkRectangle screen_rect = { 0 };
|
||||
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
|
||||
cairo_region_t *visible_region;
|
||||
cairo_rectangle_int_t screen_rect = { 0 };
|
||||
GList *children, *l;
|
||||
|
||||
/* We walk the list from top to bottom (opposite of painting order),
|
||||
@@ -116,77 +118,77 @@ mutter_window_group_paint (ClutterActor *actor)
|
||||
* optimization, however.)
|
||||
*/
|
||||
meta_screen_get_size (window_group->screen, &screen_rect.width, &screen_rect.height);
|
||||
visible_region = gdk_region_rectangle (&screen_rect);
|
||||
visible_region = cairo_region_create_rectangle (&screen_rect);
|
||||
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
MutterWindow *cw;
|
||||
MetaWindowActor *window_actor;
|
||||
gboolean x, y;
|
||||
|
||||
if (!MUTTER_IS_WINDOW (l->data) || !CLUTTER_ACTOR_IS_VISIBLE (l->data))
|
||||
if (!META_IS_WINDOW_ACTOR (l->data) || !CLUTTER_ACTOR_IS_VISIBLE (l->data))
|
||||
continue;
|
||||
|
||||
cw = l->data;
|
||||
window_actor = l->data;
|
||||
|
||||
if (!actor_is_untransformed (CLUTTER_ACTOR (cw), &x, &y))
|
||||
if (!actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
|
||||
continue;
|
||||
|
||||
/* Temporarily move to the coordinate system of the actor */
|
||||
gdk_region_offset (visible_region, - x, - y);
|
||||
cairo_region_translate (visible_region, - x, - y);
|
||||
|
||||
mutter_window_set_visible_region (cw, visible_region);
|
||||
meta_window_actor_set_visible_region (window_actor, visible_region);
|
||||
|
||||
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (cw)) == 0xff)
|
||||
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
|
||||
{
|
||||
GdkRegion *obscured_region = mutter_window_get_obscured_region (cw);
|
||||
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
|
||||
if (obscured_region)
|
||||
gdk_region_subtract (visible_region, obscured_region);
|
||||
cairo_region_subtract (visible_region, obscured_region);
|
||||
}
|
||||
|
||||
mutter_window_set_visible_region_beneath (cw, visible_region);
|
||||
gdk_region_offset (visible_region, x, y);
|
||||
meta_window_actor_set_visible_region_beneath (window_actor, visible_region);
|
||||
cairo_region_translate (visible_region, x, y);
|
||||
}
|
||||
|
||||
gdk_region_destroy (visible_region);
|
||||
cairo_region_destroy (visible_region);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (mutter_window_group_parent_class)->paint (actor);
|
||||
CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
|
||||
|
||||
/* Now that we are done painting, unset the visible regions (they will
|
||||
* mess up painting clones of our actors)
|
||||
*/
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
MutterWindow *cw;
|
||||
MetaWindowActor *window_actor;
|
||||
|
||||
if (!MUTTER_IS_WINDOW (l->data))
|
||||
if (!META_IS_WINDOW_ACTOR (l->data))
|
||||
continue;
|
||||
|
||||
cw = l->data;
|
||||
mutter_window_reset_visible_regions (cw);
|
||||
window_actor = l->data;
|
||||
meta_window_actor_reset_visible_regions (window_actor);
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_window_group_class_init (MutterWindowGroupClass *klass)
|
||||
meta_window_group_class_init (MetaWindowGroupClass *klass)
|
||||
{
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
actor_class->paint = mutter_window_group_paint;
|
||||
actor_class->paint = meta_window_group_paint;
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_window_group_init (MutterWindowGroup *window_group)
|
||||
meta_window_group_init (MetaWindowGroup *window_group)
|
||||
{
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_window_group_new (MetaScreen *screen)
|
||||
meta_window_group_new (MetaScreen *screen)
|
||||
{
|
||||
MutterWindowGroup *window_group;
|
||||
MetaWindowGroup *window_group;
|
||||
|
||||
window_group = g_object_new (MUTTER_TYPE_WINDOW_GROUP, NULL);
|
||||
window_group = g_object_new (META_TYPE_WINDOW_GROUP, NULL);
|
||||
|
||||
window_group->screen = screen;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#ifndef MUTTER_WINDOW_GROUP_H
|
||||
#define MUTTER_WINDOW_GROUP_H
|
||||
#ifndef META_WINDOW_GROUP_H
|
||||
#define META_WINDOW_GROUP_H
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
/**
|
||||
* MutterWindowGroup:
|
||||
* MetaWindowGroup:
|
||||
*
|
||||
* This class is a subclass of ClutterGroup with special handling for
|
||||
* MutterWindow when painting the group. When we are painting a stack
|
||||
* MetaWindowActor when painting the group. When we are painting a stack
|
||||
* of 5-10 maximized windows, the standard bottom-to-top method of
|
||||
* drawing every actor results in a tremendous amount of overdraw
|
||||
* and can easily max out the available memory bandwidth on a low-end
|
||||
@@ -21,7 +21,7 @@
|
||||
* The basic technique applied here is to do a pre-pass before painting
|
||||
* where we walk window from top to bottom and compute the visible area
|
||||
* at each step by subtracting out the windows above it. The visible
|
||||
* area is passed to MutterWindow which uses it to clip the portion of
|
||||
* area is passed to MetaWindowActor which uses it to clip the portion of
|
||||
* the window which drawn and avoid redrawing the shadow if it is completely
|
||||
* obscured.
|
||||
*
|
||||
@@ -34,19 +34,19 @@
|
||||
* we have lots of memory and bandwidth.)
|
||||
*/
|
||||
|
||||
#define MUTTER_TYPE_WINDOW_GROUP (mutter_window_group_get_type ())
|
||||
#define MUTTER_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_WINDOW_GROUP, MutterWindowGroup))
|
||||
#define MUTTER_WINDOW_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_WINDOW_GROUP, MutterWindowGroupClass))
|
||||
#define MUTTER_IS_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_TYPE_WINDOW_GROUP))
|
||||
#define MUTTER_IS_WINDOW_GROU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_WINDOW_GROUP))
|
||||
#define MUTTER_WINDOW_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_WINDOW_GROUP, MutterWindowGroupClass))
|
||||
#define META_TYPE_WINDOW_GROUP (meta_window_group_get_type ())
|
||||
#define META_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WINDOW_GROUP, MetaWindowGroup))
|
||||
#define META_WINDOW_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WINDOW_GROUP, MetaWindowGroupClass))
|
||||
#define META_IS_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WINDOW_GROUP))
|
||||
#define META_IS_WINDOW_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WINDOW_GROUP))
|
||||
#define META_WINDOW_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WINDOW_GROUP, MetaWindowGroupClass))
|
||||
|
||||
typedef struct _MutterWindowGroup MutterWindowGroup;
|
||||
typedef struct _MutterWindowGroupClass MutterWindowGroupClass;
|
||||
typedef struct _MutterWindowGroupPrivate MutterWindowGroupPrivate;
|
||||
typedef struct _MetaWindowGroup MetaWindowGroup;
|
||||
typedef struct _MetaWindowGroupClass MetaWindowGroupClass;
|
||||
typedef struct _MetaWindowGroupPrivate MetaWindowGroupPrivate;
|
||||
|
||||
GType mutter_window_group_get_type (void);
|
||||
GType meta_window_group_get_type (void);
|
||||
|
||||
ClutterActor *mutter_window_group_new (MetaScreen *screen);
|
||||
ClutterActor *meta_window_group_new (MetaScreen *screen);
|
||||
|
||||
#endif /* MUTTER_WINDOW_GROUP_H */
|
||||
#endif /* META_WINDOW_GROUP_H */
|
||||
253
src/compositor/meta-window-shape.c
Normal file
253
src/compositor/meta-window-shape.c
Normal file
@@ -0,0 +1,253 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaWindowShape
|
||||
*
|
||||
* Extracted invariant window shape
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "meta-window-shape.h"
|
||||
#include "region-utils.h"
|
||||
|
||||
struct _MetaWindowShape
|
||||
{
|
||||
guint ref_count;
|
||||
|
||||
int top, right, bottom, left;
|
||||
int n_rectangles;
|
||||
cairo_rectangle_int_t *rectangles;
|
||||
guint hash;
|
||||
};
|
||||
|
||||
MetaWindowShape *
|
||||
meta_window_shape_new (cairo_region_t *region)
|
||||
{
|
||||
MetaWindowShape *shape;
|
||||
MetaRegionIterator iter;
|
||||
cairo_rectangle_int_t extents;
|
||||
int max_yspan_y1 = 0;
|
||||
int max_yspan_y2 = 0;
|
||||
int max_xspan_x1 = -1;
|
||||
int max_xspan_x2 = -1;
|
||||
guint hash;
|
||||
|
||||
shape = g_slice_new0 (MetaWindowShape);
|
||||
shape->ref_count = 1;
|
||||
|
||||
cairo_region_get_extents (region, &extents);
|
||||
|
||||
shape->n_rectangles = cairo_region_num_rectangles (region);
|
||||
|
||||
if (shape->n_rectangles == 0)
|
||||
{
|
||||
shape->rectangles = NULL;
|
||||
shape->top = shape->right = shape->bottom = shape->left = 0;
|
||||
shape->hash = 0;
|
||||
return shape;
|
||||
}
|
||||
|
||||
for (meta_region_iterator_init (&iter, region);
|
||||
!meta_region_iterator_at_end (&iter);
|
||||
meta_region_iterator_next (&iter))
|
||||
{
|
||||
int max_line_xspan_x1 = -1;
|
||||
int max_line_xspan_x2 = -1;
|
||||
|
||||
if (iter.rectangle.width > max_line_xspan_x2 - max_line_xspan_x1)
|
||||
{
|
||||
max_line_xspan_x1 = iter.rectangle.x;
|
||||
max_line_xspan_x2 = iter.rectangle.x + iter.rectangle.width;
|
||||
}
|
||||
|
||||
if (iter.line_end)
|
||||
{
|
||||
if (iter.rectangle.height > max_yspan_y2 - max_yspan_y1)
|
||||
{
|
||||
max_yspan_y1 = iter.rectangle.y;
|
||||
max_yspan_y2 = iter.rectangle.y + iter.rectangle.height;
|
||||
}
|
||||
|
||||
if (max_xspan_x1 < 0) /* First line */
|
||||
{
|
||||
max_xspan_x1 = max_line_xspan_x1;
|
||||
max_xspan_x2 = max_line_xspan_x2;
|
||||
}
|
||||
else
|
||||
{
|
||||
max_xspan_x1 = MAX (max_xspan_x1, max_line_xspan_x1);
|
||||
max_xspan_x2 = MIN (max_xspan_x2, max_line_xspan_x2);
|
||||
|
||||
if (max_xspan_x2 < max_xspan_x1)
|
||||
max_xspan_x2 = max_xspan_x1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
g_print ("xspan: %d -> %d, yspan: %d -> %d\n",
|
||||
max_xspan_x1, max_xspan_x2,
|
||||
max_yspan_y1, max_yspan_y2);
|
||||
#endif
|
||||
|
||||
shape->top = max_yspan_y1 - extents.y;
|
||||
shape->right = extents.x + extents.width - max_xspan_x2;
|
||||
shape->bottom = extents.y + extents.height - max_yspan_y2;
|
||||
shape->left = max_xspan_x1 - extents.x;
|
||||
|
||||
shape->rectangles = g_new (cairo_rectangle_int_t, shape->n_rectangles);
|
||||
|
||||
hash = 0;
|
||||
for (meta_region_iterator_init (&iter, region);
|
||||
!meta_region_iterator_at_end (&iter);
|
||||
meta_region_iterator_next (&iter))
|
||||
{
|
||||
int x1, x2, y1, y2;
|
||||
|
||||
x1 = iter.rectangle.x;
|
||||
x2 = iter.rectangle.x + iter.rectangle.width;
|
||||
y1 = iter.rectangle.y;
|
||||
y2 = iter.rectangle.y + iter.rectangle.height;
|
||||
|
||||
if (x1 > max_xspan_x1)
|
||||
x1 -= MIN (x1, max_xspan_x2 - 1) - max_xspan_x1;
|
||||
if (x2 > max_xspan_x1)
|
||||
x2 -= MIN (x2, max_xspan_x2 - 1) - max_xspan_x1;
|
||||
if (y1 > max_yspan_y1)
|
||||
y1 -= MIN (y1, max_yspan_y2 - 1) - max_yspan_y1;
|
||||
if (y2 > max_yspan_y1)
|
||||
y2 -= MIN (y2, max_yspan_y2 - 1) - max_yspan_y1;
|
||||
|
||||
shape->rectangles[iter.i].x = x1 - extents.x;
|
||||
shape->rectangles[iter.i].y = y1 - extents.y;
|
||||
shape->rectangles[iter.i].width = x2 - x1;
|
||||
shape->rectangles[iter.i].height = y2 - y1;
|
||||
|
||||
#if 0
|
||||
g_print ("%d: +%d+%dx%dx%d => +%d+%dx%dx%d\n",
|
||||
i, iter.rectangle.x, iter.rectangle.y, iter.rectangle.width, iter.rectangle.height,
|
||||
shape->rectangles[i].x, shape->rectangles[i].y, shape->rectangles[i].width, shape->rectangles[i].height);
|
||||
#endif
|
||||
|
||||
hash = hash * 31 + x1 * 17 + x2 * 27 + y1 * 37 + y2 * 43;
|
||||
}
|
||||
|
||||
shape->hash = hash;
|
||||
|
||||
#if 0
|
||||
g_print ("%d %d %d %d: %#x\n\n", shape->top, shape->right, shape->bottom, shape->left, shape->hash);
|
||||
#endif
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
MetaWindowShape *
|
||||
meta_window_shape_ref (MetaWindowShape *shape)
|
||||
{
|
||||
shape->ref_count++;
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_shape_unref (MetaWindowShape *shape)
|
||||
{
|
||||
shape->ref_count--;
|
||||
if (shape->ref_count == 0)
|
||||
{
|
||||
g_free (shape->rectangles);
|
||||
g_slice_free (MetaWindowShape, shape);
|
||||
}
|
||||
}
|
||||
|
||||
guint
|
||||
meta_window_shape_hash (MetaWindowShape *shape)
|
||||
{
|
||||
return shape->hash;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_window_shape_equal (MetaWindowShape *shape_a,
|
||||
MetaWindowShape *shape_b)
|
||||
{
|
||||
if (shape_a->n_rectangles != shape_b->n_rectangles)
|
||||
return FALSE;
|
||||
|
||||
return memcmp (shape_a->rectangles, shape_b->rectangles,
|
||||
sizeof (cairo_rectangle_int_t) * shape_a->n_rectangles) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_shape_get_borders (MetaWindowShape *shape,
|
||||
int *border_top,
|
||||
int *border_right,
|
||||
int *border_bottom,
|
||||
int *border_left)
|
||||
{
|
||||
if (border_top)
|
||||
*border_top = shape->top;
|
||||
if (border_right)
|
||||
*border_right = shape->right;
|
||||
if (border_bottom)
|
||||
*border_bottom = shape->bottom;
|
||||
if (border_left)
|
||||
*border_left = shape->left;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_shape_to_region:
|
||||
* @shape: a #MetaWindowShape
|
||||
* @center_width: size of the central region horizontally
|
||||
* @center_height: size of the central region vertically
|
||||
*
|
||||
* Converts the shape to to a cairo_region_t using the given width
|
||||
* and height for the central scaled region.
|
||||
*
|
||||
* Return value: a newly created region
|
||||
*/
|
||||
cairo_region_t *
|
||||
meta_window_shape_to_region (MetaWindowShape *shape,
|
||||
int center_width,
|
||||
int center_height)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
int i;
|
||||
|
||||
region = cairo_region_create ();
|
||||
|
||||
for (i = 0; i < shape->n_rectangles; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect = shape->rectangles[i];
|
||||
|
||||
if (rect.x <= shape->left && rect.x + rect.width >= shape->left + 1)
|
||||
rect.width += center_width;
|
||||
else if (rect.x >= shape->left + 1)
|
||||
rect.x += center_width;
|
||||
|
||||
if (rect.y <= shape->top && rect.y + rect.height >= shape->top + 1)
|
||||
rect.height += center_height;
|
||||
else if (rect.y >= shape->top + 1)
|
||||
rect.y += center_height;
|
||||
|
||||
cairo_region_union_rectangle (region, &rect);
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
60
src/compositor/meta-window-shape.h
Normal file
60
src/compositor/meta-window-shape.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaWindowShape
|
||||
*
|
||||
* Extracted invariant window shape
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __META_WINDOW_SHAPE_H__
|
||||
#define __META_WINDOW_SHAPE_H__
|
||||
|
||||
#include <cairo.h>
|
||||
#include <glib.h>
|
||||
|
||||
/**
|
||||
* MetaWindowShape:
|
||||
* #MetaWindowShape represents a 9-sliced region with borders on all sides that
|
||||
* are unscaled, and a constant central region that is scaled. For example,
|
||||
* if you the regions representing two windows that around rounded rectangles,
|
||||
* with the same corner regions, but different sizes, they have the
|
||||
* same MetaWindowShape.
|
||||
*
|
||||
* #MetaWindowShape is designed to be used as part of a hash table key, so has
|
||||
* efficient hash and equal functions.
|
||||
*/
|
||||
typedef struct _MetaWindowShape MetaWindowShape;
|
||||
|
||||
MetaWindowShape * meta_window_shape_new (cairo_region_t *region);
|
||||
MetaWindowShape * meta_window_shape_ref (MetaWindowShape *shape);
|
||||
void meta_window_shape_unref (MetaWindowShape *shape);
|
||||
guint meta_window_shape_hash (MetaWindowShape *shape);
|
||||
gboolean meta_window_shape_equal (MetaWindowShape *shape_a,
|
||||
MetaWindowShape *shape_b);
|
||||
void meta_window_shape_get_borders (MetaWindowShape *shape,
|
||||
int *border_top,
|
||||
int *border_right,
|
||||
int *border_bottom,
|
||||
int *border_left);
|
||||
cairo_region_t *meta_window_shape_to_region (MetaWindowShape *shape,
|
||||
int center_width,
|
||||
int center_height);
|
||||
|
||||
#endif /* __META_WINDOW_SHAPE_H __*/
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Intel Corp.
|
||||
*
|
||||
* Author: Tomas Frydrych <tf@linux.intel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MUTTER_PLUGIN_MANAGER_H_
|
||||
#define MUTTER_PLUGIN_MANAGER_H_
|
||||
|
||||
#include "types.h"
|
||||
#include "screen.h"
|
||||
|
||||
#define MUTTER_PLUGIN_FROM_MANAGER_
|
||||
#include "mutter-plugin.h"
|
||||
#undef MUTTER_PLUGIN_FROM_MANAGER_
|
||||
|
||||
typedef struct MutterPluginManager MutterPluginManager;
|
||||
|
||||
MutterPluginManager * mutter_plugin_manager_new (MetaScreen *screen);
|
||||
gboolean mutter_plugin_manager_load (MutterPluginManager *mgr);
|
||||
gboolean mutter_plugin_manager_initialize (MutterPluginManager *plugin_mgr);
|
||||
gboolean mutter_plugin_manager_event_simple (MutterPluginManager *mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long event);
|
||||
|
||||
gboolean mutter_plugin_manager_event_maximize (MutterPluginManager *mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long event,
|
||||
gint target_x,
|
||||
gint target_y,
|
||||
gint target_width,
|
||||
gint target_height);
|
||||
void mutter_plugin_manager_update_workspaces (MutterPluginManager *mgr);
|
||||
|
||||
void mutter_plugin_manager_update_workspace (MutterPluginManager *mgr, MetaWorkspace *w);
|
||||
|
||||
gboolean mutter_plugin_manager_switch_workspace (MutterPluginManager *mgr,
|
||||
const GList **actors,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction);
|
||||
|
||||
gboolean mutter_plugin_manager_xevent_filter (MutterPluginManager *mgr,
|
||||
XEvent *xev);
|
||||
|
||||
#endif
|
||||
@@ -1,521 +0,0 @@
|
||||
/*
|
||||
* shaped texture
|
||||
*
|
||||
* An actor to draw a texture clipped to a list of rectangles
|
||||
*
|
||||
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "mutter-shaped-texture.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static void mutter_shaped_texture_dispose (GObject *object);
|
||||
static void mutter_shaped_texture_finalize (GObject *object);
|
||||
|
||||
static void mutter_shaped_texture_paint (ClutterActor *actor);
|
||||
static void mutter_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color);
|
||||
|
||||
static void mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex);
|
||||
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
G_DEFINE_TYPE (MutterShapedTexture, mutter_shaped_texture,
|
||||
CLUTTER_GLX_TYPE_TEXTURE_PIXMAP);
|
||||
#else /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
G_DEFINE_TYPE (MutterShapedTexture, mutter_shaped_texture,
|
||||
CLUTTER_X11_TYPE_TEXTURE_PIXMAP);
|
||||
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
|
||||
#define MUTTER_SHAPED_TEXTURE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_SHAPED_TEXTURE, \
|
||||
MutterShapedTexturePrivate))
|
||||
|
||||
struct _MutterShapedTexturePrivate
|
||||
{
|
||||
CoglHandle mask_texture;
|
||||
CoglHandle material;
|
||||
CoglHandle material_unshaped;
|
||||
#if 1 /* see workaround comment in mutter_shaped_texture_paint */
|
||||
CoglHandle material_workaround;
|
||||
#endif
|
||||
|
||||
GdkRegion *clip_region;
|
||||
|
||||
guint mask_width, mask_height;
|
||||
|
||||
GArray *rectangles;
|
||||
};
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_class_init (MutterShapedTextureClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
||||
|
||||
gobject_class->dispose = mutter_shaped_texture_dispose;
|
||||
gobject_class->finalize = mutter_shaped_texture_finalize;
|
||||
|
||||
actor_class->paint = mutter_shaped_texture_paint;
|
||||
actor_class->pick = mutter_shaped_texture_pick;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MutterShapedTexturePrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_init (MutterShapedTexture *self)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv;
|
||||
|
||||
priv = self->priv = MUTTER_SHAPED_TEXTURE_GET_PRIVATE (self);
|
||||
|
||||
priv->rectangles = g_array_new (FALSE, FALSE, sizeof (XRectangle));
|
||||
|
||||
priv->mask_texture = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_dispose (GObject *object)
|
||||
{
|
||||
MutterShapedTexture *self = (MutterShapedTexture *) object;
|
||||
MutterShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
mutter_shaped_texture_dirty_mask (self);
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_material_unref (priv->material);
|
||||
priv->material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
if (priv->material_unshaped != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_material_unref (priv->material_unshaped);
|
||||
priv->material_unshaped = COGL_INVALID_HANDLE;
|
||||
}
|
||||
#if 1 /* see comment in mutter_shaped_texture_paint */
|
||||
if (priv->material_workaround != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_material_unref (priv->material_workaround);
|
||||
priv->material_workaround = COGL_INVALID_HANDLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
mutter_shaped_texture_set_clip_region (self, NULL);
|
||||
|
||||
G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_finalize (GObject *object)
|
||||
{
|
||||
MutterShapedTexture *self = (MutterShapedTexture *) object;
|
||||
MutterShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
g_array_free (priv->rectangles, TRUE);
|
||||
|
||||
G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
if (priv->mask_texture != COGL_INVALID_HANDLE)
|
||||
{
|
||||
GLuint mask_gl_tex;
|
||||
GLenum mask_gl_target;
|
||||
|
||||
cogl_texture_get_gl_texture (priv->mask_texture,
|
||||
&mask_gl_tex, &mask_gl_target);
|
||||
|
||||
if (mask_gl_target == CGL_TEXTURE_RECTANGLE_ARB)
|
||||
glDeleteTextures (1, &mask_gl_tex);
|
||||
|
||||
cogl_texture_unref (priv->mask_texture);
|
||||
priv->mask_texture = COGL_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv = stex->priv;
|
||||
CoglHandle paint_tex;
|
||||
guint tex_width, tex_height;
|
||||
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
/* If the mask texture we have was created for a different size then
|
||||
recreate it */
|
||||
if (priv->mask_texture != COGL_INVALID_HANDLE
|
||||
&& (priv->mask_width != tex_width || priv->mask_height != tex_height))
|
||||
mutter_shaped_texture_dirty_mask (stex);
|
||||
|
||||
/* If we don't have a mask texture yet then create one */
|
||||
if (priv->mask_texture == COGL_INVALID_HANDLE)
|
||||
{
|
||||
guchar *mask_data;
|
||||
const XRectangle *rect;
|
||||
GLenum paint_gl_target;
|
||||
|
||||
/* Create data for an empty image */
|
||||
mask_data = g_malloc0 (tex_width * tex_height);
|
||||
|
||||
/* Cut out a hole for each rectangle */
|
||||
for (rect = (XRectangle *) priv->rectangles->data
|
||||
+ priv->rectangles->len;
|
||||
rect-- > (XRectangle *) priv->rectangles->data;)
|
||||
{
|
||||
gint x1 = rect->x, x2 = x1 + rect->width;
|
||||
gint y1 = rect->y, y2 = y1 + rect->height;
|
||||
guchar *p;
|
||||
|
||||
/* Clip the rectangle to the size of the texture */
|
||||
x1 = CLAMP (x1, 0, (gint) tex_width - 1);
|
||||
x2 = CLAMP (x2, x1, (gint) tex_width);
|
||||
y1 = CLAMP (y1, 0, (gint) tex_height - 1);
|
||||
y2 = CLAMP (y2, y1, (gint) tex_height);
|
||||
|
||||
/* Fill the rectangle */
|
||||
for (p = mask_data + y1 * tex_width + x1;
|
||||
y1 < y2;
|
||||
y1++, p += tex_width)
|
||||
memset (p, 255, x2 - x1);
|
||||
}
|
||||
|
||||
cogl_texture_get_gl_texture (paint_tex, NULL, &paint_gl_target);
|
||||
|
||||
if (paint_gl_target == CGL_TEXTURE_RECTANGLE_ARB)
|
||||
{
|
||||
GLuint tex;
|
||||
|
||||
glGenTextures (1, &tex);
|
||||
glBindTexture (CGL_TEXTURE_RECTANGLE_ARB, tex);
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, tex_width);
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
|
||||
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
|
||||
glTexImage2D (CGL_TEXTURE_RECTANGLE_ARB, 0,
|
||||
GL_ALPHA, tex_width, tex_height,
|
||||
0, GL_ALPHA, GL_UNSIGNED_BYTE, mask_data);
|
||||
|
||||
priv->mask_texture
|
||||
= cogl_texture_new_from_foreign (tex,
|
||||
CGL_TEXTURE_RECTANGLE_ARB,
|
||||
tex_width, tex_height,
|
||||
0, 0,
|
||||
COGL_PIXEL_FORMAT_A_8);
|
||||
}
|
||||
else
|
||||
priv->mask_texture = cogl_texture_new_from_data (tex_width, tex_height,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_A_8,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
tex_width,
|
||||
mask_data);
|
||||
|
||||
g_free (mask_data);
|
||||
|
||||
priv->mask_width = tex_width;
|
||||
priv->mask_height = tex_height;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_paint (ClutterActor *actor)
|
||||
{
|
||||
MutterShapedTexture *stex = (MutterShapedTexture *) actor;
|
||||
MutterShapedTexturePrivate *priv = stex->priv;
|
||||
CoglHandle paint_tex;
|
||||
guint tex_width, tex_height;
|
||||
ClutterActorBox alloc;
|
||||
CoglHandle material;
|
||||
#if 1 /* please see comment below about workaround */
|
||||
guint depth;
|
||||
#endif
|
||||
|
||||
if (priv->clip_region && gdk_region_empty (priv->clip_region))
|
||||
return;
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
|
||||
clutter_actor_realize (CLUTTER_ACTOR (stex));
|
||||
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
if (priv->rectangles->len < 1)
|
||||
{
|
||||
/* If there are no rectangles use a single-layer texture */
|
||||
|
||||
if (priv->material_unshaped == COGL_INVALID_HANDLE)
|
||||
priv->material_unshaped = cogl_material_new ();
|
||||
|
||||
material = priv->material_unshaped;
|
||||
}
|
||||
else
|
||||
{
|
||||
mutter_shaped_texture_ensure_mask (stex);
|
||||
|
||||
if (priv->material == COGL_INVALID_HANDLE)
|
||||
{
|
||||
priv->material = cogl_material_new ();
|
||||
|
||||
cogl_material_set_layer_combine (priv->material, 1,
|
||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
||||
NULL);
|
||||
}
|
||||
material = priv->material;
|
||||
|
||||
#if 1
|
||||
/* This was added as a workaround. It seems that with the intel
|
||||
* drivers when multi-texturing using an RGB TFP texture, the
|
||||
* texture is actually setup internally as an RGBA texture, where
|
||||
* the alpha channel is mostly 0.0 so you only see a shimmer of the
|
||||
* window. This workaround forcibly defines the alpha channel as
|
||||
* 1.0. Maybe there is some clutter/cogl state that is interacting
|
||||
* with this that is being overlooked, but for now this seems to
|
||||
* work. */
|
||||
g_object_get (stex, "pixmap-depth", &depth, NULL);
|
||||
if (depth == 24)
|
||||
{
|
||||
if (priv->material_workaround == COGL_INVALID_HANDLE)
|
||||
{
|
||||
material = priv->material_workaround = cogl_material_new ();
|
||||
|
||||
cogl_material_set_layer_combine (material, 0,
|
||||
"RGB = MODULATE (TEXTURE, PREVIOUS)"
|
||||
"A = REPLACE (PREVIOUS)",
|
||||
NULL);
|
||||
cogl_material_set_layer_combine (material, 1,
|
||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
||||
NULL);
|
||||
}
|
||||
|
||||
material = priv->material_workaround;
|
||||
}
|
||||
#endif
|
||||
|
||||
cogl_material_set_layer (material, 1, priv->mask_texture);
|
||||
}
|
||||
|
||||
cogl_material_set_layer (material, 0, paint_tex);
|
||||
|
||||
{
|
||||
CoglColor color;
|
||||
guchar opacity = clutter_actor_get_paint_opacity (actor);
|
||||
cogl_color_set_from_4ub (&color, opacity, opacity, opacity, opacity);
|
||||
cogl_material_set_color (material, &color);
|
||||
}
|
||||
|
||||
cogl_set_source (material);
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &alloc);
|
||||
|
||||
if (priv->clip_region)
|
||||
{
|
||||
GdkRectangle *rects;
|
||||
int n_rects;
|
||||
int i;
|
||||
|
||||
/* Limit to how many separate rectangles we'll draw; beyond this just
|
||||
* fall back and draw the whole thing */
|
||||
# define MAX_RECTS 16
|
||||
|
||||
/* Would be nice to be able to check the number of rects first */
|
||||
gdk_region_get_rectangles (priv->clip_region, &rects, &n_rects);
|
||||
if (n_rects > MAX_RECTS)
|
||||
{
|
||||
g_free (rects);
|
||||
/* Fall through to following code */
|
||||
}
|
||||
else
|
||||
{
|
||||
float coords[MAX_RECTS * 8];
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
GdkRectangle *rect = &rects[i];
|
||||
|
||||
coords[i * 8 + 0] = rect->x;
|
||||
coords[i * 8 + 1] = rect->y;
|
||||
coords[i * 8 + 2] = rect->x + rect->width;
|
||||
coords[i * 8 + 3] = rect->y + rect->height;
|
||||
coords[i * 8 + 4] = rect->x / (alloc.x2 - alloc.x1);
|
||||
coords[i * 8 + 5] = rect->y / (alloc.y2 - alloc.y1);
|
||||
coords[i * 8 + 6] = (rect->x + rect->width) / (alloc.x2 - alloc.x1);
|
||||
coords[i * 8 + 7] = (rect->y + rect->height) / (alloc.y2 - alloc.y1);
|
||||
}
|
||||
|
||||
g_free (rects);
|
||||
|
||||
cogl_rectangles_with_texture_coords (coords, n_rects);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cogl_rectangle (0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
MutterShapedTexture *stex = (MutterShapedTexture *) actor;
|
||||
MutterShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
/* If there are no rectangles then use the regular pick */
|
||||
if (priv->rectangles->len < 1)
|
||||
CLUTTER_ACTOR_CLASS (mutter_shaped_texture_parent_class)
|
||||
->pick (actor, color);
|
||||
else if (clutter_actor_should_pick_paint (actor))
|
||||
{
|
||||
CoglHandle paint_tex;
|
||||
ClutterActorBox alloc;
|
||||
guint tex_width, tex_height;
|
||||
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
mutter_shaped_texture_ensure_mask (stex);
|
||||
|
||||
cogl_set_source_color4ub (color->red, color->green, color->blue,
|
||||
color->alpha);
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &alloc);
|
||||
|
||||
/* Paint the mask rectangle in the given color */
|
||||
cogl_set_source_texture (priv->mask_texture);
|
||||
cogl_rectangle_with_texture_coords (0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1,
|
||||
0, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_shaped_texture_new (void)
|
||||
{
|
||||
ClutterActor *self = g_object_new (MUTTER_TYPE_SHAPED_TEXTURE, NULL);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
mutter_shaped_texture_clear_rectangles (MutterShapedTexture *stex)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
g_array_set_size (priv->rectangles, 0);
|
||||
mutter_shaped_texture_dirty_mask (stex);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
void
|
||||
mutter_shaped_texture_add_rectangle (MutterShapedTexture *stex,
|
||||
const XRectangle *rect)
|
||||
{
|
||||
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
mutter_shaped_texture_add_rectangles (stex, 1, rect);
|
||||
}
|
||||
|
||||
void
|
||||
mutter_shaped_texture_add_rectangles (MutterShapedTexture *stex,
|
||||
size_t num_rects,
|
||||
const XRectangle *rects)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
g_array_append_vals (priv->rectangles, rects, num_rects);
|
||||
|
||||
mutter_shaped_texture_dirty_mask (stex);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_shaped_texture_set_clip_region:
|
||||
* @frame: a #TidyTextureframe
|
||||
* @clip_region: (transfer full): the region of the texture that
|
||||
* is visible and should be painted. OWNERSHIP IS ASSUMED BY
|
||||
* THE FUNCTION (for efficiency to avoid a copy.)
|
||||
*
|
||||
* Provides a hint to the texture about what areas of the texture
|
||||
* are not completely obscured and thus need to be painted. This
|
||||
* is an optimization and is not supposed to have any effect on
|
||||
* the output.
|
||||
*
|
||||
* Typically a parent container will set the clip region before
|
||||
* painting its children, and then unset it afterwards.
|
||||
*/
|
||||
void
|
||||
mutter_shaped_texture_set_clip_region (MutterShapedTexture *stex,
|
||||
GdkRegion *clip_region)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->clip_region)
|
||||
{
|
||||
gdk_region_destroy (priv->clip_region);
|
||||
priv->clip_region = NULL;
|
||||
}
|
||||
|
||||
priv->clip_region = clip_region;
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* shaped texture
|
||||
*
|
||||
* An actor to draw a texture clipped to a list of rectangles
|
||||
*
|
||||
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __MUTTER_SHAPED_TEXTURE_H__
|
||||
#define __MUTTER_SHAPED_TEXTURE_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
#include <clutter/glx/clutter-glx.h>
|
||||
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
|
||||
#include <gdk/gdkregion.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define MUTTER_TYPE_SHAPED_TEXTURE \
|
||||
(mutter_shaped_texture_get_type())
|
||||
#define MUTTER_SHAPED_TEXTURE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE, \
|
||||
MutterShapedTexture))
|
||||
#define MUTTER_SHAPED_TEXTURE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE, \
|
||||
MutterShapedTextureClass))
|
||||
#define MUTTER_IS_SHAPED_TEXTURE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE))
|
||||
#define MUTTER_IS_SHAPED_TEXTURE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE))
|
||||
#define MUTTER_SHAPED_TEXTURE_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE, \
|
||||
MutterShapedTextureClass))
|
||||
|
||||
typedef struct _MutterShapedTexture MutterShapedTexture;
|
||||
typedef struct _MutterShapedTextureClass MutterShapedTextureClass;
|
||||
typedef struct _MutterShapedTexturePrivate MutterShapedTexturePrivate;
|
||||
|
||||
struct _MutterShapedTextureClass
|
||||
{
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
ClutterGLXTexturePixmapClass parent_class;
|
||||
#else
|
||||
ClutterX11TexturePixmapClass parent_class;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _MutterShapedTexture
|
||||
{
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
ClutterGLXTexturePixmap parent;
|
||||
#else
|
||||
ClutterX11TexturePixmap parent;
|
||||
#endif
|
||||
|
||||
MutterShapedTexturePrivate *priv;
|
||||
};
|
||||
|
||||
GType mutter_shaped_texture_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *mutter_shaped_texture_new (void);
|
||||
|
||||
void mutter_shaped_texture_clear_rectangles (MutterShapedTexture *stex);
|
||||
|
||||
void mutter_shaped_texture_add_rectangle (MutterShapedTexture *stex,
|
||||
const XRectangle *rect);
|
||||
void mutter_shaped_texture_add_rectangles (MutterShapedTexture *stex,
|
||||
size_t num_rects,
|
||||
const XRectangle *rects);
|
||||
|
||||
/* Assumes ownership of clip_region */
|
||||
void mutter_shaped_texture_set_clip_region (MutterShapedTexture *stex,
|
||||
GdkRegion *clip_region);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __MUTTER_SHAPED_TEXTURE_H__ */
|
||||
@@ -1,51 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#ifndef MUTTER_WINDOW_PRIVATE_H
|
||||
#define MUTTER_WINDOW_PRIVATE_H
|
||||
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include "compositor-mutter.h"
|
||||
|
||||
MutterWindow *mutter_window_new (MetaWindow *window);
|
||||
|
||||
void mutter_window_destroy (MutterWindow *cw);
|
||||
|
||||
void mutter_window_show (MutterWindow *cw,
|
||||
MetaCompEffect effect);
|
||||
void mutter_window_hide (MutterWindow *cw,
|
||||
MetaCompEffect effect);
|
||||
|
||||
void mutter_window_maximize (MutterWindow *cw,
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
void mutter_window_unmaximize (MutterWindow *cw,
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
|
||||
void mutter_window_process_damage (MutterWindow *cw,
|
||||
XDamageNotifyEvent *event);
|
||||
void mutter_window_pre_paint (MutterWindow *self);
|
||||
|
||||
gboolean mutter_window_effect_in_progress (MutterWindow *cw);
|
||||
void mutter_window_sync_actor_position (MutterWindow *cw);
|
||||
void mutter_window_sync_visibility (MutterWindow *cw);
|
||||
void mutter_window_update_window_type (MutterWindow *cw);
|
||||
void mutter_window_update_shape (MutterWindow *cw,
|
||||
gboolean shaped);
|
||||
void mutter_window_update_opacity (MutterWindow *cw);
|
||||
void mutter_window_mapped (MutterWindow *cw);
|
||||
void mutter_window_unmapped (MutterWindow *cw);
|
||||
|
||||
GdkRegion *mutter_window_get_obscured_region (MutterWindow *cw);
|
||||
|
||||
void mutter_window_set_visible_region (MutterWindow *cw,
|
||||
GdkRegion *visible_region);
|
||||
void mutter_window_set_visible_region_beneath (MutterWindow *cw,
|
||||
GdkRegion *beneath_region);
|
||||
void mutter_window_reset_visible_regions (MutterWindow *cw);
|
||||
|
||||
void mutter_window_effect_completed (MutterWindow *actor,
|
||||
gulong event);
|
||||
|
||||
#endif /* MUTTER_WINDOW_PRIVATE_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,8 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "mutter-plugin.h"
|
||||
#include "meta-plugin.h"
|
||||
#include "window.h"
|
||||
|
||||
#include <libintl.h>
|
||||
#define _(x) dgettext (GETTEXT_PACKAGE, x)
|
||||
@@ -39,71 +40,78 @@
|
||||
|
||||
#define ACTOR_DATA_KEY "MCCP-Default-actor-data"
|
||||
|
||||
#define MUTTER_TYPE_DEFAULT_PLUGIN (mutter_default_plugin_get_type ())
|
||||
#define MUTTER_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPlugin))
|
||||
#define MUTTER_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginClass))
|
||||
#define MUTTER_IS_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_DEFAULT_PLUGIN_TYPE))
|
||||
#define MUTTER_IS_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_DEFAULT_PLUGIN))
|
||||
#define MUTTER_DEFAULT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginClass))
|
||||
#define META_TYPE_DEFAULT_PLUGIN (meta_default_plugin_get_type ())
|
||||
#define META_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPlugin))
|
||||
#define META_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPluginClass))
|
||||
#define META_IS_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_DEFAULT_PLUGIN_TYPE))
|
||||
#define META_IS_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEFAULT_PLUGIN))
|
||||
#define META_DEFAULT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPluginClass))
|
||||
|
||||
#define MUTTER_DEFAULT_PLUGIN_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginPrivate))
|
||||
#define META_DEFAULT_PLUGIN_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPluginPrivate))
|
||||
|
||||
typedef struct _MutterDefaultPlugin MutterDefaultPlugin;
|
||||
typedef struct _MutterDefaultPluginClass MutterDefaultPluginClass;
|
||||
typedef struct _MutterDefaultPluginPrivate MutterDefaultPluginPrivate;
|
||||
typedef struct _MetaDefaultPlugin MetaDefaultPlugin;
|
||||
typedef struct _MetaDefaultPluginClass MetaDefaultPluginClass;
|
||||
typedef struct _MetaDefaultPluginPrivate MetaDefaultPluginPrivate;
|
||||
|
||||
struct _MutterDefaultPlugin
|
||||
struct _MetaDefaultPlugin
|
||||
{
|
||||
MutterPlugin parent;
|
||||
MetaPlugin parent;
|
||||
|
||||
MutterDefaultPluginPrivate *priv;
|
||||
MetaDefaultPluginPrivate *priv;
|
||||
};
|
||||
|
||||
struct _MutterDefaultPluginClass
|
||||
struct _MetaDefaultPluginClass
|
||||
{
|
||||
MutterPluginClass parent_class;
|
||||
MetaPluginClass parent_class;
|
||||
};
|
||||
|
||||
static GQuark actor_data_quark = 0;
|
||||
|
||||
static void minimize (MutterPlugin *plugin,
|
||||
MutterWindow *actor);
|
||||
static void map (MutterPlugin *plugin,
|
||||
MutterWindow *actor);
|
||||
static void destroy (MutterPlugin *plugin,
|
||||
MutterWindow *actor);
|
||||
static void maximize (MutterPlugin *plugin,
|
||||
MutterWindow *actor,
|
||||
gint x, gint y, gint width, gint height);
|
||||
static void unmaximize (MutterPlugin *plugin,
|
||||
MutterWindow *actor,
|
||||
gint x, gint y, gint width, gint height);
|
||||
static void minimize (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void map (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void destroy (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void maximize (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
static void unmaximize (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
|
||||
static void switch_workspace (MutterPlugin *plugin,
|
||||
const GList **actors, gint from, gint to,
|
||||
MetaMotionDirection direction);
|
||||
static void switch_workspace (MetaPlugin *plugin,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction);
|
||||
|
||||
static void kill_effect (MutterPlugin *plugin,
|
||||
MutterWindow *actor, gulong event);
|
||||
static void kill_window_effects (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void kill_switch_workspace (MetaPlugin *plugin);
|
||||
|
||||
static const MutterPluginInfo * plugin_info (MutterPlugin *plugin);
|
||||
static const MetaPluginInfo * plugin_info (MetaPlugin *plugin);
|
||||
|
||||
MUTTER_PLUGIN_DECLARE(MutterDefaultPlugin, mutter_default_plugin);
|
||||
META_PLUGIN_DECLARE(MetaDefaultPlugin, meta_default_plugin);
|
||||
|
||||
/*
|
||||
* Plugin private data that we store in the .plugin_private member.
|
||||
*/
|
||||
struct _MutterDefaultPluginPrivate
|
||||
struct _MetaDefaultPluginPrivate
|
||||
{
|
||||
/* Valid only when switch_workspace effect is in progress */
|
||||
ClutterTimeline *tml_switch_workspace1;
|
||||
ClutterTimeline *tml_switch_workspace2;
|
||||
GList **actors;
|
||||
ClutterActor *desktop1;
|
||||
ClutterActor *desktop2;
|
||||
|
||||
MutterPluginInfo info;
|
||||
MetaPluginInfo info;
|
||||
|
||||
gboolean debug_mode : 1;
|
||||
};
|
||||
@@ -128,26 +136,26 @@ typedef struct _ActorPrivate
|
||||
typedef struct
|
||||
{
|
||||
ClutterActor *actor;
|
||||
MutterPlugin *plugin;
|
||||
MetaPlugin *plugin;
|
||||
} EffectCompleteData;
|
||||
|
||||
|
||||
static void
|
||||
mutter_default_plugin_dispose (GObject *object)
|
||||
meta_default_plugin_dispose (GObject *object)
|
||||
{
|
||||
/* MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (object)->priv;
|
||||
/* MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (object)->priv;
|
||||
*/
|
||||
G_OBJECT_CLASS (mutter_default_plugin_parent_class)->dispose (object);
|
||||
G_OBJECT_CLASS (meta_default_plugin_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_default_plugin_finalize (GObject *object)
|
||||
meta_default_plugin_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (mutter_default_plugin_parent_class)->finalize (object);
|
||||
G_OBJECT_CLASS (meta_default_plugin_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_default_plugin_set_property (GObject *object,
|
||||
meta_default_plugin_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
@@ -161,7 +169,7 @@ mutter_default_plugin_set_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_default_plugin_get_property (GObject *object,
|
||||
meta_default_plugin_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
@@ -175,10 +183,9 @@ mutter_default_plugin_get_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_default_plugin_constructed (GObject *object)
|
||||
start (MetaPlugin *plugin)
|
||||
{
|
||||
MutterPlugin *plugin = MUTTER_PLUGIN (object);
|
||||
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (object)->priv;
|
||||
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
|
||||
|
||||
guint destroy_timeout = DESTROY_TIMEOUT;
|
||||
guint minimize_timeout = MINIMIZE_TIMEOUT;
|
||||
@@ -186,7 +193,7 @@ mutter_default_plugin_constructed (GObject *object)
|
||||
guint map_timeout = MAP_TIMEOUT;
|
||||
guint switch_timeout = SWITCH_TIMEOUT;
|
||||
|
||||
if (mutter_plugin_debug_mode (plugin))
|
||||
if (meta_plugin_debug_mode (plugin))
|
||||
{
|
||||
g_debug ("Plugin %s: Entering debug mode.", priv->info.name);
|
||||
|
||||
@@ -201,39 +208,39 @@ mutter_default_plugin_constructed (GObject *object)
|
||||
map_timeout *= 2;
|
||||
switch_timeout *= 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_default_plugin_class_init (MutterDefaultPluginClass *klass)
|
||||
meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
MutterPluginClass *plugin_class = MUTTER_PLUGIN_CLASS (klass);
|
||||
MetaPluginClass *plugin_class = META_PLUGIN_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = mutter_default_plugin_finalize;
|
||||
gobject_class->dispose = mutter_default_plugin_dispose;
|
||||
gobject_class->constructed = mutter_default_plugin_constructed;
|
||||
gobject_class->set_property = mutter_default_plugin_set_property;
|
||||
gobject_class->get_property = mutter_default_plugin_get_property;
|
||||
gobject_class->finalize = meta_default_plugin_finalize;
|
||||
gobject_class->dispose = meta_default_plugin_dispose;
|
||||
gobject_class->set_property = meta_default_plugin_set_property;
|
||||
gobject_class->get_property = meta_default_plugin_get_property;
|
||||
|
||||
plugin_class->start = start;
|
||||
plugin_class->map = map;
|
||||
plugin_class->minimize = minimize;
|
||||
plugin_class->maximize = maximize;
|
||||
plugin_class->unmaximize = unmaximize;
|
||||
plugin_class->destroy = destroy;
|
||||
plugin_class->switch_workspace = switch_workspace;
|
||||
plugin_class->kill_effect = kill_effect;
|
||||
plugin_class->plugin_info = plugin_info;
|
||||
plugin_class->kill_window_effects = kill_window_effects;
|
||||
plugin_class->kill_switch_workspace = kill_switch_workspace;
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (MutterDefaultPluginPrivate));
|
||||
g_type_class_add_private (gobject_class, sizeof (MetaDefaultPluginPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_default_plugin_init (MutterDefaultPlugin *self)
|
||||
meta_default_plugin_init (MetaDefaultPlugin *self)
|
||||
{
|
||||
MutterDefaultPluginPrivate *priv;
|
||||
MetaDefaultPluginPrivate *priv;
|
||||
|
||||
self->priv = priv = MUTTER_DEFAULT_PLUGIN_GET_PRIVATE (self);
|
||||
self->priv = priv = META_DEFAULT_PLUGIN_GET_PRIVATE (self);
|
||||
|
||||
priv->info.name = "Default Effects";
|
||||
priv->info.version = "0.1";
|
||||
@@ -253,7 +260,7 @@ free_actor_private (gpointer data)
|
||||
}
|
||||
|
||||
static ActorPrivate *
|
||||
get_actor_private (MutterWindow *actor)
|
||||
get_actor_private (MetaWindowActor *actor)
|
||||
{
|
||||
ActorPrivate *priv = g_object_get_qdata (G_OBJECT (actor), actor_data_quark);
|
||||
|
||||
@@ -272,26 +279,18 @@ get_actor_private (MutterWindow *actor)
|
||||
return priv;
|
||||
}
|
||||
|
||||
typedef struct SwitchWorkspaceData
|
||||
{
|
||||
MutterPlugin *plugin;
|
||||
const GList **actors;
|
||||
} SwitchWorkspaceData;
|
||||
|
||||
static void
|
||||
on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data)
|
||||
{
|
||||
SwitchWorkspaceData *sw_data = data;
|
||||
MutterPlugin *plugin = sw_data->plugin;
|
||||
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
|
||||
GList *l = *((GList**)sw_data->actors);
|
||||
MutterWindow *actor_for_cb = l->data;
|
||||
MetaPlugin *plugin = META_PLUGIN (data);
|
||||
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
|
||||
GList *l = meta_plugin_get_window_actors (plugin);
|
||||
|
||||
while (l)
|
||||
{
|
||||
ClutterActor *a = l->data;
|
||||
MutterWindow *mc_window = MUTTER_WINDOW (a);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (a);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
if (apriv->orig_parent)
|
||||
{
|
||||
@@ -305,40 +304,32 @@ on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data)
|
||||
clutter_actor_destroy (priv->desktop1);
|
||||
clutter_actor_destroy (priv->desktop2);
|
||||
|
||||
priv->actors = NULL;
|
||||
priv->tml_switch_workspace1 = NULL;
|
||||
priv->tml_switch_workspace2 = NULL;
|
||||
priv->desktop1 = NULL;
|
||||
priv->desktop2 = NULL;
|
||||
|
||||
g_free (data);
|
||||
|
||||
mutter_plugin_effect_completed (plugin, actor_for_cb,
|
||||
MUTTER_PLUGIN_SWITCH_WORKSPACE);
|
||||
meta_plugin_switch_workspace_completed (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
switch_workspace (MutterPlugin *plugin,
|
||||
const GList **actors, gint from, gint to,
|
||||
switch_workspace (MetaPlugin *plugin,
|
||||
gint from, gint to,
|
||||
MetaMotionDirection direction)
|
||||
{
|
||||
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
|
||||
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
|
||||
GList *l;
|
||||
gint n_workspaces;
|
||||
ClutterActor *workspace0 = clutter_group_new ();
|
||||
ClutterActor *workspace1 = clutter_group_new ();
|
||||
ClutterActor *stage;
|
||||
int screen_width, screen_height;
|
||||
MetaScreen *screen = mutter_plugin_get_screen (plugin);
|
||||
SwitchWorkspaceData *sw_data = g_new (SwitchWorkspaceData, 1);
|
||||
MetaScreen *screen = meta_plugin_get_screen (plugin);
|
||||
ClutterAnimation *animation;
|
||||
|
||||
sw_data->plugin = plugin;
|
||||
sw_data->actors = actors;
|
||||
stage = meta_plugin_get_stage (plugin);
|
||||
|
||||
stage = mutter_plugin_get_stage (plugin);
|
||||
|
||||
mutter_plugin_query_screen_size (plugin,
|
||||
meta_plugin_query_screen_size (plugin,
|
||||
&screen_width,
|
||||
&screen_height);
|
||||
clutter_actor_set_anchor_point (workspace1,
|
||||
@@ -355,32 +346,31 @@ switch_workspace (MutterPlugin *plugin,
|
||||
|
||||
if (from == to)
|
||||
{
|
||||
mutter_plugin_effect_completed (plugin, NULL,
|
||||
MUTTER_PLUGIN_SWITCH_WORKSPACE);
|
||||
meta_plugin_switch_workspace_completed (plugin);
|
||||
return;
|
||||
}
|
||||
|
||||
n_workspaces = meta_screen_get_n_workspaces (screen);
|
||||
|
||||
l = g_list_last (*((GList**) actors));
|
||||
l = g_list_last (meta_plugin_get_window_actors (plugin));
|
||||
|
||||
while (l)
|
||||
{
|
||||
MutterWindow *mc_window = l->data;
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
ClutterActor *window = CLUTTER_ACTOR (mc_window);
|
||||
gint win_workspace;
|
||||
MetaWindowActor *window_actor = l->data;
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||
gint win_workspace;
|
||||
|
||||
win_workspace = mutter_window_get_workspace (mc_window);
|
||||
win_workspace = meta_window_actor_get_workspace (window_actor);
|
||||
|
||||
if (win_workspace == to || win_workspace == from)
|
||||
{
|
||||
apriv->orig_parent = clutter_actor_get_parent (window);
|
||||
apriv->orig_parent = clutter_actor_get_parent (actor);
|
||||
|
||||
clutter_actor_reparent (window,
|
||||
clutter_actor_reparent (actor,
|
||||
win_workspace == to ? workspace1 : workspace0);
|
||||
clutter_actor_show_all (window);
|
||||
clutter_actor_raise_top (window);
|
||||
clutter_actor_show_all (actor);
|
||||
clutter_actor_raise_top (actor);
|
||||
}
|
||||
else if (win_workspace < 0)
|
||||
{
|
||||
@@ -390,14 +380,13 @@ switch_workspace (MutterPlugin *plugin,
|
||||
else
|
||||
{
|
||||
/* Window on some other desktop */
|
||||
clutter_actor_hide (window);
|
||||
clutter_actor_hide (actor);
|
||||
apriv->orig_parent = NULL;
|
||||
}
|
||||
|
||||
l = l->prev;
|
||||
}
|
||||
|
||||
priv->actors = (GList **)actors;
|
||||
priv->desktop1 = workspace0;
|
||||
priv->desktop2 = workspace1;
|
||||
|
||||
@@ -410,7 +399,7 @@ switch_workspace (MutterPlugin *plugin,
|
||||
g_signal_connect (priv->tml_switch_workspace1,
|
||||
"completed",
|
||||
G_CALLBACK (on_switch_workspace_effect_complete),
|
||||
sw_data);
|
||||
plugin);
|
||||
|
||||
animation = clutter_actor_animate (workspace1, CLUTTER_EASE_IN_SINE,
|
||||
SWITCH_TIMEOUT,
|
||||
@@ -432,11 +421,11 @@ on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
* Must reverse the effect of the effect; must hide it first to ensure
|
||||
* that the restoration will not be visible.
|
||||
*/
|
||||
MutterPlugin *plugin = data->plugin;
|
||||
MetaPlugin *plugin = data->plugin;
|
||||
ActorPrivate *apriv;
|
||||
MutterWindow *mc_window = MUTTER_WINDOW (data->actor);
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
|
||||
|
||||
apriv = get_actor_private (MUTTER_WINDOW (data->actor));
|
||||
apriv = get_actor_private (META_WINDOW_ACTOR (data->actor));
|
||||
apriv->tml_minimize = NULL;
|
||||
|
||||
clutter_actor_hide (data->actor);
|
||||
@@ -448,8 +437,7 @@ on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_MINIMIZE);
|
||||
meta_plugin_minimize_completed (plugin, window_actor);
|
||||
|
||||
g_free (data);
|
||||
}
|
||||
@@ -459,18 +447,20 @@ on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
* completion).
|
||||
*/
|
||||
static void
|
||||
minimize (MutterPlugin *plugin, MutterWindow *mc_window)
|
||||
minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
{
|
||||
MetaCompWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
|
||||
MetaWindowType type;
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||
|
||||
type = mutter_window_get_window_type (mc_window);
|
||||
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
type = meta_window_get_window_type (meta_window);
|
||||
|
||||
if (type == META_WINDOW_NORMAL)
|
||||
{
|
||||
ClutterAnimation *animation;
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
apriv->is_minimized = TRUE;
|
||||
|
||||
@@ -492,8 +482,7 @@ minimize (MutterPlugin *plugin, MutterWindow *mc_window)
|
||||
|
||||
}
|
||||
else
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_MINIMIZE);
|
||||
meta_plugin_minimize_completed (plugin, window_actor);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -506,9 +495,9 @@ on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
/*
|
||||
* Must reverse the effect of the effect.
|
||||
*/
|
||||
MutterPlugin * plugin = data->plugin;
|
||||
MutterWindow *mc_window = MUTTER_WINDOW (data->actor);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
MetaPlugin *plugin = data->plugin;
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
apriv->tml_maximize = NULL;
|
||||
|
||||
@@ -518,8 +507,7 @@ on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_MAXIMIZE);
|
||||
meta_plugin_maximize_completed (plugin, window_actor);
|
||||
|
||||
g_free (data);
|
||||
}
|
||||
@@ -533,25 +521,26 @@ on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
* (Something like a sound would be more appropriate.)
|
||||
*/
|
||||
static void
|
||||
maximize (MutterPlugin *plugin,
|
||||
MutterWindow *mc_window,
|
||||
maximize (MetaPlugin *plugin,
|
||||
MetaWindowActor *window_actor,
|
||||
gint end_x, gint end_y, gint end_width, gint end_height)
|
||||
{
|
||||
MetaCompWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
|
||||
MetaWindowType type;
|
||||
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;
|
||||
|
||||
type = mutter_window_get_window_type (mc_window);
|
||||
type = meta_window_get_window_type (meta_window);
|
||||
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
if (type == META_WINDOW_NORMAL)
|
||||
{
|
||||
ClutterAnimation *animation;
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
gfloat width, height;
|
||||
gfloat x, y;
|
||||
|
||||
@@ -589,8 +578,7 @@ maximize (MutterPlugin *plugin,
|
||||
return;
|
||||
}
|
||||
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_MAXIMIZE);
|
||||
meta_plugin_maximize_completed (plugin, window_actor);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -599,22 +587,22 @@ maximize (MutterPlugin *plugin,
|
||||
* (Just a skeleton code.)
|
||||
*/
|
||||
static void
|
||||
unmaximize (MutterPlugin *plugin,
|
||||
MutterWindow *mc_window,
|
||||
unmaximize (MetaPlugin *plugin,
|
||||
MetaWindowActor *window_actor,
|
||||
gint end_x, gint end_y, gint end_width, gint end_height)
|
||||
{
|
||||
MetaCompWindowType type = mutter_window_get_window_type (mc_window);
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
MetaWindowType type = meta_window_get_window_type (meta_window);
|
||||
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
if (type == META_WINDOW_NORMAL)
|
||||
{
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
apriv->is_maximized = FALSE;
|
||||
}
|
||||
|
||||
/* Do this conditionally, if the effect requires completion callback. */
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_UNMAXIMIZE);
|
||||
meta_plugin_unmaximize_completed (plugin, window_actor);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -623,9 +611,9 @@ on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
||||
/*
|
||||
* Must reverse the effect of the effect.
|
||||
*/
|
||||
MutterPlugin *plugin = data->plugin;
|
||||
MutterWindow *mc_window = MUTTER_WINDOW (data->actor);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
MetaPlugin *plugin = data->plugin;
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
apriv->tml_map = NULL;
|
||||
|
||||
@@ -633,7 +621,7 @@ on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_MAP);
|
||||
meta_plugin_map_completed (plugin, window_actor);
|
||||
|
||||
g_free (data);
|
||||
}
|
||||
@@ -643,18 +631,19 @@ on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
||||
* completion).
|
||||
*/
|
||||
static void
|
||||
map (MutterPlugin *plugin, MutterWindow *mc_window)
|
||||
map (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
{
|
||||
MetaCompWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
|
||||
MetaWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
|
||||
type = mutter_window_get_window_type (mc_window);
|
||||
type = meta_window_get_window_type (meta_window);
|
||||
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
if (type == META_WINDOW_NORMAL)
|
||||
{
|
||||
ClutterAnimation *animation;
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
@@ -679,8 +668,7 @@ map (MutterPlugin *plugin, MutterWindow *mc_window)
|
||||
|
||||
}
|
||||
else
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_MAP);
|
||||
meta_plugin_map_completed (plugin, window_actor);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -690,32 +678,32 @@ map (MutterPlugin *plugin, MutterWindow *mc_window)
|
||||
static void
|
||||
on_destroy_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
||||
{
|
||||
MutterPlugin *plugin = data->plugin;
|
||||
MutterWindow *mc_window = MUTTER_WINDOW (data->actor);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
MetaPlugin *plugin = data->plugin;
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
apriv->tml_destroy = NULL;
|
||||
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_DESTROY);
|
||||
meta_plugin_destroy_completed (plugin, window_actor);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple TV-out like effect.
|
||||
*/
|
||||
static void
|
||||
destroy (MutterPlugin *plugin, MutterWindow *mc_window)
|
||||
destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
{
|
||||
MetaCompWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
|
||||
MetaWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
|
||||
type = mutter_window_get_window_type (mc_window);
|
||||
type = meta_window_get_window_type (meta_window);
|
||||
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
if (type == META_WINDOW_NORMAL)
|
||||
{
|
||||
ClutterAnimation *animation;
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
@@ -734,64 +722,59 @@ destroy (MutterPlugin *plugin, MutterWindow *mc_window)
|
||||
data);
|
||||
}
|
||||
else
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_DESTROY);
|
||||
meta_plugin_destroy_completed (plugin, window_actor);
|
||||
}
|
||||
|
||||
static void
|
||||
kill_effect (MutterPlugin *plugin, MutterWindow *mc_window, gulong event)
|
||||
kill_switch_workspace (MetaPlugin *plugin)
|
||||
{
|
||||
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
|
||||
|
||||
if (priv->tml_switch_workspace1)
|
||||
{
|
||||
clutter_timeline_stop (priv->tml_switch_workspace1);
|
||||
clutter_timeline_stop (priv->tml_switch_workspace2);
|
||||
g_signal_emit_by_name (priv->tml_switch_workspace1, "completed", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
kill_window_effects (MetaPlugin *plugin,
|
||||
MetaWindowActor *window_actor)
|
||||
{
|
||||
ActorPrivate *apriv;
|
||||
|
||||
if (event & MUTTER_PLUGIN_SWITCH_WORKSPACE)
|
||||
{
|
||||
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
|
||||
apriv = get_actor_private (window_actor);
|
||||
|
||||
if (priv->tml_switch_workspace1)
|
||||
{
|
||||
clutter_timeline_stop (priv->tml_switch_workspace1);
|
||||
clutter_timeline_stop (priv->tml_switch_workspace2);
|
||||
g_signal_emit_by_name (priv->tml_switch_workspace1, "completed", NULL);
|
||||
}
|
||||
|
||||
if (!(event & ~MUTTER_PLUGIN_SWITCH_WORKSPACE))
|
||||
{
|
||||
/* Workspace switch only, nothing more to do */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
apriv = get_actor_private (mc_window);
|
||||
|
||||
if ((event & MUTTER_PLUGIN_MINIMIZE) && apriv->tml_minimize)
|
||||
if (apriv->tml_minimize)
|
||||
{
|
||||
clutter_timeline_stop (apriv->tml_minimize);
|
||||
g_signal_emit_by_name (apriv->tml_minimize, "completed", NULL);
|
||||
}
|
||||
|
||||
if ((event & MUTTER_PLUGIN_MAXIMIZE) && apriv->tml_maximize)
|
||||
if (apriv->tml_maximize)
|
||||
{
|
||||
clutter_timeline_stop (apriv->tml_maximize);
|
||||
g_signal_emit_by_name (apriv->tml_maximize, "completed", NULL);
|
||||
}
|
||||
|
||||
if ((event & MUTTER_PLUGIN_MAP) && apriv->tml_map)
|
||||
if (apriv->tml_map)
|
||||
{
|
||||
clutter_timeline_stop (apriv->tml_map);
|
||||
g_signal_emit_by_name (apriv->tml_map, "completed", NULL);
|
||||
}
|
||||
|
||||
if ((event & MUTTER_PLUGIN_DESTROY) && apriv->tml_destroy)
|
||||
if (apriv->tml_destroy)
|
||||
{
|
||||
clutter_timeline_stop (apriv->tml_destroy);
|
||||
g_signal_emit_by_name (apriv->tml_destroy, "completed", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static const MutterPluginInfo *
|
||||
plugin_info (MutterPlugin *plugin)
|
||||
static const MetaPluginInfo *
|
||||
plugin_info (MetaPlugin *plugin)
|
||||
{
|
||||
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
|
||||
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
|
||||
|
||||
return &priv->info;
|
||||
}
|
||||
|
||||
334
src/compositor/region-utils.c
Normal file
334
src/compositor/region-utils.c
Normal file
@@ -0,0 +1,334 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Utilities for region manipulation
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "region-utils.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/* MetaRegionBuilder */
|
||||
|
||||
/* Various algorithms in this file require unioning together a set of rectangles
|
||||
* that are unsorted or overlap; unioning such a set of rectangles 1-by-1
|
||||
* using cairo_region_union_rectangle() produces O(N^2) behavior (if the union
|
||||
* adds or removes rectangles in the middle of the region, then it has to
|
||||
* move all the rectangles after that.) To avoid this behavior, MetaRegionBuilder
|
||||
* creates regions for small groups of rectangles and merges them together in
|
||||
* a binary tree.
|
||||
*
|
||||
* Possible improvement: From a glance at the code, accumulating all the rectangles
|
||||
* into a flat array and then calling the (not usefully documented)
|
||||
* cairo_region_create_rectangles() would have the same behavior and would be
|
||||
* simpler and a bit more efficient.
|
||||
*/
|
||||
|
||||
/* Optimium performance seems to be with MAX_CHUNK_RECTANGLES=4; 8 is about 10% slower.
|
||||
* But using 8 may be more robust to systems with slow malloc(). */
|
||||
#define MAX_CHUNK_RECTANGLES 8
|
||||
#define MAX_LEVELS 16
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* To merge regions in a binary tree, we need to keep track of The way these are filled is in the pattern:
|
||||
*
|
||||
* |a |
|
||||
* |b |a |
|
||||
* |c | |ab |
|
||||
* |d |c |ab |
|
||||
* |e | | |abcd|
|
||||
*/
|
||||
cairo_region_t *levels[MAX_LEVELS];
|
||||
int n_levels;
|
||||
} MetaRegionBuilder;
|
||||
|
||||
static void
|
||||
meta_region_builder_init (MetaRegionBuilder *builder)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_LEVELS; i++)
|
||||
builder->levels[i] = NULL;
|
||||
builder->n_levels = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_region_builder_add_rectangle (MetaRegionBuilder *builder,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
int i;
|
||||
|
||||
if (builder->levels[0] == NULL)
|
||||
builder->levels[0] = cairo_region_create ();
|
||||
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
|
||||
cairo_region_union_rectangle (builder->levels[0], &rect);
|
||||
if (cairo_region_num_rectangles (builder->levels[0]) >= MAX_CHUNK_RECTANGLES)
|
||||
{
|
||||
for (i = 1; i < builder->n_levels + 1; i++)
|
||||
{
|
||||
if (builder->levels[i] == NULL)
|
||||
{
|
||||
if (i < MAX_LEVELS)
|
||||
{
|
||||
builder->levels[i] = builder->levels[i - 1];
|
||||
builder->levels[i - 1] = NULL;
|
||||
if (i == builder->n_levels)
|
||||
builder->n_levels++;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_region_union (builder->levels[i], builder->levels[i - 1]);
|
||||
cairo_region_destroy (builder->levels[i - 1]);
|
||||
builder->levels[i - 1] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
meta_region_builder_finish (MetaRegionBuilder *builder)
|
||||
{
|
||||
cairo_region_t *result = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < builder->n_levels; i++)
|
||||
{
|
||||
if (builder->levels[i])
|
||||
{
|
||||
if (result == NULL)
|
||||
result = builder->levels[i];
|
||||
else
|
||||
{
|
||||
cairo_region_union(result, builder->levels[i]);
|
||||
cairo_region_destroy (builder->levels[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result == NULL)
|
||||
result = cairo_region_create ();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* MetaRegionIterator */
|
||||
|
||||
void
|
||||
meta_region_iterator_init (MetaRegionIterator *iter,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
iter->region = region;
|
||||
iter->i = 0;
|
||||
iter->n_rectangles = cairo_region_num_rectangles (region);
|
||||
iter->line_start = TRUE;
|
||||
|
||||
if (iter->n_rectangles > 1)
|
||||
{
|
||||
cairo_region_get_rectangle (region, 0, &iter->rectangle);
|
||||
cairo_region_get_rectangle (region, 1, &iter->next_rectangle);
|
||||
|
||||
iter->line_end = iter->next_rectangle.y != iter->rectangle.y;
|
||||
}
|
||||
else if (iter->n_rectangles > 0)
|
||||
{
|
||||
cairo_region_get_rectangle (region, 0, &iter->rectangle);
|
||||
iter->line_end = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_region_iterator_at_end (MetaRegionIterator *iter)
|
||||
{
|
||||
return iter->i >= iter->n_rectangles;
|
||||
}
|
||||
|
||||
void
|
||||
meta_region_iterator_next (MetaRegionIterator *iter)
|
||||
{
|
||||
iter->i++;
|
||||
iter->rectangle = iter->next_rectangle;
|
||||
iter->line_start = iter->line_end;
|
||||
|
||||
if (iter->i < iter->n_rectangles)
|
||||
{
|
||||
cairo_region_get_rectangle (iter->region, iter->i + 1, &iter->next_rectangle);
|
||||
iter->line_end = iter->next_rectangle.y != iter->rectangle.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->line_end = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_expanded_rect (MetaRegionBuilder *builder,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int x_amount,
|
||||
int y_amount,
|
||||
gboolean flip)
|
||||
{
|
||||
if (flip)
|
||||
meta_region_builder_add_rectangle (builder,
|
||||
y - y_amount, x - x_amount,
|
||||
height + 2 * y_amount, width + 2 * x_amount);
|
||||
else
|
||||
meta_region_builder_add_rectangle (builder,
|
||||
x - x_amount, y - y_amount,
|
||||
width + 2 * x_amount, height + 2 * y_amount);
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
expand_region (cairo_region_t *region,
|
||||
int x_amount,
|
||||
int y_amount,
|
||||
gboolean flip)
|
||||
{
|
||||
MetaRegionBuilder builder;
|
||||
int n;
|
||||
int i;
|
||||
|
||||
meta_region_builder_init (&builder);
|
||||
|
||||
n = cairo_region_num_rectangles (region);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
add_expanded_rect (&builder,
|
||||
rect.x, rect.y, rect.width, rect.height,
|
||||
x_amount, y_amount, flip);
|
||||
}
|
||||
|
||||
return meta_region_builder_finish (&builder);
|
||||
}
|
||||
|
||||
/* This computes a (clipped version) of the inverse of the region
|
||||
* and expands it by the given amount */
|
||||
static cairo_region_t *
|
||||
expand_region_inverse (cairo_region_t *region,
|
||||
int x_amount,
|
||||
int y_amount,
|
||||
gboolean flip)
|
||||
{
|
||||
MetaRegionBuilder builder;
|
||||
MetaRegionIterator iter;
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_region_t *chunk;
|
||||
|
||||
int last_x;
|
||||
|
||||
meta_region_builder_init (&builder);
|
||||
|
||||
cairo_region_get_extents (region, &extents);
|
||||
add_expanded_rect (&builder,
|
||||
extents.x, extents.y - 1, extents.width, 1,
|
||||
x_amount, y_amount, flip);
|
||||
add_expanded_rect (&builder,
|
||||
extents.x - 1, extents.y, 1, extents.height,
|
||||
x_amount, y_amount, flip);
|
||||
add_expanded_rect (&builder,
|
||||
extents.x + extents.width, extents.y, 1, extents.height,
|
||||
x_amount, y_amount, flip);
|
||||
add_expanded_rect (&builder,
|
||||
extents.x, extents.y + extents.height, extents.width, 1,
|
||||
x_amount, y_amount, flip);
|
||||
|
||||
chunk = NULL;
|
||||
|
||||
last_x = extents.x;
|
||||
for (meta_region_iterator_init (&iter, region);
|
||||
!meta_region_iterator_at_end (&iter);
|
||||
meta_region_iterator_next (&iter))
|
||||
{
|
||||
if (chunk == NULL)
|
||||
chunk = cairo_region_create ();
|
||||
|
||||
if (iter.rectangle.x > last_x)
|
||||
add_expanded_rect (&builder,
|
||||
last_x, iter.rectangle.y,
|
||||
iter.rectangle.x - last_x, iter.rectangle.height,
|
||||
x_amount, y_amount, flip);
|
||||
|
||||
if (iter.line_end)
|
||||
{
|
||||
if (extents.x + extents.width > iter.rectangle.x + iter.rectangle.width)
|
||||
add_expanded_rect (&builder,
|
||||
iter.rectangle.x + iter.rectangle.width, iter.rectangle.y,
|
||||
(extents.x + extents.width) - (iter.rectangle.x + iter.rectangle.width), iter.rectangle.height,
|
||||
x_amount, y_amount, flip);
|
||||
last_x = extents.x;
|
||||
}
|
||||
else
|
||||
last_x = iter.rectangle.x + iter.rectangle.width;
|
||||
}
|
||||
|
||||
return meta_region_builder_finish (&builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_make_border_region:
|
||||
* @region: a #cairo_region_t
|
||||
* @x_amount: distance from the border to extend horizontally
|
||||
* @y_amount: distance from the border to extend vertically
|
||||
* @flip: if true, the result is computed with x and y interchanged
|
||||
*
|
||||
* Computes the "border region" of a given region, which is roughly
|
||||
* speaking the set of points near the boundary of the region. If we
|
||||
* define the operation of growing a region as computing the set of
|
||||
* points within a given manhattan distance of the region, then the
|
||||
* border is 'grow(region) intersect grow(inverse(region))'.
|
||||
*
|
||||
* If we create an image by filling the region with a solid color,
|
||||
* the border is the region affected by blurring the region.
|
||||
*
|
||||
* Return value: a new region which is the border of the given region
|
||||
*/
|
||||
cairo_region_t *
|
||||
meta_make_border_region (cairo_region_t *region,
|
||||
int x_amount,
|
||||
int y_amount,
|
||||
gboolean flip)
|
||||
{
|
||||
cairo_region_t *border_region;
|
||||
cairo_region_t *inverse_region;
|
||||
|
||||
border_region = expand_region (region, x_amount, y_amount, flip);
|
||||
inverse_region = expand_region_inverse (region, x_amount, y_amount, flip);
|
||||
cairo_region_intersect (border_region, inverse_region);
|
||||
cairo_region_destroy (inverse_region);
|
||||
|
||||
return border_region;
|
||||
}
|
||||
76
src/compositor/region-utils.h
Normal file
76
src/compositor/region-utils.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Utilities for region manipulation
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __META_REGION_UTILS_H__
|
||||
#define __META_REGION_UTILS_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <cairo.h>
|
||||
#include <glib.h>
|
||||
|
||||
/**
|
||||
* MetaRegionIterator:
|
||||
* @region: region being iterated
|
||||
* @rectangle: current rectangle
|
||||
* @line_start: whether the current rectangle starts a horizontal band
|
||||
* @line_end: whether the current rectangle ends a horizontal band
|
||||
*
|
||||
* cairo_region_t is a yx banded region; sometimes its useful to iterate through
|
||||
* such a region treating the start and end of each horizontal band in a distinct
|
||||
* fashion.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* MetaRegionIterator iter;
|
||||
* for (meta_region_iterator_init (&iter, region);
|
||||
* !meta_region_iterator_at_end (&iter);
|
||||
* meta_region_iterator_next (&iter))
|
||||
* {
|
||||
* [ Use iter.rectangle, iter.line_start, iter.line_end ]
|
||||
* }
|
||||
*/
|
||||
typedef struct _MetaRegionIterator MetaRegionIterator;
|
||||
|
||||
struct _MetaRegionIterator {
|
||||
cairo_region_t *region;
|
||||
cairo_rectangle_int_t rectangle;
|
||||
gboolean line_start;
|
||||
gboolean line_end;
|
||||
int i;
|
||||
|
||||
/*< private >*/
|
||||
int n_rectangles;
|
||||
cairo_rectangle_int_t next_rectangle;
|
||||
};
|
||||
|
||||
void meta_region_iterator_init (MetaRegionIterator *iter,
|
||||
cairo_region_t *region);
|
||||
gboolean meta_region_iterator_at_end (MetaRegionIterator *iter);
|
||||
void meta_region_iterator_next (MetaRegionIterator *iter);
|
||||
|
||||
cairo_region_t *meta_make_border_region (cairo_region_t *region,
|
||||
int x_amount,
|
||||
int y_amount,
|
||||
gboolean flip);
|
||||
|
||||
#endif /* __META_REGION_UTILS_H__ */
|
||||
@@ -1,350 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#define _GNU_SOURCE /* For M_PI */
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "compositor-private.h"
|
||||
#include "shadow.h"
|
||||
#include "tidy/tidy-texture-frame.h"
|
||||
|
||||
#define SHADOW_RADIUS 8
|
||||
#define SHADOW_OPACITY 0.9
|
||||
#define SHADOW_OFFSET_X (SHADOW_RADIUS)
|
||||
#define SHADOW_OFFSET_Y (SHADOW_RADIUS)
|
||||
|
||||
#define MAX_TILE_SZ 8 /* Must be <= shaddow radius */
|
||||
#define TILE_WIDTH (3*MAX_TILE_SZ)
|
||||
#define TILE_HEIGHT (3*MAX_TILE_SZ)
|
||||
|
||||
static unsigned char* shadow_gaussian_make_tile (void);
|
||||
|
||||
ClutterActor *
|
||||
mutter_create_shadow_frame (MetaCompositor *compositor)
|
||||
{
|
||||
ClutterActor *frame;
|
||||
|
||||
if (!compositor->shadow_src)
|
||||
{
|
||||
guchar *data;
|
||||
|
||||
data = shadow_gaussian_make_tile ();
|
||||
|
||||
compositor->shadow_src = clutter_texture_new ();
|
||||
|
||||
clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (compositor->shadow_src),
|
||||
data,
|
||||
TRUE,
|
||||
TILE_WIDTH,
|
||||
TILE_HEIGHT,
|
||||
TILE_WIDTH*4,
|
||||
4,
|
||||
0,
|
||||
NULL);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
frame = tidy_texture_frame_new (CLUTTER_TEXTURE (compositor->shadow_src),
|
||||
MAX_TILE_SZ,
|
||||
MAX_TILE_SZ,
|
||||
MAX_TILE_SZ,
|
||||
MAX_TILE_SZ);
|
||||
|
||||
clutter_actor_set_position (frame,
|
||||
SHADOW_OFFSET_X , SHADOW_OFFSET_Y);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
typedef struct GaussianMap
|
||||
{
|
||||
int size;
|
||||
double * data;
|
||||
} GaussianMap;
|
||||
|
||||
static double
|
||||
gaussian (double r, double x, double y)
|
||||
{
|
||||
return ((1 / (sqrt (2 * M_PI * r))) *
|
||||
exp ((- (x * x + y * y)) / (2 * r * r)));
|
||||
}
|
||||
|
||||
|
||||
static GaussianMap *
|
||||
make_gaussian_map (double r)
|
||||
{
|
||||
GaussianMap *c;
|
||||
int size = ((int) ceil ((r * 3)) + 1) & ~1;
|
||||
int center = size / 2;
|
||||
int x, y;
|
||||
double t = 0.0;
|
||||
double g;
|
||||
|
||||
c = g_malloc (sizeof (GaussianMap) + size * size * sizeof (double));
|
||||
c->size = size;
|
||||
|
||||
c->data = (double *) (c + 1);
|
||||
|
||||
for (y = 0; y < size; y++)
|
||||
for (x = 0; x < size; x++)
|
||||
{
|
||||
g = gaussian (r, (double) (x - center), (double) (y - center));
|
||||
t += g;
|
||||
c->data[y * size + x] = g;
|
||||
}
|
||||
|
||||
for (y = 0; y < size; y++)
|
||||
for (x = 0; x < size; x++)
|
||||
c->data[y*size + x] /= t;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static unsigned char
|
||||
sum_gaussian (GaussianMap * map, double opacity,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
int fx, fy;
|
||||
double * g_data;
|
||||
double * g_line = map->data;
|
||||
int g_size = map->size;
|
||||
int center = g_size / 2;
|
||||
int fx_start, fx_end;
|
||||
int fy_start, fy_end;
|
||||
double v;
|
||||
unsigned int r;
|
||||
|
||||
/*
|
||||
* Compute set of filter values which are "in range",
|
||||
* that's the set with:
|
||||
* 0 <= x + (fx-center) && x + (fx-center) < width &&
|
||||
* 0 <= y + (fy-center) && y + (fy-center) < height
|
||||
*
|
||||
* 0 <= x + (fx - center) x + fx - center < width
|
||||
* center - x <= fx fx < width + center - x
|
||||
*/
|
||||
|
||||
fx_start = center - x;
|
||||
if (fx_start < 0)
|
||||
fx_start = 0;
|
||||
fx_end = width + center - x;
|
||||
if (fx_end > g_size)
|
||||
fx_end = g_size;
|
||||
|
||||
fy_start = center - y;
|
||||
if (fy_start < 0)
|
||||
fy_start = 0;
|
||||
fy_end = height + center - y;
|
||||
if (fy_end > g_size)
|
||||
fy_end = g_size;
|
||||
|
||||
g_line = g_line + fy_start * g_size + fx_start;
|
||||
|
||||
v = 0;
|
||||
for (fy = fy_start; fy < fy_end; fy++)
|
||||
{
|
||||
g_data = g_line;
|
||||
g_line += g_size;
|
||||
|
||||
for (fx = fx_start; fx < fx_end; fx++)
|
||||
v += *g_data++;
|
||||
}
|
||||
if (v > 1)
|
||||
v = 1;
|
||||
|
||||
v *= (opacity * 255.0);
|
||||
|
||||
r = (unsigned int) v;
|
||||
|
||||
return (unsigned char) r;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
shadow_gaussian_make_tile ()
|
||||
{
|
||||
unsigned char * data;
|
||||
int size;
|
||||
int center;
|
||||
int x, y;
|
||||
unsigned char d;
|
||||
int pwidth, pheight;
|
||||
double opacity = SHADOW_OPACITY;
|
||||
static GaussianMap * gaussian_map = NULL;
|
||||
|
||||
struct _mypixel
|
||||
{
|
||||
unsigned char r;
|
||||
unsigned char g;
|
||||
unsigned char b;
|
||||
unsigned char a;
|
||||
} * _d;
|
||||
|
||||
|
||||
if (!gaussian_map)
|
||||
gaussian_map =
|
||||
make_gaussian_map (SHADOW_RADIUS);
|
||||
|
||||
size = gaussian_map->size;
|
||||
center = size / 2;
|
||||
|
||||
/* Top & bottom */
|
||||
|
||||
pwidth = MAX_TILE_SZ;
|
||||
pheight = MAX_TILE_SZ;
|
||||
|
||||
data = g_malloc0 (4 * TILE_WIDTH * TILE_HEIGHT);
|
||||
|
||||
_d = (struct _mypixel*) data;
|
||||
|
||||
/* N */
|
||||
for (y = 0; y < pheight; y++)
|
||||
{
|
||||
d = sum_gaussian (gaussian_map, opacity,
|
||||
center, y - center,
|
||||
TILE_WIDTH, TILE_HEIGHT);
|
||||
for (x = 0; x < pwidth; x++)
|
||||
{
|
||||
_d[y*3*pwidth + x + pwidth].r = 0;
|
||||
_d[y*3*pwidth + x + pwidth].g = 0;
|
||||
_d[y*3*pwidth + x + pwidth].b = 0;
|
||||
_d[y*3*pwidth + x + pwidth].a = d;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* S */
|
||||
pwidth = MAX_TILE_SZ;
|
||||
pheight = MAX_TILE_SZ;
|
||||
|
||||
for (y = 0; y < pheight; y++)
|
||||
{
|
||||
d = sum_gaussian (gaussian_map, opacity,
|
||||
center, y - center,
|
||||
TILE_WIDTH, TILE_HEIGHT);
|
||||
for (x = 0; x < pwidth; x++)
|
||||
{
|
||||
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].r = 0;
|
||||
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].g = 0;
|
||||
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].b = 0;
|
||||
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].a = d;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* w */
|
||||
pwidth = MAX_TILE_SZ;
|
||||
pheight = MAX_TILE_SZ;
|
||||
|
||||
for (x = 0; x < pwidth; x++)
|
||||
{
|
||||
d = sum_gaussian (gaussian_map, opacity,
|
||||
x - center, center,
|
||||
TILE_WIDTH, TILE_HEIGHT);
|
||||
for (y = 0; y < pheight; y++)
|
||||
{
|
||||
_d[y*3*pwidth + 3*pwidth*pheight + x].r = 0;
|
||||
_d[y*3*pwidth + 3*pwidth*pheight + x].g = 0;
|
||||
_d[y*3*pwidth + 3*pwidth*pheight + x].b = 0;
|
||||
_d[y*3*pwidth + 3*pwidth*pheight + x].a = d;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* E */
|
||||
for (x = 0; x < pwidth; x++)
|
||||
{
|
||||
d = sum_gaussian (gaussian_map, opacity,
|
||||
x - center, center,
|
||||
TILE_WIDTH, TILE_HEIGHT);
|
||||
for (y = 0; y < pheight; y++)
|
||||
{
|
||||
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].r = 0;
|
||||
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].g = 0;
|
||||
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].b = 0;
|
||||
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].a = d;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* NW */
|
||||
pwidth = MAX_TILE_SZ;
|
||||
pheight = MAX_TILE_SZ;
|
||||
|
||||
for (x = 0; x < pwidth; x++)
|
||||
for (y = 0; y < pheight; y++)
|
||||
{
|
||||
d = sum_gaussian (gaussian_map, opacity,
|
||||
x-center, y-center,
|
||||
TILE_WIDTH, TILE_HEIGHT);
|
||||
|
||||
_d[y*3*pwidth + x].r = 0;
|
||||
_d[y*3*pwidth + x].g = 0;
|
||||
_d[y*3*pwidth + x].b = 0;
|
||||
_d[y*3*pwidth + x].a = d;
|
||||
}
|
||||
|
||||
/* SW */
|
||||
for (x = 0; x < pwidth; x++)
|
||||
for (y = 0; y < pheight; y++)
|
||||
{
|
||||
d = sum_gaussian (gaussian_map, opacity,
|
||||
x-center, y-center,
|
||||
TILE_WIDTH, TILE_HEIGHT);
|
||||
|
||||
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].r = 0;
|
||||
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].g = 0;
|
||||
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].b = 0;
|
||||
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].a = d;
|
||||
}
|
||||
|
||||
/* SE */
|
||||
for (x = 0; x < pwidth; x++)
|
||||
for (y = 0; y < pheight; y++)
|
||||
{
|
||||
d = sum_gaussian (gaussian_map, opacity,
|
||||
x-center, y-center,
|
||||
TILE_WIDTH, TILE_HEIGHT);
|
||||
|
||||
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
|
||||
2*pwidth].r = 0;
|
||||
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
|
||||
2*pwidth].g = 0;
|
||||
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
|
||||
2*pwidth].b = 0;
|
||||
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
|
||||
2*pwidth].a = d;
|
||||
}
|
||||
|
||||
/* NE */
|
||||
for (x = 0; x < pwidth; x++)
|
||||
for (y = 0; y < pheight; y++)
|
||||
{
|
||||
d = sum_gaussian (gaussian_map, opacity,
|
||||
x-center, y-center,
|
||||
TILE_WIDTH, TILE_HEIGHT);
|
||||
|
||||
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].r = 0;
|
||||
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].g = 0;
|
||||
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].b = 0;
|
||||
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].a = d;
|
||||
}
|
||||
|
||||
/* center */
|
||||
pwidth = MAX_TILE_SZ;
|
||||
pheight = MAX_TILE_SZ;
|
||||
|
||||
d = sum_gaussian (gaussian_map, opacity,
|
||||
center, center, TILE_WIDTH, TILE_HEIGHT);
|
||||
|
||||
for (x = 0; x < pwidth; x++)
|
||||
for (y = 0; y < pheight; y++)
|
||||
{
|
||||
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].r = 0;
|
||||
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].g = 0;
|
||||
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].b = 0;
|
||||
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].a = 0;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#ifndef SHADOW_H
|
||||
#define SHADOW_H
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include "compositor.h"
|
||||
|
||||
ClutterActor *mutter_create_shadow_frame (MetaCompositor *compositor);
|
||||
|
||||
#endif /* SHADOW_H */
|
||||
@@ -1,641 +0,0 @@
|
||||
/* tidy-texture-frame.h: Expandible texture actor
|
||||
*
|
||||
* Copyright (C) 2007 OpenedHand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:tidy-texture-frame
|
||||
* @short_description: Stretch a texture to fit the entire allocation
|
||||
*
|
||||
* #TidyTextureFrame
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include "tidy-texture-frame.h"
|
||||
|
||||
#define TIDY_PARAM_READABLE \
|
||||
(G_PARAM_READABLE | \
|
||||
G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB)
|
||||
|
||||
#define TIDY_PARAM_READWRITE \
|
||||
(G_PARAM_READABLE | G_PARAM_WRITABLE | \
|
||||
G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_PARENT_TEXTURE,
|
||||
|
||||
PROP_LEFT,
|
||||
PROP_TOP,
|
||||
PROP_RIGHT,
|
||||
PROP_BOTTOM
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (TidyTextureFrame, tidy_texture_frame, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
#define TIDY_TEXTURE_FRAME_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFramePrivate))
|
||||
|
||||
struct _TidyTextureFramePrivate
|
||||
{
|
||||
ClutterTexture *parent_texture;
|
||||
|
||||
gfloat left;
|
||||
gfloat top;
|
||||
gfloat right;
|
||||
gfloat bottom;
|
||||
|
||||
CoglHandle material;
|
||||
|
||||
guint needs_paint : 1;
|
||||
};
|
||||
|
||||
static void
|
||||
tidy_texture_frame_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
|
||||
|
||||
if (G_UNLIKELY (priv->parent_texture == NULL))
|
||||
{
|
||||
if (min_width_p)
|
||||
*min_width_p = 0;
|
||||
|
||||
if (natural_width_p)
|
||||
*natural_width_p = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterActorClass *klass;
|
||||
|
||||
/* by directly querying the parent texture's class implementation
|
||||
* we are going around any override mechanism the parent texture
|
||||
* might have in place, and we ask directly for the original
|
||||
* preferred width
|
||||
*/
|
||||
klass = CLUTTER_ACTOR_GET_CLASS (priv->parent_texture);
|
||||
klass->get_preferred_width (CLUTTER_ACTOR (priv->parent_texture),
|
||||
for_height,
|
||||
min_width_p,
|
||||
natural_width_p);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_get_preferred_height (ClutterActor *self,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
|
||||
|
||||
if (G_UNLIKELY (priv->parent_texture == NULL))
|
||||
{
|
||||
if (min_height_p)
|
||||
*min_height_p = 0;
|
||||
|
||||
if (natural_height_p)
|
||||
*natural_height_p = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterActorClass *klass;
|
||||
|
||||
/* by directly querying the parent texture's class implementation
|
||||
* we are going around any override mechanism the parent texture
|
||||
* might have in place, and we ask directly for the original
|
||||
* preferred height
|
||||
*/
|
||||
klass = CLUTTER_ACTOR_GET_CLASS (priv->parent_texture);
|
||||
klass->get_preferred_height (CLUTTER_ACTOR (priv->parent_texture),
|
||||
for_width,
|
||||
min_height_p,
|
||||
natural_height_p);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_realize (ClutterActor *self)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
priv->material = cogl_material_new ();
|
||||
|
||||
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_unrealize (ClutterActor *self)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
|
||||
|
||||
if (priv->material == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
cogl_material_unref (priv->material);
|
||||
priv->material = COGL_INVALID_HANDLE;
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_paint (ClutterActor *self)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
|
||||
CoglHandle cogl_texture = COGL_INVALID_HANDLE;
|
||||
ClutterActorBox box = { 0, };
|
||||
gfloat width, height;
|
||||
gfloat tex_width, tex_height;
|
||||
gfloat ex, ey;
|
||||
gfloat tx1, ty1, tx2, ty2;
|
||||
guint8 opacity;
|
||||
|
||||
/* no need to paint stuff if we don't have a texture */
|
||||
if (G_UNLIKELY (priv->parent_texture == NULL))
|
||||
return;
|
||||
|
||||
if (!priv->needs_paint)
|
||||
return;
|
||||
|
||||
/* parent texture may have been hidden, so need to make sure it gets
|
||||
* realized
|
||||
*/
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent_texture))
|
||||
clutter_actor_realize (CLUTTER_ACTOR (priv->parent_texture));
|
||||
|
||||
cogl_texture = clutter_texture_get_cogl_texture (priv->parent_texture);
|
||||
if (cogl_texture == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (cogl_texture);
|
||||
tex_height = cogl_texture_get_height (cogl_texture);
|
||||
|
||||
clutter_actor_get_allocation_box (self, &box);
|
||||
width = box.x2 - box.x1;
|
||||
height = box.y2 - box.y1;
|
||||
|
||||
tx1 = priv->left / tex_width;
|
||||
tx2 = (tex_width - priv->right) / tex_width;
|
||||
ty1 = priv->top / tex_height;
|
||||
ty2 = (tex_height - priv->bottom) / tex_height;
|
||||
|
||||
ex = width - priv->right;
|
||||
if (ex < 0)
|
||||
ex = priv->right; /* FIXME ? */
|
||||
|
||||
ey = height - priv->bottom;
|
||||
if (ey < 0)
|
||||
ey = priv->bottom; /* FIXME ? */
|
||||
|
||||
opacity = clutter_actor_get_paint_opacity (self);
|
||||
|
||||
g_assert (priv->material != COGL_INVALID_HANDLE);
|
||||
|
||||
/* set the source material using the parent texture's COGL handle */
|
||||
cogl_material_set_color4ub (priv->material, opacity, opacity, opacity, opacity);
|
||||
cogl_material_set_layer (priv->material, 0, cogl_texture);
|
||||
cogl_set_source (priv->material);
|
||||
|
||||
/* top left corner */
|
||||
cogl_rectangle_with_texture_coords (0, 0, priv->left, priv->top,
|
||||
0.0, 0.0,
|
||||
tx1, ty1);
|
||||
|
||||
/* top middle */
|
||||
cogl_rectangle_with_texture_coords (priv->left, 0, ex, priv->top,
|
||||
tx1, 0.0,
|
||||
tx2, ty1);
|
||||
|
||||
/* top right */
|
||||
cogl_rectangle_with_texture_coords (ex, 0, width, priv->top,
|
||||
tx2, 0.0,
|
||||
1.0, ty1);
|
||||
|
||||
/* mid left */
|
||||
cogl_rectangle_with_texture_coords (0, priv->top, priv->left, ey,
|
||||
0.0, ty1,
|
||||
tx1, ty2);
|
||||
|
||||
/* center */
|
||||
cogl_rectangle_with_texture_coords (priv->left, priv->top, ex, ey,
|
||||
tx1, ty1,
|
||||
tx2, ty2);
|
||||
|
||||
/* mid right */
|
||||
cogl_rectangle_with_texture_coords (ex, priv->top, width, ey,
|
||||
tx2, ty1,
|
||||
1.0, ty2);
|
||||
|
||||
/* bottom left */
|
||||
cogl_rectangle_with_texture_coords (0, ey, priv->left, height,
|
||||
0.0, ty2,
|
||||
tx1, 1.0);
|
||||
|
||||
/* bottom center */
|
||||
cogl_rectangle_with_texture_coords (priv->left, ey, ex, height,
|
||||
tx1, ty2,
|
||||
tx2, 1.0);
|
||||
|
||||
/* bottom right */
|
||||
cogl_rectangle_with_texture_coords (ex, ey, width, height,
|
||||
tx2, ty2,
|
||||
1.0, 1.0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
tidy_texture_frame_set_frame_internal (TidyTextureFrame *frame,
|
||||
gfloat left,
|
||||
gfloat top,
|
||||
gfloat right,
|
||||
gfloat bottom)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = frame->priv;
|
||||
GObject *gobject = G_OBJECT (frame);
|
||||
gboolean changed = FALSE;
|
||||
|
||||
g_object_freeze_notify (gobject);
|
||||
|
||||
if (priv->top != top)
|
||||
{
|
||||
priv->top = top;
|
||||
g_object_notify (gobject, "top");
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (priv->right != right)
|
||||
{
|
||||
priv->right = right;
|
||||
g_object_notify (gobject, "right");
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (priv->bottom != bottom)
|
||||
{
|
||||
priv->bottom = bottom;
|
||||
g_object_notify (gobject, "bottom");
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (priv->left != left)
|
||||
{
|
||||
priv->left = left;
|
||||
g_object_notify (gobject, "left");
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (changed && CLUTTER_ACTOR_IS_VISIBLE (frame))
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (frame));
|
||||
|
||||
g_object_thaw_notify (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
TidyTextureFrame *frame = TIDY_TEXTURE_FRAME (gobject);
|
||||
TidyTextureFramePrivate *priv = frame->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PARENT_TEXTURE:
|
||||
tidy_texture_frame_set_parent_texture (frame,
|
||||
g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_TOP:
|
||||
tidy_texture_frame_set_frame_internal (frame,
|
||||
priv->left,
|
||||
g_value_get_float (value),
|
||||
priv->right,
|
||||
priv->bottom);
|
||||
break;
|
||||
|
||||
case PROP_RIGHT:
|
||||
tidy_texture_frame_set_frame_internal (frame,
|
||||
priv->top,
|
||||
g_value_get_float (value),
|
||||
priv->bottom,
|
||||
priv->left);
|
||||
break;
|
||||
|
||||
case PROP_BOTTOM:
|
||||
tidy_texture_frame_set_frame_internal (frame,
|
||||
priv->top,
|
||||
priv->right,
|
||||
g_value_get_float (value),
|
||||
priv->left);
|
||||
break;
|
||||
|
||||
case PROP_LEFT:
|
||||
tidy_texture_frame_set_frame_internal (frame,
|
||||
priv->top,
|
||||
priv->right,
|
||||
priv->bottom,
|
||||
g_value_get_float (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (gobject)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PARENT_TEXTURE:
|
||||
g_value_set_object (value, priv->parent_texture);
|
||||
break;
|
||||
|
||||
case PROP_LEFT:
|
||||
g_value_set_float (value, priv->left);
|
||||
break;
|
||||
|
||||
case PROP_TOP:
|
||||
g_value_set_float (value, priv->top);
|
||||
break;
|
||||
|
||||
case PROP_RIGHT:
|
||||
g_value_set_float (value, priv->right);
|
||||
break;
|
||||
|
||||
case PROP_BOTTOM:
|
||||
g_value_set_float (value, priv->bottom);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_dispose (GObject *gobject)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (gobject)->priv;
|
||||
|
||||
if (priv->parent_texture)
|
||||
{
|
||||
g_object_unref (priv->parent_texture);
|
||||
priv->parent_texture = NULL;
|
||||
}
|
||||
|
||||
if (priv->material)
|
||||
{
|
||||
cogl_material_unref (priv->material);
|
||||
priv->material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (tidy_texture_frame_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_class_init (TidyTextureFrameClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (TidyTextureFramePrivate));
|
||||
|
||||
actor_class->get_preferred_width =
|
||||
tidy_texture_frame_get_preferred_width;
|
||||
actor_class->get_preferred_height =
|
||||
tidy_texture_frame_get_preferred_height;
|
||||
actor_class->realize = tidy_texture_frame_realize;
|
||||
actor_class->unrealize = tidy_texture_frame_unrealize;
|
||||
actor_class->paint = tidy_texture_frame_paint;
|
||||
|
||||
gobject_class->set_property = tidy_texture_frame_set_property;
|
||||
gobject_class->get_property = tidy_texture_frame_get_property;
|
||||
gobject_class->dispose = tidy_texture_frame_dispose;
|
||||
|
||||
pspec = g_param_spec_object ("parent-texture",
|
||||
"Parent Texture",
|
||||
"The parent ClutterTexture",
|
||||
CLUTTER_TYPE_TEXTURE,
|
||||
TIDY_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT);
|
||||
g_object_class_install_property (gobject_class, PROP_PARENT_TEXTURE, pspec);
|
||||
|
||||
pspec = g_param_spec_float ("left",
|
||||
"Left",
|
||||
"Left offset",
|
||||
0, G_MAXFLOAT,
|
||||
0,
|
||||
TIDY_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_LEFT, pspec);
|
||||
|
||||
pspec = g_param_spec_float ("top",
|
||||
"Top",
|
||||
"Top offset",
|
||||
0, G_MAXFLOAT,
|
||||
0,
|
||||
TIDY_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_TOP, pspec);
|
||||
|
||||
pspec = g_param_spec_float ("bottom",
|
||||
"Bottom",
|
||||
"Bottom offset",
|
||||
0, G_MAXFLOAT,
|
||||
0,
|
||||
TIDY_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_BOTTOM, pspec);
|
||||
|
||||
pspec = g_param_spec_float ("right",
|
||||
"Right",
|
||||
"Right offset",
|
||||
0, G_MAXFLOAT,
|
||||
0,
|
||||
TIDY_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_RIGHT, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_init (TidyTextureFrame *self)
|
||||
{
|
||||
TidyTextureFramePrivate *priv;
|
||||
|
||||
self->priv = priv = TIDY_TEXTURE_FRAME_GET_PRIVATE (self);
|
||||
|
||||
priv->material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* tidy_texture_frame_new:
|
||||
* @texture: a #ClutterTexture or %NULL
|
||||
* @left: left margin preserving its content
|
||||
* @top: top margin preserving its content
|
||||
* @right: right margin preserving its content
|
||||
* @bottom: bottom margin preserving its content
|
||||
*
|
||||
* A #TidyTextureFrame is a specialized texture that efficiently clones
|
||||
* an area of the given @texture while keeping preserving portions of the
|
||||
* same texture.
|
||||
*
|
||||
* A #TidyTextureFrame can be used to make a rectangular texture fit a
|
||||
* given size without stretching its borders.
|
||||
*
|
||||
* Return value: the newly created #TidyTextureFrame
|
||||
*/
|
||||
ClutterActor*
|
||||
tidy_texture_frame_new (ClutterTexture *texture,
|
||||
gfloat left,
|
||||
gfloat top,
|
||||
gfloat right,
|
||||
gfloat bottom)
|
||||
{
|
||||
g_return_val_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture), NULL);
|
||||
|
||||
return g_object_new (TIDY_TYPE_TEXTURE_FRAME,
|
||||
"parent-texture", texture,
|
||||
"left", left,
|
||||
"top", top,
|
||||
"right", right,
|
||||
"bottom", bottom,
|
||||
NULL);
|
||||
}
|
||||
|
||||
ClutterTexture *
|
||||
tidy_texture_frame_get_parent_texture (TidyTextureFrame *frame)
|
||||
{
|
||||
g_return_val_if_fail (TIDY_IS_TEXTURE_FRAME (frame), NULL);
|
||||
|
||||
return frame->priv->parent_texture;
|
||||
}
|
||||
|
||||
void
|
||||
tidy_texture_frame_set_parent_texture (TidyTextureFrame *frame,
|
||||
ClutterTexture *texture)
|
||||
{
|
||||
TidyTextureFramePrivate *priv;
|
||||
gboolean was_visible;
|
||||
|
||||
g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
|
||||
g_return_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture));
|
||||
|
||||
priv = frame->priv;
|
||||
|
||||
was_visible = CLUTTER_ACTOR_IS_VISIBLE (frame);
|
||||
|
||||
if (priv->parent_texture == texture)
|
||||
return;
|
||||
|
||||
if (priv->parent_texture)
|
||||
{
|
||||
g_object_unref (priv->parent_texture);
|
||||
priv->parent_texture = NULL;
|
||||
|
||||
if (was_visible)
|
||||
clutter_actor_hide (CLUTTER_ACTOR (frame));
|
||||
}
|
||||
|
||||
if (texture)
|
||||
{
|
||||
priv->parent_texture = g_object_ref (texture);
|
||||
|
||||
if (was_visible && CLUTTER_ACTOR_IS_VISIBLE (priv->parent_texture))
|
||||
clutter_actor_show (CLUTTER_ACTOR (frame));
|
||||
}
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (frame));
|
||||
|
||||
g_object_notify (G_OBJECT (frame), "parent-texture");
|
||||
}
|
||||
|
||||
void
|
||||
tidy_texture_frame_set_frame (TidyTextureFrame *frame,
|
||||
gfloat top,
|
||||
gfloat right,
|
||||
gfloat bottom,
|
||||
gfloat left)
|
||||
{
|
||||
g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
|
||||
|
||||
tidy_texture_frame_set_frame_internal (frame, top, right, bottom, left);
|
||||
}
|
||||
|
||||
void
|
||||
tidy_texture_frame_get_frame (TidyTextureFrame *frame,
|
||||
gfloat *top,
|
||||
gfloat *right,
|
||||
gfloat *bottom,
|
||||
gfloat *left)
|
||||
{
|
||||
TidyTextureFramePrivate *priv;
|
||||
|
||||
g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
|
||||
|
||||
priv = frame->priv;
|
||||
|
||||
if (top)
|
||||
*top = priv->top;
|
||||
|
||||
if (right)
|
||||
*right = priv->right;
|
||||
|
||||
if (bottom)
|
||||
*bottom = priv->bottom;
|
||||
|
||||
if (left)
|
||||
*left = priv->left;
|
||||
}
|
||||
|
||||
/**
|
||||
* tidy_texture_frame_set_needs_paint:
|
||||
* @frame: a #TidyTextureframe
|
||||
* @needs_paint: if %FALSE, the paint will be skipped
|
||||
*
|
||||
* Provides a hint to the texture frame that it is totally obscured
|
||||
* and doesn't need to be painted. This would typically be called
|
||||
* by a parent container if it detects the condition prior to
|
||||
* painting its children and then unset afterwards.
|
||||
*
|
||||
* Since it is not supposed to have any effect on display, it does
|
||||
* not queue a repaint.
|
||||
*/
|
||||
void
|
||||
tidy_texture_frame_set_needs_paint (TidyTextureFrame *frame,
|
||||
gboolean needs_paint)
|
||||
{
|
||||
TidyTextureFramePrivate *priv;
|
||||
|
||||
g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
|
||||
|
||||
priv = frame->priv;
|
||||
|
||||
priv->needs_paint = needs_paint;
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/* tidy-texture-frame.h: Expandible texture actor
|
||||
*
|
||||
* Copyright (C) 2007, 2008 OpenedHand Ltd
|
||||
* Copyright (C) 2009 Intel Corp.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _HAVE_TIDY_TEXTURE_FRAME_H
|
||||
#define _HAVE_TIDY_TEXTURE_FRAME_H
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define TIDY_TYPE_TEXTURE_FRAME (tidy_texture_frame_get_type ())
|
||||
#define TIDY_TEXTURE_FRAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrame))
|
||||
#define TIDY_TEXTURE_FRAME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrameClass))
|
||||
#define TIDY_IS_TEXTURE_FRAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TIDY_TYPE_TEXTURE_FRAME))
|
||||
#define TIDY_IS_TEXTURE_FRAME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TIDY_TYPE_TEXTURE_FRAME))
|
||||
#define TIDY_TEXTURE_FRAME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrameClass))
|
||||
|
||||
typedef struct _TidyTextureFrame TidyTextureFrame;
|
||||
typedef struct _TidyTextureFramePrivate TidyTextureFramePrivate;
|
||||
typedef struct _TidyTextureFrameClass TidyTextureFrameClass;
|
||||
|
||||
struct _TidyTextureFrame
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActor parent_instance;
|
||||
|
||||
TidyTextureFramePrivate *priv;
|
||||
};
|
||||
|
||||
struct _TidyTextureFrameClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
/* padding for future expansion */
|
||||
void (*_clutter_box_1) (void);
|
||||
void (*_clutter_box_2) (void);
|
||||
void (*_clutter_box_3) (void);
|
||||
void (*_clutter_box_4) (void);
|
||||
};
|
||||
|
||||
GType tidy_texture_frame_get_type (void) G_GNUC_CONST;
|
||||
ClutterActor * tidy_texture_frame_new (ClutterTexture *texture,
|
||||
gfloat top,
|
||||
gfloat right,
|
||||
gfloat bottom,
|
||||
gfloat left);
|
||||
void tidy_texture_frame_set_parent_texture (TidyTextureFrame *frame,
|
||||
ClutterTexture *texture);
|
||||
ClutterTexture *tidy_texture_frame_get_parent_texture (TidyTextureFrame *frame);
|
||||
void tidy_texture_frame_set_frame (TidyTextureFrame *frame,
|
||||
gfloat top,
|
||||
gfloat right,
|
||||
gfloat bottom,
|
||||
gfloat left);
|
||||
void tidy_texture_frame_get_frame (TidyTextureFrame *frame,
|
||||
gfloat *top,
|
||||
gfloat *right,
|
||||
gfloat *bottom,
|
||||
gfloat *left);
|
||||
|
||||
void tidy_texture_frame_set_needs_paint (TidyTextureFrame *frame,
|
||||
gboolean needs_paint);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _HAVE_TIDY_TEXTURE_FRAME_H */
|
||||
@@ -1,138 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Metacity Alt-Tab abstraction */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "alttabhandlerdefault.h"
|
||||
#include "screen-private.h"
|
||||
|
||||
static GType handler_type = G_TYPE_INVALID;
|
||||
|
||||
GType meta_alt_tab_handler_default_get_type (void);
|
||||
|
||||
void
|
||||
meta_alt_tab_handler_register (GType type)
|
||||
{
|
||||
handler_type = type;
|
||||
}
|
||||
|
||||
MetaAltTabHandler *
|
||||
meta_alt_tab_handler_new (MetaScreen *screen,
|
||||
gboolean immediate)
|
||||
{
|
||||
if (handler_type == G_TYPE_INVALID)
|
||||
handler_type = meta_alt_tab_handler_default_get_type ();
|
||||
|
||||
return g_object_new (handler_type,
|
||||
"screen", screen,
|
||||
"immediate", immediate,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void meta_alt_tab_handler_class_init (GObjectClass *object_class);
|
||||
|
||||
GType
|
||||
meta_alt_tab_handler_get_type (void)
|
||||
{
|
||||
static volatile gsize g_define_type_id__volatile = 0;
|
||||
|
||||
if (g_once_init_enter (&g_define_type_id__volatile))
|
||||
{
|
||||
const GTypeInfo type_info =
|
||||
{
|
||||
sizeof (MetaAltTabHandlerInterface), /* class_size */
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc)meta_alt_tab_handler_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
0,
|
||||
0, /* n_preallocs */
|
||||
NULL
|
||||
};
|
||||
GType g_define_type_id =
|
||||
g_type_register_static (G_TYPE_INTERFACE, "MetaAltTabHandler",
|
||||
&type_info, 0);
|
||||
|
||||
g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT);
|
||||
|
||||
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
|
||||
}
|
||||
|
||||
return g_define_type_id__volatile;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_class_init (GObjectClass *object_class)
|
||||
{
|
||||
g_object_interface_install_property (object_class,
|
||||
g_param_spec_object ("screen",
|
||||
"Screen",
|
||||
"MetaScreen this is the switcher for",
|
||||
META_TYPE_SCREEN,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_interface_install_property (object_class,
|
||||
g_param_spec_boolean ("immediate",
|
||||
"Immediate mode",
|
||||
"Whether or not to select windows immediately",
|
||||
FALSE,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
|
||||
}
|
||||
|
||||
void
|
||||
meta_alt_tab_handler_add_window (MetaAltTabHandler *handler,
|
||||
MetaWindow *window)
|
||||
{
|
||||
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->add_window (handler, window);
|
||||
}
|
||||
|
||||
void
|
||||
meta_alt_tab_handler_show (MetaAltTabHandler *handler,
|
||||
MetaWindow *initial_selection)
|
||||
{
|
||||
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->show (handler,
|
||||
initial_selection);
|
||||
}
|
||||
|
||||
void
|
||||
meta_alt_tab_handler_destroy (MetaAltTabHandler *handler)
|
||||
{
|
||||
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->destroy (handler);
|
||||
}
|
||||
|
||||
void
|
||||
meta_alt_tab_handler_forward (MetaAltTabHandler *handler)
|
||||
{
|
||||
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->forward (handler);
|
||||
}
|
||||
|
||||
void
|
||||
meta_alt_tab_handler_backward (MetaAltTabHandler *handler)
|
||||
{
|
||||
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->backward (handler);
|
||||
}
|
||||
|
||||
MetaWindow *
|
||||
meta_alt_tab_handler_get_selected (MetaAltTabHandler *handler)
|
||||
{
|
||||
return META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->get_selected (handler);
|
||||
}
|
||||
@@ -1,223 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Metacity Alt-Tab abstraction: default implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "alttabhandlerdefault.h"
|
||||
#include "frame-private.h"
|
||||
#include "window-private.h"
|
||||
|
||||
static void meta_alt_tab_handler_default_interface_init (MetaAltTabHandlerInterface *handler_iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (MetaAltTabHandlerDefault, meta_alt_tab_handler_default, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_ALT_TAB_HANDLER,
|
||||
meta_alt_tab_handler_default_interface_init))
|
||||
|
||||
enum {
|
||||
PROP_SCREEN = 1,
|
||||
PROP_IMMEDIATE
|
||||
};
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_init (MetaAltTabHandlerDefault *hd)
|
||||
{
|
||||
hd->entries = g_array_new (FALSE, FALSE, sizeof (MetaTabEntry));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SCREEN:
|
||||
hd->screen = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_IMMEDIATE:
|
||||
hd->immediate_mode = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_finalize (GObject *object)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (object);
|
||||
|
||||
g_array_free (hd->entries, TRUE);
|
||||
|
||||
if (hd->tab_popup)
|
||||
meta_ui_tab_popup_free (hd->tab_popup);
|
||||
|
||||
G_OBJECT_CLASS (meta_alt_tab_handler_default_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_add_window (MetaAltTabHandler *handler,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
|
||||
MetaTabEntry entry;
|
||||
MetaRectangle r;
|
||||
|
||||
entry.key = (MetaTabEntryKey) window;
|
||||
entry.title = window->title;
|
||||
entry.icon = window->icon;
|
||||
entry.blank = FALSE;
|
||||
entry.hidden = !meta_window_showing_on_its_workspace (window);
|
||||
entry.demands_attention = window->wm_state_demands_attention;
|
||||
|
||||
if (hd->immediate_mode || !entry.hidden ||
|
||||
!meta_window_get_icon_geometry (window, &r))
|
||||
meta_window_get_outer_rect (window, &r);
|
||||
entry.rect = r;
|
||||
|
||||
/* Find inside of highlight rectangle to be used when window is
|
||||
* outlined for tabbing. This should be the size of the
|
||||
* east/west frame, and the size of the south frame, on those
|
||||
* sides. On the top it should be the size of the south frame
|
||||
* edge.
|
||||
*/
|
||||
#define OUTLINE_WIDTH 5
|
||||
/* Top side */
|
||||
if (!entry.hidden &&
|
||||
window->frame && window->frame->bottom_height > 0 &&
|
||||
window->frame->child_y >= window->frame->bottom_height)
|
||||
entry.inner_rect.y = window->frame->bottom_height;
|
||||
else
|
||||
entry.inner_rect.y = OUTLINE_WIDTH;
|
||||
|
||||
/* Bottom side */
|
||||
if (!entry.hidden &&
|
||||
window->frame && window->frame->bottom_height != 0)
|
||||
entry.inner_rect.height = r.height
|
||||
- entry.inner_rect.y - window->frame->bottom_height;
|
||||
else
|
||||
entry.inner_rect.height = r.height
|
||||
- entry.inner_rect.y - OUTLINE_WIDTH;
|
||||
|
||||
/* Left side */
|
||||
if (!entry.hidden && window->frame && window->frame->child_x != 0)
|
||||
entry.inner_rect.x = window->frame->child_x;
|
||||
else
|
||||
entry.inner_rect.x = OUTLINE_WIDTH;
|
||||
|
||||
/* Right side */
|
||||
if (!entry.hidden &&
|
||||
window->frame && window->frame->right_width != 0)
|
||||
entry.inner_rect.width = r.width
|
||||
- entry.inner_rect.x - window->frame->right_width;
|
||||
else
|
||||
entry.inner_rect.width = r.width
|
||||
- entry.inner_rect.x - OUTLINE_WIDTH;
|
||||
|
||||
g_array_append_val (hd->entries, entry);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_show (MetaAltTabHandler *handler,
|
||||
MetaWindow *initial_selection)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
|
||||
|
||||
if (hd->tab_popup)
|
||||
return;
|
||||
|
||||
hd->tab_popup = meta_ui_tab_popup_new ((MetaTabEntry *)hd->entries->data,
|
||||
hd->screen->number,
|
||||
hd->entries->len,
|
||||
5, /* FIXME */
|
||||
TRUE);
|
||||
meta_ui_tab_popup_select (hd->tab_popup, (MetaTabEntryKey) initial_selection);
|
||||
meta_ui_tab_popup_set_showing (hd->tab_popup, !hd->immediate_mode);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_destroy (MetaAltTabHandler *handler)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
|
||||
|
||||
if (hd->tab_popup)
|
||||
{
|
||||
meta_ui_tab_popup_free (hd->tab_popup);
|
||||
hd->tab_popup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_forward (MetaAltTabHandler *handler)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
|
||||
|
||||
if (hd->tab_popup)
|
||||
meta_ui_tab_popup_forward (hd->tab_popup);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_backward (MetaAltTabHandler *handler)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
|
||||
|
||||
if (hd->tab_popup)
|
||||
meta_ui_tab_popup_backward (hd->tab_popup);
|
||||
}
|
||||
|
||||
static MetaWindow *
|
||||
meta_alt_tab_handler_default_get_selected (MetaAltTabHandler *handler)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
|
||||
|
||||
if (hd->tab_popup)
|
||||
return (MetaWindow *)meta_ui_tab_popup_get_selected (hd->tab_popup);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_class_init (MetaAltTabHandlerDefaultClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = meta_alt_tab_handler_default_set_property;
|
||||
object_class->finalize = meta_alt_tab_handler_default_finalize;
|
||||
|
||||
g_object_class_override_property (object_class, PROP_SCREEN, "screen");
|
||||
g_object_class_override_property (object_class, PROP_IMMEDIATE, "immediate");
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_interface_init (MetaAltTabHandlerInterface *handler_iface)
|
||||
{
|
||||
handler_iface->add_window = meta_alt_tab_handler_default_add_window;
|
||||
handler_iface->show = meta_alt_tab_handler_default_show;
|
||||
handler_iface->destroy = meta_alt_tab_handler_default_destroy;
|
||||
handler_iface->forward = meta_alt_tab_handler_default_forward;
|
||||
handler_iface->backward = meta_alt_tab_handler_default_backward;
|
||||
handler_iface->get_selected = meta_alt_tab_handler_default_get_selected;
|
||||
}
|
||||
@@ -52,6 +52,9 @@
|
||||
#include "bell.h"
|
||||
#include "screen-private.h"
|
||||
#include "prefs.h"
|
||||
#ifdef HAVE_LIBCANBERRA
|
||||
#include <canberra-gtk.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Flashes one entire screen. This is done by making a window the size of the
|
||||
@@ -228,18 +231,18 @@ bell_flash_window_frame (MetaWindow *window)
|
||||
*/
|
||||
static void
|
||||
bell_flash_frame (MetaDisplay *display,
|
||||
XkbAnyEvent *xkb_ev)
|
||||
XkbAnyEvent *xkb_ev)
|
||||
{
|
||||
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev;
|
||||
MetaWindow *window;
|
||||
|
||||
g_assert (xkb_ev->xkb_type == XkbBellNotify);
|
||||
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
|
||||
if (!window && (display->focus_window) && (display->focus_window->frame))
|
||||
if (!window && (display->focus_window))
|
||||
{
|
||||
window = display->focus_window;
|
||||
}
|
||||
if (window)
|
||||
if (window && window->frame)
|
||||
{
|
||||
bell_flash_window_frame (window);
|
||||
}
|
||||
@@ -285,6 +288,48 @@ meta_bell_notify (MetaDisplay *display,
|
||||
/* flash something */
|
||||
if (meta_prefs_get_visual_bell ())
|
||||
bell_visual_notify (display, xkb_ev);
|
||||
|
||||
#ifdef HAVE_LIBCANBERRA
|
||||
if (meta_prefs_bell_is_audible ())
|
||||
{
|
||||
ca_proplist *p;
|
||||
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent*) xkb_ev;
|
||||
MetaWindow *window;
|
||||
int res;
|
||||
|
||||
ca_proplist_create (&p);
|
||||
ca_proplist_sets (p, CA_PROP_EVENT_ID, "bell-window-system");
|
||||
ca_proplist_sets (p, CA_PROP_EVENT_DESCRIPTION, _("Bell event"));
|
||||
ca_proplist_sets (p, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent");
|
||||
|
||||
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
|
||||
if (!window && (display->focus_window) && (display->focus_window->frame))
|
||||
window = display->focus_window;
|
||||
|
||||
if (window)
|
||||
{
|
||||
ca_proplist_sets (p, CA_PROP_WINDOW_NAME, window->title);
|
||||
ca_proplist_setf (p, CA_PROP_WINDOW_X11_XID, "%lu", (unsigned long)window->xwindow);
|
||||
ca_proplist_sets (p, CA_PROP_APPLICATION_NAME, window->res_name);
|
||||
ca_proplist_setf (p, CA_PROP_APPLICATION_PROCESS_ID, "%d", window->net_wm_pid);
|
||||
}
|
||||
|
||||
/* First, we try to play a real sound ... */
|
||||
res = ca_context_play_full (ca_gtk_context_get (), 1, p, NULL, NULL);
|
||||
|
||||
ca_proplist_destroy (p);
|
||||
|
||||
if (res != CA_SUCCESS && res != CA_ERROR_DISABLED)
|
||||
{
|
||||
/* ...and in case that failed we use the classic X11 bell. */
|
||||
XkbForceDeviceBell (display->xdisplay,
|
||||
xkb_bell_event->device,
|
||||
xkb_bell_event->bell_class,
|
||||
xkb_bell_event->bell_id,
|
||||
xkb_bell_event->percent);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_LIBCANBERRA */
|
||||
}
|
||||
#endif /* HAVE_XKB */
|
||||
|
||||
@@ -292,11 +337,19 @@ void
|
||||
meta_bell_set_audible (MetaDisplay *display, gboolean audible)
|
||||
{
|
||||
#ifdef HAVE_XKB
|
||||
#ifdef HAVE_LIBCANBERRA
|
||||
/* When we are playing sounds using libcanberra support, we handle the
|
||||
* bell whether its an audible bell or a visible bell */
|
||||
gboolean enable_system_bell = FALSE;
|
||||
#else
|
||||
gboolean enable_system_bell = audible;
|
||||
#endif /* HAVE_LIBCANBERRA */
|
||||
|
||||
XkbChangeEnabledControls (display->xdisplay,
|
||||
XkbUseCoreKbd,
|
||||
XkbAudibleBellMask,
|
||||
audible ? XkbAudibleBellMask : 0);
|
||||
#endif
|
||||
XkbUseCoreKbd,
|
||||
XkbAudibleBellMask,
|
||||
enable_system_bell ? XkbAudibleBellMask : 0);
|
||||
#endif /* HAVE_XKB */
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -323,11 +376,7 @@ meta_bell_init (MetaDisplay *display)
|
||||
XkbUseCoreKbd,
|
||||
XkbBellNotifyMask,
|
||||
XkbBellNotifyMask);
|
||||
XkbChangeEnabledControls (display->xdisplay,
|
||||
XkbUseCoreKbd,
|
||||
XkbAudibleBellMask,
|
||||
meta_prefs_bell_is_audible ()
|
||||
? XkbAudibleBellMask : 0);
|
||||
meta_bell_set_audible (display, meta_prefs_bell_is_audible ());
|
||||
if (visual_bell_auto_reset) {
|
||||
XkbSetAutoResetControls (display->xdisplay,
|
||||
XkbAudibleBellMask,
|
||||
|
||||
220
src/core/boxes-private.h
Normal file
220
src/core/boxes-private.h
Normal file
@@ -0,0 +1,220 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Simple box operations */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005, 2006 Elijah Newren
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_BOXES_PRIVATE_H
|
||||
#define META_BOXES_PRIVATE_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include "common.h"
|
||||
#include "boxes.h"
|
||||
|
||||
#define BOX_LEFT(box) ((box).x) /* Leftmost pixel of rect */
|
||||
#define BOX_RIGHT(box) ((box).x + (box).width) /* One pixel past right */
|
||||
#define BOX_TOP(box) ((box).y) /* Topmost pixel of rect */
|
||||
#define BOX_BOTTOM(box) ((box).y + (box).height) /* One pixel past bottom */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FIXED_DIRECTION_NONE = 0,
|
||||
FIXED_DIRECTION_X = 1 << 0,
|
||||
FIXED_DIRECTION_Y = 1 << 1,
|
||||
} FixedDirections;
|
||||
|
||||
/* Output functions -- note that the output buffer had better be big enough:
|
||||
* rect_to_string: RECT_LENGTH
|
||||
* region_to_string: (RECT_LENGTH+strlen(separator_string)) *
|
||||
* g_list_length (region)
|
||||
* edge_to_string: EDGE_LENGTH
|
||||
* edge_list_to_...: (EDGE_LENGTH+strlen(separator_string)) *
|
||||
* g_list_length (edge_list)
|
||||
*/
|
||||
#define RECT_LENGTH 27
|
||||
#define EDGE_LENGTH 37
|
||||
char* meta_rectangle_to_string (const MetaRectangle *rect,
|
||||
char *output);
|
||||
char* meta_rectangle_region_to_string (GList *region,
|
||||
const char *separator_string,
|
||||
char *output);
|
||||
char* meta_rectangle_edge_to_string (const MetaEdge *edge,
|
||||
char *output);
|
||||
char* meta_rectangle_edge_list_to_string (
|
||||
GList *edge_list,
|
||||
const char *separator_string,
|
||||
char *output);
|
||||
|
||||
/* Resize old_rect to the given new_width and new_height, but store the
|
||||
* result in rect. NOTE THAT THIS IS RESIZE ONLY SO IT CANNOT BE USED FOR
|
||||
* A MOVERESIZE OPERATION (that simplies the routine a little bit as it
|
||||
* means there's no difference between NorthWestGravity and StaticGravity.
|
||||
* Also, I lied a little bit--technically, you could use it in a MoveResize
|
||||
* operation if you muck with old_rect just right).
|
||||
*/
|
||||
void meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect,
|
||||
MetaRectangle *rect,
|
||||
int gravity,
|
||||
int new_width,
|
||||
int new_height);
|
||||
|
||||
/* find a list of rectangles with the property that a window is contained
|
||||
* in the given region if and only if it is contained in one of the
|
||||
* rectangles in the list.
|
||||
*
|
||||
* In this case, the region is given by taking basic_rect, removing from
|
||||
* it the intersections with all the rectangles in the all_struts list,
|
||||
* then expanding all the rectangles in the resulting list by the given
|
||||
* amounts on each side.
|
||||
*
|
||||
* See boxes.c for more details.
|
||||
*/
|
||||
GList* meta_rectangle_get_minimal_spanning_set_for_region (
|
||||
const MetaRectangle *basic_rect,
|
||||
const GSList *all_struts);
|
||||
|
||||
/* Expand all rectangles in region by the given amount on each side */
|
||||
GList* meta_rectangle_expand_region (GList *region,
|
||||
const int left_expand,
|
||||
const int right_expand,
|
||||
const int top_expand,
|
||||
const int bottom_expand);
|
||||
/* Same as for meta_rectangle_expand_region except that rectangles not at
|
||||
* least min_x or min_y in size are not expanded in that direction
|
||||
*/
|
||||
GList* meta_rectangle_expand_region_conditionally (
|
||||
GList *region,
|
||||
const int left_expand,
|
||||
const int right_expand,
|
||||
const int top_expand,
|
||||
const int bottom_expand,
|
||||
const int min_x,
|
||||
const int min_y);
|
||||
|
||||
/* Expand rect in direction to the size of expand_to, and then clip out any
|
||||
* overlapping struts oriented orthognal to the expansion direction. (Think
|
||||
* horizontal or vertical maximization)
|
||||
*/
|
||||
void meta_rectangle_expand_to_avoiding_struts (
|
||||
MetaRectangle *rect,
|
||||
const MetaRectangle *expand_to,
|
||||
const MetaDirection direction,
|
||||
const GSList *all_struts);
|
||||
|
||||
/* Free the list created by
|
||||
* meta_rectangle_get_minimal_spanning_set_for_region()
|
||||
* or
|
||||
* meta_rectangle_find_onscreen_edges ()
|
||||
* or
|
||||
* meta_rectangle_find_nonintersected_monitor_edges()
|
||||
*/
|
||||
void meta_rectangle_free_list_and_elements (GList *filled_list);
|
||||
|
||||
/* could_fit_in_region determines whether one of the spanning_rects is
|
||||
* big enough to contain rect. contained_in_region checks whether one
|
||||
* actually contains it.
|
||||
*/
|
||||
gboolean meta_rectangle_could_fit_in_region (
|
||||
const GList *spanning_rects,
|
||||
const MetaRectangle *rect);
|
||||
gboolean meta_rectangle_contained_in_region (
|
||||
const GList *spanning_rects,
|
||||
const MetaRectangle *rect);
|
||||
gboolean meta_rectangle_overlaps_with_region (
|
||||
const GList *spanning_rects,
|
||||
const MetaRectangle *rect);
|
||||
|
||||
/* Make the rectangle small enough to fit into one of the spanning_rects,
|
||||
* but make it no smaller than min_size.
|
||||
*/
|
||||
void meta_rectangle_clamp_to_fit_into_region (
|
||||
const GList *spanning_rects,
|
||||
FixedDirections fixed_directions,
|
||||
MetaRectangle *rect,
|
||||
const MetaRectangle *min_size);
|
||||
|
||||
/* Clip the rectangle so that it fits into one of the spanning_rects, assuming
|
||||
* it overlaps with at least one of them
|
||||
*/
|
||||
void meta_rectangle_clip_to_region (const GList *spanning_rects,
|
||||
FixedDirections fixed_directions,
|
||||
MetaRectangle *rect);
|
||||
|
||||
/* Shove the rectangle into one of the spanning_rects, assuming it fits in
|
||||
* one of them.
|
||||
*/
|
||||
void meta_rectangle_shove_into_region(
|
||||
const GList *spanning_rects,
|
||||
FixedDirections fixed_directions,
|
||||
MetaRectangle *rect);
|
||||
|
||||
/* Finds the point on the line connecting (x1,y1) to (x2,y2) which is closest
|
||||
* to (px, py). Useful for finding an optimal rectangle size when given a
|
||||
* range between two sizes that are all candidates.
|
||||
*/
|
||||
void meta_rectangle_find_linepoint_closest_to_point (double x1, double y1,
|
||||
double x2, double y2,
|
||||
double px, double py,
|
||||
double *valx, double *valy);
|
||||
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* Switching gears to code for edges instead of just rectangles */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/* Return whether an edge overlaps or is adjacent to the rectangle in the
|
||||
* nonzero-width dimension of the edge.
|
||||
*/
|
||||
gboolean meta_rectangle_edge_aligns (const MetaRectangle *rect,
|
||||
const MetaEdge *edge);
|
||||
|
||||
/* Compare two edges, so that sorting functions can put a list of edges in
|
||||
* canonical order.
|
||||
*/
|
||||
gint meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b);
|
||||
|
||||
/* Compare two edges, so that sorting functions can put a list of edges in
|
||||
* order. This function doesn't separate left edges first, then right edges,
|
||||
* etc., but rather compares only upon location.
|
||||
*/
|
||||
gint meta_rectangle_edge_cmp_ignore_type (gconstpointer a, gconstpointer b);
|
||||
|
||||
/* Removes an parts of edges in the given list that intersect any box in the
|
||||
* given rectangle list. Returns the result.
|
||||
*/
|
||||
GList* meta_rectangle_remove_intersections_with_boxes_from_edges (
|
||||
GList *edges,
|
||||
const GSList *rectangles);
|
||||
|
||||
/* Finds all the edges of an onscreen region, returning a GList* of
|
||||
* MetaEdgeRect's.
|
||||
*/
|
||||
GList* meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
|
||||
const GSList *all_struts);
|
||||
|
||||
/* Finds edges between adjacent monitors which are not covered by the given
|
||||
* struts.
|
||||
*/
|
||||
GList* meta_rectangle_find_nonintersected_monitor_edges (
|
||||
const GList *monitor_rects,
|
||||
const GSList *all_struts);
|
||||
|
||||
#endif /* META_BOXES_PRIVATE_H */
|
||||
@@ -26,10 +26,39 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "boxes.h"
|
||||
#include "boxes-private.h"
|
||||
#include "util.h"
|
||||
#include <X11/Xutil.h> /* Just for the definition of the various gravities */
|
||||
|
||||
/* It would make sense to use GSlice here, but until we clean up the
|
||||
* rest of this file and the internal API to use these functions, we
|
||||
* leave it using g_malloc()/g_free() for consistency.
|
||||
*/
|
||||
|
||||
MetaRectangle *
|
||||
meta_rectangle_copy (const MetaRectangle *rect)
|
||||
{
|
||||
return g_memdup (rect, sizeof (MetaRectangle));
|
||||
}
|
||||
|
||||
void
|
||||
meta_rectangle_free (MetaRectangle *rect)
|
||||
{
|
||||
g_free (rect);
|
||||
}
|
||||
|
||||
GType
|
||||
meta_rectangle_get_type (void)
|
||||
{
|
||||
static GType type_id = 0;
|
||||
|
||||
if (!type_id)
|
||||
type_id = g_boxed_type_register_static (g_intern_static_string ("MetaRectangle"),
|
||||
(GBoxedCopyFunc) meta_rectangle_copy,
|
||||
(GBoxedFreeFunc) meta_rectangle_free);
|
||||
return type_id;
|
||||
}
|
||||
|
||||
char*
|
||||
meta_rectangle_to_string (const MetaRectangle *rect,
|
||||
char *output)
|
||||
@@ -500,7 +529,12 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
|
||||
return b_area - a_area; /* positive ret value denotes b > a, ... */
|
||||
}
|
||||
|
||||
/* This function is trying to find a "minimal spanning set (of rectangles)"
|
||||
/**
|
||||
* meta_rectangle_get_minimal_spanning_set_for_region:
|
||||
* @basic_rect: Input rectangle
|
||||
* @all_struts: (element-type Meta.Rectangle): List of struts
|
||||
*
|
||||
* This function is trying to find a "minimal spanning set (of rectangles)"
|
||||
* for a given region.
|
||||
*
|
||||
* The region is given by taking basic_rect, then removing the areas
|
||||
@@ -513,10 +547,7 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
|
||||
* the region if and only if it is contained within at least one of the
|
||||
* rectangles.
|
||||
*
|
||||
* The GList* returned will be a list of (allocated) MetaRectangles.
|
||||
* The list will need to be freed by calling
|
||||
* meta_rectangle_free_spanning_set() on it (or by manually
|
||||
* implementing that function...)
|
||||
* Returns: (transfer full) (element-type Meta.Rectangle): Minimal spanning set
|
||||
*/
|
||||
GList*
|
||||
meta_rectangle_get_minimal_spanning_set_for_region (
|
||||
@@ -535,7 +566,7 @@ meta_rectangle_get_minimal_spanning_set_for_region (
|
||||
* enough to make this worth bothering. Further, it is only called from
|
||||
* workspace.c:ensure_work_areas_validated (at least as of the time of
|
||||
* writing this comment), which in turn should only be called if the
|
||||
* strut list changes or the screen or xinerama size changes. If it ever
|
||||
* strut list changes or the screen or monitor size changes. If it ever
|
||||
* does show up on profiles (most likely because people start using
|
||||
* ridiculously huge numbers of partial struts), possible optimizations
|
||||
* include:
|
||||
@@ -649,6 +680,10 @@ meta_rectangle_get_minimal_spanning_set_for_region (
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_rectangle_expand_region: (skip)
|
||||
*
|
||||
*/
|
||||
GList*
|
||||
meta_rectangle_expand_region (GList *region,
|
||||
const int left_expand,
|
||||
@@ -665,6 +700,10 @@ meta_rectangle_expand_region (GList *region,
|
||||
0);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_rectangle_expand_region_conditionally: (skip)
|
||||
*
|
||||
*/
|
||||
GList*
|
||||
meta_rectangle_expand_region_conditionally (GList *region,
|
||||
const int left_expand,
|
||||
@@ -1642,7 +1681,10 @@ fix_up_edges (MetaRectangle *rect, MetaEdge *edge,
|
||||
}
|
||||
}
|
||||
|
||||
/* This function removes intersections of edges with the rectangles from the
|
||||
/**
|
||||
* meta_rectangle_remove_intersections_with_boxes_from_edges: (skip)
|
||||
*
|
||||
* This function removes intersections of edges with the rectangles from the
|
||||
* list of edges.
|
||||
*/
|
||||
GList*
|
||||
@@ -1708,7 +1750,11 @@ meta_rectangle_remove_intersections_with_boxes_from_edges (
|
||||
return edges;
|
||||
}
|
||||
|
||||
/* This function is trying to find all the edges of an onscreen region. */
|
||||
/**
|
||||
* meta_rectangle_find_onscreen_edges: (skip)
|
||||
*
|
||||
* This function is trying to find all the edges of an onscreen region.
|
||||
*/
|
||||
GList*
|
||||
meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
|
||||
const GSList *all_struts)
|
||||
@@ -1791,15 +1837,19 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_rectangle_find_nonintersected_monitor_edges: (skip)
|
||||
*
|
||||
*/
|
||||
GList*
|
||||
meta_rectangle_find_nonintersected_xinerama_edges (
|
||||
const GList *xinerama_rects,
|
||||
meta_rectangle_find_nonintersected_monitor_edges (
|
||||
const GList *monitor_rects,
|
||||
const GSList *all_struts)
|
||||
{
|
||||
/* This function cannot easily be merged with
|
||||
* meta_rectangle_find_onscreen_edges() because real screen edges
|
||||
* and strut edges both are of the type "there ain't anything
|
||||
* immediately on the other side"; xinerama edges are different.
|
||||
* immediately on the other side"; monitor edges are different.
|
||||
*/
|
||||
GList *ret;
|
||||
const GList *cur;
|
||||
@@ -1808,14 +1858,14 @@ meta_rectangle_find_nonintersected_xinerama_edges (
|
||||
/* Initialize the return list to be empty */
|
||||
ret = NULL;
|
||||
|
||||
/* start of ret with all the edges of xineramas that are adjacent to
|
||||
* another xinerama.
|
||||
/* start of ret with all the edges of monitors that are adjacent to
|
||||
* another monitor.
|
||||
*/
|
||||
cur = xinerama_rects;
|
||||
cur = monitor_rects;
|
||||
while (cur)
|
||||
{
|
||||
MetaRectangle *cur_rect = cur->data;
|
||||
const GList *compare = xinerama_rects;
|
||||
const GList *compare = monitor_rects;
|
||||
while (compare)
|
||||
{
|
||||
MetaRectangle *compare_rect = compare->data;
|
||||
@@ -1849,15 +1899,15 @@ meta_rectangle_find_nonintersected_xinerama_edges (
|
||||
/* If the rectangles really are adjacent */
|
||||
if (x != INT_MIN)
|
||||
{
|
||||
/* We need a left edge for the xinerama on the right, and
|
||||
* a right edge for the xinerama on the left. Just fill
|
||||
/* We need a left edge for the monitor on the right, and
|
||||
* a right edge for the monitor on the left. Just fill
|
||||
* up the edges and stick 'em on the list.
|
||||
*/
|
||||
MetaEdge *new_edge = g_new (MetaEdge, 1);
|
||||
|
||||
new_edge->rect = meta_rect (x, y, width, height);
|
||||
new_edge->side_type = side_type;
|
||||
new_edge->edge_type = META_EDGE_XINERAMA;
|
||||
new_edge->edge_type = META_EDGE_MONITOR;
|
||||
|
||||
ret = g_list_prepend (ret, new_edge);
|
||||
}
|
||||
@@ -1892,15 +1942,15 @@ meta_rectangle_find_nonintersected_xinerama_edges (
|
||||
/* If the rectangles really are adjacent */
|
||||
if (y != INT_MIN)
|
||||
{
|
||||
/* We need a top edge for the xinerama on the bottom, and
|
||||
* a bottom edge for the xinerama on the top. Just fill
|
||||
/* We need a top edge for the monitor on the bottom, and
|
||||
* a bottom edge for the monitor on the top. Just fill
|
||||
* up the edges and stick 'em on the list.
|
||||
*/
|
||||
MetaEdge *new_edge = g_new (MetaEdge, 1);
|
||||
|
||||
new_edge->rect = meta_rect (x, y, width, height);
|
||||
new_edge->side_type = side_type;
|
||||
new_edge->edge_type = META_EDGE_XINERAMA;
|
||||
new_edge->edge_type = META_EDGE_MONITOR;
|
||||
|
||||
ret = g_list_prepend (ret, new_edge);
|
||||
}
|
||||
|
||||
@@ -24,9 +24,11 @@
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "boxes-private.h"
|
||||
#include "constraints.h"
|
||||
#include "workspace-private.h"
|
||||
#include "place.h"
|
||||
#include "prefs.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
@@ -93,10 +95,11 @@ typedef enum
|
||||
{
|
||||
PRIORITY_MINIMUM = 0, /* Dummy value used for loop start = min(all priorities) */
|
||||
PRIORITY_ASPECT_RATIO = 0,
|
||||
PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_XINERAMA = 0,
|
||||
PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR = 0,
|
||||
PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA = 1,
|
||||
PRIORITY_SIZE_HINTS_INCREMENTS = 1,
|
||||
PRIORITY_MAXIMIZATION = 2,
|
||||
PRIORITY_TILING = 2,
|
||||
PRIORITY_FULLSCREEN = 2,
|
||||
PRIORITY_SIZE_HINTS_LIMITS = 3,
|
||||
PRIORITY_TITLEBAR_VISIBLE = 4,
|
||||
@@ -127,23 +130,30 @@ typedef struct
|
||||
int resize_gravity;
|
||||
FixedDirections fixed_directions;
|
||||
|
||||
/* work_area_xinerama - current xinerama region minus struts
|
||||
* entire_xinerama - current xienrama, including strut regions
|
||||
/* work_area_monitor - current monitor region minus struts
|
||||
* entire_monitor - current monitor, including strut regions
|
||||
*/
|
||||
MetaRectangle work_area_xinerama;
|
||||
MetaRectangle entire_xinerama;
|
||||
MetaRectangle work_area_monitor;
|
||||
MetaRectangle entire_monitor;
|
||||
|
||||
/* Spanning rectangles for the non-covered (by struts) region of the
|
||||
* screen and also for just the current xinerama
|
||||
* screen and also for just the current monitor
|
||||
*/
|
||||
GList *usable_screen_region;
|
||||
GList *usable_xinerama_region;
|
||||
GList *usable_monitor_region;
|
||||
} ConstraintInfo;
|
||||
|
||||
static gboolean constrain_modal_dialog (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only);
|
||||
static gboolean constrain_maximization (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only);
|
||||
static gboolean constrain_tiling (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only);
|
||||
static gboolean constrain_fullscreen (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
@@ -160,7 +170,7 @@ static gboolean constrain_aspect_ratio (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only);
|
||||
static gboolean constrain_to_single_xinerama (MetaWindow *window,
|
||||
static gboolean constrain_to_single_monitor (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only);
|
||||
@@ -209,12 +219,14 @@ typedef struct {
|
||||
} Constraint;
|
||||
|
||||
static const Constraint all_constraints[] = {
|
||||
{constrain_modal_dialog, "constrain_modal_dialog"},
|
||||
{constrain_maximization, "constrain_maximization"},
|
||||
{constrain_tiling, "constrain_tiling"},
|
||||
{constrain_fullscreen, "constrain_fullscreen"},
|
||||
{constrain_size_increments, "constrain_size_increments"},
|
||||
{constrain_size_limits, "constrain_size_limits"},
|
||||
{constrain_aspect_ratio, "constrain_aspect_ratio"},
|
||||
{constrain_to_single_xinerama, "constrain_to_single_xinerama"},
|
||||
{constrain_to_single_monitor, "constrain_to_single_monitor"},
|
||||
{constrain_fully_onscreen, "constrain_fully_onscreen"},
|
||||
{constrain_titlebar_visible, "constrain_titlebar_visible"},
|
||||
{constrain_partially_onscreen, "constrain_partially_onscreen"},
|
||||
@@ -311,7 +323,7 @@ meta_window_constrain (MetaWindow *window,
|
||||
*new = info.current;
|
||||
|
||||
/* We may need to update window->require_fully_onscreen,
|
||||
* window->require_on_single_xinerama, and perhaps other quantities
|
||||
* window->require_on_single_monitor, and perhaps other quantities
|
||||
* if this was a user move or user move-and-resize operation.
|
||||
*/
|
||||
update_onscreen_requirements (window, &info);
|
||||
@@ -333,7 +345,7 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
const MetaRectangle *orig,
|
||||
MetaRectangle *new)
|
||||
{
|
||||
const MetaXineramaScreenInfo *xinerama_info;
|
||||
const MetaMonitorInfo *monitor_info;
|
||||
MetaWorkspace *cur_workspace;
|
||||
|
||||
info->orig = *orig;
|
||||
@@ -387,15 +399,15 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
if (!info->is_user_action)
|
||||
info->fixed_directions = FIXED_DIRECTION_NONE;
|
||||
|
||||
xinerama_info =
|
||||
meta_screen_get_xinerama_for_rect (window->screen, &info->current);
|
||||
meta_window_get_work_area_for_xinerama (window,
|
||||
xinerama_info->number,
|
||||
&info->work_area_xinerama);
|
||||
monitor_info =
|
||||
meta_screen_get_monitor_for_rect (window->screen, &info->current);
|
||||
meta_window_get_work_area_for_monitor (window,
|
||||
monitor_info->number,
|
||||
&info->work_area_monitor);
|
||||
|
||||
if (!window->fullscreen || window->fullscreen_monitors[0] == -1)
|
||||
{
|
||||
info->entire_xinerama = xinerama_info->rect;
|
||||
info->entire_monitor = monitor_info->rect;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -403,28 +415,29 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
long monitor;
|
||||
|
||||
monitor = window->fullscreen_monitors[i];
|
||||
info->entire_xinerama =
|
||||
window->screen->xinerama_infos[monitor].rect;
|
||||
info->entire_monitor =
|
||||
window->screen->monitor_infos[monitor].rect;
|
||||
for (i = 1; i <= 3; i++)
|
||||
{
|
||||
monitor = window->fullscreen_monitors[i];
|
||||
meta_rectangle_union (&info->entire_xinerama,
|
||||
&window->screen->xinerama_infos[monitor].rect,
|
||||
&info->entire_xinerama);
|
||||
meta_rectangle_union (&info->entire_monitor,
|
||||
&window->screen->monitor_infos[monitor].rect,
|
||||
&info->entire_monitor);
|
||||
}
|
||||
}
|
||||
|
||||
cur_workspace = window->screen->active_workspace;
|
||||
info->usable_screen_region =
|
||||
meta_workspace_get_onscreen_region (cur_workspace);
|
||||
info->usable_xinerama_region =
|
||||
meta_workspace_get_onxinerama_region (cur_workspace,
|
||||
xinerama_info->number);
|
||||
info->usable_monitor_region =
|
||||
meta_workspace_get_onmonitor_region (cur_workspace,
|
||||
monitor_info->number);
|
||||
|
||||
/* Workaround braindead legacy apps that don't know how to
|
||||
* fullscreen themselves properly.
|
||||
*/
|
||||
if (meta_rectangle_equal (new, &xinerama_info->rect) &&
|
||||
if (meta_prefs_get_force_fullscreen() &&
|
||||
meta_rectangle_equal (new, &monitor_info->rect) &&
|
||||
window->has_fullscreen_func &&
|
||||
!window->fullscreen)
|
||||
{
|
||||
@@ -448,8 +461,8 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
" is_user_action : %s\n"
|
||||
" resize_gravity : %s\n"
|
||||
" fixed_directions: %s\n"
|
||||
" work_area_xinerama: %d,%d +%d,%d\n"
|
||||
" entire_xinerama : %d,%d +%d,%d\n",
|
||||
" work_area_monitor: %d,%d +%d,%d\n"
|
||||
" entire_monitor : %d,%d +%d,%d\n",
|
||||
info->orig.x, info->orig.y, info->orig.width, info->orig.height,
|
||||
info->current.x, info->current.y,
|
||||
info->current.width, info->current.height,
|
||||
@@ -465,11 +478,11 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
(info->fixed_directions == FIXED_DIRECTION_X) ? "X fixed" :
|
||||
(info->fixed_directions == FIXED_DIRECTION_Y) ? "Y fixed" :
|
||||
"Freakin' Invalid Stupid",
|
||||
info->work_area_xinerama.x, info->work_area_xinerama.y,
|
||||
info->work_area_xinerama.width,
|
||||
info->work_area_xinerama.height,
|
||||
info->entire_xinerama.x, info->entire_xinerama.y,
|
||||
info->entire_xinerama.width, info->entire_xinerama.height);
|
||||
info->work_area_monitor.x, info->work_area_monitor.y,
|
||||
info->work_area_monitor.width,
|
||||
info->work_area_monitor.height,
|
||||
info->entire_monitor.x, info->entire_monitor.y,
|
||||
info->entire_monitor.width, info->entire_monitor.height);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -493,25 +506,25 @@ place_window_if_needed(MetaWindow *window,
|
||||
{
|
||||
MetaRectangle placed_rect = info->orig;
|
||||
MetaWorkspace *cur_workspace;
|
||||
const MetaXineramaScreenInfo *xinerama_info;
|
||||
const MetaMonitorInfo *monitor_info;
|
||||
|
||||
meta_window_place (window, info->fgeom, info->orig.x, info->orig.y,
|
||||
&placed_rect.x, &placed_rect.y);
|
||||
did_placement = TRUE;
|
||||
|
||||
/* placing the window may have changed the xinerama. Find the
|
||||
* new xinerama and update the ConstraintInfo
|
||||
/* placing the window may have changed the monitor. Find the
|
||||
* new monitor and update the ConstraintInfo
|
||||
*/
|
||||
xinerama_info =
|
||||
meta_screen_get_xinerama_for_rect (window->screen, &placed_rect);
|
||||
info->entire_xinerama = xinerama_info->rect;
|
||||
meta_window_get_work_area_for_xinerama (window,
|
||||
xinerama_info->number,
|
||||
&info->work_area_xinerama);
|
||||
monitor_info =
|
||||
meta_screen_get_monitor_for_rect (window->screen, &placed_rect);
|
||||
info->entire_monitor = monitor_info->rect;
|
||||
meta_window_get_work_area_for_monitor (window,
|
||||
monitor_info->number,
|
||||
&info->work_area_monitor);
|
||||
cur_workspace = window->screen->active_workspace;
|
||||
info->usable_xinerama_region =
|
||||
meta_workspace_get_onxinerama_region (cur_workspace,
|
||||
xinerama_info->number);
|
||||
info->usable_monitor_region =
|
||||
meta_workspace_get_onmonitor_region (cur_workspace,
|
||||
monitor_info->number);
|
||||
|
||||
|
||||
info->current.x = placed_rect.x;
|
||||
@@ -526,22 +539,23 @@ place_window_if_needed(MetaWindow *window,
|
||||
if (window->placed || did_placement)
|
||||
{
|
||||
if (window->maximize_horizontally_after_placement ||
|
||||
window->maximize_vertically_after_placement)
|
||||
window->maximize_vertically_after_placement ||
|
||||
window->fullscreen_after_placement)
|
||||
{
|
||||
/* define a sane saved_rect so that the user can unmaximize to
|
||||
* something reasonable.
|
||||
/* define a sane saved_rect so that the user can unmaximize or
|
||||
* make unfullscreen to something reasonable.
|
||||
*/
|
||||
if (info->current.width >= info->work_area_xinerama.width)
|
||||
if (info->current.width >= info->work_area_monitor.width)
|
||||
{
|
||||
info->current.width = .75 * info->work_area_xinerama.width;
|
||||
info->current.x = info->work_area_xinerama.x +
|
||||
.125 * info->work_area_xinerama.width;
|
||||
info->current.width = .75 * info->work_area_monitor.width;
|
||||
info->current.x = info->work_area_monitor.x +
|
||||
.125 * info->work_area_monitor.width;
|
||||
}
|
||||
if (info->current.height >= info->work_area_xinerama.height)
|
||||
if (info->current.height >= info->work_area_monitor.height)
|
||||
{
|
||||
info->current.height = .75 * info->work_area_xinerama.height;
|
||||
info->current.y = info->work_area_xinerama.y +
|
||||
.083 * info->work_area_xinerama.height;
|
||||
info->current.height = .75 * info->work_area_monitor.height;
|
||||
info->current.y = info->work_area_monitor.y +
|
||||
.083 * info->work_area_monitor.height;
|
||||
}
|
||||
|
||||
if (window->maximize_horizontally_after_placement ||
|
||||
@@ -556,6 +570,15 @@ place_window_if_needed(MetaWindow *window,
|
||||
if (window->frame && !window->fullscreen)
|
||||
meta_frame_calc_geometry (window->frame, info->fgeom);
|
||||
|
||||
if (window->fullscreen_after_placement)
|
||||
{
|
||||
window->saved_rect = info->current;
|
||||
window->fullscreen = TRUE;
|
||||
window->fullscreen_after_placement = FALSE;
|
||||
|
||||
g_object_notify (G_OBJECT (window), "fullscreen");
|
||||
}
|
||||
|
||||
window->maximize_horizontally_after_placement = FALSE;
|
||||
window->maximize_vertically_after_placement = FALSE;
|
||||
}
|
||||
@@ -589,7 +612,7 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
return;
|
||||
|
||||
/* USABILITY NOTE: Naturally, I only want the require_fully_onscreen,
|
||||
* require_on_single_xinerama, and require_titlebar_visible flags to
|
||||
* require_on_single_monitor, and require_titlebar_visible flags to
|
||||
* *become false* due to user interactions (which is allowed since
|
||||
* certain constraints are ignored for user interactions regardless of
|
||||
* the setting of these flags). However, whether to make these flags
|
||||
@@ -603,7 +626,7 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
* problematic case but this may need to be revisited.
|
||||
*/
|
||||
|
||||
/* The require onscreen/on-single-xinerama and titlebar_visible
|
||||
/* The require onscreen/on-single-monitor and titlebar_visible
|
||||
* stuff is relative to the outer window, not the inner
|
||||
*/
|
||||
extend_by_frame (&info->current, info->fgeom);
|
||||
@@ -622,17 +645,17 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
window->require_fully_onscreen ? "TRUE" : "FALSE");
|
||||
|
||||
/* Update whether we want future constraint runs to require the
|
||||
* window to be on a single xinerama.
|
||||
* window to be on a single monitor.
|
||||
*/
|
||||
old = window->require_on_single_xinerama;
|
||||
window->require_on_single_xinerama =
|
||||
meta_rectangle_contained_in_region (info->usable_xinerama_region,
|
||||
old = window->require_on_single_monitor;
|
||||
window->require_on_single_monitor =
|
||||
meta_rectangle_contained_in_region (info->usable_monitor_region,
|
||||
&info->current);
|
||||
if (old ^ window->require_on_single_xinerama)
|
||||
if (old ^ window->require_on_single_monitor)
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"require_on_single_xinerama for %s toggled to %s\n",
|
||||
"require_on_single_monitor for %s toggled to %s\n",
|
||||
window->desc,
|
||||
window->require_on_single_xinerama ? "TRUE" : "FALSE");
|
||||
window->require_on_single_monitor ? "TRUE" : "FALSE");
|
||||
|
||||
/* Update whether we want future constraint runs to require the
|
||||
* titlebar to be visible.
|
||||
@@ -714,6 +737,48 @@ get_size_limits (const MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
constrain_modal_dialog (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only)
|
||||
{
|
||||
int x, y;
|
||||
MetaWindow *parent = meta_window_get_transient_for (window);
|
||||
gboolean constraint_already_satisfied;
|
||||
|
||||
if (!meta_prefs_get_attach_modal_dialogs ())
|
||||
return TRUE;
|
||||
if (window->type != META_WINDOW_MODAL_DIALOG || !parent || parent == window)
|
||||
return TRUE;
|
||||
|
||||
x = parent->rect.x + (parent->rect.width / 2 - info->current.width / 2);
|
||||
y = 0;
|
||||
if (parent->frame)
|
||||
{
|
||||
MetaFrameGeometry fgeom;
|
||||
|
||||
x += parent->frame->rect.x;
|
||||
y += parent->frame->rect.y;
|
||||
|
||||
meta_frame_calc_geometry (parent->frame, &fgeom);
|
||||
y += fgeom.top_height;
|
||||
|
||||
y += info->fgeom->top_height;
|
||||
}
|
||||
else
|
||||
y = parent->rect.y + info->fgeom->top_height;
|
||||
|
||||
constraint_already_satisfied = (x == info->current.x) && (y == info->current.y);
|
||||
|
||||
if (check_only || constraint_already_satisfied)
|
||||
return constraint_already_satisfied;
|
||||
|
||||
info->current.y = y;
|
||||
info->current.x = x;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
constrain_maximization (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
@@ -730,12 +795,13 @@ constrain_maximization (MetaWindow *window,
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint applies; exit if it doesn't */
|
||||
if (!window->maximized_horizontally && !window->maximized_vertically)
|
||||
if ((!window->maximized_horizontally && !window->maximized_vertically) ||
|
||||
META_WINDOW_TILED (window))
|
||||
return TRUE;
|
||||
|
||||
/* Calculate target_size = maximized size of (window + frame) */
|
||||
if (window->maximized_horizontally && window->maximized_vertically)
|
||||
target_size = info->work_area_xinerama;
|
||||
target_size = info->work_area_monitor;
|
||||
else
|
||||
{
|
||||
/* Amount of maximization possible in a single direction depends
|
||||
@@ -757,7 +823,7 @@ constrain_maximization (MetaWindow *window,
|
||||
target_size = info->current;
|
||||
extend_by_frame (&target_size, info->fgeom);
|
||||
meta_rectangle_expand_to_avoiding_struts (&target_size,
|
||||
&info->entire_xinerama,
|
||||
&info->entire_monitor,
|
||||
direction,
|
||||
active_workspace_struts);
|
||||
}
|
||||
@@ -798,13 +864,66 @@ constrain_maximization (MetaWindow *window,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
constrain_tiling (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only)
|
||||
{
|
||||
MetaRectangle target_size;
|
||||
MetaRectangle min_size, max_size;
|
||||
gboolean hminbad, vminbad;
|
||||
gboolean horiz_equal, vert_equal;
|
||||
gboolean constraint_already_satisfied;
|
||||
|
||||
if (priority > PRIORITY_TILING)
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint applies; exit if it doesn't */
|
||||
if (!META_WINDOW_TILED (window))
|
||||
return TRUE;
|
||||
|
||||
/* Calculate target_size - as the tile previews need this as well, we
|
||||
* use an external function for the actual calculation
|
||||
*/
|
||||
meta_window_get_current_tile_area (window, &target_size);
|
||||
unextend_by_frame (&target_size, info->fgeom);
|
||||
|
||||
/* Check min size constraints; max size constraints are ignored as for
|
||||
* maximized windows.
|
||||
*/
|
||||
get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
|
||||
hminbad = target_size.width < min_size.width;
|
||||
vminbad = target_size.height < min_size.height;
|
||||
if (hminbad || vminbad)
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint is already satisfied; exit if it is */
|
||||
horiz_equal = target_size.x == info->current.x &&
|
||||
target_size.width == info->current.width;
|
||||
vert_equal = target_size.y == info->current.y &&
|
||||
target_size.height == info->current.height;
|
||||
constraint_already_satisfied = horiz_equal && vert_equal;
|
||||
if (check_only || constraint_already_satisfied)
|
||||
return constraint_already_satisfied;
|
||||
|
||||
/*** Enforce constraint ***/
|
||||
info->current.x = target_size.x;
|
||||
info->current.width = target_size.width;
|
||||
info->current.y = target_size.y;
|
||||
info->current.height = target_size.height;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
constrain_fullscreen (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only)
|
||||
{
|
||||
MetaRectangle min_size, max_size, xinerama;
|
||||
MetaRectangle min_size, max_size, monitor;
|
||||
gboolean too_big, too_small, constraint_already_satisfied;
|
||||
|
||||
if (priority > PRIORITY_FULLSCREEN)
|
||||
@@ -814,22 +933,22 @@ constrain_fullscreen (MetaWindow *window,
|
||||
if (!window->fullscreen)
|
||||
return TRUE;
|
||||
|
||||
xinerama = info->entire_xinerama;
|
||||
monitor = info->entire_monitor;
|
||||
|
||||
get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
|
||||
too_big = !meta_rectangle_could_fit_rect (&xinerama, &min_size);
|
||||
too_small = !meta_rectangle_could_fit_rect (&max_size, &xinerama);
|
||||
too_big = !meta_rectangle_could_fit_rect (&monitor, &min_size);
|
||||
too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor);
|
||||
if (too_big || too_small)
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint is already satisfied; exit if it is */
|
||||
constraint_already_satisfied =
|
||||
meta_rectangle_equal (&info->current, &xinerama);
|
||||
meta_rectangle_equal (&info->current, &monitor);
|
||||
if (check_only || constraint_already_satisfied)
|
||||
return constraint_already_satisfied;
|
||||
|
||||
/*** Enforce constraint ***/
|
||||
info->current = xinerama;
|
||||
info->current = monitor;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -849,7 +968,7 @@ constrain_size_increments (MetaWindow *window,
|
||||
|
||||
/* Determine whether constraint applies; exit if it doesn't */
|
||||
if (META_WINDOW_MAXIMIZED (window) || window->fullscreen ||
|
||||
info->action_type == ACTION_MOVE)
|
||||
META_WINDOW_TILED (window) || info->action_type == ACTION_MOVE)
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint is already satisfied; exit if it is */
|
||||
@@ -980,7 +1099,7 @@ constrain_aspect_ratio (MetaWindow *window,
|
||||
constraints_are_inconsistent = minr > maxr;
|
||||
if (constraints_are_inconsistent ||
|
||||
META_WINDOW_MAXIMIZED (window) || window->fullscreen ||
|
||||
info->action_type == ACTION_MOVE)
|
||||
META_WINDOW_TILED (window) || info->action_type == ACTION_MOVE)
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint is already satisfied; exit if it is. We
|
||||
@@ -1091,7 +1210,7 @@ constrain_aspect_ratio (MetaWindow *window,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_screen_and_xinerama_relative_constraints (
|
||||
do_screen_and_monitor_relative_constraints (
|
||||
MetaWindow *window,
|
||||
GList *region_spanning_rectangles,
|
||||
ConstraintInfo *info,
|
||||
@@ -1107,7 +1226,7 @@ do_screen_and_xinerama_relative_constraints (
|
||||
char spanning_region[1 + 28 * g_list_length (region_spanning_rectangles)];
|
||||
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"screen/xinerama constraint; region_spanning_rectangles: %s\n",
|
||||
"screen/monitor constraint; region_spanning_rectangles: %s\n",
|
||||
meta_rectangle_region_to_string (region_spanning_rectangles, ", ",
|
||||
spanning_region));
|
||||
}
|
||||
@@ -1165,32 +1284,32 @@ do_screen_and_xinerama_relative_constraints (
|
||||
}
|
||||
|
||||
static gboolean
|
||||
constrain_to_single_xinerama (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only)
|
||||
constrain_to_single_monitor (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only)
|
||||
{
|
||||
if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_XINERAMA)
|
||||
if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR)
|
||||
return TRUE;
|
||||
|
||||
/* Exit early if we know the constraint won't apply--note that this constraint
|
||||
* is only meant for normal windows (e.g. we don't want docks to be shoved
|
||||
* "onscreen" by their own strut) and we can't apply it to frameless windows
|
||||
* or else users will be unable to move windows such as XMMS across xineramas.
|
||||
* or else users will be unable to move windows such as XMMS across monitors.
|
||||
*/
|
||||
if (window->type == META_WINDOW_DESKTOP ||
|
||||
window->type == META_WINDOW_DOCK ||
|
||||
window->screen->n_xinerama_infos == 1 ||
|
||||
!window->require_on_single_xinerama ||
|
||||
window->screen->n_monitor_infos == 1 ||
|
||||
!window->require_on_single_monitor ||
|
||||
!window->frame ||
|
||||
info->is_user_action)
|
||||
return TRUE;
|
||||
|
||||
/* Have a helper function handle the constraint for us */
|
||||
return do_screen_and_xinerama_relative_constraints (window,
|
||||
info->usable_xinerama_region,
|
||||
info,
|
||||
check_only);
|
||||
return do_screen_and_monitor_relative_constraints (window,
|
||||
info->usable_monitor_region,
|
||||
info,
|
||||
check_only);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1214,10 +1333,10 @@ constrain_fully_onscreen (MetaWindow *window,
|
||||
return TRUE;
|
||||
|
||||
/* Have a helper function handle the constraint for us */
|
||||
return do_screen_and_xinerama_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
return do_screen_and_monitor_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1290,10 +1409,10 @@ constrain_titlebar_visible (MetaWindow *window,
|
||||
horiz_amount_onscreen,
|
||||
vert_amount_onscreen);
|
||||
retval =
|
||||
do_screen_and_xinerama_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
do_screen_and_monitor_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
meta_rectangle_expand_region_conditionally (info->usable_screen_region,
|
||||
-horiz_amount_offscreen,
|
||||
-horiz_amount_offscreen,
|
||||
@@ -1365,10 +1484,10 @@ constrain_partially_onscreen (MetaWindow *window,
|
||||
horiz_amount_onscreen,
|
||||
vert_amount_onscreen);
|
||||
retval =
|
||||
do_screen_and_xinerama_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
do_screen_and_monitor_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
meta_rectangle_expand_region_conditionally (info->usable_screen_region,
|
||||
-horiz_amount_offscreen,
|
||||
-horiz_amount_offscreen,
|
||||
|
||||
134
src/core/core.c
134
src/core/core.c
@@ -28,6 +28,7 @@
|
||||
#include "frame-private.h"
|
||||
#include "workspace-private.h"
|
||||
#include "prefs.h"
|
||||
#include "errors.h"
|
||||
|
||||
/* Looks up the MetaWindow representing the frame of the given X window.
|
||||
* Used as a helper function by a bunch of the functions below.
|
||||
@@ -116,65 +117,8 @@ meta_core_get (Display *xdisplay,
|
||||
*((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
|
||||
break;
|
||||
case META_CORE_GET_FRAME_TYPE:
|
||||
{
|
||||
MetaFrameType base_type = META_FRAME_TYPE_LAST;
|
||||
|
||||
switch (window->type)
|
||||
{
|
||||
case META_WINDOW_NORMAL:
|
||||
base_type = META_FRAME_TYPE_NORMAL;
|
||||
break;
|
||||
|
||||
case META_WINDOW_DIALOG:
|
||||
base_type = META_FRAME_TYPE_DIALOG;
|
||||
break;
|
||||
|
||||
case META_WINDOW_MODAL_DIALOG:
|
||||
base_type = META_FRAME_TYPE_MODAL_DIALOG;
|
||||
break;
|
||||
|
||||
case META_WINDOW_MENU:
|
||||
base_type = META_FRAME_TYPE_MENU;
|
||||
break;
|
||||
|
||||
case META_WINDOW_UTILITY:
|
||||
base_type = META_FRAME_TYPE_UTILITY;
|
||||
break;
|
||||
|
||||
case META_WINDOW_DESKTOP:
|
||||
case META_WINDOW_DOCK:
|
||||
case META_WINDOW_TOOLBAR:
|
||||
case META_WINDOW_SPLASHSCREEN:
|
||||
case META_WINDOW_DROPDOWN_MENU:
|
||||
case META_WINDOW_POPUP_MENU:
|
||||
case META_WINDOW_TOOLTIP:
|
||||
case META_WINDOW_NOTIFICATION:
|
||||
case META_WINDOW_COMBO:
|
||||
case META_WINDOW_DND:
|
||||
case META_WINDOW_OVERRIDE_OTHER:
|
||||
/* No frame */
|
||||
base_type = META_FRAME_TYPE_LAST;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (base_type == META_FRAME_TYPE_LAST)
|
||||
{
|
||||
/* can't add border if undecorated */
|
||||
*((MetaFrameType*)answer) = META_FRAME_TYPE_LAST;
|
||||
}
|
||||
else if (window->border_only)
|
||||
{
|
||||
/* override base frame type */
|
||||
*((MetaFrameType*)answer) = META_FRAME_TYPE_BORDER;
|
||||
}
|
||||
else
|
||||
{
|
||||
*((MetaFrameType*)answer) = base_type;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
*((MetaFrameType*)answer) = meta_window_get_frame_type (window);
|
||||
break;
|
||||
case META_CORE_GET_MINI_ICON:
|
||||
*((GdkPixbuf**)answer) = window->mini_icon;
|
||||
break;
|
||||
@@ -260,15 +204,14 @@ meta_core_user_raise (Display *xdisplay,
|
||||
meta_window_raise (window);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_user_lower_and_unfocus (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
guint32 timestamp)
|
||||
static gboolean
|
||||
lower_window_and_transients (MetaWindow *window,
|
||||
gpointer data)
|
||||
{
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
|
||||
meta_window_lower (window);
|
||||
|
||||
meta_window_foreach_transient (window, lower_window_and_transients, NULL);
|
||||
|
||||
if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK &&
|
||||
meta_prefs_get_raise_on_click ())
|
||||
{
|
||||
@@ -296,11 +239,59 @@ meta_core_user_lower_and_unfocus (Display *xdisplay,
|
||||
}
|
||||
}
|
||||
|
||||
/* focus the default window, if needed */
|
||||
if (window->has_focus)
|
||||
meta_workspace_focus_default_window (window->screen->active_workspace,
|
||||
NULL,
|
||||
timestamp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_user_lower_and_unfocus (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
|
||||
lower_window_and_transients (window, NULL);
|
||||
|
||||
/* Rather than try to figure that out whether we just lowered
|
||||
* the focus window, assume that's always the case. (Typically,
|
||||
* this will be invoked via keyboard action or by a mouse action;
|
||||
* in either case the window or a modal child will have been focused.) */
|
||||
meta_workspace_focus_default_window (window->screen->active_workspace,
|
||||
NULL,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_lower_beneath_focus_window (Display *xdisplay,
|
||||
Window xwindow,
|
||||
guint32 timestamp)
|
||||
{
|
||||
XWindowChanges changes;
|
||||
MetaDisplay *display;
|
||||
MetaScreen *screen;
|
||||
MetaWindow *focus_window;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
screen = meta_display_screen_for_xwindow (display, xwindow);
|
||||
focus_window = meta_stack_get_top (screen->stack);
|
||||
|
||||
if (focus_window == NULL)
|
||||
return;
|
||||
|
||||
changes.stack_mode = Below;
|
||||
changes.sibling = focus_window->frame ? focus_window->frame->xwindow
|
||||
: focus_window->xwindow;
|
||||
|
||||
meta_stack_tracker_record_lower_below (screen->stack_tracker,
|
||||
xwindow,
|
||||
changes.sibling,
|
||||
XNextRequest (screen->display->xdisplay));
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XConfigureWindow (xdisplay,
|
||||
xwindow,
|
||||
CWSibling | CWStackMode,
|
||||
&changes);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -526,6 +517,9 @@ meta_core_get_menu_accelerator (MetaMenuOp menu_op,
|
||||
|
||||
switch (menu_op)
|
||||
{
|
||||
case META_MENU_OP_NONE:
|
||||
/* No keybinding for this one */
|
||||
break;
|
||||
case META_MENU_OP_DELETE:
|
||||
name = "close";
|
||||
break;
|
||||
|
||||
@@ -22,8 +22,7 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _SVID_SOURCE /* for gethostname() */
|
||||
#define _XOPEN_SOURCE /* for kill() */
|
||||
|
||||
#include <config.h>
|
||||
#include "util.h"
|
||||
@@ -32,6 +31,7 @@
|
||||
#include "workspace.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
@@ -55,27 +55,16 @@ delete_ping_reply_func (MetaDisplay *display,
|
||||
/* we do nothing */
|
||||
}
|
||||
|
||||
static gboolean
|
||||
delete_window_callback (gpointer w_p)
|
||||
{
|
||||
meta_window_kill ((MetaWindow*) w_p);
|
||||
|
||||
return FALSE; /* don't do it again */
|
||||
}
|
||||
|
||||
static void
|
||||
sigchld_handler (MetaNexus *nexus, guint arg1, gpointer arg2, gpointer user_data)
|
||||
dialog_exited (GPid pid, int status, gpointer user_data)
|
||||
{
|
||||
MetaWindow *ours = (MetaWindow*) user_data;
|
||||
|
||||
if (GPOINTER_TO_INT (arg2) == ours->dialog_pid)
|
||||
{
|
||||
if (arg1 == 1 /* pressed "force quit" */)
|
||||
g_idle_add_full (G_PRIORITY_DEFAULT,
|
||||
delete_window_callback, user_data, NULL);
|
||||
ours->dialog_pid = -1;
|
||||
|
||||
ours->dialog_pid = -1; /* forget it anyway */
|
||||
}
|
||||
/* exit status of 1 means the user pressed "Force Quit" */
|
||||
if (WIFEXITED (status) && WEXITSTATUS (status) == 1)
|
||||
meta_window_kill (ours);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -86,7 +75,7 @@ delete_ping_timeout_func (MetaDisplay *display,
|
||||
{
|
||||
MetaWindow *window = user_data;
|
||||
char *window_title;
|
||||
gchar *window_content;
|
||||
gchar *window_content, *tmp;
|
||||
GPid dialog_pid;
|
||||
|
||||
meta_topic (META_DEBUG_PING,
|
||||
@@ -101,11 +90,14 @@ delete_ping_timeout_func (MetaDisplay *display,
|
||||
|
||||
window_title = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL);
|
||||
|
||||
window_content = g_strdup_printf(
|
||||
_("<big><b><tt>%s</tt> is not responding.</b></big>\n\n"
|
||||
"<i>You may choose to wait a short while for it to "
|
||||
"continue or force the application to quit entirely.</i>"),
|
||||
window_title);
|
||||
/* Translators: %s is a window title */
|
||||
tmp = g_strdup_printf (_("<tt>%s</tt> is not responding."),
|
||||
window_title);
|
||||
window_content = g_strdup_printf (
|
||||
"<big><b>%s</b></big>\n\n<i>%s</i>",
|
||||
tmp,
|
||||
_("You may choose to wait a short while for it to "
|
||||
"continue or force the application to quit entirely."));
|
||||
|
||||
g_free (window_title);
|
||||
|
||||
@@ -117,13 +109,10 @@ delete_ping_timeout_func (MetaDisplay *display,
|
||||
NULL, NULL);
|
||||
|
||||
g_free (window_content);
|
||||
g_free (tmp);
|
||||
|
||||
window->dialog_pid = dialog_pid;
|
||||
|
||||
g_signal_connect (sigchld_nexus, "sigchld",
|
||||
G_CALLBACK (sigchld_handler),
|
||||
window);
|
||||
|
||||
g_child_watch_add (dialog_pid, dialog_exited, window);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -147,7 +136,7 @@ meta_window_delete (MetaWindow *window,
|
||||
window->desc);
|
||||
XKillClient (window->display->xdisplay, window->xwindow);
|
||||
}
|
||||
meta_error_trap_pop (window->display, FALSE);
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
meta_display_ping_window (window->display,
|
||||
window,
|
||||
@@ -189,42 +178,29 @@ meta_window_delete (MetaWindow *window,
|
||||
void
|
||||
meta_window_kill (MetaWindow *window)
|
||||
{
|
||||
char buf[257];
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Killing %s brutally\n",
|
||||
window->desc);
|
||||
|
||||
if (window->wm_client_machine != NULL &&
|
||||
if (!meta_window_is_remote (window) &&
|
||||
window->net_wm_pid > 0)
|
||||
{
|
||||
if (gethostname (buf, sizeof(buf)-1) == 0)
|
||||
{
|
||||
if (strcmp (buf, window->wm_client_machine) == 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Killing %s with kill()\n",
|
||||
window->desc);
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Killing %s with kill()\n",
|
||||
window->desc);
|
||||
|
||||
if (kill (window->net_wm_pid, 9) < 0)
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Failed to signal %s: %s\n",
|
||||
window->desc, strerror (errno));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_warning (_("Failed to get hostname: %s\n"),
|
||||
strerror (errno));
|
||||
}
|
||||
if (kill (window->net_wm_pid, 9) < 0)
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Failed to signal %s: %s\n",
|
||||
window->desc, strerror (errno));
|
||||
}
|
||||
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Disconnecting %s with XKillClient()\n",
|
||||
window->desc);
|
||||
meta_error_trap_push (window->display);
|
||||
XKillClient (window->display->xdisplay, window->xwindow);
|
||||
meta_error_trap_pop (window->display, FALSE);
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -83,10 +83,11 @@ struct _MetaDisplay
|
||||
|
||||
char *name;
|
||||
Display *xdisplay;
|
||||
char *hostname;
|
||||
|
||||
Window leader_window;
|
||||
Window timestamp_pinging_window;
|
||||
|
||||
|
||||
/* Pull in all the names of atoms as fields; we will intern them when the
|
||||
* class is constructed.
|
||||
*/
|
||||
@@ -150,6 +151,15 @@ struct _MetaDisplay
|
||||
|
||||
guint32 current_time;
|
||||
|
||||
/* We maintain a sequence counter, incremented for each #MetaWindow
|
||||
* created. This is exposed by meta_window_get_stable_sequence()
|
||||
* but is otherwise not used inside mutter.
|
||||
*
|
||||
* It can be useful to plugins which want to sort windows in a
|
||||
* stable fashion.
|
||||
*/
|
||||
guint32 window_sequence_counter;
|
||||
|
||||
/* Pings which we're waiting for a reply from */
|
||||
GSList *pending_pings;
|
||||
|
||||
@@ -175,6 +185,9 @@ struct _MetaDisplay
|
||||
guint grab_have_pointer : 1;
|
||||
guint grab_have_keyboard : 1;
|
||||
guint grab_frame_action : 1;
|
||||
/* During a resize operation, the directions in which we've broken
|
||||
* out of the initial maximization state */
|
||||
guint grab_resize_unmaximize : 2; /* MetaMaximizeFlags */
|
||||
MetaRectangle grab_initial_window_pos;
|
||||
int grab_initial_x, grab_initial_y; /* These are only relevant for */
|
||||
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
||||
@@ -217,8 +230,8 @@ struct _MetaDisplay
|
||||
MetaKeyCombo overlay_key_combo;
|
||||
gboolean overlay_key_only_pressed;
|
||||
|
||||
/* Xinerama cache */
|
||||
unsigned int xinerama_cache_invalidated : 1;
|
||||
/* Monitor cache */
|
||||
unsigned int monitor_cache_invalidated : 1;
|
||||
|
||||
/* Opening the display */
|
||||
unsigned int display_opening : 1;
|
||||
@@ -294,22 +307,15 @@ struct _MetaDisplayClass
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/* Xserver time can wraparound, thus comparing two timestamps needs to take
|
||||
* this into account. Here's a little macro to help out. If no wraparound
|
||||
* has occurred, this is equivalent to
|
||||
* time1 < time2
|
||||
* Of course, the rest of the ugliness of this macro comes from accounting
|
||||
* for the fact that wraparound can occur and the fact that a timestamp of
|
||||
* 0 must be special-cased since it means older than anything else.
|
||||
*
|
||||
* Note that this is NOT an equivalent for time1 <= time2; if that's what
|
||||
* you need then you'll need to swap the order of the arguments and negate
|
||||
* the result.
|
||||
*/
|
||||
#define XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) \
|
||||
( (( (time1) < (time2) ) && ( (time2) - (time1) < ((guint32)-1)/2 )) || \
|
||||
(( (time1) > (time2) ) && ( (time1) - (time2) > ((guint32)-1)/2 )) \
|
||||
)
|
||||
/**
|
||||
* XSERVER_TIME_IS_BEFORE:
|
||||
*
|
||||
* See the docs for meta_display_xserver_time_is_before().
|
||||
*/
|
||||
#define XSERVER_TIME_IS_BEFORE(time1, time2) \
|
||||
( (time1) == 0 || \
|
||||
(XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) && \
|
||||
@@ -349,6 +355,9 @@ void meta_display_register_x_window (MetaDisplay *display,
|
||||
void meta_display_unregister_x_window (MetaDisplay *display,
|
||||
Window xwindow);
|
||||
|
||||
void meta_display_notify_window_created (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
|
||||
GSList* meta_display_list_windows (MetaDisplay *display,
|
||||
MetaListWindowsFlags flags);
|
||||
|
||||
@@ -378,9 +387,8 @@ void meta_display_grab_focus_window_button (MetaDisplay *display,
|
||||
void meta_display_ungrab_focus_window_button (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
|
||||
/* Next two functions are defined in edge-resistance.c */
|
||||
void meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display);
|
||||
void meta_display_cleanup_edges (MetaDisplay *display);
|
||||
/* Next function is defined in edge-resistance.c */
|
||||
void meta_display_cleanup_edges (MetaDisplay *display);
|
||||
|
||||
/* make a request to ensure the event serial has changed */
|
||||
void meta_display_increment_event_serial (MetaDisplay *display);
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
* The display is represented as a MetaDisplay struct.
|
||||
*/
|
||||
|
||||
#define _XOPEN_SOURCE 600 /* for gethostname() */
|
||||
|
||||
#include <config.h>
|
||||
#include "display-private.h"
|
||||
#include "util.h"
|
||||
@@ -72,6 +74,7 @@
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define GRAB_OP_IS_WINDOW_SWITCH(g) \
|
||||
(g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \
|
||||
@@ -129,6 +132,9 @@ enum
|
||||
{
|
||||
OVERLAY_KEY,
|
||||
FOCUS_WINDOW,
|
||||
WINDOW_CREATED,
|
||||
WINDOW_DEMANDS_ATTENTION,
|
||||
WINDOW_MARKED_URGENT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
@@ -148,8 +154,10 @@ static guint display_signals [LAST_SIGNAL] = { 0 };
|
||||
*/
|
||||
static MetaDisplay *the_display = NULL;
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static void meta_spew_event (MetaDisplay *display,
|
||||
XEvent *event);
|
||||
#endif
|
||||
|
||||
static gboolean event_callback (XEvent *event,
|
||||
gpointer data);
|
||||
@@ -226,6 +234,34 @@ meta_display_class_init (MetaDisplayClass *klass)
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
display_signals[WINDOW_CREATED] =
|
||||
g_signal_new ("window-created",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1, META_TYPE_WINDOW);
|
||||
|
||||
display_signals[WINDOW_DEMANDS_ATTENTION] =
|
||||
g_signal_new ("window-demands-attention",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1, META_TYPE_WINDOW);
|
||||
|
||||
display_signals[WINDOW_MARKED_URGENT] =
|
||||
g_signal_new ("window-marked-urgent",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
META_TYPE_WINDOW);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_FOCUS_WINDOW,
|
||||
g_param_spec_object ("focus-window",
|
||||
@@ -311,7 +347,7 @@ sn_error_trap_pop (SnDisplay *sn_display,
|
||||
MetaDisplay *display;
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
if (display != NULL)
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -396,6 +432,7 @@ meta_display_open (void)
|
||||
GSList *tmp;
|
||||
int i;
|
||||
guint32 timestamp;
|
||||
char buf[257];
|
||||
|
||||
/* A list of all atom names, so that we can intern them in one go. */
|
||||
char *atom_names[] = {
|
||||
@@ -430,6 +467,11 @@ meta_display_open (void)
|
||||
*/
|
||||
the_display->name = g_strdup (XDisplayName (NULL));
|
||||
the_display->xdisplay = xdisplay;
|
||||
if (gethostname (buf, sizeof(buf)-1) == 0)
|
||||
{
|
||||
buf[sizeof(buf)-1] = '\0';
|
||||
the_display->hostname = g_strdup (buf);
|
||||
}
|
||||
the_display->error_trap_synced_at_last_pop = TRUE;
|
||||
the_display->error_traps = 0;
|
||||
the_display->error_trap_handler = NULL;
|
||||
@@ -483,7 +525,7 @@ meta_display_open (void)
|
||||
the_display->leader_window = None;
|
||||
the_display->timestamp_pinging_window = None;
|
||||
|
||||
the_display->xinerama_cache_invalidated = TRUE;
|
||||
the_display->monitor_cache_invalidated = TRUE;
|
||||
|
||||
the_display->groups_by_leader = NULL;
|
||||
|
||||
@@ -722,6 +764,13 @@ meta_display_open (void)
|
||||
the_display->leader_window,
|
||||
the_display->atom__NET_WM_NAME,
|
||||
"Mutter");
|
||||
|
||||
/* The GNOME keybindings capplet should include both the Mutter and Metacity
|
||||
* keybindings */
|
||||
meta_prop_set_utf8_string_hint (the_display,
|
||||
the_display->leader_window,
|
||||
the_display->atom__GNOME_WM_KEYBINDINGS,
|
||||
"Mutter,Metacity");
|
||||
|
||||
meta_prop_set_utf8_string_hint (the_display,
|
||||
the_display->leader_window,
|
||||
@@ -841,7 +890,7 @@ meta_display_open (void)
|
||||
timestamp);
|
||||
}
|
||||
|
||||
meta_error_trap_pop (the_display, FALSE);
|
||||
meta_error_trap_pop (the_display);
|
||||
}
|
||||
|
||||
meta_display_ungrab (the_display);
|
||||
@@ -1050,7 +1099,7 @@ meta_display_screen_for_xwindow (MetaDisplay *display,
|
||||
meta_error_trap_push (display);
|
||||
attr.screen = NULL;
|
||||
result = XGetWindowAttributes (display->xdisplay, xwindow, &attr);
|
||||
meta_error_trap_pop (display, TRUE);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
/* Note, XGetWindowAttributes is on all kinds of crack
|
||||
* and returns 1 on success 0 on failure, rather than Success
|
||||
@@ -1280,6 +1329,43 @@ meta_grab_op_is_moving (MetaGrabOp op)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_xserver_time_is_before:
|
||||
* @display: a #MetaDisplay
|
||||
* @time1: An event timestamp
|
||||
* @time2: An event timestamp
|
||||
*
|
||||
* Xserver time can wraparound, thus comparing two timestamps needs to take
|
||||
* this into account. If no wraparound has occurred, this is equivalent to
|
||||
* time1 < time2
|
||||
* Otherwise, we need to account for the fact that wraparound can occur
|
||||
* and the fact that a timestamp of 0 must be special-cased since it
|
||||
* means "older than anything else".
|
||||
*
|
||||
* Note that this is NOT an equivalent for time1 <= time2; if that's what
|
||||
* you need then you'll need to swap the order of the arguments and negate
|
||||
* the result.
|
||||
*/
|
||||
gboolean
|
||||
meta_display_xserver_time_is_before (MetaDisplay *display,
|
||||
guint32 time1,
|
||||
guint32 time2)
|
||||
{
|
||||
return XSERVER_TIME_IS_BEFORE(time1, time2);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_get_last_user_time:
|
||||
* @display: a #MetaDisplay
|
||||
*
|
||||
* Returns: Timestamp of the last user interaction event with a window
|
||||
*/
|
||||
guint32
|
||||
meta_display_get_last_user_time (MetaDisplay *display)
|
||||
{
|
||||
return display->last_user_time;
|
||||
}
|
||||
|
||||
/* Get time of current event, or CurrentTime if none. */
|
||||
guint32
|
||||
meta_display_get_current_time (MetaDisplay *display)
|
||||
@@ -1406,7 +1492,7 @@ window_raise_with_delay_callback (void *data)
|
||||
window->xwindow,
|
||||
&root, &child,
|
||||
&root_x, &root_y, &x, &y, &mask);
|
||||
meta_error_trap_pop (window->display, TRUE);
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
point_in_window =
|
||||
(window->frame && POINT_IN_RECT (root_x, root_y, window->frame->rect)) ||
|
||||
@@ -1528,7 +1614,7 @@ event_callback (XEvent *event,
|
||||
bypass_compositor = FALSE;
|
||||
filter_out_event = FALSE;
|
||||
display->current_time = event_get_time (display, event);
|
||||
display->xinerama_cache_invalidated = TRUE;
|
||||
display->monitor_cache_invalidated = TRUE;
|
||||
|
||||
modified = event_get_modified_window (display, event);
|
||||
|
||||
@@ -1649,7 +1735,8 @@ event_callback (XEvent *event,
|
||||
}
|
||||
#endif /* HAVE_SHAPE */
|
||||
|
||||
if (window && ((event->type == KeyPress) || (event->type == ButtonPress)))
|
||||
if (window && !window->override_redirect &&
|
||||
((event->type == KeyPress) || (event->type == ButtonPress)))
|
||||
{
|
||||
if (CurrentTime == display->current_time)
|
||||
{
|
||||
@@ -2121,7 +2208,7 @@ event_callback (XEvent *event,
|
||||
window->frame->xwindow);
|
||||
meta_error_trap_push (display);
|
||||
meta_window_destroy_frame (window->frame->window);
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2290,7 +2377,7 @@ event_callback (XEvent *event,
|
||||
meta_error_trap_push (display);
|
||||
XConfigureWindow (display->xdisplay, event->xconfigurerequest.window,
|
||||
xwcm, &xwc);
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2549,7 +2636,7 @@ event_callback (XEvent *event,
|
||||
{
|
||||
case XkbBellNotify:
|
||||
if (XSERVER_TIME_IS_BEFORE(display->last_bell_time,
|
||||
xkb_ev->time - 1000))
|
||||
xkb_ev->time - 100))
|
||||
{
|
||||
display->last_bell_time = xkb_ev->time;
|
||||
meta_bell_notify (display, xkb_ev);
|
||||
@@ -3061,7 +3148,7 @@ meta_spew_event (MetaDisplay *display,
|
||||
meta_error_trap_push (display);
|
||||
str = XGetAtomName (display->xdisplay,
|
||||
event->xproperty.atom);
|
||||
meta_error_trap_pop (display, TRUE);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
if (event->xproperty.state == PropertyNewValue)
|
||||
state = "PropertyNewValue";
|
||||
@@ -3095,7 +3182,7 @@ meta_spew_event (MetaDisplay *display,
|
||||
meta_error_trap_push (display);
|
||||
str = XGetAtomName (display->xdisplay,
|
||||
event->xclient.message_type);
|
||||
meta_error_trap_pop (display, TRUE);
|
||||
meta_error_trap_pop (display);
|
||||
extra = g_strdup_printf ("type: %s format: %d\n",
|
||||
str ? str : "(unknown atom)",
|
||||
event->xclient.format);
|
||||
@@ -3203,6 +3290,13 @@ meta_display_unregister_x_window (MetaDisplay *display,
|
||||
remove_pending_pings_for_window (display, xwindow);
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_notify_window_created (MetaDisplay *display,
|
||||
MetaWindow *window)
|
||||
{
|
||||
g_signal_emit (display, display_signals[WINDOW_CREATED], 0, window);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_xwindow_is_a_no_focus_window:
|
||||
* @display: A #MetaDisplay
|
||||
@@ -3366,7 +3460,7 @@ meta_display_set_grab_op_cursor (MetaDisplay *display,
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Changed pointer with XChangeActivePointerGrab()\n");
|
||||
|
||||
if (meta_error_trap_pop_with_return (display, FALSE) != Success)
|
||||
if (meta_error_trap_pop_with_return (display) != Success)
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Error trapped from XChangeActivePointerGrab()\n");
|
||||
@@ -3399,7 +3493,7 @@ meta_display_set_grab_op_cursor (MetaDisplay *display,
|
||||
"XGrabPointer() failed time %u\n",
|
||||
timestamp);
|
||||
}
|
||||
meta_error_trap_pop (display, TRUE);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
#undef GRAB_MASK
|
||||
@@ -3516,6 +3610,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
display->grab_last_user_action_was_snap = FALSE;
|
||||
#endif
|
||||
display->grab_frame_action = frame_action;
|
||||
display->grab_resize_unmaximize = 0;
|
||||
|
||||
if (display->grab_resize_timeout_id)
|
||||
{
|
||||
@@ -3574,7 +3669,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
XSyncCAEvents,
|
||||
&values);
|
||||
|
||||
if (meta_error_trap_pop_with_return (display, FALSE) != Success)
|
||||
if (meta_error_trap_pop_with_return (display) != Success)
|
||||
display->grab_sync_request_alarm = None;
|
||||
|
||||
meta_topic (META_DEBUG_RESIZING,
|
||||
@@ -3591,18 +3686,6 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
g_assert (display->grab_window != NULL || display->grab_screen != NULL);
|
||||
g_assert (display->grab_op != META_GRAB_OP_NONE);
|
||||
|
||||
/* If this is a move or resize, cache the window edges for
|
||||
* resistance/snapping
|
||||
*/
|
||||
if (meta_grab_op_is_resizing (display->grab_op) ||
|
||||
meta_grab_op_is_moving (display->grab_op))
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Computing edges to resist-movement or snap-to for %s.\n",
|
||||
window->desc);
|
||||
meta_display_compute_resistance_and_snapping_edges (display);
|
||||
}
|
||||
|
||||
/* Save the old stacking */
|
||||
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
|
||||
{
|
||||
@@ -3805,7 +3888,7 @@ meta_change_button_grab (MetaDisplay *display,
|
||||
{
|
||||
int result;
|
||||
|
||||
result = meta_error_trap_pop_with_return (display, FALSE);
|
||||
result = meta_error_trap_pop_with_return (display);
|
||||
|
||||
if (result != Success)
|
||||
meta_verbose ("Failed to %s button %d with mask 0x%x for window 0x%lx error code %d\n",
|
||||
@@ -3816,7 +3899,7 @@ meta_change_button_grab (MetaDisplay *display,
|
||||
++ignored_mask;
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -4000,7 +4083,7 @@ meta_display_update_active_window_hint (MetaDisplay *display)
|
||||
XA_WINDOW,
|
||||
32, PropModeReplace, (guchar*) data, 1);
|
||||
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
@@ -4097,8 +4180,8 @@ meta_set_syncing (gboolean setting)
|
||||
if (setting != is_syncing)
|
||||
{
|
||||
is_syncing = setting;
|
||||
|
||||
XSynchronize (meta_get_display ()->xdisplay, is_syncing);
|
||||
if (meta_get_display ())
|
||||
XSynchronize (meta_get_display ()->xdisplay, is_syncing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4106,7 +4189,7 @@ meta_set_syncing (gboolean setting)
|
||||
* How long, in milliseconds, we should wait after pinging a window
|
||||
* before deciding it's not going to get back to us.
|
||||
*/
|
||||
#define PING_TIMEOUT_DELAY 2250
|
||||
#define PING_TIMEOUT_DELAY 5000
|
||||
|
||||
/**
|
||||
* Does whatever it is we decided to do when a window didn't respond
|
||||
@@ -4280,7 +4363,7 @@ process_request_frame_extents (MetaDisplay *display,
|
||||
display->atom__NET_FRAME_EXTENTS,
|
||||
XA_CARDINAL,
|
||||
32, PropModeReplace, (guchar*) data, 4);
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
meta_XFree (hints);
|
||||
}
|
||||
@@ -4468,6 +4551,18 @@ find_tab_backward (MetaDisplay *display,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_get_tab_list:
|
||||
* @display: a #MetaDisplay
|
||||
* @type: type of tab list
|
||||
* @screen: a #MetaScreen
|
||||
* @workspace: origin workspace
|
||||
*
|
||||
* Determine the list of windows that should be displayed for Alt-TAB
|
||||
* functionality. The windows are returned in most recently used order.
|
||||
*
|
||||
* Returns: (transfer container) (element-type Meta.Window): List of windows
|
||||
*/
|
||||
GList*
|
||||
meta_display_get_tab_list (MetaDisplay *display,
|
||||
MetaTabList type,
|
||||
@@ -4531,7 +4626,8 @@ meta_display_get_tab_list (MetaDisplay *display,
|
||||
|
||||
/* Check to see if it demands attention */
|
||||
if (l_window->wm_state_demands_attention &&
|
||||
l_window->workspace!=workspace)
|
||||
l_window->workspace!=workspace &&
|
||||
IN_TAB_CHAIN (l_window, type))
|
||||
{
|
||||
/* if it does, add it to the popup */
|
||||
tab_list = g_list_prepend (tab_list, l_window);
|
||||
@@ -4544,6 +4640,21 @@ meta_display_get_tab_list (MetaDisplay *display,
|
||||
return tab_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_get_tab_next:
|
||||
* @display: a #MetaDisplay
|
||||
* @type: type of tab list
|
||||
* @screen: a #MetaScreen
|
||||
* @workspace: origin workspace
|
||||
* @window: (allow-none): starting window
|
||||
* @backward: If %TRUE, look for the previous window.
|
||||
*
|
||||
* Determine the next window that should be displayed for Alt-TAB
|
||||
* functionality.
|
||||
*
|
||||
* Returns: (transfer none): Next window
|
||||
*
|
||||
*/
|
||||
MetaWindow*
|
||||
meta_display_get_tab_next (MetaDisplay *display,
|
||||
MetaTabList type,
|
||||
@@ -4594,6 +4705,18 @@ meta_display_get_tab_next (MetaDisplay *display,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_get_tab_current:
|
||||
* @display: a #MetaDisplay
|
||||
* @type: type of tab list
|
||||
* @screen: a #MetaScreen
|
||||
* @workspace: origin workspace
|
||||
*
|
||||
* Determine the active window that should be displayed for Alt-TAB.
|
||||
*
|
||||
* Returns: (transfer none): Current window
|
||||
*
|
||||
*/
|
||||
MetaWindow*
|
||||
meta_display_get_tab_current (MetaDisplay *display,
|
||||
MetaTabList type,
|
||||
@@ -4718,11 +4841,11 @@ convert_property (MetaDisplay *display,
|
||||
(unsigned char *)icccm_version, 2);
|
||||
else
|
||||
{
|
||||
meta_error_trap_pop_with_return (display, FALSE);
|
||||
meta_error_trap_pop_with_return (display);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (meta_error_trap_pop_with_return (display, FALSE) != Success)
|
||||
if (meta_error_trap_pop_with_return (display) != Success)
|
||||
return FALSE;
|
||||
|
||||
/* Be sure the PropertyNotify has arrived so we
|
||||
@@ -4754,7 +4877,7 @@ process_selection_request (MetaDisplay *display,
|
||||
meta_error_trap_push (display);
|
||||
str = XGetAtomName (display->xdisplay,
|
||||
event->xselectionrequest.selection);
|
||||
meta_error_trap_pop (display, TRUE);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
meta_verbose ("Selection request with selection %s window 0x%lx not a WM_Sn selection we recognize\n",
|
||||
str ? str : "(bad atom)", event->xselectionrequest.owner);
|
||||
@@ -4788,11 +4911,11 @@ process_selection_request (MetaDisplay *display,
|
||||
display->atom_ATOM_PAIR,
|
||||
&type, &format, &num, &rest, &data) != Success)
|
||||
{
|
||||
meta_error_trap_pop_with_return (display, TRUE);
|
||||
meta_error_trap_pop_with_return (display);
|
||||
return;
|
||||
}
|
||||
|
||||
if (meta_error_trap_pop_with_return (display, TRUE) == Success)
|
||||
if (meta_error_trap_pop_with_return (display) == Success)
|
||||
{
|
||||
/* FIXME: to be 100% correct, should deal with rest > 0,
|
||||
* but since we have 4 possible targets, we will hardly ever
|
||||
@@ -4815,7 +4938,7 @@ process_selection_request (MetaDisplay *display,
|
||||
event->xselectionrequest.property,
|
||||
display->atom_ATOM_PAIR,
|
||||
32, PropModeReplace, data, num);
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
meta_XFree (data);
|
||||
}
|
||||
}
|
||||
@@ -4871,7 +4994,7 @@ process_selection_clear (MetaDisplay *display,
|
||||
meta_error_trap_push (display);
|
||||
str = XGetAtomName (display->xdisplay,
|
||||
event->xselectionclear.selection);
|
||||
meta_error_trap_pop (display, TRUE);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
meta_verbose ("Selection clear with selection %s window 0x%lx not a WM_Sn selection we recognize\n",
|
||||
str ? str : "(bad atom)", event->xselectionclear.window);
|
||||
@@ -4938,6 +5061,34 @@ meta_display_stack_cmp (const void *a,
|
||||
return 0; /* not reached in theory, if windows on same display */
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_sort_windows_by_stacking:
|
||||
* @display: a #MetaDisplay
|
||||
* @windows: (element-type MetaWindow): Set of windows
|
||||
*
|
||||
* Sorts a set of windows according to their current stacking order. If windows
|
||||
* from multiple screens are present in the set of input windows, then all the
|
||||
* windows on screen 0 are sorted below all the windows on screen 1, and so forth.
|
||||
* Since the stacking order of override-redirect windows isn't controlled by
|
||||
* Metacity, if override-redirect windows are in the input, the result may not
|
||||
* correspond to the actual stacking order in the X server.
|
||||
*
|
||||
* An example of using this would be to sort the list of transient dialogs for a
|
||||
* window into their current stacking order.
|
||||
*
|
||||
* Returns: (transfer container): Input windows sorted by stacking order, from lowest to highest
|
||||
*/
|
||||
GSList *
|
||||
meta_display_sort_windows_by_stacking (MetaDisplay *display,
|
||||
GSList *windows)
|
||||
{
|
||||
GSList *copy = g_slist_copy (windows);
|
||||
|
||||
copy = g_slist_sort (copy, meta_display_stack_cmp);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_devirtualize_modifiers (MetaDisplay *display,
|
||||
MetaVirtualModifier modifiers,
|
||||
@@ -5042,6 +5193,34 @@ prefs_changed_callback (MetaPreference pref,
|
||||
else
|
||||
disable_compositor (display);
|
||||
}
|
||||
else if (pref == META_PREF_ATTACH_MODAL_DIALOGS)
|
||||
{
|
||||
MetaDisplay *display = data;
|
||||
GSList *windows;
|
||||
GSList *tmp;
|
||||
|
||||
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
|
||||
|
||||
for (tmp = windows; tmp != NULL; tmp = tmp->next)
|
||||
{
|
||||
MetaWindow *w = tmp->data;
|
||||
MetaWindow *parent = meta_window_get_transient_for (w);
|
||||
meta_window_recalc_features (w);
|
||||
|
||||
if (w->type == META_WINDOW_MODAL_DIALOG && parent && parent != w)
|
||||
{
|
||||
int x, y;
|
||||
/* Forcing a call to move_resize() does two things: first, it handles
|
||||
* resizing the dialog frame window to the correct size when we remove
|
||||
* or add the decorations. Second, it will take care of positioning the
|
||||
* dialog as "attached" to the parent when we turn the preference on
|
||||
* via the constrain_modal_dialog() constraint.
|
||||
**/
|
||||
meta_window_get_position (w, &x, &y);
|
||||
meta_window_move (w, FALSE, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -5111,9 +5290,9 @@ sanity_check_timestamps (MetaDisplay *display,
|
||||
meta_warning ("%s appears to be one of the offending windows "
|
||||
"with a timestamp of %u. Working around...\n",
|
||||
window->desc, window->net_wm_user_time);
|
||||
window->net_wm_user_time = timestamp;
|
||||
meta_window_set_user_time (window, timestamp);
|
||||
}
|
||||
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
@@ -5187,7 +5366,7 @@ meta_display_set_input_focus_window (MetaDisplay *display,
|
||||
focus_frame ? window->frame->xwindow : window->xwindow,
|
||||
RevertToPointerRoot,
|
||||
timestamp);
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
display->expected_focus_window = window;
|
||||
display->last_focus_time = timestamp;
|
||||
@@ -5242,18 +5421,32 @@ meta_display_get_compositor_version (MetaDisplay *display,
|
||||
*minor = display->composite_minor_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_get_xdisplay: (skip)
|
||||
*
|
||||
*/
|
||||
Display *
|
||||
meta_display_get_xdisplay (MetaDisplay *display)
|
||||
{
|
||||
return display->xdisplay;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_get_compositor: (skip)
|
||||
*
|
||||
*/
|
||||
MetaCompositor *
|
||||
meta_display_get_compositor (MetaDisplay *display)
|
||||
{
|
||||
return display->compositor;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_get_screens:
|
||||
* @display: a #MetaDisplay
|
||||
*
|
||||
* Returns: (transfer none) (element-type Meta.Screen): Screens for this display
|
||||
*/
|
||||
GSList *
|
||||
meta_display_get_screens (MetaDisplay *display)
|
||||
{
|
||||
@@ -5298,9 +5491,32 @@ meta_display_get_shape_event_base (MetaDisplay *display)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* meta_display_get_atom: (skip)
|
||||
*
|
||||
* Gets up an X atom that Mutter prefetched at startup.
|
||||
*
|
||||
* Return value: the X atom corresponding to the given atom enumeration
|
||||
*/
|
||||
Atom meta_display_get_atom (MetaDisplay *display, MetaAtom meta_atom)
|
||||
{
|
||||
Atom *atoms = & display->atom_WM_PROTOCOLS;
|
||||
|
||||
return atoms[meta_atom - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_get_leader_window:
|
||||
* @display: a #MetaDisplay
|
||||
*
|
||||
* Returns the window manager's leader window (as defined by the
|
||||
* _NET_SUPPORTING_WM_CHECK mechanism of EWMH). For use by plugins that wish
|
||||
* to attach additional custom properties to this window.
|
||||
*
|
||||
* Return value: (transfer none): xid of the leader window.
|
||||
**/
|
||||
Window
|
||||
meta_display_get_leader_window (MetaDisplay *display)
|
||||
{
|
||||
return display->leader_window;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#include <config.h>
|
||||
#include "edge-resistance.h"
|
||||
#include "boxes.h"
|
||||
#include "boxes-private.h"
|
||||
#include "display-private.h"
|
||||
#include "workspace-private.h"
|
||||
|
||||
@@ -63,6 +63,8 @@ struct MetaEdgeResistanceData
|
||||
ResistanceDataForAnEdge bottom_data;
|
||||
};
|
||||
|
||||
static void compute_resistance_and_snapping_edges (MetaDisplay *display);
|
||||
|
||||
/* !WARNING!: this function can return invalid indices (namely, either -1 or
|
||||
* edges->len); this is by design, but you need to remember this.
|
||||
*/
|
||||
@@ -340,12 +342,12 @@ apply_edge_resistance (MetaWindow *window,
|
||||
|
||||
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_WINDOW = 16;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW = 0;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_XINERAMA = 32;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_XINERAMA = 0;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_MONITOR = 32;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_MONITOR = 0;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_SCREEN = 32;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_SCREEN = 0;
|
||||
const int TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW = 0;
|
||||
const int TIMEOUT_RESISTANCE_LENGTH_MS_XINERAMA = 0;
|
||||
const int TIMEOUT_RESISTANCE_LENGTH_MS_MONITOR = 0;
|
||||
const int TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN = 0;
|
||||
|
||||
/* Quit if no movement was specified */
|
||||
@@ -423,8 +425,8 @@ apply_edge_resistance (MetaWindow *window,
|
||||
case META_EDGE_WINDOW:
|
||||
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW;
|
||||
break;
|
||||
case META_EDGE_XINERAMA:
|
||||
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_XINERAMA;
|
||||
case META_EDGE_MONITOR:
|
||||
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_MONITOR;
|
||||
break;
|
||||
case META_EDGE_SCREEN:
|
||||
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN;
|
||||
@@ -468,11 +470,11 @@ apply_edge_resistance (MetaWindow *window,
|
||||
else
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW;
|
||||
break;
|
||||
case META_EDGE_XINERAMA:
|
||||
case META_EDGE_MONITOR:
|
||||
if (movement_towards_edge (edge->side_type, increment))
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_XINERAMA;
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_MONITOR;
|
||||
else
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_XINERAMA;
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_MONITOR;
|
||||
break;
|
||||
case META_EDGE_SCREEN:
|
||||
if (movement_towards_edge (edge->side_type, increment))
|
||||
@@ -550,7 +552,9 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
|
||||
gboolean modified;
|
||||
int new_left, new_right, new_top, new_bottom;
|
||||
|
||||
g_assert (display->grab_edge_resistance_data != NULL);
|
||||
if (display->grab_edge_resistance_data == NULL)
|
||||
compute_resistance_and_snapping_edges (display);
|
||||
|
||||
edge_data = display->grab_edge_resistance_data;
|
||||
|
||||
if (auto_snap)
|
||||
@@ -671,7 +675,8 @@ meta_display_cleanup_edges (MetaDisplay *display)
|
||||
MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data;
|
||||
GHashTable *edges_to_be_freed;
|
||||
|
||||
g_assert (edge_data != NULL);
|
||||
if (edge_data == NULL) /* Not currently cached */
|
||||
return;
|
||||
|
||||
/* We first need to clean out any window edges */
|
||||
edges_to_be_freed = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
||||
@@ -761,7 +766,7 @@ stupid_sort_requiring_extra_pointer_dereference (gconstpointer a,
|
||||
static void
|
||||
cache_edges (MetaDisplay *display,
|
||||
GList *window_edges,
|
||||
GList *xinerama_edges,
|
||||
GList *monitor_edges,
|
||||
GList *screen_edges)
|
||||
{
|
||||
MetaEdgeResistanceData *edge_data;
|
||||
@@ -776,7 +781,7 @@ cache_edges (MetaDisplay *display,
|
||||
if (meta_is_verbose())
|
||||
{
|
||||
int max_edges = MAX (MAX( g_list_length (window_edges),
|
||||
g_list_length (xinerama_edges)),
|
||||
g_list_length (monitor_edges)),
|
||||
g_list_length (screen_edges));
|
||||
char big_buffer[(EDGE_LENGTH+2)*max_edges];
|
||||
|
||||
@@ -784,9 +789,9 @@ cache_edges (MetaDisplay *display,
|
||||
meta_topic (META_DEBUG_EDGE_RESISTANCE,
|
||||
"Window edges for resistance : %s\n", big_buffer);
|
||||
|
||||
meta_rectangle_edge_list_to_string (xinerama_edges, ", ", big_buffer);
|
||||
meta_rectangle_edge_list_to_string (monitor_edges, ", ", big_buffer);
|
||||
meta_topic (META_DEBUG_EDGE_RESISTANCE,
|
||||
"Xinerama edges for resistance: %s\n", big_buffer);
|
||||
"Monitor edges for resistance: %s\n", big_buffer);
|
||||
|
||||
meta_rectangle_edge_list_to_string (screen_edges, ", ", big_buffer);
|
||||
meta_topic (META_DEBUG_EDGE_RESISTANCE,
|
||||
@@ -807,7 +812,7 @@ cache_edges (MetaDisplay *display,
|
||||
tmp = window_edges;
|
||||
break;
|
||||
case 1:
|
||||
tmp = xinerama_edges;
|
||||
tmp = monitor_edges;
|
||||
break;
|
||||
case 2:
|
||||
tmp = screen_edges;
|
||||
@@ -875,7 +880,7 @@ cache_edges (MetaDisplay *display,
|
||||
tmp = window_edges;
|
||||
break;
|
||||
case 1:
|
||||
tmp = xinerama_edges;
|
||||
tmp = monitor_edges;
|
||||
break;
|
||||
case 2:
|
||||
tmp = screen_edges;
|
||||
@@ -938,8 +943,8 @@ initialize_grab_edge_resistance_data (MetaDisplay *display)
|
||||
edge_data->bottom_data.keyboard_buildup = 0;
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
static void
|
||||
compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
{
|
||||
GList *stacked_windows;
|
||||
GList *cur_window_iter;
|
||||
@@ -952,6 +957,11 @@ meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
*/
|
||||
GSList *rem_windows, *rem_win_stacking;
|
||||
|
||||
g_assert (display->grab_window != NULL);
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Computing edges to resist-movement or snap-to for %s.\n",
|
||||
display->grab_window->desc);
|
||||
|
||||
/*
|
||||
* 1st: Get the list of relevant windows, from bottom to top
|
||||
*/
|
||||
@@ -1110,12 +1120,12 @@ meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
|
||||
/*
|
||||
* 5th: Cache the combination of these edges with the onscreen and
|
||||
* xinerama edges in an array for quick access. Free the edges since
|
||||
* monitor edges in an array for quick access. Free the edges since
|
||||
* they've been cached elsewhere.
|
||||
*/
|
||||
cache_edges (display,
|
||||
edges,
|
||||
display->grab_screen->active_workspace->xinerama_edges,
|
||||
display->grab_screen->active_workspace->monitor_edges,
|
||||
display->grab_screen->active_workspace->screen_edges);
|
||||
g_list_free (edges);
|
||||
|
||||
|
||||
@@ -29,224 +29,38 @@
|
||||
#include <stdlib.h>
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
static int x_error_handler (Display *display,
|
||||
XErrorEvent *error);
|
||||
static int x_io_error_handler (Display *display);
|
||||
|
||||
void
|
||||
meta_errors_init (void)
|
||||
{
|
||||
XSetErrorHandler (x_error_handler);
|
||||
XSetIOErrorHandler (x_io_error_handler);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_error_trap_push_internal (MetaDisplay *display,
|
||||
gboolean need_sync)
|
||||
{
|
||||
/* GDK resets the error handler on each push */
|
||||
int (* old_error_handler) (Display *,
|
||||
XErrorEvent *);
|
||||
|
||||
if (need_sync)
|
||||
{
|
||||
XSync (display->xdisplay, False);
|
||||
}
|
||||
|
||||
gdk_error_trap_push ();
|
||||
|
||||
/* old_error_handler will just be equal to x_error_handler
|
||||
* for nested traps
|
||||
*/
|
||||
old_error_handler = XSetErrorHandler (x_error_handler);
|
||||
|
||||
/* Replace GDK handler, but save it so we can chain up */
|
||||
if (display->error_trap_handler == NULL)
|
||||
{
|
||||
g_assert (display->error_traps == 0);
|
||||
display->error_trap_handler = old_error_handler;
|
||||
g_assert (display->error_trap_handler != x_error_handler);
|
||||
}
|
||||
|
||||
display->error_traps += 1;
|
||||
|
||||
meta_topic (META_DEBUG_ERRORS, "%d traps remain\n", display->error_traps);
|
||||
}
|
||||
|
||||
static int
|
||||
meta_error_trap_pop_internal (MetaDisplay *display,
|
||||
gboolean need_sync)
|
||||
{
|
||||
int result;
|
||||
|
||||
g_assert (display->error_traps > 0);
|
||||
|
||||
if (need_sync)
|
||||
{
|
||||
XSync (display->xdisplay, False);
|
||||
}
|
||||
|
||||
result = gdk_error_trap_pop ();
|
||||
|
||||
display->error_traps -= 1;
|
||||
|
||||
if (display->error_traps == 0)
|
||||
{
|
||||
/* check that GDK put our handler back; this
|
||||
* assumes that there are no pending GDK traps from GDK itself
|
||||
*/
|
||||
|
||||
int (* restored_error_handler) (Display *,
|
||||
XErrorEvent *);
|
||||
|
||||
restored_error_handler = XSetErrorHandler (x_error_handler);
|
||||
|
||||
/* remove this */
|
||||
display->error_trap_handler = NULL;
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_ERRORS, "%d traps\n", display->error_traps);
|
||||
|
||||
return result;
|
||||
}
|
||||
/* In GTK+-3.0, the error trapping code was significantly rewritten. The new code
|
||||
* has some neat features (like knowing automatically if a sync is needed or not
|
||||
* and handling errors asynchronously when the error code isn't needed immediately),
|
||||
* but it's basically incompatible with the hacks we played with GTK+-2.0 to
|
||||
* use a custom error handler along with gdk_error_trap_push().
|
||||
*
|
||||
* Since the main point of our custom error trap was to get the error logged
|
||||
* to the right place, with GTK+-3.0 we simply omit our own error handler and
|
||||
* use the GTK+ handling straight-up.
|
||||
* (See https://bugzilla.gnome.org/show_bug.cgi?id=630216 for restoring logging.)
|
||||
*/
|
||||
|
||||
void
|
||||
meta_error_trap_push (MetaDisplay *display)
|
||||
{
|
||||
meta_error_trap_push_internal (display, FALSE);
|
||||
gdk_error_trap_push ();
|
||||
}
|
||||
|
||||
void
|
||||
meta_error_trap_pop (MetaDisplay *display,
|
||||
gboolean last_request_was_roundtrip)
|
||||
meta_error_trap_pop (MetaDisplay *display)
|
||||
{
|
||||
gboolean need_sync;
|
||||
|
||||
/* we only have to sync when popping the outermost trap */
|
||||
need_sync = (display->error_traps == 1 && !last_request_was_roundtrip);
|
||||
|
||||
if (need_sync)
|
||||
meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_pop, traps = %d, roundtrip = %d\n",
|
||||
display->error_traps, last_request_was_roundtrip);
|
||||
|
||||
display->error_trap_synced_at_last_pop = need_sync || last_request_was_roundtrip;
|
||||
|
||||
meta_error_trap_pop_internal (display, need_sync);
|
||||
gdk_error_trap_pop_ignored ();
|
||||
}
|
||||
|
||||
void
|
||||
meta_error_trap_push_with_return (MetaDisplay *display)
|
||||
{
|
||||
gboolean need_sync;
|
||||
|
||||
/* We don't sync on push_with_return if there are no traps
|
||||
* currently, because we assume that any errors were either covered
|
||||
* by a previous pop, or were fatal.
|
||||
*
|
||||
* More generally, we don't sync if we were synchronized last time
|
||||
* we popped. This is known to be the case if there are no traps,
|
||||
* but we also keep a flag so we know whether it's the case otherwise.
|
||||
*/
|
||||
|
||||
if (!display->error_trap_synced_at_last_pop)
|
||||
need_sync = TRUE;
|
||||
else
|
||||
need_sync = FALSE;
|
||||
|
||||
if (need_sync)
|
||||
meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_push_with_return, traps = %d\n",
|
||||
display->error_traps);
|
||||
|
||||
meta_error_trap_push_internal (display, FALSE);
|
||||
gdk_error_trap_push ();
|
||||
}
|
||||
|
||||
int
|
||||
meta_error_trap_pop_with_return (MetaDisplay *display,
|
||||
gboolean last_request_was_roundtrip)
|
||||
meta_error_trap_pop_with_return (MetaDisplay *display)
|
||||
{
|
||||
if (!last_request_was_roundtrip)
|
||||
meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_pop_with_return, traps = %d, roundtrip = %d\n",
|
||||
display->error_traps, last_request_was_roundtrip);
|
||||
|
||||
display->error_trap_synced_at_last_pop = TRUE;
|
||||
|
||||
return meta_error_trap_pop_internal (display,
|
||||
!last_request_was_roundtrip);
|
||||
}
|
||||
|
||||
static int
|
||||
x_error_handler (Display *xdisplay,
|
||||
XErrorEvent *error)
|
||||
{
|
||||
int retval;
|
||||
gchar buf[64];
|
||||
MetaDisplay *display;
|
||||
|
||||
XGetErrorText (xdisplay, error->error_code, buf, 63);
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
|
||||
/* Display can be NULL here because the compositing manager
|
||||
* has its own Display, but Xlib only has one global error handler
|
||||
*/
|
||||
if (display->error_traps > 0)
|
||||
{
|
||||
/* we're in an error trap, chain to the trap handler
|
||||
* saved from GDK
|
||||
*/
|
||||
meta_verbose ("X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
|
||||
buf,
|
||||
error->serial,
|
||||
error->error_code,
|
||||
error->request_code,
|
||||
error->minor_code);
|
||||
|
||||
g_assert (display->error_trap_handler != NULL);
|
||||
g_assert (display->error_trap_handler != x_error_handler);
|
||||
|
||||
retval = (* display->error_trap_handler) (xdisplay, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_bug ("Unexpected X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
|
||||
buf,
|
||||
error->serial,
|
||||
error->error_code,
|
||||
error->request_code,
|
||||
error->minor_code);
|
||||
|
||||
retval = 1; /* compiler warning */
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int
|
||||
x_io_error_handler (Display *xdisplay)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
|
||||
if (display == NULL)
|
||||
meta_bug ("IO error received for unknown display?\n");
|
||||
|
||||
if (errno == EPIPE)
|
||||
{
|
||||
meta_warning (_("Lost connection to the display '%s';\n"
|
||||
"most likely the X server was shut down or you killed/destroyed\n"
|
||||
"the window manager.\n"),
|
||||
display->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_warning (_("Fatal IO error %d (%s) on display '%s'.\n"),
|
||||
errno, g_strerror (errno),
|
||||
display->name);
|
||||
}
|
||||
|
||||
/* Xlib would force an exit anyhow */
|
||||
exit (1);
|
||||
|
||||
return 0;
|
||||
return gdk_error_trap_pop ();
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
window->rect.x,
|
||||
window->rect.y);
|
||||
/* FIXME handle this error */
|
||||
meta_error_trap_pop (window->display, FALSE);
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
/* stick frame to the window */
|
||||
window->frame = frame;
|
||||
@@ -217,7 +217,7 @@ meta_window_destroy_frame (MetaWindow *window)
|
||||
*/
|
||||
window->frame->rect.x,
|
||||
window->frame->rect.y);
|
||||
meta_error_trap_pop (window->display, FALSE);
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
meta_ui_destroy_frame_window (window->screen->ui, frame->xwindow);
|
||||
|
||||
@@ -276,7 +276,7 @@ meta_frame_get_flags (MetaFrame *frame)
|
||||
if (META_WINDOW_ALLOWS_VERTICAL_RESIZE (frame->window))
|
||||
flags |= META_FRAME_ALLOWS_VERTICAL_RESIZE;
|
||||
|
||||
if (frame->window->has_focus)
|
||||
if (meta_window_appears_focused (frame->window))
|
||||
flags |= META_FRAME_HAS_FOCUS;
|
||||
|
||||
if (frame->window->shaded)
|
||||
|
||||
@@ -104,6 +104,10 @@ meta_group_unref (MetaGroup *group)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_get_group: (skip)
|
||||
*
|
||||
*/
|
||||
MetaGroup*
|
||||
meta_window_get_group (MetaWindow *window)
|
||||
{
|
||||
@@ -198,6 +202,10 @@ meta_window_shutdown_group (MetaWindow *window)
|
||||
remove_window_from_group (window);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_lookup_group: (skip)
|
||||
*
|
||||
*/
|
||||
MetaGroup*
|
||||
meta_display_lookup_group (MetaDisplay *display,
|
||||
Window group_leader)
|
||||
@@ -213,6 +221,12 @@ meta_display_lookup_group (MetaDisplay *display,
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_group_list_windows:
|
||||
* @group: A #MetaGroup
|
||||
*
|
||||
* Returns: (transfer container) (element-type Meta.Window): List of windows
|
||||
*/
|
||||
GSList*
|
||||
meta_group_list_windows (MetaGroup *group)
|
||||
{
|
||||
@@ -263,6 +277,10 @@ meta_group_get_startup_id (MetaGroup *group)
|
||||
return group->startup_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_group_property_notify: (skip)
|
||||
*
|
||||
*/
|
||||
gboolean
|
||||
meta_group_property_notify (MetaGroup *group,
|
||||
XEvent *event)
|
||||
|
||||
@@ -241,7 +241,7 @@ read_rgb_icon (MetaDisplay *display,
|
||||
0, G_MAXLONG,
|
||||
False, XA_CARDINAL, &type, &format, &nitems,
|
||||
&bytes_after, &data);
|
||||
err = meta_error_trap_pop_with_return (display, TRUE);
|
||||
err = meta_error_trap_pop_with_return (display);
|
||||
|
||||
if (err != Success ||
|
||||
result != Success)
|
||||
@@ -394,21 +394,19 @@ try_pixmap_and_mask (MetaDisplay *display,
|
||||
|
||||
get_pixmap_geometry (display, src_pixmap, &w, &h, NULL);
|
||||
|
||||
unscaled = meta_gdk_pixbuf_get_from_pixmap (NULL,
|
||||
src_pixmap,
|
||||
0, 0, 0, 0,
|
||||
unscaled = meta_gdk_pixbuf_get_from_pixmap (src_pixmap,
|
||||
0, 0,
|
||||
w, h);
|
||||
|
||||
if (unscaled && src_mask != None)
|
||||
{
|
||||
get_pixmap_geometry (display, src_mask, &w, &h, NULL);
|
||||
mask = meta_gdk_pixbuf_get_from_pixmap (NULL,
|
||||
src_mask,
|
||||
0, 0, 0, 0,
|
||||
mask = meta_gdk_pixbuf_get_from_pixmap (src_mask,
|
||||
0, 0,
|
||||
w, h);
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
if (mask)
|
||||
{
|
||||
@@ -484,7 +482,7 @@ get_kwm_win_icon (MetaDisplay *display,
|
||||
&bytes_after, &data);
|
||||
icons = (Pixmap *)data;
|
||||
|
||||
err = meta_error_trap_pop_with_return (display, TRUE);
|
||||
err = meta_error_trap_pop_with_return (display);
|
||||
if (err != Success ||
|
||||
result != Success)
|
||||
return;
|
||||
|
||||
@@ -470,7 +470,7 @@ regrab_key_bindings (MetaDisplay *display)
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
g_slist_free (windows);
|
||||
}
|
||||
@@ -499,14 +499,25 @@ display_get_keybinding (MetaDisplay *display,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static MetaKeyBindingAction
|
||||
display_get_keybinding_action (MetaDisplay *display,
|
||||
unsigned int keysym,
|
||||
unsigned int keycode,
|
||||
unsigned long mask)
|
||||
/**
|
||||
* meta_display_get_keybinding_action:
|
||||
* @display: A #MetaDisplay
|
||||
* @keycode: Raw keycode
|
||||
* @mask: Event mask
|
||||
*
|
||||
* Returns: The action that should be taken for the given key, or
|
||||
* %META_KEYBINDING_ACTION_NONE.
|
||||
*/
|
||||
MetaKeyBindingAction
|
||||
meta_display_get_keybinding_action (MetaDisplay *display,
|
||||
unsigned int keycode,
|
||||
unsigned long mask)
|
||||
{
|
||||
MetaKeyBinding *binding;
|
||||
KeySym keysym;
|
||||
|
||||
keysym = XKeycodeToKeysym (display->xdisplay, keycode, 0);
|
||||
mask = mask & 0xff & ~display->ignored_modifier_mask;
|
||||
binding = display_get_keybinding (display, keysym, keycode, mask);
|
||||
|
||||
if (binding)
|
||||
@@ -689,7 +700,7 @@ meta_change_keygrab (MetaDisplay *display,
|
||||
{
|
||||
int result;
|
||||
|
||||
result = meta_error_trap_pop_with_return (display, FALSE);
|
||||
result = meta_error_trap_pop_with_return (display);
|
||||
|
||||
if (grab && result != Success)
|
||||
{
|
||||
@@ -705,7 +716,7 @@ meta_change_keygrab (MetaDisplay *display,
|
||||
++ignored_mask;
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -747,7 +758,7 @@ grab_keys (MetaKeyBinding *bindings,
|
||||
++i;
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -766,14 +777,14 @@ ungrab_all_keys (MetaDisplay *display,
|
||||
{
|
||||
int result;
|
||||
|
||||
result = meta_error_trap_pop_with_return (display, FALSE);
|
||||
result = meta_error_trap_pop_with_return (display);
|
||||
|
||||
if (result != Success)
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Ungrabbing all keys on 0x%lx failed\n", xwindow);
|
||||
}
|
||||
else
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -905,7 +916,7 @@ grab_keyboard (MetaDisplay *display,
|
||||
|
||||
if (grab_status != GrabSuccess)
|
||||
{
|
||||
meta_error_trap_pop_with_return (display, TRUE);
|
||||
meta_error_trap_pop_with_return (display);
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"XGrabKeyboard() returned failure status %s time %u\n",
|
||||
grab_status_to_string (grab_status),
|
||||
@@ -914,7 +925,7 @@ grab_keyboard (MetaDisplay *display,
|
||||
}
|
||||
else
|
||||
{
|
||||
result = meta_error_trap_pop_with_return (display, TRUE);
|
||||
result = meta_error_trap_pop_with_return (display);
|
||||
if (result != Success)
|
||||
{
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
@@ -937,7 +948,7 @@ ungrab_keyboard (MetaDisplay *display, guint32 timestamp)
|
||||
"Ungrabbing keyboard with timestamp %u\n",
|
||||
timestamp);
|
||||
XUngrabKeyboard (display->xdisplay, timestamp);
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -1362,8 +1373,7 @@ meta_display_process_key_event (MetaDisplay *display,
|
||||
return FALSE; /* event window is destroyed */
|
||||
|
||||
/* ignore key events on popup menus and such. */
|
||||
if (window == NULL &&
|
||||
meta_ui_window_is_widget (screen->ui, event->xany.window))
|
||||
if (meta_ui_window_is_widget (screen->ui, event->xany.window))
|
||||
return FALSE;
|
||||
|
||||
/* window may be NULL */
|
||||
@@ -2047,15 +2057,11 @@ process_tab_grab (MetaDisplay *display,
|
||||
action = META_KEYBINDING_ACTION_NONE;
|
||||
|
||||
/*
|
||||
* There are currently two different ways of customizing Alt-Tab, you can either
|
||||
* provide a replacement AltTabHandler object, or you can hook into the keybindings
|
||||
* meta_keybindings_set_custom_handler() and call meta_display_begin_grab_op()
|
||||
* yourself with one of the "tabbing" grab ops META_GRAB_OP_KEYBOARD_TABBING_NORMAL,
|
||||
* etc. See meta_display_process_key_event() for the complete list. If screen->tab_handler
|
||||
* is NULL, the latter mechanism is being used. We skip most of our normal
|
||||
* processing and just make sure that the right custom handlers get called.
|
||||
* If there is no tab_pop up object, i.e., there is some custom handler
|
||||
* implementing Alt+Tab & Co., we call this custom handler; we do not
|
||||
* mess about with the grab, as that is up to the handler to deal with.
|
||||
*/
|
||||
if (!screen->tab_handler)
|
||||
if (!screen->tab_popup)
|
||||
{
|
||||
if (event->type == KeyRelease)
|
||||
{
|
||||
@@ -2102,6 +2108,16 @@ process_tab_grab (MetaDisplay *display,
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case META_KEYBINDING_ACTION_NONE:
|
||||
{
|
||||
/*
|
||||
* If this is simply user pressing the Shift key, we do not want
|
||||
* to cancel the grab.
|
||||
*/
|
||||
if (is_modifier (display, event->xkey.keycode))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2553,7 +2569,7 @@ handle_move_to_corner_backend (MetaDisplay *display,
|
||||
int new_x, new_y;
|
||||
int frame_width, frame_height;
|
||||
|
||||
meta_window_get_work_area_all_xineramas (window, &work_area);
|
||||
meta_window_get_work_area_all_monitors (window, &work_area);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
meta_window_get_position (window, &orig_x, &orig_y);
|
||||
|
||||
@@ -2685,7 +2701,7 @@ handle_move_to_center (MetaDisplay *display,
|
||||
int orig_x, orig_y;
|
||||
int frame_width, frame_height;
|
||||
|
||||
meta_window_get_work_area_all_xineramas (window, &work_area);
|
||||
meta_window_get_work_area_all_monitors (window, &work_area);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
meta_window_get_position (window, &orig_x, &orig_y);
|
||||
|
||||
@@ -2760,10 +2776,9 @@ process_workspace_switch_grab (MetaDisplay *display,
|
||||
MetaWorkspace *target_workspace;
|
||||
MetaKeyBindingAction action;
|
||||
|
||||
action = display_get_keybinding_action (display,
|
||||
keysym,
|
||||
event->xkey.keycode,
|
||||
display->grab_mask);
|
||||
action = meta_display_get_keybinding_action (display,
|
||||
event->xkey.keycode,
|
||||
display->grab_mask);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
@@ -2883,7 +2898,7 @@ handle_panel (MetaDisplay *display,
|
||||
StructureNotifyMask,
|
||||
(XEvent*) &ev);
|
||||
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3530,6 +3545,10 @@ meta_keybindings_set_custom_handler (const gchar *name,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_keybindings_switch_window: (skip)
|
||||
*
|
||||
*/
|
||||
void
|
||||
meta_keybindings_switch_window (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
|
||||
101
src/core/main.c
101
src/core/main.c
@@ -68,13 +68,14 @@
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
#ifdef HAVE_INTROSPECTION
|
||||
#include <girepository.h>
|
||||
#include "compositor/mutter-plugin-manager.h"
|
||||
#include "compositor/meta-plugin-manager.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -124,11 +125,13 @@ log_handler (const gchar *log_domain,
|
||||
static void
|
||||
version (void)
|
||||
{
|
||||
const int latest_year = 2010;
|
||||
|
||||
g_print (_("mutter %s\n"
|
||||
"Copyright (C) 2001-2008 Havoc Pennington, Red Hat, Inc., and others\n"
|
||||
"Copyright (C) 2001-%d Havoc Pennington, Red Hat, Inc., and others\n"
|
||||
"This is free software; see the source for copying conditions.\n"
|
||||
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"),
|
||||
VERSION);
|
||||
VERSION, latest_year);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
@@ -226,6 +229,7 @@ typedef struct
|
||||
gboolean sync;
|
||||
gboolean composite;
|
||||
gboolean no_composite;
|
||||
gboolean no_force_fullscreen;
|
||||
gboolean no_tab_popup;
|
||||
gchar *introspect;
|
||||
} MetaArguments;
|
||||
@@ -304,6 +308,12 @@ meta_parse_options (int *argc, char ***argv,
|
||||
N_("Turn compositing off"),
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"no-force-fullscreen", 0, COMPOSITE_OPTS_FLAGS, G_OPTION_ARG_NONE,
|
||||
&my_args.no_force_fullscreen,
|
||||
N_("Don't make fullscreen windows that are maximized and have no decorations"),
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"mutter-plugins", 0, 0, G_OPTION_ARG_STRING,
|
||||
&my_args.mutter_plugins,
|
||||
@@ -331,6 +341,7 @@ meta_parse_options (int *argc, char ***argv,
|
||||
ctx = g_option_context_new (NULL);
|
||||
g_option_context_add_main_entries (ctx, options, "mutter");
|
||||
g_option_context_add_group (ctx, clutter_get_option_group_without_init ());
|
||||
g_option_context_add_group (ctx, cogl_get_option_group ());
|
||||
|
||||
if (!g_option_context_parse (ctx, argc, argv, &error))
|
||||
{
|
||||
@@ -390,7 +401,7 @@ static GSourceFuncs event_funcs = {
|
||||
static void
|
||||
meta_clutter_init (GOptionContext *ctx, int *argc, char ***argv)
|
||||
{
|
||||
clutter_x11_set_display (gdk_display);
|
||||
clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
||||
clutter_x11_disable_event_retrieval ();
|
||||
|
||||
if (CLUTTER_INIT_SUCCESS == clutter_init (argc, argv))
|
||||
@@ -436,37 +447,28 @@ meta_finalize (void)
|
||||
meta_session_shutdown ();
|
||||
}
|
||||
|
||||
static int sigterm_pipe_fds[2] = { -1, -1 };
|
||||
|
||||
static void
|
||||
sigterm_handler (int signum)
|
||||
{
|
||||
meta_finalize ();
|
||||
|
||||
exit (meta_exit_code);
|
||||
}
|
||||
|
||||
static guint sigchld_signal_id = 0;
|
||||
|
||||
static void
|
||||
sigchld_handler (int signum, siginfo_t *info, void *context)
|
||||
{
|
||||
int stat;
|
||||
|
||||
if (info->si_code == CLD_EXITED)
|
||||
if (sigterm_pipe_fds[1] >= 0)
|
||||
{
|
||||
g_signal_emit (sigchld_nexus, sigchld_signal_id, 0,
|
||||
info->si_status,
|
||||
GINT_TO_POINTER (info->si_pid));
|
||||
int dummy;
|
||||
|
||||
dummy = write (sigterm_pipe_fds[1], "", 1);
|
||||
close (sigterm_pipe_fds[1]);
|
||||
sigterm_pipe_fds[1] = -1;
|
||||
}
|
||||
|
||||
g_signal_handlers_disconnect_matched (sigchld_nexus,
|
||||
G_SIGNAL_MATCH_DATA,
|
||||
sigchld_signal_id,
|
||||
0, NULL, NULL,
|
||||
GINT_TO_POINTER (info->si_pid));
|
||||
|
||||
waitpid (info->si_pid, &stat, WNOHANG);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
on_sigterm (void)
|
||||
{
|
||||
meta_quit (META_EXIT_SUCCESS);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is where the story begins. It parses commandline options and
|
||||
* environment variables, sets up the screen, hands control off to
|
||||
@@ -489,8 +491,9 @@ main (int argc, char **argv)
|
||||
"Pango", "GLib-GObject", "GThread"
|
||||
};
|
||||
guint i;
|
||||
GIOChannel *channel;
|
||||
GOptionContext *ctx;
|
||||
|
||||
|
||||
if (!g_thread_supported ())
|
||||
g_thread_init (NULL);
|
||||
|
||||
@@ -512,29 +515,21 @@ main (int argc, char **argv)
|
||||
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));
|
||||
|
||||
sigchld_nexus = g_object_new (META_TYPE_NEXUS, NULL);
|
||||
|
||||
sigchld_signal_id =
|
||||
g_signal_new ("sigchld", META_TYPE_NEXUS,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
g_cclosure_marshal_VOID__UINT_POINTER,
|
||||
G_TYPE_NONE,
|
||||
2,
|
||||
G_TYPE_UINT, G_TYPE_POINTER);
|
||||
|
||||
act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
|
||||
act.sa_handler = SIG_DFL;
|
||||
act.sa_sigaction = &sigchld_handler;
|
||||
if (sigaction (SIGCHLD, &act, NULL) < 0)
|
||||
g_printerr ("Failed to register SIGCHLD handler: %s\n",
|
||||
g_strerror (errno));
|
||||
|
||||
if (g_getenv ("MUTTER_VERBOSE"))
|
||||
meta_set_verbose (TRUE);
|
||||
if (g_getenv ("MUTTER_DEBUG"))
|
||||
@@ -591,8 +586,8 @@ main (int argc, char **argv)
|
||||
* is initialized at this point, and we don't plan to run any real
|
||||
* plugin code.
|
||||
*/
|
||||
MutterPluginManager *mgr = mutter_plugin_manager_new (NULL);
|
||||
if (!mutter_plugin_manager_load (mgr))
|
||||
MetaPluginManager *mgr = meta_plugin_manager_get_default ();
|
||||
if (!meta_plugin_manager_load (mgr))
|
||||
g_critical ("failed to load plugins");
|
||||
}
|
||||
if (!g_irepository_dump (meta_args.introspect, &error))
|
||||
@@ -628,9 +623,6 @@ main (int argc, char **argv)
|
||||
|
||||
g_option_context_free (ctx);
|
||||
|
||||
/* must be after UI init so we can override GDK handlers */
|
||||
meta_errors_init ();
|
||||
|
||||
/* Load prefs */
|
||||
meta_prefs_init ();
|
||||
meta_prefs_add_listener (prefs_changed_callback, NULL);
|
||||
@@ -716,6 +708,9 @@ main (int argc, char **argv)
|
||||
if (meta_args.composite || meta_args.no_composite)
|
||||
meta_prefs_set_compositing_manager (meta_args.composite);
|
||||
|
||||
if (meta_args.no_force_fullscreen)
|
||||
meta_prefs_set_force_fullscreen (FALSE);
|
||||
|
||||
if (meta_args.no_tab_popup)
|
||||
{
|
||||
meta_prefs_override_no_tab_popup (TRUE);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "boxes-private.h"
|
||||
#include "place.h"
|
||||
#include "workspace.h"
|
||||
#include "prefs.h"
|
||||
@@ -104,7 +105,7 @@ find_next_cascade (MetaWindow *window,
|
||||
int window_width, window_height;
|
||||
int cascade_stage;
|
||||
MetaRectangle work_area;
|
||||
const MetaXineramaScreenInfo* current;
|
||||
const MetaMonitorInfo* current;
|
||||
|
||||
sorted = g_list_copy (windows);
|
||||
sorted = g_list_sort (sorted, northwestcmp);
|
||||
@@ -135,8 +136,8 @@ find_next_cascade (MetaWindow *window,
|
||||
* of NW corner of window frame.
|
||||
*/
|
||||
|
||||
current = meta_screen_get_current_xinerama (window->screen);
|
||||
meta_window_get_work_area_for_xinerama (window, current->number, &work_area);
|
||||
current = meta_screen_get_current_monitor (window->screen);
|
||||
meta_window_get_work_area_for_monitor (window, current->number, &work_area);
|
||||
|
||||
cascade_x = MAX (0, work_area.x);
|
||||
cascade_y = MAX (0, work_area.y);
|
||||
@@ -257,7 +258,7 @@ find_most_freespace (MetaWindow *window,
|
||||
frame_size_left = fgeom ? fgeom->left_width : 0;
|
||||
frame_size_top = fgeom ? fgeom->top_height : 0;
|
||||
|
||||
meta_window_get_work_area_current_xinerama (focus_window, &work_area);
|
||||
meta_window_get_work_area_current_monitor (focus_window, &work_area);
|
||||
meta_window_get_outer_rect (focus_window, &avoid);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
|
||||
@@ -508,7 +509,7 @@ find_first_fit (MetaWindow *window,
|
||||
MetaFrameGeometry *fgeom,
|
||||
/* visible windows on relevant workspaces */
|
||||
GList *windows,
|
||||
int xinerama,
|
||||
int monitor,
|
||||
int x,
|
||||
int y,
|
||||
int *new_x,
|
||||
@@ -551,16 +552,16 @@ find_first_fit (MetaWindow *window,
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
{
|
||||
char xinerama_location_string[RECT_LENGTH];
|
||||
meta_rectangle_to_string (&window->screen->xinerama_infos[xinerama].rect,
|
||||
xinerama_location_string);
|
||||
char monitor_location_string[RECT_LENGTH];
|
||||
meta_rectangle_to_string (&window->screen->monitor_infos[monitor].rect,
|
||||
monitor_location_string);
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Natural xinerama is %s\n",
|
||||
xinerama_location_string);
|
||||
"Natural monitor is %s\n",
|
||||
monitor_location_string);
|
||||
}
|
||||
#endif
|
||||
|
||||
meta_window_get_work_area_for_xinerama (window, xinerama, &work_area);
|
||||
meta_window_get_work_area_for_monitor (window, monitor, &work_area);
|
||||
|
||||
center_tile_rect_in_area (&rect, &work_area);
|
||||
|
||||
@@ -658,7 +659,7 @@ meta_window_place (MetaWindow *window,
|
||||
int *new_y)
|
||||
{
|
||||
GList *windows;
|
||||
const MetaXineramaScreenInfo *xi;
|
||||
const MetaMonitorInfo *xi;
|
||||
|
||||
/* frame member variables should NEVER be used in here, only
|
||||
* MetaFrameGeometry. But remember fgeom == NULL
|
||||
@@ -810,11 +811,11 @@ meta_window_place (MetaWindow *window,
|
||||
window->type == META_WINDOW_MODAL_DIALOG ||
|
||||
window->type == META_WINDOW_SPLASHSCREEN)
|
||||
{
|
||||
/* Center on current xinerama (i.e. on current monitor) */
|
||||
/* Center on current monitor */
|
||||
int w, h;
|
||||
|
||||
/* Warning, this function is a round trip! */
|
||||
xi = meta_screen_get_current_xinerama (window->screen);
|
||||
xi = meta_screen_get_current_monitor (window->screen);
|
||||
|
||||
w = xi->rect.width;
|
||||
h = xi->rect.height;
|
||||
@@ -825,7 +826,7 @@ meta_window_place (MetaWindow *window,
|
||||
x += xi->rect.x;
|
||||
y += xi->rect.y;
|
||||
|
||||
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on screen %d xinerama %d\n",
|
||||
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on screen %d monitor %d\n",
|
||||
window->desc, window->screen->number, xi->number);
|
||||
|
||||
goto done_check_denied_focus;
|
||||
@@ -859,7 +860,7 @@ meta_window_place (MetaWindow *window,
|
||||
}
|
||||
|
||||
/* Warning, this is a round trip! */
|
||||
xi = meta_screen_get_current_xinerama (window->screen);
|
||||
xi = meta_screen_get_current_monitor (window->screen);
|
||||
|
||||
/* "Origin" placement algorithm */
|
||||
x = xi->rect.x;
|
||||
@@ -880,9 +881,9 @@ meta_window_place (MetaWindow *window,
|
||||
MetaRectangle workarea;
|
||||
MetaRectangle outer;
|
||||
|
||||
meta_window_get_work_area_for_xinerama (window,
|
||||
xi->number,
|
||||
&workarea);
|
||||
meta_window_get_work_area_for_monitor (window,
|
||||
xi->number,
|
||||
&workarea);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
|
||||
/* If the window is bigger than the screen, then automaximize. Do NOT
|
||||
|
||||
586
src/core/prefs.c
586
src/core/prefs.c
@@ -27,6 +27,7 @@
|
||||
#include "prefs.h"
|
||||
#include "ui.h"
|
||||
#include "util.h"
|
||||
#include "compositor/meta-plugin-manager.h"
|
||||
#ifdef HAVE_GCONF
|
||||
#include <gconf/gconf-client.h>
|
||||
#endif
|
||||
@@ -52,6 +53,7 @@
|
||||
#define KEY_COMPOSITOR "/apps/metacity/general/compositing_manager"
|
||||
#define KEY_GNOME_ACCESSIBILITY "/desktop/gnome/interface/accessibility"
|
||||
|
||||
#define KEY_COMMAND_DIRECTORY "/apps/metacity/keybinding_commands"
|
||||
#define KEY_COMMAND_PREFIX "/apps/metacity/keybinding_commands/command_"
|
||||
|
||||
#define KEY_TERMINAL_DIR "/desktop/gnome/applications/terminal"
|
||||
@@ -62,6 +64,7 @@
|
||||
#define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings"
|
||||
#define KEY_LIST_BINDINGS_SUFFIX "_list"
|
||||
|
||||
#define KEY_WORKSPACE_NAME_DIRECTORY "/apps/metacity/workspace_names"
|
||||
#define KEY_WORKSPACE_NAME_PREFIX "/apps/metacity/workspace_names/name_"
|
||||
|
||||
#define KEY_CLUTTER_PLUGINS "/apps/mutter/general/clutter_plugins"
|
||||
@@ -83,6 +86,7 @@ static MetaVirtualModifier mouse_button_mods = Mod1Mask;
|
||||
static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK;
|
||||
static MetaFocusNewWindows focus_new_windows = META_FOCUS_NEW_WINDOWS_SMART;
|
||||
static gboolean raise_on_click = TRUE;
|
||||
static gboolean attach_modal_dialogs = FALSE;
|
||||
static char* current_theme = NULL;
|
||||
static int num_workspaces = 4;
|
||||
static MetaActionTitlebar action_double_click_titlebar = META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE;
|
||||
@@ -100,6 +104,8 @@ static char *cursor_theme = NULL;
|
||||
static int cursor_size = 24;
|
||||
static gboolean compositing_manager = FALSE;
|
||||
static gboolean resize_with_right_button = FALSE;
|
||||
static gboolean side_by_side_tiling = FALSE;
|
||||
static gboolean force_fullscreen = TRUE;
|
||||
|
||||
static MetaVisualBellType visual_bell_type = META_VISUAL_BELL_FULLSCREEN_FLASH;
|
||||
static MetaButtonLayout button_layout;
|
||||
@@ -121,18 +127,30 @@ static gboolean no_tab_popup = FALSE;
|
||||
#ifdef HAVE_GCONF
|
||||
static gboolean handle_preference_update_enum (const gchar *key, GConfValue *value);
|
||||
|
||||
static gboolean update_key_binding (const char *name,
|
||||
static char *binding_name (const char *gconf_key);
|
||||
|
||||
static gboolean update_key_binding (const char *key,
|
||||
const char *value);
|
||||
static gboolean find_and_update_list_binding (MetaKeyPref *bindings,
|
||||
const char *name,
|
||||
GSList *value);
|
||||
static gboolean update_key_list_binding (const char *name,
|
||||
GSList *value);
|
||||
typedef enum
|
||||
{
|
||||
META_LIST_OF_STRINGS,
|
||||
META_LIST_OF_GCONFVALUE_STRINGS
|
||||
} MetaStringListType;
|
||||
|
||||
static gboolean find_and_update_list_binding (MetaKeyPref *bindings,
|
||||
const char *key,
|
||||
GSList *value,
|
||||
MetaStringListType type_of_value);
|
||||
static gboolean update_key_list_binding (const char *key,
|
||||
GSList *value,
|
||||
MetaStringListType type_of_value);
|
||||
static gboolean update_command (const char *name,
|
||||
const char *value);
|
||||
static gboolean update_workspace_name (const char *name,
|
||||
const char *value);
|
||||
|
||||
static void notify_new_value (const char *key,
|
||||
GConfValue *value);
|
||||
static void change_notify (GConfClient *client,
|
||||
guint cnxn_id,
|
||||
GConfEntry *entry,
|
||||
@@ -142,14 +160,8 @@ static char* gconf_key_for_workspace_name (int i);
|
||||
|
||||
static void queue_changed (MetaPreference pref);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_LIST_OF_STRINGS,
|
||||
META_LIST_OF_GCONFVALUE_STRINGS
|
||||
} MetaStringListType;
|
||||
|
||||
static gboolean update_list_binding (MetaKeyPref *binding,
|
||||
GSList *value,
|
||||
static gboolean update_list_binding (MetaKeyPref *binding,
|
||||
GSList *value,
|
||||
MetaStringListType type_of_value);
|
||||
|
||||
static void cleanup_error (GError **error);
|
||||
@@ -221,7 +233,12 @@ static GConfEnumStringPair symtab_titlebar_action[] =
|
||||
{ 0, NULL },
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Note that 'gchar *key' is the first element of all these structures;
|
||||
* we count on that below in key_is_used and do_override.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The details of one preference which is constrained to be
|
||||
* one of a small number of string values-- in other words,
|
||||
* an enumeration.
|
||||
@@ -234,21 +251,6 @@ static GConfEnumStringPair symtab_titlebar_action[] =
|
||||
* been outweighed by the bugs caused when the ordering of the enum
|
||||
* strings got out of sync with the actual enum statement. Also,
|
||||
* there is existing library code to use this kind of symbol tables.
|
||||
*
|
||||
* Other things we might consider doing to clean this up in the
|
||||
* future include:
|
||||
*
|
||||
* - most of the keys begin with the same prefix, and perhaps we
|
||||
* could assume it if they don't start with a slash
|
||||
*
|
||||
* - there are several cases where a single identifier could be used
|
||||
* to generate an entire entry, and perhaps this could be done
|
||||
* with a macro. (This would reduce clarity, however, and is
|
||||
* probably a bad thing.)
|
||||
*
|
||||
* - these types all begin with a gchar* (and contain a MetaPreference)
|
||||
* and we can factor out the repeated code in the handlers by taking
|
||||
* advantage of this using some kind of union arrangement.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
@@ -361,6 +363,11 @@ static MetaEnumPreference preferences_enum[] =
|
||||
|
||||
static MetaBoolPreference preferences_bool[] =
|
||||
{
|
||||
{ "/apps/mutter/general/attach_modal_dialogs",
|
||||
META_PREF_ATTACH_MODAL_DIALOGS,
|
||||
&attach_modal_dialogs,
|
||||
TRUE,
|
||||
},
|
||||
{ "/apps/metacity/general/raise_on_click",
|
||||
META_PREF_RAISE_ON_CLICK,
|
||||
&raise_on_click,
|
||||
@@ -416,6 +423,11 @@ static MetaBoolPreference preferences_bool[] =
|
||||
&resize_with_right_button,
|
||||
FALSE,
|
||||
},
|
||||
{ "/apps/metacity/general/side_by_side_tiling",
|
||||
META_PREF_SIDE_BY_SIDE_TILING,
|
||||
&side_by_side_tiling,
|
||||
FALSE,
|
||||
},
|
||||
{ "/apps/mutter/general/live_hidden_windows",
|
||||
META_PREF_LIVE_HIDDEN_WINDOWS,
|
||||
&live_hidden_windows,
|
||||
@@ -489,6 +501,20 @@ static MetaIntPreference preferences_int[] =
|
||||
{ NULL, 0, NULL, 0, 0, 0, },
|
||||
};
|
||||
|
||||
/*
|
||||
* This is used to keep track of preferences that have been
|
||||
* repointed to a different GConf key location; we modify the
|
||||
* preferences arrays directly, but we also need to remember
|
||||
* what we have done to handle subsequent overrides correctly.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
gchar *original_key;
|
||||
gchar *new_key;
|
||||
} MetaPrefsOverriddenKey;
|
||||
|
||||
static GSList *overridden_keys;
|
||||
|
||||
static void
|
||||
handle_preference_init_enum (void)
|
||||
{
|
||||
@@ -872,6 +898,10 @@ handle_preference_update_int (const gchar *key, GConfValue *value)
|
||||
/* Listeners. */
|
||||
/****************************************************************************/
|
||||
|
||||
/**
|
||||
* meta_prefs_add_listener: (skip)
|
||||
*
|
||||
*/
|
||||
void
|
||||
meta_prefs_add_listener (MetaPrefsChangedFunc func,
|
||||
gpointer data)
|
||||
@@ -885,6 +915,10 @@ meta_prefs_add_listener (MetaPrefsChangedFunc func,
|
||||
listeners = g_list_prepend (listeners, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_prefs_remove_listener: (skip)
|
||||
*
|
||||
*/
|
||||
void
|
||||
meta_prefs_remove_listener (MetaPrefsChangedFunc func,
|
||||
gpointer data)
|
||||
@@ -1024,6 +1058,7 @@ meta_prefs_init (void)
|
||||
#ifdef HAVE_GCONF
|
||||
GError *err = NULL;
|
||||
gchar **gconf_dir_cursor;
|
||||
MetaPluginManager *plugin_manager;
|
||||
|
||||
if (default_client != NULL)
|
||||
return;
|
||||
@@ -1042,12 +1077,7 @@ meta_prefs_init (void)
|
||||
cleanup_error (&err);
|
||||
}
|
||||
|
||||
/* Pick up initial values. */
|
||||
|
||||
handle_preference_init_enum ();
|
||||
handle_preference_init_bool ();
|
||||
handle_preference_init_string ();
|
||||
handle_preference_init_int ();
|
||||
/* The plugin list is special and needs to be handled first */
|
||||
|
||||
if (!clutter_plugins_overridden)
|
||||
clutter_plugins = gconf_client_get_list (default_client, KEY_CLUTTER_PLUGINS,
|
||||
@@ -1055,6 +1085,18 @@ meta_prefs_init (void)
|
||||
|
||||
cleanup_error (&err);
|
||||
|
||||
/* We now initialize plugins so that they can override any preference locations */
|
||||
|
||||
plugin_manager = meta_plugin_manager_get_default ();
|
||||
meta_plugin_manager_load (plugin_manager);
|
||||
|
||||
/* Pick up initial values. */
|
||||
|
||||
handle_preference_init_enum ();
|
||||
handle_preference_init_bool ();
|
||||
handle_preference_init_string ();
|
||||
handle_preference_init_int ();
|
||||
|
||||
/* @@@ Is there any reason we don't do the add_dir here? */
|
||||
for (gconf_dir_cursor=gconf_dirs_we_are_interested_in;
|
||||
*gconf_dir_cursor!=NULL;
|
||||
@@ -1087,6 +1129,160 @@ meta_prefs_init (void)
|
||||
init_workspace_names ();
|
||||
}
|
||||
|
||||
/* This count on the key being the first element of the
|
||||
* preference structure */
|
||||
static gboolean
|
||||
key_is_used (void *prefs,
|
||||
size_t pref_size,
|
||||
const char *new_key)
|
||||
{
|
||||
void *p = prefs;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
char **key = p;
|
||||
if (*key == NULL)
|
||||
break;
|
||||
|
||||
if (strcmp (*key, new_key) == 0)
|
||||
return TRUE;
|
||||
|
||||
p = (guchar *)p + pref_size;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_override (void *prefs,
|
||||
size_t pref_size,
|
||||
const char *search_key,
|
||||
char *new_key)
|
||||
{
|
||||
void *p = prefs;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
char **key = p;
|
||||
if (*key == NULL)
|
||||
break;
|
||||
|
||||
if (strcmp (*key, search_key) == 0)
|
||||
{
|
||||
*key = new_key;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
p = (guchar *)p + pref_size;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_prefs_override_preference_location
|
||||
* @original_key: the normal Metacity preference location
|
||||
* @new_key: the Metacity preference location to use instead.
|
||||
*
|
||||
* Substitute a different location to use instead of a standard Metacity
|
||||
* GConf key location. This might be used if a plugin expected a different
|
||||
* value for some preference than the Metacity default. While this function
|
||||
* can be called at any point, this function should generally be called
|
||||
* in a plugin's constructor, rather than in its start() method so the
|
||||
* preference isn't first loaded with one value then changed to another
|
||||
* value.
|
||||
*/
|
||||
void
|
||||
meta_prefs_override_preference_location (const char *original_key,
|
||||
const char *new_key)
|
||||
{
|
||||
const char *search_key;
|
||||
char *new_key_copy;
|
||||
gboolean found;
|
||||
MetaPrefsOverriddenKey *overridden;
|
||||
GSList *tmp;
|
||||
|
||||
/* Merge identical overrides, this isn't an error */
|
||||
for (tmp = overridden_keys; tmp; tmp = tmp->next)
|
||||
{
|
||||
MetaPrefsOverriddenKey *tmp_overridden = tmp->data;
|
||||
if (strcmp (tmp_overridden->original_key, original_key) == 0 &&
|
||||
strcmp (tmp_overridden->new_key, new_key) == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
/* We depend on a unique mapping from GConf key to preference, so
|
||||
* enforce this */
|
||||
|
||||
if (key_is_used (preferences_enum, sizeof(MetaEnumPreference), new_key) ||
|
||||
key_is_used (preferences_bool, sizeof(MetaBoolPreference), new_key) ||
|
||||
key_is_used (preferences_string, sizeof(MetaStringPreference), new_key) ||
|
||||
key_is_used (preferences_int, sizeof(MetaIntPreference), new_key))
|
||||
{
|
||||
meta_warning (_("GConf key %s is already in use and can't be used to override %s\n"),
|
||||
new_key, original_key);
|
||||
|
||||
}
|
||||
|
||||
new_key_copy = g_strdup (new_key);
|
||||
|
||||
search_key = original_key;
|
||||
overridden = NULL;
|
||||
|
||||
for (tmp = overridden_keys; tmp; tmp = tmp->next)
|
||||
{
|
||||
MetaPrefsOverriddenKey *tmp_overridden = tmp->data;
|
||||
if (strcmp (overridden->original_key, original_key) == 0)
|
||||
{
|
||||
overridden = tmp_overridden;
|
||||
search_key = tmp_overridden->new_key;
|
||||
}
|
||||
}
|
||||
|
||||
found =
|
||||
do_override (preferences_enum, sizeof(MetaEnumPreference), search_key, new_key_copy) ||
|
||||
do_override (preferences_bool, sizeof(MetaBoolPreference), search_key, new_key_copy) ||
|
||||
do_override (preferences_string, sizeof(MetaStringPreference), search_key, new_key_copy) ||
|
||||
do_override (preferences_int, sizeof(MetaIntPreference), search_key, new_key_copy);
|
||||
if (found)
|
||||
{
|
||||
if (overridden)
|
||||
{
|
||||
g_free (overridden->new_key);
|
||||
overridden->new_key = new_key_copy;
|
||||
}
|
||||
else
|
||||
{
|
||||
overridden = g_slice_new (MetaPrefsOverriddenKey);
|
||||
overridden->original_key = g_strdup (original_key);
|
||||
overridden->new_key = new_key_copy;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GCONF
|
||||
if (default_client != NULL)
|
||||
{
|
||||
/* We're already initialized, so notify of a change */
|
||||
|
||||
GConfValue *value;
|
||||
GError *err = NULL;
|
||||
|
||||
value = gconf_client_get (default_client, new_key, &err);
|
||||
cleanup_error (&err);
|
||||
|
||||
notify_new_value (new_key, value);
|
||||
|
||||
if (value)
|
||||
gconf_value_free (value);
|
||||
}
|
||||
#endif /* HAVE_GCONF */
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_warning (_("Can't override GConf key, %s not found\n"), original_key);
|
||||
g_free (new_key_copy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Updates. */
|
||||
@@ -1102,6 +1298,23 @@ gboolean (*preference_update_handler[]) (const gchar*, GConfValue*) = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
notify_new_value (const char *key,
|
||||
GConfValue *value)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
/* FIXME: Use MetaGenericPreference and save a bit of code duplication */
|
||||
|
||||
while (preference_update_handler[i] != NULL)
|
||||
{
|
||||
if (preference_update_handler[i] (key, value))
|
||||
return;
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
change_notify (GConfClient *client,
|
||||
guint cnxn_id,
|
||||
@@ -1110,25 +1323,13 @@ change_notify (GConfClient *client,
|
||||
{
|
||||
const char *key;
|
||||
GConfValue *value;
|
||||
gint i=0;
|
||||
|
||||
key = gconf_entry_get_key (entry);
|
||||
value = gconf_entry_get_value (entry);
|
||||
|
||||
/* First, search for a handler that might know what to do. */
|
||||
|
||||
/* FIXME: When this is all working, since the first item in every
|
||||
* array is the gchar* of the key, there's no reason we can't
|
||||
* find the correct record for that key here and save code duplication.
|
||||
*/
|
||||
|
||||
while (preference_update_handler[i]!=NULL)
|
||||
{
|
||||
if (preference_update_handler[i] (key, value))
|
||||
goto out; /* Get rid of this eventually */
|
||||
|
||||
i++;
|
||||
}
|
||||
notify_new_value (key, value);
|
||||
|
||||
if (g_str_has_prefix (key, KEY_WINDOW_BINDINGS_PREFIX) ||
|
||||
g_str_has_prefix (key, KEY_SCREEN_BINDINGS_PREFIX))
|
||||
@@ -1146,7 +1347,7 @@ change_notify (GConfClient *client,
|
||||
|
||||
list = value ? gconf_value_get_list (value) : NULL;
|
||||
|
||||
if (update_key_list_binding (key, list))
|
||||
if (update_key_list_binding (key, list, META_LIST_OF_GCONFVALUE_STRINGS))
|
||||
queue_changed (META_PREF_KEYBINDINGS);
|
||||
}
|
||||
else
|
||||
@@ -1304,6 +1505,12 @@ meta_prefs_get_focus_new_windows (void)
|
||||
return focus_new_windows;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_attach_modal_dialogs (void)
|
||||
{
|
||||
return attach_modal_dialogs;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_raise_on_click (void)
|
||||
{
|
||||
@@ -1725,6 +1932,9 @@ meta_preference_to_string (MetaPreference pref)
|
||||
case META_PREF_FOCUS_NEW_WINDOWS:
|
||||
return "FOCUS_NEW_WINDOWS";
|
||||
|
||||
case META_PREF_ATTACH_MODAL_DIALOGS:
|
||||
return "ATTACH_MODAL_DIALOGS";
|
||||
|
||||
case META_PREF_RAISE_ON_CLICK:
|
||||
return "RAISE_ON_CLICK";
|
||||
|
||||
@@ -1800,6 +2010,12 @@ meta_preference_to_string (MetaPreference pref)
|
||||
case META_PREF_RESIZE_WITH_RIGHT_BUTTON:
|
||||
return "RESIZE_WITH_RIGHT_BUTTON";
|
||||
|
||||
case META_PREF_SIDE_BY_SIDE_TILING:
|
||||
return "SIDE_BY_SIDE_TILING";
|
||||
|
||||
case META_PREF_FORCE_FULLSCREEN:
|
||||
return "FORCE_FULLSCREEN";
|
||||
|
||||
case META_PREF_CLUTTER_PLUGINS:
|
||||
return "CLUTTER_PLUGINS";
|
||||
|
||||
@@ -1888,57 +2104,66 @@ init_special_bindings (void)
|
||||
static void
|
||||
init_bindings (void)
|
||||
{
|
||||
#ifdef HAVE_GCONF
|
||||
int i = 0;
|
||||
GError *err;
|
||||
#ifdef HAVE_GCONF
|
||||
const char *prefix[] = {
|
||||
KEY_WINDOW_BINDINGS_PREFIX,
|
||||
KEY_SCREEN_BINDINGS_PREFIX,
|
||||
NULL
|
||||
};
|
||||
int i;
|
||||
GSList *list, *l, *list_val;
|
||||
const char *str_val;
|
||||
const char *key;
|
||||
GConfEntry *entry;
|
||||
GConfValue *value;
|
||||
GHashTable *to_update;
|
||||
|
||||
g_assert (G_N_ELEMENTS (key_bindings) == META_KEYBINDING_ACTION_LAST + 1);
|
||||
|
||||
to_update = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
|
||||
for (i = 0; prefix[i]; i++)
|
||||
{
|
||||
list = gconf_client_all_entries (default_client, prefix[i], NULL);
|
||||
for (l = list; l; l = l->next)
|
||||
{
|
||||
entry = l->data;
|
||||
key = gconf_entry_get_key (entry);
|
||||
value = gconf_entry_get_value (entry);
|
||||
if (g_str_has_suffix (key, KEY_LIST_BINDINGS_SUFFIX))
|
||||
{
|
||||
/* List bindings are used in addition to the normal bindings and never
|
||||
* have defaults, so we just go ahead and set them immediately; there
|
||||
* will be only a few of them, so don't worry about the linear scan
|
||||
* in find_and_update_list_binding.
|
||||
*/
|
||||
list_val = gconf_client_get_list (default_client, key, GCONF_VALUE_STRING, NULL);
|
||||
|
||||
update_key_list_binding (key, list_val, META_LIST_OF_STRINGS);
|
||||
g_slist_foreach (list_val, (GFunc)g_free, NULL);
|
||||
g_slist_free (list_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
str_val = gconf_value_get_string (value);
|
||||
g_hash_table_insert (to_update, binding_name (key), g_strdup (str_val));
|
||||
}
|
||||
gconf_entry_free (entry);
|
||||
}
|
||||
g_slist_free (list);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (key_bindings[i].name)
|
||||
{
|
||||
GSList *list_val, *tmp;
|
||||
char *str_val;
|
||||
char *key;
|
||||
|
||||
key = g_strconcat (key_bindings[i].per_window?
|
||||
KEY_WINDOW_BINDINGS_PREFIX:
|
||||
KEY_SCREEN_BINDINGS_PREFIX,
|
||||
"/",
|
||||
key_bindings[i].name, NULL);
|
||||
|
||||
err = NULL;
|
||||
str_val = gconf_client_get_string (default_client, key, &err);
|
||||
cleanup_error (&err);
|
||||
|
||||
update_binding (&key_bindings[i], str_val);
|
||||
|
||||
g_free (str_val);
|
||||
g_free (key);
|
||||
|
||||
key = g_strconcat (key_bindings[i].per_window?
|
||||
KEY_WINDOW_BINDINGS_PREFIX:
|
||||
KEY_SCREEN_BINDINGS_PREFIX,
|
||||
"/",
|
||||
key_bindings[i].name,
|
||||
KEY_LIST_BINDINGS_SUFFIX, NULL);
|
||||
|
||||
err = NULL;
|
||||
|
||||
list_val = gconf_client_get_list (default_client, key, GCONF_VALUE_STRING, &err);
|
||||
cleanup_error (&err);
|
||||
|
||||
update_list_binding (&key_bindings[i], list_val, META_LIST_OF_STRINGS);
|
||||
|
||||
tmp = list_val;
|
||||
while (tmp)
|
||||
{
|
||||
g_free (tmp->data);
|
||||
tmp = tmp->next;
|
||||
}
|
||||
g_slist_free (list_val);
|
||||
g_free (key);
|
||||
update_binding (&key_bindings[i],
|
||||
g_hash_table_lookup (to_update, key_bindings[i].name));
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
g_hash_table_destroy (to_update);
|
||||
|
||||
#else /* HAVE_GCONF */
|
||||
int i = 0;
|
||||
while (key_bindings[i].name)
|
||||
@@ -1960,28 +2185,23 @@ static void
|
||||
init_commands (void)
|
||||
{
|
||||
#ifdef HAVE_GCONF
|
||||
int i;
|
||||
GError *err;
|
||||
|
||||
i = 0;
|
||||
while (i < MAX_COMMANDS)
|
||||
GSList *list, *l;
|
||||
const char *str_val;
|
||||
const char *key;
|
||||
GConfEntry *entry;
|
||||
GConfValue *value;
|
||||
|
||||
list = gconf_client_all_entries (default_client, KEY_COMMAND_DIRECTORY, NULL);
|
||||
for (l = list; l; l = l->next)
|
||||
{
|
||||
char *str_val;
|
||||
char *key;
|
||||
|
||||
key = meta_prefs_get_gconf_key_for_command (i);
|
||||
|
||||
err = NULL;
|
||||
str_val = gconf_client_get_string (default_client, key, &err);
|
||||
cleanup_error (&err);
|
||||
|
||||
entry = l->data;
|
||||
key = gconf_entry_get_key (entry);
|
||||
value = gconf_entry_get_value (entry);
|
||||
str_val = gconf_value_get_string (value);
|
||||
update_command (key, str_val);
|
||||
|
||||
g_free (str_val);
|
||||
g_free (key);
|
||||
|
||||
++i;
|
||||
gconf_entry_free (entry);
|
||||
}
|
||||
g_slist_free (list);
|
||||
#else
|
||||
int i;
|
||||
for (i = 0; i < MAX_COMMANDS; i++)
|
||||
@@ -1992,39 +2212,34 @@ init_commands (void)
|
||||
static void
|
||||
init_workspace_names (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef HAVE_GCONF
|
||||
int i;
|
||||
GError *err;
|
||||
|
||||
i = 0;
|
||||
while (i < MAX_REASONABLE_WORKSPACES)
|
||||
GSList *list, *l;
|
||||
const char *str_val;
|
||||
const char *key;
|
||||
GConfEntry *entry;
|
||||
GConfValue *value;
|
||||
|
||||
list = gconf_client_all_entries (default_client, KEY_WORKSPACE_NAME_DIRECTORY, NULL);
|
||||
for (l = list; l; l = l->next)
|
||||
{
|
||||
char *str_val;
|
||||
char *key;
|
||||
|
||||
key = gconf_key_for_workspace_name (i);
|
||||
|
||||
err = NULL;
|
||||
str_val = gconf_client_get_string (default_client, key, &err);
|
||||
cleanup_error (&err);
|
||||
|
||||
entry = l->data;
|
||||
key = gconf_entry_get_key (entry);
|
||||
value = gconf_entry_get_value (entry);
|
||||
str_val = gconf_value_get_string (value);
|
||||
update_workspace_name (key, str_val);
|
||||
|
||||
g_assert (workspace_names[i] != NULL);
|
||||
|
||||
g_free (str_val);
|
||||
g_free (key);
|
||||
|
||||
++i;
|
||||
gconf_entry_free (entry);
|
||||
}
|
||||
#else
|
||||
int i;
|
||||
g_slist_free (list);
|
||||
#endif /* HAVE_GCONF */
|
||||
|
||||
for (i = 0; i < MAX_REASONABLE_WORKSPACES; i++)
|
||||
workspace_names[i] = g_strdup_printf (_("Workspace %d"), i + 1);
|
||||
if (workspace_names[i] == NULL)
|
||||
workspace_names[i] = g_strdup_printf (_("Workspace %d"), i + 1);
|
||||
|
||||
meta_topic (META_DEBUG_PREFS,
|
||||
"Initialized workspace names\n");
|
||||
#endif /* HAVE_GCONF */
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -2275,16 +2490,22 @@ update_list_binding (MetaKeyPref *binding,
|
||||
return changed;
|
||||
}
|
||||
|
||||
static const gchar*
|
||||
relative_key (const gchar* key)
|
||||
static char *
|
||||
binding_name (const char *gconf_key)
|
||||
{
|
||||
const gchar* end;
|
||||
|
||||
end = strrchr (key, '/');
|
||||
const char *start, *end;
|
||||
|
||||
++end;
|
||||
if (*gconf_key == '/')
|
||||
start = strrchr (gconf_key, '/') + 1;
|
||||
else
|
||||
start = gconf_key;
|
||||
|
||||
return end;
|
||||
if (g_str_has_suffix (gconf_key, KEY_LIST_BINDINGS_SUFFIX))
|
||||
end = gconf_key + strlen(gconf_key) - strlen (KEY_LIST_BINDINGS_SUFFIX);
|
||||
else
|
||||
end = gconf_key + strlen(gconf_key);
|
||||
|
||||
return g_strndup (start, end - start);
|
||||
}
|
||||
|
||||
/* Return value is TRUE if a preference changed and we need to
|
||||
@@ -2292,22 +2513,19 @@ relative_key (const gchar* key)
|
||||
*/
|
||||
static gboolean
|
||||
find_and_update_binding (MetaKeyPref *bindings,
|
||||
const char *name,
|
||||
const char *key,
|
||||
const char *value)
|
||||
{
|
||||
const char *key;
|
||||
char *name = binding_name (key);
|
||||
int i;
|
||||
|
||||
if (*name == '/')
|
||||
key = relative_key (name);
|
||||
else
|
||||
key = name;
|
||||
|
||||
i = 0;
|
||||
while (bindings[i].name &&
|
||||
strcmp (key, bindings[i].name) != 0)
|
||||
strcmp (name, bindings[i].name) != 0)
|
||||
++i;
|
||||
|
||||
g_free (name);
|
||||
|
||||
if (bindings[i].name)
|
||||
return update_binding (&bindings[i], value);
|
||||
else
|
||||
@@ -2315,46 +2533,40 @@ find_and_update_binding (MetaKeyPref *bindings,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_key_binding (const char *name,
|
||||
const char *value)
|
||||
update_key_binding (const char *key,
|
||||
const char *value)
|
||||
{
|
||||
return find_and_update_binding (key_bindings, name, value);
|
||||
return find_and_update_binding (key_bindings, key, value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
find_and_update_list_binding (MetaKeyPref *bindings,
|
||||
const char *name,
|
||||
GSList *value)
|
||||
find_and_update_list_binding (MetaKeyPref *bindings,
|
||||
const char *key,
|
||||
GSList *value,
|
||||
MetaStringListType type_of_value)
|
||||
{
|
||||
const char *key;
|
||||
char *name = binding_name (key);
|
||||
int i;
|
||||
gchar *name_without_suffix = g_strdup(name);
|
||||
|
||||
name_without_suffix[strlen(name_without_suffix) - strlen(KEY_LIST_BINDINGS_SUFFIX)] = 0;
|
||||
|
||||
if (*name_without_suffix == '/')
|
||||
key = relative_key (name_without_suffix);
|
||||
else
|
||||
key = name_without_suffix;
|
||||
|
||||
i = 0;
|
||||
while (bindings[i].name &&
|
||||
strcmp (key, bindings[i].name) != 0)
|
||||
strcmp (name, bindings[i].name) != 0)
|
||||
++i;
|
||||
|
||||
g_free (name_without_suffix);
|
||||
g_free (name);
|
||||
|
||||
if (bindings[i].name)
|
||||
return update_list_binding (&bindings[i], value, META_LIST_OF_GCONFVALUE_STRINGS);
|
||||
return update_list_binding (&bindings[i], value, type_of_value);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_key_list_binding (const char *name,
|
||||
GSList *value)
|
||||
update_key_list_binding (const char *key,
|
||||
GSList *value,
|
||||
MetaStringListType type_of_value)
|
||||
{
|
||||
return find_and_update_list_binding (key_bindings, name, value);
|
||||
return find_and_update_list_binding (key_bindings, key, value, type_of_value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -2713,6 +2925,12 @@ meta_prefs_get_gnome_animations ()
|
||||
return gnome_animations;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_side_by_side_tiling ()
|
||||
{
|
||||
return side_by_side_tiling;
|
||||
}
|
||||
|
||||
MetaKeyBindingAction
|
||||
meta_prefs_get_keybinding_action (const char *name)
|
||||
{
|
||||
@@ -2792,6 +3010,12 @@ meta_prefs_get_mouse_button_menu (void)
|
||||
return resize_with_right_button ? 2: 3;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_force_fullscreen (void)
|
||||
{
|
||||
return force_fullscreen;
|
||||
}
|
||||
|
||||
void
|
||||
meta_prefs_set_compositing_manager (gboolean whether)
|
||||
{
|
||||
@@ -2814,6 +3038,11 @@ meta_prefs_set_compositing_manager (gboolean whether)
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_prefs_get_clutter_plugins:
|
||||
*
|
||||
* Returns: (transfer none) (element-type utf8): Plugin names to load
|
||||
*/
|
||||
GSList *
|
||||
meta_prefs_get_clutter_plugins (void)
|
||||
{
|
||||
@@ -2823,6 +3052,7 @@ meta_prefs_get_clutter_plugins (void)
|
||||
void
|
||||
meta_prefs_set_clutter_plugins (GSList *list)
|
||||
{
|
||||
#ifdef HAVE_GCONF
|
||||
GError *err = NULL;
|
||||
|
||||
gconf_client_set_list (default_client,
|
||||
@@ -2837,6 +3067,7 @@ meta_prefs_set_clutter_plugins (GSList *list)
|
||||
err->message);
|
||||
g_error_free (err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2957,3 +3188,10 @@ init_button_layout(void)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
meta_prefs_set_force_fullscreen (gboolean whether)
|
||||
{
|
||||
force_fullscreen = whether;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,12 +37,11 @@
|
||||
#include "screen.h"
|
||||
#include <X11/Xutil.h>
|
||||
#include "stack-tracker.h"
|
||||
#include "alttabhandler.h"
|
||||
#include "ui.h"
|
||||
|
||||
typedef struct _MetaXineramaScreenInfo MetaXineramaScreenInfo;
|
||||
typedef struct _MetaMonitorInfo MetaMonitorInfo;
|
||||
|
||||
struct _MetaXineramaScreenInfo
|
||||
struct _MetaMonitorInfo
|
||||
{
|
||||
int number;
|
||||
MetaRectangle rect;
|
||||
@@ -82,9 +81,11 @@ struct _MetaScreen
|
||||
Visual *default_xvisual;
|
||||
MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */
|
||||
MetaUI *ui;
|
||||
MetaAltTabHandler *tab_handler;
|
||||
MetaTabPopup *ws_popup;
|
||||
|
||||
MetaTabPopup *tab_popup, *ws_popup;
|
||||
MetaTilePreview *tile_preview;
|
||||
|
||||
guint tile_preview_timeout_id;
|
||||
|
||||
MetaWorkspace *active_workspace;
|
||||
|
||||
/* This window holds the focus when we don't want to focus
|
||||
@@ -105,11 +106,11 @@ struct _MetaScreen
|
||||
Atom wm_sn_atom;
|
||||
guint32 wm_sn_timestamp;
|
||||
|
||||
MetaXineramaScreenInfo *xinerama_infos;
|
||||
int n_xinerama_infos;
|
||||
MetaMonitorInfo *monitor_infos;
|
||||
int n_monitor_infos;
|
||||
|
||||
/* Cache the current Xinerama */
|
||||
int last_xinerama_index;
|
||||
/* Cache the current monitor */
|
||||
int last_monitor_index;
|
||||
|
||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||
SnMonitorContext *sn_context;
|
||||
@@ -118,8 +119,9 @@ struct _MetaScreen
|
||||
#endif
|
||||
|
||||
Window wm_cm_selection_window;
|
||||
guint32 wm_cm_timestamp;
|
||||
|
||||
guint work_area_idle;
|
||||
guint work_area_later;
|
||||
|
||||
int rows_of_workspaces;
|
||||
int columns_of_workspaces;
|
||||
@@ -131,9 +133,6 @@ struct _MetaScreen
|
||||
|
||||
int closing;
|
||||
|
||||
/* gc for XOR on root window */
|
||||
GC root_xor_gc;
|
||||
|
||||
/* Managed by compositor.c */
|
||||
gpointer compositor_data;
|
||||
|
||||
@@ -147,7 +146,8 @@ struct _MetaScreenClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (*restacked) (MetaScreen *);
|
||||
void (*restacked) (MetaScreen *);
|
||||
void (*workareas_changed) (MetaScreen *);
|
||||
};
|
||||
|
||||
MetaScreen* meta_screen_new (MetaDisplay *display,
|
||||
@@ -182,22 +182,25 @@ void meta_screen_workspace_popup_select (MetaScreen *screen,
|
||||
MetaWorkspace*meta_screen_workspace_popup_get_selected (MetaScreen *screen);
|
||||
void meta_screen_workspace_popup_destroy (MetaScreen *screen);
|
||||
|
||||
void meta_screen_tile_preview_update (MetaScreen *screen,
|
||||
gboolean delay);
|
||||
|
||||
MetaWindow* meta_screen_get_mouse_window (MetaScreen *screen,
|
||||
MetaWindow *not_this_one);
|
||||
|
||||
const MetaXineramaScreenInfo* meta_screen_get_current_xinerama (MetaScreen *screen);
|
||||
const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_rect (MetaScreen *screen,
|
||||
MetaRectangle *rect);
|
||||
const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_window (MetaScreen *screen,
|
||||
MetaWindow *window);
|
||||
const MetaMonitorInfo* meta_screen_get_current_monitor (MetaScreen *screen);
|
||||
const MetaMonitorInfo* meta_screen_get_monitor_for_rect (MetaScreen *screen,
|
||||
MetaRectangle *rect);
|
||||
const MetaMonitorInfo* meta_screen_get_monitor_for_window (MetaScreen *screen,
|
||||
MetaWindow *window);
|
||||
|
||||
|
||||
const MetaXineramaScreenInfo* meta_screen_get_xinerama_neighbor (MetaScreen *screen,
|
||||
int which_xinerama,
|
||||
MetaScreenDirection dir);
|
||||
void meta_screen_get_natural_xinerama_list (MetaScreen *screen,
|
||||
int** xineramas_list,
|
||||
int* n_xineramas);
|
||||
const MetaMonitorInfo* meta_screen_get_monitor_neighbor (MetaScreen *screen,
|
||||
int which_monitor,
|
||||
MetaScreenDirection dir);
|
||||
void meta_screen_get_natural_monitor_list (MetaScreen *screen,
|
||||
int** monitors_list,
|
||||
int* n_monitors);
|
||||
|
||||
void meta_screen_update_workspace_layout (MetaScreen *screen);
|
||||
void meta_screen_update_workspace_names (MetaScreen *screen);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,6 +29,7 @@
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#ifndef HAVE_SM
|
||||
void
|
||||
@@ -83,6 +84,7 @@ static char* load_state (const char *previous_save_file);
|
||||
static void regenerate_save_file (void);
|
||||
static const char* full_save_file (void);
|
||||
static void warn_about_lame_clients_and_finish_interact (gboolean shutdown);
|
||||
static void disconnect (void);
|
||||
|
||||
/* This is called when data is available on an ICE connection. */
|
||||
static gboolean
|
||||
@@ -105,9 +107,12 @@ process_ice_messages (GIOChannel *channel,
|
||||
IcePointer context = IceGetConnectionContext (connection);
|
||||
#endif
|
||||
|
||||
/* We were disconnected */
|
||||
IceSetShutdownNegotiation (connection, False);
|
||||
IceCloseConnection (connection);
|
||||
/* We were disconnected; close our connection to the
|
||||
* session manager, this will result in the ICE connection
|
||||
* being cleaned up, since it is owned by libSM.
|
||||
*/
|
||||
disconnect ();
|
||||
meta_quit (META_EXIT_SUCCESS);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1104,8 +1109,6 @@ load_state (const char *previous_save_file)
|
||||
{
|
||||
/* oh, just give up */
|
||||
|
||||
meta_warning (_("Failed to read saved session file %s: %s\n"),
|
||||
canonical_session_file, error->message);
|
||||
g_error_free (error);
|
||||
g_free (session_file);
|
||||
g_free (canonical_session_file);
|
||||
@@ -1749,11 +1752,11 @@ finish_interact (gboolean shutdown)
|
||||
}
|
||||
|
||||
static void
|
||||
sigchld_handler (MetaNexus *nexus, guint arg1, gpointer arg2, gpointer user_data)
|
||||
dialog_closed (GPid pid, int status, gpointer user_data)
|
||||
{
|
||||
gboolean shutdown = GPOINTER_TO_INT (user_data);
|
||||
|
||||
if (arg1 == 0) /* pressed "OK" */
|
||||
if (WIFEXITED (status) && WEXITSTATUS (status) == 0) /* pressed "OK" */
|
||||
{
|
||||
finish_interact (shutdown);
|
||||
}
|
||||
@@ -1767,6 +1770,7 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown)
|
||||
GSList *lame_details = NULL;
|
||||
GSList *tmp;
|
||||
GSList *columns = NULL;
|
||||
GPid pid;
|
||||
|
||||
windows = meta_display_list_windows (meta_get_display (), META_LIST_DEFAULT);
|
||||
tmp = windows;
|
||||
@@ -1814,23 +1818,20 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown)
|
||||
}
|
||||
g_slist_free (lame);
|
||||
|
||||
meta_show_dialog("--list",
|
||||
_("These windows do not support "save current setup" "
|
||||
"and will have to be restarted manually next time "
|
||||
"you log in."),
|
||||
"240",
|
||||
meta_screen_get_screen_number (meta_get_display()->active_screen),
|
||||
NULL, NULL,
|
||||
None,
|
||||
columns,
|
||||
lame_details);
|
||||
pid = meta_show_dialog("--list",
|
||||
_("These windows do not support "save current setup" "
|
||||
"and will have to be restarted manually next time "
|
||||
"you log in."),
|
||||
"240",
|
||||
meta_screen_get_screen_number (meta_get_display()->active_screen),
|
||||
NULL, NULL,
|
||||
None,
|
||||
columns,
|
||||
lame_details);
|
||||
|
||||
g_slist_free (lame_details);
|
||||
|
||||
g_signal_connect (sigchld_nexus, "sigchld",
|
||||
G_CALLBACK (sigchld_handler),
|
||||
GINT_TO_POINTER (shutdown));
|
||||
|
||||
g_child_watch_add (pid, dialog_closed, GINT_TO_POINTER (shutdown));
|
||||
}
|
||||
|
||||
#endif /* HAVE_SM */
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "frame-private.h"
|
||||
#include "screen-private.h"
|
||||
#include "stack-tracker.h"
|
||||
#include "util.h"
|
||||
@@ -134,7 +135,7 @@ struct _MetaStackTracker
|
||||
/* Idle function used to sync the compositor's view of the window
|
||||
* stack up with our best guess before a frame is drawn.
|
||||
*/
|
||||
guint sync_stack_idle;
|
||||
guint sync_stack_later;
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -383,8 +384,8 @@ meta_stack_tracker_new (MetaScreen *screen)
|
||||
void
|
||||
meta_stack_tracker_free (MetaStackTracker *tracker)
|
||||
{
|
||||
if (tracker->sync_stack_idle)
|
||||
g_source_remove (tracker->sync_stack_idle);
|
||||
if (tracker->sync_stack_later)
|
||||
meta_later_remove (tracker->sync_stack_later);
|
||||
|
||||
g_array_free (tracker->server_stack, TRUE);
|
||||
if (tracker->predicted_stack)
|
||||
@@ -667,10 +668,10 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
|
||||
int n_windows;
|
||||
int i;
|
||||
|
||||
if (tracker->sync_stack_idle)
|
||||
if (tracker->sync_stack_later)
|
||||
{
|
||||
g_source_remove (tracker->sync_stack_idle);
|
||||
tracker->sync_stack_idle = 0;
|
||||
meta_later_remove (tracker->sync_stack_later);
|
||||
tracker->sync_stack_later = 0;
|
||||
}
|
||||
|
||||
meta_stack_tracker_get_stack (tracker, &windows, &n_windows);
|
||||
@@ -682,7 +683,15 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
|
||||
|
||||
meta_window = meta_display_lookup_x_window (tracker->screen->display,
|
||||
windows[i]);
|
||||
if (meta_window)
|
||||
/* When mapping back from xwindow to MetaWindow we have to be a bit careful;
|
||||
* children of the root could include unmapped windows created by toolkits
|
||||
* for internal purposes, including ones that we have registered in our
|
||||
* XID => window table. (Wine uses a toplevel for _NET_WM_USER_TIME_WINDOW;
|
||||
* see window-prop.c:reload_net_wm_user_time_window() for registration.)
|
||||
*/
|
||||
if (meta_window &&
|
||||
(windows[i] == meta_window->xwindow ||
|
||||
(meta_window->frame && windows[i] == meta_window->frame->xwindow)))
|
||||
meta_windows = g_list_prepend (meta_windows, meta_window);
|
||||
}
|
||||
|
||||
@@ -696,7 +705,7 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
stack_tracker_sync_stack_idle (gpointer data)
|
||||
stack_tracker_sync_stack_later (gpointer data)
|
||||
{
|
||||
meta_stack_tracker_sync_stack (data);
|
||||
|
||||
@@ -719,10 +728,10 @@ stack_tracker_sync_stack_idle (gpointer data)
|
||||
void
|
||||
meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker)
|
||||
{
|
||||
if (tracker->sync_stack_idle == 0)
|
||||
if (tracker->sync_stack_later == 0)
|
||||
{
|
||||
tracker->sync_stack_idle = g_idle_add_full (META_PRIORITY_BEFORE_REDRAW,
|
||||
stack_tracker_sync_stack_idle,
|
||||
tracker->sync_stack_later = meta_later_add (META_LATER_BEFORE_REDRAW,
|
||||
stack_tracker_sync_stack_later,
|
||||
tracker, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,14 +224,14 @@ is_focused_foreach (MetaWindow *window,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
windows_on_different_xinerama (MetaWindow *a,
|
||||
MetaWindow *b)
|
||||
windows_on_different_monitor (MetaWindow *a,
|
||||
MetaWindow *b)
|
||||
{
|
||||
if (a->screen != b->screen)
|
||||
return TRUE;
|
||||
|
||||
return meta_screen_get_xinerama_for_window (a->screen, a) !=
|
||||
meta_screen_get_xinerama_for_window (b->screen, b);
|
||||
return meta_screen_get_monitor_for_window (a->screen, a) !=
|
||||
meta_screen_get_monitor_for_window (b->screen, b);
|
||||
}
|
||||
|
||||
/* Get layer ignoring any transient or group relationships */
|
||||
@@ -275,8 +275,8 @@ get_standalone_layer (MetaWindow *window)
|
||||
window == window->display->expected_focus_window ||
|
||||
window->display->expected_focus_window == NULL ||
|
||||
(window->display->expected_focus_window != NULL &&
|
||||
windows_on_different_xinerama (window,
|
||||
window->display->expected_focus_window))))
|
||||
windows_on_different_monitor (window,
|
||||
window->display->expected_focus_window))))
|
||||
layer = META_LAYER_FULLSCREEN;
|
||||
else if (window->wm_state_above)
|
||||
layer = META_LAYER_TOP;
|
||||
@@ -1026,7 +1026,7 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
|
||||
xwindow,
|
||||
CWSibling | CWStackMode,
|
||||
&changes);
|
||||
meta_error_trap_pop (screen->display, FALSE);
|
||||
meta_error_trap_pop (screen->display);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1046,7 +1046,7 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
|
||||
XNextRequest (screen->display->xdisplay));
|
||||
XLowerWindow (screen->display->xdisplay,
|
||||
xwindow);
|
||||
meta_error_trap_pop (screen->display, FALSE);
|
||||
meta_error_trap_pop (screen->display);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1267,7 +1267,7 @@ stack_sync_to_server (MetaStack *stack)
|
||||
all_hidden->len);
|
||||
g_array_free (all_hidden, TRUE);
|
||||
|
||||
meta_error_trap_pop (stack->screen->display, FALSE);
|
||||
meta_error_trap_pop (stack->screen->display);
|
||||
/* on error, a window was destroyed; it should eventually
|
||||
* get removed from the stacking list when we unmanage it
|
||||
* and we'll fix stacking at that time.
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "boxes.h"
|
||||
#include "boxes-private.h"
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -85,7 +85,7 @@ new_screen_edge (int x, int y, int width, int height, int side_type)
|
||||
}
|
||||
|
||||
static MetaEdge*
|
||||
new_xinerama_edge (int x, int y, int width, int height, int side_type)
|
||||
new_monitor_edge (int x, int y, int width, int height, int side_type)
|
||||
{
|
||||
MetaEdge* temporary;
|
||||
temporary = g_new (MetaEdge, 1);
|
||||
@@ -94,7 +94,7 @@ new_xinerama_edge (int x, int y, int width, int height, int side_type)
|
||||
temporary->rect.width = width;
|
||||
temporary->rect.height = height;
|
||||
temporary->side_type = side_type;
|
||||
temporary->edge_type = META_EDGE_XINERAMA;
|
||||
temporary->edge_type = META_EDGE_MONITOR;
|
||||
|
||||
return temporary;
|
||||
}
|
||||
@@ -317,15 +317,15 @@ get_screen_edges (int which)
|
||||
}
|
||||
|
||||
static GList*
|
||||
get_xinerama_edges (int which_xinerama_set, int which_strut_set)
|
||||
get_monitor_edges (int which_monitor_set, int which_strut_set)
|
||||
{
|
||||
GList *ret;
|
||||
GSList *struts;
|
||||
GList *xins;
|
||||
|
||||
xins = NULL;
|
||||
g_assert (which_xinerama_set >=0 && which_xinerama_set <= 3);
|
||||
switch (which_xinerama_set)
|
||||
g_assert (which_monitor_set >=0 && which_monitor_set <= 3);
|
||||
switch (which_monitor_set)
|
||||
{
|
||||
case 0:
|
||||
xins = g_list_prepend (xins, new_meta_rect ( 0, 0, 1600, 1200));
|
||||
@@ -348,7 +348,7 @@ get_xinerama_edges (int which_xinerama_set, int which_strut_set)
|
||||
ret = NULL;
|
||||
|
||||
struts = get_strut_list (which_strut_set);
|
||||
ret = meta_rectangle_find_nonintersected_xinerama_edges (xins, struts);
|
||||
ret = meta_rectangle_find_nonintersected_monitor_edges (xins, struts);
|
||||
|
||||
free_strut_list (struts);
|
||||
meta_rectangle_free_list_and_elements (xins);
|
||||
@@ -1145,7 +1145,7 @@ test_find_onscreen_edges ()
|
||||
}
|
||||
|
||||
static void
|
||||
test_find_nonintersected_xinerama_edges ()
|
||||
test_find_nonintersected_monitor_edges ()
|
||||
{
|
||||
GList* edges;
|
||||
GList* tmp;
|
||||
@@ -1156,32 +1156,32 @@ test_find_nonintersected_xinerama_edges ()
|
||||
int bottom = META_DIRECTION_BOTTOM;
|
||||
|
||||
/*************************************************************************/
|
||||
/* Make sure test xinerama set 0 for with region 0 has the correct edges */
|
||||
/* Make sure test monitor set 0 for with region 0 has the correct edges */
|
||||
/*************************************************************************/
|
||||
edges = get_xinerama_edges (0, 0);
|
||||
edges = get_monitor_edges (0, 0);
|
||||
tmp = NULL;
|
||||
verify_edge_lists_are_equal (edges, tmp);
|
||||
meta_rectangle_free_list_and_elements (tmp);
|
||||
meta_rectangle_free_list_and_elements (edges);
|
||||
|
||||
/*************************************************************************/
|
||||
/* Make sure test xinerama set 2 for with region 1 has the correct edges */
|
||||
/* Make sure test monitor set 2 for with region 1 has the correct edges */
|
||||
/*************************************************************************/
|
||||
edges = get_xinerama_edges (2, 1);
|
||||
edges = get_monitor_edges (2, 1);
|
||||
tmp = NULL;
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 1600, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 1600, 0, top));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 1600, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 1600, 0, top));
|
||||
verify_edge_lists_are_equal (edges, tmp);
|
||||
meta_rectangle_free_list_and_elements (tmp);
|
||||
meta_rectangle_free_list_and_elements (edges);
|
||||
|
||||
/*************************************************************************/
|
||||
/* Make sure test xinerama set 1 for with region 2 has the correct edges */
|
||||
/* Make sure test monitor set 1 for with region 2 has the correct edges */
|
||||
/*************************************************************************/
|
||||
edges = get_xinerama_edges (1, 2);
|
||||
edges = get_monitor_edges (1, 2);
|
||||
tmp = NULL;
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 20, 0, 1080, right));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 20, 0, 1180, left));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 20, 0, 1080, right));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 20, 0, 1180, left));
|
||||
#if 0
|
||||
#define FUDGE 50
|
||||
char big_buffer1[(EDGE_LENGTH+2)*FUDGE], big_buffer2[(EDGE_LENGTH+2)*FUDGE];
|
||||
@@ -1195,36 +1195,36 @@ test_find_nonintersected_xinerama_edges ()
|
||||
meta_rectangle_free_list_and_elements (edges);
|
||||
|
||||
/*************************************************************************/
|
||||
/* Make sure test xinerama set 3 for with region 3 has the correct edges */
|
||||
/* Make sure test monitor set 3 for with region 3 has the correct edges */
|
||||
/*************************************************************************/
|
||||
edges = get_xinerama_edges (3, 3);
|
||||
edges = get_monitor_edges (3, 3);
|
||||
tmp = NULL;
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 900, 600, 700, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 700, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 900, 600, 700, 0, top));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 700, 0, top));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 675, 0, 425, right));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 675, 0, 525, left));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 900, 600, 700, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 700, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 900, 600, 700, 0, top));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 700, 0, top));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 675, 0, 425, right));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 675, 0, 525, left));
|
||||
verify_edge_lists_are_equal (edges, tmp);
|
||||
meta_rectangle_free_list_and_elements (tmp);
|
||||
meta_rectangle_free_list_and_elements (edges);
|
||||
|
||||
/*************************************************************************/
|
||||
/* Make sure test xinerama set 3 for with region 4 has the correct edges */
|
||||
/* Make sure test monitor set 3 for with region 4 has the correct edges */
|
||||
/*************************************************************************/
|
||||
edges = get_xinerama_edges (3, 4);
|
||||
edges = get_monitor_edges (3, 4);
|
||||
tmp = NULL;
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 600, 800, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 600, 800, 0, top));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 600, 0, 600, right));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 600, 800, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 600, 800, 0, top));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 600, 0, 600, right));
|
||||
verify_edge_lists_are_equal (edges, tmp);
|
||||
meta_rectangle_free_list_and_elements (tmp);
|
||||
meta_rectangle_free_list_and_elements (edges);
|
||||
|
||||
/*************************************************************************/
|
||||
/* Make sure test xinerama set 3 for with region 5has the correct edges */
|
||||
/* Make sure test monitor set 3 for with region 5has the correct edges */
|
||||
/*************************************************************************/
|
||||
edges = get_xinerama_edges (3, 5);
|
||||
edges = get_monitor_edges (3, 5);
|
||||
tmp = NULL;
|
||||
verify_edge_lists_are_equal (edges, tmp);
|
||||
meta_rectangle_free_list_and_elements (tmp);
|
||||
@@ -1405,7 +1405,7 @@ main()
|
||||
|
||||
/* And now the functions dealing with edges more than boxes */
|
||||
test_find_onscreen_edges ();
|
||||
test_find_nonintersected_xinerama_edges ();
|
||||
test_find_nonintersected_monitor_edges ();
|
||||
|
||||
/* And now the misfit functions that don't quite fit in anywhere else... */
|
||||
test_gravity_resize ();
|
||||
|
||||
319
src/core/util.c
319
src/core/util.c
@@ -26,9 +26,12 @@
|
||||
#define _POSIX_C_SOURCE 200112L /* for fdopen() */
|
||||
|
||||
#include <config.h>
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
|
||||
#include <clutter/clutter.h> /* For clutter_threads_add_repaint_func() */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -37,7 +40,12 @@
|
||||
#include <X11/Xlib.h> /* must explicitly be included for Solaris; #326746 */
|
||||
#include <X11/Xutil.h> /* Just for the definition of the various gravities */
|
||||
|
||||
MetaNexus *sigchld_nexus;
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static void
|
||||
meta_topic_real_valist (MetaDebugTopic topic,
|
||||
const char *format,
|
||||
va_list args);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BACKTRACE
|
||||
#include <execinfo.h>
|
||||
@@ -70,7 +78,7 @@ meta_print_backtrace (void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean is_verbose = FALSE;
|
||||
static gint verbose_topics = 0;
|
||||
static gboolean is_debugging = FALSE;
|
||||
static gboolean replace_current = FALSE;
|
||||
static int no_prefix = 0;
|
||||
@@ -127,7 +135,7 @@ ensure_logfile (void)
|
||||
gboolean
|
||||
meta_is_verbose (void)
|
||||
{
|
||||
return is_verbose;
|
||||
return verbose_topics != 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -140,8 +148,48 @@ meta_set_verbose (gboolean setting)
|
||||
if (setting)
|
||||
ensure_logfile ();
|
||||
#endif
|
||||
|
||||
is_verbose = setting;
|
||||
|
||||
if (setting)
|
||||
meta_add_verbose_topic (META_DEBUG_VERBOSE);
|
||||
else
|
||||
meta_remove_verbose_topic (META_DEBUG_VERBOSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_add_verbose_topic:
|
||||
* @topic: Topic for which logging will be started
|
||||
*
|
||||
* Ensure log messages for the given topic @topic
|
||||
* will be printed.
|
||||
*/
|
||||
void
|
||||
meta_add_verbose_topic (MetaDebugTopic topic)
|
||||
{
|
||||
if (verbose_topics == META_DEBUG_VERBOSE)
|
||||
return;
|
||||
if (topic == META_DEBUG_VERBOSE)
|
||||
verbose_topics = META_DEBUG_VERBOSE;
|
||||
else
|
||||
verbose_topics |= topic;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_remove_verbose_topic:
|
||||
* @topic: Topic for which logging will be stopped
|
||||
*
|
||||
* Stop printing log messages for the given topic @topic. Note
|
||||
* that this method does not stack with meta_add_verbose_topic();
|
||||
* i.e. if two calls to meta_add_verbose_topic() for the same
|
||||
* topic are made, one call to meta_remove_verbose_topic() will
|
||||
* remove it.
|
||||
*/
|
||||
void
|
||||
meta_remove_verbose_topic (MetaDebugTopic topic)
|
||||
{
|
||||
if (topic == META_DEBUG_VERBOSE)
|
||||
verbose_topics = 0;
|
||||
else
|
||||
verbose_topics &= ~topic;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -249,27 +297,10 @@ void
|
||||
meta_verbose_real (const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
gchar *str;
|
||||
FILE *out;
|
||||
|
||||
g_return_if_fail (format != NULL);
|
||||
|
||||
if (!is_verbose)
|
||||
return;
|
||||
|
||||
va_start (args, format);
|
||||
str = g_strdup_vprintf (format, args);
|
||||
meta_topic_real_valist (META_DEBUG_VERBOSE, format, args);
|
||||
va_end (args);
|
||||
|
||||
out = logfile ? logfile : stderr;
|
||||
|
||||
if (no_prefix == 0)
|
||||
utf8_fputs ("Window manager: ", out);
|
||||
utf8_fputs (str, out);
|
||||
|
||||
fflush (out);
|
||||
|
||||
g_free (str);
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
@@ -323,6 +354,8 @@ topic_name (MetaDebugTopic topic)
|
||||
return "COMPOSITOR";
|
||||
case META_DEBUG_EDGE_RESISTANCE:
|
||||
return "EDGE_RESISTANCE";
|
||||
case META_DEBUG_VERBOSE:
|
||||
return "VERBOSE";
|
||||
}
|
||||
|
||||
return "WM";
|
||||
@@ -330,23 +363,22 @@ topic_name (MetaDebugTopic topic)
|
||||
|
||||
static int sync_count = 0;
|
||||
|
||||
void
|
||||
meta_topic_real (MetaDebugTopic topic,
|
||||
const char *format,
|
||||
...)
|
||||
static void
|
||||
meta_topic_real_valist (MetaDebugTopic topic,
|
||||
const char *format,
|
||||
va_list args)
|
||||
{
|
||||
va_list args;
|
||||
gchar *str;
|
||||
FILE *out;
|
||||
|
||||
g_return_if_fail (format != NULL);
|
||||
|
||||
if (!is_verbose)
|
||||
if (verbose_topics == 0
|
||||
|| (topic == META_DEBUG_VERBOSE && verbose_topics != META_DEBUG_VERBOSE)
|
||||
|| (!(verbose_topics & topic)))
|
||||
return;
|
||||
|
||||
va_start (args, format);
|
||||
|
||||
str = g_strdup_vprintf (format, args);
|
||||
va_end (args);
|
||||
|
||||
out = logfile ? logfile : stderr;
|
||||
|
||||
@@ -365,6 +397,18 @@ meta_topic_real (MetaDebugTopic topic,
|
||||
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
void
|
||||
meta_topic_real (MetaDebugTopic topic,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
meta_topic_real_valist (topic, format, args);
|
||||
va_end (args);
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
void
|
||||
@@ -557,7 +601,7 @@ meta_show_dialog (const char *type,
|
||||
int i=0;
|
||||
GPid child_pid;
|
||||
const char **argvl = g_malloc(sizeof (char*) *
|
||||
(15 +
|
||||
(17 +
|
||||
g_slist_length (columns)*2 +
|
||||
g_slist_length (entries)));
|
||||
|
||||
@@ -565,6 +609,8 @@ meta_show_dialog (const char *type,
|
||||
argvl[i++] = type;
|
||||
argvl[i++] = "--screen";
|
||||
argvl[i++] = screen_number_text;
|
||||
argvl[i++] = "--class";
|
||||
argvl[i++] = "mutter-dialog";
|
||||
argvl[i++] = "--title";
|
||||
/* Translators: This is the title used on dialog boxes */
|
||||
argvl[i++] = _("Mutter");
|
||||
@@ -638,29 +684,200 @@ meta_show_dialog (const char *type,
|
||||
return child_pid;
|
||||
}
|
||||
|
||||
GType
|
||||
meta_nexus_get_type (void)
|
||||
/***************************************************************************
|
||||
* Later functions: like idles but integrated with the Clutter repaint loop
|
||||
***************************************************************************/
|
||||
|
||||
static guint last_later_id = 0;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
static GType nexus_type = 0;
|
||||
guint id;
|
||||
MetaLaterType when;
|
||||
GSourceFunc func;
|
||||
gpointer data;
|
||||
GDestroyNotify notify;
|
||||
int source;
|
||||
gboolean run_once;
|
||||
} MetaLater;
|
||||
|
||||
if (!nexus_type)
|
||||
static GSList *laters = NULL;
|
||||
/* This is a dummy timeline used to get the Clutter master clock running */
|
||||
static ClutterTimeline *later_timeline;
|
||||
static guint later_repaint_func = 0;
|
||||
|
||||
static void ensure_later_repaint_func (void);
|
||||
|
||||
static void
|
||||
destroy_later (MetaLater *later)
|
||||
{
|
||||
if (later->source)
|
||||
g_source_remove (later->source);
|
||||
if (later->notify)
|
||||
later->notify (later->data);
|
||||
g_slice_free (MetaLater, later);
|
||||
}
|
||||
|
||||
/* Used to sort the list of laters with the highest priority
|
||||
* functions first.
|
||||
*/
|
||||
static int
|
||||
compare_laters (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
return ((const MetaLater *)a)->when - ((const MetaLater *)b)->when;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
run_repaint_laters (gpointer data)
|
||||
{
|
||||
GSList *old_laters = laters;
|
||||
GSList *l;
|
||||
gboolean keep_timeline_running = FALSE;
|
||||
laters = NULL;
|
||||
|
||||
for (l = old_laters; l; l = l->next)
|
||||
{
|
||||
static const GTypeInfo nexus_info =
|
||||
{
|
||||
sizeof (MetaNexusClass),
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
sizeof (MetaNexus),
|
||||
0,
|
||||
NULL, NULL
|
||||
};
|
||||
|
||||
nexus_type = g_type_register_static (G_TYPE_OBJECT,
|
||||
"MetaNexus",
|
||||
&nexus_info,
|
||||
0);
|
||||
MetaLater *later = l->data;
|
||||
if (later->source == 0 ||
|
||||
(later->when <= META_LATER_BEFORE_REDRAW && !later->run_once))
|
||||
{
|
||||
if (later->func (later->data))
|
||||
{
|
||||
if (later->source == 0)
|
||||
keep_timeline_running = TRUE;
|
||||
laters = g_slist_insert_sorted (laters, later, compare_laters);
|
||||
}
|
||||
else
|
||||
destroy_later (later);
|
||||
}
|
||||
else
|
||||
laters = g_slist_insert_sorted (laters, later, compare_laters);
|
||||
}
|
||||
|
||||
return nexus_type;
|
||||
if (!keep_timeline_running)
|
||||
clutter_timeline_stop (later_timeline);
|
||||
|
||||
g_slist_free (old_laters);
|
||||
|
||||
/* Just keep the repaint func around - it's cheap if the list is empty */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_later_repaint_func (void)
|
||||
{
|
||||
if (!later_timeline)
|
||||
later_timeline = clutter_timeline_new (G_MAXUINT);
|
||||
|
||||
if (later_repaint_func == 0)
|
||||
later_repaint_func = clutter_threads_add_repaint_func (run_repaint_laters,
|
||||
NULL, NULL);
|
||||
|
||||
/* Make sure the repaint function gets run */
|
||||
clutter_timeline_start (later_timeline);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
call_idle_later (gpointer data)
|
||||
{
|
||||
MetaLater *later = data;
|
||||
|
||||
if (!later->func (later->data))
|
||||
{
|
||||
laters = g_slist_remove (laters, later);
|
||||
later->source = 0;
|
||||
destroy_later (later);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
later->run_once = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_later_add:
|
||||
* @when: enumeration value determining the phase at which to run the callback
|
||||
* @func: callback to run later
|
||||
* @data: data to pass to the callback
|
||||
* @notify: function to call to destroy @data when it is no longer in use, or %NULL
|
||||
*
|
||||
* Sets up a callback to be called at some later time. @when determines the
|
||||
* particular later occasion at which it is called. This is much like g_idle_add(),
|
||||
* except that the functions interact properly with clutter event handling.
|
||||
* If a "later" function is added from a clutter event handler, and is supposed
|
||||
* to be run before the stage is redrawn, it will be run before that redraw
|
||||
* of the stage, not the next one.
|
||||
*
|
||||
* Return value: an integer ID (guaranteed to be non-zero) that can be used
|
||||
* to cancel the callback and prevent it from being run.
|
||||
*/
|
||||
guint
|
||||
meta_later_add (MetaLaterType when,
|
||||
GSourceFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
MetaLater *later = g_slice_new0 (MetaLater);
|
||||
|
||||
later->id = ++last_later_id;
|
||||
later->when = when;
|
||||
later->func = func;
|
||||
later->data = data;
|
||||
later->notify = notify;
|
||||
|
||||
laters = g_slist_insert_sorted (laters, later, compare_laters);
|
||||
|
||||
switch (when)
|
||||
{
|
||||
case META_LATER_RESIZE:
|
||||
/* We add this one two ways - as a high-priority idle and as a
|
||||
* repaint func. If we are in a clutter event callback, the repaint
|
||||
* handler will get hit first, and we'll take care of this function
|
||||
* there so it gets called before the stage is redrawn, even if
|
||||
* we haven't gotten back to the main loop. Otherwise, the idle
|
||||
* handler will get hit first and we want to call this function
|
||||
* there so it will happen before GTK+ repaints.
|
||||
*/
|
||||
later->source = g_idle_add_full (META_PRIORITY_RESIZE, call_idle_later, later, NULL);
|
||||
ensure_later_repaint_func ();
|
||||
break;
|
||||
case META_LATER_BEFORE_REDRAW:
|
||||
ensure_later_repaint_func ();
|
||||
break;
|
||||
case META_LATER_IDLE:
|
||||
later->source = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, call_idle_later, later, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
return later->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_later_remove:
|
||||
* @later_id: the integer ID returned from meta_later_add()
|
||||
*
|
||||
* Removes a callback added with meta_later_add()
|
||||
*/
|
||||
void
|
||||
meta_later_remove (guint later_id)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = laters; l; l = l->next)
|
||||
{
|
||||
MetaLater *later = l->data;
|
||||
if (later->id == later_id)
|
||||
{
|
||||
laters = g_slist_remove_link (laters, l);
|
||||
/* If this was a "repaint func" later, we just let the
|
||||
* repaint func run and get removed
|
||||
*/
|
||||
destroy_later (later);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* eof util.c */
|
||||
|
||||
@@ -46,9 +46,6 @@
|
||||
|
||||
typedef struct _MetaWindowQueue MetaWindowQueue;
|
||||
|
||||
typedef gboolean (*MetaWindowForeachFunc) (MetaWindow *window,
|
||||
void *data);
|
||||
|
||||
typedef enum {
|
||||
META_CLIENT_TYPE_UNKNOWN = 0,
|
||||
META_CLIENT_TYPE_APPLICATION = 1,
|
||||
@@ -64,6 +61,12 @@ typedef enum {
|
||||
|
||||
#define NUMBER_OF_QUEUES 3
|
||||
|
||||
typedef enum {
|
||||
META_TILE_NONE,
|
||||
META_TILE_LEFT,
|
||||
META_TILE_RIGHT
|
||||
} MetaTileMode;
|
||||
|
||||
struct _MetaWindow
|
||||
{
|
||||
GObject parent_instance;
|
||||
@@ -99,6 +102,7 @@ struct _MetaWindow
|
||||
char *sm_client_id;
|
||||
char *wm_client_machine;
|
||||
char *startup_id;
|
||||
char *mutter_hints;
|
||||
|
||||
int net_wm_pid;
|
||||
|
||||
@@ -124,12 +128,23 @@ struct _MetaWindow
|
||||
guint maximize_vertically_after_placement : 1;
|
||||
guint minimize_after_placement : 1;
|
||||
|
||||
/* The current or requested tile mode. If maximized_vertically is true,
|
||||
* this is the current mode. If not, it is the mode which will be
|
||||
* requested after the window grab is released */
|
||||
guint tile_mode : 2;
|
||||
|
||||
/* Whether we're shaded */
|
||||
guint shaded : 1;
|
||||
|
||||
/* Whether we're fullscreen */
|
||||
guint fullscreen : 1;
|
||||
|
||||
/* Whether the urgent flag of WM_HINTS is set */
|
||||
guint wm_hints_urgent : 1;
|
||||
|
||||
/* Whether we have to fullscreen after placement */
|
||||
guint fullscreen_after_placement : 1;
|
||||
|
||||
/* Area to cover when in fullscreen mode. If _NET_WM_FULLSCREEN_MONITORS has
|
||||
* been overridden (via a client message), the window will cover the union of
|
||||
* these monitors. If not, this is the single monitor which the window's
|
||||
@@ -139,8 +154,8 @@ struct _MetaWindow
|
||||
/* Whether we're trying to constrain the window to be fully onscreen */
|
||||
guint require_fully_onscreen : 1;
|
||||
|
||||
/* Whether we're trying to constrain the window to be on a single xinerama */
|
||||
guint require_on_single_xinerama : 1;
|
||||
/* Whether we're trying to constrain the window to be on a single monitor */
|
||||
guint require_on_single_monitor : 1;
|
||||
|
||||
/* Whether we're trying to constrain the window's titlebar to be onscreen */
|
||||
guint require_titlebar_visible : 1;
|
||||
@@ -246,6 +261,9 @@ struct _MetaWindow
|
||||
/* Have we placed this window? */
|
||||
guint placed : 1;
|
||||
|
||||
/* Must we force_save_user_window_placement? */
|
||||
guint force_save_user_rect : 1;
|
||||
|
||||
/* Is this not a transient of the focus window which is being denied focus? */
|
||||
guint denied_focus_and_not_transient : 1;
|
||||
|
||||
@@ -316,6 +334,9 @@ struct _MetaWindow
|
||||
*/
|
||||
int unmaps_pending;
|
||||
|
||||
/* See docs for meta_window_get_stable_sequence() */
|
||||
guint32 stable_sequence;
|
||||
|
||||
/* set to the most recent user-interaction event timestamp that we
|
||||
know about for this window */
|
||||
guint32 net_wm_user_time;
|
||||
@@ -377,6 +398,7 @@ struct _MetaWindowClass
|
||||
void (*workspace_changed) (MetaWindow *window, int old_workspace);
|
||||
void (*focus) (MetaWindow *window);
|
||||
void (*raised) (MetaWindow *window);
|
||||
void (*unmanaged) (MetaWindow *window);
|
||||
};
|
||||
|
||||
/* These differ from window->has_foo_func in that they consider
|
||||
@@ -387,8 +409,11 @@ struct _MetaWindowClass
|
||||
(w)->maximized_vertically)
|
||||
#define META_WINDOW_MAXIMIZED_VERTICALLY(w) ((w)->maximized_vertically)
|
||||
#define META_WINDOW_MAXIMIZED_HORIZONTALLY(w) ((w)->maximized_horizontally)
|
||||
#define META_WINDOW_TILED(w) ((w)->maximized_vertically && \
|
||||
!(w)->maximized_horizontally && \
|
||||
(w)->tile_mode != META_TILE_NONE)
|
||||
#define META_WINDOW_ALLOWS_MOVE(w) ((w)->has_move_func && !(w)->fullscreen)
|
||||
#define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w) ((w)->has_resize_func && !META_WINDOW_MAXIMIZED (w) && !(w)->fullscreen && !(w)->shaded)
|
||||
#define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w) ((w)->has_resize_func && !META_WINDOW_MAXIMIZED (w) && !META_WINDOW_TILED(w) && !(w)->fullscreen && !(w)->shaded)
|
||||
#define META_WINDOW_ALLOWS_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && \
|
||||
(((w)->size_hints.min_width < (w)->size_hints.max_width) || \
|
||||
((w)->size_hints.min_height < (w)->size_hints.max_height)))
|
||||
@@ -411,6 +436,11 @@ void meta_window_queue (MetaWindow *window,
|
||||
void meta_window_maximize_internal (MetaWindow *window,
|
||||
MetaMaximizeFlags directions,
|
||||
MetaRectangle *saved_rect);
|
||||
void meta_window_unmaximize_with_gravity (MetaWindow *window,
|
||||
MetaMaximizeFlags directions,
|
||||
int new_width,
|
||||
int new_height,
|
||||
int gravity);
|
||||
void meta_window_make_above (MetaWindow *window);
|
||||
void meta_window_unmake_above (MetaWindow *window);
|
||||
void meta_window_shade (MetaWindow *window,
|
||||
@@ -493,8 +523,6 @@ void meta_window_get_geometry (MetaWindow *window,
|
||||
void meta_window_kill (MetaWindow *window);
|
||||
void meta_window_focus (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
void meta_window_raise (MetaWindow *window);
|
||||
void meta_window_lower (MetaWindow *window);
|
||||
|
||||
void meta_window_update_unfocused_button_grabs (MetaWindow *window);
|
||||
|
||||
@@ -544,13 +572,16 @@ GList* meta_window_get_workspaces (MetaWindow *window);
|
||||
gboolean meta_window_located_on_workspace (MetaWindow *window,
|
||||
MetaWorkspace *workspace);
|
||||
|
||||
void meta_window_get_work_area_current_xinerama (MetaWindow *window,
|
||||
MetaRectangle *area);
|
||||
void meta_window_get_work_area_for_xinerama (MetaWindow *window,
|
||||
int which_xinerama,
|
||||
MetaRectangle *area);
|
||||
void meta_window_get_work_area_all_xineramas (MetaWindow *window,
|
||||
MetaRectangle *area);
|
||||
void meta_window_get_work_area_current_monitor (MetaWindow *window,
|
||||
MetaRectangle *area);
|
||||
void meta_window_get_work_area_for_monitor (MetaWindow *window,
|
||||
int which_monitor,
|
||||
MetaRectangle *area);
|
||||
void meta_window_get_work_area_all_monitors (MetaWindow *window,
|
||||
MetaRectangle *area);
|
||||
|
||||
void meta_window_get_current_tile_area (MetaWindow *window,
|
||||
MetaRectangle *tile_area);
|
||||
|
||||
|
||||
gboolean meta_window_same_application (MetaWindow *window,
|
||||
@@ -569,12 +600,6 @@ void meta_window_refresh_resize_popup (MetaWindow *window);
|
||||
|
||||
void meta_window_free_delete_dialog (MetaWindow *window);
|
||||
|
||||
void meta_window_foreach_transient (MetaWindow *window,
|
||||
MetaWindowForeachFunc func,
|
||||
void *data);
|
||||
void meta_window_foreach_ancestor (MetaWindow *window,
|
||||
MetaWindowForeachFunc func,
|
||||
void *data);
|
||||
|
||||
void meta_window_begin_grab_op (MetaWindow *window,
|
||||
MetaGrabOp op,
|
||||
@@ -597,10 +622,6 @@ void meta_window_stack_just_below (MetaWindow *window,
|
||||
void meta_window_set_user_time (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
|
||||
void meta_window_set_demands_attention (MetaWindow *window);
|
||||
|
||||
void meta_window_unset_demands_attention (MetaWindow *window);
|
||||
|
||||
void meta_window_update_icon_now (MetaWindow *window);
|
||||
|
||||
void meta_window_update_role (MetaWindow *window);
|
||||
|
||||
@@ -442,7 +442,7 @@ set_title_text (MetaWindow *window,
|
||||
XDeleteProperty (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
atom);
|
||||
meta_error_trap_pop (window->display, FALSE);
|
||||
meta_error_trap_pop (window->display);
|
||||
}
|
||||
|
||||
return modified;
|
||||
@@ -523,6 +523,49 @@ reload_wm_name (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
reload_mutter_hints (MetaWindow *window,
|
||||
MetaPropValue *value,
|
||||
gboolean initial)
|
||||
{
|
||||
if (value->type != META_PROP_VALUE_INVALID)
|
||||
{
|
||||
char *new_hints = value->v.str;
|
||||
char *old_hints = window->mutter_hints;
|
||||
gboolean changed = FALSE;
|
||||
|
||||
if (new_hints)
|
||||
{
|
||||
if (!old_hints || strcmp (new_hints, old_hints))
|
||||
changed = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (old_hints)
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
g_free (old_hints);
|
||||
|
||||
if (new_hints)
|
||||
window->mutter_hints = g_strdup (new_hints);
|
||||
else
|
||||
window->mutter_hints = NULL;
|
||||
|
||||
g_object_notify (G_OBJECT (window), "mutter-hints");
|
||||
}
|
||||
}
|
||||
else if (window->mutter_hints)
|
||||
{
|
||||
g_free (window->mutter_hints);
|
||||
window->mutter_hints = NULL;
|
||||
|
||||
g_object_notify (G_OBJECT (window), "mutter-hints");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_icon_title (MetaWindow *window,
|
||||
const char *title)
|
||||
@@ -604,6 +647,7 @@ reload_net_wm_state (MetaWindow *window,
|
||||
window->shaded = FALSE;
|
||||
window->maximized_horizontally = FALSE;
|
||||
window->maximized_vertically = FALSE;
|
||||
window->fullscreen = FALSE;
|
||||
window->wm_state_modal = FALSE;
|
||||
window->wm_state_skip_taskbar = FALSE;
|
||||
window->wm_state_skip_pager = FALSE;
|
||||
@@ -632,13 +676,7 @@ reload_net_wm_state (MetaWindow *window,
|
||||
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_SKIP_PAGER)
|
||||
window->wm_state_skip_pager = TRUE;
|
||||
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_FULLSCREEN)
|
||||
{
|
||||
if (!window->fullscreen)
|
||||
{
|
||||
window->fullscreen = TRUE;
|
||||
g_object_notify (G_OBJECT (window), "fullscreen");
|
||||
}
|
||||
}
|
||||
window->fullscreen_after_placement = TRUE;
|
||||
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_ABOVE)
|
||||
window->wm_state_above = TRUE;
|
||||
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_BELOW)
|
||||
@@ -1350,8 +1388,10 @@ reload_wm_hints (MetaWindow *window,
|
||||
gboolean initial)
|
||||
{
|
||||
Window old_group_leader;
|
||||
|
||||
gboolean old_urgent;
|
||||
|
||||
old_group_leader = window->xgroup_leader;
|
||||
old_urgent = window->wm_hints_urgent;
|
||||
|
||||
/* Fill in defaults */
|
||||
window->input = TRUE;
|
||||
@@ -1359,7 +1399,8 @@ reload_wm_hints (MetaWindow *window,
|
||||
window->xgroup_leader = None;
|
||||
window->wm_hints_pixmap = None;
|
||||
window->wm_hints_mask = None;
|
||||
|
||||
window->wm_hints_urgent = FALSE;
|
||||
|
||||
if (value->type != META_PROP_VALUE_INVALID)
|
||||
{
|
||||
const XWMHints *hints = value->v.wm_hints;
|
||||
@@ -1378,7 +1419,10 @@ reload_wm_hints (MetaWindow *window,
|
||||
|
||||
if (hints->flags & IconMaskHint)
|
||||
window->wm_hints_mask = hints->icon_mask;
|
||||
|
||||
|
||||
if (hints->flags & XUrgencyHint)
|
||||
window->wm_hints_urgent = TRUE;
|
||||
|
||||
meta_verbose ("Read WM_HINTS input: %d iconic: %d group leader: 0x%lx pixmap: 0x%lx mask: 0x%lx\n",
|
||||
window->input, window->initially_iconic,
|
||||
window->xgroup_leader,
|
||||
@@ -1394,6 +1438,21 @@ reload_wm_hints (MetaWindow *window,
|
||||
meta_window_group_leader_changed (window);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not emit urgency notification on the inital property load
|
||||
*/
|
||||
if (!initial && (window->wm_hints_urgent != old_urgent))
|
||||
g_object_notify (G_OBJECT (window), "urgent");
|
||||
|
||||
/*
|
||||
* Do not emit signal for the initial property load, let the constructor to
|
||||
* take care of it once the MetaWindow is fully constructed.
|
||||
*
|
||||
* Only emit if the property is both changed and set.
|
||||
*/
|
||||
if (!initial && window->wm_hints_urgent && !old_urgent)
|
||||
g_signal_emit_by_name (window->display, "window-marked-urgent", window);
|
||||
|
||||
meta_icon_cache_property_changed (&window->icon_cache,
|
||||
window->display,
|
||||
XA_WM_HINTS);
|
||||
@@ -1490,6 +1549,7 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
|
||||
{ XA_WM_CLASS, META_PROP_VALUE_CLASS_HINT, reload_wm_class, TRUE, TRUE },
|
||||
{ display->atom__NET_WM_PID, META_PROP_VALUE_CARDINAL, reload_net_wm_pid, TRUE, TRUE },
|
||||
{ XA_WM_NAME, META_PROP_VALUE_TEXT_PROPERTY, reload_wm_name, TRUE, TRUE },
|
||||
{ display->atom__MUTTER_HINTS, META_PROP_VALUE_TEXT_PROPERTY, reload_mutter_hints, TRUE, TRUE },
|
||||
{ display->atom__NET_WM_ICON_NAME, META_PROP_VALUE_UTF8, reload_net_wm_icon_name, TRUE, FALSE },
|
||||
{ XA_WM_ICON_NAME, META_PROP_VALUE_TEXT_PROPERTY, reload_wm_icon_name, TRUE, FALSE },
|
||||
{ display->atom__NET_WM_DESKTOP, META_PROP_VALUE_CARDINAL, reload_net_wm_desktop, TRUE, FALSE },
|
||||
|
||||
1272
src/core/window.c
1272
src/core/window.c
File diff suppressed because it is too large
Load Diff
@@ -47,12 +47,12 @@ struct _MetaWorkspace
|
||||
GList *list_containing_self;
|
||||
|
||||
MetaRectangle work_area_screen;
|
||||
MetaRectangle *work_area_xinerama;
|
||||
MetaRectangle *work_area_monitor;
|
||||
GList *screen_region;
|
||||
GList **xinerama_region;
|
||||
gint n_xinerama_regions;
|
||||
GList **monitor_region;
|
||||
gint n_monitor_regions;
|
||||
GList *screen_edges;
|
||||
GList *xinerama_edges;
|
||||
GList *monitor_edges;
|
||||
GSList *builtin_struts;
|
||||
GSList *all_struts;
|
||||
guint work_areas_invalid : 1;
|
||||
@@ -77,14 +77,12 @@ void meta_workspace_relocate_windows (MetaWorkspace *workspace,
|
||||
void meta_workspace_invalidate_work_area (MetaWorkspace *workspace);
|
||||
|
||||
|
||||
void meta_workspace_get_work_area_for_xinerama (MetaWorkspace *workspace,
|
||||
int which_xinerama,
|
||||
void meta_workspace_get_work_area_for_monitor (MetaWorkspace *workspace,
|
||||
int which_monitor,
|
||||
MetaRectangle *area);
|
||||
GList* meta_workspace_get_onscreen_region (MetaWorkspace *workspace);
|
||||
GList* meta_workspace_get_onxinerama_region (MetaWorkspace *workspace,
|
||||
int which_xinerama);
|
||||
void meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
|
||||
MetaRectangle *area);
|
||||
GList* meta_workspace_get_onmonitor_region (MetaWorkspace *workspace,
|
||||
int which_monitor);
|
||||
|
||||
void meta_workspace_focus_default_window (MetaWorkspace *workspace,
|
||||
MetaWindow *not_this_one,
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <config.h>
|
||||
#include "workspace.h"
|
||||
#include "workspace-private.h"
|
||||
#include "boxes-private.h"
|
||||
#include "errors.h"
|
||||
#include "prefs.h"
|
||||
|
||||
@@ -33,6 +34,9 @@
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_LIBCANBERRA
|
||||
#include <canberra-gtk.h>
|
||||
#endif
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
@@ -170,16 +174,16 @@ meta_workspace_new (MetaScreen *screen)
|
||||
meta_screen_foreach_window (screen, maybe_add_to_list, &workspace->mru_list);
|
||||
|
||||
workspace->work_areas_invalid = TRUE;
|
||||
workspace->work_area_xinerama = NULL;
|
||||
workspace->work_area_monitor = NULL;
|
||||
workspace->work_area_screen.x = 0;
|
||||
workspace->work_area_screen.y = 0;
|
||||
workspace->work_area_screen.width = 0;
|
||||
workspace->work_area_screen.height = 0;
|
||||
|
||||
workspace->screen_region = NULL;
|
||||
workspace->xinerama_region = NULL;
|
||||
workspace->monitor_region = NULL;
|
||||
workspace->screen_edges = NULL;
|
||||
workspace->xinerama_edges = NULL;
|
||||
workspace->monitor_edges = NULL;
|
||||
workspace->list_containing_self = g_list_prepend (NULL, workspace);
|
||||
|
||||
workspace->builtin_struts = NULL;
|
||||
@@ -263,7 +267,7 @@ meta_workspace_remove (MetaWorkspace *workspace)
|
||||
workspace->screen->workspaces =
|
||||
g_list_remove (workspace->screen->workspaces, workspace);
|
||||
|
||||
g_free (workspace->work_area_xinerama);
|
||||
g_free (workspace->work_area_monitor);
|
||||
|
||||
g_list_free (workspace->mru_list);
|
||||
g_list_free (workspace->list_containing_self);
|
||||
@@ -280,12 +284,12 @@ meta_workspace_remove (MetaWorkspace *workspace)
|
||||
if (!workspace->work_areas_invalid)
|
||||
{
|
||||
workspace_free_all_struts (workspace);
|
||||
for (i = 0; i < screen->n_xinerama_infos; i++)
|
||||
meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]);
|
||||
g_free (workspace->xinerama_region);
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
meta_rectangle_free_list_and_elements (workspace->monitor_region[i]);
|
||||
g_free (workspace->monitor_region);
|
||||
meta_rectangle_free_list_and_elements (workspace->screen_region);
|
||||
meta_rectangle_free_list_and_elements (workspace->screen_edges);
|
||||
meta_rectangle_free_list_and_elements (workspace->xinerama_edges);
|
||||
meta_rectangle_free_list_and_elements (workspace->monitor_edges);
|
||||
}
|
||||
|
||||
g_object_unref (workspace);
|
||||
@@ -439,6 +443,69 @@ meta_workspace_queue_calc_showing (MetaWorkspace *workspace)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
workspace_switch_sound(MetaWorkspace *from,
|
||||
MetaWorkspace *to)
|
||||
{
|
||||
#ifdef HAVE_LIBCANBERRA
|
||||
MetaWorkspaceLayout layout;
|
||||
int i, nw, x, y, fi, ti;
|
||||
const char *e;
|
||||
|
||||
nw = meta_screen_get_n_workspaces(from->screen);
|
||||
fi = meta_workspace_index(from);
|
||||
ti = meta_workspace_index(to);
|
||||
|
||||
meta_screen_calc_workspace_layout(from->screen,
|
||||
nw,
|
||||
fi,
|
||||
&layout);
|
||||
|
||||
for (i = 0; i < nw; i++)
|
||||
if (layout.grid[i] == ti)
|
||||
break;
|
||||
|
||||
if (i >= nw)
|
||||
{
|
||||
meta_bug("Failed to find destination workspace in layout\n");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
y = i / layout.cols;
|
||||
x = i % layout.cols;
|
||||
|
||||
/* We priorize horizontal over vertical movements here. The
|
||||
rationale for this is that horizontal movements are probably more
|
||||
interesting for sound effects because speakers are usually
|
||||
positioned on a horizontal and not a vertical axis. i.e. your
|
||||
spatial "Woosh!" effects will easily be able to encode horizontal
|
||||
movement but not such much vertical movement. */
|
||||
|
||||
if (x < layout.current_col)
|
||||
e = "desktop-switch-left";
|
||||
else if (x > layout.current_col)
|
||||
e = "desktop-switch-right";
|
||||
else if (y < layout.current_row)
|
||||
e = "desktop-switch-up";
|
||||
else if (y > layout.current_row)
|
||||
e = "desktop-switch-down";
|
||||
else
|
||||
{
|
||||
meta_bug("Uh, origin and destination workspace at same logic position!\n");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ca_context_play(ca_gtk_context_get(), 1,
|
||||
CA_PROP_EVENT_ID, e,
|
||||
CA_PROP_EVENT_DESCRIPTION, "Desktop switched",
|
||||
CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
|
||||
NULL);
|
||||
|
||||
finish:
|
||||
meta_screen_free_workspace_layout (&layout);
|
||||
#endif /* HAVE_LIBCANBERRA */
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_workspace_activate_with_focus:
|
||||
* @workspace: a #MetaWorkspace
|
||||
@@ -478,6 +545,13 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
|
||||
if (workspace->screen->active_workspace == workspace)
|
||||
return;
|
||||
|
||||
/* Free any cached pointers to the workspaces's edges from
|
||||
* a current resize or move operation */
|
||||
meta_display_cleanup_edges (workspace->screen->display);
|
||||
|
||||
if (workspace->screen->active_workspace)
|
||||
workspace_switch_sound (workspace->screen->active_workspace, workspace);
|
||||
|
||||
/* Note that old can be NULL; e.g. when starting up */
|
||||
old = workspace->screen->active_workspace;
|
||||
|
||||
@@ -633,12 +707,12 @@ meta_workspace_update_window_hints (MetaWorkspace *workspace)
|
||||
|
||||
/**
|
||||
* meta_workspace_list_windows:
|
||||
* @display: a #MetaDisplay
|
||||
* @workspace: a #MetaWorkspace
|
||||
*
|
||||
* Gets windows contained on the workspace, including workspace->windows
|
||||
* and also sticky windows. Override-redirect windows are not included.
|
||||
*
|
||||
* Return value: (transfer container): the list of windows.
|
||||
* Return value: (transfer container) (element-type MetaWindow): the list of windows.
|
||||
*/
|
||||
GList*
|
||||
meta_workspace_list_windows (MetaWorkspace *workspace)
|
||||
@@ -691,7 +765,7 @@ set_active_space_hint (MetaScreen *screen)
|
||||
screen->display->atom__NET_CURRENT_DESKTOP,
|
||||
XA_CARDINAL,
|
||||
32, PropModeReplace, (guchar*) data, 1);
|
||||
meta_error_trap_pop (screen->display, FALSE);
|
||||
meta_error_trap_pop (screen->display);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -713,21 +787,26 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
|
||||
"Invalidating work area for workspace %d\n",
|
||||
meta_workspace_index (workspace));
|
||||
|
||||
g_free (workspace->work_area_xinerama);
|
||||
workspace->work_area_xinerama = NULL;
|
||||
/* If we are in the middle of a resize or move operation, we
|
||||
* might have cached pointers to the workspace's edges */
|
||||
if (workspace == workspace->screen->active_workspace)
|
||||
meta_display_cleanup_edges (workspace->screen->display);
|
||||
|
||||
g_free (workspace->work_area_monitor);
|
||||
workspace->work_area_monitor = NULL;
|
||||
|
||||
workspace_free_all_struts (workspace);
|
||||
|
||||
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
|
||||
meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]);
|
||||
g_free (workspace->xinerama_region);
|
||||
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
|
||||
meta_rectangle_free_list_and_elements (workspace->monitor_region[i]);
|
||||
g_free (workspace->monitor_region);
|
||||
meta_rectangle_free_list_and_elements (workspace->screen_region);
|
||||
meta_rectangle_free_list_and_elements (workspace->screen_edges);
|
||||
meta_rectangle_free_list_and_elements (workspace->xinerama_edges);
|
||||
workspace->xinerama_region = NULL;
|
||||
meta_rectangle_free_list_and_elements (workspace->monitor_edges);
|
||||
workspace->monitor_region = NULL;
|
||||
workspace->screen_region = NULL;
|
||||
workspace->screen_edges = NULL;
|
||||
workspace->xinerama_edges = NULL;
|
||||
workspace->monitor_edges = NULL;
|
||||
|
||||
workspace->work_areas_invalid = TRUE;
|
||||
|
||||
@@ -780,10 +859,10 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
||||
return;
|
||||
|
||||
g_assert (workspace->all_struts == NULL);
|
||||
g_assert (workspace->xinerama_region == NULL);
|
||||
g_assert (workspace->monitor_region == NULL);
|
||||
g_assert (workspace->screen_region == NULL);
|
||||
g_assert (workspace->screen_edges == NULL);
|
||||
g_assert (workspace->xinerama_edges == NULL);
|
||||
g_assert (workspace->monitor_edges == NULL);
|
||||
|
||||
/* STEP 1: Get the list of struts */
|
||||
|
||||
@@ -803,18 +882,18 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
||||
g_list_free (windows);
|
||||
|
||||
/* STEP 2: Get the maximal/spanning rects for the onscreen and
|
||||
* on-single-xinerama regions
|
||||
* on-single-monitor regions
|
||||
*/
|
||||
g_assert (workspace->xinerama_region == NULL);
|
||||
g_assert (workspace->monitor_region == NULL);
|
||||
g_assert (workspace->screen_region == NULL);
|
||||
|
||||
workspace->xinerama_region = g_new (GList*,
|
||||
workspace->screen->n_xinerama_infos);
|
||||
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
|
||||
workspace->monitor_region = g_new (GList*,
|
||||
workspace->screen->n_monitor_infos);
|
||||
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
|
||||
{
|
||||
workspace->xinerama_region[i] =
|
||||
workspace->monitor_region[i] =
|
||||
meta_rectangle_get_minimal_spanning_set_for_region (
|
||||
&workspace->screen->xinerama_infos[i].rect,
|
||||
&workspace->screen->monitor_infos[i].rect,
|
||||
workspace->all_struts);
|
||||
}
|
||||
workspace->screen_region =
|
||||
@@ -823,7 +902,7 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
||||
workspace->all_struts);
|
||||
|
||||
/* STEP 3: Get the work areas (region-to-maximize-to) for the screen and
|
||||
* xineramas.
|
||||
* monitors.
|
||||
*/
|
||||
work_area = workspace->screen->rect; /* start with the screen */
|
||||
if (workspace->screen_region == NULL)
|
||||
@@ -878,35 +957,35 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
||||
workspace->work_area_screen.width,
|
||||
workspace->work_area_screen.height);
|
||||
|
||||
/* Now find the work areas for each xinerama */
|
||||
g_free (workspace->work_area_xinerama);
|
||||
workspace->work_area_xinerama = g_new (MetaRectangle,
|
||||
workspace->screen->n_xinerama_infos);
|
||||
/* Now find the work areas for each monitor */
|
||||
g_free (workspace->work_area_monitor);
|
||||
workspace->work_area_monitor = g_new (MetaRectangle,
|
||||
workspace->screen->n_monitor_infos);
|
||||
|
||||
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
|
||||
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
|
||||
{
|
||||
work_area = workspace->screen->xinerama_infos[i].rect;
|
||||
work_area = workspace->screen->monitor_infos[i].rect;
|
||||
|
||||
if (workspace->xinerama_region[i] == NULL)
|
||||
if (workspace->monitor_region[i] == NULL)
|
||||
/* FIXME: constraints.c untested with this, but it might be nice for
|
||||
* a screen reader or magnifier.
|
||||
*/
|
||||
work_area = meta_rect (work_area.x, work_area.y, -1, -1);
|
||||
else
|
||||
meta_rectangle_clip_to_region (workspace->xinerama_region[i],
|
||||
meta_rectangle_clip_to_region (workspace->monitor_region[i],
|
||||
FIXED_DIRECTION_NONE,
|
||||
&work_area);
|
||||
|
||||
workspace->work_area_xinerama[i] = work_area;
|
||||
workspace->work_area_monitor[i] = work_area;
|
||||
meta_topic (META_DEBUG_WORKAREA,
|
||||
"Computed work area for workspace %d "
|
||||
"xinerama %d: %d,%d %d x %d\n",
|
||||
"monitor %d: %d,%d %d x %d\n",
|
||||
meta_workspace_index (workspace),
|
||||
i,
|
||||
workspace->work_area_xinerama[i].x,
|
||||
workspace->work_area_xinerama[i].y,
|
||||
workspace->work_area_xinerama[i].width,
|
||||
workspace->work_area_xinerama[i].height);
|
||||
workspace->work_area_monitor[i].x,
|
||||
workspace->work_area_monitor[i].y,
|
||||
workspace->work_area_monitor[i].width,
|
||||
workspace->work_area_monitor[i].height);
|
||||
}
|
||||
|
||||
/* STEP 4: Make sure the screen_region is nonempty (separate from step 2
|
||||
@@ -920,17 +999,17 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
||||
workspace->screen_region = g_list_prepend (NULL, nonempty_region);
|
||||
}
|
||||
|
||||
/* STEP 5: Cache screen and xinerama edges for edge resistance and snapping */
|
||||
/* STEP 5: Cache screen and monitor edges for edge resistance and snapping */
|
||||
g_assert (workspace->screen_edges == NULL);
|
||||
g_assert (workspace->xinerama_edges == NULL);
|
||||
g_assert (workspace->monitor_edges == NULL);
|
||||
workspace->screen_edges =
|
||||
meta_rectangle_find_onscreen_edges (&workspace->screen->rect,
|
||||
workspace->all_struts);
|
||||
tmp = NULL;
|
||||
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
|
||||
tmp = g_list_prepend (tmp, &workspace->screen->xinerama_infos[i].rect);
|
||||
workspace->xinerama_edges =
|
||||
meta_rectangle_find_nonintersected_xinerama_edges (tmp,
|
||||
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
|
||||
tmp = g_list_prepend (tmp, &workspace->screen->monitor_infos[i].rect);
|
||||
workspace->monitor_edges =
|
||||
meta_rectangle_find_nonintersected_monitor_edges (tmp,
|
||||
workspace->all_struts);
|
||||
g_list_free (tmp);
|
||||
|
||||
@@ -950,10 +1029,27 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
strut_lists_equal (GSList *l,
|
||||
GSList *m)
|
||||
{
|
||||
for (; l && m; l = l->next, m = m->next)
|
||||
{
|
||||
MetaStrut *a = l->data;
|
||||
MetaStrut *b = m->data;
|
||||
|
||||
if (a->side != b->side ||
|
||||
!meta_rectangle_equal (&a->rect, &b->rect))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return l == NULL && m == NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_workspace_set_builtin_struts:
|
||||
* @workspace: a #MetaWorkspace
|
||||
* @struts: (element-type Strut) (transfer none): list of #MetaStrut
|
||||
* @struts: (element-type Meta.Strut) (transfer none): list of #MetaStrut
|
||||
*
|
||||
* Sets a list of struts that will be used in addition to the struts
|
||||
* of the windows in the workspace when computing the work area of
|
||||
@@ -963,6 +1059,12 @@ void
|
||||
meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
|
||||
GSList *struts)
|
||||
{
|
||||
/* Reordering doesn't actually matter, so we don't catch all
|
||||
* no-impact changes, but this is just a (possibly unnecessary
|
||||
* anyways) optimization */
|
||||
if (strut_lists_equal (struts, workspace->builtin_struts))
|
||||
return;
|
||||
|
||||
workspace_free_builtin_struts (workspace);
|
||||
workspace->builtin_struts = copy_strut_list (struts);
|
||||
|
||||
@@ -970,21 +1072,21 @@ meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
|
||||
}
|
||||
|
||||
void
|
||||
meta_workspace_get_work_area_for_xinerama (MetaWorkspace *workspace,
|
||||
int which_xinerama,
|
||||
MetaRectangle *area)
|
||||
meta_workspace_get_work_area_for_monitor (MetaWorkspace *workspace,
|
||||
int which_monitor,
|
||||
MetaRectangle *area)
|
||||
{
|
||||
g_assert (which_xinerama >= 0);
|
||||
g_assert (which_monitor >= 0);
|
||||
|
||||
ensure_work_areas_validated (workspace);
|
||||
g_assert (which_xinerama < workspace->screen->n_xinerama_infos);
|
||||
g_assert (which_monitor < workspace->screen->n_monitor_infos);
|
||||
|
||||
*area = workspace->work_area_xinerama[which_xinerama];
|
||||
*area = workspace->work_area_monitor[which_monitor];
|
||||
}
|
||||
|
||||
void
|
||||
meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
|
||||
MetaRectangle *area)
|
||||
meta_workspace_get_work_area_all_monitors (MetaWorkspace *workspace,
|
||||
MetaRectangle *area)
|
||||
{
|
||||
ensure_work_areas_validated (workspace);
|
||||
|
||||
@@ -1000,12 +1102,12 @@ meta_workspace_get_onscreen_region (MetaWorkspace *workspace)
|
||||
}
|
||||
|
||||
GList*
|
||||
meta_workspace_get_onxinerama_region (MetaWorkspace *workspace,
|
||||
int which_xinerama)
|
||||
meta_workspace_get_onmonitor_region (MetaWorkspace *workspace,
|
||||
int which_monitor)
|
||||
{
|
||||
ensure_work_areas_validated (workspace);
|
||||
|
||||
return workspace->xinerama_region[which_xinerama];
|
||||
return workspace->monitor_region[which_monitor];
|
||||
}
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
@@ -1202,7 +1304,10 @@ focus_ancestor_or_mru_window (MetaWorkspace *workspace,
|
||||
MetaWindow *ancestor;
|
||||
ancestor = NULL;
|
||||
meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor);
|
||||
if (ancestor != NULL)
|
||||
if (ancestor != NULL &&
|
||||
(ancestor->on_all_workspaces ||
|
||||
ancestor->workspace == workspace) &&
|
||||
meta_window_showing_on_its_workspace (ancestor))
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing %s, ancestor of %s\n",
|
||||
|
||||
@@ -126,7 +126,7 @@ validate_or_free_results (GetPropertyResults *results,
|
||||
type_name = XGetAtomName (results->display->xdisplay, results->type);
|
||||
expected_name = XGetAtomName (results->display->xdisplay, expected_type);
|
||||
prop_name = XGetAtomName (results->display->xdisplay, results->xatom);
|
||||
meta_error_trap_pop (results->display, TRUE);
|
||||
meta_error_trap_pop (results->display);
|
||||
|
||||
w = meta_display_lookup_x_window (results->display, results->xwindow);
|
||||
|
||||
@@ -204,11 +204,11 @@ get_property (MetaDisplay *display,
|
||||
{
|
||||
if (results->prop)
|
||||
XFree (results->prop);
|
||||
meta_error_trap_pop_with_return (display, TRUE);
|
||||
meta_error_trap_pop_with_return (display);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (meta_error_trap_pop_with_return (display, TRUE) != Success)
|
||||
if (meta_error_trap_pop_with_return (display) != Success)
|
||||
{
|
||||
if (results->prop)
|
||||
XFree (results->prop);
|
||||
@@ -264,6 +264,16 @@ cardinal_list_from_results (GetPropertyResults *results,
|
||||
*n_cardinals_p = results->n_items;
|
||||
results->prop = NULL;
|
||||
|
||||
#if GLIB_SIZEOF_LONG == 8
|
||||
/* Xlib sign-extends format=32 items, but we want them unsigned */
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < *n_cardinals_p; i++)
|
||||
(*cardinals_p)[i] = (*cardinals_p)[i] & 0xffffffff;
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -480,7 +490,7 @@ utf8_list_from_results (GetPropertyResults *results,
|
||||
|
||||
meta_error_trap_push (results->display);
|
||||
name = XGetAtomName (results->display->xdisplay, results->xatom);
|
||||
meta_error_trap_pop (results->display, TRUE);
|
||||
meta_error_trap_pop (results->display);
|
||||
meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n"),
|
||||
name, results->xwindow, i);
|
||||
meta_XFree (name);
|
||||
@@ -537,7 +547,7 @@ meta_prop_set_utf8_string_hint (MetaDisplay *display,
|
||||
xwindow, atom,
|
||||
display->atom_UTF8_STRING,
|
||||
8, PropModeReplace, (guchar*) val, strlen (val));
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -608,6 +618,10 @@ cardinal_with_atom_type_from_results (GetPropertyResults *results,
|
||||
return FALSE;
|
||||
|
||||
*cardinal_p = *(gulong*) results->prop;
|
||||
#if GLIB_SIZEOF_LONG == 8
|
||||
/* Xlib sign-extends format=32 items, but we want them unsigned */
|
||||
*cardinal_p &= 0xffffffff;
|
||||
#endif
|
||||
XFree (results->prop);
|
||||
results->prop = NULL;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user