Compare commits
766 Commits
wip/sassWi
...
wip/halfli
Author | SHA1 | Date | |
---|---|---|---|
832240a80b | |||
629f408fe5 | |||
86c6ab3c01 | |||
4a6ff94701 | |||
e480b08d58 | |||
caf53861d1 | |||
d0480648ba | |||
eb8cfe799f | |||
b9f2541880 | |||
bde9b08bfe | |||
8a4c862633 | |||
785c90f4b8 | |||
dd6a11e4c7 | |||
64e9503adb | |||
36c885bf34 | |||
ad7cde805d | |||
2c2c67f4dc | |||
cc4f8dfab0 | |||
0fb13608c5 | |||
09dbe17da0 | |||
fdd347c9aa | |||
572095515b | |||
f2d4aa0822 | |||
030a22d795 | |||
c70afcdb44 | |||
526d6c03b8 | |||
261b55300d | |||
e13bfd9a17 | |||
e096d18bac | |||
9460f0e4f3 | |||
e6591f52ac | |||
07e3d1fd5c | |||
1fbc6b24c8 | |||
982777be94 | |||
6610a34ad0 | |||
bfa8a0441a | |||
7723622ec7 | |||
6bcc8c70ef | |||
d114d5f95a | |||
b5c734da42 | |||
2077bb94c1 | |||
65a4ee7fb4 | |||
debf293298 | |||
a0df3e7d1e | |||
0d67c2d164 | |||
682bd7b622 | |||
fa0e54edbb | |||
5a0b209663 | |||
7e8859fd0e | |||
444fa2e0ab | |||
a31455b921 | |||
ac0213a516 | |||
45a6e2c305 | |||
11cbd396c0 | |||
a343445cd2 | |||
be3d62487c | |||
58905bd01a | |||
08506eac2d | |||
02c6b0374d | |||
0722c06275 | |||
17a4044d97 | |||
27a7194634 | |||
d73f560bcc | |||
e92f43b83e | |||
fed79ce4e6 | |||
fc45cf03bf | |||
efde11a0f3 | |||
fb951ff9b5 | |||
f5865e895e | |||
b8c2d4c6c7 | |||
778ad49ab4 | |||
fe7dd1305f | |||
378a3df5ea | |||
e63b81d69c | |||
c2fa2cdd8a | |||
6f215427f8 | |||
67ed4e0570 | |||
8a15178557 | |||
f3ecfab378 | |||
804563d5b2 | |||
c3e5d983b9 | |||
d21edcfed5 | |||
9b69a45eee | |||
7424ee755a | |||
ff664fd1d8 | |||
fd3f03580d | |||
a09150846a | |||
f2a9c55637 | |||
eaa3f83e46 | |||
e786cc1454 | |||
cd0c632fcb | |||
d5f248cb82 | |||
6a800abe06 | |||
fe265554a7 | |||
7305466765 | |||
9ac55a98f1 | |||
a1149fb6ad | |||
dfc4cc4aaf | |||
ef7541291b | |||
248a3e6b7e | |||
6b1e381750 | |||
feaf6108f9 | |||
9ad104585d | |||
7c44af3616 | |||
0599bf41b0 | |||
eac303f84c | |||
7bdd1c625c | |||
0003760fd9 | |||
eafb8c8e38 | |||
60c8105559 | |||
54626c6f7e | |||
cca528a630 | |||
530193a3a2 | |||
52e3149040 | |||
ad297ea9dc | |||
2015fc97dc | |||
35889a0f7d | |||
dcd84a4b53 | |||
01374989b1 | |||
f300462003 | |||
1e4da1b99c | |||
e1de6cb98d | |||
59a18c4ead | |||
b881e4b62a | |||
7060ae077b | |||
a7b0910566 | |||
60706f72d4 | |||
2e77f6b34b | |||
50d5030949 | |||
03dbb0f931 | |||
249619fabd | |||
60d1f7797c | |||
dc4b8c876e | |||
1724723e63 | |||
02455b1e28 | |||
47a9b97f8b | |||
0aa29daa72 | |||
182b1c1941 | |||
bbc8010de3 | |||
15baa56584 | |||
a72683707f | |||
f4baa4ddf8 | |||
f9eb36434f | |||
bc5e16bcea | |||
86e04048ff | |||
d7c0ff5e89 | |||
51e1efa277 | |||
67f636cc68 | |||
fcdfebd0e7 | |||
069ec3b910 | |||
1092f55b54 | |||
8a8abf12f9 | |||
f044e29526 | |||
4f703019ca | |||
0e6baec350 | |||
08690d658f | |||
674325e96c | |||
f8aa486ad1 | |||
be78f0f36a | |||
9917f05be8 | |||
d23228522c | |||
8c9896561e | |||
23cdb2125e | |||
43fc598bd5 | |||
2105d2f952 | |||
d18ec919dd | |||
da3e5f9746 | |||
594a227bc1 | |||
7277744dc0 | |||
e4718d3f7f | |||
5afd04781c | |||
a0868bac6b | |||
265b1f0292 | |||
2c12f3a509 | |||
0141a2be9e | |||
6660342d2f | |||
92667e3b7f | |||
a0632e3e02 | |||
c6d2946ce6 | |||
86304418a9 | |||
2f228e21da | |||
8521556723 | |||
9f5ac0e6d5 | |||
cc38dd1d49 | |||
66a5c0c094 | |||
8e802fd32f | |||
e87656af16 | |||
8327dbd611 | |||
e1b575dddc | |||
018025dada | |||
49fe0335ee | |||
bbe417121c | |||
0068098996 | |||
36d9cc329d | |||
1f2e53dd15 | |||
048a14f1f3 | |||
fd6ef482f0 | |||
d8926b96e2 | |||
934ec3c3fe | |||
216e996f66 | |||
a4b5583995 | |||
b00a1d6b7f | |||
d24abab4a8 | |||
23a9fb0314 | |||
5e26d0c90c | |||
aeb971c33a | |||
8897385714 | |||
e2a17fa8b4 | |||
14da6b68dc | |||
9a01a7ae07 | |||
c3bf4a325d | |||
2d71456944 | |||
9934529a0b | |||
ef6e8f5bb2 | |||
2ce7a3baa6 | |||
c0d224e200 | |||
4b2e5a4375 | |||
fbecbca9a0 | |||
c312891774 | |||
486d4dfb68 | |||
169b00aa64 | |||
f2c1a416bf | |||
28ef88911c | |||
e2161f385d | |||
f0c0687b43 | |||
e76e874093 | |||
d2a0cfb6d4 | |||
e5270cb6ec | |||
ee360d8749 | |||
bb4e6fd2da | |||
651600ac19 | |||
67f4cf3cff | |||
9b76e9f90a | |||
ba919b9c6a | |||
4da2862f8f | |||
b1de1ada25 | |||
1002bbc212 | |||
15e42c4d5f | |||
bb61dd4b44 | |||
2d4ba30ba2 | |||
54f46e8486 | |||
0ee762263a | |||
826682cc07 | |||
8b6e566728 | |||
e4a20e51e2 | |||
173ff91640 | |||
438d0d4feb | |||
8f275a79a9 | |||
a504dd866b | |||
dfc51ef243 | |||
a25d2dc256 | |||
b2ae945cf2 | |||
681861c8c7 | |||
6d40cb98e7 | |||
81d7ab1e49 | |||
2212b4ea71 | |||
5650355da5 | |||
20a9206919 | |||
3533b2a8bc | |||
b8d2238ff0 | |||
96c8870820 | |||
177e9316b0 | |||
27b7e6ef4b | |||
32d686d90f | |||
f812e9be7d | |||
c7185d597b | |||
6380526c12 | |||
fa4f6c4561 | |||
a5b7eaec1a | |||
d165295c83 | |||
5f5874f8ca | |||
ab5e950cd0 | |||
3e760f5ca6 | |||
9e8a24467e | |||
d84d1f79a0 | |||
024ec36cc0 | |||
51b1258866 | |||
ff1b76f4c7 | |||
0389ae5299 | |||
35ab60b712 | |||
0ea15f70c3 | |||
f1c7a36dde | |||
cc9093f118 | |||
775a2ea051 | |||
cb3d5c2b51 | |||
dc1c31d704 | |||
777616d8b0 | |||
8aeebbbf78 | |||
dade67ba5a | |||
921a9071a1 | |||
90a08ba0b6 | |||
4e52ed9df7 | |||
01b51cd081 | |||
d1efc274e5 | |||
d48d787c1e | |||
e4ad31a5dd | |||
b61cb92053 | |||
e72450f5d8 | |||
d9211b8e20 | |||
c16b83fc3e | |||
8b5a44e119 | |||
b0be6b8678 | |||
bb73547acf | |||
d8fc58e174 | |||
b9fdffbb62 | |||
e48a83fcfc | |||
4c7eae7ef2 | |||
75745fc23f | |||
82479db084 | |||
9becb3985d | |||
4cb7df67b7 | |||
e0a12f55b9 | |||
b18240370d | |||
4253df6463 | |||
d8b43865a2 | |||
3eb8b9ef68 | |||
f96077bd0f | |||
741846d1ff | |||
f36d7bd078 | |||
bd51c92d65 | |||
2aed6ade79 | |||
83e5ea4827 | |||
5915348396 | |||
567dc70c9b | |||
8323891294 | |||
5bf8695295 | |||
7012437929 | |||
83ad98d640 | |||
1816f763d2 | |||
1a01f07b2c | |||
23d48fb334 | |||
dada0420b1 | |||
17a336c795 | |||
8c347965d7 | |||
e1816cd228 | |||
3614da6845 | |||
8aa1765f24 | |||
8eb0782f25 | |||
5f6aba7f4b | |||
986b14fb1b | |||
7c03b88b74 | |||
1f277ebcb9 | |||
8c54bc68e0 | |||
6e39be5b19 | |||
cf71ea016f | |||
4affa5528a | |||
8536f9312c | |||
a0e8456cb5 | |||
77074b5646 | |||
cd68ed8297 | |||
eaef067b3e | |||
e23dfe533d | |||
39ecd3b5a8 | |||
f5e07fbeba | |||
ef3077a7fe | |||
4ff489d24b | |||
0ebba112d7 | |||
e7fa83ea1a | |||
b58f08bda1 | |||
3ec764d584 | |||
2c6443fd29 | |||
bb2d7f7e7e | |||
39a57eea4d | |||
d8505934e8 | |||
8f424e7d96 | |||
39fd7b9a05 | |||
60f6715228 | |||
1c36ade125 | |||
ebf132770e | |||
8f902a9379 | |||
6bb905895c | |||
99af774c98 | |||
42a214aa24 | |||
6c3dd2d4e0 | |||
eadc39356f | |||
8eb236ae41 | |||
707cc9e315 | |||
fab25e18da | |||
e01076a48b | |||
38a2f26e44 | |||
88cde2a97d | |||
b4bfe9a0c6 | |||
55df98298a | |||
a101f46544 | |||
afc2253e5d | |||
db4076b697 | |||
313ee70cf7 | |||
61c5f259ec | |||
874cf0ba15 | |||
f1370ef578 | |||
8f136e46d4 | |||
8a732d3c13 | |||
ad3e24e0bb | |||
f85d68aa70 | |||
6c5861ab3d | |||
be52ad999f | |||
5a47ad837b | |||
11e4f5c094 | |||
79c04c93e4 | |||
f015f4574f | |||
3b914ed4f7 | |||
bb7a99968f | |||
fdd6fc976c | |||
c60eb857bf | |||
147d192fa3 | |||
39b823dcec | |||
99ef24ba44 | |||
e34e183282 | |||
4ab275080c | |||
5a3b9a034e | |||
08d753fd29 | |||
7d058901ef | |||
0023059fa3 | |||
58da16c786 | |||
4a38359635 | |||
714bc5f103 | |||
d56411729b | |||
b3a96f2f6c | |||
5f5dc8327f | |||
c9bcb411fc | |||
86c6716786 | |||
46fe11a541 | |||
c2104dbf85 | |||
e23a03d639 | |||
ad92584b72 | |||
bf57397cb8 | |||
19cef181ad | |||
1a255d988b | |||
890a809022 | |||
530e8273ff | |||
62e9978c52 | |||
8d7db75fc5 | |||
6a504f5c62 | |||
b376a5dcdd | |||
dfd00d5483 | |||
13dbc3f15d | |||
22ac75556c | |||
8e665da103 | |||
7846fdbd2c | |||
99d61062e1 | |||
b37496d086 | |||
db2b83edf3 | |||
971179a10a | |||
ea855442be | |||
0a70909f10 | |||
abc43c9ece | |||
5bdaffd36e | |||
4660015bb1 | |||
634e5ff9e0 | |||
c79d24b60e | |||
509464fd61 | |||
d5d9f6283d | |||
560835dd0c | |||
8e40aa96ba | |||
4e7261532c | |||
3836cab769 | |||
79fc1a2383 | |||
c749facedb | |||
83648cf7d0 | |||
16914ddda3 | |||
167610c580 | |||
945caed602 | |||
7d2690ac5a | |||
a23f87de5e | |||
d6bb3de2fd | |||
c02b66bad1 | |||
880b240ecb | |||
078aafb10c | |||
4e7000988d | |||
d6d1fec4bd | |||
27318a8967 | |||
07664e7d2f | |||
6da0ebe35f | |||
af4e84383d | |||
1c1f63a7d7 | |||
8dab692f93 | |||
4de20272e5 | |||
ad75739fc5 | |||
1c5b73bfdf | |||
c045ab6171 | |||
1d23539576 | |||
71ae7e69c5 | |||
4c91db4661 | |||
09c38fda51 | |||
2b65d24ac1 | |||
2d3aff3f04 | |||
01056d72ab | |||
39d59b6eb6 | |||
cd5318baa7 | |||
67eade6482 | |||
30c6e541f1 | |||
e8a023a78f | |||
87ae45a12f | |||
ec66b32df6 | |||
815eaa1d4d | |||
8ecf901dd4 | |||
53b3d2a6c2 | |||
a3c1c09cc1 | |||
71f59de797 | |||
8032e672e9 | |||
f6c84d6185 | |||
e189a34fc0 | |||
aedc2428be | |||
faf00036e2 | |||
d903e831f3 | |||
4eff643d59 | |||
8c72c93aae | |||
d6eea0e380 | |||
1ef5281c55 | |||
77413feb57 | |||
830b4559c0 | |||
4a709792cd | |||
f2d0fcabd1 | |||
9c9da8a176 | |||
b81be42d08 | |||
485cd0f278 | |||
08d2e617e1 | |||
06586eb95d | |||
b00f122fcf | |||
11b3ed276b | |||
dfd887066f | |||
025985eb07 | |||
65a5baa902 | |||
e404369c0f | |||
88c7039ebe | |||
efc0ec4740 | |||
7d1382afd3 | |||
e850d9e29b | |||
464f552dd2 | |||
053e54f944 | |||
f84addcadc | |||
de27e4e1b2 | |||
33c5f5726e | |||
26330fde7e | |||
39cfe488a4 | |||
df81c98b65 | |||
43ada376f8 | |||
e317bfdab7 | |||
f38263a67f | |||
3a03a36533 | |||
9f3a7ab432 | |||
f3f887da73 | |||
443e0e6b1f | |||
8b65871c90 | |||
59b9ffa864 | |||
c9965f43c1 | |||
fada6645a2 | |||
e516b40c8c | |||
2c795f7d05 | |||
94438e9d69 | |||
4d12baea02 | |||
f34b5a04a1 | |||
5c5ed37b8b | |||
3e40168e54 | |||
a2a7ca6882 | |||
ce5a82a294 | |||
462bfccc7e | |||
61be034c6d | |||
da49b8110e | |||
7b3eeefc85 | |||
fc1849b475 | |||
ef999930f6 | |||
402676be84 | |||
c68abfbacf | |||
2758c71cf7 | |||
b772a14cbd | |||
8d66fff2aa | |||
75e0894de0 | |||
fbef56b602 | |||
c398e02700 | |||
48cfd35b65 | |||
ce38ae64cc | |||
98e6fd9cfb | |||
b30ecd29d8 | |||
a0df7aa2b8 | |||
e2500092fd | |||
cbeebbf264 | |||
aebf641d2d | |||
1c8af221af | |||
f0ef47a70a | |||
5f0030edf7 | |||
dde91ab9a6 | |||
3680f7c814 | |||
a27ca0765a | |||
fa76e39717 | |||
aa5c722eca | |||
1fd968d520 | |||
ef3285d5e7 | |||
e71b0a57fb | |||
333becef45 | |||
3732a6891d | |||
6a5e3ea12d | |||
4cf6293066 | |||
ee673cc5c4 | |||
604bb1fe82 | |||
1f83911bb6 | |||
95a6e52f1a | |||
5e9d491480 | |||
068ebbf2a6 | |||
6bc222f37b | |||
6cf53a8d1c | |||
95e141e47e | |||
b053f4c74b | |||
d0d60fbd93 | |||
a6f572e49a | |||
bd49559357 | |||
ec6841429f | |||
98ccc45f80 | |||
868a199144 | |||
7be4238aa2 | |||
cb698f9a09 | |||
d2dad4f0fa | |||
cdbb39b9e4 | |||
bfbb442b9d | |||
3531052e69 | |||
c9f9ac0f35 | |||
3ccdc5f8ba | |||
ac3e315a47 | |||
6972bc90f2 | |||
a2a5a3c908 | |||
d8b2cd5f8e | |||
3b759f7966 | |||
0ded0dbfd5 | |||
bca8e371b0 | |||
c2f5813463 | |||
f4301147bb | |||
ea9e5bc52c | |||
f08e2b72d2 | |||
240cdc6565 | |||
aa2ae29ad8 | |||
a4fb55b4ca | |||
5a8923ef95 | |||
a71ab9abb2 | |||
5cddab3305 | |||
c4a775e94a | |||
c7031d9e56 | |||
d113c92b5f | |||
3ba8a578e8 | |||
7aa75f8eb0 | |||
98d3a6772f | |||
625a38f605 | |||
8d617166fe | |||
ae4e82c82b | |||
7bb7734869 | |||
2f554e27f2 | |||
b4c8a00e38 | |||
f755e73a48 | |||
12cb023050 | |||
299ec4f368 | |||
4da7f20759 | |||
ea66329423 | |||
39d3ff6caf | |||
513d1a195d | |||
d54b87c455 | |||
397460d64c | |||
1900468846 | |||
fb6598ac10 | |||
12b00501cc | |||
c647be375a | |||
7b31d2146a | |||
3b846f0e9c | |||
21056a967f | |||
ead4c2b863 | |||
086fcd4a32 | |||
b82f11acf3 | |||
1da9546c40 | |||
e69cc20fc7 | |||
c363e2a322 | |||
dd0c3296bb | |||
52048c03da | |||
c8765eeebd | |||
b9b9faacbd | |||
d04340c675 | |||
c556d28b98 | |||
a333bfec19 | |||
19fbbfd74d | |||
f393bb41aa | |||
4bf53cd507 | |||
fd45d3589b | |||
6efa9e46ca | |||
9f5a2d8aca | |||
ce35d523a2 | |||
0bfaa5c6a3 | |||
67ec1e5519 | |||
cc05d303d8 | |||
554de3fb24 | |||
76315fca9f | |||
af889168f0 | |||
d8ca374a06 | |||
19c7da7b08 | |||
42ccfe0ccd | |||
538272bb23 | |||
985e909876 | |||
d183f13456 | |||
e150a9cff2 | |||
60b3d43ea7 | |||
e3a8a284a4 | |||
3136ca086b | |||
3f913b2895 | |||
8345fe006e | |||
67a807e849 | |||
cea946e745 | |||
966ae2c370 | |||
897144baba | |||
f585fee4cf | |||
85ec77eb26 | |||
2d372e6201 | |||
cb84c3a921 | |||
fce3cd534a | |||
3291281957 | |||
01c6392c13 | |||
186f9b2e2c | |||
2c8e405e27 | |||
94446eb8c4 | |||
6803528810 | |||
2aa4fb02dd | |||
906106c700 | |||
0257a23c31 | |||
e0eebc90e0 | |||
ddeac2386f | |||
7b9be2188a | |||
117a81e06f | |||
522fe8e8bf | |||
73480255b1 | |||
09d3f8eb71 | |||
0592adead5 | |||
b21f5c5566 | |||
7602260462 | |||
0448effd82 | |||
90dedccc87 | |||
b29e8a1a3d | |||
9689a9ba8b | |||
4eb0a672db | |||
cad56c871a | |||
0acc7ed4c2 | |||
2940ef07e9 | |||
deddac8748 | |||
f4cc3327e8 | |||
977448b6bc | |||
d69eceab3b | |||
ed7649c93a | |||
af6ed9e02a | |||
983314333f | |||
26389f92f5 | |||
1e8e5d4671 | |||
31d375093e | |||
546ae00854 | |||
e00bfcc2cf | |||
943f6c9d28 | |||
dbf16d6ea3 | |||
77b0c07410 | |||
e36eb02ab0 | |||
2935fd4ffe | |||
5961f162fa | |||
5d440fa8d9 | |||
3d4408dce8 | |||
ea707dcd75 | |||
196429a18f | |||
487b5cd0a9 | |||
891f30ff63 | |||
45e42d7b9e | |||
facaea6850 | |||
e467a734a1 | |||
050378743e | |||
25bf2ff87a | |||
551b96d79f |
2
.gitignore
vendored
@ -32,6 +32,7 @@ data/org.gnome.shell.evolution.calendar.gschema.xml
|
||||
data/org.gnome.shell.evolution.calendar.gschema.valid
|
||||
data/org.gnome.Shell.PortalHelper.desktop
|
||||
data/org.gnome.Shell.PortalHelper.service
|
||||
data/theme/.sass-cache
|
||||
docs/reference/*/*.args
|
||||
docs/reference/*/*.bak
|
||||
docs/reference/*/*.hierarchy
|
||||
@ -86,6 +87,7 @@ src/gnome-shell-perf-helper
|
||||
src/gnome-shell-perf-tool
|
||||
src/gnome-shell-portal-helper
|
||||
src/hotplug-sniffer/org.gnome.Shell.HotplugSniffer.service
|
||||
src/org-gtk-application.[ch]
|
||||
src/run-js-test
|
||||
src/test-recorder
|
||||
src/test-recorder.ogg
|
||||
|
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
||||
[submodule "src/gvc"]
|
||||
path = src/gvc
|
||||
url = git://git.gnome.org/libgnome-volume-control
|
||||
[submodule "data/theme/gnome-shell-sass"]
|
||||
path = data/theme/gnome-shell-sass
|
||||
url = git://git.gnome.org/gnome-shell-sass
|
||||
|
327
NEWS
@ -1,3 +1,330 @@
|
||||
3.17.92
|
||||
=======
|
||||
* Fix race when loading multiple background animations [Josselin; #741453]
|
||||
|
||||
Contributors:
|
||||
Michael Biebl, Josselin Mouette, Florian Müllner
|
||||
|
||||
Translations:
|
||||
Baurzhan Muftakhidinov [kk], Changwoo Ryu [ko], Christian Kirbach [de],
|
||||
Kjartan Maraas [nb], Jiri Grönroos [fi], Arash Mousavi [fa],
|
||||
Jiro Matsuzawa [ja], Marek Černocký [cs], Milo Casagrande [it]
|
||||
|
||||
3.17.91
|
||||
=======
|
||||
* Fix login screen spinner causing wakeups while VT-switched away
|
||||
[Ray, Rui; #753891]
|
||||
* Fix scrolling of user list on login screen [Florian; #754525]
|
||||
|
||||
Contributors:
|
||||
Piotr Drąg, Rui Matos, Florian Müllner, Ray Strode
|
||||
|
||||
Translations:
|
||||
Dušan Kazik [sk], Jordi Mas [ca], Aurimas Černius [lt], Stas Solovey [ru],
|
||||
Piotr Drąg [pl], Pedro Albuquerque [pt], Daniel Mustieles [es],
|
||||
Chao-Hsiung Liao [zh_TW], Muhammet Kara [tr], Fran Dieguez [gl],
|
||||
Hannie Dumoleyn [nl], Yosef Or Boczko [he], Tom Tryfonidis [el],
|
||||
A S Alam [pa], Balázs Úr [hu], Alexandre Franke [fr], Frédéric Péters [fr]
|
||||
|
||||
3.17.90
|
||||
=======
|
||||
* Avoid caret/focus viewport changes during pointer movement [Rui; #752138]
|
||||
* Match GTK+'s modal dialogs for system modal dialogs [Carlos; #746108]
|
||||
* Refine message list style [Florian; #749958]
|
||||
* Fix type-ahead behavior for backspace and compose key [Rui; #753319, #753320]
|
||||
* Refine the system status menu [Florian; #751377]
|
||||
* Misc. bug fixes and cleanups [Bastien, Ray, Florian, Jakub; #752779, #752739,
|
||||
#741366, #651503, #753064, #753181, #752881]
|
||||
|
||||
Contributors:
|
||||
Rui Matos, Florian Müllner, Bastien Nocera, Carlos Soriano, Jakub Steiner,
|
||||
Ray Strode, Rico Tzschichholz
|
||||
|
||||
Translations:
|
||||
Marek Černocký [cs], Kjartan Maraas [nb], Jordi Mas [ca], Muhammet Kara [tr],
|
||||
Enrico Nicoletto [pt_BR]
|
||||
|
||||
3.17.4
|
||||
======
|
||||
* Fix fuzziness of app menu icon [Jakub; #747932]
|
||||
* Implement 4 finger swipe gesture for touchpads [Carlos; #752250]
|
||||
* Misc. bug fixes [Florian, Alexandre, Piotr, Ray, Mario; #751921, #659969,
|
||||
#752438, #752675]
|
||||
|
||||
Contributors:
|
||||
Piotr Drąg, Alexandre Franke, Carlos Garnacho, Florian Müllner,
|
||||
Mario Sanchez Prada, Jakub Steiner, Jasper St. Pierre, Ray Strode
|
||||
|
||||
Translations:
|
||||
Benjamin Steinwender [de], Pedro Albuquerque [pt], Fabio Tomat [fur],
|
||||
Matej Urbančič [sl], Daniel Mustieles [es], Yosef Or Boczko [he],
|
||||
Daniel Martinez [an]
|
||||
|
||||
3.17.3
|
||||
======
|
||||
* Handle touch events in OSK on wayland [Rui; #750287]
|
||||
* Reinstate left/right movement to window menu [Ron; #751344]
|
||||
* Allow extensions to disable "Window is ready" notification [Adel; #748846]
|
||||
* Misc. bug fixes [Watson, Michael, Ray, Rui, Florian, Cosimo; #750465,
|
||||
#751016, #751517, #750714, #751541, #751599]
|
||||
|
||||
Contributors:
|
||||
Michael Biebl, Cosimo Cecchi, Adel Gadllah, Rui Matos, Florian Müllner,
|
||||
Ray Strode, Wim Taymans, Ron Yorston, Watson Yuuma Sato
|
||||
|
||||
Translations:
|
||||
Sebastian Rasmussen [sv], Dimitris Spingos [el], Muhammet Kara [tr],
|
||||
Stas Solovey [ru], Benjamin Steinwender [de], Balázs Úr [hu],
|
||||
Victor Ibragimov [tg], Dušan Kazik [sk], Pedro Albuquerque [pt]
|
||||
|
||||
3.17.2
|
||||
======
|
||||
* Remove StTable widget [Florian; #703833]
|
||||
* Increase visibility of expanders in alt-tab popup [Jakub; #745058]
|
||||
* Ensure suspend inhibitors are released when VT switched away [Rui; #749228]
|
||||
* Use iio-sensor-proxy directly for orientation lock [Bastien; #749671]
|
||||
* Misc. bug fixes [Florian, Lan, Carlos; #749279, #749383, #749529, #749490,
|
||||
#749742]
|
||||
|
||||
Contributors:
|
||||
Carlos Garnacho, Ting-Wei Lan, Rui Matos, Florian Müllner, Bastien Nocera,
|
||||
Jakub Steiner
|
||||
|
||||
Translations:
|
||||
Yosef Or Boczko [he], sun [zh_CN], Felipe Braga [pt_BR],
|
||||
Victor Ibragimov [tg], Gábor Kelemen [hu], Cédric Valmary [oc],
|
||||
Dušan Kazik [sk], Kjartan Maraas [nb], Bruno Ramalhete [pt],
|
||||
Matej Urbančič [sl], Daniel Mustieles [es]
|
||||
|
||||
3.17.1
|
||||
======
|
||||
* Add Display Settings entry to background menu [Meet; #697346]
|
||||
* Add window menu option to move to different monitor [Isaac; #633994]
|
||||
* Improve switch style in default/highContrast themes [Jakub; #746294, #747912]
|
||||
* Make event highlight in calendar more prominent [Jakub; #747715]
|
||||
* Fix keyboard focus when focusing a notification banner [Florian; #747205]
|
||||
* Move notification banners below the dateMenu [Meet, Florian; #745910]
|
||||
* Misc. bug fixes [Mario, Rui; #748338, #748541]
|
||||
|
||||
Contributors:
|
||||
Isaac Ge, Rui Matos, Florian Müllner, Meet Parikh, Mario Sanchez Prada,
|
||||
Jakub Steiner, Jasper St. Pierre
|
||||
|
||||
Translations:
|
||||
Sveinn í Felli [is], Marek Černocký [cs], laurent Soleil [oc]
|
||||
|
||||
3.16.1
|
||||
======
|
||||
* gdm: Move long session chooser menus to the side [Florian; #734352]
|
||||
* Work around background corruption with NVIDIA driver [Rui; #739178]
|
||||
* Don't allow move-to-workspace for always-sticky windows [Florian; #746782]
|
||||
* Allow switching workspaces with PgUp/PgDown in overview [Devyani; #742581]
|
||||
* Bump time PAM messages are displayed [Sarvjeet; #720885]
|
||||
* Fix "stutter" when moving window past the last workspace [Shivam; #712778]
|
||||
* Fix blurred text on login screen [Clément; #746912]
|
||||
* keyboard: Restore whole MRU list after password mode [Rui; #746605]
|
||||
* Pass event timestamps when activating remote actions [Owen; #747323]
|
||||
* Fix hung login screen when password is typed too quickly [Shivam; #737586]
|
||||
* Make on-screen keyboard work for shell chrome on wayland [Rui; #747274]
|
||||
* Implement reexec_self() for FreeBSD [Ting-Wei; #747788]
|
||||
* Allow to dismiss resident notifications [Florian; #746860]
|
||||
* Temporarily reveal legacy tray when icons are added [Florian; #746025]
|
||||
* Make concealed tray smaller to minimize overlap with apps [Florian; #746787]
|
||||
* Misc. bug fixes [Florian, Rui, Giovanni; #746323, #746579, #746902, #746364,
|
||||
#746509, #747636]
|
||||
|
||||
Contributors:
|
||||
Sarvjeet, Giovanni Campagna, Adel Gadllah, Clément Guérin, Devyani Kota,
|
||||
Ting-Wei Lan, Rui Matos, Shivam Mishra, Florian Müllner, Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Khaled Hosny [ar], Dušan Kazik [sk], Yuri Myasoedov [ru], Stas Solovey [ru],
|
||||
Hannie Dumoleyn [nl], Rūdolfs Mazurs [lv]
|
||||
|
||||
3.16.0
|
||||
======
|
||||
* Revert erroneous login dialog changes [Ray; #740142]
|
||||
* Improve accessibility of legacy tray [Florian; #746487]
|
||||
* Fix legacy status icons leaking into other monitors [Florian; #745824]
|
||||
|
||||
Contributors:
|
||||
Florian Müllner, Ray Strode
|
||||
|
||||
Translations:
|
||||
Daniel Martinez [an], Sebastian Rasmussen [sv], Fran Dieguez [gl],
|
||||
Andika Triwidada [id], Jordi Mas [ca], Kjartan Maraas [nb],
|
||||
Inaki Larranaga Murgoitio [eu], Muhammet Kara [tr], Khaled Hosny [ar],
|
||||
Bernd Homuth [de], Jiro Matsuzawa [ja]
|
||||
|
||||
3.15.92
|
||||
=======
|
||||
* gdm: Fix user list accessibility [Florian; #729603]
|
||||
* Handle multiline questions in mount operations [Ross; #745713]
|
||||
* Improve classic theme [Jakub; #745686, #745687]
|
||||
* Fix ordering of calendar events [Florian; #745988]
|
||||
* Pick first input source for new windows when per-window [Rui; #746037]
|
||||
* networkAgent: Show a notification for non-user-initiated password requests
|
||||
[Giovanni; #660293]
|
||||
* Fix dismissing calendar events [Florian; #744927]
|
||||
* Add legacy tray to ctrl-alt-tab popup [Florian; #746022]
|
||||
* Manage on-screen-keyboard visibility in gnome-shell [Carlos; #745977]
|
||||
* Add pointer barriers to legacy tray [Cosimo; #746026]
|
||||
* Use fallback when app icon cannot be resolved [Cosimo; #746219]
|
||||
* Fix handling of removed smartcard at startup [Ray; #740143]
|
||||
* gdm: Don't pick a random session for the user [Jasper; #740142]
|
||||
* Make menu selection behavior consistent with GTK [Florian; #745246]
|
||||
* gdm: Fix empty user list on user switching [Ray; #719418]
|
||||
* Misc bug fixes [Florian, Giovanni, Clément, Rui; #745666, #746019, #745861,
|
||||
#746027, #746223, #737502, #746343, #746288]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Cosimo Cecchi, Piotr Drąg, Adel Gadllah, Carlos Garnacho,
|
||||
Clément Guérin, Ross Lagerwall, Rui Matos, Florian Müllner, Jakub Steiner,
|
||||
Jasper St. Pierre, Ray Strode
|
||||
|
||||
Translations:
|
||||
Piotr Drąg [pl], Changwoo Ryu [ko], Milo Casagrande [it],
|
||||
Baurzhan Muftakhidinov [kk], Мирослав Николић [sr, sr@latin], Balázs Úr [hu],
|
||||
IWAI, Masaharu [ja], Daniel Korostil [uk], Aurimas Černius [lt],
|
||||
Matej Urbančič [sl], Daniel Mustieles [es], Kjartan Maraas [nb],
|
||||
Victor Ibragimov [tg], Claude Paroz [fr], Jordi Mas [ca], Bernd Homuth [de],
|
||||
Muhammet Kara [tr], Frédéric Péters [fr], Jiri Grönroos [fi],
|
||||
Alexander Shopov [bg], Stas Solovey [ru], Trần Ngọc Quân [vi],
|
||||
Samir Ribic [bs], Dušan Kazik [sk], Enrico Nicoletto [pt_BR],
|
||||
Marek Černocký [cs], A S Alam [pa], Ask Hjorth Larsen [da],
|
||||
Tom Tryfonidis [el], Alexandre Franke [fr], Yosef Or Boczko [he],
|
||||
Chao-Hsiung Liao [zh_TW]
|
||||
|
||||
3.15.91
|
||||
=======
|
||||
* Don't disable all shortcuts while non-panel menus are open [Florian; #745039]
|
||||
* Do not wake up the screen for disabled notifications [Florian; #744114]
|
||||
* Add unminimize animation [Florian; #702662]
|
||||
* Change default shortcut for viewing notifications [Florian; #687986]
|
||||
* Add shortcut to dismiss notifications from list [Florian; #745279]
|
||||
* Use Polari instead of Empathy for IRC conversations [Giovanni; #745431]
|
||||
* Add a hideable bottom tray for legacy status icons [Florian; #745162]
|
||||
* Improve accessibility of calendar/message list [Florian; #706903, #745393]
|
||||
* Fix window thumbnail scaling in overview [Sebastian; #744883]
|
||||
* Stop handling non-chat notifications for Empathy [Giovanni; #745503]
|
||||
* Fix mouse interaction with ibus candidate window [Rui; #745167, #745245]
|
||||
* Misc bug fixes and cleanups [Giovanni, Florian, Miguel, Cosimo, Jakub,
|
||||
Michele, Raul, Matthias, Rui; #677412, #744880, #744900, #744894, #744907,
|
||||
#745061, #741111, #744912, #745175, #745246, #744959, #744575, #745570,
|
||||
#652742, #659187, #745412, #745521, #745521, #741665, #745574, #745627,
|
||||
#745494, #745111, #745132, #745110]
|
||||
|
||||
Contributors:
|
||||
Michele, Giovanni Campagna, Cosimo Cecchi, Matthias Clasen,
|
||||
Raul Gutierrez Segales, Sebastian Keller, David Liang, Rui Matos,
|
||||
Florian Müllner, Yosef Or Boczko, Jakub Steiner, Jasper St. Pierre,
|
||||
Rico Tzschichholz, Miguel Vaello Martínez
|
||||
|
||||
Translations:
|
||||
Dušan Kazik [sk], Chao-Hsiung Liao [zh_TW], Muhammet Kara [tr],
|
||||
Balázs Úr [hu], Daniel Mustieles [es], Frédéric Péters [fr],
|
||||
Rafael Ferreira [pt_BR], Aurimas Černius [lt], Milo Casagrande [it],
|
||||
Yosef Or Boczko [he], Stas Solovey [ru], Baurzhan Muftakhidinov [kk],
|
||||
Daniel Korostil [uk], Fran Dieguez [gl], Kjartan Maraas [nb],
|
||||
Tom Tryfonidis [el], Cheng-Chia Tseng [zh_TW], Friedel Wolff [af],
|
||||
Alexandre Franke [fr], Efstathios Iosifidis [el], Aron Xu [zh_CN],
|
||||
Marek Černocký [cs], Enrico Nicoletto [pt_BR]
|
||||
|
||||
3.15.90
|
||||
=======
|
||||
* gdm: Fix reactivity of first user in user list [Ray; #743370]
|
||||
* Prevent DND to dash when favorites are locked down [David; #741325]
|
||||
* Prevent DND in app picker when favorites are locked down [Murray; #741325]
|
||||
* Implement Display panel's OSD monitor labels in the shell [Rui; #743744]
|
||||
* Remove GSystem dependency [Colin; #744457]
|
||||
* Do not duplicate "New Window" action in dash [Florian; #744446]
|
||||
* Fix 'draw-cursor' option of screen recorder [Alexander; #744599]
|
||||
* Fix screencast timestamps [Sebastian; #744642]
|
||||
* Allow keybindings for switching to VT8-VT12 [Ray; #744800]
|
||||
* Implement notification redesign [Florian; #744498, #744815, #744817, #744850]
|
||||
* Fix struts computation of chrome on non-primary monitors [Sylvain; #744183]
|
||||
* Visual refresh based on GTK+ theme redesign [Jakub, Carlos; #737785, #744680]
|
||||
* Misc. bug fixes and cleanups [Ray, Bastien, Cosimo, Rui, Florian; #743371,
|
||||
#736182, #744013, #743993, #744665]
|
||||
|
||||
Contributors:
|
||||
Cosimo Cecchi, Murray Cumming, Sebastian Dröge, David King,
|
||||
Alexander Larsson, Rui Matos, Florian Müllner, Bastien Nocera,
|
||||
Sylvain Pasche, Carlos Soriano, Jakub Steiner, Jasper St. Pierre, Ray Strode,
|
||||
Colin Walters
|
||||
|
||||
Translations:
|
||||
Daniel Martinez [an], Sveinn í Felli [is], GNOME Translation Robot [de],
|
||||
Yosef Or Boczko [he], Kristjan SCHMIDT [eo], Dušan Kazik [sk],
|
||||
Andika Triwidada [id], Marek Černocký [cs], Muhammet Kara [tr],
|
||||
Matej Urbančič [sl], Milo Casagrande [it], Anders Jonsson [sv]
|
||||
|
||||
3.15.4
|
||||
======
|
||||
* Add mode parameter to AcceleratorActivated signal [Florian; #711682]
|
||||
* Fix PID based window/app association [Sebastian; #736527]
|
||||
* Fix current day highlight on day change [Sebastian; #742492]
|
||||
* Switch to vp9 for screencast recordings [Adel; #742744]
|
||||
* Disable IBus input sources on password entries [Takao; #730628]
|
||||
* Make slider scrolling smoother [Adel; #742648]
|
||||
* Allow move-up shortcut to move window above top workspace [Florian; #665764]
|
||||
* Misc. bug fixes [Adel, Rui; #742748, #742824, #741114]
|
||||
|
||||
Contributors:
|
||||
Cosimo Cecchi, Takao Fujiwara, Adel Gadllah, Sebastian Keller, Rui Matos,
|
||||
Florian Müllner, Jasper St. Pierre
|
||||
|
||||
Translations:
|
||||
Andika Triwidada [id], Matej Urbančič [sl], Saibal Ray [bn_IN],
|
||||
Inaki Larranaga Murgoitio [eu], Stas Solovey [ru], Kjartan Maraas [nb],
|
||||
Balázs Úr [hu], Marek Černocký [cs], Rafael Ferreira [pt_BR],
|
||||
Bernd Homuth [de], Daniel Mustieles [es], Fabio Tomat [fur]
|
||||
|
||||
3.15.3
|
||||
======
|
||||
* Add support for high-contrast themes [Florian; #740447]
|
||||
* Fix banner message on login screen without user list [Ray; #703972]
|
||||
* Fix flicker when activating windows on another workspace [Florian; #741680]
|
||||
* Misc. bug fixes [Giovanni, Florian; #735308, #740237]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Florian Müllner, Jasper St. Pierre, Ray Strode
|
||||
|
||||
Translations:
|
||||
Balázs Úr [hu], Josef Andersson [sv], Muhammet Kara [tr],
|
||||
Baurzhan Muftakhidinov [kk], Inaki Larranaga Murgoitio [eu]
|
||||
|
||||
3.15.2
|
||||
======
|
||||
* Fix visual glitch of window preview outline in overview [Chris; #699044]
|
||||
* Change user facing name of "Captive Portal" to "Network Login" [Elad; #737198]
|
||||
* Port to Python 3 [Slavek; #732478]
|
||||
* Hide Airplane mode indicator when g-s-d says so [Cosimo; #736292]
|
||||
* Allow translators to change non-work days [Lavi; #664645]
|
||||
* Delay invocation of caribou daemon until really needed [Daiki; #739712]
|
||||
* Don't lock screen after crash if locking is disabled [Adel; #704884]
|
||||
* Improve layout of extension installation dialog [William; #739888]
|
||||
* Fix workspace changes from app picker [Yuki; #737534]
|
||||
* Preload all ibus input sources in user configuration [Takao; #695428]
|
||||
* Properly remove network connections from list [Ryan; #740227]
|
||||
* Support CSS margin property [Carlos; #728437]
|
||||
* Improve handling of BUSY application state [Phillip; #736492]
|
||||
* Fix erroneous week numbers in calendar [Florian; #736722]
|
||||
* Misc. bugfixes and cleanups [Darcy, Yuki, Alexander, Eskild, Bastien, Cosimo, Colin,
|
||||
Ray; #738725, #739497, #739241, #672500, #739822, #740074, #704163, #740141]
|
||||
|
||||
Contributors:
|
||||
Yuki, Lavi .A, Elad Alfassa, Cosimo Cecchi, Takao Fujiwara, Adel Gadllah,
|
||||
Eskild Hustvedt, Chris Johns, William Jon McCann, Slavek Kabrda, Ryan Lortie,
|
||||
Florian Müllner, Bastien Nocera, Christian Persch, Carlos Soriano,
|
||||
Jasper St. Pierre, Ray Strode, Alexander Tsoy, Daiki Ueno, Colin Walters,
|
||||
Phillip Wood
|
||||
|
||||
Translations:
|
||||
Jorge Perez Perez [an], Daniel Martinez [an], Daniel Mustieles [es],
|
||||
Trần Ngọc Quân [vi], Changwoo Ryu [ko], Kjartan Maraas [nb],
|
||||
Yosef Or Boczko [he], Marek Černocký [cs]
|
||||
|
||||
3.15.1
|
||||
======
|
||||
* Use GResources for theme loading [Cosimo; #736936]
|
||||
|
@ -4,8 +4,6 @@
|
||||
srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
PKG_NAME="gnome-shell"
|
||||
|
||||
(test -f $srcdir/configure.ac \
|
||||
&& test -d $srcdir/src) || {
|
||||
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
|
||||
@ -14,7 +12,7 @@ PKG_NAME="gnome-shell"
|
||||
}
|
||||
|
||||
# Fetch submodules if needed
|
||||
if test ! -f src/gvc/Makefile.am;
|
||||
if test ! -f src/gvc/Makefile.am || test ! -f data/theme/gnome-shell-sass/COPYING;
|
||||
then
|
||||
echo "+ Setting up submodules"
|
||||
git submodule init
|
||||
@ -26,4 +24,4 @@ which gnome-autogen.sh || {
|
||||
echo "your OS vendor's package manager)."
|
||||
exit 1
|
||||
}
|
||||
USE_GNOME2_MACROS=1 USE_COMMON_DOC_BUILD=yes . gnome-autogen.sh
|
||||
. gnome-autogen.sh
|
||||
|
30
configure.ac
@ -1,5 +1,5 @@
|
||||
AC_PREREQ(2.63)
|
||||
AC_INIT([gnome-shell],[3.15.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||
AC_INIT([gnome-shell],[3.17.92],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_SRCDIR([src/shell-global.c])
|
||||
@ -63,8 +63,8 @@ AC_ARG_ENABLE([systemd],
|
||||
[enable_systemd=$enableval],
|
||||
[enable_systemd=auto])
|
||||
AS_IF([test x$enable_systemd != xno], [
|
||||
AC_MSG_CHECKING([for libsystemd-journal])
|
||||
PKG_CHECK_EXISTS([libsystemd-journal],
|
||||
AC_MSG_CHECKING([for libsystemd])
|
||||
PKG_CHECK_EXISTS([libsystemd],
|
||||
[have_systemd=yes
|
||||
AC_DEFINE([HAVE_SYSTEMD], [1], [Define if we have systemd])],
|
||||
[have_systemd=no])
|
||||
@ -73,14 +73,14 @@ AS_IF([test x$enable_systemd != xno], [
|
||||
|
||||
AC_MSG_RESULT($enable_systemd)
|
||||
|
||||
CLUTTER_MIN_VERSION=1.15.90
|
||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
|
||||
CLUTTER_MIN_VERSION=1.21.5
|
||||
GOBJECT_INTROSPECTION_MIN_VERSION=1.45.4
|
||||
GJS_MIN_VERSION=1.39.0
|
||||
MUTTER_MIN_VERSION=3.15.1
|
||||
MUTTER_MIN_VERSION=3.17.92
|
||||
GTK_MIN_VERSION=3.15.0
|
||||
GIO_MIN_VERSION=2.37.0
|
||||
GIO_MIN_VERSION=2.45.3
|
||||
LIBECAL_MIN_VERSION=3.5.3
|
||||
LIBEDATASERVER_MIN_VERSION=3.5.3
|
||||
LIBEDATASERVER_MIN_VERSION=3.17.2
|
||||
TELEPATHY_GLIB_MIN_VERSION=0.17.5
|
||||
POLKIT_MIN_VERSION=0.100
|
||||
STARTUP_NOTIFICATION_MIN_VERSION=0.11
|
||||
@ -97,7 +97,6 @@ SHARED_PCS="gio-unix-2.0 >= $GIO_MIN_VERSION
|
||||
gjs-internals-1.0 >= $GJS_MIN_VERSION
|
||||
$recorder_modules
|
||||
gdk-x11-3.0 libsoup-2.4
|
||||
xtst
|
||||
clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
|
||||
clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
|
||||
libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_MIN_VERSION
|
||||
@ -107,7 +106,7 @@ SHARED_PCS="gio-unix-2.0 >= $GIO_MIN_VERSION
|
||||
polkit-agent-1 >= $POLKIT_MIN_VERSION
|
||||
gcr-base-3 >= $GCR_MIN_VERSION"
|
||||
if test x$have_systemd = xyes; then
|
||||
SHARED_PCS="${SHARED_PCS} libsystemd-journal"
|
||||
SHARED_PCS="${SHARED_PCS} libsystemd"
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(GNOME_SHELL, $SHARED_PCS)
|
||||
@ -119,8 +118,7 @@ PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
|
||||
PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0)
|
||||
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
|
||||
PKG_CHECK_MODULES(GVC, libpulse >= $PULSE_MIN_VERS libpulse-mainloop-glib gobject-2.0)
|
||||
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.4)
|
||||
PKG_CHECK_MODULES(CARIBOU, caribou-1.0 >= 0.4.8)
|
||||
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.13.1)
|
||||
|
||||
AC_ARG_ENABLE(browser-plugin,
|
||||
[AS_HELP_STRING([--enable-browser-plugin],
|
||||
@ -237,6 +235,14 @@ if test -z "${BROWSER_PLUGIN_DIR}"; then
|
||||
fi
|
||||
AC_ARG_VAR([BROWSER_PLUGIN_DIR],[Where to install the plugin to])
|
||||
|
||||
AC_ARG_VAR([GDBUS_CODEGEN],[the gdbus-codegen programme])
|
||||
AC_PATH_PROG([GDBUS_CODEGEN],[gdbus-codegen],[])
|
||||
if test -z "$GDBUS_CODEGEN"; then
|
||||
AC_MSG_ERROR([gdbus-codegen not found])
|
||||
fi
|
||||
|
||||
AC_PATH_PROG([SASS],[sass],[])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
data/Makefile
|
||||
|
@ -6,7 +6,7 @@
|
||||
package="gnome-shell">
|
||||
|
||||
<KeyListEntry name="toggle-message-tray"
|
||||
_description="Show the message tray"/>
|
||||
_description="Show the notification list"/>
|
||||
|
||||
<KeyListEntry name="focus-active-notification"
|
||||
_description="Focus the active notification"/>
|
||||
|
@ -1,4 +1,5 @@
|
||||
CLEANFILES =
|
||||
NULL =
|
||||
|
||||
desktopdir=$(datadir)/applications
|
||||
desktop_DATA = gnome-shell.desktop gnome-shell-wayland.desktop gnome-shell-extension-prefs.desktop
|
||||
@ -11,7 +12,8 @@ service_DATA = org.gnome.Shell.PortalHelper.service
|
||||
|
||||
CLEANFILES += \
|
||||
org.gnome.Shell.PortalHelper.service \
|
||||
org.gnome.Shell.PortalHelper.desktop
|
||||
org.gnome.Shell.PortalHelper.desktop \
|
||||
$(NULL)
|
||||
|
||||
endif
|
||||
|
||||
@ -33,7 +35,36 @@ introspection_DATA = \
|
||||
org.gnome.Shell.Screencast.xml \
|
||||
org.gnome.Shell.Screenshot.xml \
|
||||
org.gnome.ShellSearchProvider.xml \
|
||||
org.gnome.ShellSearchProvider2.xml
|
||||
org.gnome.ShellSearchProvider2.xml \
|
||||
$(NULL)
|
||||
|
||||
theme_sources = \
|
||||
theme/gnome-shell-high-contrast.scss \
|
||||
theme/gnome-shell.scss \
|
||||
theme/gnome-shell-sass/_colors.scss \
|
||||
theme/gnome-shell-sass/_common.scss \
|
||||
theme/gnome-shell-sass/_drawing.scss \
|
||||
theme/gnome-shell-sass/_high-contrast-colors.scss \
|
||||
$(NULL)
|
||||
|
||||
dist_theme_files = \
|
||||
$(theme_sources) \
|
||||
theme/Gemfile \
|
||||
theme/HACKING \
|
||||
theme/README \
|
||||
theme/gnome-shell-sass/COPYING \
|
||||
theme/gnome-shell-sass/HACKING \
|
||||
theme/gnome-shell-sass/NEWS \
|
||||
theme/gnome-shell-sass/README \
|
||||
theme/gnome-shell-sass/gnome-shell-sass.doap \
|
||||
theme/parse-sass.sh \
|
||||
$(NULL)
|
||||
|
||||
%.css: %.scss $(theme_sources)
|
||||
@if test -n "$(SASS)"; then \
|
||||
if $(AM_V_P); then PS4= set -x; else echo " GEN $@"; fi; \
|
||||
$(SASS) --sourcemap=none -f -q --update $<; \
|
||||
fi
|
||||
|
||||
resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir)/theme --generate-dependencies $(srcdir)/gnome-shell-theme.gresource.xml)
|
||||
gnome-shell-theme.gresource: gnome-shell-theme.gresource.xml $(resource_files)
|
||||
@ -80,12 +111,14 @@ EXTRA_DIST = \
|
||||
$(menu_DATA) \
|
||||
$(convert_DATA) \
|
||||
$(keys_in_files) \
|
||||
$(dist_theme_files) \
|
||||
perf-background.xml.in \
|
||||
org.gnome.Shell.PortalHelper.desktop.in \
|
||||
org.gnome.Shell.PortalHelper.service.in \
|
||||
org.gnome.shell.gschema.xml.in.in \
|
||||
gnome-shell-theme.gresource.xml \
|
||||
$(resource_files)
|
||||
$(resource_files) \
|
||||
$(NULL)
|
||||
|
||||
CLEANFILES += \
|
||||
gnome-shell.desktop.in \
|
||||
@ -98,4 +131,5 @@ CLEANFILES += \
|
||||
gschemas.compiled \
|
||||
org.gnome.shell.gschema.valid \
|
||||
org.gnome.shell.gschema.xml.in \
|
||||
gnome-shell-theme.gresource
|
||||
gnome-shell-theme.gresource \
|
||||
$(NULL)
|
||||
|
@ -16,8 +16,11 @@
|
||||
<file>filter-selected-ltr.svg</file>
|
||||
<file>filter-selected-rtl.svg</file>
|
||||
<file>gnome-shell.css</file>
|
||||
<file>gnome-shell-high-contrast.css</file>
|
||||
<file>logged-in-indicator.svg</file>
|
||||
<file>more-results.svg</file>
|
||||
<file>no-events.svg</file>
|
||||
<file>no-notifications.svg</file>
|
||||
<file>noise-texture.png</file>
|
||||
<file>page-indicator-active.svg</file>
|
||||
<file>page-indicator-inactive.svg</file>
|
||||
@ -29,8 +32,10 @@
|
||||
<file>summary-counter.svg</file>
|
||||
<file>toggle-off-us.svg</file>
|
||||
<file>toggle-off-intl.svg</file>
|
||||
<file>toggle-off-hc.svg</file>
|
||||
<file>toggle-on-us.svg</file>
|
||||
<file>toggle-on-intl.svg</file>
|
||||
<file>toggle-on-hc.svg</file>
|
||||
<file>ws-switch-arrow-up.png</file>
|
||||
<file>ws-switch-arrow-down.png</file>
|
||||
</gresource>
|
||||
|
@ -51,6 +51,7 @@
|
||||
</key>
|
||||
<key name="looking-glass-history" type="as">
|
||||
<default>[]</default>
|
||||
<!-- Translators: looking glass is a debugger and inspector tool, see https://live.gnome.org/GnomeShell/LookingGlass -->
|
||||
<_summary>History for the looking glass dialog</_summary>
|
||||
</key>
|
||||
<key name="always-show-log-out" type="b">
|
||||
@ -112,10 +113,10 @@
|
||||
</_description>
|
||||
</key>
|
||||
<key name="toggle-message-tray" type="as">
|
||||
<default>["<Super>m"]</default>
|
||||
<_summary>Keybinding to toggle the visibility of the message tray</_summary>
|
||||
<default>["<Super>v","<Super>m"]</default>
|
||||
<_summary>Keybinding to toggle the visibility of the notification list</_summary>
|
||||
<_description>
|
||||
Keybinding to toggle the visibility of the message tray.
|
||||
Keybinding to toggle the visibility of the notification list.
|
||||
</_description>
|
||||
</key>
|
||||
<key name="focus-active-notification" type="as">
|
||||
|
1
data/theme/Gemfile
Normal file
@ -0,0 +1 @@
|
||||
gem "sass", "~> 3.4.0"
|
3
data/theme/HACKING
Normal file
@ -0,0 +1,3 @@
|
||||
To generate the css files, from the project directory:
|
||||
|
||||
sass --sourcemap=none --update .
|
36
data/theme/README
Normal file
@ -0,0 +1,36 @@
|
||||
Summary
|
||||
-------
|
||||
|
||||
* Do not edit the CSS directly, edit the source SCSS files and process them with SASS (running
|
||||
`make` should do that when you have the required software installed, as described below;
|
||||
run `/.parse-sass.sh` manually if it doesn't)
|
||||
* To be able to use the lates/adequate version of sass, install ruby, gem, sass & bundle.
|
||||
On Fedora F20, this is done with `sudo dnf install rubygems && gem install bundle && bundle install`
|
||||
from the same directory this README resides in.
|
||||
|
||||
How to tweak the theme
|
||||
----------------------
|
||||
|
||||
Adwaita is a complex theme, so to keep it maintainable it's written and processed in SASS, the
|
||||
generated CSS is then transformed into a gresource file during gtk build and used at runtime in a
|
||||
non-legible or editable form.
|
||||
|
||||
It is very likely your change will happen in the _common.scss file. That's where all the widget
|
||||
selectors are defined. Here's a rundown of the "supporting" stylesheets, that are unlikely to be the
|
||||
right place for a drive by stylesheet fix:
|
||||
|
||||
_colors.scss - global color definitions. We keep the number of defined colors to a necessary minimum,
|
||||
most colors are derived from a handful of basics. It is an exact copy of the gtk+
|
||||
counterpart. Light theme is used for the classic theme and dark is for GNOME3 shell
|
||||
default.
|
||||
|
||||
_drawing.scss - drawing helper mixings/functions to allow easier definition of widget drawing under
|
||||
specific context. This is why Adwaita isn't 15000 LOC.
|
||||
|
||||
_common.scss - actual definitions of style for each widget. This is where you are likely to add/remove
|
||||
your changes.
|
||||
|
||||
You can read about SASS at http://sass-lang.com/documentation/. Once you make your changes to the
|
||||
_common.scss file, you can either run the ./parse-sass.sh script or keep SASS watching for changes as you
|
||||
edit. This is done by running `bundle exec sass --watch --sourcemap=none .` If sass is out of date, or is
|
||||
missing, you can install it with `bundle install`.
|
@ -1,44 +0,0 @@
|
||||
// When color definition differs for dark and light variant,
|
||||
// it gets @if ed depending on $variant
|
||||
|
||||
|
||||
$base_color: if($variant =='light', #ffffff, #292929);
|
||||
$bg_color: if($variant =='light', #ededed, #393f3f);
|
||||
$fg_color: if($variant =='light', #2e3436, #eeeeec);
|
||||
|
||||
$selected_fg_color: #ffffff;
|
||||
$selected_bg_color: if($variant == 'light', #4a90d9, darken(#4a90d9,20%));
|
||||
$selected_borders_color: if($variant=='light', darken($selected_bg_color, 30%),
|
||||
darken($selected_bg_color, 20%));
|
||||
$borders_color: if($variant =='light', darken($bg_color,30%), darken($bg_color,12%));
|
||||
$borders_edge: if($variant =='light', white, transparentize($fg_color, 0.9));
|
||||
$link_color: if($variant == 'light', darken($selected_bg_color,10%),
|
||||
lighten($selected_bg_color,20%));
|
||||
$link_visited_color: if($variant == 'light', darken($selected_bg_color,20%),
|
||||
lighten($selected_bg_color,10%));
|
||||
$top_hilight: $borders_edge;
|
||||
|
||||
$warning_color: #f57900;
|
||||
$error_color: #cc0000;
|
||||
$success_color: if($variant =='light', #73d216, darken(#73d216,10%));
|
||||
$destructive_color: if($variant =='light', #ef2929, darken(#ef2929,10%));
|
||||
|
||||
$osd_fg_color: #eeeeec;
|
||||
$osd_bg_color: #2e3436;
|
||||
$osd_borders_color: transparentize(black, 0.3);
|
||||
$osd_outer_borders_color: transparentize(white, 0.9);
|
||||
|
||||
$tooltip_borders_color: $osd_outer_borders_color;
|
||||
|
||||
//insensitive state derived colors
|
||||
$insensitive_fg_color: mix($fg_color, $bg_color, 50%);
|
||||
$insensitive_bg_color: mix($bg_color, $base_color, 60%);
|
||||
$insensitive_borders_color: $borders_color;
|
||||
|
||||
//colors for the backdrop state, derived from the main colors.
|
||||
$backdrop_base_color: if($variant =='light', darken($base_color,1%), lighten($base_color,1%));
|
||||
$backdrop_bg_color: $bg_color;
|
||||
$backdrop_fg_color: mix($fg_color, $backdrop_bg_color, 80%);
|
||||
$backdrop_insensitive_color: if($variant =='light', darken($backdrop_bg_color,15%), lighten($backdrop_bg_color,15%));
|
||||
$backdrop_borders_color: mix($borders_color, $bg_color, 90%);
|
||||
$backdrop_dark_fill: mix($backdrop_borders_color,$backdrop_bg_color, 35%);
|
@ -1,963 +0,0 @@
|
||||
//This is the RIGHT PLACE to edit the stylesheet
|
||||
|
||||
//let's start by telling people not to edit the generated CSS:
|
||||
$cakeisalie: "This stylesheet is generated, DO NOT EDIT";
|
||||
/* #{$cakeisalie} */
|
||||
|
||||
/* Copyright 2009, Red Hat, Inc.
|
||||
*
|
||||
* Portions adapted from Mx's data/style/default.css
|
||||
* Copyright 2009 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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 program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
/* GLOBALS */
|
||||
$font-size: 11;
|
||||
$font-family: Cantarell, Sans-Serif;
|
||||
|
||||
stage {
|
||||
font-family: $font-family;
|
||||
@include fontsize($font-size);
|
||||
color: $fg_color;
|
||||
}
|
||||
|
||||
/* WIDGETS */
|
||||
|
||||
/* Buttons */
|
||||
// one would think we may want a generic button class:
|
||||
// bug #737785
|
||||
.candidate-page-button,
|
||||
.notification-button,
|
||||
.notification-icon-button,
|
||||
.hotplug-notification-item,
|
||||
.hotplug-resident-eject-button,
|
||||
.modal-dialog-button,
|
||||
.app-view-control {
|
||||
border-radius: 3px;
|
||||
border-width: 1px;
|
||||
padding: 4px 32px;
|
||||
@include button(normal);
|
||||
&:hover { @include button(hover); }
|
||||
&:focus { @include button(focus); }
|
||||
&:insensitive { @include button(insensitive); }
|
||||
&:active { @include button(active); }
|
||||
}
|
||||
|
||||
/* Entries */
|
||||
StEntry {
|
||||
border-radius: 3px;
|
||||
padding: 4px;
|
||||
border-width: 1px;
|
||||
color: $fg_color;
|
||||
@include entry(normal);
|
||||
//&:hover { @include entry(hover);}
|
||||
&:focus { @include entry(focus,$fc:transparentize($fg_color,0.5));}
|
||||
&:insensitive { @include entry(insensitive);}
|
||||
selection-background-color: $selected_bg_color;
|
||||
selected-color: $selected_fg_color;
|
||||
}
|
||||
|
||||
|
||||
/* Scrollbars */
|
||||
|
||||
StScrollBar {
|
||||
padding: 0;
|
||||
&.vfade { -st-vfade-offset: 68px; }
|
||||
&.hfade { -st-hfade-offset: 68px; }
|
||||
|
||||
StScrollView & {
|
||||
min-width: 14px;
|
||||
min-height: 14px;
|
||||
}
|
||||
|
||||
StBin#trough {
|
||||
border-radius: 0;
|
||||
background-color: darken($bg_color,10%);
|
||||
}
|
||||
|
||||
StButton#vhandle, StButton#hhandle {
|
||||
border-radius: 8px;
|
||||
background-color: $bg_color;
|
||||
border: 3px solid darken($bg_color,10%); //would be nice to margin or at least to transparent
|
||||
&:hover { background-color: lighten($bg_color,10%); }
|
||||
&:active { background-color: $selected_bg_color; }
|
||||
}
|
||||
}
|
||||
|
||||
/* Slider */
|
||||
|
||||
.slider {
|
||||
height: 1em;
|
||||
-slider-height: 0.3em;
|
||||
-slider-background-color: $insensitive_bg_color; //background of the trough
|
||||
-slider-border-color: $borders_color; //trough border color
|
||||
-slider-active-background-color: $selected_bg_color; //active trough fill
|
||||
-slider-active-border-color: darken($selected_bg_color,10%); //active trough border
|
||||
-slider-border-width: 1px;
|
||||
-slider-handle-radius: 6px;
|
||||
}
|
||||
|
||||
/* Check Boxes */
|
||||
|
||||
.check-box {
|
||||
StBoxLayout { spacing: .8em; }
|
||||
StBin {
|
||||
width: 24px;
|
||||
height: 22px;
|
||||
background-image: url("checkbox-off.svg");
|
||||
}
|
||||
&:focus Stbin { background-image: url("checkbox-off-focused.svg"); }
|
||||
&:checked Stbin { background-image: url("checkbox.svg"); }
|
||||
&:focus:checked Stbin { background-image: url("checkbox-focused.svg"); }
|
||||
}
|
||||
|
||||
/* Switches */
|
||||
.toggle-switch {
|
||||
width: 65px;
|
||||
height: 22px;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
@each $v in us, intl {
|
||||
.toggle-switch-#{$v} {
|
||||
background-image: url("toggle-off-#{$v}.svg");
|
||||
&:checked { background-image: url("toggle-on-#{$v}.svg"); }
|
||||
}
|
||||
}
|
||||
|
||||
/* links */
|
||||
.shell-link {
|
||||
color: $link_color;
|
||||
&:hover { color: lighten($link_color,10%); }
|
||||
}
|
||||
|
||||
/* Modal Dialogs */
|
||||
|
||||
.lightbox { background-color: black; } //FIXME where is this?
|
||||
.flashspot { background-color: white; } //FIXME where is this?
|
||||
|
||||
.modal-dialog {
|
||||
border-radius: 5px;
|
||||
background-color: transparentize(darken($bg_color,10%),0.05);
|
||||
border: 1px solid $borders_color;
|
||||
padding: 24px;
|
||||
|
||||
.run-dialog-entry { width: 20em; }
|
||||
.run-dialog-error-box {
|
||||
padding-top: 16px;
|
||||
spacing: 6px;
|
||||
}
|
||||
.run-dialog-button-box { padding-top: 1em; }
|
||||
.run-dialog-label {
|
||||
font-size: fontsize($font-size + 1.1);
|
||||
font-weight: bold;
|
||||
color: darken($fg_color,10%);
|
||||
padding-bottom: .4em;
|
||||
}
|
||||
|
||||
}
|
||||
.button-dialog-button-box {
|
||||
spacing: 18px;
|
||||
padding-top: 48px;
|
||||
}
|
||||
|
||||
.show-processes-dialog-subject,
|
||||
.mount-question-dialog-subject,
|
||||
.end-session-dialog-subject { //this should be a generic header class
|
||||
font-size: fontsize($font-size * 1.3);
|
||||
}
|
||||
|
||||
/* Popvers/Menus */
|
||||
|
||||
.popup-menu {
|
||||
min-width: 200px;
|
||||
|
||||
.popup-menu-arrow { } //defined globally in the TOP BAR
|
||||
.popup-sub-menu {
|
||||
background-color: darken($bg_color,2%);
|
||||
border-top: 1px solid lighten($borders_color,5%);
|
||||
border-bottom: 1px solid lighten($borders_color,5%);
|
||||
}
|
||||
|
||||
.popup-menu-content { padding: 1em 0em; }
|
||||
.popup-menu-item {
|
||||
spacing: 12px;
|
||||
|
||||
&:ltr { padding: .4em 1.75em .4em 0em; }
|
||||
&:rtl { padding: .4em 0em .4em 1.75em; }
|
||||
&:active { background-color: lighten($bg_color,10%); }
|
||||
&:insensitive { background-color: transparentize($bg_color,.5); }
|
||||
}
|
||||
.popup-inactive-menu-item { //all icons and other graphical elements
|
||||
color: $fg_color;
|
||||
|
||||
&:insensitive { color: transparentize($fg_color,0.5); }
|
||||
}
|
||||
//.popup-status-menu-item { font-weight: normal; color: pink; } //dunno what that is
|
||||
}
|
||||
|
||||
.popup-menu-ornament {
|
||||
text-align: right;
|
||||
width: 1em;
|
||||
}
|
||||
.popup-menu-boxpointer,
|
||||
.candidate-popup-boxpointer {
|
||||
-arrow-border-radius: 3px;
|
||||
-arrow-background-color: $bg_color;
|
||||
-arrow-border-width: 1px;
|
||||
-arrow-border-color: $borders_color;
|
||||
-arrow-base: 24px;
|
||||
-arrow-rise: 11px;
|
||||
-arrow-box-shadow: 0 1px 3px red; //dreaming. bug #689995
|
||||
}
|
||||
|
||||
.popup-separator-menu-item {
|
||||
-margin-horizontal: 24px;
|
||||
height: 1px; //not really the whole box
|
||||
padding: 0; //not really centered
|
||||
background-color: transparent;
|
||||
border-color: lighten($borders_color,10%);
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
|
||||
|
||||
/* fallback menu
|
||||
- odd thing for styling App menu when apparently not running under shell. Light Adwaita styled
|
||||
app menu inside the main app window itself rather than the top bar
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* TOP BAR */
|
||||
|
||||
#panel {
|
||||
background-color: black;
|
||||
font-weight: bold;
|
||||
height: 1.86em;
|
||||
|
||||
&.unlock-screen,
|
||||
&.login-screen,
|
||||
&.lock-screen {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#panelLeft, #panelCenter { // spacing between activities<>app menu and such
|
||||
spacing: 4px;
|
||||
}
|
||||
|
||||
.panel-corner {
|
||||
-panel-corner-radius: 6px;
|
||||
-panel-corner-background-color: black;
|
||||
-panel-corner-border-width: 2px;
|
||||
-panel-corner-border-color: transparent;
|
||||
|
||||
&:active, &:overview, &:focus {
|
||||
-panel-corner-border-color: lighten($selected_bg_color,5%);
|
||||
}
|
||||
|
||||
&.lock-screen, &.login-screen, &unlock-screen {
|
||||
-panel-corner-radius: 0;
|
||||
-panel-corner-background-color: transparent;
|
||||
-panel-corner-border-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-button {
|
||||
padding: 0px 12px;
|
||||
font-weight: bold;
|
||||
color: #ccc;
|
||||
transition-duration: 100ms;
|
||||
|
||||
#appMenuIcon {
|
||||
app-icon-bottom-clip: 1px;
|
||||
|
||||
.panel-button:active &,
|
||||
.panel-button:overview &,
|
||||
.panel-button:focus &,
|
||||
.panel-button:checked & {
|
||||
app-icon-bottom-clip: 2px;
|
||||
}
|
||||
|
||||
}
|
||||
&:hover {
|
||||
color: lighten($fg_color, 10%);
|
||||
text-shadow: black 0 2px 2px;
|
||||
}
|
||||
|
||||
&:active, &:overview, &:focus, &:checked {
|
||||
// Trick due to St limitations. It needs a background to draw
|
||||
// a box-shadow
|
||||
background-color: rgba(0, 0, 0, 0.01);
|
||||
box-shadow: inset 0 -2px 0px lighten($selected_bg_color,5%);
|
||||
color: lighten($fg_color,10%);
|
||||
text-shadow: black 0px 2px 2px;
|
||||
|
||||
& > .system-status-icon { icon-shadow: black 0 2px 2px; }
|
||||
}
|
||||
|
||||
.system-status-icon { icon-size: 1.09em; padding: 0 5px; }
|
||||
.unlock-screen &,
|
||||
.login-screen &,
|
||||
.lock-screen & {
|
||||
color: lighten($fg_color, 10%);
|
||||
&:focus, &:hover, &:active { color: lighten($fg_color, 10%); }
|
||||
}
|
||||
}
|
||||
|
||||
.panel-status-button {
|
||||
|
||||
&:active, &:overview, &:focus, &:checked {
|
||||
border-color: lighten($selected_bg_color,5%);
|
||||
border-bottom-width: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-menu { -boxpointer-gap: 4px; } //FIXME
|
||||
.panel-status-indicators-box, //FIXME
|
||||
.panel-status-menu-box {
|
||||
spacing: 2px;
|
||||
}
|
||||
|
||||
.screencast-indicator { color: $warning_color; }
|
||||
}
|
||||
|
||||
// a little unstructured mess:
|
||||
|
||||
.system-switch-user-submenu-icon {
|
||||
icon-size: 24px;
|
||||
border: 1px solid transparentize($fg_color,0.6);
|
||||
}
|
||||
|
||||
#appMenu {
|
||||
spinner-image: url("process-working.svg");
|
||||
spacing: 4px;
|
||||
|
||||
.label-shadow { color: transparentize(#000,0.5); }
|
||||
}
|
||||
|
||||
.aggregate-menu {
|
||||
width: 360px;
|
||||
.popup-menu-icon { padding: 0 4px; }
|
||||
}
|
||||
|
||||
.system-menu-action {
|
||||
color: $fg_color;
|
||||
border-radius: 32px; /* wish we could do 50% */
|
||||
padding: 13px;
|
||||
border: 1px solid lighten($borders_color,5%);
|
||||
|
||||
&:hover, &:focus {
|
||||
color: lighten($fg_color, 10%);
|
||||
background-color: lighten($bg_color,10%);
|
||||
border: none;
|
||||
padding: 14px;
|
||||
}
|
||||
&:active { background-color: lighten($borders_color,5%); }
|
||||
|
||||
& > StIcon { icon-size: 16px; }
|
||||
}
|
||||
|
||||
// not really top bar only
|
||||
.popup-menu-arrow { width: 16px; height: 16px; }
|
||||
.popup-menu-icon { icon-size: 1.09em; }
|
||||
|
||||
//close buttons
|
||||
|
||||
.window-close, .notification-close {
|
||||
background-image: url("close-window.svg");
|
||||
background-size: 32px;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
}
|
||||
.window-close {
|
||||
-shell-close-overlap: 16px;
|
||||
&:rtl { -st-background-image-shadow: 2px 2px 6px rgba(0,0,0,0.5); }
|
||||
}
|
||||
.notification-close {
|
||||
-shell-close-overlap-x: 14px;
|
||||
-shell-close-overlap-y: -12px;
|
||||
|
||||
&:rtl { -shell-close-overlap-x: -14px; }
|
||||
}
|
||||
|
||||
/* OVERVIEW */
|
||||
|
||||
#overview {
|
||||
spacing: 24px; //
|
||||
|
||||
}
|
||||
.window-picker { //container around window thumbnails
|
||||
-horizontal-spacing: 32px;
|
||||
-vertical-spacing: 32px;
|
||||
padding-left: 32px;
|
||||
padding-right: 32px;
|
||||
padding-bottom: 48px;
|
||||
|
||||
&.external-monitor { padding: 32px; }
|
||||
}
|
||||
|
||||
.window-clone-border {
|
||||
border: 4px solid $selected_bg_color;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.window-caption {
|
||||
spacing: 25px;
|
||||
background-color: transparentize($bg_color,0.3);
|
||||
border-radius: 8px;
|
||||
padding: 4px 12px;
|
||||
-shell-caption-spacing: 12px;
|
||||
&:hover { background-color: $selected_bg_color; }
|
||||
}
|
||||
|
||||
.messages-indicator { color: transparentize($fg_color,.2); height: 32px; }
|
||||
.messages-indicator-contents { spacing: 12px; padding-bottom: 12px; }
|
||||
|
||||
//search entry
|
||||
.search-entry {
|
||||
width: 320px;
|
||||
padding: 7px 9px;
|
||||
border-radius: 24px;
|
||||
&:focus {
|
||||
padding: 6px 8px;
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
.search-entry-icon { icon-size: 1em; padding: 0 4px; color: transparentize($fg_color,.3); }
|
||||
|
||||
&:hover, &:focus {
|
||||
.search-entry-icon { color: $fg_color; }
|
||||
}
|
||||
}
|
||||
|
||||
//search results
|
||||
|
||||
#searchResultsBin {
|
||||
max-width: 1000px;
|
||||
}
|
||||
|
||||
#searchResultsContent {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
spacing: 16px;
|
||||
}
|
||||
|
||||
.search-section { spacing: 16px; } // This should be equal to #searchResultsContent spacing
|
||||
.search-section-content { spacing: 32px; } // This is the space between the provider icon and the results container
|
||||
.search-statustext { // "no results"
|
||||
@extend %status_text;
|
||||
}
|
||||
.list-search-results { spacing: 3px; }
|
||||
|
||||
.search-section-separator {
|
||||
-gradient-height: 1px;
|
||||
-gradient-start: rgba(255,255,255,0);
|
||||
-gradient-end: rgba(255,255,255,0.1);
|
||||
-margin-horizontal: 1.5em;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.list-search-result-content { spacing: 12px; padding: 12px; }
|
||||
.list-search-result-title { font-size: 1.5em; color: darken($fg_color,5%); }
|
||||
.list-search-result-description { color: darken($fg_color,15%); }
|
||||
.search-provider-icon { padding: 15px; }
|
||||
.search-provider-icon-more {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-image: url("more-results.svg");
|
||||
}
|
||||
|
||||
|
||||
/* DASHBOARD */
|
||||
|
||||
#dash {
|
||||
@extend %overview-panel;
|
||||
padding: 4px;
|
||||
border-left: 0px;
|
||||
border-radius: 0px 9px 9px 0px;
|
||||
|
||||
&:rtl {
|
||||
border-left-width: 1px;
|
||||
border-right-width: 0;
|
||||
border-radius: 9px 0 0 9px;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
background-image: url("dash-placeholder.svg");
|
||||
background-size: contain;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.empty-dash-drop-target {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.dash-item-container > StWidget {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.dash-label { //osd tooltip
|
||||
border-radius: 7px;
|
||||
padding: 4px 12px;
|
||||
background-color: transparentize($bg_color,0.3);
|
||||
text-align: center;
|
||||
-x-offset: 8px;
|
||||
}
|
||||
|
||||
/* App Vault/Grid */
|
||||
.icon-grid {
|
||||
spacing: 30px;
|
||||
-shell-grid-horizontal-item-size: 136px;
|
||||
-shell-grid-vertical-item-size: 136px;
|
||||
|
||||
.overview-icon { icon-size: 96px; } //FIXME no effect
|
||||
}
|
||||
//.app-display { spacing: 20px; }
|
||||
|
||||
.app-view-controls { //favorties | all toggle container
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
.app-view-control { //favorties | all toggle button
|
||||
padding: 4px 32px;
|
||||
&:checked { @include button(active); }
|
||||
&:first-child {
|
||||
border-right-width: 0;
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
&:last-child {
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Icon tile
|
||||
.search-provider-icon,
|
||||
.list-search-result {
|
||||
@extend %icon_tile;
|
||||
&:active, &:checked { background-color: transparentize(darken($bg_color,10%),.1); }
|
||||
&:focus, &:selected, &:hover {
|
||||
background-color: transparentize($fg_color,.9);
|
||||
transition-duration: 200ms;
|
||||
}
|
||||
}
|
||||
.app-well-app,
|
||||
.app-well-app.app-folder,
|
||||
.show-apps,
|
||||
.grid-search-result {
|
||||
& > .overview-icon {
|
||||
@extend %icon_tile;
|
||||
}
|
||||
&.running > .overview-icon {
|
||||
text-shadow: black 0px 2px 2px;
|
||||
}
|
||||
&:active > .overview-icon,
|
||||
&:checked > .overview-icon {
|
||||
background-color: transparentize(darken($bg_color,10%),.1); //FIXME not working?
|
||||
box-shadow: inset 0 1px 2px $borders_color;
|
||||
}
|
||||
&:hover > .overview-icon,
|
||||
&.running:hover > .overview-icon,
|
||||
&:focus > .overview-icon,
|
||||
&:selected > .overview-icon {
|
||||
background-color: transparentize($fg_color,.9);
|
||||
transition-duration: 0ms;
|
||||
border-image: none;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.app-well-app-running-dot { //running apps indicator
|
||||
width: 10px; height: 3px;
|
||||
background-color: $selected_bg_color;
|
||||
margin-bottom: 2px; //FIXME will happen :)
|
||||
}
|
||||
|
||||
%icon_tile {
|
||||
border-radius: 4px;
|
||||
padding: 6px;
|
||||
border: 1px solid transparent;
|
||||
transition-duration: 100ms;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.app-well-app.app-folder > .overview-icon {
|
||||
background-color: transparentize($bg_color,.6);
|
||||
}
|
||||
|
||||
.show-apps:checked .show-apps-icon,
|
||||
.show-apps:focus .show-apps-icon {
|
||||
color: white;
|
||||
transition-duration: 100ms;
|
||||
}
|
||||
|
||||
|
||||
// Collections
|
||||
.app-folder-popup { //expanded collection
|
||||
-arrow-border-radius: 8px;
|
||||
-arrow-background-color: transparentize($bg_color,0.7);
|
||||
-arrow-base: 24px;
|
||||
-arrow-rise: 11px;
|
||||
}
|
||||
.app-folder-popup-bin { padding: 5px; }
|
||||
.app-folder-icon {
|
||||
padding: 5px;
|
||||
spacing-rows: 5px;
|
||||
spacing-columns: 5px;
|
||||
}
|
||||
|
||||
.page-indicator {
|
||||
padding: 15px 20px;
|
||||
|
||||
.page-indicator-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background-image: url(page-indicator-inactive.svg);
|
||||
}
|
||||
|
||||
&:hover .page-indicator-icon { background-image: url(page-indicator-hover.svg); }
|
||||
&:active .page-indicator-icon { background-image: url(page-indicator-active.svg); }
|
||||
&:checked .page-indicator-icon,
|
||||
&:checked:active { background-image: url(page-indicator-checked.svg); }
|
||||
}
|
||||
|
||||
.no-frequent-applications-label { @extend %status_text; }
|
||||
|
||||
.app-well-app > .overview-icon.overview-icon-with-label,
|
||||
.grid-search-result .overview-icon.overview-icon-with-label {
|
||||
padding: 10px 8px 5px 8px;
|
||||
spacing: 4px;
|
||||
}
|
||||
|
||||
// Workspace pager
|
||||
.workspace-thumbnails { //container ala dash
|
||||
@extend %overview-panel;
|
||||
visible-width: 32px; //amount visible before hover
|
||||
spacing: 11px;
|
||||
padding: 8px;
|
||||
border-radius: 9px 0 0 9px;
|
||||
//border-width: 1px 0 1px 1px; //fixme: can't have non unoform borders :(
|
||||
&:rtl { border-radius: 0 9px 9px 0;}
|
||||
}
|
||||
.workspace-thumbnail-indicator {
|
||||
border: 4px solid $selected_bg_color;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
//Some hacks I don't even
|
||||
// FIXME
|
||||
.search-display > StBoxLayout,
|
||||
.all-apps,
|
||||
.frequent-apps > StBoxLayout {
|
||||
// horizontal padding to make sure scrollbars or dash don't overlap content
|
||||
padding: 0px 88px 10px 88px;
|
||||
}
|
||||
|
||||
%overview-panel {
|
||||
color: $fg_color;
|
||||
background-color: $bg_color;
|
||||
border: 1px solid transparentize($fg_color,0.8);
|
||||
}
|
||||
|
||||
%status_text {
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
color: $fg_color;
|
||||
}
|
||||
|
||||
/* NOTIFICATIONS & MESSAGE TRAY */
|
||||
|
||||
#message-tray {
|
||||
background: darken($bg_color,10%) url("noise-texture.png");
|
||||
background-repeat: repeat;
|
||||
height: 72px;
|
||||
box-shadow: inset 0 2px 4px rgba(0,0,0,0.5);
|
||||
padding: 4px;
|
||||
.message-tray-summary { height: 72px; }
|
||||
|
||||
.message-tray-menu-button {
|
||||
StIcon {
|
||||
padding: 0 20px;
|
||||
color: $fg_color;
|
||||
icon-size: 24px;
|
||||
opacity: 1;
|
||||
}
|
||||
&:hover StIcon { color: lighten($fg_color, 15%); }
|
||||
&:active StIcon { color: lighten($selected_bg_color, 10%); }
|
||||
}
|
||||
.no-messages-label { color: darken($fg_color,10%); }
|
||||
}
|
||||
.url-highlighter { link-color: $selected_bg_color; }
|
||||
|
||||
// Banners
|
||||
.notification {
|
||||
font-size: 11pt;
|
||||
width: 34em;
|
||||
border-radius: 6px 6px 0 0;
|
||||
background-color: transparentize(darken($bg_color,8%),.05);
|
||||
border: 1px solid $borders_color;
|
||||
border-bottom-width: 0;
|
||||
//box-shadow: 0 1px 4px black;
|
||||
spacing-rows: 4px;
|
||||
padding: 8px 8px 4px 8px;
|
||||
spacing-columns: 10px;
|
||||
&.multi-line-notification { padding-bottom: 8px; }
|
||||
}
|
||||
.notification-unexpanded {
|
||||
// We want to force the actor at a specific size, irrespective
|
||||
// of its minimum and preferred size, so we override both
|
||||
min-height: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
// We use row-span = 2 for the image cell, which prevents its height preferences to be
|
||||
// taken into account during allocation, so its height ends up being limited by the height
|
||||
// of the content in the other rows. To avoid showing a stretched image, we set the minimum
|
||||
// height of the table to be ICON_SIZE + IMAGE_SIZE + spacing-rows = 24 + 125 + 10 = 159
|
||||
.notification-with-image {
|
||||
min-height: 159px;
|
||||
}
|
||||
.notification-body { spacing: 5px; }
|
||||
.notification-actions {
|
||||
paddinf-top: 18px;
|
||||
spacing: 6px;
|
||||
}
|
||||
//Message tray items
|
||||
.summary-source {
|
||||
border-radius: 0;
|
||||
-st-natural-width: 60px; //FIXME left aligned rather than centered
|
||||
padding: 9px;
|
||||
transition-duration: 100ms;
|
||||
}
|
||||
.summary-source-button {
|
||||
&:hover .summary-source,
|
||||
&:selected .summary-source,
|
||||
&:focus .summary-source { background-color: lighten($bg_color,2%); }
|
||||
}
|
||||
.summary-source-counter {
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
height: 1.6em; width: 1.6em;
|
||||
-shell-counter-overlap-x: 3px;
|
||||
-shell-counter-overlap-y: 3px;
|
||||
background-color: $selected_bg_color;
|
||||
border: 2px solid $fg_color;
|
||||
box-shadow: 0 2px 2px rgba(0,0,0,0.5);
|
||||
border-radius: 0.9em; // should be 0.8 but whatever; wish I could do 50%;
|
||||
}
|
||||
|
||||
//Message tray popovers
|
||||
.summary-boxpointer {
|
||||
-arrow-border-radius: 15px;
|
||||
-arrow-background-color: transparentize(darken($bg_color,8%),.05);
|
||||
-arrow-base: 36px;
|
||||
-arrow-rise: 18px;
|
||||
color: $fg_color;
|
||||
-boxpointer-gap: 4px;
|
||||
.notification {
|
||||
border-radius: 9px;
|
||||
border-width: 0; //temporary workaround for border brokenness
|
||||
background-color: transparentize(darken($bg_color,8%),.05) !important;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
#summary-right-click-menu {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
}
|
||||
.summary-notification-stack-scrollview {
|
||||
max-height: 24em;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
&:ltr { padding-right: 8px; }
|
||||
&:rtl { padding-left: 8px; }
|
||||
}
|
||||
.notification-scrollview {
|
||||
max-height: 18em;
|
||||
-st-vfade-offset: 24px;
|
||||
&:ltr > StScrollBar { padding-left: 6px; }
|
||||
&:rtl > StScrollBar { padding-right: 6px; }
|
||||
}
|
||||
.notification-button { -st-natural-width: 140px; }
|
||||
.notification-icon-button {
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
&:focus { }//FIXME
|
||||
& > StIcon { icons-size: 16px; padding: 8px; }
|
||||
}
|
||||
.secondary-icon { icon-size: 1.09em; } //FIXME
|
||||
|
||||
//chat bubbles
|
||||
.chat-log-message { color: darken($fg_color,10%); }
|
||||
.chat-empty-line { font-size: 4px; }
|
||||
.chat-received {
|
||||
padding-left: 4px;
|
||||
&:rtl { padding-left: 0px; padding-right: 4px; }
|
||||
}
|
||||
.chat-sent {
|
||||
padding-left: 18pt;
|
||||
color: darken($fg_color, 15%);
|
||||
&:rtl { padding-left: 0; padding-right: 18pt; }
|
||||
}
|
||||
.chat-meta-message {
|
||||
padding-left: 4px;
|
||||
font-size: 9pt;
|
||||
font-weight: bold;
|
||||
color: darken($fg_color,20%);
|
||||
&:rtl { padding-left: 0; padding-right: 4px; }
|
||||
}
|
||||
.chat-notification-scrollview { max-height: 22em; }
|
||||
.subscription-message { font-style: italic; }
|
||||
|
||||
//hotplug
|
||||
.hotplug-transient-box {
|
||||
spacing: 6px;
|
||||
padding: 2px 72px 2px 12px;//FIXME wat?
|
||||
}
|
||||
.hotplug-notification-item {
|
||||
padding: 2px 10px;
|
||||
&:focus { padding: 1px 71px 1px 11px; } //FIXME wat?
|
||||
}
|
||||
|
||||
.hotplug-notification-item-icon {
|
||||
icon-size: 24px;
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
.hotplug-resident-box { spacing: 8px; }
|
||||
|
||||
.hotplug-resident-mount {
|
||||
spacing: 8px;
|
||||
border-radius: 4px;
|
||||
color: green;
|
||||
&:hover {
|
||||
color: red;
|
||||
background-color: blue;
|
||||
}
|
||||
}
|
||||
|
||||
.hotplug-resident-mount-label {
|
||||
color: inherit;
|
||||
padding-left: 6px;
|
||||
}
|
||||
|
||||
.hotplug-resident-mount-icon {
|
||||
icon-size: 24px;
|
||||
padding-left: 6px;
|
||||
}
|
||||
|
||||
.hotplug-resident-eject-icon {
|
||||
icon-size: 16px;
|
||||
}
|
||||
|
||||
.hotplug-resident-eject-button {
|
||||
padding: 7px;
|
||||
border-radius: 5px;
|
||||
color: pink;
|
||||
}
|
||||
|
||||
/* Eeeky things */
|
||||
//Mess that is Looking Glass
|
||||
|
||||
#LookingGlassDialog {
|
||||
background-color: rgba(0,0,0,0.80);
|
||||
spacing: 4px;
|
||||
padding: 4px;
|
||||
border: 2px solid grey;
|
||||
border-radius: 4px;
|
||||
& > #Toolbar {
|
||||
border: 1px solid grey;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.labels { spacing: 4px; }
|
||||
.notebook-tab {
|
||||
-natural-hpadding: 12px;
|
||||
-minimum-hpadding: 6px;
|
||||
font-weight: bold;
|
||||
color: #ccc;
|
||||
transition-duration: 100ms;
|
||||
padding-left: .3em;
|
||||
padding-right: .3em;
|
||||
&:hover {
|
||||
color: white;
|
||||
text-shadow: black 0px 2px 2px;
|
||||
}
|
||||
&:selected {
|
||||
border-bottom-width: 2px;
|
||||
border-color: lighten($selected_bg_color,5%);
|
||||
color: white;
|
||||
text-shadow: black 0px 2px 2px;
|
||||
}
|
||||
}
|
||||
StBoxLayout#EvalBox { padding: 4px; spacing: 4px; }
|
||||
StBoxLayout#ResultsArea { spacing: 4px; }
|
||||
}
|
||||
|
||||
.lg-dialog {
|
||||
StEntry {
|
||||
selection-background-color: #bbbbbb;
|
||||
selected-color: #333333;
|
||||
}
|
||||
.shell-link {
|
||||
color: #999999;
|
||||
&:hover { color: #dddddd; }
|
||||
}
|
||||
}
|
||||
|
||||
.lg-completions-text {
|
||||
font-size: .9em;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.lg-obj-inspector-title {
|
||||
spacing: 4px;
|
||||
}
|
||||
|
||||
.lg-obj-inspector-button {
|
||||
border: 1px solid gray;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
&:hover { border: 1px solid #ffffff; }
|
||||
}
|
||||
|
||||
#lookingGlassExtensions { padding: 4px; }
|
||||
|
||||
.lg-extensions-list {
|
||||
padding: 4px;
|
||||
spacing: 6px;
|
||||
}
|
||||
|
||||
.lg-extension {
|
||||
border: 1px solid #6f6f6f;
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.lg-extension-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.lg-extension-meta {
|
||||
spacing: 6px;
|
||||
}
|
||||
|
||||
#LookingGlassPropertyInspector {
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
border: 2px solid grey;
|
||||
border-radius: 4px;
|
||||
padding: 6px;
|
||||
}
|
@ -1,219 +0,0 @@
|
||||
// Drawing mixins
|
||||
|
||||
// generic drawing of more complex things
|
||||
|
||||
@function _widget_edge($c:$borders_edge) {
|
||||
// outer highlight "used" on most widgets
|
||||
@return 0 1px $c;
|
||||
}
|
||||
|
||||
// provide font size in rem, with px fallback
|
||||
@mixin fontsize($size: 24, $base: 16) {
|
||||
font-size: round($size) + pt;
|
||||
//font-size: ($size / $base) * 1rem;
|
||||
}
|
||||
|
||||
@mixin _shadows($shadow1, $shadow2:none, $shadow3:none, $shadow4:none) {
|
||||
//
|
||||
// Helper function to stack up to 4 box-shadows;
|
||||
//
|
||||
@if $shadow4!=none { box-shadow: $shadow1, $shadow2, $shadow3, $shadow4; }
|
||||
@else if $shadow3!=none { box-shadow: $shadow1, $shadow2, $shadow3; }
|
||||
@else if $shadow2!=none { box-shadow: $shadow1, $shadow2; }
|
||||
@else { box-shadow: $shadow1; }
|
||||
}
|
||||
|
||||
// entries
|
||||
|
||||
@mixin entry($t, $fc:$selected_bg_color, $edge: $borders_edge) {
|
||||
//
|
||||
// Entries drawing function
|
||||
//
|
||||
// $t: entry type
|
||||
// $fc: focus color
|
||||
// $edge: set to none to not draw the bottom edge or specify a color to not
|
||||
// use the default one
|
||||
//
|
||||
// possible $t values:
|
||||
// normal, focus, insensitive
|
||||
//
|
||||
$_inner_shadows: inset 0 2px 4px transparentize(black, 0.6);
|
||||
|
||||
@if $t==normal {
|
||||
background-color: $base_color;
|
||||
border-color: $borders_color;
|
||||
@include _shadows($_inner_shadows);
|
||||
|
||||
}
|
||||
@if $t==focus {
|
||||
@include _shadows($_inner_shadows);
|
||||
border-color: if($fc==$selected_bg_color,
|
||||
$selected_borders_color,
|
||||
darken($fc,35%));
|
||||
}
|
||||
@if $t==hover { }
|
||||
@if $t==insensitive {
|
||||
color: $insensitive_fg_color;
|
||||
border-color: $insensitive_bg_color;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
// buttons
|
||||
|
||||
@function _border_color ($c) { @return darken($c,25%); } // colored buttons want
|
||||
// the border form the
|
||||
// base color
|
||||
|
||||
@function _text_shadow_color ($tc:$fg_color, $bg:$bg_color) {
|
||||
//
|
||||
// calculate the color of text shadows
|
||||
//
|
||||
// $tc is the text color
|
||||
// $bg is the background color
|
||||
//
|
||||
$_lbg: lightness($bg)/100%;
|
||||
@if lightness($tc)<50% { @return transparentize(white,1-$_lbg/($_lbg*1.3)); }
|
||||
@else { @return transparentize(black,$_lbg*0.8); }
|
||||
}
|
||||
|
||||
@function _button_hilight_color($c) {
|
||||
//
|
||||
// calculate the right top hilight color for buttons
|
||||
//
|
||||
// $c: base color;
|
||||
//
|
||||
@if lightness($c)>90% { @return white; }
|
||||
@else if lightness($c)>80% { @return transparentize(white, 0.3); }
|
||||
@else if lightness($c)>50% { @return transparentize(white, 0.5); }
|
||||
@else if lightness($c)>40% { @return transparentize(white, 0.7); }
|
||||
@else { @return transparentize(white, 0.9); }
|
||||
}
|
||||
|
||||
@mixin _button_text_shadow ($tc:$fg_color, $bg:$bg_color) {
|
||||
//
|
||||
// helper function for the text emboss effect
|
||||
//
|
||||
// $tc is the optional text color, not the shadow color
|
||||
//
|
||||
// TODO: this functions needs a way to deal with special cases
|
||||
//
|
||||
|
||||
$_shadow: _text_shadow_color($tc, $bg);
|
||||
|
||||
@if lightness($tc)<50% {
|
||||
text-shadow: 0 1px $_shadow;
|
||||
icon-shadow: 0 1px $_shadow;
|
||||
}
|
||||
@else {
|
||||
text-shadow: 0 -1px $_shadow;
|
||||
icon-shadow: 0 -1px $_shadow;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin button($t, $c:$osd_bg_color, $tc:$fg_color, $edge: $borders_edge) {
|
||||
//
|
||||
// Button drawing function
|
||||
//
|
||||
// $t: button type,
|
||||
// $c: base button color for colored* types
|
||||
// $tc: optional text color for colored* types
|
||||
// $edge: set to none to not draw the bottom edge or specify a color to not
|
||||
// use the default one
|
||||
//
|
||||
// possible $t values:
|
||||
// normal, hover, active, insensitive, insensitive-active,
|
||||
// backdrop, backdrop-active, backdrop-insensitive, backdrop-insensitive-active,
|
||||
// osd, osd-hover, osd-active, osd-insensitive, osd-backdrop, undecorated
|
||||
//
|
||||
|
||||
$_hilight_color: _button_hilight_color($c);
|
||||
$_button_edge: if($edge == none, none, _widget_edge($edge));
|
||||
$_blank_edge: if($edge == none, none, _widget_edge(transparentize($edge,1)));
|
||||
|
||||
|
||||
@if $t==normal {
|
||||
//
|
||||
// normal button
|
||||
//
|
||||
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.5),
|
||||
$osd_bg_color);
|
||||
|
||||
color: $osd_fg_color;
|
||||
background-color: $_bg;
|
||||
border-color: $osd_borders_color;
|
||||
box-shadow: inset 0 1px lighten($osd_bg_color,10%);
|
||||
text-shadow: 0 1px black;
|
||||
icon-shadow: 0 1px black;
|
||||
}
|
||||
@if $t==focus {
|
||||
//
|
||||
// focused button
|
||||
//
|
||||
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.5),
|
||||
$osd_bg_color);
|
||||
|
||||
color: $osd_fg_color;
|
||||
border-color: $selected_bg_color;
|
||||
box-shadow: inset 0 1px lighten($osd_bg_color,10%);
|
||||
text-shadow: 0 1px black;
|
||||
icon-shadow: 0 1px black;
|
||||
}
|
||||
|
||||
@else if $t==hover {
|
||||
//
|
||||
// active osd button
|
||||
//
|
||||
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
|
||||
lighten($osd_bg_color,10%));
|
||||
|
||||
color: white;
|
||||
border-color: $osd_borders_color;
|
||||
background-color: $_bg;
|
||||
box-shadow: inset 0 1px lighten($osd_bg_color,20%);
|
||||
text-shadow: 0 1px black;
|
||||
icon-shadow: 0 1px black;
|
||||
|
||||
}
|
||||
@else if $t==active {
|
||||
//
|
||||
// active osd button
|
||||
//
|
||||
$_bg: if($c!=$bg_color, $c, $osd_borders_color);
|
||||
|
||||
color: white;
|
||||
border-color: $osd_borders_color;
|
||||
background-color: darken($_bg,5%);
|
||||
box-shadow: none;
|
||||
text-shadow: none;
|
||||
icon-shadow: none;
|
||||
}
|
||||
@else if $t==insensitive {
|
||||
//
|
||||
// insensitive osd button
|
||||
//
|
||||
$_bg: transparentize(mix($insensitive_fg_color,$osd_bg_color,20%),0.3);
|
||||
|
||||
color: $insensitive_fg_color;
|
||||
border-color: $osd_borders_color;
|
||||
background-color: $_bg;
|
||||
box-shadow: none;
|
||||
text-shadow: none;
|
||||
icon-shadow: none;
|
||||
}
|
||||
@else if $t==undecorated {
|
||||
//
|
||||
// reset
|
||||
//
|
||||
border-color: transparent;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
|
||||
@include _shadows(inset 0 1px transparentize(white,1),
|
||||
$_blank_edge);
|
||||
|
||||
text-shadow: none;
|
||||
icon-shadow: none;
|
||||
}
|
||||
}
|
||||
|
@ -10,11 +10,11 @@
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="29"
|
||||
height="29"
|
||||
width="24"
|
||||
height="24"
|
||||
id="svg10621"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="calendar-today.svg">
|
||||
<defs
|
||||
id="defs10623">
|
||||
@ -118,17 +118,6 @@
|
||||
fx="51"
|
||||
fy="30"
|
||||
r="42" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient34508-1-3"
|
||||
id="radialGradient3113"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.72146227,0,0,0.27484277,14.205424,21.754717)"
|
||||
cx="51"
|
||||
cy="30"
|
||||
fx="51"
|
||||
fy="30"
|
||||
r="42" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
@ -137,22 +126,23 @@
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="15.839192"
|
||||
inkscape:cx="20.652108"
|
||||
inkscape:cy="11.839084"
|
||||
inkscape:zoom="8"
|
||||
inkscape:cx="-23.537329"
|
||||
inkscape:cy="-31.442864"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="741"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
borderlayer="true">
|
||||
inkscape:window-width="2133"
|
||||
inkscape:window-height="1241"
|
||||
inkscape:window-x="238"
|
||||
inkscape:window-y="88"
|
||||
inkscape:window-maximized="0"
|
||||
borderlayer="true"
|
||||
inkscape:showpageshadow="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3109"
|
||||
@ -169,7 +159,7 @@
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
@ -177,28 +167,12 @@
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-469.08263,-532.99307)">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:0.4625;color:#000000;fill:url(#radialGradient3113);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path34506-3"
|
||||
sodipodi:cx="51"
|
||||
sodipodi:cy="30"
|
||||
sodipodi:rx="42"
|
||||
sodipodi:ry="16"
|
||||
d="M 9,29.999999 A 42,16 0 0 1 93,30 l -42,0 z"
|
||||
sodipodi:start="3.1415927"
|
||||
sodipodi:end="6.2831853"
|
||||
transform="matrix(0.43692393,0,0,1.3783114,461.29951,517.6437)"
|
||||
inkscape:export-filename="/home/jimmac/src/cvs/gnome/gnome-shell-design/mockups/motion/textures/panel.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:0.50196078;stroke-width:0.43599999;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="rect2996"
|
||||
width="31"
|
||||
height="3"
|
||||
x="468.08264"
|
||||
y="558.99304" />
|
||||
transform="translate(-469.08263,-537.99307)">
|
||||
<circle
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:0.23756906;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="path7305"
|
||||
cx="481.57138"
|
||||
cy="559.4649"
|
||||
r="1.5" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 5.6 KiB |
1750
data/theme/gnome-shell-high-contrast.css
Normal file
14
data/theme/gnome-shell-high-contrast.scss
Normal file
@ -0,0 +1,14 @@
|
||||
@import "gnome-shell-sass/_high-contrast-colors"; //use gtk colors
|
||||
@import "gnome-shell-sass/_drawing";
|
||||
@import "gnome-shell-sass/_common";
|
||||
|
||||
//force symbolic icons
|
||||
stage {
|
||||
-st-icon-style: symbolic;
|
||||
}
|
||||
|
||||
.toggle-switch { width: 48px; }
|
||||
.toggle-switch-us, .toggle-switch-intl {
|
||||
background-image: url("resource:///org/gnome/shell/theme/toggle-off-hc.svg");
|
||||
&:checked { background-image: url("resource:///org/gnome/shell/theme/toggle-on-hc.svg"); }
|
||||
}
|
1
data/theme/gnome-shell-sass
Submodule
@ -1,6 +1,5 @@
|
||||
$variant: 'dark';
|
||||
|
||||
@import "_gnome-shell-old.scss"; //temporary. sadlu shell crashes when trying to build a theme from scratch
|
||||
@import "_colors"; //use gtk colors
|
||||
@import "_drawing";
|
||||
@import "_common";
|
||||
@import "gnome-shell-sass/_colors"; //use gtk colors
|
||||
@import "gnome-shell-sass/_drawing";
|
||||
@import "gnome-shell-sass/_common";
|
||||
|
119
data/theme/no-events.svg
Normal file
@ -0,0 +1,119 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64px"
|
||||
height="64px"
|
||||
id="svg3471"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="New document 5">
|
||||
<defs
|
||||
id="defs3473" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.5"
|
||||
inkscape:cx="32"
|
||||
inkscape:cy="32"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="1461"
|
||||
inkscape:window-height="772"
|
||||
inkscape:window-x="37"
|
||||
inkscape:window-y="64"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata3476">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
transform="matrix(4,0,0,4,1.9999997,2.3636364)"
|
||||
id="g19145"
|
||||
style="fill:#bebebe;fill-opacity:1;display:inline">
|
||||
<g
|
||||
id="g19147"
|
||||
inkscape:label="status"
|
||||
style="fill:#bebebe;fill-opacity:1;display:inline"
|
||||
transform="translate(-541.0002,-301)" />
|
||||
<g
|
||||
style="fill:#bebebe;fill-opacity:1"
|
||||
id="g19149"
|
||||
inkscape:label="devices"
|
||||
transform="translate(-541.0002,-301)" />
|
||||
<g
|
||||
style="fill:#bebebe;fill-opacity:1"
|
||||
id="g19151"
|
||||
inkscape:label="apps"
|
||||
transform="translate(-541.0002,-301)" />
|
||||
<g
|
||||
style="fill:#bebebe;fill-opacity:1"
|
||||
id="g19153"
|
||||
inkscape:label="places"
|
||||
transform="translate(-541.0002,-301)" />
|
||||
<g
|
||||
style="fill:#bebebe;fill-opacity:1"
|
||||
id="g19155"
|
||||
inkscape:label="mimetypes"
|
||||
transform="translate(-541.0002,-301)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 543.0002,301 c -1.05237,0 -2,0.84508 -2,1.9375 l 0,11.125 c 0,1.09242 0.94763,1.9375 2,1.9375 l 11,0 c 1.05237,0 2,-0.84508 2,-1.9375 l 0,-11.125 c 0,-1.09242 -0.94763,-1.9375 -2,-1.9375 l -11,0 z m 0,5 3.03125,0 0,2 -3.03125,0 0,-2 z m 4.03125,0 2.96875,0 0,2 -2.96875,0 0,-2 z m 3.96875,0 3,0 0,2 -3,0 0,-2 z m -8,3 3.03125,0 0,2 -3.03125,0 0,-2 z m 4.03125,0 2.96875,0 0,2 -2.96875,0 0,-2 z m 3.96875,0 3,0 0,2 -3,0 0,-2 z m -8,3 3.03125,0 0,2 -3.03125,0 0,-2 z m 4.03125,0 2.96875,0 0,2 -2.96875,0 0,-2 z m 3.96875,0 3,0 0,2 -3,0 0,-2 z"
|
||||
id="path19157"
|
||||
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new;font-family:Sans;-inkscape-font-specification:Sans" />
|
||||
<rect
|
||||
height="1.9999993"
|
||||
id="rect19159"
|
||||
style="opacity:0.35;color:#000000;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
width="2.9999993"
|
||||
x="551.00018"
|
||||
y="309" />
|
||||
</g>
|
||||
<g
|
||||
id="g19161"
|
||||
inkscape:label="emblems"
|
||||
style="fill:#bebebe;fill-opacity:1;display:inline"
|
||||
transform="translate(-541.0002,-301)" />
|
||||
<g
|
||||
id="g19163"
|
||||
inkscape:label="emotes"
|
||||
style="fill:#bebebe;fill-opacity:1;display:inline"
|
||||
transform="translate(-541.0002,-301)" />
|
||||
<g
|
||||
id="g19165"
|
||||
inkscape:label="categories"
|
||||
style="fill:#bebebe;fill-opacity:1;display:inline"
|
||||
transform="translate(-541.0002,-301)" />
|
||||
<g
|
||||
id="g19167"
|
||||
inkscape:label="actions"
|
||||
style="fill:#bebebe;fill-opacity:1;display:inline"
|
||||
transform="translate(-541.0002,-301)" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.7 KiB |
114
data/theme/no-notifications.svg
Normal file
@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64px"
|
||||
height="64px"
|
||||
id="svg3393"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="New document 2">
|
||||
<defs
|
||||
id="defs3395" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.5"
|
||||
inkscape:cx="32"
|
||||
inkscape:cy="32"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="697"
|
||||
inkscape:window-height="613"
|
||||
inkscape:window-x="100"
|
||||
inkscape:window-y="77"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata3398">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
style="display:inline"
|
||||
transform="matrix(4,0,0,4,0.29733827,-0.35415646)"
|
||||
id="g19245">
|
||||
<g
|
||||
id="g19247"
|
||||
inkscape:label="status"
|
||||
style="display:inline"
|
||||
transform="translate(-323.02908,-649.02581)" />
|
||||
<g
|
||||
id="g19249"
|
||||
inkscape:label="devices"
|
||||
transform="translate(-323.02908,-649.02581)" />
|
||||
<g
|
||||
id="g19251"
|
||||
inkscape:label="apps"
|
||||
transform="translate(-323.02908,-649.02581)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 331.9377,653 c 0.0187,0.16677 0.0625,0.32822 0.0625,0.5 0,2.48528 -2.01472,4.5 -4.5,4.5 -0.11769,0 -0.22834,-0.0224 -0.34375,-0.0312 l 0,2.21875 c 0,1.00412 0.80838,1.8125 1.8125,1.8125 l 1.54511,-5e-5 2,2.04688 2.0625,-2.04688 1.61114,0 c 1.00413,0 1.8125,-0.80838 1.8125,-1.8125 l 0,-5.375 c 0,-1.00412 -0.80837,-1.8125 -1.8125,-1.8125 z"
|
||||
id="path19253"
|
||||
sodipodi:nodetypes="csscsscccssssc"
|
||||
style="opacity:0.5;color:#000000;fill:#c3c3c3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 327.5002,650 c -1.933,0 -3.5,1.567 -3.5,3.5 0,1.933 1.567,3.5 3.5,3.5 1.933,0 3.5,-1.567 3.5,-3.5 0,-1.933 -1.567,-3.5 -3.5,-3.5 z m -0.53125,1 1.03125,0 -0.0625,1.375 a 0.19951718,0.19951718 0 0 0 0,0.0625 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0.125,0.125 0.19951718,0.19951718 0 0 0 0.0312,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 l 1.15625,-0.75 0.5,0.90625 -1.21875,0.625 a 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0312,0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0.0937 0.19951718,0.19951718 0 0 0 0,0.0625 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0.0312,0.0625 0.19951718,0.19951718 0 0 0 0.0312,0.0312 0.19951718,0.19951718 0 0 0 0.0312,0.0312 l 1.25,0.625 -0.53125,0.90625 -1.15625,-0.781 a 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0625,0 0.19951718,0.19951718 0 0 0 -0.125,0.0937 0.19951718,0.19951718 0 0 0 -0.0312,0.0312 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0,0.0625 l 0.0625,1.3751 -1.03125,0 0.0937,-1.375 a 0.19951718,0.19951718 0 0 0 -0.0312,-0.0937 0.19951718,0.19951718 0 0 0 -0.0312,-0.0625 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0937,0.0312 l -1.1875,0.78125 -0.5,-0.90625 1.25,-0.625 a 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 0,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,-0.0625 0.19951718,0.19951718 0 0 0 -0.0312,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0 l -1.25,-0.625 0.5,-0.90625 1.1875,0.75 a 0.19951718,0.19951718 0 0 0 0.0312,0.0312 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0312,0 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 L 326.96895,651 z"
|
||||
id="path19255"
|
||||
style="color:#000000;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
</g>
|
||||
<g
|
||||
id="g19257"
|
||||
inkscape:label="places"
|
||||
transform="translate(-323.02908,-649.02581)" />
|
||||
<g
|
||||
id="g19259"
|
||||
inkscape:label="mimetypes"
|
||||
transform="translate(-323.02908,-649.02581)" />
|
||||
<g
|
||||
id="g19261"
|
||||
inkscape:label="emblems"
|
||||
style="display:inline"
|
||||
transform="translate(-323.02908,-649.02581)" />
|
||||
<g
|
||||
id="g19263"
|
||||
inkscape:label="emotes"
|
||||
style="display:inline"
|
||||
transform="translate(-323.02908,-649.02581)" />
|
||||
<g
|
||||
id="g19265"
|
||||
inkscape:label="categories"
|
||||
style="display:inline"
|
||||
transform="translate(-323.02908,-649.02581)" />
|
||||
<g
|
||||
id="g19267"
|
||||
inkscape:label="actions"
|
||||
style="display:inline"
|
||||
transform="translate(-323.02908,-649.02581)" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.1 KiB |
3
data/theme/parse-sass.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
bundle exec sass --update --sourcemap=none .
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 98 KiB |
133
data/theme/toggle-off-hc.svg
Normal file
@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="48"
|
||||
height="22"
|
||||
id="svg2857"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="toggle-off-hc.svg">
|
||||
<defs
|
||||
id="defs2859">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective2865" />
|
||||
<inkscape:perspective
|
||||
id="perspective2843"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect77541-4"
|
||||
is_visible="true" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="-6.1820581"
|
||||
inkscape:cy="-16.463788"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g37994"
|
||||
showgrid="false"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1364"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
borderlayer="true"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:snap-bbox="true"
|
||||
showborder="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid12954"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata2862">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-444.64286,-781.36218)">
|
||||
<g
|
||||
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
|
||||
id="g37994">
|
||||
<g
|
||||
transform="matrix(1.5323214,0,0,1.2413968,-324.76058,489.69039)"
|
||||
id="toggle-off"
|
||||
inkscape:label="#g8477">
|
||||
<circle
|
||||
cy="1033.993"
|
||||
cx="571.95966"
|
||||
id="path8444"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
r="7" />
|
||||
<rect
|
||||
ry="2.0108337"
|
||||
rx="1.9562569"
|
||||
y="1031.9885"
|
||||
x="565.0083"
|
||||
height="4.0216675"
|
||||
width="34.850178"
|
||||
id="rect8461"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(1.5323214,0,0,1.2413968,-324.85635,491.16456)"
|
||||
id="toggle-on"
|
||||
inkscape:label="#g8481">
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#3465a4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect8475"
|
||||
width="34.850178"
|
||||
height="4.0216675"
|
||||
x="565.0083"
|
||||
y="1070.9279"
|
||||
rx="1.9562569"
|
||||
ry="2.0108337" />
|
||||
<circle
|
||||
transform="scale(-1,1)"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#3465a4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="circle8463"
|
||||
cx="-591.0213"
|
||||
cy="1072.9402"
|
||||
r="9" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.1 KiB |
113
data/theme/toggle-on-hc.svg
Normal file
@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="48"
|
||||
height="22"
|
||||
id="svg2857"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="toggle-on-hc.svg">
|
||||
<defs
|
||||
id="defs2859">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective2865" />
|
||||
<inkscape:perspective
|
||||
id="perspective2843"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect77541-4"
|
||||
is_visible="true" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="-222.95215"
|
||||
inkscape:cy="3.9378433"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g37994"
|
||||
showgrid="false"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1364"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
borderlayer="true"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:snap-bbox="true"
|
||||
showborder="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid12954"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata2862">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-444.64286,-781.36218)">
|
||||
<g
|
||||
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
|
||||
id="g37994">
|
||||
<g
|
||||
transform="matrix(1.5323214,0,0,1.2413968,-324.85635,441.50868)"
|
||||
id="toggle-on"
|
||||
inkscape:label="#g8481">
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#3465a4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect8475"
|
||||
width="34.850178"
|
||||
height="4.0216675"
|
||||
x="565.0083"
|
||||
y="1070.9279"
|
||||
rx="1.9562569"
|
||||
ry="2.0108337" />
|
||||
<circle
|
||||
transform="scale(-1,1)"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#3465a4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="circle8463"
|
||||
cx="-591.0213"
|
||||
cy="1072.9402"
|
||||
r="9" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.4 KiB |
@ -14,7 +14,7 @@
|
||||
height="22"
|
||||
id="svg2857"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="toggle-on-intl.svg">
|
||||
<defs
|
||||
id="defs2859">
|
||||
@ -52,7 +52,7 @@
|
||||
<stop
|
||||
id="stop77465"
|
||||
offset="1"
|
||||
style="stop-color:#204a87;stop-opacity:1" />
|
||||
style="stop-color:#205b9a;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
@ -88,14 +88,14 @@
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="32"
|
||||
inkscape:cx="17.255148"
|
||||
inkscape:cy="8.9252639"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="37.410841"
|
||||
inkscape:cy="16.009314"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g37994"
|
||||
showgrid="true"
|
||||
showgrid="false"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1375"
|
||||
inkscape:window-height="1376"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
@ -14,7 +14,7 @@
|
||||
height="22"
|
||||
id="svg2857"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="toggle-on-us.svg">
|
||||
<defs
|
||||
id="defs2859">
|
||||
@ -32,28 +32,6 @@
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient77461"
|
||||
id="linearGradient77551"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.3066667,0,0,1,-841.64667,-483)"
|
||||
x1="1164.7644"
|
||||
y1="962.93695"
|
||||
x2="1164.7644"
|
||||
y2="970.51404" />
|
||||
<linearGradient
|
||||
id="linearGradient77461"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop77463"
|
||||
offset="0"
|
||||
style="stop-color:#182f4c;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop77465"
|
||||
offset="1"
|
||||
style="stop-color:#204a87;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient76469-7-7-4"
|
||||
@ -80,6 +58,38 @@
|
||||
effect="spiro"
|
||||
id="path-effect77541-4"
|
||||
is_visible="true" />
|
||||
<linearGradient
|
||||
id="linearGradient77461-1"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop77463-1"
|
||||
offset="0"
|
||||
style="stop-color:#182f4c;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop77465-4"
|
||||
offset="1"
|
||||
style="stop-color:#205b9a;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient77461-1"
|
||||
id="linearGradient77551-6-5"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8527367,0,0,0.80554422,-969.41608,-778.00299)"
|
||||
x1="1164.7644"
|
||||
y1="962.93695"
|
||||
x2="1164.7644"
|
||||
y2="970.51404" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient77461-1"
|
||||
id="linearGradient11198"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.3066667,0,0,1,-1066.3709,794.25325)"
|
||||
x1="1322.5831"
|
||||
y1="-312.51855"
|
||||
x2="1322.5831"
|
||||
y2="-306.53461" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
@ -89,13 +99,13 @@
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="33.380898"
|
||||
inkscape:cy="6.9658271"
|
||||
inkscape:cx="-26.798898"
|
||||
inkscape:cy="5.3753009"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g37994"
|
||||
showgrid="false"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1375"
|
||||
inkscape:window-height="1376"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
@ -152,7 +162,7 @@
|
||||
height="25"
|
||||
width="98"
|
||||
id="rect38000"
|
||||
style="color:#000000;fill:url(#linearGradient77551);fill-opacity:1;fill-rule:nonzero;stroke:#182f4c;stroke-width:1.37920964;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
style="color:#000000;fill:url(#linearGradient11198);fill-opacity:1;fill-rule:nonzero;stroke:#182f4c;stroke-width:1.37920964;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;clip-rule:nonzero;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;filter-blend-mode:normal;filter-gaussianBlur-deviation:0;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(2.0625,-2)"
|
||||
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.7 KiB |
@ -17,7 +17,6 @@
|
||||
<chapter>
|
||||
<title>Actors</title>
|
||||
<xi:include href="xml/shell-generic-container.xml"/>
|
||||
<xi:include href="xml/shell-slicer.xml"/>
|
||||
<xi:include href="xml/shell-stack.xml"/>
|
||||
</chapter>
|
||||
<chapter>
|
||||
@ -46,7 +45,7 @@
|
||||
<xi:include href="doc-gen-org.gnome.Shell.SearchProvider.xml"/>
|
||||
<xi:include href="doc-gen-org.gnome.Shell.SearchProvider2.xml"/>
|
||||
<xi:include href="xml/shell-global.xml"/>
|
||||
<xi:include href="xml/shell-keybinding-modes.xml"/>
|
||||
<xi:include href="xml/shell-action-modes.xml"/>
|
||||
<xi:include href="xml/shell-wm.xml"/>
|
||||
<xi:include href="xml/shell-util.xml"/>
|
||||
<xi:include href="xml/shell-mount-operation.xml"/>
|
||||
|
@ -35,7 +35,6 @@
|
||||
<xi:include href="xml/st-bin.xml"/>
|
||||
<xi:include href="xml/st-box-layout.xml"/>
|
||||
<xi:include href="xml/st-scroll-view.xml"/>
|
||||
<xi:include href="xml/st-table.xml"/>
|
||||
</chapter>
|
||||
|
||||
<chapter id="styling">
|
||||
|
@ -54,7 +54,6 @@ const Application = new Lang.Class({
|
||||
this._startupUuid = null;
|
||||
this._loaded = false;
|
||||
this._skipMainWindow = false;
|
||||
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
|
||||
},
|
||||
|
||||
_extensionAvailable: function(uuid) {
|
||||
|
@ -14,7 +14,7 @@ const ShellEntry = imports.ui.shellEntry;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const UserWidget = imports.ui.userWidget;
|
||||
|
||||
const DEFAULT_BUTTON_WELL_ICON_SIZE = 24;
|
||||
const DEFAULT_BUTTON_WELL_ICON_SIZE = 16;
|
||||
const DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1.0;
|
||||
const DEFAULT_BUTTON_WELL_ANIMATION_TIME = 0.3;
|
||||
|
||||
@ -140,7 +140,7 @@ const AuthPrompt = new Lang.Class({
|
||||
},
|
||||
|
||||
_initButtons: function() {
|
||||
this.cancelButton = new St.Button({ style_class: 'modal-dialog-button',
|
||||
this.cancelButton = new St.Button({ style_class: 'modal-dialog-button button',
|
||||
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
@ -162,7 +162,7 @@ const AuthPrompt = new Lang.Class({
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.MIDDLE });
|
||||
this.nextButton = new St.Button({ style_class: 'modal-dialog-button',
|
||||
this.nextButton = new St.Button({ style_class: 'modal-dialog-button button',
|
||||
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
@ -194,17 +194,15 @@ const AuthPrompt = new Lang.Class({
|
||||
},
|
||||
|
||||
_onAskQuestion: function(verifier, serviceName, question, passwordChar) {
|
||||
if (this._preemptiveAnswer) {
|
||||
if (this._queryingService)
|
||||
this._userVerifier.answerQuery(this._queryingService, this._preemptiveAnswer);
|
||||
this._preemptiveAnswer = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._queryingService)
|
||||
this.clear();
|
||||
|
||||
this._queryingService = serviceName;
|
||||
if (this._preemptiveAnswer) {
|
||||
this._userVerifier.answerQuery(this._queryingService, this._preemptiveAnswer);
|
||||
this._preemptiveAnswer = null;
|
||||
return;
|
||||
}
|
||||
this.setPasswordChar(passwordChar);
|
||||
this.setQuestion(question);
|
||||
|
||||
@ -260,7 +258,9 @@ const AuthPrompt = new Lang.Class({
|
||||
},
|
||||
|
||||
_onVerificationComplete: function() {
|
||||
this.setActorInDefaultButtonWell(null);
|
||||
this.verificationStatus = AuthPromptStatus.VERIFICATION_SUCCEEDED;
|
||||
this.cancelButton.reactive = false;
|
||||
},
|
||||
|
||||
_onReset: function() {
|
||||
@ -282,6 +282,12 @@ const AuthPrompt = new Lang.Class({
|
||||
if (oldActor)
|
||||
Tweener.removeTweens(oldActor);
|
||||
|
||||
let wasSpinner;
|
||||
if (oldActor == this._spinner.actor)
|
||||
wasSpinner = true;
|
||||
else
|
||||
wasSpinner = false;
|
||||
|
||||
let isSpinner;
|
||||
if (actor == this._spinner.actor)
|
||||
isSpinner = true;
|
||||
@ -291,6 +297,11 @@ const AuthPrompt = new Lang.Class({
|
||||
if (this._defaultButtonWellActor != actor && oldActor) {
|
||||
if (!animate) {
|
||||
oldActor.opacity = 0;
|
||||
|
||||
if (wasSpinner) {
|
||||
if (this._spinner)
|
||||
this._spinner.stop();
|
||||
}
|
||||
} else {
|
||||
Tweener.addTween(oldActor,
|
||||
{ opacity: 0,
|
||||
@ -299,7 +310,7 @@ const AuthPrompt = new Lang.Class({
|
||||
transition: 'linear',
|
||||
onCompleteScope: this,
|
||||
onComplete: function() {
|
||||
if (isSpinner) {
|
||||
if (wasSpinner) {
|
||||
if (this._spinner)
|
||||
this._spinner.stop();
|
||||
}
|
||||
@ -402,7 +413,7 @@ const AuthPrompt = new Lang.Class({
|
||||
},
|
||||
|
||||
updateSensitivity: function(sensitive) {
|
||||
this._updateNextButtonSensitivity(sensitive);
|
||||
this._updateNextButtonSensitivity(sensitive && this._entry.text.length > 0);
|
||||
this._entry.reactive = sensitive;
|
||||
this._entry.clutter_text.editable = sensitive;
|
||||
},
|
||||
@ -432,8 +443,10 @@ const AuthPrompt = new Lang.Class({
|
||||
reset: function() {
|
||||
let oldStatus = this.verificationStatus;
|
||||
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
|
||||
this.cancelButton.reactive = true;
|
||||
this.nextButton.label = _("Next");
|
||||
|
||||
if (oldStatus == AuthPromptStatus.VERIFYING)
|
||||
if (this._userVerifier)
|
||||
this._userVerifier.cancel();
|
||||
|
||||
this._queryingService = null;
|
||||
@ -488,6 +501,7 @@ const AuthPrompt = new Lang.Class({
|
||||
|
||||
finish: function(onComplete) {
|
||||
if (!this._userVerifier.hasPendingMessages) {
|
||||
this._userVerifier.clear();
|
||||
onComplete();
|
||||
return;
|
||||
}
|
||||
@ -495,11 +509,15 @@ const AuthPrompt = new Lang.Class({
|
||||
let signalId = this._userVerifier.connect('no-more-messages',
|
||||
Lang.bind(this, function() {
|
||||
this._userVerifier.disconnect(signalId);
|
||||
this._userVerifier.clear();
|
||||
onComplete();
|
||||
}));
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED) {
|
||||
return;
|
||||
}
|
||||
this.reset();
|
||||
this.emit('cancelled');
|
||||
}
|
||||
|
@ -22,10 +22,12 @@ const Clutter = imports.gi.Clutter;
|
||||
const Gdm = imports.gi.Gdm;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
@ -47,6 +49,7 @@ const _FADE_ANIMATION_TIME = 0.25;
|
||||
const _SCROLL_ANIMATION_TIME = 0.5;
|
||||
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
|
||||
const _LOGO_ICON_HEIGHT = 48;
|
||||
const _MAX_BOTTOM_MENU_ITEMS = 5;
|
||||
|
||||
const UserListItem = new Lang.Class({
|
||||
Name: 'UserListItem',
|
||||
@ -70,6 +73,9 @@ const UserListItem = new Lang.Class({
|
||||
this._userWidget = new UserWidget.UserWidget(this.user);
|
||||
layout.add(this._userWidget.actor);
|
||||
|
||||
this._userWidget.actor.bind_property('label-actor', this.actor, 'label-actor',
|
||||
GObject.BindingFlags.SYNC_CREATE);
|
||||
|
||||
this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator',
|
||||
scale_x: 0 });
|
||||
layout.add(this._timedLoginIndicator);
|
||||
@ -278,7 +284,16 @@ const SessionMenuButton = new Lang.Class({
|
||||
|
||||
this.actor = new St.Bin({ child: this._button });
|
||||
|
||||
this._menu = new PopupMenu.PopupMenu(this._button, 0, St.Side.TOP);
|
||||
let side = St.Side.TOP;
|
||||
let align = 0;
|
||||
if (Gdm.get_session_ids().length > _MAX_BOTTOM_MENU_ITEMS) {
|
||||
if (this.actor.text_direction == Clutter.TextDirection.RTL)
|
||||
side = St.Side.RIGHT;
|
||||
else
|
||||
side = St.Side.LEFT;
|
||||
align = 0.5;
|
||||
}
|
||||
this._menu = new PopupMenu.PopupMenu(this._button, align, side);
|
||||
Main.uiGroup.add_actor(this._menu.actor);
|
||||
this._menu.actor.hide();
|
||||
|
||||
@ -364,28 +379,17 @@ const LoginDialog = new Lang.Class({
|
||||
Name: 'LoginDialog',
|
||||
|
||||
_init: function(parentActor) {
|
||||
this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW,
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
style_class: 'login-dialog',
|
||||
visible: false });
|
||||
this.actor = new Shell.GenericContainer({ style_class: 'login-dialog',
|
||||
visible: false });
|
||||
this.actor.get_accessible().set_role(Atk.Role.WINDOW);
|
||||
|
||||
this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true }));
|
||||
this.actor.connect('allocate', Lang.bind(this, this._onAllocate));
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
parentActor.add_child(this.actor);
|
||||
|
||||
this._userManager = AccountsService.UserManager.get_default()
|
||||
let gdmClient = new Gdm.Client();
|
||||
|
||||
if (GLib.getenv('GDM_GREETER_TEST') != '1') {
|
||||
this._greeter = gdmClient.get_greeter_sync(null);
|
||||
|
||||
this._defaultSessionChangedId = this._greeter.connect('default-session-name-changed',
|
||||
Lang.bind(this, this._onDefaultSessionChanged));
|
||||
this._sessionOpenedId = this._greeter.connect('session-opened',
|
||||
Lang.bind(this, this._onSessionOpened));
|
||||
this._timedLoginRequestedId = this._greeter.connect('timed-login-requested',
|
||||
Lang.bind(this, this._onTimedLoginRequested));
|
||||
}
|
||||
this._gdmClient = new Gdm.Client();
|
||||
|
||||
this._settings = new Gio.Settings({ schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA });
|
||||
|
||||
@ -405,24 +409,17 @@ const LoginDialog = new Lang.Class({
|
||||
this._userSelectionBox = new St.BoxLayout({ style_class: 'login-dialog-user-selection-box',
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
vertical: true,
|
||||
visible: false });
|
||||
this.actor.add_child(this._userSelectionBox);
|
||||
|
||||
this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
|
||||
text: '' });
|
||||
this._userSelectionBox.add(this._bannerLabel);
|
||||
this._updateBanner();
|
||||
|
||||
this._userList = new UserList();
|
||||
this._userSelectionBox.add(this._userList.actor,
|
||||
{ expand: true,
|
||||
x_fill: true,
|
||||
y_fill: true });
|
||||
|
||||
this._authPrompt = new AuthPrompt.AuthPrompt(gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_OR_LOG_IN);
|
||||
this._authPrompt = new AuthPrompt.AuthPrompt(this._gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_OR_LOG_IN);
|
||||
this._authPrompt.connect('prompted', Lang.bind(this, this._onPrompted));
|
||||
this._authPrompt.connect('reset', Lang.bind(this, this._onReset));
|
||||
this._authPrompt.hide();
|
||||
@ -450,11 +447,25 @@ const LoginDialog = new Lang.Class({
|
||||
x_align: St.Align.START,
|
||||
x_fill: true });
|
||||
|
||||
this._bannerView = new St.ScrollView({ style_class: 'login-dialog-banner-view',
|
||||
opacity: 0,
|
||||
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER });
|
||||
this.actor.add_child(this._bannerView);
|
||||
|
||||
let bannerBox = new St.BoxLayout({ vertical: true });
|
||||
|
||||
this._bannerView.add_actor(bannerBox);
|
||||
this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
|
||||
text: '' });
|
||||
this._bannerLabel.clutter_text.line_wrap = true;
|
||||
this._bannerLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
bannerBox.add_child(this._bannerLabel);
|
||||
this._updateBanner();
|
||||
|
||||
this._logoBin = new St.Widget({ style_class: 'login-dialog-logo-bin',
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.END,
|
||||
x_expand: true,
|
||||
y_expand: true });
|
||||
y_align: Clutter.ActorAlign.END });
|
||||
this.actor.add_child(this._logoBin);
|
||||
this._updateLogo();
|
||||
|
||||
@ -476,6 +487,10 @@ const LoginDialog = new Lang.Class({
|
||||
this._disableUserList = undefined;
|
||||
this._userListLoaded = false;
|
||||
|
||||
this._realmManager = new Realmd.Manager();
|
||||
this._realmSignalId = this._realmManager.connect('login-format-changed',
|
||||
Lang.bind(this, this._showRealmLoginHint));
|
||||
|
||||
LoginManager.getLoginManager().getCurrentSessionProxy(Lang.bind(this, this._gotGreeterSessionProxy));
|
||||
|
||||
// If the user list is enabled, it should take key focus; make sure the
|
||||
@ -485,6 +500,190 @@ const LoginDialog = new Lang.Class({
|
||||
Lang.bind(this, this._updateDisableUserList));
|
||||
},
|
||||
|
||||
_getBannerAllocation: function (dialogBox) {
|
||||
let actorBox = new Clutter.ActorBox();
|
||||
|
||||
let [minWidth, minHeight, natWidth, natHeight] = this._bannerView.get_preferred_size();
|
||||
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
|
||||
|
||||
actorBox.x1 = Math.floor(centerX - natWidth / 2);
|
||||
actorBox.y1 = dialogBox.y1 + Main.layoutManager.panelBox.height;
|
||||
actorBox.x2 = actorBox.x1 + natWidth;
|
||||
actorBox.y2 = actorBox.y1 + natHeight;
|
||||
|
||||
return actorBox;
|
||||
},
|
||||
|
||||
_getLogoBinAllocation: function (dialogBox) {
|
||||
let actorBox = new Clutter.ActorBox();
|
||||
|
||||
let [minWidth, minHeight, natWidth, natHeight] = this._logoBin.get_preferred_size();
|
||||
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
|
||||
|
||||
actorBox.x1 = Math.floor(centerX - natWidth / 2);
|
||||
actorBox.y1 = dialogBox.y2 - natHeight;
|
||||
actorBox.x2 = actorBox.x1 + natWidth;
|
||||
actorBox.y2 = actorBox.y1 + natHeight;
|
||||
|
||||
return actorBox;
|
||||
},
|
||||
|
||||
_getCenterActorAllocation: function (dialogBox, actor) {
|
||||
let actorBox = new Clutter.ActorBox();
|
||||
|
||||
let [minWidth, minHeight, natWidth, natHeight] = actor.get_preferred_size();
|
||||
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
|
||||
let centerY = dialogBox.y1 + (dialogBox.y2 - dialogBox.y1) / 2;
|
||||
|
||||
natWidth = Math.min(natWidth, dialogBox.x2 - dialogBox.x1);
|
||||
natHeight = Math.min(natHeight, dialogBox.y2 - dialogBox.y1);
|
||||
|
||||
actorBox.x1 = Math.floor(centerX - natWidth / 2);
|
||||
actorBox.y1 = Math.floor(centerY - natHeight / 2);
|
||||
actorBox.x2 = actorBox.x1 + natWidth;
|
||||
actorBox.y2 = actorBox.y1 + natHeight;
|
||||
|
||||
return actorBox;
|
||||
},
|
||||
|
||||
_onAllocate: function (actor, dialogBox, flags) {
|
||||
let dialogWidth = dialogBox.x2 - dialogBox.x1;
|
||||
let dialogHeight = dialogBox.y2 - dialogBox.y1;
|
||||
|
||||
// First find out what space the children require
|
||||
let bannerAllocation = null;
|
||||
let bannerHeight = 0;
|
||||
let bannerWidth = 0;
|
||||
if (this._bannerView.visible) {
|
||||
bannerAllocation = this._getBannerAllocation(dialogBox, this._bannerView);
|
||||
bannerHeight = bannerAllocation.y2 - bannerAllocation.y1;
|
||||
bannerWidth = bannerAllocation.x2 - bannerAllocation.x1;
|
||||
}
|
||||
|
||||
let authPromptAllocation = null;
|
||||
let authPromptHeight = 0;
|
||||
let authPromptWidth = 0;
|
||||
if (this._authPrompt.actor.visible) {
|
||||
authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor);
|
||||
authPromptHeight = authPromptAllocation.y2 - authPromptAllocation.y1;
|
||||
authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1;
|
||||
}
|
||||
|
||||
let userSelectionAllocation = null;
|
||||
let userSelectionHeight = 0;
|
||||
if (this._userSelectionBox.visible) {
|
||||
userSelectionAllocation = this._getCenterActorAllocation(dialogBox, this._userSelectionBox);
|
||||
userSelectionHeight = userSelectionAllocation.y2 - userSelectionAllocation.y1;
|
||||
}
|
||||
|
||||
let logoAllocation = null;
|
||||
let logoHeight = 0;
|
||||
if (this._logoBin.visible) {
|
||||
logoAllocation = this._getLogoBinAllocation(dialogBox);
|
||||
logoHeight = logoAllocation.y2 - logoAllocation.y1;
|
||||
}
|
||||
|
||||
// Then figure out if we're overly constrained and need to
|
||||
// try a different layout, or if we have what extra space we
|
||||
// can hand out
|
||||
if (bannerAllocation) {
|
||||
let bannerSpace;
|
||||
|
||||
if (authPromptAllocation)
|
||||
bannerSpace = authPromptAllocation.y1 - bannerAllocation.y1;
|
||||
else
|
||||
bannerSpace = 0;
|
||||
|
||||
let leftOverYSpace = bannerSpace - bannerHeight;
|
||||
|
||||
if (leftOverYSpace > 0) {
|
||||
// First figure out how much left over space is up top
|
||||
let leftOverTopSpace = leftOverYSpace / 2;
|
||||
|
||||
// Then, shift the banner into the middle of that extra space
|
||||
let yShift = Math.floor(leftOverTopSpace / 2);
|
||||
|
||||
bannerAllocation.y1 += yShift;
|
||||
bannerAllocation.y2 += yShift;
|
||||
} else {
|
||||
// Then figure out how much space there would be if we switched to a
|
||||
// wide layout with banner on one side and authprompt on the other.
|
||||
let leftOverXSpace = dialogWidth - authPromptWidth;
|
||||
|
||||
// In a wide view, half of the available space goes to the banner,
|
||||
// and the other half goes to the margins.
|
||||
let wideBannerWidth = leftOverXSpace / 2;
|
||||
let wideSpacing = leftOverXSpace - wideBannerWidth;
|
||||
|
||||
// If we do go with a wide layout, we need there to be at least enough
|
||||
// space for the banner and the auth prompt to be the same width,
|
||||
// so it doesn't look unbalanced.
|
||||
if (authPromptWidth > 0 && wideBannerWidth > authPromptWidth) {
|
||||
let centerX = dialogBox.x1 + dialogWidth / 2;
|
||||
let centerY = dialogBox.y1 + dialogHeight / 2;
|
||||
|
||||
// A small portion of the spacing goes down the center of the
|
||||
// screen to help delimit the two columns of the wide view
|
||||
let centerGap = wideSpacing / 8;
|
||||
|
||||
// place the banner along the left edge of the center margin
|
||||
bannerAllocation.x2 = Math.floor(centerX - centerGap / 2);
|
||||
bannerAllocation.x1 = Math.floor(bannerAllocation.x2 - wideBannerWidth);
|
||||
|
||||
// figure out how tall it would like to be and try to accomodate
|
||||
// but don't let it get too close to the logo
|
||||
let [wideMinHeight, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth);
|
||||
|
||||
let maxWideHeight = dialogHeight - 3 * logoHeight;
|
||||
wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight);
|
||||
bannerAllocation.y1 = Math.floor(centerY - wideBannerHeight / 2);
|
||||
bannerAllocation.y2 = bannerAllocation.y1 + wideBannerHeight;
|
||||
|
||||
// place the auth prompt along the right edge of the center margin
|
||||
authPromptAllocation.x1 = Math.floor(centerX + centerGap / 2);
|
||||
authPromptAllocation.x2 = authPromptAllocation.x1 + authPromptWidth;
|
||||
} else {
|
||||
// If we aren't going to do a wide view, then we need to limit
|
||||
// the height of the banner so it will present scrollbars
|
||||
|
||||
// First figure out how much space there is without the banner
|
||||
leftOverYSpace += bannerHeight;
|
||||
|
||||
// Then figure out how much of that space is up top
|
||||
let availableTopSpace = Math.floor(leftOverYSpace / 2);
|
||||
|
||||
// Then give all of that space to the banner
|
||||
bannerAllocation.y2 = bannerAllocation.y1 + availableTopSpace;
|
||||
}
|
||||
}
|
||||
} else if (userSelectionAllocation) {
|
||||
// Grow the user list to fill the space
|
||||
let leftOverYSpace = dialogHeight - userSelectionHeight - logoHeight;
|
||||
|
||||
if (leftOverYSpace > 0) {
|
||||
let topExpansion = Math.floor(leftOverYSpace / 2);
|
||||
let bottomExpansion = topExpansion;
|
||||
|
||||
userSelectionAllocation.y1 -= topExpansion;
|
||||
userSelectionAllocation.y2 += bottomExpansion;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally hand out the allocations
|
||||
if (bannerAllocation) {
|
||||
this._bannerView.allocate(bannerAllocation, flags);
|
||||
}
|
||||
|
||||
if (authPromptAllocation)
|
||||
this._authPrompt.actor.allocate(authPromptAllocation, flags);
|
||||
|
||||
if (userSelectionAllocation)
|
||||
this._userSelectionBox.allocate(userSelectionAllocation, flags);
|
||||
|
||||
if (logoAllocation)
|
||||
this._logoBin.allocate(logoAllocation, flags);
|
||||
},
|
||||
|
||||
_ensureUserListLoaded: function() {
|
||||
if (!this._userManager.is_loaded) {
|
||||
this._userManagerLoadedId = this._userManager.connect('notify::is-loaded',
|
||||
@ -537,6 +736,20 @@ const LoginDialog = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_fadeInBannerView: function() {
|
||||
this._bannerView.show();
|
||||
Tweener.addTween(this._bannerView,
|
||||
{ opacity: 255,
|
||||
time: _FADE_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
},
|
||||
|
||||
_hideBannerView: function() {
|
||||
Tweener.removeTweens(this._bannerView);
|
||||
this._bannerView.opacity = 0;
|
||||
this._bannerView.hide();
|
||||
},
|
||||
|
||||
_updateLogoTexture: function(cache, file) {
|
||||
if (this._logoFile && !this._logoFile.equal(file))
|
||||
return;
|
||||
@ -565,7 +778,24 @@ const LoginDialog = new Lang.Class({
|
||||
this._showPrompt();
|
||||
},
|
||||
|
||||
_resetGreeterProxy: function() {
|
||||
if (GLib.getenv('GDM_GREETER_TEST') != '1') {
|
||||
if (this._greeter) {
|
||||
this._greeter.run_dispose();
|
||||
}
|
||||
this._greeter = this._gdmClient.get_greeter_sync(null);
|
||||
|
||||
this._defaultSessionChangedId = this._greeter.connect('default-session-name-changed',
|
||||
Lang.bind(this, this._onDefaultSessionChanged));
|
||||
this._sessionOpenedId = this._greeter.connect('session-opened',
|
||||
Lang.bind(this, this._onSessionOpened));
|
||||
this._timedLoginRequestedId = this._greeter.connect('timed-login-requested',
|
||||
Lang.bind(this, this._onTimedLoginRequested));
|
||||
}
|
||||
},
|
||||
|
||||
_onReset: function(authPrompt, beginRequest) {
|
||||
this._resetGreeterProxy();
|
||||
this._sessionMenuButton.updateSensitivity(true);
|
||||
|
||||
this._user = null;
|
||||
@ -604,6 +834,7 @@ const LoginDialog = new Lang.Class({
|
||||
{ opacity: 255,
|
||||
time: _FADE_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
this._fadeInBannerView();
|
||||
},
|
||||
|
||||
_showRealmLoginHint: function(realmManager, hint) {
|
||||
@ -623,31 +854,30 @@ const LoginDialog = new Lang.Class({
|
||||
this._authPrompt.setPasswordChar('');
|
||||
this._authPrompt.setQuestion(_("Username: "));
|
||||
|
||||
let realmManager = new Realmd.Manager();
|
||||
let realmSignalId = realmManager.connect('login-format-changed',
|
||||
Lang.bind(this, this._showRealmLoginHint));
|
||||
this._showRealmLoginHint(realmManager.loginFormat);
|
||||
this._showRealmLoginHint(this._realmManager.loginFormat);
|
||||
|
||||
let nextSignalId = this._authPrompt.connect('next',
|
||||
Lang.bind(this, function() {
|
||||
this._authPrompt.disconnect(nextSignalId);
|
||||
this._authPrompt.updateSensitivity(false);
|
||||
let answer = this._authPrompt.getAnswer();
|
||||
this._user = this._userManager.get_user(answer);
|
||||
this._authPrompt.clear();
|
||||
this._authPrompt.startSpinning();
|
||||
this._authPrompt.begin({ userName: answer });
|
||||
this._updateCancelButton();
|
||||
|
||||
realmManager.disconnect(realmSignalId)
|
||||
realmManager.release();
|
||||
}));
|
||||
if (this._nextSignalId)
|
||||
this._authPrompt.disconnect(this._nextSignalId);
|
||||
this._nextSignalId = this._authPrompt.connect('next',
|
||||
Lang.bind(this, function() {
|
||||
this._authPrompt.disconnect(this._nextSignalId);
|
||||
this._nextSignalId = 0;
|
||||
this._authPrompt.updateSensitivity(false);
|
||||
let answer = this._authPrompt.getAnswer();
|
||||
this._user = this._userManager.get_user(answer);
|
||||
this._authPrompt.clear();
|
||||
this._authPrompt.startSpinning();
|
||||
this._authPrompt.begin({ userName: answer });
|
||||
this._updateCancelButton();
|
||||
}));
|
||||
this._updateCancelButton();
|
||||
|
||||
this._authPrompt.updateSensitivity(true);
|
||||
this._showPrompt();
|
||||
},
|
||||
|
||||
_loginScreenSessionActivated: function() {
|
||||
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFICATION_SUCCEEDED)
|
||||
if (this.actor.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
|
||||
return;
|
||||
|
||||
Tweener.addTween(this.actor,
|
||||
@ -664,7 +894,8 @@ const LoginDialog = new Lang.Class({
|
||||
},
|
||||
onUpdateScope: this,
|
||||
onComplete: function() {
|
||||
this._authPrompt.reset();
|
||||
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
|
||||
this._authPrompt.reset();
|
||||
},
|
||||
onCompleteScope: this });
|
||||
},
|
||||
@ -858,6 +1089,7 @@ const LoginDialog = new Lang.Class({
|
||||
_showUserList: function() {
|
||||
this._ensureUserListLoaded();
|
||||
this._authPrompt.hide();
|
||||
this._hideBannerView();
|
||||
this._sessionMenuButton.close();
|
||||
this._setUserListExpanded(true);
|
||||
this._notListedButton.show();
|
||||
@ -876,18 +1108,11 @@ const LoginDialog = new Lang.Class({
|
||||
},
|
||||
|
||||
_onUserListActivated: function(activatedItem) {
|
||||
let tasks = [function() {
|
||||
return GdmUtil.cloneAndFadeOutActor(this._userSelectionBox);
|
||||
},
|
||||
function() {
|
||||
this._setUserListExpanded(false);
|
||||
}];
|
||||
|
||||
this._user = activatedItem.user;
|
||||
|
||||
this._updateCancelButton();
|
||||
|
||||
let batch = new Batch.ConcurrentBatch(this, [new Batch.ConsecutiveBatch(this, tasks),
|
||||
let batch = new Batch.ConcurrentBatch(this, [GdmUtil.cloneAndFadeOutActor(this._userSelectionBox),
|
||||
this._beginVerificationForItem(activatedItem)]);
|
||||
batch.run();
|
||||
},
|
||||
@ -921,6 +1146,12 @@ const LoginDialog = new Lang.Class({
|
||||
this._greeterSessionProxy.disconnect(this._greeterSessionProxyChangedId);
|
||||
this._greeterSessionProxy = null;
|
||||
}
|
||||
if (this._realmManager) {
|
||||
this._realmManager.disconnect(this._realmSignalId);
|
||||
this._realmSignalId = 0;
|
||||
this._realmManager.release();
|
||||
this._realmManager = null;
|
||||
}
|
||||
},
|
||||
|
||||
_loadUserList: function() {
|
||||
@ -957,7 +1188,7 @@ const LoginDialog = new Lang.Class({
|
||||
this.actor.show();
|
||||
this.actor.opacity = 0;
|
||||
|
||||
Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOGIN_SCREEN });
|
||||
Main.pushModal(this.actor, { actionMode: Shell.ActionMode.LOGIN_SCREEN });
|
||||
|
||||
Tweener.addTween(this.actor,
|
||||
{ opacity: 255,
|
||||
|
@ -35,8 +35,8 @@ const ALLOWED_FAILURES_KEY = 'allowed-failures';
|
||||
const LOGO_KEY = 'logo';
|
||||
const DISABLE_USER_LIST_KEY = 'disable-user-list';
|
||||
|
||||
// Give user 16ms to read each character of a PAM message
|
||||
const USER_READ_TIME = 16
|
||||
// Give user 48ms to read each character of a PAM message
|
||||
const USER_READ_TIME = 48
|
||||
|
||||
const MessageType = {
|
||||
NONE: 0,
|
||||
@ -410,7 +410,7 @@ const ShellUserVerifier = new Lang.Class({
|
||||
_updateDefaultService: function() {
|
||||
if (this._settings.get_boolean(PASSWORD_AUTHENTICATION_KEY))
|
||||
this._defaultService = PASSWORD_SERVICE_NAME;
|
||||
else if (this.smartcardDetected)
|
||||
else if (this._settings.get_boolean(SMARTCARD_AUTHENTICATION_KEY))
|
||||
this._defaultService = SMARTCARD_SERVICE_NAME;
|
||||
else if (this._haveFingerprintReader)
|
||||
this._defaultService = FINGERPRINT_SERVICE_NAME;
|
||||
|
@ -57,6 +57,7 @@
|
||||
<file>ui/layout.js</file>
|
||||
<file>ui/lightbox.js</file>
|
||||
<file>ui/lookingGlass.js</file>
|
||||
<file>ui/legacyTray.js</file>
|
||||
<file>ui/magnifier.js</file>
|
||||
<file>ui/magnifierDBus.js</file>
|
||||
<file>ui/main.js</file>
|
||||
@ -64,6 +65,7 @@
|
||||
<file>ui/modalDialog.js</file>
|
||||
<file>ui/notificationDaemon.js</file>
|
||||
<file>ui/osdWindow.js</file>
|
||||
<file>ui/osdMonitorLabeler.js</file>
|
||||
<file>ui/overview.js</file>
|
||||
<file>ui/overviewControls.js</file>
|
||||
<file>ui/panel.js</file>
|
||||
|
@ -43,7 +43,7 @@ function getCurrentExtension() {
|
||||
let path = match[1];
|
||||
let file = Gio.File.new_for_path(path);
|
||||
|
||||
// Walk up the directory tree, looking for an extesion with
|
||||
// Walk up the directory tree, looking for an extension with
|
||||
// the same UUID as a directory name.
|
||||
while (file != null) {
|
||||
let extension = extensions[file.get_basename()];
|
||||
|
@ -1,13 +1,14 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
|
||||
try {
|
||||
var IBus = imports.gi.IBus;
|
||||
if (!('new_async' in IBus.Bus))
|
||||
throw "IBus version is too old";
|
||||
_checkIBusVersion(1, 5, 2);
|
||||
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
|
||||
} catch (e) {
|
||||
var IBus = null;
|
||||
@ -16,6 +17,18 @@ try {
|
||||
|
||||
let _ibusManager = null;
|
||||
|
||||
function _checkIBusVersion(requiredMajor, requiredMinor, requiredMicro) {
|
||||
if ((IBus.MAJOR_VERSION > requiredMajor) ||
|
||||
(IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION > requiredMinor) ||
|
||||
(IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION == requiredMinor &&
|
||||
IBus.MICRO_VERSION >= requiredMicro))
|
||||
return;
|
||||
|
||||
throw "Found IBus version %d.%d.%d but required is %d.%d.%d".
|
||||
format(IBus.MAJOR_VERSION, IBus.MINOR_VERSION, IBus.MINOR_VERSION,
|
||||
requiredMajor, requiredMinor, requiredMicro);
|
||||
}
|
||||
|
||||
function getIBusManager() {
|
||||
if (_ibusManager == null)
|
||||
_ibusManager = new IBusManager();
|
||||
@ -28,6 +41,7 @@ const IBusManager = new Lang.Class({
|
||||
// This is the longest we'll keep the keyboard frozen until an input
|
||||
// source is active.
|
||||
_MAX_INPUT_SOURCE_ACTIVATION_TIME: 4000, // ms
|
||||
_PRELOAD_ENGINES_DELAY_TIME: 30, // sec
|
||||
|
||||
_init: function() {
|
||||
if (!IBus)
|
||||
@ -42,6 +56,7 @@ const IBusManager = new Lang.Class({
|
||||
this._ready = false;
|
||||
this._registerPropertiesId = 0;
|
||||
this._currentEngineName = null;
|
||||
this._preloadEnginesId = 0;
|
||||
|
||||
this._ibus = IBus.Bus.new_async();
|
||||
this._ibus.connect('connected', Lang.bind(this, this._onConnected));
|
||||
@ -106,6 +121,16 @@ const IBusManager = new Lang.Class({
|
||||
object_path: IBus.PATH_PANEL });
|
||||
this._candidatePopup.setPanelService(this._panelService);
|
||||
this._panelService.connect('update-property', Lang.bind(this, this._updateProperty));
|
||||
try {
|
||||
// IBus versions older than 1.5.10 have a bug which
|
||||
// causes spurious set-content-type emissions when
|
||||
// switching input focus that temporarily lose purpose
|
||||
// and hints defeating its intended semantics and
|
||||
// confusing users. We thus don't use it in that case.
|
||||
_checkIBusVersion(1, 5, 10);
|
||||
this._panelService.connect('set-content-type', Lang.bind(this, this._setContentType));
|
||||
} catch (e) {
|
||||
}
|
||||
// If an engine is already active we need to get its properties
|
||||
this._ibus.get_global_engine_async(-1, null, Lang.bind(this, function(i, result) {
|
||||
let engine;
|
||||
@ -155,6 +180,10 @@ const IBusManager = new Lang.Class({
|
||||
this.emit('property-updated', this._currentEngineName, prop);
|
||||
},
|
||||
|
||||
_setContentType: function(panel, purpose, hints) {
|
||||
this.emit('set-content-type', purpose, hints);
|
||||
},
|
||||
|
||||
activateProperty: function(key, state) {
|
||||
this._panelService.property_activate(key, state);
|
||||
},
|
||||
@ -167,7 +196,10 @@ const IBusManager = new Lang.Class({
|
||||
},
|
||||
|
||||
setEngine: function(id, callback) {
|
||||
if (!IBus || !this._ready || id == this._currentEngineName) {
|
||||
// Send id even if id == this._currentEngineName
|
||||
// because 'properties-registered' signal can be emitted
|
||||
// while this._ibusSources == null on a lock screen.
|
||||
if (!IBus || !this._ready) {
|
||||
if (callback)
|
||||
callback();
|
||||
return;
|
||||
@ -176,5 +208,27 @@ const IBusManager = new Lang.Class({
|
||||
this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
|
||||
null, callback);
|
||||
},
|
||||
|
||||
preloadEngines: function(ids) {
|
||||
if (!IBus || !this._ibus || ids.length == 0)
|
||||
return;
|
||||
|
||||
if (this._preloadEnginesId != 0) {
|
||||
Mainloop.source_remove(this._preloadEnginesId);
|
||||
this._preloadEnginesId = 0;
|
||||
}
|
||||
|
||||
this._preloadEnginesId =
|
||||
Mainloop.timeout_add_seconds(this._PRELOAD_ENGINES_DELAY_TIME,
|
||||
Lang.bind(this, function() {
|
||||
this._ibus.preload_engines_async(
|
||||
ids,
|
||||
-1,
|
||||
null,
|
||||
null);
|
||||
this._preloadEnginesId = 0;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
},
|
||||
});
|
||||
Signals.addSignalMethods(IBusManager.prototype);
|
||||
|
@ -134,7 +134,7 @@ const LoginManagerSystemd = new Lang.Class({
|
||||
if (error)
|
||||
asyncCallback(false);
|
||||
else
|
||||
asyncCallback(result[0] != 'no');
|
||||
asyncCallback(result[0] != 'no' && result[0] != 'na');
|
||||
});
|
||||
},
|
||||
|
||||
|
103
js/misc/util.js
@ -4,10 +4,12 @@ const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Params = imports.misc.params;
|
||||
|
||||
const SCROLL_TIME = 0.1;
|
||||
|
||||
@ -38,6 +40,8 @@ const _urlRegexp = new RegExp(
|
||||
')' +
|
||||
')', 'gi');
|
||||
|
||||
let _desktopSettings = null;
|
||||
|
||||
// findUrls:
|
||||
// @str: string to find URLs in
|
||||
//
|
||||
@ -157,6 +161,105 @@ function _handleSpawnError(command, err) {
|
||||
Main.notifyError(title, err.message);
|
||||
}
|
||||
|
||||
function formatTime(time, params) {
|
||||
let date;
|
||||
// HACK: The built-in Date type sucks at timezones, which we need for the
|
||||
// world clock; it's often more convenient though, so allow either
|
||||
// Date or GLib.DateTime as parameter
|
||||
if (time instanceof Date)
|
||||
date = GLib.DateTime.new_from_unix_local(time.getTime() / 1000);
|
||||
else
|
||||
date = time;
|
||||
|
||||
let now = GLib.DateTime.new_now_local();
|
||||
|
||||
let daysAgo = now.difference(date) / (24 * 60 * 60 * 1000 * 1000);
|
||||
|
||||
let format;
|
||||
|
||||
if (_desktopSettings == null)
|
||||
_desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
|
||||
let clockFormat = _desktopSettings.get_string('clock-format');
|
||||
let hasAmPm = date.format('%p') != '';
|
||||
|
||||
params = Params.parse(params, { timeOnly: false });
|
||||
|
||||
if (clockFormat == '24h' || !hasAmPm) {
|
||||
// Show only the time if date is on today
|
||||
if (daysAgo < 1 || params.timeOnly)
|
||||
/* Translators: Time in 24h format */
|
||||
format = N_("%H\u2236%M");
|
||||
// Show the word "Yesterday" and time if date is on yesterday
|
||||
else if (daysAgo <2)
|
||||
/* Translators: this is the word "Yesterday" followed by a
|
||||
time string in 24h format. i.e. "Yesterday, 14:30" */
|
||||
// xgettext:no-c-format
|
||||
format = N_("Yesterday, %H\u2236%M");
|
||||
// Show a week day and time if date is in the last week
|
||||
else if (daysAgo < 7)
|
||||
/* Translators: this is the week day name followed by a time
|
||||
string in 24h format. i.e. "Monday, 14:30" */
|
||||
// xgettext:no-c-format
|
||||
format = N_("%A, %H\u2236%M");
|
||||
else if (date.get_year() == now.get_year())
|
||||
/* Translators: this is the month name and day number
|
||||
followed by a time string in 24h format.
|
||||
i.e. "May 25, 14:30" */
|
||||
// xgettext:no-c-format
|
||||
format = N_("%B %d, %H\u2236%M");
|
||||
else
|
||||
/* Translators: this is the month name, day number, year
|
||||
number followed by a time string in 24h format.
|
||||
i.e. "May 25 2012, 14:30" */
|
||||
// xgettext:no-c-format
|
||||
format = N_("%B %d %Y, %H\u2236%M");
|
||||
} else {
|
||||
// Show only the time if date is on today
|
||||
if (daysAgo < 1 || params.timeOnly)
|
||||
/* Translators: Time in 12h format */
|
||||
format = N_("%l\u2236%M %p");
|
||||
// Show the word "Yesterday" and time if date is on yesterday
|
||||
else if (daysAgo <2)
|
||||
/* Translators: this is the word "Yesterday" followed by a
|
||||
time string in 12h format. i.e. "Yesterday, 2:30 pm" */
|
||||
// xgettext:no-c-format
|
||||
format = N_("Yesterday, %l\u2236%M %p");
|
||||
// Show a week day and time if date is in the last week
|
||||
else if (daysAgo < 7)
|
||||
/* Translators: this is the week day name followed by a time
|
||||
string in 12h format. i.e. "Monday, 2:30 pm" */
|
||||
// xgettext:no-c-format
|
||||
format = N_("%A, %l\u2236%M %p");
|
||||
else if (date.get_year() == now.get_year())
|
||||
/* Translators: this is the month name and day number
|
||||
followed by a time string in 12h format.
|
||||
i.e. "May 25, 2:30 pm" */
|
||||
// xgettext:no-c-format
|
||||
format = N_("%B %d, %l\u2236%M %p");
|
||||
else
|
||||
/* Translators: this is the month name, day number, year
|
||||
number followed by a time string in 12h format.
|
||||
i.e. "May 25 2012, 2:30 pm"*/
|
||||
// xgettext:no-c-format
|
||||
format = N_("%B %d %Y, %l\u2236%M %p");
|
||||
}
|
||||
return date.format(Shell.util_translate_time_string(format));
|
||||
}
|
||||
|
||||
function createTimeLabel(date, params) {
|
||||
if (_desktopSettings == null)
|
||||
_desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
|
||||
|
||||
let label = new St.Label({ text: formatTime(date, params) });
|
||||
let id = _desktopSettings.connect('changed::clock-format', function() {
|
||||
label.text = formatTime(date, params);
|
||||
});
|
||||
label.connect('destroy', function() {
|
||||
_desktopSettings.disconnect(id);
|
||||
});
|
||||
return label;
|
||||
}
|
||||
|
||||
// lowerBound:
|
||||
// @array: an array or array-like object, already sorted
|
||||
// according to @cmp
|
||||
|
@ -80,8 +80,8 @@ const PortalWindow = new Lang.Class({
|
||||
if (title) {
|
||||
this.title = title;
|
||||
} else {
|
||||
// TRANSLATORS: this is the title of the wifi captive portal login
|
||||
// window, until we know the title of the actual login page
|
||||
/* TRANSLATORS: this is the title of the wifi captive portal login
|
||||
* window, until we know the title of the actual login page */
|
||||
this.title = _("Web Authentication Redirect");
|
||||
}
|
||||
},
|
||||
|
@ -81,7 +81,6 @@ const AppSwitcherPopup = new Lang.Class({
|
||||
let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
|
||||
let rightPadding = this.actor.get_theme_node().get_padding(St.Side.RIGHT);
|
||||
let bottomPadding = this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
|
||||
let vPadding = this.actor.get_theme_node().get_vertical_padding();
|
||||
let hPadding = leftPadding + rightPadding;
|
||||
|
||||
let icon = this._items[this._selectedIndex].actor;
|
||||
|
@ -7,7 +7,7 @@ const St = imports.gi.St;
|
||||
const Signals = imports.signals;
|
||||
const Atk = imports.gi.Atk;
|
||||
|
||||
const ANIMATED_ICON_UPDATE_TIMEOUT = 100;
|
||||
const ANIMATED_ICON_UPDATE_TIMEOUT = 14;
|
||||
|
||||
const Animation = new Lang.Class({
|
||||
Name: 'Animation',
|
||||
|
@ -500,6 +500,11 @@ const AllView = new Lang.Class({
|
||||
|
||||
_loadApps: function() {
|
||||
let apps = Gio.AppInfo.get_all().filter(function(appInfo) {
|
||||
try {
|
||||
let id = appInfo.get_id(); // catch invalid file encodings
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
return appInfo.should_show();
|
||||
}).map(function(app) {
|
||||
return app.get_id();
|
||||
@ -517,9 +522,19 @@ const AllView = new Lang.Class({
|
||||
this.folderIcons.push(icon);
|
||||
}));
|
||||
|
||||
// Allow dragging of the icon only if the Dash would accept a drop to
|
||||
// change favorite-apps. There are no other possible drop targets from
|
||||
// the app picker, so there's no other need for a drag to start,
|
||||
// at least on single-monitor setups.
|
||||
// This also disables drag-to-launch on multi-monitor setups,
|
||||
// but we hope that is not used much.
|
||||
let favoritesWritable = global.settings.is_writable('favorite-apps');
|
||||
|
||||
apps.forEach(Lang.bind(this, function(appId) {
|
||||
let app = appSys.lookup_app(appId);
|
||||
let icon = new AppIcon(app);
|
||||
|
||||
let icon = new AppIcon(app,
|
||||
{ isDraggable: favoritesWritable });
|
||||
this.addItem(icon);
|
||||
}));
|
||||
|
||||
@ -529,6 +544,13 @@ const AllView = new Lang.Class({
|
||||
|
||||
// Overriden from BaseAppView
|
||||
animate: function (animationDirection, onComplete) {
|
||||
this._scrollView.reactive = false;
|
||||
let completionFunc = Lang.bind(this, function() {
|
||||
this._scrollView.reactive = true;
|
||||
if (onComplete)
|
||||
onComplete();
|
||||
});
|
||||
|
||||
if (animationDirection == IconGrid.AnimationDirection.OUT &&
|
||||
this._displayingPopup && this._currentPopup) {
|
||||
this._currentPopup.popdown();
|
||||
@ -539,10 +561,10 @@ const AllView = new Lang.Class({
|
||||
// signal handler, call again animate which will
|
||||
// call the parent given that popup is already
|
||||
// closed.
|
||||
this.animate(animationDirection, onComplete);
|
||||
this.animate(animationDirection, completionFunc);
|
||||
}));
|
||||
} else {
|
||||
this.parent(animationDirection, onComplete);
|
||||
this.parent(animationDirection, completionFunc);
|
||||
if (animationDirection == IconGrid.AnimationDirection.OUT)
|
||||
this._pageIndicators.animateIndicators(animationDirection);
|
||||
}
|
||||
@ -629,7 +651,7 @@ const AllView = new Lang.Class({
|
||||
},
|
||||
|
||||
_onScroll: function(actor, event) {
|
||||
if (this._displayingPopup)
|
||||
if (this._displayingPopup || !this._scrollView.reactive)
|
||||
return Clutter.EVENT_STOP;
|
||||
|
||||
let direction = event.get_scroll_direction();
|
||||
@ -736,7 +758,8 @@ const AllView = new Lang.Class({
|
||||
let fadeOffset = Math.min(this._grid.topPadding,
|
||||
this._grid.bottomPadding);
|
||||
this._scrollView.update_fade_effect(fadeOffset, 0);
|
||||
this._scrollView.get_effect('fade').fade_edges = true;
|
||||
if (fadeOffset > 0)
|
||||
this._scrollView.get_effect('fade').fade_edges = true;
|
||||
|
||||
if (this._availWidth != availWidth || this._availHeight != availHeight || oldNPages != this._grid.nPages()) {
|
||||
this._adjustment.value = 0;
|
||||
@ -763,6 +786,7 @@ const FrequentView = new Lang.Class({
|
||||
|
||||
_init: function() {
|
||||
this.parent(null, { fillParent: true });
|
||||
|
||||
this.actor = new St.Widget({ style_class: 'frequent-apps',
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true, y_expand: true });
|
||||
@ -799,10 +823,19 @@ const FrequentView = new Lang.Class({
|
||||
if(!hasUsefulData)
|
||||
return;
|
||||
|
||||
// Allow dragging of the icon only if the Dash would accept a drop to
|
||||
// change favorite-apps. There are no other possible drop targets from
|
||||
// the app picker, so there's no other need for a drag to start,
|
||||
// at least on single-monitor setups.
|
||||
// This also disables drag-to-launch on multi-monitor setups,
|
||||
// but we hope that is not used much.
|
||||
let favoritesWritable = global.settings.is_writable('favorite-apps');
|
||||
|
||||
for (let i = 0; i < mostUsed.length; i++) {
|
||||
if (!mostUsed[i].get_app_info().should_show())
|
||||
continue;
|
||||
let appIcon = new AppIcon(mostUsed[i]);
|
||||
let appIcon = new AppIcon(mostUsed[i],
|
||||
{ isDraggable: favoritesWritable });
|
||||
this._grid.addItem(appIcon, -1);
|
||||
}
|
||||
},
|
||||
@ -879,14 +912,14 @@ const AppDisplay = new Lang.Class({
|
||||
let view, button;
|
||||
view = new FrequentView();
|
||||
button = new St.Button({ label: _("Frequent"),
|
||||
style_class: 'app-view-control',
|
||||
style_class: 'app-view-control button',
|
||||
can_focus: true,
|
||||
x_expand: true });
|
||||
this._views[Views.FREQUENT] = { 'view': view, 'control': button };
|
||||
|
||||
view = new AllView();
|
||||
button = new St.Button({ label: _("All"),
|
||||
style_class: 'app-view-control',
|
||||
style_class: 'app-view-control button',
|
||||
can_focus: true,
|
||||
x_expand: true });
|
||||
this._views[Views.ALL] = { 'view': view, 'control': button };
|
||||
@ -1033,7 +1066,7 @@ const AppSearchProvider = new Lang.Class({
|
||||
|
||||
getInitialResultSet: function(terms, callback, cancellable) {
|
||||
let query = terms.join(' ');
|
||||
let groups = Gio.DesktopAppInfo.search(query);
|
||||
let groups = Shell.AppSystem.search(query);
|
||||
let usage = Shell.AppUsage.get_default();
|
||||
let results = [];
|
||||
groups.forEach(function(group) {
|
||||
@ -1262,7 +1295,10 @@ const FolderIcon = new Lang.Class({
|
||||
if (!_listsIntersect(folderCategories, appCategories))
|
||||
return;
|
||||
|
||||
addAppId(appInfo.get_id());
|
||||
try {
|
||||
addAppId(appInfo.get_id()); // catch invalid file encodings
|
||||
} catch(e) {
|
||||
}
|
||||
});
|
||||
|
||||
this.actor.visible = this.view.getAllItems().length > 0;
|
||||
@ -1517,12 +1553,12 @@ const AppIcon = new Lang.Class({
|
||||
this.id = app.get_id();
|
||||
this.name = app.get_name();
|
||||
|
||||
// We need to make it track_hover so dash item can connect to
|
||||
// the hover signal of the actor in _hookupLabel to call
|
||||
// shouldShowTooltip when hovered.
|
||||
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(),
|
||||
this.actor = new St.Button({ style_class: 'app-well-app',
|
||||
reactive: true,
|
||||
track_hover: true });
|
||||
button_mask: St.ButtonMask.ONE | St.ButtonMask.TWO,
|
||||
can_focus: true,
|
||||
x_fill: true,
|
||||
y_fill: true });
|
||||
|
||||
this._dot = new St.Widget({ style_class: 'app-well-app-running-dot',
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
@ -1530,54 +1566,54 @@ const AppIcon = new Lang.Class({
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.END });
|
||||
|
||||
this._dot.hide();
|
||||
this._iconContainer = new St.Widget({ layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true, y_expand: true });
|
||||
|
||||
this._button = new St.Button({ style_class: 'app-well-app',
|
||||
reactive: true,
|
||||
button_mask: St.ButtonMask.ONE | St.ButtonMask.TWO,
|
||||
can_focus: true,
|
||||
x_fill: true,
|
||||
y_fill: true });
|
||||
|
||||
this.actor.add_actor(this._button);
|
||||
this.actor.add_actor(this._dot);
|
||||
this.actor.set_child(this._iconContainer);
|
||||
this._iconContainer.add_child(this._dot);
|
||||
|
||||
this.actor._delegate = this;
|
||||
this._button._delegate = this;
|
||||
|
||||
if (!iconParams)
|
||||
iconParams = {};
|
||||
|
||||
// Get the isDraggable property without passing it on to the BaseIcon:
|
||||
let appIconParams = Params.parse(iconParams, { isDraggable: true }, true);
|
||||
let isDraggable = appIconParams['isDraggable'];
|
||||
delete iconParams['isDraggable'];
|
||||
|
||||
iconParams['createIcon'] = Lang.bind(this, this._createIcon);
|
||||
iconParams['setSizeManually'] = true;
|
||||
this.icon = new IconGrid.BaseIcon(app.get_name(), iconParams);
|
||||
this._button.set_child(this.icon.actor);
|
||||
this._iconContainer.add_child(this.icon.actor);
|
||||
|
||||
this.actor.label_actor = this.icon.label;
|
||||
|
||||
this._button.connect('leave-event', Lang.bind(this, this._onLeaveEvent));
|
||||
this._button.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
||||
this._button.connect('touch-event', Lang.bind(this, this._onTouchEvent));
|
||||
this._button.connect('clicked', Lang.bind(this, this._onClicked));
|
||||
this._button.connect('popup-menu', Lang.bind(this, this._onKeyboardPopupMenu));
|
||||
this.actor.connect('leave-event', Lang.bind(this, this._onLeaveEvent));
|
||||
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
||||
this.actor.connect('touch-event', Lang.bind(this, this._onTouchEvent));
|
||||
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
|
||||
this.actor.connect('popup-menu', Lang.bind(this, this._onKeyboardPopupMenu));
|
||||
|
||||
this._menu = null;
|
||||
this._menuManager = new PopupMenu.PopupMenuManager(this);
|
||||
|
||||
this._draggable = DND.makeDraggable(this._button);
|
||||
this._draggable.connect('drag-begin', Lang.bind(this,
|
||||
function () {
|
||||
this._removeMenuTimeout();
|
||||
Main.overview.beginItemDrag(this);
|
||||
}));
|
||||
this._draggable.connect('drag-cancelled', Lang.bind(this,
|
||||
function () {
|
||||
Main.overview.cancelledItemDrag(this);
|
||||
}));
|
||||
this._draggable.connect('drag-end', Lang.bind(this,
|
||||
function () {
|
||||
Main.overview.endItemDrag(this);
|
||||
}));
|
||||
if (isDraggable) {
|
||||
this._draggable = DND.makeDraggable(this.actor);
|
||||
this._draggable.connect('drag-begin', Lang.bind(this,
|
||||
function () {
|
||||
this._removeMenuTimeout();
|
||||
Main.overview.beginItemDrag(this);
|
||||
}));
|
||||
this._draggable.connect('drag-cancelled', Lang.bind(this,
|
||||
function () {
|
||||
Main.overview.cancelledItemDrag(this);
|
||||
}));
|
||||
this._draggable.connect('drag-end', Lang.bind(this,
|
||||
function () {
|
||||
Main.overview.endItemDrag(this);
|
||||
}));
|
||||
}
|
||||
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
||||
@ -1589,18 +1625,6 @@ const AppIcon = new Lang.Class({
|
||||
this._updateRunningStyle();
|
||||
},
|
||||
|
||||
// Needed for containers that want to track focus of the widget
|
||||
// for i.e. scroll the container when navigating through items
|
||||
getFocusReceiver: function () {
|
||||
return this._button;
|
||||
},
|
||||
|
||||
// Needed for containers that want to change style of the widget
|
||||
// for i.e. set as selected when searching in shell
|
||||
getStyleReceiver: function () {
|
||||
return this._button;
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
if (this._stateChangedId > 0)
|
||||
this.app.disconnect(this._stateChangedId);
|
||||
@ -1620,13 +1644,10 @@ const AppIcon = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateRunningStyle: function() {
|
||||
if (this.app.state != Shell.AppState.STOPPED) {
|
||||
this._button.add_style_class_name('running');
|
||||
if (this.app.state != Shell.AppState.STOPPED)
|
||||
this._dot.show();
|
||||
} else {
|
||||
this._button.remove_style_class_name('running');
|
||||
else
|
||||
this._dot.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_setPopupTimeout: function() {
|
||||
@ -1641,7 +1662,7 @@ const AppIcon = new Lang.Class({
|
||||
},
|
||||
|
||||
_onLeaveEvent: function(actor, event) {
|
||||
this._button.fake_release();
|
||||
this.actor.fake_release();
|
||||
this._removeMenuTimeout();
|
||||
},
|
||||
|
||||
@ -1679,8 +1700,10 @@ const AppIcon = new Lang.Class({
|
||||
|
||||
popupMenu: function() {
|
||||
this._removeMenuTimeout();
|
||||
this._button.fake_release();
|
||||
this._draggable.fakeRelease();
|
||||
this.actor.fake_release();
|
||||
|
||||
if (this._draggable)
|
||||
this._draggable.fakeRelease();
|
||||
|
||||
if (!this._menu) {
|
||||
this._menu = new AppIconMenu(this);
|
||||
@ -1691,14 +1714,17 @@ const AppIcon = new Lang.Class({
|
||||
if (!isPoppedUp)
|
||||
this._onMenuPoppedDown();
|
||||
}));
|
||||
Main.overview.connect('hiding', Lang.bind(this, function () { this._menu.close(); }));
|
||||
let id = Main.overview.connect('hiding', Lang.bind(this, function () { this._menu.close(); }));
|
||||
this.actor.connect('destroy', function() {
|
||||
Main.overview.disconnect(id);
|
||||
});
|
||||
|
||||
this._menuManager.addMenu(this._menu);
|
||||
}
|
||||
|
||||
this.emit('menu-state-changed', true);
|
||||
|
||||
this._button.set_hover(true);
|
||||
this.actor.set_hover(true);
|
||||
this._menu.popup();
|
||||
this._menuManager.ignoreRelease();
|
||||
this.emit('sync-tooltip');
|
||||
@ -1715,7 +1741,7 @@ const AppIcon = new Lang.Class({
|
||||
},
|
||||
|
||||
_onMenuPoppedDown: function() {
|
||||
this._button.sync_hover();
|
||||
this.actor.sync_hover();
|
||||
this.emit('menu-state-changed', false);
|
||||
},
|
||||
|
||||
@ -1820,7 +1846,10 @@ const AppIconMenu = new Lang.Class({
|
||||
if (!this._source.app.is_window_backed()) {
|
||||
this._appendSeparator();
|
||||
|
||||
if (this._source.app.can_open_new_window()) {
|
||||
let appInfo = this._source.app.get_app_info();
|
||||
let actions = appInfo.list_actions();
|
||||
if (this._source.app.can_open_new_window() &&
|
||||
actions.indexOf('new-window') == -1) {
|
||||
this._newWindowMenuItem = this._appendMenuItem(_("New Window"));
|
||||
this._newWindowMenuItem.connect('activate', Lang.bind(this, function() {
|
||||
if (this._source.app.state == Shell.AppState.STOPPED)
|
||||
@ -1832,8 +1861,6 @@ const AppIconMenu = new Lang.Class({
|
||||
this._appendSeparator();
|
||||
}
|
||||
|
||||
let appInfo = this._source.app.get_app_info();
|
||||
let actions = appInfo.list_actions();
|
||||
for (let i = 0; i < actions.length; i++) {
|
||||
let action = actions[i];
|
||||
let item = this._appendMenuItem(appInfo.get_action_name(action));
|
||||
@ -1842,22 +1869,27 @@ const AppIconMenu = new Lang.Class({
|
||||
this.emit('activate-window', null);
|
||||
}));
|
||||
}
|
||||
this._appendSeparator();
|
||||
|
||||
let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id());
|
||||
let canFavorite = global.settings.is_writable('favorite-apps');
|
||||
|
||||
if (isFavorite) {
|
||||
let item = this._appendMenuItem(_("Remove from Favorites"));
|
||||
item.connect('activate', Lang.bind(this, function() {
|
||||
let favs = AppFavorites.getAppFavorites();
|
||||
favs.removeFavorite(this._source.app.get_id());
|
||||
}));
|
||||
} else {
|
||||
let item = this._appendMenuItem(_("Add to Favorites"));
|
||||
item.connect('activate', Lang.bind(this, function() {
|
||||
let favs = AppFavorites.getAppFavorites();
|
||||
favs.addFavorite(this._source.app.get_id());
|
||||
}));
|
||||
if (canFavorite) {
|
||||
this._appendSeparator();
|
||||
|
||||
let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id());
|
||||
|
||||
if (isFavorite) {
|
||||
let item = this._appendMenuItem(_("Remove from Favorites"));
|
||||
item.connect('activate', Lang.bind(this, function() {
|
||||
let favs = AppFavorites.getAppFavorites();
|
||||
favs.removeFavorite(this._source.app.get_id());
|
||||
}));
|
||||
} else {
|
||||
let item = this._appendMenuItem(_("Add to Favorites"));
|
||||
item.connect('activate', Lang.bind(this, function() {
|
||||
let favs = AppFavorites.getAppFavorites();
|
||||
favs.addFavorite(this._source.app.get_id());
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (Shell.AppSystem.get_default().lookup_app('org.gnome.Software.desktop')) {
|
||||
|
@ -144,6 +144,7 @@ const BackgroundCache = new Lang.Class({
|
||||
this._pendingFileLoads = [];
|
||||
this._fileMonitors = {};
|
||||
this._backgroundSources = {};
|
||||
this._animations = {};
|
||||
},
|
||||
|
||||
monitorFile: function(file) {
|
||||
@ -162,12 +163,13 @@ const BackgroundCache = new Lang.Class({
|
||||
|
||||
getAnimation: function(params) {
|
||||
params = Params.parse(params, { file: null,
|
||||
settingsSchema: null,
|
||||
onLoaded: null });
|
||||
|
||||
if (_fileEqual0(this._animationFile, params.file)) {
|
||||
if (this._animations[params.settingsSchema] && _fileEqual0(this._animationFile, params.file)) {
|
||||
if (params.onLoaded) {
|
||||
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
|
||||
params.onLoaded(this._animation);
|
||||
params.onLoaded(this._animations[params.settingsSchema]);
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
GLib.Source.set_name_by_id(id, '[gnome-shell] params.onLoaded');
|
||||
@ -178,12 +180,11 @@ const BackgroundCache = new Lang.Class({
|
||||
let animation = new Animation({ file: params.file });
|
||||
|
||||
animation.load(Lang.bind(this, function() {
|
||||
this._animationFile = params.file;
|
||||
this._animation = animation;
|
||||
this._animations[params.settingsSchema] = animation;
|
||||
|
||||
if (params.onLoaded) {
|
||||
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
|
||||
params.onLoaded(this._animation);
|
||||
params.onLoaded(this._animations[params.settingsSchema]);
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
GLib.Source.set_name_by_id(id, '[gnome-shell] params.onLoaded');
|
||||
@ -403,17 +404,18 @@ const Background = new Lang.Class({
|
||||
|
||||
_loadAnimation: function(file) {
|
||||
this._cache.getAnimation({ file: file,
|
||||
onLoaded: Lang.bind(this, function(animation) {
|
||||
this._animation = animation;
|
||||
settingsSchema: this._settings.schema_id,
|
||||
onLoaded: Lang.bind(this, function(animation) {
|
||||
this._animation = animation;
|
||||
|
||||
if (!this._animation || this._cancellable.is_cancelled()) {
|
||||
this._setLoaded();
|
||||
return;
|
||||
}
|
||||
if (!this._animation || this._cancellable.is_cancelled()) {
|
||||
this._setLoaded();
|
||||
return;
|
||||
}
|
||||
|
||||
this._updateAnimation();
|
||||
this._watchFile(file);
|
||||
})
|
||||
this._updateAnimation();
|
||||
this._watchFile(file);
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
@ -527,6 +529,10 @@ const BackgroundSource = new Lang.Class({
|
||||
let file = null;
|
||||
let style;
|
||||
|
||||
// We don't watch changes to settings here,
|
||||
// instead we rely on Background to watch those
|
||||
// and emit 'changed' at the right time
|
||||
|
||||
if (this._overrideImage != null) {
|
||||
file = Gio.File.new_for_path(this._overrideImage);
|
||||
style = GDesktopEnums.BackgroundStyle.ZOOM; // Hardcode
|
||||
|
@ -16,9 +16,10 @@ const BackgroundMenu = new Lang.Class({
|
||||
_init: function(layoutManager) {
|
||||
this.parent(layoutManager.dummyCursor, 0, St.Side.TOP);
|
||||
|
||||
this.addSettingsAction(_("Settings"), 'gnome-control-center.desktop');
|
||||
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this.addSettingsAction(_("Change Background…"), 'gnome-background-panel.desktop');
|
||||
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this.addSettingsAction(_("Display Settings"), 'gnome-display-panel.desktop');
|
||||
this.addSettingsAction(_("Settings"), 'gnome-control-center.desktop');
|
||||
|
||||
this.actor.add_style_class_name('background-menu');
|
||||
|
||||
|
1475
js/ui/calendar.js
@ -24,11 +24,11 @@ const AutorunSetting = {
|
||||
};
|
||||
|
||||
// misc utils
|
||||
function shouldAutorunMount(mount, forTransient) {
|
||||
function shouldAutorunMount(mount) {
|
||||
let root = mount.get_root();
|
||||
let volume = mount.get_volume();
|
||||
|
||||
if (!volume || (!volume.allowAutorun && forTransient))
|
||||
if (!volume || !volume.allowAutorun)
|
||||
return false;
|
||||
|
||||
if (root.is_native() && isMountRootHidden(root))
|
||||
@ -167,276 +167,38 @@ const AutorunManager = new Lang.Class({
|
||||
this._session = new GnomeSession.SessionManager();
|
||||
this._volumeMonitor = Gio.VolumeMonitor.get();
|
||||
|
||||
this._transDispatcher = new AutorunTransientDispatcher(this);
|
||||
},
|
||||
|
||||
_ensureResidentSource: function() {
|
||||
if (this._residentSource)
|
||||
return;
|
||||
|
||||
this._residentSource = new AutorunResidentSource(this);
|
||||
let destroyId = this._residentSource.connect('destroy', Lang.bind(this, function() {
|
||||
this._residentSource.disconnect(destroyId);
|
||||
this._residentSource = null;
|
||||
}));
|
||||
this._dispatcher = new AutorunDispatcher(this);
|
||||
},
|
||||
|
||||
enable: function() {
|
||||
this._scanMounts();
|
||||
|
||||
this._mountAddedId = this._volumeMonitor.connect('mount-added', Lang.bind(this, this._onMountAdded));
|
||||
this._mountRemovedId = this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._onMountRemoved));
|
||||
},
|
||||
|
||||
disable: function() {
|
||||
if (this._residentSource)
|
||||
this._residentSource.destroy();
|
||||
this._volumeMonitor.disconnect(this._mountAddedId);
|
||||
this._volumeMonitor.disconnect(this._mountRemovedId);
|
||||
},
|
||||
|
||||
_processMount: function(mount, hotplug) {
|
||||
let discoverer = new ContentTypeDiscoverer(Lang.bind(this, function(mount, apps, contentTypes) {
|
||||
this._ensureResidentSource();
|
||||
this._residentSource.addMount(mount, apps);
|
||||
|
||||
if (hotplug)
|
||||
this._transDispatcher.addMount(mount, apps, contentTypes);
|
||||
}));
|
||||
discoverer.guessContentTypes(mount);
|
||||
},
|
||||
|
||||
_scanMounts: function() {
|
||||
let mounts = this._volumeMonitor.get_mounts();
|
||||
mounts.forEach(Lang.bind(this, function(mount) {
|
||||
this._processMount(mount, false);
|
||||
}));
|
||||
},
|
||||
|
||||
_onMountAdded: function(monitor, mount) {
|
||||
// don't do anything if our session is not the currently
|
||||
// active one
|
||||
if (!this._session.SessionIsActive)
|
||||
return;
|
||||
|
||||
this._processMount(mount, true);
|
||||
let discoverer = new ContentTypeDiscoverer(Lang.bind(this, function(mount, apps, contentTypes) {
|
||||
this._dispatcher.addMount(mount, apps, contentTypes);
|
||||
}));
|
||||
discoverer.guessContentTypes(mount);
|
||||
},
|
||||
|
||||
_onMountRemoved: function(monitor, mount) {
|
||||
this._transDispatcher.removeMount(mount);
|
||||
if (this._residentSource)
|
||||
this._residentSource.removeMount(mount);
|
||||
},
|
||||
|
||||
ejectMount: function(mount) {
|
||||
let mountOp = new ShellMountOperation.ShellMountOperation(mount);
|
||||
|
||||
// first, see if we have a drive
|
||||
let drive = mount.get_drive();
|
||||
let volume = mount.get_volume();
|
||||
|
||||
if (drive &&
|
||||
drive.get_start_stop_type() == Gio.DriveStartStopType.SHUTDOWN &&
|
||||
drive.can_stop()) {
|
||||
drive.stop(0, mountOp.mountOp, null,
|
||||
Lang.bind(this, this._onStop));
|
||||
} else {
|
||||
if (mount.can_eject()) {
|
||||
mount.eject_with_operation(0, mountOp.mountOp, null,
|
||||
Lang.bind(this, this._onEject));
|
||||
} else if (volume && volume.can_eject()) {
|
||||
volume.eject_with_operation(0, mountOp.mountOp, null,
|
||||
Lang.bind(this, this._onEject));
|
||||
} else if (drive && drive.can_eject()) {
|
||||
drive.eject_with_operation(0, mountOp.mountOp, null,
|
||||
Lang.bind(this, this._onEject));
|
||||
} else if (mount.can_unmount()) {
|
||||
mount.unmount_with_operation(0, mountOp.mountOp, null,
|
||||
Lang.bind(this, this._onUnmount));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_onUnmount: function(mount, res) {
|
||||
try {
|
||||
mount.unmount_with_operation_finish(res);
|
||||
} catch (e) {
|
||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
|
||||
log('Unable to eject the mount ' + mount.get_name()
|
||||
+ ': ' + e.toString());
|
||||
}
|
||||
},
|
||||
|
||||
_onEject: function(source, res) {
|
||||
try {
|
||||
source.eject_with_operation_finish(res);
|
||||
} catch (e) {
|
||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
|
||||
log('Unable to eject the drive ' + source.get_name()
|
||||
+ ': ' + e.toString());
|
||||
}
|
||||
},
|
||||
|
||||
_onStop: function(drive, res) {
|
||||
try {
|
||||
drive.stop_finish(res);
|
||||
} catch (e) {
|
||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
|
||||
log('Unable to stop the drive ' + drive.get_name()
|
||||
+ ': ' + e.toString());
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const AutorunResidentSource = new Lang.Class({
|
||||
Name: 'AutorunResidentSource',
|
||||
Extends: MessageTray.Source,
|
||||
|
||||
_init: function(manager) {
|
||||
this.parent(_("Removable Devices"), 'media-removable');
|
||||
this.resident = true;
|
||||
|
||||
this._mounts = [];
|
||||
|
||||
this._manager = manager;
|
||||
this._notification = new AutorunResidentNotification(this._manager, this);
|
||||
},
|
||||
|
||||
_createPolicy: function() {
|
||||
return new MessageTray.NotificationPolicy({ showInLockScreen: false });
|
||||
},
|
||||
|
||||
buildRightClickMenu: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
addMount: function(mount, apps) {
|
||||
if (!shouldAutorunMount(mount, false))
|
||||
return;
|
||||
|
||||
let filtered = this._mounts.filter(function (element) {
|
||||
return (element.mount == mount);
|
||||
});
|
||||
|
||||
if (filtered.length != 0)
|
||||
return;
|
||||
|
||||
let element = { mount: mount, apps: apps };
|
||||
this._mounts.push(element);
|
||||
this._redisplay();
|
||||
},
|
||||
|
||||
removeMount: function(mount) {
|
||||
this._mounts =
|
||||
this._mounts.filter(function (element) {
|
||||
return (element.mount != mount);
|
||||
});
|
||||
|
||||
this._redisplay();
|
||||
},
|
||||
|
||||
_redisplay: function() {
|
||||
if (this._mounts.length == 0) {
|
||||
this._notification.destroy();
|
||||
this.destroy();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this._notification.updateForMounts(this._mounts);
|
||||
|
||||
// add ourselves as a source, and push the notification
|
||||
if (!Main.messageTray.contains(this)) {
|
||||
Main.messageTray.add(this);
|
||||
this.pushNotification(this._notification);
|
||||
}
|
||||
this._dispatcher.removeMount(mount);
|
||||
}
|
||||
});
|
||||
|
||||
const AutorunResidentNotification = new Lang.Class({
|
||||
Name: 'AutorunResidentNotification',
|
||||
Extends: MessageTray.Notification,
|
||||
|
||||
_init: function(manager, source) {
|
||||
this.parent(source, source.title, null, { customContent: true });
|
||||
|
||||
// set the notification as resident
|
||||
this.setResident(true);
|
||||
|
||||
this._layout = new St.BoxLayout ({ style_class: 'hotplug-resident-box',
|
||||
vertical: true });
|
||||
this._manager = manager;
|
||||
|
||||
this.addActor(this._layout,
|
||||
{ x_expand: true,
|
||||
x_fill: true });
|
||||
},
|
||||
|
||||
updateForMounts: function(mounts) {
|
||||
// remove all the layout content
|
||||
this._layout.destroy_all_children();
|
||||
|
||||
for (let idx = 0; idx < mounts.length; idx++) {
|
||||
let element = mounts[idx];
|
||||
|
||||
let actor = this._itemForMount(element.mount, element.apps);
|
||||
this._layout.add(actor, { x_fill: true,
|
||||
expand: true });
|
||||
}
|
||||
},
|
||||
|
||||
_itemForMount: function(mount, apps) {
|
||||
let item = new St.BoxLayout();
|
||||
|
||||
// prepare the mount button content
|
||||
let mountLayout = new St.BoxLayout();
|
||||
|
||||
let mountIcon = new St.Icon({ gicon: mount.get_icon(),
|
||||
style_class: 'hotplug-resident-mount-icon' });
|
||||
mountLayout.add_actor(mountIcon);
|
||||
|
||||
let labelBin = new St.Bin({ y_align: St.Align.MIDDLE });
|
||||
let mountLabel =
|
||||
new St.Label({ text: mount.get_name(),
|
||||
style_class: 'hotplug-resident-mount-label',
|
||||
track_hover: true,
|
||||
reactive: true });
|
||||
labelBin.add_actor(mountLabel);
|
||||
mountLayout.add_actor(labelBin);
|
||||
|
||||
let mountButton = new St.Button({ child: mountLayout,
|
||||
x_align: St.Align.START,
|
||||
x_fill: true,
|
||||
style_class: 'hotplug-resident-mount',
|
||||
button_mask: St.ButtonMask.ONE });
|
||||
item.add(mountButton, { x_align: St.Align.START,
|
||||
expand: true });
|
||||
|
||||
let ejectIcon =
|
||||
new St.Icon({ icon_name: 'media-eject-symbolic',
|
||||
style_class: 'hotplug-resident-eject-icon' });
|
||||
|
||||
let ejectButton =
|
||||
new St.Button({ style_class: 'hotplug-resident-eject-button',
|
||||
button_mask: St.ButtonMask.ONE,
|
||||
child: ejectIcon });
|
||||
item.add(ejectButton, { x_align: St.Align.END });
|
||||
|
||||
// now connect signals
|
||||
mountButton.connect('clicked', Lang.bind(this, function(actor, event) {
|
||||
startAppForMount(apps[0], mount);
|
||||
}));
|
||||
|
||||
ejectButton.connect('clicked', Lang.bind(this, function() {
|
||||
this._manager.ejectMount(mount);
|
||||
}));
|
||||
|
||||
return item;
|
||||
},
|
||||
});
|
||||
|
||||
const AutorunTransientDispatcher = new Lang.Class({
|
||||
Name: 'AutorunTransientDispatcher',
|
||||
const AutorunDispatcher = new Lang.Class({
|
||||
Name: 'AutorunDispatcher',
|
||||
|
||||
_init: function(manager) {
|
||||
this._manager = manager;
|
||||
@ -482,7 +244,7 @@ const AutorunTransientDispatcher = new Lang.Class({
|
||||
return;
|
||||
|
||||
// add a new source
|
||||
this._sources.push(new AutorunTransientSource(this._manager, mount, apps));
|
||||
this._sources.push(new AutorunSource(this._manager, mount, apps));
|
||||
},
|
||||
|
||||
addMount: function(mount, apps, contentTypes) {
|
||||
@ -491,7 +253,7 @@ const AutorunTransientDispatcher = new Lang.Class({
|
||||
return;
|
||||
|
||||
// if the mount doesn't want to be autorun, return
|
||||
if (!shouldAutorunMount(mount, true))
|
||||
if (!shouldAutorunMount(mount))
|
||||
return;
|
||||
|
||||
let setting = this._getAutorunSettingForType(contentTypes[0]);
|
||||
@ -531,8 +293,8 @@ const AutorunTransientDispatcher = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
const AutorunTransientSource = new Lang.Class({
|
||||
Name: 'AutorunTransientSource',
|
||||
const AutorunSource = new Lang.Class({
|
||||
Name: 'AutorunSource',
|
||||
Extends: MessageTray.Source,
|
||||
|
||||
_init: function(manager, mount, apps) {
|
||||
@ -542,7 +304,7 @@ const AutorunTransientSource = new Lang.Class({
|
||||
|
||||
this.parent(mount.get_name());
|
||||
|
||||
this._notification = new AutorunTransientNotification(this._manager, this);
|
||||
this._notification = new AutorunNotification(this._manager, this);
|
||||
|
||||
// add ourselves as a source, and popup the notification
|
||||
Main.messageTray.add(this);
|
||||
@ -554,35 +316,31 @@ const AutorunTransientSource = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
const AutorunTransientNotification = new Lang.Class({
|
||||
Name: 'AutorunTransientNotification',
|
||||
const AutorunNotification = new Lang.Class({
|
||||
Name: 'AutorunNotification',
|
||||
Extends: MessageTray.Notification,
|
||||
|
||||
_init: function(manager, source) {
|
||||
this.parent(source, source.title, null, { customContent: true });
|
||||
this.parent(source, source.title);
|
||||
|
||||
this._manager = manager;
|
||||
this._box = new St.BoxLayout({ style_class: 'hotplug-transient-box',
|
||||
vertical: true });
|
||||
this.addActor(this._box);
|
||||
|
||||
this._mount = source.mount;
|
||||
|
||||
source.apps.forEach(Lang.bind(this, function (app) {
|
||||
// set the notification to urgent, so that it expands out
|
||||
this.setUrgency(MessageTray.Urgency.CRITICAL);
|
||||
},
|
||||
|
||||
createBanner: function() {
|
||||
let banner = new MessageTray.NotificationBanner(this);
|
||||
|
||||
this.source.apps.forEach(Lang.bind(this, function (app) {
|
||||
let actor = this._buttonForApp(app);
|
||||
|
||||
if (actor)
|
||||
this._box.add(actor, { x_fill: true,
|
||||
x_align: St.Align.START });
|
||||
banner.addButton(actor);
|
||||
}));
|
||||
|
||||
this._box.add(this._buttonForEject(), { x_fill: true,
|
||||
x_align: St.Align.START });
|
||||
|
||||
// set the notification to transient and urgent, so that it
|
||||
// expands out
|
||||
this.setTransient(true);
|
||||
this.setUrgency(MessageTray.Urgency.CRITICAL);
|
||||
return banner;
|
||||
},
|
||||
|
||||
_buttonForApp: function(app) {
|
||||
@ -600,8 +358,9 @@ const AutorunTransientNotification = new Lang.Class({
|
||||
let button = new St.Button({ child: box,
|
||||
x_fill: true,
|
||||
x_align: St.Align.START,
|
||||
x_expand: true,
|
||||
button_mask: St.ButtonMask.ONE,
|
||||
style_class: 'hotplug-notification-item' });
|
||||
style_class: 'hotplug-notification-item button' });
|
||||
|
||||
button.connect('clicked', Lang.bind(this, function() {
|
||||
startAppForMount(app, this._mount);
|
||||
@ -611,29 +370,11 @@ const AutorunTransientNotification = new Lang.Class({
|
||||
return button;
|
||||
},
|
||||
|
||||
_buttonForEject: function() {
|
||||
let box = new St.BoxLayout();
|
||||
let icon = new St.Icon({ icon_name: 'media-eject-symbolic',
|
||||
style_class: 'hotplug-notification-item-icon' });
|
||||
box.add(icon);
|
||||
activate: function() {
|
||||
this.parent();
|
||||
|
||||
let label = new St.Bin({ y_align: St.Align.MIDDLE,
|
||||
child: new St.Label
|
||||
({ text: _("Eject") })
|
||||
});
|
||||
box.add(label);
|
||||
|
||||
let button = new St.Button({ child: box,
|
||||
x_fill: true,
|
||||
x_align: St.Align.START,
|
||||
button_mask: St.ButtonMask.ONE,
|
||||
style_class: 'hotplug-notification-item' });
|
||||
|
||||
button.connect('clicked', Lang.bind(this, function() {
|
||||
this._manager.ejectMount(this._mount);
|
||||
}));
|
||||
|
||||
return button;
|
||||
let app = Gio.app_info_get_default_for_type('inode/directory', false);
|
||||
startAppForMount(app, this._mount);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -9,9 +9,15 @@ const Gio = imports.gi.Gio;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gcr = imports.gi.Gcr;
|
||||
|
||||
const Animation = imports.ui.animation;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
const CheckBox = imports.ui.checkBox;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const WORK_SPINNER_ICON_SIZE = 16;
|
||||
const WORK_SPINNER_ANIMATION_DELAY = 1.0;
|
||||
const WORK_SPINNER_ANIMATION_TIME = 0.3;
|
||||
|
||||
const KeyringDialog = new Lang.Class({
|
||||
Name: 'KeyringDialog',
|
||||
@ -41,7 +47,7 @@ const KeyringDialog = new Lang.Class({
|
||||
mainContentBox.add(this._messageBox,
|
||||
{ y_align: St.Align.START, expand: true, x_fill: true, y_fill: true });
|
||||
|
||||
let subject = new St.Label({ style_class: 'prompt-dialog-headline' });
|
||||
let subject = new St.Label({ style_class: 'prompt-dialog-headline headline' });
|
||||
this.prompt.bind_property('message', subject, 'text', GObject.BindingFlags.SYNC_CREATE);
|
||||
|
||||
this._messageBox.add(subject,
|
||||
@ -58,27 +64,47 @@ const KeyringDialog = new Lang.Class({
|
||||
{ y_fill: true,
|
||||
y_align: St.Align.START });
|
||||
|
||||
this._workSpinner = null;
|
||||
this._controlTable = null;
|
||||
|
||||
|
||||
this._cancelButton = this.addButton({ label: '',
|
||||
action: Lang.bind(this, this._onCancelButton),
|
||||
key: Clutter.Escape },
|
||||
{ expand: true, x_fill: false, x_align: St.Align.START });
|
||||
this.placeSpinner({ expand: false,
|
||||
x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.MIDDLE });
|
||||
key: Clutter.Escape });
|
||||
this._continueButton = this.addButton({ label: '',
|
||||
action: Lang.bind(this, this._onContinueButton),
|
||||
default: true },
|
||||
{ expand: false, x_fill: false, x_align: St.Align.END });
|
||||
default: true });
|
||||
|
||||
this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE);
|
||||
this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE);
|
||||
},
|
||||
|
||||
_setWorking: function(working) {
|
||||
if (!this._workSpinner)
|
||||
return;
|
||||
|
||||
Tweener.removeTweens(this._workSpinner.actor);
|
||||
if (working) {
|
||||
this._workSpinner.play();
|
||||
Tweener.addTween(this._workSpinner.actor,
|
||||
{ opacity: 255,
|
||||
delay: WORK_SPINNER_ANIMATION_DELAY,
|
||||
time: WORK_SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear'
|
||||
});
|
||||
} else {
|
||||
Tweener.addTween(this._workSpinner.actor,
|
||||
{ opacity: 0,
|
||||
time: WORK_SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear',
|
||||
onCompleteScope: this,
|
||||
onComplete: function() {
|
||||
if (this._workSpinner)
|
||||
this._workSpinner.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_buildControlTable: function() {
|
||||
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
|
||||
let table = new St.Widget({ style_class: 'keyring-dialog-control-table',
|
||||
@ -101,15 +127,22 @@ const KeyringDialog = new Lang.Class({
|
||||
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
|
||||
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onPasswordActivate));
|
||||
|
||||
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
|
||||
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
|
||||
this._workSpinner.actor.opacity = 0;
|
||||
|
||||
if (rtl) {
|
||||
layout.attach(this._passwordEntry, 0, row, 1, 1);
|
||||
layout.attach(label, 1, row, 1, 1);
|
||||
layout.attach(this._workSpinner.actor, 0, row, 1, 1);
|
||||
layout.attach(this._passwordEntry, 1, row, 1, 1);
|
||||
layout.attach(label, 2, row, 1, 1);
|
||||
} else {
|
||||
layout.attach(label, 0, row, 1, 1);
|
||||
layout.attach(this._passwordEntry, 1, row, 1, 1);
|
||||
layout.attach(this._workSpinner.actor, 2, row, 1, 1);
|
||||
}
|
||||
row++;
|
||||
} else {
|
||||
this._workSpinner = null;
|
||||
this._passwordEntry = null;
|
||||
}
|
||||
|
||||
@ -178,7 +211,7 @@ const KeyringDialog = new Lang.Class({
|
||||
|
||||
this._continueButton.can_focus = sensitive;
|
||||
this._continueButton.reactive = sensitive;
|
||||
this.setWorking(!sensitive);
|
||||
this._setWorking(!sensitive);
|
||||
},
|
||||
|
||||
_ensureOpen: function() {
|
||||
|
@ -12,6 +12,8 @@ const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Config = imports.misc.config;
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
@ -54,7 +56,7 @@ const NetworkSecretDialog = new Lang.Class({
|
||||
mainContentBox.add(messageBox,
|
||||
{ y_align: St.Align.START });
|
||||
|
||||
let subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline',
|
||||
let subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline headline',
|
||||
text: this._content.title });
|
||||
messageBox.add(subjectLabel,
|
||||
{ y_fill: false,
|
||||
@ -338,6 +340,7 @@ const NetworkSecretDialog = new Lang.Class({
|
||||
content.message = _("PIN code is needed for the mobile broadband device");
|
||||
content.secrets.push({ label: _("PIN: "), key: 'pin',
|
||||
value: gsmSetting.pin || '', password: true });
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
case 'cdma':
|
||||
@ -610,6 +613,7 @@ const NetworkAgent = new Lang.Class({
|
||||
|
||||
this._dialogs = { };
|
||||
this._vpnRequests = { };
|
||||
this._notifications = { };
|
||||
|
||||
this._native.connect('new-request', Lang.bind(this, this._newRequest));
|
||||
this._native.connect('cancel-request', Lang.bind(this, this._cancelRequest));
|
||||
@ -632,21 +636,92 @@ const NetworkAgent = new Lang.Class({
|
||||
this._vpnRequests[requestId].cancel(true);
|
||||
this._vpnRequests = { };
|
||||
|
||||
for (requestId in this._notifications)
|
||||
this._notifications[requestId].destroy();
|
||||
this._notifications = { };
|
||||
|
||||
this._enabled = false;
|
||||
},
|
||||
|
||||
_showNotification: function(requestId, connection, settingName, hints, flags) {
|
||||
let source = new MessageTray.Source(_("Network Manager"), 'network-transmit-receive');
|
||||
source.policy = new MessageTray.NotificationApplicationPolicy('gnome-network-panel');
|
||||
|
||||
let title, body;
|
||||
|
||||
let connectionSetting = connection.get_setting_connection();
|
||||
let connectionType = connectionSetting.get_connection_type();
|
||||
switch (connectionType) {
|
||||
case '802-11-wireless':
|
||||
let wirelessSetting = connection.get_setting_wireless();
|
||||
let ssid = NetworkManager.utils_ssid_to_utf8(wirelessSetting.get_ssid());
|
||||
title = _("Authentication required by wireless network");
|
||||
body = _("Passwords or encryption keys are required to access the wireless network “%s”.").format(ssid);
|
||||
break;
|
||||
case '802-3-ethernet':
|
||||
title = _("Wired 802.1X authentication");
|
||||
body = _("A password is required to connect to “%s”.".format(connection.get_id()));
|
||||
break;
|
||||
case 'pppoe':
|
||||
title = _("DSL authentication");
|
||||
body = _("A password is required to connect to “%s”.".format(connection.get_id()));
|
||||
break;
|
||||
case 'gsm':
|
||||
if (hints.indexOf('pin') != -1) {
|
||||
let gsmSetting = connection.get_setting_gsm();
|
||||
title = _("PIN code required");
|
||||
message = _("PIN code is needed for the mobile broadband device");
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
case 'cdma':
|
||||
case 'bluetooth':
|
||||
title = _("Mobile broadband network password");
|
||||
message = _("A password is required to connect to “%s”.").format(connectionSetting.get_id());
|
||||
break;
|
||||
default:
|
||||
log('Invalid connection type: ' + connectionType);
|
||||
this._native.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
let notification = new MessageTray.Notification(source, title, body);
|
||||
|
||||
notification.connect('activated', Lang.bind(this, function() {
|
||||
notification.answered = true;
|
||||
this._handleRequest(requestId, connection, settingName, hints, flags);
|
||||
}));
|
||||
|
||||
this._notifications[requestId] = notification;
|
||||
notification.connect('destroy', Lang.bind(this, function() {
|
||||
if (!notification.answered)
|
||||
this._native.respond(requestId, Shell.NetworkAgentResponse.USER_CANCELED);
|
||||
delete this._notifications[requestId];
|
||||
}));
|
||||
|
||||
Main.messageTray.add(source);
|
||||
source.notify(notification);
|
||||
},
|
||||
|
||||
_newRequest: function(agent, requestId, connection, settingName, hints, flags) {
|
||||
if (!this._enabled) {
|
||||
agent.respond(requestId, Shell.NetworkAgentResponse.USER_CANCELED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(flags & NMClient.SecretAgentGetSecretsFlags.USER_REQUESTED))
|
||||
this._showNotification(requestId, connection, settingName, hints, flags);
|
||||
else
|
||||
this._handleRequest(requestId, connection, settingName, hints, flags);
|
||||
},
|
||||
|
||||
_handleRequest: function(requestId, connection, settingName, hints, flags) {
|
||||
if (settingName == 'vpn') {
|
||||
this._vpnRequest(requestId, connection, hints, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
let dialog = new NetworkSecretDialog(agent, requestId, connection, settingName, hints);
|
||||
let dialog = new NetworkSecretDialog(this._native, requestId, connection, settingName, hints);
|
||||
dialog.connect('destroy', Lang.bind(this, function() {
|
||||
delete this._dialogs[requestId];
|
||||
}));
|
||||
|
@ -13,13 +13,19 @@ const Mainloop = imports.mainloop;
|
||||
const Polkit = imports.gi.Polkit;
|
||||
const PolkitAgent = imports.gi.PolkitAgent;
|
||||
|
||||
const Animation = imports.ui.animation;
|
||||
const Components = imports.ui.components;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
const UserWidget = imports.ui.userWidget;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const DIALOG_ICON_SIZE = 48;
|
||||
|
||||
const WORK_SPINNER_ICON_SIZE = 16;
|
||||
const WORK_SPINNER_ANIMATION_DELAY = 1.0;
|
||||
const WORK_SPINNER_ANIMATION_TIME = 0.3;
|
||||
|
||||
const AuthenticationDialog = new Lang.Class({
|
||||
Name: 'AuthenticationDialog',
|
||||
Extends: ModalDialog.ModalDialog,
|
||||
@ -50,7 +56,7 @@ const AuthenticationDialog = new Lang.Class({
|
||||
mainContentBox.add(messageBox,
|
||||
{ expand: true, y_align: St.Align.START });
|
||||
|
||||
this._subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline',
|
||||
this._subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline headline',
|
||||
text: _("Authentication Required") });
|
||||
|
||||
messageBox.add(this._subjectLabel,
|
||||
@ -136,6 +142,13 @@ const AuthenticationDialog = new Lang.Class({
|
||||
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivate));
|
||||
this._passwordBox.add(this._passwordEntry,
|
||||
{ expand: true });
|
||||
|
||||
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
|
||||
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
|
||||
this._workSpinner.actor.opacity = 0;
|
||||
|
||||
this._passwordBox.add(this._workSpinner.actor);
|
||||
|
||||
this.setInitialKeyFocus(this._passwordEntry);
|
||||
this._passwordBox.hide();
|
||||
|
||||
@ -165,17 +178,10 @@ const AuthenticationDialog = new Lang.Class({
|
||||
|
||||
this._cancelButton = this.addButton({ label: _("Cancel"),
|
||||
action: Lang.bind(this, this.cancel),
|
||||
key: Clutter.Escape },
|
||||
{ expand: true, x_fill: false, x_align: St.Align.START });
|
||||
this.placeSpinner({ expand: false,
|
||||
x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.MIDDLE });
|
||||
key: Clutter.Escape });
|
||||
this._okButton = this.addButton({ label: _("Authenticate"),
|
||||
action: Lang.bind(this, this._onAuthenticateButtonPressed),
|
||||
default: true },
|
||||
{ expand: false, x_fill: false, x_align: St.Align.END });
|
||||
default: true });
|
||||
|
||||
this._doneEmitted = false;
|
||||
|
||||
@ -183,6 +189,30 @@ const AuthenticationDialog = new Lang.Class({
|
||||
this._cookie = cookie;
|
||||
},
|
||||
|
||||
_setWorking: function(working) {
|
||||
Tweener.removeTweens(this._workSpinner.actor);
|
||||
if (working) {
|
||||
this._workSpinner.play();
|
||||
Tweener.addTween(this._workSpinner.actor,
|
||||
{ opacity: 255,
|
||||
delay: WORK_SPINNER_ANIMATION_DELAY,
|
||||
time: WORK_SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear'
|
||||
});
|
||||
} else {
|
||||
Tweener.addTween(this._workSpinner.actor,
|
||||
{ opacity: 0,
|
||||
time: WORK_SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear',
|
||||
onCompleteScope: this,
|
||||
onComplete: function() {
|
||||
if (this._workSpinner)
|
||||
this._workSpinner.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
performAuthentication: function() {
|
||||
this.destroySession();
|
||||
this._session = new PolkitAgent.Session({ identity: this._identityToAuth,
|
||||
@ -229,7 +259,7 @@ const AuthenticationDialog = new Lang.Class({
|
||||
|
||||
this._okButton.can_focus = sensitive;
|
||||
this._okButton.reactive = sensitive;
|
||||
this.setWorking(!sensitive);
|
||||
this._setWorking(!sensitive);
|
||||
},
|
||||
|
||||
_onEntryActivate: function() {
|
||||
|
@ -27,8 +27,8 @@ const CtrlAltTabManager = new Lang.Class({
|
||||
_init: function() {
|
||||
this._items = [];
|
||||
this.addGroup(global.window_group, _("Windows"),
|
||||
'emblem-documents-symbolic', { sortGroup: SortGroup.TOP,
|
||||
focusCallback: Lang.bind(this, this._focusWindows) });
|
||||
'focus-windows-symbolic', { sortGroup: SortGroup.TOP,
|
||||
focusCallback: Lang.bind(this, this._focusWindows) });
|
||||
},
|
||||
|
||||
addGroup: function(root, name, icon, params) {
|
||||
@ -100,7 +100,7 @@ const CtrlAltTabManager = new Lang.Class({
|
||||
if (app)
|
||||
icon = app.create_icon_texture(POPUP_APPICON_SIZE);
|
||||
else
|
||||
icon = textureCache.bind_pixbuf_property(windows[i], 'icon');
|
||||
icon = textureCache.bind_cairo_surface_property(windows[i], 'icon');
|
||||
}
|
||||
|
||||
items.push({ name: windows[i].title,
|
||||
|
@ -1,6 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Signals = imports.signals;
|
||||
const Lang = imports.lang;
|
||||
@ -269,6 +270,9 @@ const ShowAppsIcon = new Lang.Class({
|
||||
if (app == null)
|
||||
return false;
|
||||
|
||||
if (!global.settings.is_writable('favorite-apps'))
|
||||
return false;
|
||||
|
||||
let id = app.get_id();
|
||||
let isFavorite = AppFavorites.getAppFavorites().isFavorite(id);
|
||||
return isFavorite;
|
||||
@ -513,10 +517,13 @@ const Dash = new Lang.Class({
|
||||
this._syncLabel(item, appIcon);
|
||||
}));
|
||||
|
||||
Main.overview.connect('hiding', Lang.bind(this, function() {
|
||||
let id = Main.overview.connect('hiding', Lang.bind(this, function() {
|
||||
this._labelShowing = false;
|
||||
item.hideLabel();
|
||||
}));
|
||||
item.child.connect('destroy', function() {
|
||||
Main.overview.disconnect(id);
|
||||
});
|
||||
|
||||
if (appIcon) {
|
||||
appIcon.connect('sync-tooltip', Lang.bind(this, function() {
|
||||
@ -529,14 +536,17 @@ const Dash = new Lang.Class({
|
||||
let appIcon = new AppDisplay.AppIcon(app,
|
||||
{ setSizeManually: true,
|
||||
showLabel: false });
|
||||
appIcon._draggable.connect('drag-begin',
|
||||
Lang.bind(this, function() {
|
||||
appIcon.actor.opacity = 50;
|
||||
}));
|
||||
appIcon._draggable.connect('drag-end',
|
||||
Lang.bind(this, function() {
|
||||
appIcon.actor.opacity = 255;
|
||||
}));
|
||||
if (appIcon._draggable) {
|
||||
appIcon._draggable.connect('drag-begin',
|
||||
Lang.bind(this, function() {
|
||||
appIcon.actor.opacity = 50;
|
||||
}));
|
||||
appIcon._draggable.connect('drag-end',
|
||||
Lang.bind(this, function() {
|
||||
appIcon.actor.opacity = 255;
|
||||
}));
|
||||
}
|
||||
|
||||
appIcon.connect('menu-state-changed',
|
||||
Lang.bind(this, function(appIcon, opened) {
|
||||
this._itemMenuStateChanged(item, opened);
|
||||
@ -850,6 +860,9 @@ const Dash = new Lang.Class({
|
||||
if (app == null || app.is_window_backed())
|
||||
return DND.DragMotionResult.NO_DROP;
|
||||
|
||||
if (!global.settings.is_writable('favorite-apps'))
|
||||
return DND.DragMotionResult.NO_DROP;
|
||||
|
||||
let favorites = AppFavorites.getAppFavorites().getFavorites();
|
||||
let numFavorites = favorites.length;
|
||||
|
||||
@ -926,6 +939,9 @@ const Dash = new Lang.Class({
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!global.settings.is_writable('favorite-apps'))
|
||||
return false;
|
||||
|
||||
let id = app.get_id();
|
||||
|
||||
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
|
||||
|
@ -4,6 +4,8 @@ const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GnomeDesktop = imports.gi.GnomeDesktop;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const GWeather = imports.gi.GWeather;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Cairo = imports.cairo;
|
||||
@ -19,24 +21,293 @@ const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Calendar = imports.ui.calendar;
|
||||
|
||||
const N_ = function(s) { return s; };
|
||||
|
||||
function _onVertSepRepaint(area) {
|
||||
let cr = area.get_context();
|
||||
let themeNode = area.get_theme_node();
|
||||
let [width, height] = area.get_surface_size();
|
||||
let stippleColor = themeNode.get_color('-stipple-color');
|
||||
let stippleWidth = themeNode.get_length('-stipple-width');
|
||||
let x = Math.floor(width/2) + 0.5;
|
||||
cr.moveTo(x, 0);
|
||||
cr.lineTo(x, height);
|
||||
Clutter.cairo_set_source_color(cr, stippleColor);
|
||||
cr.setDash([1, 3], 1); // Hard-code for now
|
||||
cr.setLineWidth(stippleWidth);
|
||||
cr.stroke();
|
||||
cr.$dispose();
|
||||
function _isToday(date) {
|
||||
let now = new Date();
|
||||
return now.getYear() == date.getYear() &&
|
||||
now.getMonth() == date.getMonth() &&
|
||||
now.getDate() == date.getDate();
|
||||
}
|
||||
|
||||
const TodayButton = new Lang.Class({
|
||||
Name: 'TodayButton',
|
||||
|
||||
_init: function(calendar) {
|
||||
// Having the ability to go to the current date if the user is already
|
||||
// on the current date can be confusing. So don't make the button reactive
|
||||
// until the selected date changes.
|
||||
this.actor = new St.Button({ style_class: 'datemenu-today-button',
|
||||
x_align: St.Align.START,
|
||||
can_focus: true,
|
||||
reactive: false
|
||||
});
|
||||
this.actor.connect('clicked', Lang.bind(this,
|
||||
function() {
|
||||
this._calendar.setDate(new Date(), false);
|
||||
}));
|
||||
|
||||
let hbox = new St.BoxLayout({ vertical: true });
|
||||
this.actor.add_actor(hbox);
|
||||
|
||||
this._dayLabel = new St.Label({ style_class: 'day-label',
|
||||
x_align: Clutter.ActorAlign.START });
|
||||
hbox.add_actor(this._dayLabel);
|
||||
|
||||
this._dateLabel = new St.Label({ style_class: 'date-label' });
|
||||
hbox.add_actor(this._dateLabel);
|
||||
|
||||
this._calendar = calendar;
|
||||
this._calendar.connect('selected-date-changed', Lang.bind(this,
|
||||
function(calendar, date) {
|
||||
// Make the button reactive only if the selected date is not the
|
||||
// current date.
|
||||
this.actor.reactive = !_isToday(date)
|
||||
}));
|
||||
},
|
||||
|
||||
setDate: function(date) {
|
||||
this._dayLabel.set_text(date.toLocaleFormat('%A'));
|
||||
|
||||
/* Translators: This is the date format to use when the calendar popup is
|
||||
* shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
|
||||
*/
|
||||
let dateFormat = Shell.util_translate_time_string (N_("%B %e %Y"));
|
||||
this._dateLabel.set_text(date.toLocaleFormat(dateFormat));
|
||||
|
||||
/* Translators: This is the accessible name of the date button shown
|
||||
* below the time in the shell; it should combine the weekday and the
|
||||
* date, e.g. "Tuesday February 17 2015".
|
||||
*/
|
||||
let dateFormat = Shell.util_translate_time_string (N_("%A %B %e %Y"));
|
||||
this.actor.accessible_name = date.toLocaleFormat(dateFormat);
|
||||
}
|
||||
});
|
||||
|
||||
const WorldClocksSection = new Lang.Class({
|
||||
Name: 'WorldClocksSection',
|
||||
|
||||
_init: function() {
|
||||
this._clock = new GnomeDesktop.WallClock();
|
||||
this._settings = null;
|
||||
this._clockNotifyId = 0;
|
||||
this._changedId = 0;
|
||||
|
||||
this._locations = [];
|
||||
|
||||
this.actor = new St.Button({ style_class: 'world-clocks-button',
|
||||
x_fill: true,
|
||||
can_focus: true });
|
||||
this.actor.connect('clicked', Lang.bind(this,
|
||||
function() {
|
||||
let app = this._getClockApp();
|
||||
app.activate();
|
||||
|
||||
Main.overview.hide();
|
||||
Main.panel.closeCalendar();
|
||||
}));
|
||||
|
||||
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
|
||||
this._grid = new St.Widget({ style_class: 'world-clocks-grid',
|
||||
layout_manager: layout });
|
||||
layout.hookup_style(this._grid);
|
||||
|
||||
this.actor.child = this._grid;
|
||||
|
||||
Shell.AppSystem.get_default().connect('installed-changed',
|
||||
Lang.bind(this, this._sync));
|
||||
this._sync();
|
||||
},
|
||||
|
||||
_getClockApp: function() {
|
||||
return Shell.AppSystem.get_default().lookup_app('org.gnome.clocks.desktop');
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
this.actor.visible = (this._getClockApp() != null);
|
||||
|
||||
if (this.actor.visible) {
|
||||
if (!this._settings) {
|
||||
this._settings = new Gio.Settings({ schema_id: 'org.gnome.clocks' });
|
||||
this._changedId =
|
||||
this._settings.connect('changed::world-clocks',
|
||||
Lang.bind(this, this._clocksChanged));
|
||||
this._clocksChanged();
|
||||
}
|
||||
} else {
|
||||
if (this._settings)
|
||||
this._settings.disconnect(this._changedId);
|
||||
this._settings = null;
|
||||
this._changedId = 0;
|
||||
}
|
||||
},
|
||||
|
||||
_clocksChanged: function() {
|
||||
this._grid.destroy_all_children();
|
||||
this._locations = [];
|
||||
|
||||
let world = GWeather.Location.get_world();
|
||||
let clocks = this._settings.get_value('world-clocks').deep_unpack();
|
||||
for (let i = 0; i < clocks.length; i++) {
|
||||
let l = world.deserialize(clocks[i].location);
|
||||
this._locations.push({ location: l });
|
||||
}
|
||||
|
||||
this._locations.sort(function(a, b) {
|
||||
return a.location.get_timezone().get_offset() -
|
||||
b.location.get_timezone().get_offset();
|
||||
});
|
||||
|
||||
let layout = this._grid.layout_manager;
|
||||
let title = (this._locations.length == 0) ? _("Add world clocks…")
|
||||
: _("World Clocks");
|
||||
let header = new St.Label({ style_class: 'world-clocks-header',
|
||||
x_align: Clutter.ActorAlign.START,
|
||||
text: title });
|
||||
layout.attach(header, 0, 0, 2, 1);
|
||||
this.actor.label_actor = header;
|
||||
|
||||
for (let i = 0; i < this._locations.length; i++) {
|
||||
let l = this._locations[i].location;
|
||||
|
||||
let label = new St.Label({ style_class: 'world-clocks-city',
|
||||
text: l.get_city_name(),
|
||||
x_align: Clutter.ActorAlign.START,
|
||||
x_expand: true });
|
||||
|
||||
let time = new St.Label({ style_class: 'world-clocks-time',
|
||||
x_align: Clutter.ActorAlign.END,
|
||||
x_expand: true });
|
||||
|
||||
if (this._grid.text_direction == Clutter.TextDirection.RTL) {
|
||||
layout.attach(time, 0, i + 1, 1, 1);
|
||||
layout.attach(label, 1, i + 1, 1, 1);
|
||||
} else {
|
||||
layout.attach(label, 0, i + 1, 1, 1);
|
||||
layout.attach(time, 1, i + 1, 1, 1);
|
||||
}
|
||||
|
||||
this._locations[i].actor = time;
|
||||
}
|
||||
|
||||
if (this._grid.get_n_children() > 1) {
|
||||
if (!this._clockNotifyId)
|
||||
this._clockNotifyId =
|
||||
this._clock.connect('notify::clock', Lang.bind(this, this._updateLabels));
|
||||
this._updateLabels();
|
||||
} else {
|
||||
if (this._clockNotifyId)
|
||||
this._clock.disconnect(this._clockNotifyId);
|
||||
this._clockNotifyId = 0;
|
||||
}
|
||||
},
|
||||
|
||||
_updateLabels: function() {
|
||||
for (let i = 0; i < this._locations.length; i++) {
|
||||
let l = this._locations[i];
|
||||
let tz = GLib.TimeZone.new(l.location.get_timezone().get_tzid());
|
||||
let now = GLib.DateTime.new_now(tz);
|
||||
l.actor.text = Util.formatTime(now, { timeOnly: true });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const MessagesIndicator = new Lang.Class({
|
||||
Name: 'MessagesIndicator',
|
||||
|
||||
_init: function() {
|
||||
this.actor = new St.Label({ text: '⚫', visible: false, y_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
|
||||
this._sources = [];
|
||||
|
||||
Main.messageTray.connect('source-added', Lang.bind(this, this._onSourceAdded));
|
||||
Main.messageTray.connect('source-removed', Lang.bind(this, this._onSourceRemoved));
|
||||
Main.messageTray.connect('queue-changed', Lang.bind(this, this._updateCount));
|
||||
|
||||
let sources = Main.messageTray.getSources();
|
||||
sources.forEach(Lang.bind(this, function(source) { this._onSourceAdded(null, source); }));
|
||||
},
|
||||
|
||||
_onSourceAdded: function(tray, source) {
|
||||
source.connect('count-updated', Lang.bind(this, this._updateCount));
|
||||
this._sources.push(source);
|
||||
this._updateCount();
|
||||
},
|
||||
|
||||
_onSourceRemoved: function(tray, source) {
|
||||
this._sources.splice(this._sources.indexOf(source), 1);
|
||||
this._updateCount();
|
||||
},
|
||||
|
||||
_updateCount: function() {
|
||||
let count = 0;
|
||||
this._sources.forEach(Lang.bind(this,
|
||||
function(source) {
|
||||
count += source.unseenCount;
|
||||
}));
|
||||
count -= Main.messageTray.queueCount;
|
||||
|
||||
this.actor.visible = (count > 0);
|
||||
}
|
||||
});
|
||||
|
||||
const IndicatorPad = new Lang.Class({
|
||||
Name: 'IndicatorPad',
|
||||
Extends: St.Widget,
|
||||
|
||||
_init: function(actor) {
|
||||
this._source = actor;
|
||||
this._source.connect('notify::visible',
|
||||
Lang.bind(this, this.queue_relayout));
|
||||
this.parent();
|
||||
},
|
||||
|
||||
vfunc_get_preferred_width: function(container, forHeight) {
|
||||
if (this._source.visible)
|
||||
return this._source.get_preferred_width(forHeight);
|
||||
return [0, 0];
|
||||
},
|
||||
|
||||
vfunc_get_preferred_height: function(container, forWidth) {
|
||||
if (this._source.visible)
|
||||
return this._source.get_preferred_height(forWidth);
|
||||
return [0, 0];
|
||||
}
|
||||
});
|
||||
|
||||
const FreezableBinLayout = new Lang.Class({
|
||||
Name: 'FreezableBinLayout',
|
||||
Extends: Clutter.BinLayout,
|
||||
|
||||
_init: function() {
|
||||
this.parent();
|
||||
|
||||
this._frozen = false;
|
||||
this._savedWidth = [NaN, NaN];
|
||||
this._savedHeight = [NaN, NaN];
|
||||
},
|
||||
|
||||
set frozen(v) {
|
||||
if (this._frozen == v)
|
||||
return;
|
||||
|
||||
this._frozen = v;
|
||||
if (!this._frozen)
|
||||
this.layout_changed();
|
||||
},
|
||||
|
||||
vfunc_get_preferred_width: function(container, forHeight) {
|
||||
if (!this._frozen || this._savedWidth.some(isNaN))
|
||||
this._savedWidth = this.parent(container, forHeight);
|
||||
return this._savedWidth;
|
||||
},
|
||||
|
||||
vfunc_get_preferred_height: function(container, forWidth) {
|
||||
if (!this._frozen || this._savedHeight.some(isNaN))
|
||||
this._savedHeight = this.parent(container, forWidth);
|
||||
return this._savedHeight;
|
||||
}
|
||||
});
|
||||
|
||||
const DateMenuButton = new Lang.Class({
|
||||
Name: 'DateMenuButton',
|
||||
Extends: PanelMenu.Button,
|
||||
@ -46,96 +317,76 @@ const DateMenuButton = new Lang.Class({
|
||||
let hbox;
|
||||
let vbox;
|
||||
|
||||
let menuAlignment = 0.25;
|
||||
let menuAlignment = 0.5;
|
||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
||||
menuAlignment = 1.0 - menuAlignment;
|
||||
this.parent(menuAlignment);
|
||||
|
||||
this._clockDisplay = new St.Label({ y_align: Clutter.ActorAlign.CENTER });
|
||||
this._indicator = new MessagesIndicator();
|
||||
|
||||
let box = new St.BoxLayout();
|
||||
box.add_actor(new IndicatorPad(this._indicator.actor));
|
||||
box.add_actor(this._clockDisplay);
|
||||
box.add_actor(this._indicator.actor);
|
||||
|
||||
this.actor.label_actor = this._clockDisplay;
|
||||
this.actor.add_actor(this._clockDisplay);
|
||||
this.actor.add_actor(box);
|
||||
this.actor.add_style_class_name ('clock-display');
|
||||
|
||||
|
||||
let layout = new FreezableBinLayout();
|
||||
let bin = new St.Widget({ layout_manager: layout });
|
||||
this.menu.box.add_child(bin);
|
||||
|
||||
hbox = new St.BoxLayout({ name: 'calendarArea' });
|
||||
this.menu.box.add_child(hbox);
|
||||
bin.add_actor(hbox);
|
||||
|
||||
// Fill up the first column
|
||||
|
||||
vbox = new St.BoxLayout({vertical: true});
|
||||
hbox.add(vbox);
|
||||
|
||||
// Date
|
||||
// Having the ability to go to the current date if the user is already
|
||||
// on the current date can be confusing. So don't make the button reactive
|
||||
// until the selected date changes.
|
||||
this._date = new St.Button({ style_class: 'datemenu-date-label',
|
||||
reactive: false
|
||||
});
|
||||
this._date.connect('clicked',
|
||||
Lang.bind(this, function() {
|
||||
this._calendar.setDate(new Date(), false);
|
||||
}));
|
||||
vbox.add(this._date, { x_fill: false });
|
||||
|
||||
this._eventList = new Calendar.EventsList();
|
||||
this._calendar = new Calendar.Calendar();
|
||||
|
||||
this._calendar.connect('selected-date-changed',
|
||||
Lang.bind(this, function(calendar, date) {
|
||||
// we know this._eventList is defined here, because selected-data-changed
|
||||
// only gets emitted when the user clicks a date in the calendar,
|
||||
// and the calender makes those dates unclickable when instantiated with
|
||||
// a null event source
|
||||
this._eventList.setDate(date);
|
||||
|
||||
// Make the button reactive only if the selected date is not the current date.
|
||||
this._date.can_focus = this._date.reactive = !this._isToday(date)
|
||||
layout.frozen = !_isToday(date);
|
||||
this._messageList.setDate(date);
|
||||
}));
|
||||
vbox.add(this._calendar.actor);
|
||||
|
||||
let separator = new PopupMenu.PopupSeparatorMenuItem();
|
||||
vbox.add(separator.actor, { y_align: St.Align.END, expand: true, y_fill: false });
|
||||
|
||||
this._openCalendarItem = new PopupMenu.PopupMenuItem(_("Open Calendar"));
|
||||
this._openCalendarItem.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
|
||||
vbox.add(this._openCalendarItem.actor, {y_align: St.Align.END, expand: true, y_fill: false});
|
||||
|
||||
this._openClocksItem = new PopupMenu.PopupMenuItem(_("Open Clocks"));
|
||||
this._openClocksItem.connect('activate', Lang.bind(this, this._onOpenClocksActivate));
|
||||
vbox.add(this._openClocksItem.actor, {y_align: St.Align.END, expand: true, y_fill: false});
|
||||
|
||||
Shell.AppSystem.get_default().connect('installed-changed',
|
||||
Lang.bind(this, this._appInstalledChanged));
|
||||
|
||||
item = this.menu.addSettingsAction(_("Date & Time Settings"), 'gnome-datetime-panel.desktop');
|
||||
if (item) {
|
||||
item.actor.show_on_set_parent = false;
|
||||
item.actor.reparent(vbox);
|
||||
this._dateAndTimeSeparator = separator;
|
||||
}
|
||||
|
||||
this._separator = new St.DrawingArea({ style_class: 'calendar-vertical-separator',
|
||||
pseudo_class: 'highlighted' });
|
||||
this._separator.connect('repaint', Lang.bind(this, _onVertSepRepaint));
|
||||
hbox.add(this._separator);
|
||||
|
||||
// Fill up the second column
|
||||
hbox.add(this._eventList.actor, { expand: true, y_fill: false, y_align: St.Align.START });
|
||||
|
||||
// Whenever the menu is opened, select today
|
||||
this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {
|
||||
// Whenever the menu is opened, select today
|
||||
if (isOpen) {
|
||||
let now = new Date();
|
||||
this._calendar.setDate(now);
|
||||
|
||||
/* Translators: This is the date format to use when the calendar popup is
|
||||
* shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
|
||||
*/
|
||||
let dateFormat = Shell.util_translate_time_string (N_("%A %B %e, %Y"));
|
||||
this._date.set_label(now.toLocaleFormat(dateFormat));
|
||||
this._date.setDate(now);
|
||||
this._messageList.setDate(now);
|
||||
}
|
||||
}));
|
||||
|
||||
// Fill up the first column
|
||||
this._messageList = new Calendar.MessageList();
|
||||
hbox.add(this._messageList.actor, { expand: true, y_fill: false, y_align: St.Align.START });
|
||||
|
||||
// Fill up the second column
|
||||
vbox = new St.BoxLayout({ style_class: 'datemenu-calendar-column',
|
||||
vertical: true });
|
||||
hbox.add(vbox);
|
||||
|
||||
this._date = new TodayButton(this._calendar);
|
||||
vbox.add_actor(this._date.actor);
|
||||
|
||||
vbox.add(this._calendar.actor);
|
||||
|
||||
this._displaysSection = new St.ScrollView({ style_class: 'datemenu-displays-section vfade',
|
||||
x_expand: true, x_fill: true,
|
||||
overlay_scrollbars: true });
|
||||
this._displaysSection.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
vbox.add_actor(this._displaysSection);
|
||||
|
||||
let displaysBox = new St.BoxLayout({ vertical: true,
|
||||
style_class: 'datemenu-displays-box' });
|
||||
this._displaysSection.add_actor(displaysBox);
|
||||
|
||||
this._clocksItem = new WorldClocksSection();
|
||||
displaysBox.add(this._clocksItem.actor, { x_fill: true });
|
||||
|
||||
|
||||
// Done with hbox for calendar and event list
|
||||
|
||||
this._clock = new GnomeDesktop.WallClock();
|
||||
@ -145,36 +396,6 @@ const DateMenuButton = new Lang.Class({
|
||||
this._sessionUpdated();
|
||||
},
|
||||
|
||||
_isToday: function(date) {
|
||||
let now = new Date();
|
||||
return now.getYear() == date.getYear() &&
|
||||
now.getMonth() == date.getMonth() &&
|
||||
now.getDate() == date.getDate();
|
||||
},
|
||||
|
||||
_appInstalledChanged: function() {
|
||||
this._calendarApp = undefined;
|
||||
this._updateEventsVisibility();
|
||||
},
|
||||
|
||||
_updateEventsVisibility: function() {
|
||||
let visible = this._eventSource.hasCalendars;
|
||||
this._openCalendarItem.actor.visible = visible &&
|
||||
(this._getCalendarApp() != null);
|
||||
this._openClocksItem.actor.visible = visible &&
|
||||
(this._getClockApp() != null);
|
||||
this._separator.visible = visible;
|
||||
this._eventList.actor.visible = visible;
|
||||
if (visible) {
|
||||
let alignment = 0.25;
|
||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
||||
alignment = 1.0 - alignment;
|
||||
this.menu._arrowAlignment = alignment;
|
||||
} else {
|
||||
this.menu._arrowAlignment = 0.5;
|
||||
}
|
||||
},
|
||||
|
||||
_getEventSource: function() {
|
||||
return new Calendar.DBusEventSource();
|
||||
},
|
||||
@ -184,12 +405,9 @@ const DateMenuButton = new Lang.Class({
|
||||
this._eventSource.destroy();
|
||||
|
||||
this._calendar.setEventSource(eventSource);
|
||||
this._eventList.setEventSource(eventSource);
|
||||
this._messageList.setEventSource(eventSource);
|
||||
|
||||
this._eventSource = eventSource;
|
||||
this._eventSource.connect('notify::has-calendars', Lang.bind(this, function() {
|
||||
this._updateEventsVisibility();
|
||||
}));
|
||||
},
|
||||
|
||||
_sessionUpdated: function() {
|
||||
@ -201,44 +419,10 @@ const DateMenuButton = new Lang.Class({
|
||||
eventSource = new Calendar.EmptyEventSource();
|
||||
}
|
||||
this._setEventSource(eventSource);
|
||||
this._updateEventsVisibility();
|
||||
|
||||
// This needs to be handled manually, as the code to
|
||||
// autohide separators doesn't work across the vbox
|
||||
this._dateAndTimeSeparator.actor.visible = Main.sessionMode.allowSettings;
|
||||
},
|
||||
|
||||
_getCalendarApp: function() {
|
||||
if (this._calendarApp !== undefined)
|
||||
return this._calendarApp;
|
||||
|
||||
let apps = Gio.AppInfo.get_recommended_for_type('text/calendar');
|
||||
if (apps && (apps.length > 0)) {
|
||||
let app = Gio.AppInfo.get_default_for_type('text/calendar', false);
|
||||
let defaultInRecommended = apps.some(function(a) { return a.equal(app); });
|
||||
this._calendarApp = defaultInRecommended ? app : apps[0];
|
||||
} else {
|
||||
this._calendarApp = null;
|
||||
}
|
||||
return this._calendarApp;
|
||||
},
|
||||
|
||||
_getClockApp: function() {
|
||||
return Shell.AppSystem.get_default().lookup_app('org.gnome.clocks.desktop');
|
||||
},
|
||||
|
||||
_onOpenCalendarActivate: function() {
|
||||
this.menu.close();
|
||||
|
||||
let app = this._getCalendarApp();
|
||||
if (app.get_id() == 'evolution.desktop')
|
||||
app = Gio.DesktopAppInfo.new('evolution-calendar.desktop');
|
||||
app.launch([], global.create_app_launch_context(0, -1));
|
||||
},
|
||||
|
||||
_onOpenClocksActivate: function() {
|
||||
this.menu.close();
|
||||
let app = this._getClockApp();
|
||||
app.activate();
|
||||
// Displays are not actually expected to launch Settings when activated
|
||||
// but the corresponding app (clocks, weather); however we can consider
|
||||
// that display-specific settings, so re-use "allowSettings" here ...
|
||||
this._displaysSection.visible = Main.sessionMode.allowSettings;
|
||||
}
|
||||
});
|
||||
|
@ -6,6 +6,8 @@ const Meta = imports.gi.Meta;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const EDGE_THRESHOLD = 20;
|
||||
const DRAG_DISTANCE = 80;
|
||||
|
||||
@ -13,9 +15,10 @@ const EdgeDragAction = new Lang.Class({
|
||||
Name: 'EdgeDragAction',
|
||||
Extends: Clutter.GestureAction,
|
||||
|
||||
_init : function(side) {
|
||||
_init : function(side, allowedModes) {
|
||||
this.parent();
|
||||
this._side = side;
|
||||
this._allowedModes = allowedModes;
|
||||
this.set_n_touch_points(1);
|
||||
|
||||
global.display.connect('grab-op-begin', Lang.bind(this, function() {
|
||||
@ -34,6 +37,9 @@ const EdgeDragAction = new Lang.Class({
|
||||
if (this.get_n_current_points() == 0)
|
||||
return false;
|
||||
|
||||
if (!(this._allowedModes & Main.actionMode))
|
||||
return false;
|
||||
|
||||
let [x, y] = this.get_press_coords(0);
|
||||
let monitorRect = this._getMonitorRect(x, y);
|
||||
|
||||
|
@ -77,10 +77,10 @@ function init() {
|
||||
window._ = Gettext.gettext;
|
||||
window.C_ = Gettext.pgettext;
|
||||
window.ngettext = Gettext.ngettext;
|
||||
window.N_ = function(s) { return s; };
|
||||
|
||||
// Miscellaneous monkeypatching
|
||||
_patchContainerClass(St.BoxLayout);
|
||||
_patchContainerClass(St.Table);
|
||||
|
||||
_patchLayoutClass(Clutter.TableLayout, { row_spacing: 'spacing-rows',
|
||||
column_spacing: 'spacing-columns' });
|
||||
|
@ -203,14 +203,16 @@ const InstallExtensionDialog = new Lang.Class({
|
||||
|
||||
let message = _("Download and install “%s” from extensions.gnome.org?").format(info.name);
|
||||
|
||||
let box = new St.BoxLayout();
|
||||
let box = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
|
||||
vertical: false });
|
||||
this.contentLayout.add(box);
|
||||
|
||||
let gicon = new Gio.FileIcon({ file: Gio.File.new_for_uri(REPOSITORY_URL_BASE + info.icon) })
|
||||
let icon = new St.Icon({ gicon: gicon });
|
||||
box.add(icon);
|
||||
|
||||
let label = new St.Label({ text: message });
|
||||
let label = new St.Label({ style_class: 'prompt-dialog-headline headline',
|
||||
text: message });
|
||||
box.add(label);
|
||||
},
|
||||
|
||||
|
@ -41,11 +41,11 @@ const CandidateArea = new Lang.Class({
|
||||
|
||||
this._buttonBox = new St.BoxLayout({ style_class: 'candidate-page-button-box' });
|
||||
|
||||
this._previousButton = new St.Button({ style_class: 'candidate-page-button candidate-page-button-previous' });
|
||||
this._previousButton = new St.Button({ style_class: 'candidate-page-button candidate-page-button-previous button' });
|
||||
this._previousButton.child = new St.Icon({ style_class: 'candidate-page-button-icon' });
|
||||
this._buttonBox.add(this._previousButton, { expand: true });
|
||||
|
||||
this._nextButton = new St.Button({ style_class: 'candidate-page-button candidate-page-button-next' });
|
||||
this._nextButton = new St.Button({ style_class: 'candidate-page-button candidate-page-button-next button' });
|
||||
this._nextButton.child = new St.Icon({ style_class: 'candidate-page-button-icon' });
|
||||
this._buttonBox.add(this._nextButton, { expand: true });
|
||||
|
||||
|
@ -278,6 +278,20 @@ const IconGrid = new Lang.Class({
|
||||
this._grid.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||
this._grid.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||
this._grid.connect('allocate', Lang.bind(this, this._allocate));
|
||||
this._grid.connect('actor-added', Lang.bind(this, this._childAdded));
|
||||
this._grid.connect('actor-removed', Lang.bind(this, this._childRemoved));
|
||||
},
|
||||
|
||||
_keyFocusIn: function(actor) {
|
||||
this.emit('key-focus-in', actor);
|
||||
},
|
||||
|
||||
_childAdded: function(grid, child) {
|
||||
child._iconGridKeyFocusInId = child.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
|
||||
},
|
||||
|
||||
_childRemoved: function(grid, child) {
|
||||
child.disconnect(child._iconGridKeyFocusInId);
|
||||
},
|
||||
|
||||
_getPreferredWidth: function (grid, forHeight, alloc) {
|
||||
@ -668,10 +682,6 @@ const IconGrid = new Lang.Class({
|
||||
this._grid.destroy_all_children();
|
||||
},
|
||||
|
||||
_keyFocusIn: function(actor) {
|
||||
this.emit('key-focus-in', actor._associatedItem);
|
||||
},
|
||||
|
||||
addItem: function(item, index) {
|
||||
if (!item.icon instanceof BaseIcon)
|
||||
throw new Error('Only items with a BaseIcon icon property can be added to IconGrid');
|
||||
@ -681,26 +691,9 @@ const IconGrid = new Lang.Class({
|
||||
this._grid.insert_child_at_index(item.actor, index);
|
||||
else
|
||||
this._grid.add_actor(item.actor);
|
||||
|
||||
// Maybe the item actor acts as a container, so ask the item if
|
||||
// it has a specific actor to track focus
|
||||
let focusReceiver = item.actor;
|
||||
if (item.getFocusReceiver)
|
||||
focusReceiver = item.getFocusReceiver();
|
||||
|
||||
focusReceiver._associatedItem = item.actor;
|
||||
focusReceiver._iconGridKeyFocusInId = focusReceiver.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
|
||||
},
|
||||
|
||||
removeItem: function(item) {
|
||||
let focusReceiver = item.actor;
|
||||
if (item.getFocusReceiver)
|
||||
focusReceiver = item.getFocusReceiver();
|
||||
|
||||
|
||||
focusReceiver._associatedItem = null;
|
||||
focusReceiver.disconnect(focusReceiver._iconGridKeyFocusInId);
|
||||
|
||||
this._grid.remove_child(item.actor);
|
||||
},
|
||||
|
||||
|
@ -6,6 +6,7 @@ const Gdk = imports.gi.Gdk;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
@ -23,9 +24,6 @@ const KEYBOARD_TYPE = 'keyboard-type';
|
||||
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
|
||||
const SHOW_KEYBOARD = 'screen-keyboard-enabled';
|
||||
|
||||
const CURSOR_BUS_NAME = 'org.gnome.SettingsDaemon.Cursor';
|
||||
const CURSOR_OBJECT_PATH = '/org/gnome/SettingsDaemon/Cursor';
|
||||
|
||||
const CARIBOU_BUS_NAME = 'org.gnome.Caribou.Daemon';
|
||||
const CARIBOU_OBJECT_PATH = '/org/gnome/Caribou/Daemon';
|
||||
|
||||
@ -60,14 +58,7 @@ const CaribouDaemonIface = '<node> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const CursorManagerIface = '<node> \
|
||||
<interface name="org.gnome.SettingsDaemon.Cursor"> \
|
||||
<property name="ShowOSK" type="b" access="read" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const CaribouDaemonProxy = Gio.DBusProxy.makeProxyWrapper(CaribouDaemonIface);
|
||||
const CursorManagerProxy = Gio.DBusProxy.makeProxyWrapper(CursorManagerIface);
|
||||
|
||||
const Key = new Lang.Class({
|
||||
Name: 'Key',
|
||||
@ -120,6 +111,35 @@ const Key = new Lang.Class({
|
||||
key.release();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
button.connect('touch-event', Lang.bind(this,
|
||||
function (actor, event) {
|
||||
let device = event.get_device();
|
||||
let sequence = event.get_event_sequence();
|
||||
|
||||
// We only handle touch events here on wayland. On X11
|
||||
// we do get emulated pointer events, which already works
|
||||
// for single-touch cases. Besides, the X11 passive touch grab
|
||||
// set up by Mutter will make us see first the touch events
|
||||
// and later the pointer events, so it will look like two
|
||||
// unrelated series of events, we want to avoid double handling
|
||||
// in these cases.
|
||||
if (!Meta.is_wayland_compositor())
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (!this._touchPressed &&
|
||||
event.type() == Clutter.EventType.TOUCH_BEGIN) {
|
||||
device.sequence_grab(sequence, actor);
|
||||
this._touchPressed = true;
|
||||
key.press();
|
||||
} else if (this._touchPressed &&
|
||||
event.type() == Clutter.EventType.TOUCH_END &&
|
||||
device.sequence_get_grabbed_actor(sequence) == actor) {
|
||||
device.sequence_ungrab(sequence);
|
||||
this._touchPressed = false;
|
||||
key.release();
|
||||
}
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}));
|
||||
|
||||
return button;
|
||||
},
|
||||
@ -184,21 +204,23 @@ const Keyboard = new Lang.Class({
|
||||
this._keyboardSettings.connect('changed', Lang.bind(this, this._sync));
|
||||
this._a11yApplicationsSettings = new Gio.Settings({ schema_id: A11Y_APPLICATIONS_SCHEMA });
|
||||
this._a11yApplicationsSettings.connect('changed', Lang.bind(this, this._sync));
|
||||
this._watchNameId = Gio.bus_watch_name(Gio.BusType.SESSION, CURSOR_BUS_NAME, 0,
|
||||
Lang.bind(this, this._sync),
|
||||
Lang.bind(this, this._sync));
|
||||
this._daemonProxy = null;
|
||||
this._cursorProxy = new CursorManagerProxy(Gio.DBus.session, CURSOR_BUS_NAME,
|
||||
CURSOR_OBJECT_PATH,
|
||||
Lang.bind(this, function(proxy, error) {
|
||||
if (error) {
|
||||
log(error.message);
|
||||
return;
|
||||
}
|
||||
this._cursorProxy.connect('g-properties-changed',
|
||||
Lang.bind(this, this._sync));
|
||||
this._sync();
|
||||
}));
|
||||
this._lastDeviceId = null;
|
||||
|
||||
if (Meta.is_wayland_compositor() &&
|
||||
Caribou.DisplayAdapter.set_default)
|
||||
Caribou.DisplayAdapter.set_default(new ShellWaylandAdapter());
|
||||
|
||||
Meta.get_backend().connect('last-device-changed', Lang.bind(this,
|
||||
function (backend, deviceId) {
|
||||
let manager = Clutter.DeviceManager.get_default();
|
||||
let device = manager.get_device(deviceId);
|
||||
|
||||
if (device.get_device_name().indexOf('XTEST') < 0) {
|
||||
this._lastDeviceId = deviceId;
|
||||
this._sync();
|
||||
}
|
||||
}));
|
||||
this._sync();
|
||||
|
||||
this._showIdleId = 0;
|
||||
@ -217,9 +239,22 @@ const Keyboard = new Lang.Class({
|
||||
this._redraw();
|
||||
},
|
||||
|
||||
_lastDeviceIsTouchscreen: function () {
|
||||
if (!this._lastDeviceId)
|
||||
return false;
|
||||
|
||||
let manager = Clutter.DeviceManager.get_default();
|
||||
let device = manager.get_device(this._lastDeviceId);
|
||||
|
||||
if (!device)
|
||||
return false;
|
||||
|
||||
return device.get_device_type() == Clutter.InputDeviceType.TOUCHSCREEN_DEVICE;
|
||||
},
|
||||
|
||||
_sync: function () {
|
||||
this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD) ||
|
||||
this._cursorProxy.ShowOSK;
|
||||
this._lastDeviceIsTouchscreen();
|
||||
if (!this._enableKeyboard && !this._keyboard)
|
||||
return;
|
||||
if (this._enableKeyboard && this._keyboard &&
|
||||
@ -717,3 +752,24 @@ const KeyboardSource = new Lang.Class({
|
||||
this._keyboard.show(Main.layoutManager.bottomIndex);
|
||||
}
|
||||
});
|
||||
|
||||
const ShellWaylandAdapter = new Lang.Class({
|
||||
Name: 'ShellWaylandAdapter',
|
||||
Extends: Caribou.XAdapter,
|
||||
|
||||
vfunc_keyval_press: function(keyval) {
|
||||
let focus = global.stage.get_key_focus();
|
||||
if (focus instanceof Clutter.Text)
|
||||
Shell.util_text_insert_keyval(focus, keyval);
|
||||
else
|
||||
this.parent(keyval);
|
||||
},
|
||||
|
||||
vfunc_keyval_release: function(keyval) {
|
||||
let focus = global.stage.get_key_focus();
|
||||
if (focus instanceof Clutter.Text)
|
||||
return; // do nothing
|
||||
else
|
||||
this.parent(keyval);
|
||||
},
|
||||
});
|
||||
|
225
js/ui/layout.js
@ -11,6 +11,7 @@ const St = imports.gi.St;
|
||||
|
||||
const Background = imports.ui.background;
|
||||
const BackgroundMenu = imports.ui.backgroundMenu;
|
||||
const LoginManager = imports.misc.loginManager;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
const Main = imports.ui.main;
|
||||
@ -21,11 +22,6 @@ const STARTUP_ANIMATION_TIME = 0.5;
|
||||
const KEYBOARD_ANIMATION_TIME = 0.15;
|
||||
const BACKGROUND_FADE_ANIMATION_TIME = 1.0;
|
||||
|
||||
// The message tray takes this much pressure
|
||||
// in the pressure barrier at once to release it.
|
||||
const MESSAGE_TRAY_PRESSURE_THRESHOLD = 250; // pixels
|
||||
const MESSAGE_TRAY_PRESSURE_TIMEOUT = 1000; // ms
|
||||
|
||||
const HOT_CORNER_PRESSURE_THRESHOLD = 100; // pixels
|
||||
const HOT_CORNER_PRESSURE_TIMEOUT = 1000; // ms
|
||||
|
||||
@ -50,11 +46,16 @@ const MonitorConstraint = new Lang.Class({
|
||||
'index': GObject.ParamSpec.int('index',
|
||||
'Monitor index', 'Track specific monitor',
|
||||
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
|
||||
-1, 64, -1)},
|
||||
-1, 64, -1),
|
||||
'work-area': GObject.ParamSpec.boolean('work-area',
|
||||
'Work-area', 'Track monitor\'s work-area',
|
||||
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
|
||||
false)},
|
||||
|
||||
_init: function(props) {
|
||||
this._primary = false;
|
||||
this._index = -1;
|
||||
this._workArea = false;
|
||||
|
||||
this.parent(props);
|
||||
},
|
||||
@ -84,6 +85,19 @@ const MonitorConstraint = new Lang.Class({
|
||||
this.notify('index');
|
||||
},
|
||||
|
||||
get work_area() {
|
||||
return this._workArea;
|
||||
},
|
||||
|
||||
set work_area(v) {
|
||||
if (v == this._workArea)
|
||||
return;
|
||||
this._workArea = v;
|
||||
if (this.actor)
|
||||
this.actor.queue_relayout();
|
||||
this.notify('work-area');
|
||||
},
|
||||
|
||||
vfunc_set_actor: function(actor) {
|
||||
if (actor) {
|
||||
if (!this._monitorsChangedId) {
|
||||
@ -91,10 +105,21 @@ const MonitorConstraint = new Lang.Class({
|
||||
this.actor.queue_relayout();
|
||||
}));
|
||||
}
|
||||
|
||||
if (!this._workareasChangedId) {
|
||||
this._workareasChangedId = global.screen.connect('workareas-changed', Lang.bind(this, function() {
|
||||
if (this._workArea)
|
||||
this.actor.queue_relayout();
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
if (this._monitorsChangedId)
|
||||
Main.layoutManager.disconnect(this._monitorsChangedId);
|
||||
this._monitorsChangedId = 0;
|
||||
|
||||
if (this._workareasChangedId)
|
||||
global.screen.disconnect(this._workareasChangedId);
|
||||
this._workareasChangedId = 0;
|
||||
}
|
||||
|
||||
this.parent(actor);
|
||||
@ -104,15 +129,21 @@ const MonitorConstraint = new Lang.Class({
|
||||
if (!this._primary && this._index < 0)
|
||||
return;
|
||||
|
||||
let monitor;
|
||||
if (this._primary) {
|
||||
monitor = Main.layoutManager.primaryMonitor;
|
||||
let index;
|
||||
if (this._primary)
|
||||
index = Main.layoutManager.primaryIndex;
|
||||
else
|
||||
index = Math.min(this._index, Main.layoutManager.monitors.length - 1);
|
||||
|
||||
let rect;
|
||||
if (this._workArea) {
|
||||
let ws = global.screen.get_workspace_by_index(0);
|
||||
rect = ws.get_work_area_for_monitor(index);
|
||||
} else {
|
||||
let index = Math.min(this._index, Main.layoutManager.monitors.length - 1);
|
||||
monitor = Main.layoutManager.monitors[index];
|
||||
rect = Main.layoutManager.monitors[index];
|
||||
}
|
||||
|
||||
actorBox.init_rect(monitor.x, monitor.y, monitor.width, monitor.height);
|
||||
actorBox.init_rect(rect.x, rect.y, rect.width, rect.height);
|
||||
}
|
||||
});
|
||||
|
||||
@ -135,6 +166,7 @@ const Monitor = new Lang.Class({
|
||||
const defaultParams = {
|
||||
trackFullscreen: false,
|
||||
affectsStruts: false,
|
||||
affectsInputRegion: true
|
||||
};
|
||||
|
||||
const LayoutManager = new Lang.Class({
|
||||
@ -149,7 +181,6 @@ const LayoutManager = new Lang.Class({
|
||||
|
||||
this._keyboardIndex = -1;
|
||||
this._rightPanelBarrier = null;
|
||||
this._trayBarrier = null;
|
||||
|
||||
this._inOverview = false;
|
||||
this._updateRegionIdle = 0;
|
||||
@ -206,11 +237,6 @@ const LayoutManager = new Lang.Class({
|
||||
this.panelBox.connect('allocation-changed',
|
||||
Lang.bind(this, this._panelBoxChanged));
|
||||
|
||||
this.trayBox = new St.Widget({ name: 'trayBox',
|
||||
layout_manager: new Clutter.BinLayout() });
|
||||
this.addChrome(this.trayBox);
|
||||
this._setupTrayPressure();
|
||||
|
||||
this.modalDialogGroup = new St.Widget({ name: 'modalDialogGroup',
|
||||
layout_manager: new Clutter.BinLayout() });
|
||||
this.uiGroup.add_actor(this.modalDialogGroup);
|
||||
@ -248,6 +274,18 @@ const LayoutManager = new Lang.Class({
|
||||
global.screen.connect('in-fullscreen-changed',
|
||||
Lang.bind(this, this._updateFullscreen));
|
||||
this._monitorsChanged();
|
||||
|
||||
// NVIDIA drivers don't preserve FBO contents across
|
||||
// suspend/resume, see
|
||||
// https://bugzilla.gnome.org/show_bug.cgi?id=739178
|
||||
if (Shell.util_need_background_refresh()) {
|
||||
LoginManager.getLoginManager().connect('prepare-for-sleep',
|
||||
function(lm, suspending) {
|
||||
if (suspending)
|
||||
return;
|
||||
Meta.Background.refresh_all();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// This is called by Main after everything else is constructed
|
||||
@ -423,10 +461,6 @@ const LayoutManager = new Lang.Class({
|
||||
this.panelBox.set_size(this.primaryMonitor.width, -1);
|
||||
|
||||
this.keyboardIndex = this.primaryIndex;
|
||||
|
||||
this.trayBox.set_position(this.bottomMonitor.x,
|
||||
this.bottomMonitor.y + this.bottomMonitor.height);
|
||||
this.trayBox.set_size(this.bottomMonitor.width, -1);
|
||||
},
|
||||
|
||||
_panelBoxChanged: function() {
|
||||
@ -455,50 +489,9 @@ const LayoutManager = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_setupTrayPressure: function() {
|
||||
this._trayPressure = new PressureBarrier(MESSAGE_TRAY_PRESSURE_THRESHOLD,
|
||||
MESSAGE_TRAY_PRESSURE_TIMEOUT,
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
this._trayPressure.setEventFilter(this._trayBarrierEventFilter);
|
||||
this._trayPressure.connect('trigger', function(barrier) {
|
||||
if (Main.layoutManager.bottomMonitor.inFullscreen)
|
||||
return;
|
||||
|
||||
Main.messageTray.openTray();
|
||||
});
|
||||
},
|
||||
|
||||
_updateTrayBarrier: function() {
|
||||
let monitor = this.bottomMonitor;
|
||||
|
||||
if (this._trayBarrier) {
|
||||
this._trayPressure.removeBarrier(this._trayBarrier);
|
||||
this._trayBarrier.destroy();
|
||||
this._trayBarrier = null;
|
||||
}
|
||||
|
||||
this._trayBarrier = new Meta.Barrier({ display: global.display,
|
||||
x1: monitor.x, x2: monitor.x + monitor.width,
|
||||
y1: monitor.y + monitor.height, y2: monitor.y + monitor.height,
|
||||
directions: Meta.BarrierDirection.NEGATIVE_Y });
|
||||
this._trayPressure.addBarrier(this._trayBarrier);
|
||||
},
|
||||
|
||||
_trayBarrierEventFilter: function(event) {
|
||||
// Throw out all events where the pointer was grabbed by another
|
||||
// client, as the client that grabbed the pointer expects to have
|
||||
// complete control over it
|
||||
if (event.grabbed && Main.modalCount == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
_monitorsChanged: function() {
|
||||
this._updateMonitors();
|
||||
this._updateBoxes();
|
||||
this._updateTrayBarrier();
|
||||
this._updateHotCorners();
|
||||
this._updateBackgrounds();
|
||||
this._updateFullscreen();
|
||||
@ -608,7 +601,6 @@ const LayoutManager = new Lang.Class({
|
||||
// the UI group to get the correct allocation for the struts.
|
||||
this._updateRegions();
|
||||
|
||||
this.trayBox.hide();
|
||||
this.keyboardBox.hide();
|
||||
|
||||
let monitor = this.primaryMonitor;
|
||||
@ -675,7 +667,6 @@ const LayoutManager = new Lang.Class({
|
||||
|
||||
this._startingUp = false;
|
||||
|
||||
this.trayBox.show();
|
||||
this.keyboardBox.show();
|
||||
|
||||
if (!Main.sessionMode.isGreeter) {
|
||||
@ -748,10 +739,11 @@ const LayoutManager = new Lang.Class({
|
||||
// @actor: an actor to add to the chrome
|
||||
// @params: (optional) additional params
|
||||
//
|
||||
// Adds @actor to the chrome, and extends the input region
|
||||
// to include it. Changes in @actor's size, position, and
|
||||
// visibility will automatically result in appropriate changes
|
||||
// to the input region.
|
||||
// Adds @actor to the chrome, and (unless %affectsInputRegion in
|
||||
// @params is %false) extends the input region to include it.
|
||||
// Changes in @actor's size, position, and visibility will
|
||||
// automatically result in appropriate changes to the input
|
||||
// region.
|
||||
//
|
||||
// If %affectsStruts in @params is %true (and @actor is along a
|
||||
// screen edge), then @actor's size and position will also affect
|
||||
@ -845,6 +837,7 @@ const LayoutManager = new Lang.Class({
|
||||
// need to connect to 'destroy' too.
|
||||
|
||||
this._trackedActors.push(actorData);
|
||||
this._updateActorVisibility(actorData);
|
||||
this._queueUpdateRegions();
|
||||
},
|
||||
|
||||
@ -863,25 +856,23 @@ const LayoutManager = new Lang.Class({
|
||||
this._queueUpdateRegions();
|
||||
},
|
||||
|
||||
_updateActorVisibility: function(actorData) {
|
||||
if (!actorData.trackFullscreen)
|
||||
return;
|
||||
|
||||
let monitor = this.findMonitorForActor(actorData.actor);
|
||||
actorData.actor.visible = !(global.window_group.visible &&
|
||||
monitor &&
|
||||
monitor.inFullscreen);
|
||||
},
|
||||
|
||||
_updateVisibility: function() {
|
||||
let windowsVisible = Main.sessionMode.hasWindows && !this._inOverview;
|
||||
|
||||
global.window_group.visible = windowsVisible;
|
||||
global.top_window_group.visible = windowsVisible;
|
||||
|
||||
for (let i = 0; i < this._trackedActors.length; i++) {
|
||||
let actorData = this._trackedActors[i], visible;
|
||||
if (!actorData.trackFullscreen)
|
||||
continue;
|
||||
|
||||
if (!windowsVisible)
|
||||
visible = true;
|
||||
else if (this.findMonitorForActor(actorData.actor).inFullscreen)
|
||||
visible = false;
|
||||
else
|
||||
visible = true;
|
||||
actorData.actor.visible = visible;
|
||||
}
|
||||
this._trackedActors.forEach(Lang.bind(this, this._updateActorVisibility));
|
||||
},
|
||||
|
||||
getWorkAreaForMonitor: function(monitorIndex) {
|
||||
@ -953,7 +944,7 @@ const LayoutManager = new Lang.Class({
|
||||
|
||||
for (i = 0; i < this._trackedActors.length; i++) {
|
||||
let actorData = this._trackedActors[i];
|
||||
if (!wantsInputRegion && !actorData.affectsStruts)
|
||||
if (!(actorData.affectsInputRegion && wantsInputRegion) && !actorData.affectsStruts)
|
||||
continue;
|
||||
|
||||
let [x, y] = actorData.actor.get_transformed_position();
|
||||
@ -963,7 +954,7 @@ const LayoutManager = new Lang.Class({
|
||||
w = Math.round(w);
|
||||
h = Math.round(h);
|
||||
|
||||
if (wantsInputRegion && actorData.actor.get_paint_visibility())
|
||||
if (actorData.affectsInputRegion && wantsInputRegion && actorData.actor.get_paint_visibility())
|
||||
rects.push(new Meta.Rectangle({ x: x, y: y, width: w, height: h }));
|
||||
|
||||
if (actorData.affectsStruts) {
|
||||
@ -973,46 +964,39 @@ const LayoutManager = new Lang.Class({
|
||||
let y1 = Math.max(y, 0);
|
||||
let y2 = Math.min(y + h, global.screen_height);
|
||||
|
||||
// NetWM struts are not really powerful enought to handle
|
||||
// a multi-monitor scenario, they only describe what happens
|
||||
// around the outer sides of the full display region. However
|
||||
// it can describe a partial region along each side, so
|
||||
// we can support having the struts only affect the
|
||||
// primary monitor. This should be enough as we only have
|
||||
// chrome affecting the struts on the primary monitor so
|
||||
// far.
|
||||
//
|
||||
// Metacity wants to know what side of the screen the
|
||||
// strut is considered to be attached to. If the actor is
|
||||
// Metacity wants to know what side of the monitor the
|
||||
// strut is considered to be attached to. First, we find
|
||||
// the monitor that contains the strut. If the actor is
|
||||
// only touching one edge, or is touching the entire
|
||||
// border of the primary monitor, then it's obvious which
|
||||
// side to call it. If it's in a corner, we pick a side
|
||||
// arbitrarily. If it doesn't touch any edges, or it spans
|
||||
// the width/height across the middle of the screen, then
|
||||
// we don't create a strut for it at all.
|
||||
// border of that monitor, then it's obvious which side
|
||||
// to call it. If it's in a corner, we pick a side
|
||||
// arbitrarily. If it doesn't touch any edges, or it
|
||||
// spans the width/height across the middle of the
|
||||
// screen, then we don't create a strut for it at all.
|
||||
|
||||
let monitor = this.findMonitorForActor(actorData.actor);
|
||||
let side;
|
||||
let primary = this.primaryMonitor;
|
||||
if (x1 <= primary.x && x2 >= primary.x + primary.width) {
|
||||
if (y1 <= primary.y)
|
||||
if (x1 <= monitor.x && x2 >= monitor.x + monitor.width) {
|
||||
if (y1 <= monitor.y)
|
||||
side = Meta.Side.TOP;
|
||||
else if (y2 >= primary.y + primary.height)
|
||||
else if (y2 >= monitor.y + monitor.height)
|
||||
side = Meta.Side.BOTTOM;
|
||||
else
|
||||
continue;
|
||||
} else if (y1 <= primary.y && y2 >= primary.y + primary.height) {
|
||||
if (x1 <= 0)
|
||||
} else if (y1 <= monitor.y && y2 >= monitor.y + monitor.height) {
|
||||
if (x1 <= monitor.x)
|
||||
side = Meta.Side.LEFT;
|
||||
else if (x2 >= primary.x + primary.width)
|
||||
else if (x2 >= monitor.x + monitor.width)
|
||||
side = Meta.Side.RIGHT;
|
||||
else
|
||||
continue;
|
||||
} else if (x1 <= 0)
|
||||
} else if (x1 <= monitor.x)
|
||||
side = Meta.Side.LEFT;
|
||||
else if (y1 <= 0)
|
||||
else if (y1 <= monitor.y)
|
||||
side = Meta.Side.TOP;
|
||||
else if (x2 >= global.screen_width)
|
||||
else if (x2 >= monitor.x + monitor.width)
|
||||
side = Meta.Side.RIGHT;
|
||||
else if (y2 >= global.screen_height)
|
||||
else if (y2 >= monitor.y + monitor.height)
|
||||
side = Meta.Side.BOTTOM;
|
||||
else
|
||||
continue;
|
||||
@ -1067,8 +1051,8 @@ const HotCorner = new Lang.Class({
|
||||
|
||||
this._pressureBarrier = new PressureBarrier(HOT_CORNER_PRESSURE_THRESHOLD,
|
||||
HOT_CORNER_PRESSURE_TIMEOUT,
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW);
|
||||
this._pressureBarrier.connect('trigger', Lang.bind(this, this._toggleOverview));
|
||||
|
||||
// Cache the three ripples instead of dynamically creating and destroying them.
|
||||
@ -1245,10 +1229,10 @@ const HotCorner = new Lang.Class({
|
||||
const PressureBarrier = new Lang.Class({
|
||||
Name: 'PressureBarrier',
|
||||
|
||||
_init: function(threshold, timeout, keybindingMode) {
|
||||
_init: function(threshold, timeout, actionMode) {
|
||||
this._threshold = threshold;
|
||||
this._timeout = timeout;
|
||||
this._keybindingMode = keybindingMode;
|
||||
this._actionMode = actionMode;
|
||||
this._barriers = [];
|
||||
this._eventFilter = null;
|
||||
|
||||
@ -1331,8 +1315,11 @@ const PressureBarrier = new Lang.Class({
|
||||
},
|
||||
|
||||
_onBarrierLeft: function(barrier, event) {
|
||||
this._reset();
|
||||
this._isTriggered = false;
|
||||
barrier._isHit = false;
|
||||
if (this._barriers.every(function(b) { return !b._isHit; })) {
|
||||
this._reset();
|
||||
this._isTriggered = false;
|
||||
}
|
||||
},
|
||||
|
||||
_trigger: function() {
|
||||
@ -1342,6 +1329,8 @@ const PressureBarrier = new Lang.Class({
|
||||
},
|
||||
|
||||
_onBarrierHit: function(barrier, event) {
|
||||
barrier._isHit = true;
|
||||
|
||||
// If we've triggered the barrier, wait until the pointer has the
|
||||
// left the barrier hitbox until we trigger it again.
|
||||
if (this._isTriggered)
|
||||
@ -1351,7 +1340,7 @@ const PressureBarrier = new Lang.Class({
|
||||
return;
|
||||
|
||||
// Throw out all events not in the proper keybinding mode
|
||||
if (!(this._keybindingMode & Main.keybindingMode))
|
||||
if (!(this._actionMode & Main.actionMode))
|
||||
return;
|
||||
|
||||
let slide = this._getDistanceAlongBarrier(barrier, event);
|
||||
|
273
js/ui/legacyTray.js
Normal file
@ -0,0 +1,273 @@
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const CtrlAltTab = imports.ui.ctrlAltTab;
|
||||
const Lang = imports.lang;
|
||||
const Layout = imports.ui.layout;
|
||||
const Main = imports.ui.main;
|
||||
const Overview = imports.ui.overview;
|
||||
const OverviewControls = imports.ui.overviewControls;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
|
||||
'bluetooth-applet': 'bluetooth',
|
||||
'gnome-volume-control-applet': 'volume', // renamed to gnome-sound-applet
|
||||
// when moved to control center
|
||||
'gnome-sound-applet': 'volume',
|
||||
'nm-applet': 'network',
|
||||
'gnome-power-manager': 'battery',
|
||||
'keyboard': 'keyboard',
|
||||
'a11y-keyboard': 'a11y',
|
||||
'kbd-scrolllock': 'keyboard',
|
||||
'kbd-numlock': 'keyboard',
|
||||
'kbd-capslock': 'keyboard',
|
||||
'ibus-ui-gtk': 'keyboard'
|
||||
};
|
||||
|
||||
// Offset of the original position from the bottom-right corner
|
||||
const CONCEALED_WIDTH = 3;
|
||||
const REVEAL_ANIMATION_TIME = 0.2;
|
||||
const TEMP_REVEAL_TIME = 2;
|
||||
|
||||
const BARRIER_THRESHOLD = 70;
|
||||
const BARRIER_TIMEOUT = 1000;
|
||||
|
||||
const LegacyTray = new Lang.Class({
|
||||
Name: 'LegacyTray',
|
||||
|
||||
_init: function() {
|
||||
this.actor = new St.Widget({ clip_to_allocation: true,
|
||||
layout_manager: new Clutter.BinLayout() });
|
||||
let constraint = new Layout.MonitorConstraint({ primary: true,
|
||||
work_area: true });
|
||||
this.actor.add_constraint(constraint);
|
||||
|
||||
this._slideLayout = new OverviewControls.SlideLayout();
|
||||
this._slideLayout.translationX = 0;
|
||||
this._slideLayout.slideDirection = OverviewControls.SlideDirection.LEFT;
|
||||
|
||||
this._slider = new St.Widget({ style_class: 'legacy-tray',
|
||||
x_expand: true, y_expand: true,
|
||||
x_align: Clutter.ActorAlign.START,
|
||||
y_align: Clutter.ActorAlign.END,
|
||||
layout_manager: this._slideLayout });
|
||||
this.actor.add_actor(this._slider);
|
||||
this._slider.connect('notify::allocation', Lang.bind(this, this._syncBarrier));
|
||||
|
||||
this._box = new St.BoxLayout();
|
||||
this._slider.add_actor(this._box);
|
||||
|
||||
this._concealHandle = new St.Button({ style_class: 'legacy-tray-handle',
|
||||
/* translators: 'Hide' is a verb */
|
||||
accessible_name: _("Hide tray"),
|
||||
can_focus: true });
|
||||
this._concealHandle.child = new St.Icon({ icon_name: 'go-previous-symbolic' });
|
||||
this._box.add_child(this._concealHandle);
|
||||
|
||||
this._iconBox = new St.BoxLayout({ style_class: 'legacy-tray-icon-box' });
|
||||
this._box.add_actor(this._iconBox);
|
||||
|
||||
this._revealHandle = new St.Button({ style_class: 'legacy-tray-handle' });
|
||||
this._revealHandle.child = new St.Icon({ icon_name: 'go-next-symbolic' });
|
||||
this._box.add_child(this._revealHandle);
|
||||
|
||||
this._revealHandle.bind_property('visible',
|
||||
this._concealHandle, 'visible',
|
||||
GObject.BindingFlags.BIDIRECTIONAL |
|
||||
GObject.BindingFlags.INVERT_BOOLEAN);
|
||||
this._revealHandle.connect('notify::visible',
|
||||
Lang.bind(this, this._sync));
|
||||
this._revealHandle.connect('notify::hover',
|
||||
Lang.bind(this ,this._sync));
|
||||
this._revealHandle.connect('clicked', Lang.bind(this,
|
||||
function() {
|
||||
this._concealHandle.show();
|
||||
}));
|
||||
this._concealHandle.connect('clicked', Lang.bind(this,
|
||||
function() {
|
||||
this._revealHandle.show();
|
||||
}));
|
||||
|
||||
this._horizontalBarrier = null;
|
||||
this._pressureBarrier = new Layout.PressureBarrier(BARRIER_THRESHOLD,
|
||||
BARRIER_TIMEOUT,
|
||||
Shell.ActionMode.NORMAL);
|
||||
this._pressureBarrier.connect('trigger', Lang.bind(this, function() {
|
||||
this._concealHandle.show();
|
||||
}));
|
||||
|
||||
Main.layoutManager.addChrome(this.actor, { affectsInputRegion: false });
|
||||
Main.layoutManager.trackChrome(this._slider, { affectsInputRegion: true });
|
||||
Main.uiGroup.set_child_below_sibling(this.actor, Main.layoutManager.modalDialogGroup);
|
||||
Main.ctrlAltTabManager.addGroup(this.actor,
|
||||
_("Status Icons"), 'focus-legacy-systray-symbolic',
|
||||
{ sortGroup: CtrlAltTab.SortGroup.BOTTOM });
|
||||
|
||||
this._trayManager = new Shell.TrayManager();
|
||||
this._trayIconAddedId = this._trayManager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
|
||||
this._trayIconRemovedId = this._trayManager.connect('tray-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
|
||||
this._trayManager.manage_screen(global.screen, this.actor);
|
||||
|
||||
Main.overview.connect('showing', Lang.bind(this,
|
||||
function() {
|
||||
Tweener.removeTweens(this._slider);
|
||||
Tweener.addTween(this._slider, { opacity: 0,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
}));
|
||||
Main.overview.connect('shown', Lang.bind(this, this._sync));
|
||||
Main.overview.connect('hiding', Lang.bind(this,
|
||||
function() {
|
||||
this._sync();
|
||||
Tweener.removeTweens(this._slider);
|
||||
Tweener.addTween(this._slider, { opacity: 255,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
}));
|
||||
|
||||
Main.layoutManager.connect('monitors-changed',
|
||||
Lang.bind(this, this._sync));
|
||||
global.screen.connect('in-fullscreen-changed',
|
||||
Lang.bind(this, this._sync));
|
||||
Main.sessionMode.connect('updated', Lang.bind(this, this._sync));
|
||||
|
||||
this._sync();
|
||||
},
|
||||
|
||||
_onTrayIconAdded: function(tm, icon) {
|
||||
let wmClass = icon.wm_class ? icon.wm_class.toLowerCase() : '';
|
||||
if (STANDARD_TRAY_ICON_IMPLEMENTATIONS[wmClass] !== undefined)
|
||||
return;
|
||||
|
||||
let button = new St.Button({ child: icon,
|
||||
style_class: 'legacy-tray-icon',
|
||||
button_mask: St.ButtonMask.ONE |
|
||||
St.ButtonMask.TWO |
|
||||
St.ButtonMask.THREE,
|
||||
can_focus: true,
|
||||
x_fill: true, y_fill: true });
|
||||
|
||||
let app = Shell.WindowTracker.get_default().get_app_from_pid(icon.pid);
|
||||
if (!app)
|
||||
app = Shell.AppSystem.get_default().lookup_startup_wmclass(wmClass);
|
||||
if (!app)
|
||||
app = Shell.AppSystem.get_default().lookup_desktop_wmclass(wmClass);
|
||||
if (app)
|
||||
button.accessible_name = app.get_name();
|
||||
else
|
||||
button.accessible_name = icon.title;
|
||||
|
||||
button.connect('clicked',
|
||||
function() {
|
||||
icon.click(Clutter.get_current_event());
|
||||
});
|
||||
button.connect('key-press-event',
|
||||
function() {
|
||||
icon.click(Clutter.get_current_event());
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
});
|
||||
button.connect('key-focus-in', Lang.bind(this,
|
||||
function() {
|
||||
this._concealHandle.show();
|
||||
}));
|
||||
|
||||
this._iconBox.add_actor(button);
|
||||
|
||||
if (!this._concealHandle.visible) {
|
||||
this._concealHandle.show();
|
||||
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, TEMP_REVEAL_TIME,
|
||||
Lang.bind(this, function() {
|
||||
this._concealHandle.hide();
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
_onTrayIconRemoved: function(tm, icon) {
|
||||
if (!this.actor.contains(icon))
|
||||
return;
|
||||
|
||||
icon.get_parent().destroy();
|
||||
this._sync();
|
||||
},
|
||||
|
||||
_syncBarrier: function() {
|
||||
let rtl = (this._slider.get_text_direction() == Clutter.TextDirection.RTL);
|
||||
let [x, y] = this._slider.get_transformed_position();
|
||||
let [w, h] = this._slider.get_transformed_size();
|
||||
|
||||
let x1 = Math.round(x);
|
||||
if (rtl)
|
||||
x1 += Math.round(w);
|
||||
|
||||
let x2 = x1;
|
||||
let y1 = Math.round(y);
|
||||
let y2 = y1 + Math.round(h);
|
||||
|
||||
if (this._horizontalBarrier &&
|
||||
this._horizontalBarrier.x1 == x1 &&
|
||||
this._horizontalBarrier.y1 == y1 &&
|
||||
this._horizontalBarrier.x2 == x2 &&
|
||||
this._horizontalBarrier.y2 == y2)
|
||||
return;
|
||||
|
||||
this._unsetBarrier();
|
||||
|
||||
let directions = (rtl ? Meta.BarrierDirection.NEGATIVE_X : Meta.BarrierDirection.POSITIVE_X);
|
||||
this._horizontalBarrier = new Meta.Barrier({ display: global.display,
|
||||
x1: x1, x2: x2,
|
||||
y1: y1, y2: y2,
|
||||
directions: directions });
|
||||
this._pressureBarrier.addBarrier(this._horizontalBarrier);
|
||||
},
|
||||
|
||||
_unsetBarrier: function() {
|
||||
if (this._horizontalBarrier == null)
|
||||
return;
|
||||
|
||||
this._pressureBarrier.removeBarrier(this._horizontalBarrier);
|
||||
this._horizontalBarrier.destroy();
|
||||
this._horizontalBarrier = null;
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
// FIXME: we no longer treat tray icons as notifications
|
||||
let allowed = Main.sessionMode.hasNotifications;
|
||||
let hasIcons = this._iconBox.get_n_children() > 0;
|
||||
let inOverview = Main.overview.visible && !Main.overview.animationInProgress;
|
||||
let inFullscreen = Main.layoutManager.primaryMonitor.inFullscreen;
|
||||
this.actor.visible = allowed && hasIcons && !inOverview && !inFullscreen;
|
||||
|
||||
if (!hasIcons)
|
||||
this._concealHandle.hide();
|
||||
|
||||
let targetSlide;
|
||||
if (this._concealHandle.visible) {
|
||||
targetSlide = 1.0;
|
||||
} else if (!hasIcons) {
|
||||
targetSlide = 0.0;
|
||||
} else {
|
||||
let [, boxWidth] = this._box.get_preferred_width(-1);
|
||||
let [, handleWidth] = this._revealHandle.get_preferred_width(-1);
|
||||
|
||||
if (this._revealHandle.hover)
|
||||
targetSlide = handleWidth / boxWidth;
|
||||
else
|
||||
targetSlide = CONCEALED_WIDTH / boxWidth;
|
||||
}
|
||||
|
||||
if (this.actor.visible) {
|
||||
Tweener.addTween(this._slideLayout,
|
||||
{ slideX: targetSlide,
|
||||
time: REVEAL_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
} else {
|
||||
this._slideLayout.slideX = targetSlide;
|
||||
this._unsetBarrier();
|
||||
}
|
||||
}
|
||||
});
|
@ -1040,7 +1040,7 @@ const LookingGlass = new Lang.Class({
|
||||
let availableHeight = primary.height - Main.layoutManager.keyboardBox.height;
|
||||
let myHeight = Math.min(primary.height * 0.7, availableHeight * 0.9);
|
||||
this.actor.x = primary.x + (primary.width - myWidth) / 2;
|
||||
this._hiddenY = primary.y + Main.layoutManager.panelBox.height - myHeight - 4; // -4 to hide the top corners
|
||||
this._hiddenY = primary.y + Main.layoutManager.panelBox.height - myHeight;
|
||||
this._targetY = this._hiddenY + myHeight;
|
||||
this.actor.y = this._hiddenY;
|
||||
this.actor.width = myWidth;
|
||||
@ -1086,7 +1086,7 @@ const LookingGlass = new Lang.Class({
|
||||
if (this._open)
|
||||
return;
|
||||
|
||||
if (!Main.pushModal(this._entry, { keybindingMode: Shell.KeyBindingMode.LOOKING_GLASS }))
|
||||
if (!Main.pushModal(this._entry, { actionMode: Shell.ActionMode.LOOKING_GLASS }))
|
||||
return;
|
||||
|
||||
this._notebook.selectIndex(0);
|
||||
|
@ -4,6 +4,7 @@ const Atspi = imports.gi.Atspi;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GDesktopEnums = imports.gi.GDesktopEnums;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const Lang = imports.lang;
|
||||
@ -22,6 +23,8 @@ const MOUSE_POLL_FREQUENCY = 50;
|
||||
const CROSSHAIRS_CLIP_SIZE = [100, 100];
|
||||
const NO_CHANGE = 0.0;
|
||||
|
||||
const POINTER_REST_TIME = 1000; // milliseconds
|
||||
|
||||
// Settings
|
||||
const APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
|
||||
const SHOW_KEY = 'screen-magnifier-enabled';
|
||||
@ -444,55 +447,6 @@ const Magnifier = new Lang.Class({
|
||||
this._appSettings = new Gio.Settings({ schema_id: APPLICATIONS_SCHEMA });
|
||||
this._settings = new Gio.Settings({ schema_id: MAGNIFIER_SCHEMA });
|
||||
|
||||
if (zoomRegion) {
|
||||
// Mag factor is accurate to two decimal places.
|
||||
let aPref = parseFloat(this._settings.get_double(MAG_FACTOR_KEY).toFixed(2));
|
||||
if (aPref != 0.0)
|
||||
zoomRegion.setMagFactor(aPref, aPref);
|
||||
|
||||
aPref = this._settings.get_enum(SCREEN_POSITION_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setScreenPosition(aPref);
|
||||
|
||||
zoomRegion.setLensMode(this._settings.get_boolean(LENS_MODE_KEY));
|
||||
zoomRegion.setClampScrollingAtEdges(!this._settings.get_boolean(CLAMP_MODE_KEY));
|
||||
|
||||
aPref = this._settings.get_enum(MOUSE_TRACKING_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setMouseTrackingMode(aPref);
|
||||
|
||||
aPref = this._settings.get_enum(FOCUS_TRACKING_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setFocusTrackingMode(aPref);
|
||||
|
||||
aPref = this._settings.get_enum(CARET_TRACKING_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setCaretTrackingMode(aPref);
|
||||
|
||||
aPref = this._settings.get_boolean(INVERT_LIGHTNESS_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setInvertLightness(aPref);
|
||||
|
||||
aPref = this._settings.get_double(COLOR_SATURATION_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setColorSaturation(aPref);
|
||||
|
||||
let bc = {};
|
||||
bc.r = this._settings.get_double(BRIGHT_RED_KEY);
|
||||
bc.g = this._settings.get_double(BRIGHT_GREEN_KEY);
|
||||
bc.b = this._settings.get_double(BRIGHT_BLUE_KEY);
|
||||
zoomRegion.setBrightness(bc);
|
||||
|
||||
bc.r = this._settings.get_double(CONTRAST_RED_KEY);
|
||||
bc.g = this._settings.get_double(CONTRAST_GREEN_KEY);
|
||||
bc.b = this._settings.get_double(CONTRAST_BLUE_KEY);
|
||||
zoomRegion.setContrast(bc);
|
||||
}
|
||||
|
||||
let showCrosshairs = this._settings.get_boolean(SHOW_CROSS_HAIRS_KEY);
|
||||
this.addCrosshairs();
|
||||
this.setCrosshairsVisible(showCrosshairs);
|
||||
|
||||
this._appSettings.connect('changed::' + SHOW_KEY,
|
||||
Lang.bind(this, function() {
|
||||
this.setActive(this._appSettings.get_boolean(SHOW_KEY));
|
||||
@ -561,6 +515,56 @@ const Magnifier = new Lang.Class({
|
||||
Lang.bind(this, function() {
|
||||
this.setCrosshairsClip(this._settings.get_boolean(CROSS_HAIRS_CLIP_KEY));
|
||||
}));
|
||||
|
||||
if (zoomRegion) {
|
||||
// Mag factor is accurate to two decimal places.
|
||||
let aPref = parseFloat(this._settings.get_double(MAG_FACTOR_KEY).toFixed(2));
|
||||
if (aPref != 0.0)
|
||||
zoomRegion.setMagFactor(aPref, aPref);
|
||||
|
||||
aPref = this._settings.get_enum(SCREEN_POSITION_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setScreenPosition(aPref);
|
||||
|
||||
zoomRegion.setLensMode(this._settings.get_boolean(LENS_MODE_KEY));
|
||||
zoomRegion.setClampScrollingAtEdges(!this._settings.get_boolean(CLAMP_MODE_KEY));
|
||||
|
||||
aPref = this._settings.get_enum(MOUSE_TRACKING_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setMouseTrackingMode(aPref);
|
||||
|
||||
aPref = this._settings.get_enum(FOCUS_TRACKING_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setFocusTrackingMode(aPref);
|
||||
|
||||
aPref = this._settings.get_enum(CARET_TRACKING_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setCaretTrackingMode(aPref);
|
||||
|
||||
aPref = this._settings.get_boolean(INVERT_LIGHTNESS_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setInvertLightness(aPref);
|
||||
|
||||
aPref = this._settings.get_double(COLOR_SATURATION_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setColorSaturation(aPref);
|
||||
|
||||
let bc = {};
|
||||
bc.r = this._settings.get_double(BRIGHT_RED_KEY);
|
||||
bc.g = this._settings.get_double(BRIGHT_GREEN_KEY);
|
||||
bc.b = this._settings.get_double(BRIGHT_BLUE_KEY);
|
||||
zoomRegion.setBrightness(bc);
|
||||
|
||||
bc.r = this._settings.get_double(CONTRAST_RED_KEY);
|
||||
bc.g = this._settings.get_double(CONTRAST_GREEN_KEY);
|
||||
bc.b = this._settings.get_double(CONTRAST_BLUE_KEY);
|
||||
zoomRegion.setContrast(bc);
|
||||
}
|
||||
|
||||
let showCrosshairs = this._settings.get_boolean(SHOW_CROSS_HAIRS_KEY);
|
||||
this.addCrosshairs();
|
||||
this.setCrosshairsVisible(showCrosshairs);
|
||||
|
||||
return this._appSettings.get_boolean(SHOW_KEY);
|
||||
},
|
||||
|
||||
@ -708,6 +712,9 @@ const ZoomRegion = new Lang.Class({
|
||||
this._xCaret = 0;
|
||||
this._yCaret = 0;
|
||||
|
||||
this._pointerIdleMonitor = Meta.IdleMonitor.get_for_device(Meta.VIRTUAL_CORE_POINTER_ID);
|
||||
this._scrollContentsTimerId = 0;
|
||||
|
||||
Main.layoutManager.connect('monitors-changed',
|
||||
Lang.bind(this, this._monitorsChanged));
|
||||
this._focusCaretTracker.connect('caret-moved',
|
||||
@ -1067,6 +1074,26 @@ const ZoomRegion = new Lang.Class({
|
||||
return this._isMouseOverRegion();
|
||||
},
|
||||
|
||||
_clearScrollContentsTimer: function() {
|
||||
if (this._scrollContentsTimerId != 0) {
|
||||
Mainloop.source_remove(this._scrollContentsTimerId);
|
||||
this._scrollContentsTimerId = 0;
|
||||
}
|
||||
},
|
||||
|
||||
_scrollContentsToDelayed: function(x, y) {
|
||||
if (this._pointerIdleMonitor.get_idletime() >= POINTER_REST_TIME) {
|
||||
this.scrollContentsTo(x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
this._clearScrollContentsTimer();
|
||||
this._scrollContentsTimerId = Mainloop.timeout_add(POINTER_REST_TIME, Lang.bind(this, function() {
|
||||
this._scrollContentsToDelayed(x, y);
|
||||
return GLib.SOURCE_REMOVE;
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* scrollContentsTo:
|
||||
* Shift the contents of the magnified view such it is centered on the given
|
||||
@ -1075,6 +1102,8 @@ const ZoomRegion = new Lang.Class({
|
||||
* @y: The y-coord of the point to center on.
|
||||
*/
|
||||
scrollContentsTo: function(x, y) {
|
||||
this._clearScrollContentsTimer();
|
||||
|
||||
this._followingCursor = false;
|
||||
this._changeROI({ xCenter: x,
|
||||
yCenter: y });
|
||||
@ -1380,7 +1409,7 @@ const ZoomRegion = new Lang.Class({
|
||||
else if (this._caretTrackingMode == GDesktopEnums.MagnifierCaretTrackingMode.CENTERED)
|
||||
[xCaret, yCaret] = this._centerFromPointCentered(xCaret, yCaret);
|
||||
|
||||
this.scrollContentsTo(xCaret, yCaret);
|
||||
this._scrollContentsToDelayed(xCaret, yCaret);
|
||||
},
|
||||
|
||||
_centerFromFocusPosition: function() {
|
||||
@ -1394,7 +1423,7 @@ const ZoomRegion = new Lang.Class({
|
||||
else if (this._focusTrackingMode == GDesktopEnums.MagnifierFocusTrackingMode.CENTERED)
|
||||
[xFocus, yFocus] = this._centerFromPointCentered(xFocus, yFocus);
|
||||
|
||||
this.scrollContentsTo(xFocus, yFocus);
|
||||
this._scrollContentsToDelayed(xFocus, yFocus);
|
||||
},
|
||||
|
||||
_centerFromPointPush: function(xPoint, yPoint) {
|
||||
|
@ -4,6 +4,7 @@ const Clutter = imports.gi.Clutter;
|
||||
const Gdk = imports.gi.Gdk;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
@ -17,9 +18,11 @@ const Environment = imports.ui.environment;
|
||||
const ExtensionSystem = imports.ui.extensionSystem;
|
||||
const ExtensionDownloader = imports.ui.extensionDownloader;
|
||||
const Keyboard = imports.ui.keyboard;
|
||||
const LegacyTray = imports.ui.legacyTray;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const OsdWindow = imports.ui.osdWindow;
|
||||
const OsdMonitorLabeler = imports.ui.osdMonitorLabeler;
|
||||
const Overview = imports.ui.overview;
|
||||
const Panel = imports.ui.panel;
|
||||
const Params = imports.misc.params;
|
||||
@ -50,19 +53,21 @@ let overview = null;
|
||||
let runDialog = null;
|
||||
let lookingGlass = null;
|
||||
let wm = null;
|
||||
let legacyTray = null;
|
||||
let messageTray = null;
|
||||
let screenShield = null;
|
||||
let notificationDaemon = null;
|
||||
let windowAttentionHandler = null;
|
||||
let ctrlAltTabManager = null;
|
||||
let osdWindowManager = null;
|
||||
let osdMonitorLabeler = null;
|
||||
let sessionMode = null;
|
||||
let shellDBusService = null;
|
||||
let shellMountOpDBusService = null;
|
||||
let screenSaverDBus = null;
|
||||
let screencastService = null;
|
||||
let modalCount = 0;
|
||||
let keybindingMode = Shell.KeyBindingMode.NONE;
|
||||
let actionMode = Shell.ActionMode.NONE;
|
||||
let modalActorFocusStack = [];
|
||||
let uiGroup = null;
|
||||
let magnifier = null;
|
||||
@ -75,18 +80,19 @@ let _cssStylesheet = null;
|
||||
let _a11ySettings = null;
|
||||
|
||||
function _sessionUpdated() {
|
||||
_loadDefaultStylesheet();
|
||||
if (sessionMode.isPrimary)
|
||||
_loadDefaultStylesheet();
|
||||
|
||||
wm.setCustomKeybindingHandler('panel-main-menu',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
sessionMode.hasOverview ? Lang.bind(overview, overview.toggle) : null);
|
||||
wm.allowKeybinding('overlay-key', Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW);
|
||||
wm.allowKeybinding('overlay-key', Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW);
|
||||
|
||||
wm.setCustomKeybindingHandler('panel-run-dialog',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
sessionMode.hasRunDialog ? openRunDialog : null);
|
||||
|
||||
if (!sessionMode.hasRunDialog) {
|
||||
@ -109,6 +115,8 @@ function start() {
|
||||
|
||||
sessionMode = new SessionMode.SessionMode();
|
||||
sessionMode.connect('updated', _sessionUpdated);
|
||||
Gtk.Settings.get_default().connect('notify::gtk-theme-name',
|
||||
_loadDefaultStylesheet);
|
||||
_initializeUI();
|
||||
|
||||
shellDBusService = new ShellDBus.GnomeShell();
|
||||
@ -146,14 +154,16 @@ function _initializeUI() {
|
||||
xdndHandler = new XdndHandler.XdndHandler();
|
||||
ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
|
||||
osdWindowManager = new OsdWindow.OsdWindowManager();
|
||||
osdMonitorLabeler = new OsdMonitorLabeler.OsdMonitorLabeler();
|
||||
overview = new Overview.Overview();
|
||||
wm = new WindowManager.WindowManager();
|
||||
magnifier = new Magnifier.Magnifier();
|
||||
if (LoginManager.canLock())
|
||||
screenShield = new ScreenShield.ScreenShield();
|
||||
|
||||
panel = new Panel.Panel();
|
||||
legacyTray = new LegacyTray.LegacyTray();
|
||||
messageTray = new MessageTray.MessageTray();
|
||||
panel = new Panel.Panel();
|
||||
keyboard = new Keyboard.Keyboard();
|
||||
notificationDaemon = new NotificationDaemon.NotificationDaemon();
|
||||
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
|
||||
@ -205,44 +215,50 @@ function _initializeUI() {
|
||||
}
|
||||
|
||||
layoutManager.connect('startup-complete', function() {
|
||||
if (keybindingMode == Shell.KeyBindingMode.NONE) {
|
||||
keybindingMode = Shell.KeyBindingMode.NORMAL;
|
||||
if (actionMode == Shell.ActionMode.NONE) {
|
||||
actionMode = Shell.ActionMode.NORMAL;
|
||||
}
|
||||
if (screenShield) {
|
||||
screenShield.lockIfWasLocked();
|
||||
}
|
||||
if (LoginManager.haveSystemd() &&
|
||||
sessionMode.currentMode != 'gdm' &&
|
||||
if (sessionMode.currentMode != 'gdm' &&
|
||||
sessionMode.currentMode != 'initial-setup') {
|
||||
// Do not import globally to not depend
|
||||
// on systemd on non-systemd systems.
|
||||
let GSystem = imports.gi.GSystem;
|
||||
GSystem.log_structured_print('GNOME Shell started at ' + _startDate,
|
||||
['MESSAGE_ID=' + GNOMESHELL_STARTED_MESSAGE_ID]);
|
||||
} else {
|
||||
log('GNOME Shell started at ' + _startDate);
|
||||
Shell.Global.log_structured('GNOME Shell started at ' + _startDate,
|
||||
['MESSAGE_ID=' + GNOMESHELL_STARTED_MESSAGE_ID]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function _getDefaultStylesheet() {
|
||||
function _getStylesheet(name) {
|
||||
let stylesheet;
|
||||
|
||||
stylesheet = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/' + sessionMode.stylesheetName);
|
||||
stylesheet = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/' + name);
|
||||
if (stylesheet.query_exists(null))
|
||||
return stylesheet;
|
||||
|
||||
stylesheet = Gio.File.new_for_path(global.datadir + '/theme/' + sessionMode.stylesheetName);
|
||||
stylesheet = Gio.File.new_for_path(global.datadir + '/theme/' + name);
|
||||
if (stylesheet.query_exists(null))
|
||||
return stylesheet;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function _loadDefaultStylesheet() {
|
||||
if (!sessionMode.isPrimary)
|
||||
return;
|
||||
function _getDefaultStylesheet() {
|
||||
let stylesheet = null;
|
||||
let name = sessionMode.stylesheetName;
|
||||
|
||||
// Look for a high-contrast variant first when using GTK+'s HighContrast
|
||||
// theme
|
||||
if (Gtk.Settings.get_default().gtk_theme_name == 'HighContrast')
|
||||
stylesheet = _getStylesheet(name.replace('.css', '-high-contrast.css'));
|
||||
|
||||
if (stylesheet == null)
|
||||
stylesheet = _getStylesheet(sessionMode.stylesheetName);
|
||||
|
||||
return stylesheet;
|
||||
}
|
||||
|
||||
function _loadDefaultStylesheet() {
|
||||
let stylesheet = _getDefaultStylesheet();
|
||||
if (_defaultCssStylesheet && _defaultCssStylesheet.equal(stylesheet))
|
||||
return;
|
||||
@ -256,7 +272,7 @@ function _loadDefaultStylesheet() {
|
||||
*
|
||||
* Get the theme CSS file that the shell will load
|
||||
*
|
||||
* Returns: A file path that contains the theme CSS,
|
||||
* Returns: A #GFile that contains the theme CSS,
|
||||
* null if using the default
|
||||
*/
|
||||
function getThemeStylesheet() {
|
||||
@ -271,7 +287,7 @@ function getThemeStylesheet() {
|
||||
* Set the theme CSS file that the shell will load
|
||||
*/
|
||||
function setThemeStylesheet(cssStylesheet) {
|
||||
_cssStylesheet = Gio.File.new_for_path(cssStylesheet);
|
||||
_cssStylesheet = cssStylesheet ? Gio.File.new_for_path(cssStylesheet) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -356,7 +372,7 @@ function _findModal(actor) {
|
||||
* - options: Meta.ModalOptions flags to indicate that the pointer is
|
||||
* already grabbed
|
||||
*
|
||||
* - keybindingMode: used to set the current Shell.KeyBindingMode to filter
|
||||
* - actionMode: used to set the current Shell.ActionMode to filter
|
||||
* global keybindings; the default of NONE will filter
|
||||
* out all keybindings
|
||||
*
|
||||
@ -365,7 +381,7 @@ function _findModal(actor) {
|
||||
function pushModal(actor, params) {
|
||||
params = Params.parse(params, { timestamp: global.get_current_time(),
|
||||
options: 0,
|
||||
keybindingMode: Shell.KeyBindingMode.NONE });
|
||||
actionMode: Shell.ActionMode.NONE });
|
||||
|
||||
if (modalCount == 0) {
|
||||
if (!global.begin_modal(params.timestamp, params.options)) {
|
||||
@ -395,9 +411,9 @@ function pushModal(actor, params) {
|
||||
destroyId: actorDestroyId,
|
||||
prevFocus: prevFocus,
|
||||
prevFocusDestroyId: prevFocusDestroyId,
|
||||
keybindingMode: keybindingMode });
|
||||
actionMode: actionMode });
|
||||
|
||||
keybindingMode = params.keybindingMode;
|
||||
actionMode = params.actionMode;
|
||||
global.stage.set_key_focus(actor);
|
||||
return true;
|
||||
}
|
||||
@ -423,7 +439,7 @@ function popModal(actor, timestamp) {
|
||||
if (focusIndex < 0) {
|
||||
global.stage.set_key_focus(null);
|
||||
global.end_modal(timestamp);
|
||||
keybindingMode = Shell.KeyBindingMode.NORMAL;
|
||||
actionMode = Shell.ActionMode.NORMAL;
|
||||
|
||||
throw new Error('incorrect pop');
|
||||
}
|
||||
@ -436,7 +452,7 @@ function popModal(actor, timestamp) {
|
||||
if (focusIndex == modalActorFocusStack.length - 1) {
|
||||
if (record.prevFocus)
|
||||
record.prevFocus.disconnect(record.prevFocusDestroyId);
|
||||
keybindingMode = record.keybindingMode;
|
||||
actionMode = record.actionMode;
|
||||
global.stage.set_key_focus(record.prevFocus);
|
||||
} else {
|
||||
// If we have:
|
||||
@ -461,7 +477,7 @@ function popModal(actor, timestamp) {
|
||||
for (let i = modalActorFocusStack.length - 1; i > focusIndex; i--) {
|
||||
modalActorFocusStack[i].prevFocus = modalActorFocusStack[i - 1].prevFocus;
|
||||
modalActorFocusStack[i].prevFocusDestroyId = modalActorFocusStack[i - 1].prevFocusDestroyId;
|
||||
modalActorFocusStack[i].keybindingMode = modalActorFocusStack[i - 1].keybindingMode;
|
||||
modalActorFocusStack[i].actionMode = modalActorFocusStack[i - 1].actionMode;
|
||||
}
|
||||
}
|
||||
modalActorFocusStack.splice(focusIndex, 1);
|
||||
@ -472,7 +488,7 @@ function popModal(actor, timestamp) {
|
||||
layoutManager.modalEnded();
|
||||
global.end_modal(timestamp);
|
||||
Meta.enable_unredirect_for_screen(global.screen);
|
||||
keybindingMode = Shell.KeyBindingMode.NORMAL;
|
||||
actionMode = Shell.ActionMode.NORMAL;
|
||||
}
|
||||
|
||||
function createLookingGlass() {
|
||||
@ -513,6 +529,7 @@ function activateWindow(window, time, workspaceNum) {
|
||||
}
|
||||
|
||||
overview.hide();
|
||||
panel.closeCalendar();
|
||||
}
|
||||
|
||||
// TODO - replace this timeout with some system to guess when the user might
|
||||
@ -640,7 +657,7 @@ const RestartMessage = new Lang.Class({
|
||||
|
||||
_init : function(message) {
|
||||
this.parent({ shellReactive: true,
|
||||
styleClass: 'restart-message',
|
||||
styleClass: 'restart-message headline',
|
||||
shouldFadeIn: false,
|
||||
destroyOnClose: true });
|
||||
|
||||
|
2159
js/ui/messageTray.js
@ -14,7 +14,6 @@ const Atk = imports.gi.Atk;
|
||||
|
||||
const Params = imports.misc.params;
|
||||
|
||||
const Animation = imports.ui.animation;
|
||||
const Layout = imports.ui.layout;
|
||||
const Lightbox = imports.ui.lightbox;
|
||||
const Main = imports.ui.main;
|
||||
@ -23,10 +22,6 @@ const Tweener = imports.ui.tweener;
|
||||
const OPEN_AND_CLOSE_TIME = 0.1;
|
||||
const FADE_OUT_DIALOG_TIME = 1.0;
|
||||
|
||||
const WORK_SPINNER_ICON_SIZE = 24;
|
||||
const WORK_SPINNER_ANIMATION_DELAY = 1.0;
|
||||
const WORK_SPINNER_ANIMATION_TIME = 0.3;
|
||||
|
||||
const State = {
|
||||
OPENED: 0,
|
||||
CLOSED: 1,
|
||||
@ -41,14 +36,14 @@ const ModalDialog = new Lang.Class({
|
||||
_init: function(params) {
|
||||
params = Params.parse(params, { shellReactive: false,
|
||||
styleClass: null,
|
||||
keybindingMode: Shell.KeyBindingMode.SYSTEM_MODAL,
|
||||
actionMode: Shell.ActionMode.SYSTEM_MODAL,
|
||||
shouldFadeIn: true,
|
||||
shouldFadeOut: true,
|
||||
destroyOnClose: true });
|
||||
|
||||
this.state = State.CLOSED;
|
||||
this._hasModal = false;
|
||||
this._keybindingMode = params.keybindingMode;
|
||||
this._actionMode = params.actionMode;
|
||||
this._shellReactive = params.shellReactive;
|
||||
this._shouldFadeIn = params.shouldFadeIn;
|
||||
this._shouldFadeOut = params.shouldFadeOut;
|
||||
@ -79,7 +74,9 @@ const ModalDialog = new Lang.Class({
|
||||
this._group.add_actor(this._backgroundBin);
|
||||
|
||||
this.dialogLayout = new St.BoxLayout({ style_class: 'modal-dialog',
|
||||
vertical: true });
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
vertical: true });
|
||||
// modal dialogs are fixed width and grow vertically; set the request
|
||||
// mode accordingly so wrapped labels are handled correctly during
|
||||
// size requests.
|
||||
@ -100,7 +97,8 @@ const ModalDialog = new Lang.Class({
|
||||
this.backgroundStack.add_actor(this.dialogLayout);
|
||||
|
||||
|
||||
this.contentLayout = new St.BoxLayout({ vertical: true });
|
||||
this.contentLayout = new St.BoxLayout({ vertical: true,
|
||||
style_class: "modal-dialog-content-box" });
|
||||
this.dialogLayout.add(this.contentLayout,
|
||||
{ expand: true,
|
||||
x_fill: true,
|
||||
@ -108,8 +106,7 @@ const ModalDialog = new Lang.Class({
|
||||
x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.START });
|
||||
|
||||
this.buttonLayout = new St.BoxLayout({ style_class: 'modal-dialog-button-box',
|
||||
vertical: false });
|
||||
this.buttonLayout = new St.Widget ({ layout_manager: new Clutter.BoxLayout ({ homogeneous:true }) });
|
||||
this.dialogLayout.add(this.buttonLayout,
|
||||
{ x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.END });
|
||||
@ -118,8 +115,6 @@ const ModalDialog = new Lang.Class({
|
||||
this._initialKeyFocus = this.dialogLayout;
|
||||
this._initialKeyFocusDestroyId = 0;
|
||||
this._savedKeyFocus = null;
|
||||
|
||||
this._workSpinner = null;
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
@ -147,16 +142,12 @@ const ModalDialog = new Lang.Class({
|
||||
else
|
||||
x_alignment = St.Align.MIDDLE;
|
||||
|
||||
this.addButton(buttonInfo, { expand: true,
|
||||
x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: x_alignment,
|
||||
y_align: St.Align.MIDDLE });
|
||||
this.addButton(buttonInfo);
|
||||
}
|
||||
},
|
||||
|
||||
addButton: function(buttonInfo, layoutInfo) {
|
||||
let label = buttonInfo['label'];
|
||||
addButton: function(buttonInfo) {
|
||||
let label = buttonInfo['label']
|
||||
let action = buttonInfo['action'];
|
||||
let key = buttonInfo['key'];
|
||||
let isDefault = buttonInfo['default'];
|
||||
@ -170,10 +161,12 @@ const ModalDialog = new Lang.Class({
|
||||
else
|
||||
keys = [];
|
||||
|
||||
let button = new St.Button({ style_class: 'modal-dialog-button',
|
||||
let button = new St.Button({ style_class: 'modal-dialog-linked-button',
|
||||
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
label: label });
|
||||
button.connect('clicked', action);
|
||||
|
||||
@ -188,47 +181,11 @@ const ModalDialog = new Lang.Class({
|
||||
for (let i in keys)
|
||||
this._buttonKeys[keys[i]] = buttonInfo;
|
||||
|
||||
this.buttonLayout.add(button, layoutInfo);
|
||||
this.buttonLayout.add_actor(button);
|
||||
|
||||
return button;
|
||||
},
|
||||
|
||||
placeSpinner: function(layoutInfo) {
|
||||
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
|
||||
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
|
||||
this._workSpinner.actor.opacity = 0;
|
||||
this._workSpinner.actor.show();
|
||||
|
||||
this.buttonLayout.add(this._workSpinner.actor, layoutInfo);
|
||||
},
|
||||
|
||||
setWorking: function(working) {
|
||||
if (!this._workSpinner)
|
||||
return;
|
||||
|
||||
Tweener.removeTweens(this._workSpinner.actor);
|
||||
if (working) {
|
||||
this._workSpinner.play();
|
||||
Tweener.addTween(this._workSpinner.actor,
|
||||
{ opacity: 255,
|
||||
delay: WORK_SPINNER_ANIMATION_DELAY,
|
||||
time: WORK_SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear'
|
||||
});
|
||||
} else {
|
||||
Tweener.addTween(this._workSpinner.actor,
|
||||
{ opacity: 0,
|
||||
time: WORK_SPINNER_ANIMATION_TIME,
|
||||
transition: 'linear',
|
||||
onCompleteScope: this,
|
||||
onComplete: function() {
|
||||
if (this._workSpinner)
|
||||
this._workSpinner.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_onKeyPressEvent: function(object, event) {
|
||||
this._pressedKey = event.get_key_symbol();
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
@ -362,7 +319,7 @@ const ModalDialog = new Lang.Class({
|
||||
if (this._hasModal)
|
||||
return true;
|
||||
if (!Main.pushModal(this._group, { timestamp: timestamp,
|
||||
keybindingMode: this._keybindingMode }))
|
||||
actionMode: this._actionMode }))
|
||||
return false;
|
||||
|
||||
this._hasModal = true;
|
||||
|
@ -91,21 +91,6 @@ const rewriteRules = {
|
||||
]
|
||||
};
|
||||
|
||||
const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
|
||||
'bluetooth-applet': 'bluetooth',
|
||||
'gnome-volume-control-applet': 'volume', // renamed to gnome-sound-applet
|
||||
// when moved to control center
|
||||
'gnome-sound-applet': 'volume',
|
||||
'nm-applet': 'network',
|
||||
'gnome-power-manager': 'battery',
|
||||
'keyboard': 'keyboard',
|
||||
'a11y-keyboard': 'a11y',
|
||||
'kbd-scrolllock': 'keyboard',
|
||||
'kbd-numlock': 'keyboard',
|
||||
'kbd-capslock': 'keyboard',
|
||||
'ibus-ui-gtk': 'keyboard'
|
||||
};
|
||||
|
||||
const FdoNotificationDaemon = new Lang.Class({
|
||||
Name: 'FdoNotificationDaemon',
|
||||
|
||||
@ -120,13 +105,10 @@ const FdoNotificationDaemon = new Lang.Class({
|
||||
|
||||
this._nextNotificationId = 1;
|
||||
|
||||
Shell.WindowTracker.get_default().connect('notify::focus-app', Lang.bind(this, this._onFocusAppChanged));
|
||||
Main.overview.connect('hidden', Lang.bind(this, this._onFocusAppChanged));
|
||||
|
||||
this._trayManager = new Shell.TrayManager();
|
||||
this._trayIconAddedId = this._trayManager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
|
||||
this._trayIconRemovedId = this._trayManager.connect('tray-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
|
||||
this._trayManager.manage_screen(global.screen, Main.messageTray.actor);
|
||||
Shell.WindowTracker.get_default().connect('notify::focus-app',
|
||||
Lang.bind(this, this._onFocusAppChanged));
|
||||
Main.overview.connect('hidden',
|
||||
Lang.bind(this, this._onFocusAppChanged));
|
||||
},
|
||||
|
||||
_imageForNotificationData: function(hints) {
|
||||
@ -167,11 +149,10 @@ const FdoNotificationDaemon = new Lang.Class({
|
||||
return null;
|
||||
},
|
||||
|
||||
_lookupSource: function(title, pid, trayIcon) {
|
||||
_lookupSource: function(title, pid) {
|
||||
for (let i = 0; i < this._sources.length; i++) {
|
||||
let source = this._sources[i];
|
||||
if (source.pid == pid &&
|
||||
(source.initialTitle == title || source.trayIcon || trayIcon))
|
||||
if (source.pid == pid && source.initialTitle == title)
|
||||
return source;
|
||||
}
|
||||
return null;
|
||||
@ -188,7 +169,7 @@ const FdoNotificationDaemon = new Lang.Class({
|
||||
//
|
||||
// Either a pid or ndata.notification is needed to retrieve or
|
||||
// create a source.
|
||||
_getSource: function(title, pid, ndata, sender, trayIcon) {
|
||||
_getSource: function(title, pid, ndata, sender) {
|
||||
if (!pid && !(ndata && ndata.notification))
|
||||
return null;
|
||||
|
||||
@ -199,13 +180,13 @@ const FdoNotificationDaemon = new Lang.Class({
|
||||
if (ndata && ndata.notification)
|
||||
return ndata.notification.source;
|
||||
|
||||
let source = this._lookupSource(title, pid, trayIcon);
|
||||
let source = this._lookupSource(title, pid);
|
||||
if (source) {
|
||||
source.setTitle(title);
|
||||
return source;
|
||||
}
|
||||
|
||||
let source = new FdoNotificationDaemonSource(title, pid, sender, trayIcon, ndata ? ndata.hints['desktop-entry'] : null);
|
||||
let source = new FdoNotificationDaemonSource(title, pid, sender, ndata ? ndata.hints['desktop-entry'] : null);
|
||||
|
||||
this._sources.push(source);
|
||||
source.connect('destroy', Lang.bind(this, function() {
|
||||
@ -231,13 +212,10 @@ const FdoNotificationDaemon = new Lang.Class({
|
||||
|
||||
// Filter out chat, presence, calls and invitation notifications from
|
||||
// Empathy, since we handle that information from telepathyClient.js
|
||||
if (appName == 'Empathy' && (hints['category'] == 'im.received' ||
|
||||
hints['category'] == 'x-empathy.im.room-invitation' ||
|
||||
hints['category'] == 'x-empathy.call.incoming' ||
|
||||
hints['category'] == 'x-empathy.transfer.incoming' ||
|
||||
hints['category'] == 'x-empathy.im.subscription-request' ||
|
||||
hints['category'] == 'presence.online' ||
|
||||
hints['category'] == 'presence.offline')) {
|
||||
//
|
||||
// Note that empathy uses im.received for one to one chats and
|
||||
// x-empathy.im.mentioned for multi-user, so we're good here
|
||||
if (appName == 'Empathy' && hints['category'] == 'im.received') {
|
||||
// Ignore replacesId since we already sent back a
|
||||
// NotificationClosed for that id.
|
||||
id = this._nextNotificationId++;
|
||||
@ -330,19 +308,6 @@ const FdoNotificationDaemon = new Lang.Class({
|
||||
return invocation.return_value(GLib.Variant.new('(u)', [id]));
|
||||
},
|
||||
|
||||
_makeButton: function(id, label, useActionIcons) {
|
||||
let button = new St.Button({ can_focus: true });
|
||||
let iconName = id.endsWith('-symbolic') ? id : id + '-symbolic';
|
||||
if (useActionIcons && Gtk.IconTheme.get_default().has_icon(iconName)) {
|
||||
button.add_style_class_name('notification-icon-button');
|
||||
button.child = new St.Icon({ icon_name: iconName });
|
||||
} else {
|
||||
button.add_style_class_name('notification-button');
|
||||
button.label = label;
|
||||
}
|
||||
return button;
|
||||
},
|
||||
|
||||
_notifyForSource: function(source, ndata) {
|
||||
let [id, icon, summary, body, actions, hints, notification] =
|
||||
[ndata.id, ndata.icon, ndata.summary, ndata.body,
|
||||
@ -370,26 +335,17 @@ const FdoNotificationDaemon = new Lang.Class({
|
||||
}));
|
||||
}
|
||||
|
||||
// Mark music notifications so they can be shown in the screen shield
|
||||
notification.isMusic = (ndata.hints['category'] == 'x-gnome.music');
|
||||
|
||||
let gicon = this._iconForNotificationData(icon, hints);
|
||||
let gimage = this._imageForNotificationData(hints);
|
||||
|
||||
let image = null;
|
||||
|
||||
// If an icon is not specified, we use 'image-data' or 'image-path' hint for an icon
|
||||
// and don't show a large image. There are currently many applications that use
|
||||
// notify_notification_set_icon_from_pixbuf() from libnotify, which in turn sets
|
||||
// the 'image-data' hint. These applications don't typically pass in 'app_icon'
|
||||
// argument to Notify() and actually expect the pixbuf to be shown as an icon.
|
||||
// So the logic here does the right thing for this case. If both an icon and either
|
||||
// one of 'image-data' or 'image-path' are specified, we show both an icon and
|
||||
// a large image.
|
||||
if (gicon && gimage)
|
||||
image = new St.Icon({ gicon: gimage,
|
||||
icon_size: notification.IMAGE_SIZE });
|
||||
else if (!gicon && gimage)
|
||||
// one of 'image-data' or 'image-path' are specified, the icon and takes precedence.
|
||||
if (!gicon && gimage)
|
||||
gicon = gimage;
|
||||
else if (!gicon)
|
||||
gicon = this._fallbackIconForNotificationData(hints);
|
||||
@ -399,31 +355,27 @@ const FdoNotificationDaemon = new Lang.Class({
|
||||
clear: true,
|
||||
soundFile: hints['sound-file'],
|
||||
soundName: hints['sound-name'] });
|
||||
notification.setImage(image);
|
||||
|
||||
let hasDefaultAction = false;
|
||||
|
||||
if (actions.length) {
|
||||
let useActionIcons = (hints['action-icons'] == true);
|
||||
|
||||
for (let i = 0; i < actions.length - 1; i += 2) {
|
||||
let [actionId, label] = [actions[i], actions[i+1]];
|
||||
if (actionId == 'default') {
|
||||
if (actionId == 'default')
|
||||
hasDefaultAction = true;
|
||||
} else {
|
||||
notification.addButton(this._makeButton(actionId, label, useActionIcons), Lang.bind(this, function() {
|
||||
else
|
||||
notification.addAction(label, Lang.bind(this, function() {
|
||||
this._emitActionInvoked(ndata.id, actionId);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasDefaultAction) {
|
||||
notification.connect('clicked', Lang.bind(this, function() {
|
||||
notification.connect('activated', Lang.bind(this, function() {
|
||||
this._emitActionInvoked(ndata.id, 'default');
|
||||
}));
|
||||
} else {
|
||||
notification.connect('clicked', Lang.bind(this, function() {
|
||||
notification.connect('activated', Lang.bind(this, function() {
|
||||
source.open();
|
||||
}));
|
||||
}
|
||||
@ -460,7 +412,7 @@ const FdoNotificationDaemon = new Lang.Class({
|
||||
GetCapabilities: function() {
|
||||
return [
|
||||
'actions',
|
||||
'action-icons',
|
||||
// 'action-icons',
|
||||
'body',
|
||||
// 'body-hyperlinks',
|
||||
// 'body-images',
|
||||
@ -503,20 +455,6 @@ const FdoNotificationDaemon = new Lang.Class({
|
||||
_emitActionInvoked: function(id, action) {
|
||||
this._dbusImpl.emit_signal('ActionInvoked',
|
||||
GLib.Variant.new('(us)', [id, action]));
|
||||
},
|
||||
|
||||
_onTrayIconAdded: function(o, icon) {
|
||||
let wmClass = icon.wm_class ? icon.wm_class.toLowerCase() : '';
|
||||
if (STANDARD_TRAY_ICON_IMPLEMENTATIONS[wmClass] !== undefined)
|
||||
return;
|
||||
|
||||
let source = this._getSource(icon.title || icon.wm_class || C_("program", "Unknown"), icon.pid, null, null, icon);
|
||||
},
|
||||
|
||||
_onTrayIconRemoved: function(o, icon) {
|
||||
let source = this._lookupSource(null, icon.pid, true);
|
||||
if (source)
|
||||
source.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
@ -524,10 +462,9 @@ const FdoNotificationDaemonSource = new Lang.Class({
|
||||
Name: 'FdoNotificationDaemonSource',
|
||||
Extends: MessageTray.Source,
|
||||
|
||||
_init: function(title, pid, sender, trayIcon, appId) {
|
||||
_init: function(title, pid, sender, appId) {
|
||||
// Need to set the app before chaining up, so
|
||||
// methods called from the parent constructor can find it
|
||||
this.trayIcon = trayIcon;
|
||||
this.pid = pid;
|
||||
this.app = this._getApp(appId);
|
||||
|
||||
@ -547,12 +484,6 @@ const FdoNotificationDaemonSource = new Lang.Class({
|
||||
Lang.bind(this, this._onNameVanished));
|
||||
else
|
||||
this._nameWatcherId = 0;
|
||||
|
||||
if (this.trayIcon) {
|
||||
// Try again finding the app, using the WM_CLASS from the tray icon
|
||||
this._setSummaryIcon(this.trayIcon);
|
||||
this.useNotificationIcon = false;
|
||||
}
|
||||
},
|
||||
|
||||
_createPolicy: function() {
|
||||
@ -570,15 +501,14 @@ const FdoNotificationDaemonSource = new Lang.Class({
|
||||
// of which аre removed from DBus immediately.
|
||||
// Sender being removed from DBus would normally result in a tray icon being removed,
|
||||
// so allow the code path that handles the tray icon being removed to handle that case.
|
||||
if (!this.trayIcon && this.app)
|
||||
if (this.app)
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
processNotification: function(notification, gicon) {
|
||||
if (gicon)
|
||||
this._gicon = gicon;
|
||||
if (!this.trayIcon)
|
||||
this.iconUpdated();
|
||||
this.iconUpdated();
|
||||
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
if (notification.resident && this.app && tracker.focus_app == this.app)
|
||||
@ -587,29 +517,6 @@ const FdoNotificationDaemonSource = new Lang.Class({
|
||||
this.notify(notification);
|
||||
},
|
||||
|
||||
handleSummaryClick: function(button) {
|
||||
if (!this.trayIcon)
|
||||
return false;
|
||||
|
||||
let event = Clutter.get_current_event();
|
||||
|
||||
// Left clicks are passed through only where there aren't unacknowledged
|
||||
// notifications, so it possible to open them in summary mode; right
|
||||
// clicks are always forwarded, as the right click menu is not useful for
|
||||
// tray icons
|
||||
if (button == 1 &&
|
||||
this.notifications.length > 0)
|
||||
return false;
|
||||
|
||||
let id = global.stage.connect('deactivate', Lang.bind(this, function () {
|
||||
global.stage.disconnect(id);
|
||||
this.trayIcon.click(event);
|
||||
}));
|
||||
|
||||
Main.overview.hide();
|
||||
return true;
|
||||
},
|
||||
|
||||
_getApp: function(appId) {
|
||||
let app;
|
||||
|
||||
@ -617,16 +524,6 @@ const FdoNotificationDaemonSource = new Lang.Class({
|
||||
if (app != null)
|
||||
return app;
|
||||
|
||||
if (this.trayIcon) {
|
||||
app = Shell.AppSystem.get_default().lookup_startup_wmclass(this.trayIcon.wm_class);
|
||||
if (app != null)
|
||||
return app;
|
||||
|
||||
app = Shell.AppSystem.get_default().lookup_desktop_wmclass(this.trayIcon.wm_class);
|
||||
if (app != null)
|
||||
return app;
|
||||
}
|
||||
|
||||
if (appId) {
|
||||
app = Shell.AppSystem.get_default().lookup_app(appId + '.desktop');
|
||||
if (app != null)
|
||||
@ -651,17 +548,13 @@ const FdoNotificationDaemonSource = new Lang.Class({
|
||||
this.destroyNonResidentNotifications();
|
||||
},
|
||||
|
||||
_lastNotificationRemoved: function() {
|
||||
if (!this.trayIcon)
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
openApp: function() {
|
||||
if (this.app == null)
|
||||
return;
|
||||
|
||||
this.app.activate();
|
||||
Main.overview.hide();
|
||||
Main.panel.closeCalendar();
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
@ -674,11 +567,7 @@ const FdoNotificationDaemonSource = new Lang.Class({
|
||||
},
|
||||
|
||||
createIcon: function(size) {
|
||||
if (this.trayIcon) {
|
||||
return new Clutter.Clone({ width: size,
|
||||
height: size,
|
||||
source: this.trayIcon });
|
||||
} else if (this.app) {
|
||||
if (this.app) {
|
||||
return this.app.create_icon_texture(size);
|
||||
} else if (this._gicon) {
|
||||
return new St.Icon({ gicon: this._gicon,
|
||||
@ -753,7 +642,7 @@ const GtkNotificationDaemonNotification = new Lang.Class({
|
||||
this._activateAction(action.unpack(), actionTarget);
|
||||
},
|
||||
|
||||
_onClicked: function() {
|
||||
activate: function() {
|
||||
this._activateAction(this._defaultAction, this._defaultActionTarget);
|
||||
this.parent();
|
||||
},
|
||||
@ -820,11 +709,17 @@ const GtkNotificationDaemonAppSource = new Lang.Class({
|
||||
activateAction: function(actionId, target) {
|
||||
let app = this._createApp();
|
||||
app.ActivateActionRemote(actionId, target ? [target] : [], getPlatformData());
|
||||
|
||||
Main.overview.hide();
|
||||
Main.panel.closeCalendar();
|
||||
},
|
||||
|
||||
open: function() {
|
||||
let app = this._createApp();
|
||||
app.ActivateRemote(getPlatformData());
|
||||
|
||||
Main.overview.hide();
|
||||
Main.panel.closeCalendar();
|
||||
},
|
||||
|
||||
addNotification: function(notificationId, notificationParams, showBanner) {
|
||||
|
129
js/ui/osdMonitorLabeler.js
Normal file
@ -0,0 +1,129 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Meta = imports.gi.Meta;
|
||||
|
||||
const FADE_TIME = 0.1;
|
||||
|
||||
const OsdMonitorLabel = new Lang.Class({
|
||||
Name: 'OsdMonitorLabel',
|
||||
|
||||
_init: function(monitor, label) {
|
||||
this._actor = new St.Widget({ x_expand: true,
|
||||
y_expand: true });
|
||||
|
||||
this._monitor = monitor;
|
||||
|
||||
this._box = new St.BoxLayout({ style_class: 'osd-window',
|
||||
vertical: true });
|
||||
this._actor.add_actor(this._box);
|
||||
|
||||
this._label = new St.Label({ style_class: 'osd-monitor-label',
|
||||
text: label });
|
||||
this._box.add(this._label);
|
||||
|
||||
Main.uiGroup.add_child(this._actor);
|
||||
Main.uiGroup.set_child_above_sibling(this._actor, null);
|
||||
this._position();
|
||||
|
||||
Meta.disable_unredirect_for_screen(global.screen);
|
||||
},
|
||||
|
||||
_position: function() {
|
||||
let workArea = Main.layoutManager.getWorkAreaForMonitor(this._monitor);
|
||||
|
||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
||||
this._box.x = workArea.x + (workArea.width - this._box.width);
|
||||
else
|
||||
this._box.x = workArea.x;
|
||||
|
||||
this._box.y = workArea.y;
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this._actor.destroy();
|
||||
Meta.enable_unredirect_for_screen(global.screen);
|
||||
}
|
||||
});
|
||||
|
||||
const OsdMonitorLabeler = new Lang.Class({
|
||||
Name: 'OsdMonitorLabeler',
|
||||
|
||||
_init: function() {
|
||||
this._monitorManager = Meta.MonitorManager.get();
|
||||
this._client = null;
|
||||
this._clientWatchId = 0;
|
||||
this._osdLabels = [];
|
||||
this._monitorLabels = null;
|
||||
Main.layoutManager.connect('monitors-changed',
|
||||
Lang.bind(this, this._reset));
|
||||
this._reset();
|
||||
},
|
||||
|
||||
_reset: function() {
|
||||
for (let i in this._osdLabels)
|
||||
this._osdLabels[i].destroy();
|
||||
this._osdLabels = [];
|
||||
this._monitorLabels = new Map();
|
||||
let monitors = Main.layoutManager.monitors;
|
||||
for (let i in monitors)
|
||||
this._monitorLabels.set(monitors[i].index, []);
|
||||
},
|
||||
|
||||
_trackClient: function(client) {
|
||||
if (this._client)
|
||||
return (this._client == client);
|
||||
|
||||
this._client = client;
|
||||
this._clientWatchId = Gio.bus_watch_name(Gio.BusType.SESSION, client, 0, null,
|
||||
Lang.bind(this, function(c, name) {
|
||||
this.hide(name);
|
||||
}));
|
||||
return true;
|
||||
},
|
||||
|
||||
_untrackClient: function(client) {
|
||||
if (!this._client || this._client != client)
|
||||
return false;
|
||||
|
||||
Gio.bus_unwatch_name(this._clientWatchId);
|
||||
this._clientWatchId = 0;
|
||||
this._client = null;
|
||||
return true;
|
||||
},
|
||||
|
||||
show: function(client, params) {
|
||||
if (!this._trackClient(client))
|
||||
return;
|
||||
|
||||
this._reset();
|
||||
|
||||
for (let id in params) {
|
||||
let monitor = this._monitorManager.get_monitor_for_output(id);
|
||||
if (monitor == -1)
|
||||
continue;
|
||||
this._monitorLabels.get(monitor).push(params[id].deep_unpack());
|
||||
}
|
||||
|
||||
// In mirrored display setups, more than one physical outputs
|
||||
// might be showing the same logical monitor. In that case, we
|
||||
// join each output's labels on the same OSD widget.
|
||||
for (let [monitor, labels] of this._monitorLabels.entries()) {
|
||||
labels.sort();
|
||||
this._osdLabels.push(new OsdMonitorLabel(monitor, labels.join(' ')));
|
||||
}
|
||||
},
|
||||
|
||||
hide: function(client) {
|
||||
if (!this._untrackClient(client))
|
||||
return;
|
||||
|
||||
this._reset();
|
||||
}
|
||||
});
|
@ -107,13 +107,6 @@ const Overview = new Lang.Class({
|
||||
|
||||
this._overviewCreated = true;
|
||||
|
||||
// The main Background actors are inside global.window_group which are
|
||||
// hidden when displaying the overview, so we create a new
|
||||
// one. Instances of this class share a single CoglTexture behind the
|
||||
// scenes which allows us to show the background with different
|
||||
// rendering options without duplicating the texture data.
|
||||
let monitor = Main.layoutManager.primaryMonitor;
|
||||
|
||||
let layout = new Clutter.BinLayout();
|
||||
this._stack = new Clutter.Actor({ layout_manager: layout });
|
||||
this._stack.add_constraint(new LayoutManager.MonitorConstraint({ primary: true }));
|
||||
@ -128,6 +121,11 @@ const Overview = new Lang.Class({
|
||||
y_expand: true });
|
||||
this._overview._delegate = this;
|
||||
|
||||
// The main Background actors are inside global.window_group which are
|
||||
// hidden when displaying the overview, so we create a new
|
||||
// one. Instances of this class share a single CoglTexture behind the
|
||||
// scenes which allows us to show the background with different
|
||||
// rendering options without duplicating the texture data.
|
||||
this._backgroundGroup = new Meta.BackgroundGroup();
|
||||
Main.layoutManager.overviewGroup.add_child(this._backgroundGroup);
|
||||
this._bgManagers = [];
|
||||
@ -259,8 +257,6 @@ const Overview = new Lang.Class({
|
||||
this._overview.add(this._controls.actor, { y_fill: true, expand: true });
|
||||
this._controls.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
|
||||
|
||||
this._stack.add_actor(this._controls.indicatorActor);
|
||||
|
||||
// TODO - recalculate everything when desktop size changes
|
||||
this.dashIconSize = this._dash.iconSize;
|
||||
this._dash.connect('icon-size-changed',
|
||||
@ -509,7 +505,7 @@ const Overview = new Lang.Class({
|
||||
if (shouldBeModal) {
|
||||
if (!this._modal) {
|
||||
if (Main.pushModal(this._overview,
|
||||
{ keybindingMode: Shell.KeyBindingMode.OVERVIEW })) {
|
||||
{ actionMode: Shell.ActionMode.OVERVIEW })) {
|
||||
this._modal = true;
|
||||
} else {
|
||||
this.hide();
|
||||
@ -605,9 +601,9 @@ const Overview = new Lang.Class({
|
||||
return;
|
||||
}
|
||||
|
||||
this._animateNotVisible();
|
||||
|
||||
this._shown = false;
|
||||
|
||||
this._animateNotVisible();
|
||||
this._syncGrab();
|
||||
},
|
||||
|
||||
|
@ -391,111 +391,6 @@ const DashSpacer = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
const MessagesIndicator = new Lang.Class({
|
||||
Name: 'MessagesIndicator',
|
||||
|
||||
_init: function(viewSelector) {
|
||||
this._count = 0;
|
||||
this._sources = [];
|
||||
this._viewSelector = viewSelector;
|
||||
|
||||
this._container = new St.BoxLayout({ style_class: 'messages-indicator-contents',
|
||||
reactive: true,
|
||||
track_hover: true,
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
x_align: Clutter.ActorAlign.CENTER });
|
||||
|
||||
this._icon = new St.Icon({ icon_name: 'user-idle-symbolic',
|
||||
icon_size: 16 });
|
||||
this._container.add_actor(this._icon);
|
||||
|
||||
this._label = new St.Label();
|
||||
this._container.add_actor(this._label);
|
||||
|
||||
this._highlight = new St.Widget({ style_class: 'messages-indicator-highlight',
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
y_align: Clutter.ActorAlign.END,
|
||||
visible: false });
|
||||
|
||||
this._container.connect('notify::hover', Lang.bind(this,
|
||||
function() {
|
||||
this._highlight.visible = this._container.hover;
|
||||
}));
|
||||
|
||||
let clickAction = new Clutter.ClickAction();
|
||||
this._container.add_action(clickAction);
|
||||
clickAction.connect('clicked', Lang.bind(this,
|
||||
function() {
|
||||
Main.messageTray.openTray();
|
||||
}));
|
||||
|
||||
Main.messageTray.connect('showing', Lang.bind(this,
|
||||
function() {
|
||||
this._highlight.visible = false;
|
||||
this._container.hover = false;
|
||||
}));
|
||||
|
||||
let layout = new Clutter.BinLayout();
|
||||
this.actor = new St.Widget({ layout_manager: layout,
|
||||
style_class: 'messages-indicator',
|
||||
y_expand: true,
|
||||
y_align: Clutter.ActorAlign.END,
|
||||
visible: false });
|
||||
this.actor.add_actor(this._container);
|
||||
this.actor.add_actor(this._highlight);
|
||||
|
||||
Main.messageTray.connect('source-added', Lang.bind(this, this._onSourceAdded));
|
||||
Main.messageTray.connect('source-removed', Lang.bind(this, this._onSourceRemoved));
|
||||
|
||||
let sources = Main.messageTray.getSources();
|
||||
sources.forEach(Lang.bind(this, function(source) { this._onSourceAdded(null, source); }));
|
||||
|
||||
this._viewSelector.connect('page-changed', Lang.bind(this, this._updateVisibility));
|
||||
Main.overview.connect('showing', Lang.bind(this, this._updateVisibility));
|
||||
},
|
||||
|
||||
_onSourceAdded: function(tray, source) {
|
||||
if (source.trayIcon)
|
||||
return;
|
||||
|
||||
source.connect('count-updated', Lang.bind(this, this._updateCount));
|
||||
this._sources.push(source);
|
||||
this._updateCount();
|
||||
},
|
||||
|
||||
_onSourceRemoved: function(tray, source) {
|
||||
this._sources.splice(this._sources.indexOf(source), 1);
|
||||
this._updateCount();
|
||||
},
|
||||
|
||||
_updateCount: function() {
|
||||
let count = 0;
|
||||
let hasChats = false;
|
||||
this._sources.forEach(Lang.bind(this,
|
||||
function(source) {
|
||||
count += source.indicatorCount;
|
||||
hasChats |= source.isChat;
|
||||
}));
|
||||
|
||||
this._count = count;
|
||||
this._label.text = ngettext("%d new message",
|
||||
"%d new messages",
|
||||
count).format(count);
|
||||
|
||||
this._icon.visible = hasChats;
|
||||
this._updateVisibility();
|
||||
},
|
||||
|
||||
_updateVisibility: function() {
|
||||
let activePage = this._viewSelector.getActivePage();
|
||||
let visible = ((this._count > 0) && (activePage == ViewSelector.ViewPage.WINDOWS));
|
||||
|
||||
this.actor.visible = visible;
|
||||
}
|
||||
});
|
||||
|
||||
const ControlsLayout = new Lang.Class({
|
||||
Name: 'ControlsLayout',
|
||||
Extends: Clutter.BinLayout,
|
||||
@ -524,9 +419,6 @@ const ControlsManager = new Lang.Class({
|
||||
this.viewSelector.connect('page-changed', Lang.bind(this, this._setVisibility));
|
||||
this.viewSelector.connect('page-empty', Lang.bind(this, this._onPageEmpty));
|
||||
|
||||
this._indicator = new MessagesIndicator(this.viewSelector);
|
||||
this.indicatorActor = this._indicator.actor;
|
||||
|
||||
let layout = new ControlsLayout();
|
||||
this.actor = new St.Widget({ layout_manager: layout,
|
||||
reactive: true,
|
||||
|
208
js/ui/panel.js
@ -25,11 +25,12 @@ const RemoteMenu = imports.ui.remoteMenu;
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const PANEL_ICON_SIZE = 24;
|
||||
const PANEL_ICON_SIZE = 16;
|
||||
const APP_MENU_ICON_MARGIN = 0;
|
||||
|
||||
const BUTTON_DND_ACTIVATION_TIMEOUT = 250;
|
||||
|
||||
const SPINNER_ANIMATION_TIME = 0.2;
|
||||
const SPINNER_ANIMATION_TIME = 1.0;
|
||||
|
||||
// To make sure the panel corners blend nicely with the panel,
|
||||
// we draw background and borders the same way, e.g. drawing
|
||||
@ -74,90 +75,6 @@ function _unpremultiply(color) {
|
||||
blue: blue, alpha: color.alpha });
|
||||
};
|
||||
|
||||
const TextShadower = new Lang.Class({
|
||||
Name: 'TextShadower',
|
||||
|
||||
_init: function() {
|
||||
this.actor = new Shell.GenericContainer();
|
||||
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||
|
||||
this._label = new St.Label();
|
||||
this.actor.add_actor(this._label);
|
||||
for (let i = 0; i < 4; i++) {
|
||||
let actor = new St.Label({ style_class: 'label-shadow' });
|
||||
actor.clutter_text.ellipsize = Pango.EllipsizeMode.END;
|
||||
this.actor.add_actor(actor);
|
||||
}
|
||||
this._label.raise_top();
|
||||
},
|
||||
|
||||
setText: function(text) {
|
||||
let children = this.actor.get_children();
|
||||
for (let i = 0; i < children.length; i++)
|
||||
children[i].set_text(text);
|
||||
},
|
||||
|
||||
_getPreferredWidth: function(actor, forHeight, alloc) {
|
||||
let [minWidth, natWidth] = this._label.get_preferred_width(forHeight);
|
||||
alloc.min_size = minWidth + 2;
|
||||
alloc.natural_size = natWidth + 2;
|
||||
},
|
||||
|
||||
_getPreferredHeight: function(actor, forWidth, alloc) {
|
||||
let [minHeight, natHeight] = this._label.get_preferred_height(forWidth);
|
||||
alloc.min_size = minHeight + 2;
|
||||
alloc.natural_size = natHeight + 2;
|
||||
},
|
||||
|
||||
_allocate: function(actor, box, flags) {
|
||||
let children = this.actor.get_children();
|
||||
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let availHeight = box.y2 - box.y1;
|
||||
|
||||
let [minChildWidth, minChildHeight, natChildWidth, natChildHeight] =
|
||||
this._label.get_preferred_size();
|
||||
|
||||
let childWidth = Math.min(natChildWidth, availWidth - 2);
|
||||
let childHeight = Math.min(natChildHeight, availHeight - 2);
|
||||
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let child = children[i];
|
||||
let childBox = new Clutter.ActorBox();
|
||||
// The order of the labels here is arbitrary, except
|
||||
// we know the "real" label is at the end because Clutter.Actor
|
||||
// sorts by Z order
|
||||
switch (i) {
|
||||
case 0: // top
|
||||
childBox.x1 = 1;
|
||||
childBox.y1 = 0;
|
||||
break;
|
||||
case 1: // right
|
||||
childBox.x1 = 2;
|
||||
childBox.y1 = 1;
|
||||
break;
|
||||
case 2: // bottom
|
||||
childBox.x1 = 1;
|
||||
childBox.y1 = 2;
|
||||
break;
|
||||
case 3: // left
|
||||
childBox.x1 = 0;
|
||||
childBox.y1 = 1;
|
||||
break;
|
||||
case 4: // center
|
||||
childBox.x1 = 1;
|
||||
childBox.y1 = 1;
|
||||
break;
|
||||
}
|
||||
childBox.x2 = childBox.x1 + childWidth;
|
||||
childBox.y2 = childBox.y1 + childHeight;
|
||||
child.allocate(childBox, flags);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* AppMenuButton:
|
||||
*
|
||||
@ -181,6 +98,7 @@ const AppMenuButton = new Lang.Class({
|
||||
this._targetApp = null;
|
||||
this._appMenuNotifyId = 0;
|
||||
this._actionGroupNotifyId = 0;
|
||||
this._busyNotifyId = 0;
|
||||
|
||||
let bin = new St.Bin({ name: 'appMenu' });
|
||||
bin.connect('style-changed', Lang.bind(this, this._onStyleChanged));
|
||||
@ -189,28 +107,22 @@ const AppMenuButton = new Lang.Class({
|
||||
this.actor.bind_property("reactive", this.actor, "can-focus", 0);
|
||||
this.actor.reactive = false;
|
||||
|
||||
this._container = St.BoxLayout({ style_class: 'panel-status-menu-box' });
|
||||
this._container = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
|
||||
bin.set_child(this._container);
|
||||
|
||||
let textureCache = St.TextureCache.get_default();
|
||||
textureCache.connect('icon-theme-changed',
|
||||
Lang.bind(this, this._onIconThemeChanged));
|
||||
|
||||
this._iconBox = new Shell.Slicer({ name: 'appMenuIcon' });
|
||||
this._iconBox.connect('style-changed',
|
||||
Lang.bind(this, this._onIconBoxStyleChanged));
|
||||
this._iconBox.connect('notify::allocation',
|
||||
Lang.bind(this, this._updateIconBoxClip));
|
||||
this._iconBox = new St.Bin({ style_class: 'app-menu-icon' });
|
||||
this._container.add_actor(this._iconBox);
|
||||
|
||||
this._label = new TextShadower();
|
||||
this._label.actor.y_align = Clutter.ActorAlign.CENTER;
|
||||
this._container.add_actor(this._label.actor);
|
||||
this._label = new St.Label({ y_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
this._container.add_actor(this._label);
|
||||
this._arrow = PopupMenu.arrowIcon(St.Side.BOTTOM);
|
||||
this._container.add_actor(this._arrow);
|
||||
|
||||
this._iconBottomClip = 0;
|
||||
|
||||
this._visible = !Main.overview.visible;
|
||||
if (!this._visible)
|
||||
this.actor.hide();
|
||||
@ -275,17 +187,11 @@ const AppMenuButton = new Lang.Class({
|
||||
this._spinner.actor.hide();
|
||||
},
|
||||
|
||||
_onIconBoxStyleChanged: function() {
|
||||
let node = this._iconBox.get_theme_node();
|
||||
this._iconBottomClip = node.get_length('app-icon-bottom-clip');
|
||||
this._updateIconBoxClip();
|
||||
},
|
||||
|
||||
_syncIcon: function() {
|
||||
if (!this._targetApp)
|
||||
return;
|
||||
|
||||
let icon = this._targetApp.create_icon_texture(2 * PANEL_ICON_SIZE);
|
||||
let icon = this._targetApp.create_icon_texture(PANEL_ICON_SIZE - APP_MENU_ICON_MARGIN);
|
||||
this._iconBox.set_child(icon);
|
||||
},
|
||||
|
||||
@ -296,16 +202,6 @@ const AppMenuButton = new Lang.Class({
|
||||
this._syncIcon();
|
||||
},
|
||||
|
||||
_updateIconBoxClip: function() {
|
||||
let allocation = this._iconBox.allocation;
|
||||
if (this._iconBottomClip > 0)
|
||||
this._iconBox.set_clip(0, 0,
|
||||
allocation.x2 - allocation.x1,
|
||||
allocation.y2 - allocation.y1 - this._iconBottomClip);
|
||||
else
|
||||
this._iconBox.remove_clip();
|
||||
},
|
||||
|
||||
stopAnimation: function() {
|
||||
if (this._stop)
|
||||
return;
|
||||
@ -393,13 +289,18 @@ const AppMenuButton = new Lang.Class({
|
||||
this._targetApp.disconnect(this._actionGroupNotifyId);
|
||||
this._actionGroupNotifyId = 0;
|
||||
}
|
||||
if (this._busyNotifyId) {
|
||||
this._targetApp.disconnect(this._busyNotifyId);
|
||||
this._busyNotifyId = 0;
|
||||
}
|
||||
|
||||
this._targetApp = targetApp;
|
||||
|
||||
if (this._targetApp) {
|
||||
this._appMenuNotifyId = this._targetApp.connect('notify::menu', Lang.bind(this, this._sync));
|
||||
this._actionGroupNotifyId = this._targetApp.connect('notify::action-group', Lang.bind(this, this._sync));
|
||||
this._label.setText(this._targetApp.get_name());
|
||||
this._busyNotifyId = this._targetApp.connect('notify::busy', Lang.bind(this, this._sync));
|
||||
this._label.set_text(this._targetApp.get_name());
|
||||
this.actor.set_accessible_name(this._targetApp.get_name());
|
||||
}
|
||||
}
|
||||
@ -412,7 +313,7 @@ const AppMenuButton = new Lang.Class({
|
||||
|
||||
let isBusy = (this._targetApp != null &&
|
||||
(this._targetApp.get_state() == Shell.AppState.STARTING ||
|
||||
this._targetApp.get_state() == Shell.AppState.BUSY));
|
||||
this._targetApp.get_busy()));
|
||||
if (isBusy)
|
||||
this.startAnimation();
|
||||
else
|
||||
@ -750,7 +651,7 @@ const AggregateMenu = new Lang.Class({
|
||||
this.menu.actor.add_style_class_name('aggregate-menu');
|
||||
|
||||
this._indicators = new St.BoxLayout({ style_class: 'panel-status-indicators-box' });
|
||||
this.actor.add_actor(this._indicators);
|
||||
this.actor.add_child(this._indicators);
|
||||
|
||||
if (Config.HAVE_NETWORKMANAGER) {
|
||||
this._network = new imports.ui.status.network.NMApplet();
|
||||
@ -796,7 +697,6 @@ const AggregateMenu = new Lang.Class({
|
||||
this.menu.addMenuItem(this._location.menu);
|
||||
this.menu.addMenuItem(this._rfkill.menu);
|
||||
this.menu.addMenuItem(this._power.menu);
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this.menu.addMenuItem(this._system.menu);
|
||||
},
|
||||
});
|
||||
@ -823,7 +723,7 @@ const Panel = new Lang.Class({
|
||||
|
||||
this.statusArea = {};
|
||||
|
||||
this.menuManager = new PopupMenu.PopupMenuManager(this, { keybindingMode: Shell.KeyBindingMode.TOPBAR_POPUP });
|
||||
this.menuManager = new PopupMenu.PopupMenuManager(this);
|
||||
|
||||
this._leftBox = new St.BoxLayout({ name: 'panelLeft' });
|
||||
this.actor.add_actor(this._leftBox);
|
||||
@ -851,7 +751,7 @@ const Panel = new Lang.Class({
|
||||
}));
|
||||
|
||||
Main.layoutManager.panelBox.add(this.actor);
|
||||
Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'emblem-system-symbolic',
|
||||
Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'focus-top-bar-symbolic',
|
||||
{ sortGroup: CtrlAltTab.SortGroup.TOP });
|
||||
|
||||
Main.sessionMode.connect('updated', Lang.bind(this, this._updatePanel));
|
||||
@ -977,9 +877,8 @@ const Panel = new Lang.Class({
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
toggleAppMenu: function() {
|
||||
let indicator = this.statusArea.appMenu;
|
||||
if (!indicator) // appMenu not supported by current session mode
|
||||
_toggleMenu: function(indicator) {
|
||||
if (!indicator) // menu not supported by current session mode
|
||||
return;
|
||||
|
||||
let menu = indicator.menu;
|
||||
@ -991,6 +890,26 @@ const Panel = new Lang.Class({
|
||||
menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
},
|
||||
|
||||
toggleAppMenu: function() {
|
||||
this._toggleMenu(this.statusArea.appMenu);
|
||||
},
|
||||
|
||||
toggleCalendar: function() {
|
||||
this._toggleMenu(this.statusArea.dateMenu);
|
||||
},
|
||||
|
||||
closeCalendar: function() {
|
||||
let indicator = this.statusArea.dateMenu;
|
||||
if (!indicator) // calendar not supported by current session mode
|
||||
return;
|
||||
|
||||
let menu = indicator.menu;
|
||||
if (!indicator.actor.reactive)
|
||||
return;
|
||||
|
||||
menu.close();
|
||||
},
|
||||
|
||||
set boxOpacity(value) {
|
||||
let isReactive = value > 0;
|
||||
|
||||
@ -1013,6 +932,14 @@ const Panel = new Lang.Class({
|
||||
this._updateBox(panel.center, this._centerBox);
|
||||
this._updateBox(panel.right, this._rightBox);
|
||||
|
||||
if (panel.left.indexOf('dateMenu') != -1)
|
||||
Main.messageTray.bannerAlignment = Clutter.ActorAlign.START;
|
||||
else if (panel.right.indexOf('dateMenu') != -1)
|
||||
Main.messageTray.bannerAlignment = Clutter.ActorAlign.END;
|
||||
// Default to center if there is no dateMenu
|
||||
else
|
||||
Main.messageTray.bannerAlignment = Clutter.ActorAlign.CENTER;
|
||||
|
||||
if (this._sessionStyle)
|
||||
this._removeStyleClassName(this._sessionStyle);
|
||||
|
||||
@ -1036,7 +963,7 @@ const Panel = new Lang.Class({
|
||||
continue;
|
||||
if (indicator.menu)
|
||||
indicator.menu.close();
|
||||
indicator.actor.hide();
|
||||
indicator.container.hide();
|
||||
}
|
||||
},
|
||||
|
||||
@ -1068,15 +995,25 @@ const Panel = new Lang.Class({
|
||||
},
|
||||
|
||||
_addToPanelBox: function(role, indicator, position, box) {
|
||||
indicator.actor.show();
|
||||
box.insert_child_at_index(indicator.actor, position);
|
||||
let container = indicator.container;
|
||||
container.show();
|
||||
|
||||
let parent = container.get_parent();
|
||||
if (parent)
|
||||
parent.remove_actor(container);
|
||||
|
||||
|
||||
box.insert_child_at_index(container, position);
|
||||
if (indicator.menu)
|
||||
this.menuManager.addMenu(indicator.menu);
|
||||
this.statusArea[role] = indicator;
|
||||
let destroyId = indicator.connect('destroy', Lang.bind(this, function(emitter) {
|
||||
delete this.statusArea[role];
|
||||
emitter.disconnect(destroyId);
|
||||
container.destroy();
|
||||
}));
|
||||
indicator.connect('menu-set', Lang.bind(this, this._onMenuSet));
|
||||
this._onMenuSet(indicator);
|
||||
},
|
||||
|
||||
addToStatusArea: function(role, indicator, position, box) {
|
||||
@ -1108,5 +1045,24 @@ const Panel = new Lang.Class({
|
||||
this.actor.remove_style_class_name(className);
|
||||
this._rightCorner.actor.remove_style_class_name(className);
|
||||
this._leftCorner.actor.remove_style_class_name(className);
|
||||
},
|
||||
|
||||
_onMenuSet: function(indicator) {
|
||||
if (!indicator.menu || indicator.menu._openChangedId > 0)
|
||||
return;
|
||||
|
||||
indicator.menu._openChangedId = indicator.menu.connect('open-state-changed',
|
||||
Lang.bind(this, function(menu, isOpen) {
|
||||
let boxAlignment;
|
||||
if (this._leftBox.contains(indicator.container))
|
||||
boxAlignment = Clutter.ActorAlign.START;
|
||||
else if (this._centerBox.contains(indicator.container))
|
||||
boxAlignment = Clutter.ActorAlign.CENTER;
|
||||
else if (this._rightBox.contains(indicator.container))
|
||||
boxAlignment = Clutter.ActorAlign.END;
|
||||
|
||||
if (boxAlignment == Main.messageTray.bannerAlignment)
|
||||
Main.messageTray.bannerBlocked = isOpen;
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
@ -13,16 +13,92 @@ const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const ButtonBox = new Lang.Class({
|
||||
Name: 'ButtonBox',
|
||||
|
||||
_init: function(params) {
|
||||
params = Params.parse(params, { style_class: 'panel-button' }, true);
|
||||
this.actor = new Shell.GenericContainer(params);
|
||||
this.actor._delegate = this;
|
||||
|
||||
this.container = new St.Bin({ y_fill: true,
|
||||
x_fill: true,
|
||||
child: this.actor });
|
||||
|
||||
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||
|
||||
this.actor.connect('style-changed', Lang.bind(this, this._onStyleChanged));
|
||||
this._minHPadding = this._natHPadding = 0.0;
|
||||
},
|
||||
|
||||
_onStyleChanged: function(actor) {
|
||||
let themeNode = actor.get_theme_node();
|
||||
|
||||
this._minHPadding = themeNode.get_length('-minimum-hpadding');
|
||||
this._natHPadding = themeNode.get_length('-natural-hpadding');
|
||||
},
|
||||
|
||||
_getPreferredWidth: function(actor, forHeight, alloc) {
|
||||
let child = actor.get_first_child();
|
||||
|
||||
if (child) {
|
||||
[alloc.min_size, alloc.natural_size] = child.get_preferred_width(-1);
|
||||
} else {
|
||||
alloc.min_size = alloc.natural_size = 0;
|
||||
}
|
||||
|
||||
alloc.min_size += 2 * this._minHPadding;
|
||||
alloc.natural_size += 2 * this._natHPadding;
|
||||
},
|
||||
|
||||
_getPreferredHeight: function(actor, forWidth, alloc) {
|
||||
let child = actor.get_first_child();
|
||||
|
||||
if (child) {
|
||||
[alloc.min_size, alloc.natural_size] = child.get_preferred_height(-1);
|
||||
} else {
|
||||
alloc.min_size = alloc.natural_size = 0;
|
||||
}
|
||||
},
|
||||
|
||||
_allocate: function(actor, box, flags) {
|
||||
let child = actor.get_first_child();
|
||||
if (!child)
|
||||
return;
|
||||
|
||||
let [minWidth, natWidth] = child.get_preferred_width(-1);
|
||||
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let availHeight = box.y2 - box.y1;
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
if (natWidth + 2 * this._natHPadding <= availWidth) {
|
||||
childBox.x1 = this._natHPadding;
|
||||
childBox.x2 = availWidth - this._natHPadding;
|
||||
} else {
|
||||
childBox.x1 = this._minHPadding;
|
||||
childBox.x2 = availWidth - this._minHPadding;
|
||||
}
|
||||
|
||||
childBox.y1 = 0;
|
||||
childBox.y2 = availHeight;
|
||||
|
||||
child.allocate(childBox, flags);
|
||||
},
|
||||
});
|
||||
|
||||
const Button = new Lang.Class({
|
||||
Name: 'PanelMenuButton',
|
||||
Extends: ButtonBox,
|
||||
|
||||
_init: function(menuAlignment, nameText, dontCreateMenu) {
|
||||
this.actor = new St.Bin({ style_class: 'panel-button',
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
track_hover: true,
|
||||
accessible_name: nameText ? nameText : "",
|
||||
accessible_role: Atk.Role.MENU });
|
||||
this.parent({ reactive: true,
|
||||
can_focus: true,
|
||||
track_hover: true,
|
||||
accessible_name: nameText ? nameText : "",
|
||||
accessible_role: Atk.Role.MENU });
|
||||
|
||||
this.actor.connect('event', Lang.bind(this, this._onEvent));
|
||||
this.actor.connect('notify::visible', Lang.bind(this, this._onVisibilityChanged));
|
||||
@ -52,6 +128,7 @@ const Button = new Lang.Class({
|
||||
Main.uiGroup.add_actor(this.menu.actor);
|
||||
this.menu.actor.hide();
|
||||
}
|
||||
this.emit('menu-set');
|
||||
},
|
||||
|
||||
_onEvent: function(actor, event) {
|
||||
@ -97,10 +174,13 @@ const Button = new Lang.Class({
|
||||
// menu is higher then the screen; it's useful if part of the menu is
|
||||
// scrollable so the minimum height is smaller than the natural height
|
||||
let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
|
||||
this.menu.actor.style = ('max-height: ' + Math.round(workArea.height) + 'px;');
|
||||
let verticalMargins = this.menu.actor.margin_top + this.menu.actor.margin_bottom;
|
||||
this.menu.actor.style = ('max-height: ' + Math.round(workArea.height - verticalMargins) + 'px;');
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.actor._delegate = null;
|
||||
|
||||
if (this.menu)
|
||||
this.menu.destroy();
|
||||
this.actor.destroy();
|
||||
|
@ -12,7 +12,6 @@ const BoxPointer = imports.ui.boxpointer;
|
||||
const GrabHelper = imports.ui.grabHelper;
|
||||
const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
const Separator = imports.ui.separator;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const Ornament = {
|
||||
@ -91,6 +90,7 @@ const PopupBaseMenuItem = new Lang.Class({
|
||||
this.actor.add_style_class_name(params.style_class);
|
||||
|
||||
if (this._activatable) {
|
||||
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPressEvent));
|
||||
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonReleaseEvent));
|
||||
this.actor.connect('touch-event', Lang.bind(this, this._onTouchEvent));
|
||||
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
|
||||
@ -114,15 +114,26 @@ const PopupBaseMenuItem = new Lang.Class({
|
||||
this._parent = parent;
|
||||
},
|
||||
|
||||
_onButtonPressEvent: function (actor, event) {
|
||||
// This is the CSS active state
|
||||
this.actor.add_style_pseudo_class ('active');
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
|
||||
_onButtonReleaseEvent: function (actor, event) {
|
||||
this.actor.remove_style_pseudo_class ('active');
|
||||
this.activate(event);
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_onTouchEvent: function (actor, event) {
|
||||
if (event.type() == Clutter.EventType.TOUCH_END) {
|
||||
this.actor.remove_style_pseudo_class ('active');
|
||||
this.activate(event);
|
||||
return Clutter.EVENT_STOP;
|
||||
} else if (event.type() == Clutter.EventType.TOUCH_BEGIN) {
|
||||
// This is the CSS active state
|
||||
this.actor.add_style_pseudo_class ('active');
|
||||
}
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
},
|
||||
@ -158,10 +169,17 @@ const PopupBaseMenuItem = new Lang.Class({
|
||||
if (activeChanged) {
|
||||
this.active = active;
|
||||
if (active) {
|
||||
this.actor.add_style_pseudo_class('active');
|
||||
this.actor.add_style_class_name('selected');
|
||||
this.actor.grab_key_focus();
|
||||
} else {
|
||||
this.actor.remove_style_pseudo_class('active');
|
||||
this.actor.remove_style_class_name('selected');
|
||||
// Remove the CSS active state if the user press the button and
|
||||
// while holding moves to another menu item, so we don't paint all items.
|
||||
// The correct behaviour would be to set the new item with the CSS
|
||||
// active state as well, but button-press-event is not trigered,
|
||||
// so we should track it in our own, which would involve some work
|
||||
// in the container
|
||||
this.actor.remove_style_pseudo_class ('active');
|
||||
}
|
||||
this.emit('active-changed', active);
|
||||
}
|
||||
@ -245,8 +263,10 @@ const PopupSeparatorMenuItem = new Lang.Class({
|
||||
Lang.bind(this, this._syncVisibility));
|
||||
this._syncVisibility();
|
||||
|
||||
this._separator = new Separator.HorizontalSeparator({ style_class: 'popup-separator-menu-item' });
|
||||
this.actor.add(this._separator.actor, { expand: true });
|
||||
this._separator = new St.Widget({ style_class: 'popup-separator-menu-item',
|
||||
y_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
this.actor.add(this._separator, { expand: true });
|
||||
},
|
||||
|
||||
_syncVisibility: function() {
|
||||
@ -1039,11 +1059,6 @@ const PopupSubMenuMenuItem = new Lang.Class({
|
||||
let expander = new St.Bin({ style_class: 'popup-menu-item-expander' });
|
||||
this.actor.add(expander, { expand: true });
|
||||
|
||||
this.status = new St.Label({ style_class: 'popup-status-menu-item',
|
||||
y_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
this.actor.add_child(this.status);
|
||||
|
||||
this._triangle = arrowIcon(St.Side.RIGHT);
|
||||
this._triangle.pivot_point = new Clutter.Point({ x: 0.5, y: 0.6 });
|
||||
|
||||
@ -1075,10 +1090,12 @@ const PopupSubMenuMenuItem = new Lang.Class({
|
||||
this.actor.add_style_pseudo_class('open');
|
||||
this._getTopMenu()._setOpenedSubMenu(this.menu);
|
||||
this.actor.add_accessible_state (Atk.StateType.EXPANDED);
|
||||
this.actor.add_style_pseudo_class('checked');
|
||||
} else {
|
||||
this.actor.remove_style_pseudo_class('open');
|
||||
this._getTopMenu()._setOpenedSubMenu(null);
|
||||
this.actor.remove_accessible_state (Atk.StateType.EXPANDED);
|
||||
this.actor.remove_style_pseudo_class('checked');
|
||||
}
|
||||
},
|
||||
|
||||
@ -1123,6 +1140,9 @@ const PopupSubMenuMenuItem = new Lang.Class({
|
||||
},
|
||||
|
||||
_onButtonReleaseEvent: function(actor) {
|
||||
// Since we override the parent, we need to manage what the parent does
|
||||
// with the active style class
|
||||
this.actor.remove_style_pseudo_class ('active');
|
||||
this._setOpenState(!this._getOpenState());
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
@ -1135,6 +1155,8 @@ const PopupMenuManager = new Lang.Class({
|
||||
Name: 'PopupMenuManager',
|
||||
|
||||
_init: function(owner, grabParams) {
|
||||
grabParams = Params.parse(grabParams,
|
||||
{ actionMode: Shell.ActionMode.POPUP });
|
||||
this._owner = owner;
|
||||
this._grabHelper = new GrabHelper.GrabHelper(owner.actor, grabParams);
|
||||
this._menus = [];
|
||||
|
@ -63,7 +63,7 @@ const SearchProvider2Iface = '<node> \
|
||||
var SearchProviderProxyInfo = Gio.DBusInterfaceInfo.new_for_xml(SearchProviderIface);
|
||||
var SearchProvider2ProxyInfo = Gio.DBusInterfaceInfo.new_for_xml(SearchProvider2Iface);
|
||||
|
||||
function loadRemoteSearchProviders(callback) {
|
||||
function loadRemoteSearchProviders(searchSettings, callback) {
|
||||
let objectPaths = {};
|
||||
let loadedProviders = [];
|
||||
|
||||
@ -124,7 +124,6 @@ function loadRemoteSearchProviders(callback) {
|
||||
}
|
||||
}
|
||||
|
||||
let searchSettings = new Gio.Settings({ schema_id: Search.SEARCH_PROVIDERS_SCHEMA });
|
||||
if (searchSettings.get_boolean('disable-external')) {
|
||||
callback([]);
|
||||
return;
|
||||
@ -236,8 +235,10 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
|
||||
_getResultsFinished: function(results, error, callback) {
|
||||
if (error) {
|
||||
if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
log('Received error from DBus search provider %s: %s'.format(this.id, String(error)));
|
||||
if (error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
return;
|
||||
|
||||
log('Received error from DBus search provider %s: %s'.format(this.id, String(error)));
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
|
@ -272,6 +272,10 @@ const RunDialog = new Lang.Class({
|
||||
},
|
||||
|
||||
_restart: function() {
|
||||
if (Meta.is_wayland_compositor()) {
|
||||
this._showError('Restart is not available on Wayland');
|
||||
return;
|
||||
}
|
||||
this._shouldFadeOut = false;
|
||||
this.close();
|
||||
Meta.restart(_("Restarting…"));
|
||||
|
@ -60,9 +60,6 @@ const CURTAIN_SLIDE_TIME = 0.3;
|
||||
const Clock = new Lang.Class({
|
||||
Name: 'ScreenShieldClock',
|
||||
|
||||
CLOCK_FORMAT_KEY: 'clock-format',
|
||||
CLOCK_SHOW_SECONDS_KEY: 'clock-show-seconds',
|
||||
|
||||
_init: function() {
|
||||
this.actor = new St.BoxLayout({ style_class: 'screen-shield-clock',
|
||||
vertical: true });
|
||||
@ -101,18 +98,14 @@ const NotificationsBox = new Lang.Class({
|
||||
_init: function() {
|
||||
this.actor = new St.BoxLayout({ vertical: true,
|
||||
name: 'screenShieldNotifications',
|
||||
style_class: 'screen-shield-notifications-box' });
|
||||
|
||||
this._musicBin = new St.Bin({ style_class: 'screen-shield-notifications-box',
|
||||
visible: false });
|
||||
style_class: 'screen-shield-notifications-container' });
|
||||
|
||||
this._scrollView = new St.ScrollView({ x_fill: false, x_align: St.Align.START,
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER });
|
||||
this._notificationBox = new St.BoxLayout({ vertical: true,
|
||||
style_class: 'screen-shield-notifications-box' });
|
||||
style_class: 'screen-shield-notifications-container' });
|
||||
this._scrollView.add_actor(this._notificationBox);
|
||||
|
||||
this.actor.add(this._musicBin);
|
||||
this.actor.add(this._scrollView, { x_fill: true, x_align: St.Align.START });
|
||||
|
||||
this._sources = new Map();
|
||||
@ -139,12 +132,11 @@ const NotificationsBox = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateVisibility: function() {
|
||||
this._musicBin.visible = this._musicBin.child != null && this._musicBin.child.visible;
|
||||
this._notificationBox.visible = this._notificationBox.get_children().some(function(a) {
|
||||
return a.visible;
|
||||
});
|
||||
|
||||
this.actor.visible = this._musicBin.visible || this._notificationBox.visible;
|
||||
this.actor.visible = this._notificationBox.visible;
|
||||
},
|
||||
|
||||
_makeNotificationCountText: function(count, isChat) {
|
||||
@ -192,7 +184,7 @@ const NotificationsBox = new Lang.Class({
|
||||
for (let i = 0; i < source.notifications.length; i++) {
|
||||
let n = source.notifications[i];
|
||||
|
||||
if (n.acknowledged || n.isMusic)
|
||||
if (n.acknowledged)
|
||||
continue;
|
||||
|
||||
let body = '';
|
||||
@ -213,29 +205,13 @@ const NotificationsBox = new Lang.Class({
|
||||
},
|
||||
|
||||
_showSource: function(source, obj, box) {
|
||||
let musicNotification = source.getMusicNotification();
|
||||
|
||||
if (musicNotification != null &&
|
||||
this._musicBin.child == null) {
|
||||
musicNotification.acknowledged = true;
|
||||
if (musicNotification.actor.get_parent() != null)
|
||||
musicNotification.actor.get_parent().remove_actor(musicNotification.actor);
|
||||
this._musicBin.child = musicNotification.actor;
|
||||
this._musicBin.child.visible = obj.visible;
|
||||
|
||||
musicNotification.expand(false /* animate */);
|
||||
|
||||
obj.musicNotification = musicNotification;
|
||||
}
|
||||
|
||||
if (obj.detailed) {
|
||||
[obj.titleLabel, obj.countLabel] = this._makeNotificationDetailedSource(source, box);
|
||||
} else {
|
||||
[obj.titleLabel, obj.countLabel] = this._makeNotificationSource(source, box);
|
||||
}
|
||||
|
||||
box.visible = obj.visible &&
|
||||
(source.unseenCount > (musicNotification ? 1 : 0));
|
||||
box.visible = obj.visible && (source.unseenCount > 0);
|
||||
},
|
||||
|
||||
_sourceAdded: function(tray, source, initial) {
|
||||
@ -246,23 +222,16 @@ const NotificationsBox = new Lang.Class({
|
||||
sourceCountChangedId: 0,
|
||||
sourceTitleChangedId: 0,
|
||||
sourceUpdatedId: 0,
|
||||
sourceNotifyId: 0,
|
||||
musicNotification: null,
|
||||
sourceBox: null,
|
||||
titleLabel: null,
|
||||
countLabel: null,
|
||||
};
|
||||
|
||||
obj.sourceBox = new St.BoxLayout({ style_class: 'screen-shield-notification-source' });
|
||||
obj.sourceBox = new St.BoxLayout({ style_class: 'screen-shield-notification-source',
|
||||
x_expand: true });
|
||||
this._showSource(source, obj, obj.sourceBox);
|
||||
this._notificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START });
|
||||
|
||||
if (obj.musicNotification) {
|
||||
obj.sourceNotifyId = source.connect('notify', Lang.bind(this, function(source, notification) {
|
||||
notification.acknowledged = true;
|
||||
}));
|
||||
}
|
||||
|
||||
obj.sourceCountChangedId = source.connect('count-updated', Lang.bind(this, function(source) {
|
||||
this._countChanged(source, obj);
|
||||
}));
|
||||
@ -302,7 +271,8 @@ const NotificationsBox = new Lang.Class({
|
||||
});
|
||||
|
||||
this._updateVisibility();
|
||||
this.emit('wake-up-screen');
|
||||
if (obj.sourceBox.visible)
|
||||
this.emit('wake-up-screen');
|
||||
}
|
||||
},
|
||||
|
||||
@ -323,8 +293,7 @@ const NotificationsBox = new Lang.Class({
|
||||
obj.countLabel.text = this._makeNotificationCountText(count, source.isChat);
|
||||
}
|
||||
|
||||
obj.sourceBox.visible = obj.visible &&
|
||||
(source.unseenCount > (obj.musicNotification ? 1 : 0));
|
||||
obj.sourceBox.visible = obj.visible && (source.unseenCount > 0);
|
||||
|
||||
this._updateVisibility();
|
||||
if (obj.sourceBox.visible)
|
||||
@ -336,10 +305,7 @@ const NotificationsBox = new Lang.Class({
|
||||
return;
|
||||
|
||||
obj.visible = source.policy.showInLockScreen;
|
||||
if (obj.musicNotification)
|
||||
obj.musicNotification.actor.visible = obj.visible;
|
||||
obj.sourceBox.visible = obj.visible &&
|
||||
source.unseenCount > (obj.musicNotification ? 1 : 0);
|
||||
obj.sourceBox.visible = obj.visible && source.unseenCount > 0;
|
||||
|
||||
this._updateVisibility();
|
||||
if (obj.sourceBox.visible)
|
||||
@ -366,13 +332,6 @@ const NotificationsBox = new Lang.Class({
|
||||
obj.sourceBox.destroy();
|
||||
obj.sourceBox = obj.titleLabel = obj.countLabel = null;
|
||||
|
||||
if (obj.musicNotification) {
|
||||
this._musicBin.child = null;
|
||||
obj.musicNotification = null;
|
||||
|
||||
source.disconnect(obj.sourceNotifyId);
|
||||
}
|
||||
|
||||
source.disconnect(obj.sourceDestroyId);
|
||||
source.disconnect(obj.sourceCountChangedId);
|
||||
source.disconnect(obj.sourceTitleChangedId);
|
||||
@ -548,21 +507,22 @@ const ScreenShield = new Lang.Class({
|
||||
this._liftShield(true, 0);
|
||||
}));
|
||||
|
||||
this._inhibitor = null;
|
||||
this._aboutToSuspend = false;
|
||||
this._loginManager = LoginManager.getLoginManager();
|
||||
this._loginManager.connect('prepare-for-sleep',
|
||||
Lang.bind(this, this._prepareForSleep));
|
||||
this._inhibitSuspend();
|
||||
|
||||
this._loginSession = null;
|
||||
this._loginManager.getCurrentSessionProxy(Lang.bind(this,
|
||||
function(sessionProxy) {
|
||||
this._loginSession = sessionProxy;
|
||||
this._loginSession.connectSignal('Lock', Lang.bind(this, function() { this.lock(false); }));
|
||||
this._loginSession.connectSignal('Unlock', Lang.bind(this, function() { this.deactivate(false); }));
|
||||
this._loginSession.connect('g-properties-changed', Lang.bind(this, this._syncInhibitor));
|
||||
this._syncInhibitor();
|
||||
}));
|
||||
|
||||
this._settings = new Gio.Settings({ schema_id: SCREENSAVER_SCHEMA });
|
||||
this._settings.connect('changed::' + LOCK_ENABLED_KEY, Lang.bind(this, this._syncInhibitor));
|
||||
|
||||
this._isModal = false;
|
||||
this._hasLockScreen = false;
|
||||
@ -588,6 +548,18 @@ const ScreenShield = new Lang.Class({
|
||||
|
||||
this.idleMonitor = Meta.IdleMonitor.get_core();
|
||||
this._cursorTracker = Meta.CursorTracker.get_for_screen(global.screen);
|
||||
|
||||
this._syncInhibitor();
|
||||
},
|
||||
|
||||
_setActive: function(active) {
|
||||
let prevIsActive = this._isActive;
|
||||
this._isActive = active;
|
||||
|
||||
if (prevIsActive != this._isActive)
|
||||
this.emit('active-changed');
|
||||
|
||||
this._syncInhibitor();
|
||||
},
|
||||
|
||||
_createBackground: function(monitorIndex) {
|
||||
@ -647,14 +619,14 @@ const ScreenShield = new Lang.Class({
|
||||
if (this._isModal)
|
||||
return true;
|
||||
|
||||
this._isModal = Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN });
|
||||
this._isModal = Main.pushModal(this.actor, { actionMode: Shell.ActionMode.LOCK_SCREEN });
|
||||
if (this._isModal)
|
||||
return true;
|
||||
|
||||
// We failed to get a pointer grab, it means that
|
||||
// something else has it. Try with a keyboard grab only
|
||||
this._isModal = Main.pushModal(this.actor, { options: Meta.ModalOptions.POINTER_ALREADY_GRABBED,
|
||||
keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN });
|
||||
actionMode: Shell.ActionMode.LOCK_SCREEN });
|
||||
return this._isModal;
|
||||
},
|
||||
|
||||
@ -705,31 +677,28 @@ const ScreenShield = new Lang.Class({
|
||||
return Clutter.EVENT_STOP;
|
||||
},
|
||||
|
||||
_inhibitSuspend: function() {
|
||||
this._loginManager.inhibit(_("GNOME needs to lock the screen"),
|
||||
Lang.bind(this, function(inhibitor) {
|
||||
this._inhibitor = inhibitor;
|
||||
}));
|
||||
},
|
||||
|
||||
_uninhibitSuspend: function() {
|
||||
if (this._inhibitor)
|
||||
this._inhibitor.close(null);
|
||||
this._inhibitor = null;
|
||||
_syncInhibitor: function() {
|
||||
let inhibit = (this._loginSession && this._loginSession.Active &&
|
||||
!this._isActive && this._settings.get_boolean(LOCK_ENABLED_KEY));
|
||||
if (inhibit) {
|
||||
this._loginManager.inhibit(_("GNOME needs to lock the screen"),
|
||||
Lang.bind(this, function(inhibitor) {
|
||||
if (this._inhibitor)
|
||||
this._inhibitor.close(null);
|
||||
this._inhibitor = inhibitor;
|
||||
}));
|
||||
} else {
|
||||
if (this._inhibitor)
|
||||
this._inhibitor.close(null);
|
||||
this._inhibitor = null;
|
||||
}
|
||||
},
|
||||
|
||||
_prepareForSleep: function(loginManager, aboutToSuspend) {
|
||||
this._aboutToSuspend = aboutToSuspend;
|
||||
|
||||
if (aboutToSuspend) {
|
||||
if (!this._settings.get_boolean(LOCK_ENABLED_KEY)) {
|
||||
this._uninhibitSuspend();
|
||||
return;
|
||||
}
|
||||
this.lock(true);
|
||||
if (this._settings.get_boolean(LOCK_ENABLED_KEY))
|
||||
this.lock(true);
|
||||
} else {
|
||||
this._inhibitSuspend();
|
||||
|
||||
this._wakeUpScreen();
|
||||
}
|
||||
},
|
||||
@ -1124,15 +1093,7 @@ const ScreenShield = new Lang.Class({
|
||||
},
|
||||
|
||||
_completeLockScreenShown: function() {
|
||||
let prevIsActive = this._isActive;
|
||||
this._isActive = true;
|
||||
|
||||
if (prevIsActive != this._isActive)
|
||||
this.emit('active-changed');
|
||||
|
||||
if (this._aboutToSuspend)
|
||||
this._uninhibitSuspend();
|
||||
|
||||
this._setActive(true);
|
||||
this.emit('lock-screen-shown');
|
||||
},
|
||||
|
||||
@ -1226,8 +1187,7 @@ const ScreenShield = new Lang.Class({
|
||||
// gnome-settings-daemon will stop blanking the screen
|
||||
|
||||
this._activationTime = 0;
|
||||
this._isActive = false;
|
||||
this.emit('active-changed');
|
||||
this._setActive(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1270,9 +1230,8 @@ const ScreenShield = new Lang.Class({
|
||||
}
|
||||
|
||||
this._activationTime = 0;
|
||||
this._isActive = false;
|
||||
this._setActive(false);
|
||||
this._isLocked = false;
|
||||
this.emit('active-changed');
|
||||
this.emit('locked-changed');
|
||||
global.set_runtime_state(LOCKED_STATE_STR, null);
|
||||
},
|
||||
|
@ -99,7 +99,7 @@ const ScreencastService = new Lang.Class({
|
||||
recorder.set_pipeline(options['pipeline']);
|
||||
if (options['framerate'])
|
||||
recorder.set_framerate(options['framerate']);
|
||||
if (options['draw-cursor'])
|
||||
if ('draw-cursor' in options)
|
||||
recorder.set_draw_cursor(options['draw-cursor']);
|
||||
},
|
||||
|
||||
|
@ -283,8 +283,8 @@ const SelectArea = new Lang.Class({
|
||||
_getGeometry: function() {
|
||||
return { x: Math.min(this._startX, this._lastX),
|
||||
y: Math.min(this._startY, this._lastY),
|
||||
width: Math.abs(this._startX - this._lastX),
|
||||
height: Math.abs(this._startY - this._lastY) };
|
||||
width: Math.abs(this._startX - this._lastX) + 1,
|
||||
height: Math.abs(this._startY - this._lastY) + 1 };
|
||||
},
|
||||
|
||||
_onMotionEvent: function(actor, event) {
|
||||
@ -292,6 +292,8 @@ const SelectArea = new Lang.Class({
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
[this._lastX, this._lastY] = event.get_coords();
|
||||
this._lastX = Math.floor(this._lastX);
|
||||
this._lastY = Math.floor(this._lastY);
|
||||
let geometry = this._getGeometry();
|
||||
|
||||
this._rubberband.set_position(geometry.x, geometry.y);
|
||||
@ -302,6 +304,8 @@ const SelectArea = new Lang.Class({
|
||||
|
||||
_onButtonPress: function(actor, event) {
|
||||
[this._startX, this._startY] = event.get_coords();
|
||||
this._startX = Math.floor(this._startX);
|
||||
this._startY = Math.floor(this._startY);
|
||||
this._rubberband.set_position(this._startX, this._startY);
|
||||
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
@ -199,12 +199,16 @@ const SearchResultsBase = new Lang.Class({
|
||||
this._cancellable.reset();
|
||||
|
||||
this.provider.getResultMetas(metasNeeded, Lang.bind(this, function(metas) {
|
||||
if (metas.length == 0) {
|
||||
if (metas.length != metasNeeded.length) {
|
||||
log('Wrong number of result metas returned by search provider ' + this.provider.id +
|
||||
': expected ' + metasNeeded.length + ' but got ' + metas.length);
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
if (metas.length != metasNeeded.length) {
|
||||
log('Wrong number of result metas returned by search provider');
|
||||
if (metas.some(function(meta) {
|
||||
return !meta.name || !meta.id;
|
||||
})) {
|
||||
log('Invalid result meta returned from search provider ' + this.provider.id);
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
@ -236,6 +240,7 @@ const SearchResultsBase = new Lang.Class({
|
||||
this._ensureResultActors(results, Lang.bind(this, function(successful) {
|
||||
if (!successful) {
|
||||
this._clearResultDisplay();
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -411,6 +416,7 @@ const SearchResults = new Lang.Class({
|
||||
|
||||
this._searchSettings = new Gio.Settings({ schema_id: SEARCH_PROVIDERS_SCHEMA });
|
||||
this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
|
||||
this._searchSettings.connect('changed::enabled', Lang.bind(this, this._reloadRemoteProviders));
|
||||
this._searchSettings.connect('changed::disable-external', Lang.bind(this, this._reloadRemoteProviders));
|
||||
this._searchSettings.connect('changed::sort-order', Lang.bind(this, this._reloadRemoteProviders));
|
||||
|
||||
@ -429,7 +435,7 @@ const SearchResults = new Lang.Class({
|
||||
this._unregisterProvider(provider);
|
||||
}));
|
||||
|
||||
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, function(providers) {
|
||||
RemoteSearch.loadRemoteSearchProviders(this._searchSettings, Lang.bind(this, function(providers) {
|
||||
providers.forEach(Lang.bind(this, this._registerProvider));
|
||||
}));
|
||||
},
|
||||
@ -659,15 +665,11 @@ const SearchResults = new Lang.Class({
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
let styleReceiver = result.actor;
|
||||
if (result.getStyleReceiver)
|
||||
styleReceiver = result.getStyleReceiver();
|
||||
|
||||
if (selected) {
|
||||
styleReceiver.add_style_pseudo_class('selected');
|
||||
result.actor.add_style_pseudo_class('selected');
|
||||
Util.ensureActorVisibleInScrollView(this._scrollView, result.actor);
|
||||
} else {
|
||||
styleReceiver.remove_style_pseudo_class('selected');
|
||||
result.actor.remove_style_pseudo_class('selected');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -25,6 +25,10 @@ const GnomeShellIface = '<node> \
|
||||
<method name="ShowOSD"> \
|
||||
<arg type="a{sv}" direction="in" name="params"/> \
|
||||
</method> \
|
||||
<method name="ShowMonitorLabels"> \
|
||||
<arg type="a{uv}" direction="in" name="params" /> \
|
||||
</method> \
|
||||
<method name="HideMonitorLabels" /> \
|
||||
<method name="FocusApp"> \
|
||||
<arg type="s" direction="in" name="id"/> \
|
||||
</method> \
|
||||
@ -44,8 +48,7 @@ const GnomeShellIface = '<node> \
|
||||
</method> \
|
||||
<signal name="AcceleratorActivated"> \
|
||||
<arg name="action" type="u" /> \
|
||||
<arg name="deviceid" type="u" /> \
|
||||
<arg name="timestamp" type="u" /> \
|
||||
<arg name="parameters" type="a{sv}" /> \
|
||||
</signal> \
|
||||
<property name="Mode" type="s" access="read" /> \
|
||||
<property name="OverviewActive" type="b" access="readwrite" /> \
|
||||
@ -90,6 +93,12 @@ const GnomeShell = new Lang.Class({
|
||||
function(display, action, deviceid, timestamp) {
|
||||
this._emitAcceleratorActivated(action, deviceid, timestamp);
|
||||
}));
|
||||
|
||||
this._cachedOverviewVisible = false;
|
||||
Main.overview.connect('showing',
|
||||
Lang.bind(this, this._checkOverviewVisibleChanged));
|
||||
Main.overview.connect('hidden',
|
||||
Lang.bind(this, this._checkOverviewVisibleChanged));
|
||||
},
|
||||
|
||||
/**
|
||||
@ -134,7 +143,7 @@ const GnomeShell = new Lang.Class({
|
||||
params[param] = params[param].deep_unpack();
|
||||
|
||||
let monitorIndex = -1;
|
||||
if (params['monitor'])
|
||||
if (params['monitor'] >= 0)
|
||||
monitorIndex = params['monitor'];
|
||||
|
||||
let icon = null;
|
||||
@ -190,11 +199,14 @@ const GnomeShell = new Lang.Class({
|
||||
|
||||
let connection = this._dbusImpl.get_connection();
|
||||
let info = this._dbusImpl.get_info();
|
||||
let params = { 'device-id': GLib.Variant.new('u', deviceid),
|
||||
'timestamp': GLib.Variant.new('u', timestamp),
|
||||
'action-mode': GLib.Variant.new('u', Main.actionMode) };
|
||||
connection.emit_signal(destination,
|
||||
this._dbusImpl.get_object_path(),
|
||||
info ? info.name : null,
|
||||
'AcceleratorActivated',
|
||||
GLib.Variant.new('(uuu)', [action, deviceid, timestamp]));
|
||||
GLib.Variant.new('(ua{sv})', [action, params]));
|
||||
},
|
||||
|
||||
_grabAcceleratorForSender: function(accelerator, flags, sender) {
|
||||
@ -232,11 +244,29 @@ const GnomeShell = new Lang.Class({
|
||||
this._grabbers.delete(name);
|
||||
},
|
||||
|
||||
ShowMonitorLabelsAsync: function(params, invocation) {
|
||||
let sender = invocation.get_sender();
|
||||
let [dict] = params;
|
||||
Main.osdMonitorLabeler.show(sender, dict);
|
||||
},
|
||||
|
||||
HideMonitorLabelsAsync: function(params, invocation) {
|
||||
let sender = invocation.get_sender();
|
||||
Main.osdMonitorLabeler.hide(sender);
|
||||
},
|
||||
|
||||
|
||||
Mode: global.session_mode,
|
||||
|
||||
_checkOverviewVisibleChanged: function() {
|
||||
if (Main.overview.visible !== this._cachedOverviewVisible) {
|
||||
this._cachedOverviewVisible = Main.overview.visible;
|
||||
this._dbusImpl.emit_property_changed('OverviewActive', new GLib.Variant('b', this._cachedOverviewVisible));
|
||||
}
|
||||
},
|
||||
|
||||
get OverviewActive() {
|
||||
return Main.overview.visible;
|
||||
return this._cachedOverviewVisible;
|
||||
},
|
||||
|
||||
set OverviewActive(visible) {
|
||||
|
@ -49,9 +49,9 @@ function _setButtonsForChoices(dialog, choices) {
|
||||
function _setLabelsForMessage(dialog, message) {
|
||||
let labels = message.split('\n');
|
||||
|
||||
_setLabelText(dialog.subjectLabel, labels[0]);
|
||||
if (labels.length > 1)
|
||||
_setLabelText(dialog.descriptionLabel, labels[1]);
|
||||
_setLabelText(dialog.subjectLabel, labels.shift());
|
||||
if (labels.length > 0)
|
||||
_setLabelText(dialog.descriptionLabel, labels.join('\n'));
|
||||
}
|
||||
|
||||
function _createIcon(gicon) {
|
||||
@ -347,7 +347,7 @@ const ShellMountPasswordDialog = new Lang.Class({
|
||||
mainContentBox.add(this._messageBox,
|
||||
{ y_align: St.Align.START, expand: true, x_fill: true, y_fill: true });
|
||||
|
||||
let subject = new St.Label({ style_class: 'prompt-dialog-headline' });
|
||||
let subject = new St.Label({ style_class: 'prompt-dialog-headline headline' });
|
||||
this._messageBox.add(subject,
|
||||
{ y_fill: false,
|
||||
y_align: St.Align.START });
|
||||
|
@ -7,7 +7,7 @@ const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const SLIDER_SCROLL_STEP = 0.05; /* Slider scrolling step in % */
|
||||
const SLIDER_SCROLL_STEP = 0.02; /* Slider scrolling step in % */
|
||||
|
||||
const Slider = new Lang.Class({
|
||||
Name: "Slider",
|
||||
@ -197,7 +197,7 @@ const Slider = new Lang.Class({
|
||||
let [dx, dy] = event.get_scroll_delta();
|
||||
// Even though the slider is horizontal, use dy to match
|
||||
// the UP/DOWN above.
|
||||
delta = -dy / 10;
|
||||
delta = -dy * SLIDER_SCROLL_STEP;
|
||||
}
|
||||
|
||||
this._value = Math.min(Math.max(0, this._value + delta), 1);
|
||||
|
@ -119,23 +119,46 @@ const ATIndicator = new Lang.Class({
|
||||
|
||||
_buildItem: function(string, schema, key) {
|
||||
let settings = new Gio.Settings({ schema_id: schema });
|
||||
settings.connect('changed::'+key, Lang.bind(this, function() {
|
||||
widget.setToggleState(settings.get_boolean(key));
|
||||
|
||||
this._queueSyncMenuVisibility();
|
||||
}));
|
||||
|
||||
let widget = this._buildItemExtended(string,
|
||||
settings.get_boolean(key),
|
||||
settings.is_writable(key),
|
||||
function(enabled) {
|
||||
return settings.set_boolean(key, enabled);
|
||||
});
|
||||
settings.connect('changed::'+key, Lang.bind(this, function() {
|
||||
widget.setToggleState(settings.get_boolean(key));
|
||||
|
||||
this._queueSyncMenuVisibility();
|
||||
}));
|
||||
return widget;
|
||||
},
|
||||
|
||||
_buildHCItem: function() {
|
||||
let interfaceSettings = new Gio.Settings({ schema_id: DESKTOP_INTERFACE_SCHEMA });
|
||||
let wmSettings = new Gio.Settings({ schema_id: WM_SCHEMA });
|
||||
interfaceSettings.connect('changed::' + KEY_GTK_THEME, Lang.bind(this, function() {
|
||||
let value = interfaceSettings.get_string(KEY_GTK_THEME);
|
||||
if (value == HIGH_CONTRAST_THEME) {
|
||||
highContrast.setToggleState(true);
|
||||
} else {
|
||||
highContrast.setToggleState(false);
|
||||
gtkTheme = value;
|
||||
}
|
||||
|
||||
this._queueSyncMenuVisibility();
|
||||
}));
|
||||
interfaceSettings.connect('changed::' + KEY_ICON_THEME, function() {
|
||||
let value = interfaceSettings.get_string(KEY_ICON_THEME);
|
||||
if (value != HIGH_CONTRAST_THEME)
|
||||
iconTheme = value;
|
||||
});
|
||||
wmSettings.connect('changed::' + KEY_WM_THEME, function() {
|
||||
let value = wmSettings.get_string(KEY_WM_THEME);
|
||||
if (value != HIGH_CONTRAST_THEME)
|
||||
wmTheme = value;
|
||||
});
|
||||
|
||||
let gtkTheme = interfaceSettings.get_string(KEY_GTK_THEME);
|
||||
let iconTheme = interfaceSettings.get_string(KEY_ICON_THEME);
|
||||
let wmTheme = wmSettings.get_string(KEY_WM_THEME);
|
||||
@ -161,32 +184,18 @@ const ATIndicator = new Lang.Class({
|
||||
wmSettings.reset(KEY_WM_THEME);
|
||||
}
|
||||
});
|
||||
interfaceSettings.connect('changed::' + KEY_GTK_THEME, Lang.bind(this, function() {
|
||||
let value = interfaceSettings.get_string(KEY_GTK_THEME);
|
||||
if (value == HIGH_CONTRAST_THEME) {
|
||||
highContrast.setToggleState(true);
|
||||
} else {
|
||||
highContrast.setToggleState(false);
|
||||
gtkTheme = value;
|
||||
}
|
||||
|
||||
this._queueSyncMenuVisibility();
|
||||
}));
|
||||
interfaceSettings.connect('changed::' + KEY_ICON_THEME, function() {
|
||||
let value = interfaceSettings.get_string(KEY_ICON_THEME);
|
||||
if (value != HIGH_CONTRAST_THEME)
|
||||
iconTheme = value;
|
||||
});
|
||||
wmSettings.connect('changed::' + KEY_WM_THEME, function() {
|
||||
let value = wmSettings.get_string(KEY_WM_THEME);
|
||||
if (value != HIGH_CONTRAST_THEME)
|
||||
wmTheme = value;
|
||||
});
|
||||
return highContrast;
|
||||
},
|
||||
|
||||
_buildFontItem: function() {
|
||||
let settings = new Gio.Settings({ schema_id: DESKTOP_INTERFACE_SCHEMA });
|
||||
settings.connect('changed::' + KEY_TEXT_SCALING_FACTOR, Lang.bind(this, function() {
|
||||
let factor = settings.get_double(KEY_TEXT_SCALING_FACTOR);
|
||||
let active = (factor > 1.0);
|
||||
widget.setToggleState(active);
|
||||
|
||||
this._queueSyncMenuVisibility();
|
||||
}));
|
||||
|
||||
let factor = settings.get_double(KEY_TEXT_SCALING_FACTOR);
|
||||
let initial_setting = (factor > 1.0);
|
||||
@ -200,13 +209,6 @@ const ATIndicator = new Lang.Class({
|
||||
else
|
||||
settings.reset(KEY_TEXT_SCALING_FACTOR);
|
||||
});
|
||||
settings.connect('changed::' + KEY_TEXT_SCALING_FACTOR, Lang.bind(this, function() {
|
||||
let factor = settings.get_double(KEY_TEXT_SCALING_FACTOR);
|
||||
let active = (factor > 1.0);
|
||||
widget.setToggleState(active);
|
||||
|
||||
this._queueSyncMenuVisibility();
|
||||
}));
|
||||
return widget;
|
||||
}
|
||||
});
|
||||
|
@ -46,7 +46,7 @@ const Indicator = new Lang.Class({
|
||||
|
||||
// The Bluetooth menu only appears when Bluetooth is in use,
|
||||
// so just statically build it with a "Turn Off" menu item.
|
||||
this._item = new PopupMenu.PopupSubMenuMenuItem(_("Bluetooth"), true);
|
||||
this._item = new PopupMenu.PopupSubMenuMenuItem('', true);
|
||||
this._item.icon.icon_name = 'bluetooth-active-symbolic';
|
||||
this._item.menu.addAction(_("Turn Off"), Lang.bind(this, function() {
|
||||
this._proxy.BluetoothAirplaneMode = true;
|
||||
@ -101,8 +101,9 @@ const Indicator = new Lang.Class({
|
||||
this._item.actor.visible = this._proxy.BluetoothHasAirplaneMode && !this._proxy.BluetoothAirplaneMode;
|
||||
|
||||
if (nDevices > 0)
|
||||
this._item.status.text = ngettext("%d Connected Device", "%d Connected Devices", nDevices).format(nDevices);
|
||||
/* Translators: this is the number of connected bluetooth devices */
|
||||
this._item.label.text = ngettext("%d Connected", "%d Connected", nDevices).format(nDevices);
|
||||
else
|
||||
this._item.status.text = _("Not Connected");
|
||||
this._item.label.text = _("Not In Use");
|
||||
},
|
||||
});
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
@ -18,10 +19,6 @@ const PanelMenu = imports.ui.panelMenu;
|
||||
const SwitcherPopup = imports.ui.switcherPopup;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const DESKTOP_INPUT_SOURCES_SCHEMA = 'org.gnome.desktop.input-sources';
|
||||
const KEY_INPUT_SOURCES = 'sources';
|
||||
const KEY_KEYBOARD_OPTIONS = 'xkb-options';
|
||||
|
||||
const INPUT_SOURCE_TYPE_XKB = 'xkb';
|
||||
const INPUT_SOURCE_TYPE_IBUS = 'ibus';
|
||||
|
||||
@ -142,6 +139,149 @@ const InputSourceSwitcher = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
const InputSourceSettings = new Lang.Class({
|
||||
Name: 'InputSourceSettings',
|
||||
Abstract: true,
|
||||
|
||||
_emitInputSourcesChanged: function() {
|
||||
this.emit('input-sources-changed');
|
||||
},
|
||||
|
||||
_emitKeyboardOptionsChanged: function() {
|
||||
this.emit('keyboard-options-changed');
|
||||
},
|
||||
|
||||
_emitPerWindowChanged: function() {
|
||||
this.emit('per-window-changed');
|
||||
},
|
||||
|
||||
get inputSources() {
|
||||
return [];
|
||||
},
|
||||
|
||||
get keyboardOptions() {
|
||||
return [];
|
||||
},
|
||||
|
||||
get perWindow() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(InputSourceSettings.prototype);
|
||||
|
||||
const InputSourceSystemSettings = new Lang.Class({
|
||||
Name: 'InputSourceSystemSettings',
|
||||
Extends: InputSourceSettings,
|
||||
|
||||
_BUS_NAME: 'org.freedesktop.locale1',
|
||||
_BUS_PATH: '/org/freedesktop/locale1',
|
||||
_BUS_IFACE: 'org.freedesktop.locale1',
|
||||
_BUS_PROPS_IFACE: 'org.freedesktop.DBus.Properties',
|
||||
|
||||
_init: function() {
|
||||
this._layouts = '';
|
||||
this._variants = '';
|
||||
this._options = '';
|
||||
|
||||
this._reload();
|
||||
|
||||
Gio.DBus.system.signal_subscribe(this._BUS_NAME,
|
||||
this._BUS_PROPS_IFACE,
|
||||
'PropertiesChanged',
|
||||
this._BUS_PATH,
|
||||
null,
|
||||
Gio.DBusSignalFlags.NONE,
|
||||
Lang.bind(this, this._reload));
|
||||
},
|
||||
|
||||
_reload: function() {
|
||||
Gio.DBus.system.call(this._BUS_NAME,
|
||||
this._BUS_PATH,
|
||||
this._BUS_PROPS_IFACE,
|
||||
'GetAll',
|
||||
new GLib.Variant('(s)', [this._BUS_IFACE]),
|
||||
null, Gio.DBusCallFlags.NONE, -1, null,
|
||||
Lang.bind(this, function(conn, result) {
|
||||
let props;
|
||||
try {
|
||||
props = conn.call_finish(result).deep_unpack()[0];
|
||||
} catch(e) {
|
||||
log('Could not get properties from ' + this._BUS_NAME);
|
||||
return;
|
||||
}
|
||||
let layouts = props['X11Layout'].unpack();
|
||||
let variants = props['X11Variant'].unpack();
|
||||
let options = props['X11Options'].unpack();
|
||||
|
||||
if (layouts != this._layouts ||
|
||||
variants != this._variants) {
|
||||
this._layouts = layouts;
|
||||
this._variants = variants;
|
||||
this._emitInputSourcesChanged();
|
||||
}
|
||||
if (options != this._options) {
|
||||
this._options = options;
|
||||
this._emitKeyboardOptionsChanged();
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
get inputSources() {
|
||||
let sourcesList = [];
|
||||
let layouts = this._layouts.split(',');
|
||||
let variants = this._variants.split(',');
|
||||
|
||||
for (let i = 0; i < layouts.length && !!layouts[i]; i++) {
|
||||
let id = layouts[i];
|
||||
if (!!variants[i])
|
||||
id += '+' + variants[i];
|
||||
sourcesList.push({ type: INPUT_SOURCE_TYPE_XKB, id: id });
|
||||
}
|
||||
return sourcesList;
|
||||
},
|
||||
|
||||
get keyboardOptions() {
|
||||
return this._options.split(',');
|
||||
}
|
||||
});
|
||||
|
||||
const InputSourceSessionSettings = new Lang.Class({
|
||||
Name: 'InputSourceSessionSettings',
|
||||
Extends: InputSourceSettings,
|
||||
|
||||
_DESKTOP_INPUT_SOURCES_SCHEMA: 'org.gnome.desktop.input-sources',
|
||||
_KEY_INPUT_SOURCES: 'sources',
|
||||
_KEY_KEYBOARD_OPTIONS: 'xkb-options',
|
||||
_KEY_PER_WINDOW: 'per-window',
|
||||
|
||||
_init: function() {
|
||||
this._settings = new Gio.Settings({ schema_id: this._DESKTOP_INPUT_SOURCES_SCHEMA });
|
||||
this._settings.connect('changed::' + this._KEY_INPUT_SOURCES, Lang.bind(this, this._emitInputSourcesChanged));
|
||||
this._settings.connect('changed::' + this._KEY_KEYBOARD_OPTIONS, Lang.bind(this, this._emitKeyboardOptionsChanged));
|
||||
this._settings.connect('changed::' + this._KEY_PER_WINDOW, Lang.bind(this, this._emitPerWindowChanged));
|
||||
},
|
||||
|
||||
get inputSources() {
|
||||
let sourcesList = [];
|
||||
let sources = this._settings.get_value(this._KEY_INPUT_SOURCES);
|
||||
let nSources = sources.n_children();
|
||||
|
||||
for (let i = 0; i < nSources; i++) {
|
||||
let [type, id] = sources.get_child_value(i).deep_unpack();
|
||||
sourcesList.push({ type: type, id: id });
|
||||
}
|
||||
return sourcesList;
|
||||
},
|
||||
|
||||
get keyboardOptions() {
|
||||
return this._settings.get_strv(this._KEY_KEYBOARD_OPTIONS);
|
||||
},
|
||||
|
||||
get perWindow() {
|
||||
return this._settings.get_boolean(this._KEY_PER_WINDOW);
|
||||
}
|
||||
});
|
||||
|
||||
const InputSourceManager = new Lang.Class({
|
||||
Name: 'InputSourceManager',
|
||||
|
||||
@ -159,21 +299,25 @@ const InputSourceManager = new Lang.Class({
|
||||
// All valid input sources currently in the gsettings
|
||||
// KEY_INPUT_SOURCES list ordered by most recently used
|
||||
this._mruSources = [];
|
||||
this._mruSourcesBackup = null;
|
||||
this._keybindingAction =
|
||||
Main.wm.addKeybinding('switch-input-source',
|
||||
new Gio.Settings({ schema_id: "org.gnome.desktop.wm.keybindings" }),
|
||||
Meta.KeyBindingFlags.NONE,
|
||||
Shell.KeyBindingMode.ALL,
|
||||
Shell.ActionMode.ALL,
|
||||
Lang.bind(this, this._switchInputSource));
|
||||
this._keybindingActionBackward =
|
||||
Main.wm.addKeybinding('switch-input-source-backward',
|
||||
new Gio.Settings({ schema_id: "org.gnome.desktop.wm.keybindings" }),
|
||||
Meta.KeyBindingFlags.IS_REVERSED,
|
||||
Shell.KeyBindingMode.ALL,
|
||||
Shell.ActionMode.ALL,
|
||||
Lang.bind(this, this._switchInputSource));
|
||||
this._settings = new Gio.Settings({ schema_id: DESKTOP_INPUT_SOURCES_SCHEMA });
|
||||
this._settings.connect('changed::' + KEY_INPUT_SOURCES, Lang.bind(this, this._inputSourcesChanged));
|
||||
this._settings.connect('changed::' + KEY_KEYBOARD_OPTIONS, Lang.bind(this, this._keyboardOptionsChanged));
|
||||
if (Main.sessionMode.isGreeter)
|
||||
this._settings = new InputSourceSystemSettings();
|
||||
else
|
||||
this._settings = new InputSourceSessionSettings();
|
||||
this._settings.connect('input-sources-changed', Lang.bind(this, this._inputSourcesChanged));
|
||||
this._settings.connect('keyboard-options-changed', Lang.bind(this, this._keyboardOptionsChanged));
|
||||
|
||||
this._xkbInfo = KeyboardManager.getXkbInfo();
|
||||
this._keyboardManager = KeyboardManager.getKeyboardManager();
|
||||
@ -183,6 +327,7 @@ const InputSourceManager = new Lang.Class({
|
||||
this._ibusManager.connect('ready', Lang.bind(this, this._ibusReadyCallback));
|
||||
this._ibusManager.connect('properties-registered', Lang.bind(this, this._ibusPropertiesRegistered));
|
||||
this._ibusManager.connect('property-updated', Lang.bind(this, this._ibusPropertyUpdated));
|
||||
this._ibusManager.connect('set-content-type', Lang.bind(this, this._ibusSetContentType));
|
||||
|
||||
global.display.connect('modifiers-accelerator-activated', Lang.bind(this, this._modifiersSwitcher));
|
||||
|
||||
@ -190,12 +335,13 @@ const InputSourceManager = new Lang.Class({
|
||||
this._focusWindowNotifyId = 0;
|
||||
this._overviewShowingId = 0;
|
||||
this._overviewHiddenId = 0;
|
||||
this._settings.connect('changed::per-window', Lang.bind(this, this._sourcesPerWindowChanged));
|
||||
this._settings.connect('per-window-changed', Lang.bind(this, this._sourcesPerWindowChanged));
|
||||
this._sourcesPerWindowChanged();
|
||||
this._disableIBus = false;
|
||||
},
|
||||
|
||||
reload: function() {
|
||||
this._keyboardManager.setKeyboardOptions(this._settings.get_strv(KEY_KEYBOARD_OPTIONS));
|
||||
this._keyboardManager.setKeyboardOptions(this._settings.keyboardOptions);
|
||||
this._inputSourcesChanged();
|
||||
},
|
||||
|
||||
@ -239,8 +385,7 @@ const InputSourceManager = new Lang.Class({
|
||||
// effect without considerable work to consolidate the usage
|
||||
// of pushModal/popModal and grabHelper. See
|
||||
// https://bugzilla.gnome.org/show_bug.cgi?id=695143 .
|
||||
if (Main.keybindingMode == Shell.KeyBindingMode.MESSAGE_TRAY ||
|
||||
Main.keybindingMode == Shell.KeyBindingMode.TOPBAR_POPUP) {
|
||||
if (Main.actionMode == Shell.ActionMode.POPUP) {
|
||||
this._modifiersSwitcher();
|
||||
return;
|
||||
}
|
||||
@ -251,7 +396,7 @@ const InputSourceManager = new Lang.Class({
|
||||
},
|
||||
|
||||
_keyboardOptionsChanged: function() {
|
||||
this._keyboardManager.setKeyboardOptions(this._settings.get_strv(KEY_KEYBOARD_OPTIONS));
|
||||
this._keyboardManager.setKeyboardOptions(this._settings.keyboardOptions);
|
||||
this._keyboardManager.reapply();
|
||||
},
|
||||
|
||||
@ -292,8 +437,8 @@ const InputSourceManager = new Lang.Class({
|
||||
},
|
||||
|
||||
_inputSourcesChanged: function() {
|
||||
let sources = this._settings.get_value(KEY_INPUT_SOURCES);
|
||||
let nSources = sources.n_children();
|
||||
let sources = this._settings.inputSources;
|
||||
let nSources = sources.length;
|
||||
|
||||
this._inputSources = {};
|
||||
this._ibusSources = {};
|
||||
@ -302,13 +447,16 @@ const InputSourceManager = new Lang.Class({
|
||||
for (let i = 0; i < nSources; i++) {
|
||||
let displayName;
|
||||
let shortName;
|
||||
let [type, id] = sources.get_child_value(i).deep_unpack();
|
||||
let type = sources[i].type;
|
||||
let id = sources[i].id;
|
||||
let exists = false;
|
||||
|
||||
if (type == INPUT_SOURCE_TYPE_XKB) {
|
||||
[exists, displayName, shortName, , ] =
|
||||
this._xkbInfo.get_layout_info(id);
|
||||
} else if (type == INPUT_SOURCE_TYPE_IBUS) {
|
||||
if (this._disableIBus)
|
||||
continue;
|
||||
let engineDesc = this._ibusManager.getEngineDesc(id);
|
||||
if (engineDesc) {
|
||||
let language = IBus.get_language_name(engineDesc.get_language());
|
||||
@ -368,6 +516,11 @@ const InputSourceManager = new Lang.Class({
|
||||
|
||||
this._keyboardManager.setUserLayouts(sourcesList.map(function(x) { return x.xkbId; }));
|
||||
|
||||
if (!this._disableIBus && this._mruSourcesBackup) {
|
||||
this._mruSources = this._mruSourcesBackup;
|
||||
this._mruSourcesBackup = null;
|
||||
}
|
||||
|
||||
let mruSources = [];
|
||||
for (let i = 0; i < this._mruSources.length; i++) {
|
||||
for (let j = 0; j < sourcesList.length; j++)
|
||||
@ -381,6 +534,10 @@ const InputSourceManager = new Lang.Class({
|
||||
|
||||
if (this._mruSources.length > 0)
|
||||
this._mruSources[0].activate();
|
||||
|
||||
// All ibus engines are preloaded here to reduce the launching time
|
||||
// when users switch the input sources.
|
||||
this._ibusManager.preloadEngines(Object.keys(this._ibusSources));
|
||||
},
|
||||
|
||||
_makeEngineShortName: function(engineDesc) {
|
||||
@ -433,14 +590,38 @@ const InputSourceManager = new Lang.Class({
|
||||
return false;
|
||||
},
|
||||
|
||||
_getNewInputSource: function(current) {
|
||||
for (let i in this._inputSources) {
|
||||
let is = this._inputSources[i];
|
||||
if (is.type == current.type &&
|
||||
is.id == current.id)
|
||||
return is;
|
||||
_ibusSetContentType: function(im, purpose, hints) {
|
||||
if (purpose == IBus.InputPurpose.PASSWORD) {
|
||||
if (Object.keys(this._inputSources).length == Object.keys(this._ibusSources).length)
|
||||
return;
|
||||
|
||||
if (this._disableIBus)
|
||||
return;
|
||||
this._disableIBus = true;
|
||||
this._mruSourcesBackup = this._mruSources.slice();
|
||||
} else {
|
||||
if (!this._disableIBus)
|
||||
return;
|
||||
this._disableIBus = false;
|
||||
}
|
||||
return this._currentSource;
|
||||
this.reload();
|
||||
},
|
||||
|
||||
_getNewInputSource: function(current) {
|
||||
let sourceIndexes = Object.keys(this._inputSources);
|
||||
if (sourceIndexes.length == 0)
|
||||
return null;
|
||||
|
||||
if (current) {
|
||||
for (let i in this._inputSources) {
|
||||
let is = this._inputSources[i];
|
||||
if (is.type == current.type &&
|
||||
is.id == current.id)
|
||||
return is;
|
||||
}
|
||||
}
|
||||
|
||||
return this._inputSources[sourceIndexes[0]];
|
||||
},
|
||||
|
||||
_getCurrentWindow: function() {
|
||||
@ -455,20 +636,17 @@ const InputSourceManager = new Lang.Class({
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (!window._inputSources) {
|
||||
window._inputSources = this._inputSources;
|
||||
window._currentSource = this._currentSource;
|
||||
} else if (window._inputSources == this._inputSources) {
|
||||
window._currentSource.activate();
|
||||
} else {
|
||||
if (window._inputSources != this._inputSources) {
|
||||
window._inputSources = this._inputSources;
|
||||
window._currentSource = this._getNewInputSource(window._currentSource);
|
||||
window._currentSource.activate();
|
||||
}
|
||||
|
||||
if (window._currentSource)
|
||||
window._currentSource.activate();
|
||||
},
|
||||
|
||||
_sourcesPerWindowChanged: function() {
|
||||
this._sourcesPerWindow = this._settings.get_boolean('per-window');
|
||||
this._sourcesPerWindow = this._settings.perWindow;
|
||||
|
||||
if (this._sourcesPerWindow && this._focusWindowNotifyId == 0) {
|
||||
this._focusWindowNotifyId = global.display.connect('notify::focus-window',
|
||||
@ -547,7 +725,6 @@ const InputSourceIndicator = new Lang.Class({
|
||||
this._hbox.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM));
|
||||
|
||||
this.actor.add_child(this._hbox);
|
||||
this.actor.add_style_class_name('panel-status-button');
|
||||
|
||||
this._propSeparator = new PopupMenu.PopupSeparatorMenuItem();
|
||||
this.menu.addMenuItem(this._propSeparator);
|
||||
|
@ -62,13 +62,13 @@ const Indicator = new Lang.Class({
|
||||
this._indicator = this._addIndicator();
|
||||
this._indicator.icon_name = 'find-location-symbolic';
|
||||
|
||||
this._item = new PopupMenu.PopupSubMenuMenuItem(_("Location"), true);
|
||||
this._item = new PopupMenu.PopupSubMenuMenuItem('', true);
|
||||
this._item.icon.icon_name = 'find-location-symbolic';
|
||||
|
||||
this._agent = Gio.DBusExportedObject.wrapJSObject(AgentIface, this);
|
||||
this._agent.export(Gio.DBus.system, '/org/freedesktop/GeoClue2/Agent');
|
||||
|
||||
this._item.status.text = _("Enabled");
|
||||
this._item.label.text = _("Location Enabled");
|
||||
this._onOffAction = this._item.menu.addAction(_("Disable"), Lang.bind(this, this._onOnOffAction));
|
||||
this._item.menu.addSettingsAction(_("Privacy Settings"), 'gnome-privacy-panel.desktop');
|
||||
|
||||
@ -173,10 +173,11 @@ const Indicator = new Lang.Class({
|
||||
|
||||
_updateMenuLabels: function() {
|
||||
if (this._settings.get_boolean(ENABLED)) {
|
||||
this._item.status.text = this._indicator.visible ? _("In Use") : _("Enabled");
|
||||
this._item.label.text = this._indicator.visible ? _("Location In Use")
|
||||
: _("Location Enabled");
|
||||
this._onOffAction.label.text = _("Disable");
|
||||
} else {
|
||||
this._item.status.text = _("Disabled");
|
||||
this._item.label.text = _("Location Disabled");
|
||||
this._onOffAction.label.text = _("Enable");
|
||||
}
|
||||
},
|
||||
|
@ -257,16 +257,8 @@ const NMConnectionSection = new Lang.Class({
|
||||
this._radioSection.actor.visible = (nItems > 1);
|
||||
this._labelSection.actor.visible = (nItems == 1);
|
||||
|
||||
this.item.status.text = this._getStatus();
|
||||
this.item.label.text = this._getStatus();
|
||||
this.item.icon.icon_name = this._getMenuIcon();
|
||||
|
||||
// desc can be undefined at cold-plug, before we called
|
||||
// NMGtk.disambiguate_device_names() at least once
|
||||
let desc = this._getDescription();
|
||||
if (desc)
|
||||
this.item.label.text = desc;
|
||||
else
|
||||
this.item.label.text = '';
|
||||
},
|
||||
|
||||
_getMenuIcon: function() {
|
||||
@ -355,6 +347,7 @@ const NMConnectionDevice = new Lang.Class({
|
||||
this.parent(client);
|
||||
this._device = device;
|
||||
this._settings = settings;
|
||||
this._description = '';
|
||||
|
||||
this._autoConnectItem = this.item.menu.addAction(_("Connect"), Lang.bind(this, this._autoConnect));
|
||||
this._deactivateItem = this._radioSection.addAction(_("Turn Off"), Lang.bind(this, this.deactivateConnection));
|
||||
@ -454,38 +447,44 @@ const NMConnectionDevice = new Lang.Class({
|
||||
|
||||
switch(this._device.state) {
|
||||
case NetworkManager.DeviceState.DISCONNECTED:
|
||||
return _("Off");
|
||||
/* Translators: %s is a network identifier */
|
||||
return _("%s Off").format(this._getDescription());
|
||||
case NetworkManager.DeviceState.ACTIVATED:
|
||||
return _("Connected");
|
||||
/* Translators: %s is a network identifier */
|
||||
return _("%s Connected").format(this._getDescription());
|
||||
case NetworkManager.DeviceState.UNMANAGED:
|
||||
/* Translators: this is for network devices that are physically present but are not
|
||||
under NetworkManager's control (and thus cannot be used in the menu) */
|
||||
return _("Unmanaged");
|
||||
under NetworkManager's control (and thus cannot be used in the menu);
|
||||
%s is a network identifier */
|
||||
return _("%s Unmanaged").format(this._getDescription());
|
||||
case NetworkManager.DeviceState.DEACTIVATING:
|
||||
return _("Disconnecting");
|
||||
/* Translators: %s is a network identifier */
|
||||
return _("%s Disconnecting").format(this._getDescription());
|
||||
case NetworkManager.DeviceState.PREPARE:
|
||||
case NetworkManager.DeviceState.CONFIG:
|
||||
case NetworkManager.DeviceState.IP_CONFIG:
|
||||
case NetworkManager.DeviceState.IP_CHECK:
|
||||
case NetworkManager.DeviceState.SECONDARIES:
|
||||
return _("Connecting");
|
||||
/* Translators: %s is a network identifier */
|
||||
return _("%s Connecting").format(this._getDescription());
|
||||
case NetworkManager.DeviceState.NEED_AUTH:
|
||||
/* Translators: this is for network connections that require some kind of key or password */
|
||||
return _("Authentication required");
|
||||
/* Translators: this is for network connections that require some kind of key or password; %s is a network identifier */
|
||||
return _("%s Requires Authentication").format(this._getDescription());
|
||||
case NetworkManager.DeviceState.UNAVAILABLE:
|
||||
// This state is actually a compound of various states (generically unavailable,
|
||||
// firmware missing), that are exposed by different properties (whose state may
|
||||
// or may not updated when we receive state-changed).
|
||||
if (this._device.firmware_missing) {
|
||||
/* Translators: this is for devices that require some kind of firmware or kernel
|
||||
module, which is missing */
|
||||
return _("Firmware missing");
|
||||
module, which is missing; %s is a network identifier */
|
||||
return _("Firmware Missing For %s").format(this._getDescription());
|
||||
}
|
||||
/* Translators: this is for a network device that cannot be activated (for example it
|
||||
is disabled by rfkill, or it has no coverage */
|
||||
return _("Unavailable");
|
||||
is disabled by rfkill, or it has no coverage; %s is a network identifier */
|
||||
return _("%s Unavailable").format(this._getDescription());
|
||||
case NetworkManager.DeviceState.FAILED:
|
||||
return _("Connection failed");
|
||||
/* Translators: %s is a network identifier */
|
||||
return _("%s Connection Failed").format(this._getDescription());
|
||||
default:
|
||||
log('Device state invalid, is %d'.format(this._device.state));
|
||||
return 'invalid';
|
||||
@ -585,11 +584,12 @@ const NMDeviceModem = new Lang.Class({
|
||||
|
||||
_getStatus: function() {
|
||||
if (!this._client.wwan_hardware_enabled)
|
||||
return _("Hardware Disabled");
|
||||
/* Translators: %s is a network identifier */
|
||||
return _("%s Hardware Disabled").format(this._getDescription());
|
||||
else if (!this._client.wwan_enabled)
|
||||
/* Translators: this is for a network device that cannot be activated
|
||||
because it's disabled by rfkill (airplane mode) */
|
||||
return _("Disabled");
|
||||
because it's disabled by rfkill (airplane mode); %s is a network identifier */
|
||||
return _("%s Disabled").format(this._getDescription());
|
||||
else if (this._device.state == NetworkManager.DeviceState.ACTIVATED &&
|
||||
this._mobileDevice && this._mobileDevice.operator_name)
|
||||
return this._mobileDevice.operator_name;
|
||||
@ -877,7 +877,7 @@ const NMWirelessDialog = new Lang.Class({
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
|
||||
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
|
||||
this._noNetworksSpinner = new Animation.AnimatedIcon(file, 24, 24);
|
||||
this._noNetworksSpinner = new Animation.AnimatedIcon(file, 16, 16);
|
||||
this._noNetworksBox.add_actor(this._noNetworksSpinner.actor);
|
||||
this._noNetworksBox.add_actor(new St.Label({ style_class: 'no-networks-label',
|
||||
text: _("No Networks") }));
|
||||
@ -888,11 +888,11 @@ const NMWirelessDialog = new Lang.Class({
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
this._airplaneIcon = new St.Icon({ icon_size: 48 });
|
||||
this._airplaneHeadline = new St.Label({ style_class: 'nm-dialog-airplane-headline' });
|
||||
this._airplaneHeadline = new St.Label({ style_class: 'nm-dialog-airplane-headline headline' });
|
||||
this._airplaneText = new St.Label({ style_class: 'nm-dialog-airplane-text' });
|
||||
|
||||
let airplaneSubStack = new St.Widget({ layout_manager: new Clutter.BinLayout });
|
||||
this._airplaneButton = new St.Button({ style_class: 'modal-dialog-button' });
|
||||
this._airplaneButton = new St.Button({ style_class: 'modal-dialog-button button' });
|
||||
this._airplaneButton.connect('clicked', Lang.bind(this, function() {
|
||||
if (this._rfkill.airplaneMode)
|
||||
this._rfkill.airplaneMode = false;
|
||||
@ -917,10 +917,7 @@ const NMWirelessDialog = new Lang.Class({
|
||||
key: Clutter.Escape });
|
||||
this._connectButton = this.addButton({ action: Lang.bind(this, this._connect),
|
||||
label: _("Connect"),
|
||||
key: Clutter.Return },
|
||||
{ expand: true,
|
||||
x_fill: false,
|
||||
x_align: St.Align.END });
|
||||
key: Clutter.Return });
|
||||
},
|
||||
|
||||
_connect: function() {
|
||||
@ -1282,9 +1279,8 @@ const NMDeviceWireless = new Lang.Class({
|
||||
this._toggleItem.label.text = this._client.wireless_enabled ? _("Turn Off") : _("Turn On");
|
||||
this._toggleItem.actor.visible = this._client.wireless_hardware_enabled;
|
||||
|
||||
this.item.status.text = this._getStatus();
|
||||
this.item.icon.icon_name = this._getMenuIcon();
|
||||
this.item.label.text = this._description;
|
||||
this.item.label.text = this._getStatus();
|
||||
},
|
||||
|
||||
setDeviceDescription: function(desc) {
|
||||
@ -1296,18 +1292,23 @@ const NMDeviceWireless = new Lang.Class({
|
||||
let ap = this._device.active_access_point;
|
||||
|
||||
if (this._isHotSpotMaster())
|
||||
return _("Hotspot Active");
|
||||
/* Translators: %s is a network identifier */
|
||||
return _("%s Hotspot Active").format(this._description);
|
||||
else if (this._device.state >= NetworkManager.DeviceState.PREPARE &&
|
||||
this._device.state < NetworkManager.DeviceState.ACTIVATED)
|
||||
return _("Connecting");
|
||||
/* Translators: %s is a network identifier */
|
||||
return _("%s Connecting").format(this._description);
|
||||
else if (ap)
|
||||
return ssidToLabel(ap.get_ssid());
|
||||
else if (!this._client.wireless_hardware_enabled)
|
||||
return _("Hardware Disabled");
|
||||
/* Translators: %s is a network identifier */
|
||||
return _("%s Hardware Disabled").format(this._description);
|
||||
else if (!this._client.wireless_enabled)
|
||||
return _("Off");
|
||||
/* Translators: %s is a network identifier */
|
||||
return _("%s Off").format(this._description);
|
||||
else if (this._device.state == NetworkManager.DeviceState.DISCONNECTED)
|
||||
return _("Not Connected");
|
||||
/* Translators: %s is a network identifier */
|
||||
return _("%s Not Connected").format(this._description);
|
||||
else
|
||||
return '';
|
||||
},
|
||||
@ -1509,7 +1510,7 @@ const NMVPNSection = new Lang.Class({
|
||||
return item.getName();
|
||||
}
|
||||
|
||||
return _("Off");
|
||||
return _("VPN Off");
|
||||
},
|
||||
|
||||
_getMenuIcon: function() {
|
||||
@ -1867,7 +1868,7 @@ const NMApplet = new Lang.Class({
|
||||
_connectionRemoved: function(connection) {
|
||||
let pos = this._connections.indexOf(connection);
|
||||
if (pos != -1)
|
||||
this._connections.splice(connection, 1);
|
||||
this._connections.splice(pos, 1);
|
||||
|
||||
let section = connection._section;
|
||||
|
||||
|
@ -112,12 +112,6 @@ const Indicator = new Lang.Class({
|
||||
this._item.icon.icon_name = icon;
|
||||
|
||||
// The status label
|
||||
this._item.status.text = this._getStatus();
|
||||
|
||||
// The sub-menu heading
|
||||
if (this._proxy.Type == UPower.DeviceKind.UPS)
|
||||
this._item.label.text = _("UPS");
|
||||
else
|
||||
this._item.label.text = _("Battery");
|
||||
this._item.label.text = this._getStatus();
|
||||
},
|
||||
});
|
||||
|
@ -85,9 +85,8 @@ const Indicator = new Lang.Class({
|
||||
// The menu only appears when airplane mode is on, so just
|
||||
// statically build it as if it was on, rather than dynamically
|
||||
// changing the menu contents.
|
||||
this._item = new PopupMenu.PopupSubMenuMenuItem(_("Airplane Mode"), true);
|
||||
this._item = new PopupMenu.PopupSubMenuMenuItem(_("Airplane Mode On"), true);
|
||||
this._item.icon.icon_name = 'airplane-mode-symbolic';
|
||||
this._item.status.text = _("On");
|
||||
this._offItem = this._item.menu.addAction(_("Turn Off"), Lang.bind(this, function() {
|
||||
this._manager.airplaneMode = false;
|
||||
}));
|
||||
|
@ -17,15 +17,24 @@ const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown';
|
||||
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
|
||||
const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
|
||||
const PRIVACY_SCHEMA = 'org.gnome.desktop.privacy'
|
||||
const DISABLE_USER_SWITCH_KEY = 'disable-user-switching';
|
||||
const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen';
|
||||
const DISABLE_LOG_OUT_KEY = 'disable-log-out';
|
||||
const DISABLE_RESTART_KEY = 'disable-restart-buttons';
|
||||
const ALWAYS_SHOW_LOG_OUT_KEY = 'always-show-log-out';
|
||||
|
||||
const SENSOR_BUS_NAME = 'net.hadess.SensorProxy';
|
||||
const SENSOR_OBJECT_PATH = '/net/hadess/SensorProxy';
|
||||
|
||||
const SensorProxyInterface = '<node> \
|
||||
<interface name="net.hadess.SensorProxy"> \
|
||||
<property name="HasAccelerometer" type="b" access="read"/> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const SensorProxy = Gio.DBusProxy.makeProxyWrapper(SensorProxyInterface);
|
||||
|
||||
const AltSwitcher = new Lang.Class({
|
||||
Name: 'AltSwitcher',
|
||||
|
||||
@ -95,10 +104,8 @@ const Indicator = new Lang.Class({
|
||||
_init: function() {
|
||||
this.parent();
|
||||
|
||||
this._screenSaverSettings = new Gio.Settings({ schema_id: SCREENSAVER_SCHEMA });
|
||||
this._loginScreenSettings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA });
|
||||
this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA });
|
||||
this._privacySettings = new Gio.Settings({ schema_id: PRIVACY_SCHEMA });
|
||||
this._orientationSettings = new Gio.Settings({ schema_id: 'org.gnome.settings-daemon.peripherals.touchscreen' });
|
||||
|
||||
this._session = new GnomeSession.SessionManager();
|
||||
@ -129,6 +136,7 @@ const Indicator = new Lang.Class({
|
||||
Lang.bind(this, this._updateMultiUser));
|
||||
this._updateSwitchUser();
|
||||
this._updateMultiUser();
|
||||
this._updateLockScreen();
|
||||
|
||||
// Whether shutdown is available or not depends on both lockdown
|
||||
// settings (disable-log-out) and Polkit policy - the latter doesn't
|
||||
@ -147,23 +155,32 @@ const Indicator = new Lang.Class({
|
||||
|
||||
this._orientationSettings.connect('changed::orientation-lock',
|
||||
Lang.bind(this, this._updateOrientationLock));
|
||||
this._orientationExists = false;
|
||||
Gio.DBus.session.watch_name('org.gnome.SettingsDaemon.Orientation',
|
||||
Gio.BusNameWatcherFlags.NONE,
|
||||
Lang.bind(this, function() {
|
||||
this._orientationExists = true;
|
||||
this._updateOrientationLock();
|
||||
}),
|
||||
Lang.bind(this, function() {
|
||||
this._orientationExists = false;
|
||||
this._updateOrientationLock();
|
||||
}));
|
||||
Gio.DBus.system.watch_name(SENSOR_BUS_NAME,
|
||||
Gio.BusNameWatcherFlags.NONE,
|
||||
Lang.bind(this, this._sensorProxyAppeared),
|
||||
Lang.bind(this, function() {
|
||||
this._sensorProxy = null;
|
||||
this._updateOrientationLock();
|
||||
}));
|
||||
this._updateOrientationLock();
|
||||
|
||||
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
|
||||
this._sessionUpdated();
|
||||
},
|
||||
|
||||
_sensorProxyAppeared: function() {
|
||||
this._sensorProxy = new SensorProxy(Gio.DBus.system, SENSOR_BUS_NAME, SENSOR_OBJECT_PATH,
|
||||
Lang.bind(this, function(proxy, error) {
|
||||
if (error) {
|
||||
log(error.message);
|
||||
return;
|
||||
}
|
||||
this._sensorProxy.connect('g-properties-changed',
|
||||
Lang.bind(this, this._updateOrientationLock));
|
||||
this._updateOrientationLock();
|
||||
}));
|
||||
},
|
||||
|
||||
_updateActionsVisibility: function() {
|
||||
let visible = (this._settingsAction.visible ||
|
||||
this._orientationLockAction.visible ||
|
||||
@ -234,13 +251,22 @@ const Indicator = new Lang.Class({
|
||||
let file = Gio.File.new_for_path(iconFile);
|
||||
let gicon = new Gio.FileIcon({ file: file });
|
||||
this._switchUserSubMenu.icon.gicon = gicon;
|
||||
|
||||
this._switchUserSubMenu.icon.add_style_class_name('user-icon');
|
||||
this._switchUserSubMenu.icon.remove_style_class_name('default-icon');
|
||||
} else {
|
||||
this._switchUserSubMenu.icon.icon_name = 'avatar-default-symbolic';
|
||||
|
||||
this._switchUserSubMenu.icon.add_style_class_name('default-icon');
|
||||
this._switchUserSubMenu.icon.remove_style_class_name('user-icon');
|
||||
}
|
||||
},
|
||||
|
||||
_updateOrientationLock: function() {
|
||||
this._orientationLockAction.visible = this._orientationExists;
|
||||
if (this._sensorProxy)
|
||||
this._orientationLockAction.visible = this._sensorProxy.HasAccelerometer;
|
||||
else
|
||||
this._orientationLockAction.visible = false;
|
||||
|
||||
let locked = this._orientationSettings.get_boolean('orientation-lock');
|
||||
let icon = this._orientationLockAction.child;
|
||||
@ -285,7 +311,7 @@ const Indicator = new Lang.Class({
|
||||
let disabled = Main.sessionMode.isLocked ||
|
||||
(Main.sessionMode.isGreeter &&
|
||||
this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY));
|
||||
this._suspendAction.visible = this._haveShutdown && !disabled;
|
||||
this._suspendAction.visible = this._haveSuspend && !disabled;
|
||||
this._updateActionsVisibility();
|
||||
},
|
||||
|
||||
@ -324,6 +350,9 @@ const Indicator = new Lang.Class({
|
||||
this._switchUserSubMenu.menu.addMenuItem(item);
|
||||
this._logoutItem = item;
|
||||
|
||||
this._switchUserSubMenu.menu.addSettingsAction(_("Account Settings"),
|
||||
'gnome-user-accounts-panel.desktop');
|
||||
|
||||
this._user.connect('notify::is-loaded', Lang.bind(this, this._updateSwitchUserSubMenu));
|
||||
this._user.connect('changed', Lang.bind(this, this._updateSwitchUserSubMenu));
|
||||
|
||||
|
@ -87,8 +87,6 @@ const SwitcherPopup = new Lang.Class({
|
||||
|
||||
let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
|
||||
let rightPadding = this.actor.get_theme_node().get_padding(St.Side.RIGHT);
|
||||
let bottomPadding = this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
|
||||
let vPadding = this.actor.get_theme_node().get_vertical_padding();
|
||||
let hPadding = leftPadding + rightPadding;
|
||||
|
||||
// Allocate the switcherList
|
||||
|
@ -154,7 +154,7 @@ const UnlockDialog = new Lang.Class({
|
||||
return true;
|
||||
|
||||
if (!Main.pushModal(this.actor, { timestamp: timestamp,
|
||||
keybindingMode: Shell.KeyBindingMode.UNLOCK_SCREEN }))
|
||||
actionMode: Shell.ActionMode.UNLOCK_SCREEN }))
|
||||
return false;
|
||||
|
||||
this._isModal = true;
|
||||
|
@ -6,6 +6,7 @@ const Clutter = imports.gi.Clutter;
|
||||
const AccountsService = imports.gi.AccountsService;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GObject = imports.gi.GObject;
|
||||
const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
|
||||
@ -117,6 +118,7 @@ const UserWidgetLabel = new Lang.Class({
|
||||
this._currentLabel = this._realNameLabel;
|
||||
else
|
||||
this._currentLabel = this._userNameLabel;
|
||||
this.label_actor = this._currentLabel;
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
childBox.x1 = 0;
|
||||
@ -158,6 +160,9 @@ const UserWidget = new Lang.Class({
|
||||
this._label = new UserWidgetLabel(user);
|
||||
this.actor.add_child(this._label);
|
||||
|
||||
this._label.bind_property('label-actor', this.actor, 'label-actor',
|
||||
GObject.BindingFlags.SYNC_CREATE);
|
||||
|
||||
this._userLoadedId = this._user.connect('notify::is-loaded', Lang.bind(this, this._updateUser));
|
||||
this._userChangedId = this._user.connect('changed', Lang.bind(this, this._updateUser));
|
||||
this._updateUser();
|
||||
|
@ -65,7 +65,8 @@ const ShowOverviewAction = new Lang.Class({
|
||||
},
|
||||
|
||||
vfunc_gesture_prepare : function(action, actor) {
|
||||
return this.get_n_current_points() == this.get_n_touch_points();
|
||||
return Main.actionMode == Shell.ActionMode.NORMAL &&
|
||||
this.get_n_current_points() == this.get_n_touch_points();
|
||||
},
|
||||
|
||||
_getBoundingRect : function(motion) {
|
||||
@ -151,7 +152,7 @@ const ViewSelector = new Lang.Class({
|
||||
|
||||
this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
|
||||
this._workspacesPage = this._addPage(this._workspacesDisplay.actor,
|
||||
_("Windows"), 'emblem-documents-symbolic');
|
||||
_("Windows"), 'focus-windows-symbolic');
|
||||
|
||||
this.appDisplay = new AppDisplay.AppDisplay();
|
||||
this._appsPage = this._addPage(this.appDisplay.actor,
|
||||
@ -193,27 +194,33 @@ const ViewSelector = new Lang.Class({
|
||||
// the windows to animate, but now we no longer want to
|
||||
// show it given that we are now on the apps page or
|
||||
// search page.
|
||||
if (this._activePage != this._workspacesPage)
|
||||
if (this._activePage != this._workspacesPage) {
|
||||
this._workspacesPage.opacity = 0;
|
||||
this._workspacesPage.hide();
|
||||
}
|
||||
}));
|
||||
|
||||
Main.wm.addKeybinding('toggle-application-view',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.NONE,
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._toggleAppsPage));
|
||||
|
||||
Main.wm.addKeybinding('toggle-overview',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.NONE,
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(Main.overview, Main.overview.toggle));
|
||||
|
||||
let gesture;
|
||||
|
||||
gesture = new EdgeDragAction.EdgeDragAction(St.Side.LEFT);
|
||||
let side;
|
||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
||||
side = St.Side.RIGHT;
|
||||
else
|
||||
side = St.Side.LEFT;
|
||||
let gesture = new EdgeDragAction.EdgeDragAction(side,
|
||||
Shell.ActionMode.NORMAL);
|
||||
gesture.connect('activated', Lang.bind(this, function() {
|
||||
if (Main.overview.visible)
|
||||
Main.overview.hide();
|
||||
@ -458,6 +465,12 @@ const ViewSelector = new Lang.Class({
|
||||
},
|
||||
|
||||
_shouldTriggerSearch: function(symbol) {
|
||||
if (symbol == Clutter.Multi_key)
|
||||
return true;
|
||||
|
||||
if (symbol == Clutter.BackSpace && this._searchActive)
|
||||
return true;
|
||||
|
||||
let unicode = Clutter.keysym_to_unicode(symbol);
|
||||
if (unicode == 0)
|
||||
return false;
|
||||
@ -465,7 +478,7 @@ const ViewSelector = new Lang.Class({
|
||||
if (getTermsForSearchString(String.fromCharCode(unicode)).length > 0)
|
||||
return true;
|
||||
|
||||
return symbol == Clutter.BackSpace && this._searchActive;
|
||||
return false;
|
||||
},
|
||||
|
||||
startSearch: function(event) {
|
||||
@ -548,7 +561,9 @@ const ViewSelector = new Lang.Class({
|
||||
_onCapturedEvent: function(actor, event) {
|
||||
if (event.type() == Clutter.EventType.BUTTON_PRESS) {
|
||||
let source = event.get_source();
|
||||
if (source != this._text && this._text.text == '' &&
|
||||
if (source != this._text &&
|
||||
this._text.text == '' &&
|
||||
!this._text.has_preedit () &&
|
||||
!Main.layoutManager.keyboardBox.contains(source)) {
|
||||
// the user clicked outside after activating the entry, but
|
||||
// with no search term entered and no keyboard button pressed
|
||||
|
@ -11,7 +11,8 @@ const WindowAttentionHandler = new Lang.Class({
|
||||
|
||||
_init : function() {
|
||||
this._tracker = Shell.WindowTracker.get_default();
|
||||
global.display.connect('window-demands-attention', Lang.bind(this, this._onWindowDemandsAttention));
|
||||
this._windowDemandsAttentionId = global.display.connect('window-demands-attention',
|
||||
Lang.bind(this, this._onWindowDemandsAttention));
|
||||
},
|
||||
|
||||
_getTitleAndBanner: function(app, window) {
|
||||
@ -39,7 +40,7 @@ const WindowAttentionHandler = new Lang.Class({
|
||||
let [title, banner] = this._getTitleAndBanner(app, window);
|
||||
|
||||
let notification = new MessageTray.Notification(source, title, banner);
|
||||
notification.connect('clicked', function() {
|
||||
notification.connect('activated', function() {
|
||||
source.open();
|
||||
});
|
||||
notification.setForFeedback(true);
|
||||
|
@ -19,8 +19,6 @@ const Tweener = imports.ui.tweener;
|
||||
const WindowMenu = imports.ui.windowMenu;
|
||||
|
||||
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
|
||||
const MAXIMIZE_WINDOW_ANIMATION_TIME = 0.15;
|
||||
const UNMAXIMIZE_WINDOW_ANIMATION_TIME = 0.15;
|
||||
const MINIMIZE_WINDOW_ANIMATION_TIME = 0.2;
|
||||
const SHOW_WINDOW_ANIMATION_TIME = 0.15;
|
||||
const DIALOG_SHOW_WINDOW_ANIMATION_TIME = 0.1;
|
||||
@ -83,12 +81,10 @@ const DisplayChangeDialog = new Lang.Class({
|
||||
*/
|
||||
this._cancelButton = this.addButton({ label: _("Revert Settings"),
|
||||
action: Lang.bind(this, this._onFailure),
|
||||
key: Clutter.Escape },
|
||||
{ expand: true, x_fill: false, x_align: St.Align.START });
|
||||
key: Clutter.Escape });
|
||||
this._okButton = this.addButton({ label: _("Keep Changes"),
|
||||
action: Lang.bind(this, this._onSuccess),
|
||||
default: true },
|
||||
{ expand: false, x_fill: false, x_align: St.Align.END });
|
||||
default: true });
|
||||
|
||||
this._timeoutId = Mainloop.timeout_add(ONE_SECOND, Lang.bind(this, this._tick));
|
||||
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._tick');
|
||||
@ -197,6 +193,8 @@ const WorkspaceTracker = new Lang.Class({
|
||||
this._workspaces = [];
|
||||
this._checkWorkspacesId = 0;
|
||||
|
||||
this._pauseWorkspaceCheck = false;
|
||||
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
tracker.connect('startup-sequence-changed', Lang.bind(this, this._queueCheckWorkspaces));
|
||||
|
||||
@ -215,11 +213,20 @@ const WorkspaceTracker = new Lang.Class({
|
||||
|
||||
_getWorkspaceSettings: function() {
|
||||
let settings = global.get_overrides_settings();
|
||||
if (settings.list_keys().indexOf('dynamic-workspaces') > -1)
|
||||
if (settings &&
|
||||
settings.settings_schema.list_keys().indexOf('dynamic-workspaces') > -1)
|
||||
return settings;
|
||||
return new Gio.Settings({ schema_id: 'org.gnome.mutter' });
|
||||
},
|
||||
|
||||
blockUpdates: function() {
|
||||
this._pauseWorkspaceCheck = true;
|
||||
},
|
||||
|
||||
unblockUpdates: function() {
|
||||
this._pauseWorkspaceCheck = false;
|
||||
},
|
||||
|
||||
_checkWorkspaces: function() {
|
||||
let i;
|
||||
let emptyWorkspaces = [];
|
||||
@ -229,6 +236,10 @@ const WorkspaceTracker = new Lang.Class({
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update workspaces only if Dynamic Workspace Management has not been paused by some other function
|
||||
if (this._pauseWorkspaceCheck)
|
||||
return true;
|
||||
|
||||
for (i = 0; i < this._workspaces.length; i++) {
|
||||
let lastRemoved = this._workspaces[i]._lastRemovedWindow;
|
||||
if ((lastRemoved &&
|
||||
@ -464,50 +475,100 @@ const TilePreview = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
const TouchpadWorkspaceSwitchAction = new Lang.Class({
|
||||
Name: 'TouchpadWorkspaceSwitchAction',
|
||||
|
||||
_init: function(actor) {
|
||||
this._dx = 0;
|
||||
this._dy = 0;
|
||||
actor.connect('captured-event', Lang.bind(this, this._handleEvent));
|
||||
},
|
||||
|
||||
_checkActivated: function() {
|
||||
const MOTION_THRESHOLD = 50;
|
||||
let allowedModes = Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW;
|
||||
let dir;
|
||||
|
||||
if ((allowedModes & Main.actionMode) == 0)
|
||||
return;
|
||||
|
||||
if (this._dy < -MOTION_THRESHOLD)
|
||||
dir = Meta.MotionDirection.DOWN;
|
||||
else if (this._dy > MOTION_THRESHOLD)
|
||||
dir = Meta.MotionDirection.UP;
|
||||
else if (this._dx < -MOTION_THRESHOLD)
|
||||
dir = Meta.MotionDirection.RIGHT;
|
||||
else if (this._dx > MOTION_THRESHOLD)
|
||||
dir = Meta.MotionDirection.LEFT;
|
||||
else
|
||||
return;
|
||||
|
||||
this.emit('activated', dir);
|
||||
},
|
||||
|
||||
_handleEvent: function(actor, event) {
|
||||
if (event.type() != Clutter.EventType.TOUCHPAD_SWIPE)
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (event.get_gesture_swipe_finger_count() != 4)
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (event.get_gesture_phase() == Clutter.TouchpadGesturePhase.UPDATE) {
|
||||
let [dx, dy] = event.get_gesture_motion_delta(event);
|
||||
|
||||
this._dx += dx;
|
||||
this._dy += dy;
|
||||
} else {
|
||||
if (event.get_gesture_phase() == Clutter.TouchpadGesturePhase.END)
|
||||
this._checkActivated();
|
||||
|
||||
this._dx = 0;
|
||||
this._dy = 0;
|
||||
}
|
||||
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(TouchpadWorkspaceSwitchAction.prototype);
|
||||
|
||||
const WorkspaceSwitchAction = new Lang.Class({
|
||||
Name: 'WorkspaceSwitchAction',
|
||||
Extends: Clutter.GestureAction,
|
||||
Extends: Clutter.SwipeAction,
|
||||
|
||||
_init : function() {
|
||||
const MOTION_THRESHOLD = 50;
|
||||
|
||||
this.parent();
|
||||
this.set_n_touch_points(4);
|
||||
this.set_threshold_trigger_distance(MOTION_THRESHOLD, MOTION_THRESHOLD);
|
||||
|
||||
global.display.connect('grab-op-begin', Lang.bind(this, function() {
|
||||
this.cancel();
|
||||
}));
|
||||
},
|
||||
|
||||
vfunc_gesture_prepare : function(action, actor) {
|
||||
return this.get_n_current_points() == this.get_n_touch_points();
|
||||
vfunc_gesture_prepare : function(actor) {
|
||||
let allowedModes = Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW;
|
||||
|
||||
if (!this.parent(actor))
|
||||
return false;
|
||||
|
||||
return (allowedModes & Main.actionMode);
|
||||
},
|
||||
|
||||
vfunc_gesture_end : function(action, actor) {
|
||||
const MOTION_THRESHOLD = 50;
|
||||
vfunc_swept : function(actor, direction) {
|
||||
let dir;
|
||||
|
||||
// Just check one touchpoint here
|
||||
let [startX, startY] = this.get_press_coords(0);
|
||||
let [x, y] = this.get_motion_coords(0);
|
||||
let offsetX = x - startX;
|
||||
let offsetY = y - startY;
|
||||
let direction;
|
||||
if (direction & Clutter.SwipeDirection.UP)
|
||||
dir = Meta.MotionDirection.DOWN;
|
||||
else if (direction & Clutter.SwipeDirection.DOWN)
|
||||
dir = Meta.MotionDirection.UP;
|
||||
else if (direction & Clutter.SwipeDirection.LEFT)
|
||||
dir = Meta.MotionDirection.RIGHT;
|
||||
else if (direction & Clutter.SwipeDirection.RIGHT)
|
||||
dir = Meta.MotionDirection.LEFT;
|
||||
|
||||
if (Math.abs(offsetX) < MOTION_THRESHOLD &&
|
||||
Math.abs(offsetY) < MOTION_THRESHOLD)
|
||||
return;
|
||||
|
||||
if (Math.abs(offsetY) > Math.abs(offsetX)) {
|
||||
if (offsetY > 0)
|
||||
direction = Meta.MotionDirection.UP;
|
||||
else
|
||||
direction = Meta.MotionDirection.DOWN;
|
||||
} else {
|
||||
if (offsetX > 0)
|
||||
direction = Meta.MotionDirection.LEFT;
|
||||
else
|
||||
direction = Meta.MotionDirection.RIGHT;
|
||||
}
|
||||
|
||||
this.emit('activated', direction);
|
||||
this.emit('activated', dir);
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(WorkspaceSwitchAction.prototype);
|
||||
@ -526,7 +587,7 @@ const AppSwitchAction = new Lang.Class({
|
||||
},
|
||||
|
||||
vfunc_gesture_prepare : function(action, actor) {
|
||||
if (Main.overview.visible) {
|
||||
if (Main.actionMode != Shell.ActionMode.NORMAL) {
|
||||
this.cancel();
|
||||
return false;
|
||||
}
|
||||
@ -578,6 +639,35 @@ const AppSwitchAction = new Lang.Class({
|
||||
});
|
||||
Signals.addSignalMethods(AppSwitchAction.prototype);
|
||||
|
||||
const ResizePopup = new Lang.Class({
|
||||
Name: 'ResizePopup',
|
||||
|
||||
_init: function() {
|
||||
this._widget = new St.Widget({ layout_manager: new Clutter.BinLayout() });
|
||||
this._label = new St.Label({ style_class: 'resize-popup',
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
x_expand: true, y_expand: true });
|
||||
this._widget.add_child(this._label);
|
||||
Main.uiGroup.add_actor(this._widget);
|
||||
},
|
||||
|
||||
set: function(rect, displayW, displayH) {
|
||||
/* Translators: This represents the size of a window. The first number is
|
||||
* the width of the window and the second is the height. */
|
||||
let text = _("%d x %d").format(displayW, displayH);
|
||||
this._label.set_text(text);
|
||||
|
||||
this._widget.set_position(rect.x, rect.y);
|
||||
this._widget.set_size(rect.width, rect.height);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this._widget.destroy();
|
||||
this._widget = null;
|
||||
},
|
||||
});
|
||||
|
||||
const WindowManager = new Lang.Class({
|
||||
Name: 'WindowManager',
|
||||
|
||||
@ -585,8 +675,7 @@ const WindowManager = new Lang.Class({
|
||||
this._shellwm = global.window_manager;
|
||||
|
||||
this._minimizing = [];
|
||||
this._maximizing = [];
|
||||
this._unmaximizing = [];
|
||||
this._unminimizing = [];
|
||||
this._mapping = [];
|
||||
this._destroying = [];
|
||||
this._movingWindow = null;
|
||||
@ -595,12 +684,12 @@ const WindowManager = new Lang.Class({
|
||||
|
||||
this._allowedKeybindings = {};
|
||||
|
||||
this._isWorkspacePrepended = false;
|
||||
|
||||
this._switchData = null;
|
||||
this._shellwm.connect('kill-switch-workspace', Lang.bind(this, this._switchWorkspaceDone));
|
||||
this._shellwm.connect('kill-window-effects', Lang.bind(this, function (shellwm, actor) {
|
||||
this._minimizeWindowDone(shellwm, actor);
|
||||
this._maximizeWindowDone(shellwm, actor);
|
||||
this._unmaximizeWindowDone(shellwm, actor);
|
||||
this._mapWindowDone(shellwm, actor);
|
||||
this._destroyWindowDone(shellwm, actor);
|
||||
}));
|
||||
@ -610,185 +699,209 @@ const WindowManager = new Lang.Class({
|
||||
this._shellwm.connect('hide-tile-preview', Lang.bind(this, this._hideTilePreview));
|
||||
this._shellwm.connect('show-window-menu', Lang.bind(this, this._showWindowMenu));
|
||||
this._shellwm.connect('minimize', Lang.bind(this, this._minimizeWindow));
|
||||
this._shellwm.connect('maximize', Lang.bind(this, this._maximizeWindow));
|
||||
this._shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow));
|
||||
this._shellwm.connect('unminimize', Lang.bind(this, this._unminimizeWindow));
|
||||
this._shellwm.connect('size-change', Lang.bind(this, this._sizeChangeWindow));
|
||||
this._shellwm.connect('map', Lang.bind(this, this._mapWindow));
|
||||
this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
|
||||
this._shellwm.connect('filter-keybinding', Lang.bind(this, this._filterKeybinding));
|
||||
this._shellwm.connect('confirm-display-change', Lang.bind(this, this._confirmDisplayChange));
|
||||
global.screen.connect('restacked', Lang.bind(this, this._syncStacking));
|
||||
|
||||
this._workspaceSwitcherPopup = null;
|
||||
this._tilePreview = null;
|
||||
|
||||
this.allowKeybinding('switch-to-session-1', Shell.ActionMode.ALL);
|
||||
this.allowKeybinding('switch-to-session-2', Shell.ActionMode.ALL);
|
||||
this.allowKeybinding('switch-to-session-3', Shell.ActionMode.ALL);
|
||||
this.allowKeybinding('switch-to-session-4', Shell.ActionMode.ALL);
|
||||
this.allowKeybinding('switch-to-session-5', Shell.ActionMode.ALL);
|
||||
this.allowKeybinding('switch-to-session-6', Shell.ActionMode.ALL);
|
||||
this.allowKeybinding('switch-to-session-7', Shell.ActionMode.ALL);
|
||||
this.allowKeybinding('switch-to-session-8', Shell.ActionMode.ALL);
|
||||
this.allowKeybinding('switch-to-session-9', Shell.ActionMode.ALL);
|
||||
this.allowKeybinding('switch-to-session-10', Shell.ActionMode.ALL);
|
||||
this.allowKeybinding('switch-to-session-11', Shell.ActionMode.ALL);
|
||||
this.allowKeybinding('switch-to-session-12', Shell.ActionMode.ALL);
|
||||
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-left',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-right',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-up',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-down',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-last',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-left',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-right',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-up',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-down',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-1',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-2',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-3',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-4',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-5',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-6',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-7',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-8',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-9',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-10',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-11',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-to-workspace-12',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-1',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-2',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-3',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-4',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-5',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-6',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-7',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-8',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-9',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-10',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-11',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-12',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('move-to-workspace-last',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._showWorkspaceSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-applications',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._startAppSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-group',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._startAppSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-applications-backward',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._startAppSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-group-backward',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._startAppSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-windows',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._startWindowSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-windows-backward',
|
||||
Shell.KeyBindingMode.NORMAL,
|
||||
Shell.ActionMode.NORMAL,
|
||||
Lang.bind(this, this._startWindowSwitcher));
|
||||
this.setCustomKeybindingHandler('switch-panels',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW |
|
||||
Shell.KeyBindingMode.LOCK_SCREEN |
|
||||
Shell.KeyBindingMode.UNLOCK_SCREEN |
|
||||
Shell.KeyBindingMode.LOGIN_SCREEN,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW |
|
||||
Shell.ActionMode.LOCK_SCREEN |
|
||||
Shell.ActionMode.UNLOCK_SCREEN |
|
||||
Shell.ActionMode.LOGIN_SCREEN,
|
||||
Lang.bind(this, this._startA11ySwitcher));
|
||||
this.setCustomKeybindingHandler('switch-panels-backward',
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.OVERVIEW |
|
||||
Shell.KeyBindingMode.LOCK_SCREEN |
|
||||
Shell.KeyBindingMode.UNLOCK_SCREEN |
|
||||
Shell.KeyBindingMode.LOGIN_SCREEN,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW |
|
||||
Shell.ActionMode.LOCK_SCREEN |
|
||||
Shell.ActionMode.UNLOCK_SCREEN |
|
||||
Shell.ActionMode.LOGIN_SCREEN,
|
||||
Lang.bind(this, this._startA11ySwitcher));
|
||||
|
||||
this.addKeybinding('pause-resume-tweens',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.NONE,
|
||||
Shell.KeyBindingMode.ALL,
|
||||
Shell.ActionMode.ALL,
|
||||
Lang.bind(this, this._toggleTweens));
|
||||
|
||||
this.addKeybinding('open-application-menu',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.NONE,
|
||||
Shell.KeyBindingMode.NORMAL |
|
||||
Shell.KeyBindingMode.TOPBAR_POPUP,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.POPUP,
|
||||
Lang.bind(this, this._toggleAppMenu));
|
||||
|
||||
this.addKeybinding('toggle-message-tray',
|
||||
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
||||
Meta.KeyBindingFlags.NONE,
|
||||
Shell.ActionMode.NORMAL |
|
||||
Shell.ActionMode.OVERVIEW |
|
||||
Shell.ActionMode.POPUP,
|
||||
Lang.bind(this, this._toggleCalendar));
|
||||
|
||||
global.display.connect('show-resize-popup', Lang.bind(this, this._showResizePopup));
|
||||
|
||||
Main.overview.connect('showing', Lang.bind(this, function() {
|
||||
for (let i = 0; i < this._dimmedWindows.length; i++)
|
||||
this._undimWindow(this._dimmedWindows[i]);
|
||||
@ -807,15 +920,22 @@ const WindowManager = new Lang.Class({
|
||||
false, -1, 1);
|
||||
|
||||
let gesture = new WorkspaceSwitchAction();
|
||||
gesture.connect('activated', Lang.bind(this, function(action, direction) {
|
||||
let newWs = global.screen.get_active_workspace().get_neighbor(direction);
|
||||
this.actionMoveWorkspace(newWs);
|
||||
}));
|
||||
gesture.connect('activated', Lang.bind(this, this._actionSwitchWorkspace));
|
||||
global.stage.add_action(gesture);
|
||||
|
||||
// This is not a normal Clutter.GestureAction, doesn't need add_action()
|
||||
gesture = new TouchpadWorkspaceSwitchAction(global.stage);
|
||||
gesture.connect('activated', Lang.bind(this, this._actionSwitchWorkspace));
|
||||
|
||||
gesture = new AppSwitchAction();
|
||||
gesture.connect('activated', Lang.bind(this, this._switchApp));
|
||||
global.stage.add_action(gesture);
|
||||
|
||||
},
|
||||
|
||||
_actionSwitchWorkspace: function(action, direction) {
|
||||
let newWs = global.screen.get_active_workspace().get_neighbor(direction);
|
||||
this.actionMoveWorkspace(newWs);
|
||||
},
|
||||
|
||||
_lookupIndex: function (windows, metaWindow) {
|
||||
@ -854,6 +974,46 @@ const WindowManager = new Lang.Class({
|
||||
Main.activateWindow(nextWindow);
|
||||
},
|
||||
|
||||
insertWorkspace: function(pos) {
|
||||
if (!Meta.prefs_get_dynamic_workspaces())
|
||||
return;
|
||||
|
||||
global.screen.append_new_workspace(false, global.get_current_time());
|
||||
|
||||
let windows = global.get_window_actors().map(function(winActor) {
|
||||
return winActor.meta_window;
|
||||
});
|
||||
|
||||
// To create a new workspace, we slide all the windows on workspaces
|
||||
// below us to the next workspace, leaving a blank workspace for us
|
||||
// to recycle.
|
||||
windows.forEach(function(window) {
|
||||
// If the window is attached to an ancestor, we don't need/want
|
||||
// to move it
|
||||
if (window.get_transient_for() != null)
|
||||
return;
|
||||
// Same for OR windows
|
||||
if (window.is_override_redirect())
|
||||
return;
|
||||
// Windows on workspaces below pos don't need moving
|
||||
let index = window.get_workspace().index();
|
||||
if (index < pos)
|
||||
return;
|
||||
window.change_workspace_by_index(index + 1, true);
|
||||
});
|
||||
|
||||
// If the new workspace was inserted before the active workspace,
|
||||
// activate the workspace to which its windows went
|
||||
let activeIndex = global.screen.get_active_workspace_index();
|
||||
if (activeIndex >= pos) {
|
||||
let newWs = global.screen.get_workspace_by_index(activeIndex + 1);
|
||||
this._blockAnimations = true;
|
||||
newWs.activate(global.get_current_time());
|
||||
this._blockAnimations = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
keepWorkspaceAlive: function(workspace, duration) {
|
||||
if (!this._workspaceTracker)
|
||||
return;
|
||||
@ -875,7 +1035,7 @@ const WindowManager = new Lang.Class({
|
||||
|
||||
removeKeybinding: function(name) {
|
||||
if (global.display.remove_keybinding(name))
|
||||
this.allowKeybinding(name, Shell.KeyBindingMode.NONE);
|
||||
this.allowKeybinding(name, Shell.ActionMode.NONE);
|
||||
},
|
||||
|
||||
allowKeybinding: function(name, modes) {
|
||||
@ -883,7 +1043,7 @@ const WindowManager = new Lang.Class({
|
||||
},
|
||||
|
||||
_shouldAnimate: function() {
|
||||
return !Main.overview.visible;
|
||||
return !(Main.overview.visible || this._blockAnimations);
|
||||
},
|
||||
|
||||
_shouldAnimateActor: function(actor, types) {
|
||||
@ -980,21 +1140,85 @@ const WindowManager = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
_maximizeWindow : function(shellwm, actor, targetX, targetY, targetWidth, targetHeight) {
|
||||
shellwm.completed_maximize(actor);
|
||||
_unminimizeWindow : function(shellwm, actor) {
|
||||
let types = [Meta.WindowType.NORMAL,
|
||||
Meta.WindowType.MODAL_DIALOG,
|
||||
Meta.WindowType.DIALOG];
|
||||
if (!this._shouldAnimateActor(actor, types)) {
|
||||
shellwm.completed_unminimize(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
this._unminimizing.push(actor);
|
||||
|
||||
if (actor.meta_window.is_monitor_sized()) {
|
||||
actor.opacity = 0;
|
||||
actor.set_scale(1.0, 1.0);
|
||||
Tweener.addTween(actor,
|
||||
{ opacity: 255,
|
||||
time: MINIMIZE_WINDOW_ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: this._unminimizeWindowDone,
|
||||
onCompleteScope: this,
|
||||
onCompleteParams: [shellwm, actor],
|
||||
onOverwrite: this._unminimizeWindowOverwritten,
|
||||
onOverwriteScope: this,
|
||||
onOverwriteParams: [shellwm, actor]
|
||||
});
|
||||
} else {
|
||||
let [success, geom] = actor.meta_window.get_icon_geometry();
|
||||
if (success) {
|
||||
actor.set_position(geom.x, geom.y);
|
||||
actor.set_scale(geom.width / actor.width,
|
||||
geom.height / actor.height);
|
||||
} else {
|
||||
let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()];
|
||||
actor.set_position(monitor.x, monitor.y);
|
||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
||||
actor.x += monitor.width;
|
||||
actor.set_scale(0, 0);
|
||||
}
|
||||
|
||||
let rect = actor.meta_window.get_frame_rect();
|
||||
let [xDest, yDest] = [rect.x, rect.y];
|
||||
|
||||
actor.show();
|
||||
Tweener.addTween(actor,
|
||||
{ scale_x: 1.0,
|
||||
scale_y: 1.0,
|
||||
x: xDest,
|
||||
y: yDest,
|
||||
time: MINIMIZE_WINDOW_ANIMATION_TIME,
|
||||
transition: 'easeInExpo',
|
||||
onComplete: this._unminimizeWindowDone,
|
||||
onCompleteScope: this,
|
||||
onCompleteParams: [shellwm, actor],
|
||||
onOverwrite: this._unminimizeWindowOverwritten,
|
||||
onOverwriteScope: this,
|
||||
onOverwriteParams: [shellwm, actor]
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_maximizeWindowDone : function(shellwm, actor) {
|
||||
_unminimizeWindowDone : function(shellwm, actor) {
|
||||
if (this._removeEffect(this._unminimizing, actor)) {
|
||||
Tweener.removeTweens(actor);
|
||||
actor.set_scale(1.0, 1.0);
|
||||
actor.set_opacity(255);
|
||||
actor.set_pivot_point(0, 0);
|
||||
|
||||
shellwm.completed_unminimize(actor);
|
||||
}
|
||||
},
|
||||
|
||||
_maximizeWindowOverwrite : function(shellwm, actor) {
|
||||
_unminimizeWindowOverwritten : function(shellwm, actor) {
|
||||
if (this._removeEffect(this._unminimizing, actor)) {
|
||||
shellwm.completed_unminimize(actor);
|
||||
}
|
||||
},
|
||||
|
||||
_unmaximizeWindow : function(shellwm, actor, targetX, targetY, targetWidth, targetHeight) {
|
||||
shellwm.completed_unmaximize(actor);
|
||||
},
|
||||
|
||||
_unmaximizeWindowDone : function(shellwm, actor) {
|
||||
_sizeChangeWindow : function(shellwm, actor, whichChange, oldFrameRect, oldBufferRect) {
|
||||
shellwm.completed_size_change(actor);
|
||||
},
|
||||
|
||||
_hasAttachedDialogs: function(window, ignoreWindow) {
|
||||
@ -1074,10 +1298,8 @@ const WindowManager = new Lang.Class({
|
||||
return;
|
||||
}
|
||||
|
||||
if (actor.meta_window.is_attached_dialog()) {
|
||||
/* Scale the window from the center of the parent */
|
||||
if (actor.meta_window.is_attached_dialog())
|
||||
this._checkDimming(actor.get_meta_window().get_transient_for());
|
||||
}
|
||||
|
||||
switch (actor._windowType) {
|
||||
case Meta.WindowType.NORMAL:
|
||||
@ -1232,18 +1454,36 @@ const WindowManager = new Lang.Class({
|
||||
},
|
||||
|
||||
_filterKeybinding: function(shellwm, binding) {
|
||||
if (Main.keybindingMode == Shell.KeyBindingMode.NONE)
|
||||
if (Main.actionMode == Shell.ActionMode.NONE)
|
||||
return true;
|
||||
|
||||
// There's little sense in implementing a keybinding in mutter and
|
||||
// not having it work in NORMAL mode; handle this case generically
|
||||
// so we don't have to explicitly allow all builtin keybindings in
|
||||
// NORMAL mode.
|
||||
if (Main.keybindingMode == Shell.KeyBindingMode.NORMAL &&
|
||||
if (Main.actionMode == Shell.ActionMode.NORMAL &&
|
||||
binding.is_builtin())
|
||||
return false;
|
||||
|
||||
return !(this._allowedKeybindings[binding.get_name()] & Main.keybindingMode);
|
||||
return !(this._allowedKeybindings[binding.get_name()] & Main.actionMode);
|
||||
},
|
||||
|
||||
_syncStacking: function() {
|
||||
if (this._switchData == null)
|
||||
return;
|
||||
|
||||
// Update stacking of windows in inGroup (aka the workspace we are
|
||||
// switching to). Windows in outGroup are about to be hidden anyway,
|
||||
// so we just ignore them here.
|
||||
let windows = global.get_window_actors();
|
||||
let sibling = null;
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
if (windows[i].get_parent() != this._switchData.inGroup)
|
||||
continue;
|
||||
|
||||
this._switchData.inGroup.set_child_above_sibling(windows[i], sibling);
|
||||
sibling = windows[i];
|
||||
}
|
||||
},
|
||||
|
||||
_switchWorkspace : function(shellwm, from, to, direction) {
|
||||
@ -1413,6 +1653,10 @@ const WindowManager = new Lang.Class({
|
||||
Main.panel.toggleAppMenu();
|
||||
},
|
||||
|
||||
_toggleCalendar: function(display, screen, window, event, binding) {
|
||||
Main.panel.toggleCalendar();
|
||||
},
|
||||
|
||||
_toggleTweens: function() {
|
||||
this._tweensPaused = !this._tweensPaused;
|
||||
const OrigTweener = imports.tweener.tweener;
|
||||
@ -1433,10 +1677,27 @@ const WindowManager = new Lang.Class({
|
||||
let newWs;
|
||||
let direction;
|
||||
|
||||
if (action == 'move') {
|
||||
// "Moving" a window to another workspace doesn't make sense when
|
||||
// it cannot be unstuck, and is potentially confusing if a new
|
||||
// workspaces is added at the start/end
|
||||
if (window.is_always_on_all_workspaces() ||
|
||||
(Meta.prefs_get_workspaces_only_on_primary() &&
|
||||
window.get_monitor() != Main.layoutManager.primaryIndex))
|
||||
return;
|
||||
}
|
||||
|
||||
if (target == 'last') {
|
||||
direction = Meta.MotionDirection.DOWN;
|
||||
newWs = screen.get_workspace_by_index(screen.n_workspaces - 1);
|
||||
} else if (isNaN(target)) {
|
||||
// Prepend a new workspace dynamically
|
||||
if (screen.get_active_workspace_index() == 0 &&
|
||||
action == 'move' && target == 'up' && this._isWorkspacePrepended == false) {
|
||||
this.insertWorkspace(0);
|
||||
this._isWorkspacePrepended = true;
|
||||
}
|
||||
|
||||
direction = Meta.MotionDirection[target.toUpperCase()];
|
||||
newWs = screen.get_active_workspace().get_neighbor(direction);
|
||||
} else if (target > 0) {
|
||||
@ -1460,9 +1721,12 @@ const WindowManager = new Lang.Class({
|
||||
|
||||
if (!Main.overview.visible) {
|
||||
if (this._workspaceSwitcherPopup == null) {
|
||||
this._workspaceTracker.blockUpdates();
|
||||
this._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
|
||||
this._workspaceSwitcherPopup.connect('destroy', Lang.bind(this, function() {
|
||||
this._workspaceTracker.unblockUpdates();
|
||||
this._workspaceSwitcherPopup = null;
|
||||
this._isWorkspacePrepended = false;
|
||||
}));
|
||||
}
|
||||
this._workspaceSwitcherPopup.display(direction, newWs.index());
|
||||
@ -1501,4 +1765,18 @@ const WindowManager = new Lang.Class({
|
||||
let dialog = new DisplayChangeDialog(this._shellwm);
|
||||
dialog.open();
|
||||
},
|
||||
|
||||
_showResizePopup: function(display, show, rect, displayW, displayH) {
|
||||
if (show) {
|
||||
if (!this._resizePopup)
|
||||
this._resizePopup = new ResizePopup();
|
||||
|
||||
this._resizePopup.set(rect, displayW, displayH);
|
||||
} else {
|
||||
if (this._resizePopup) {
|
||||
this._resizePopup.destroy();
|
||||
this._resizePopup = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
@ -74,7 +74,7 @@ const WindowMenu = new Lang.Class({
|
||||
window.make_above();
|
||||
}));
|
||||
if (window.is_above())
|
||||
item.setOrnament(PopupMenu.Ornament.DOT);
|
||||
item.setOrnament(PopupMenu.Ornament.CHECK);
|
||||
if (window.get_maximized() == Meta.MaximizeFlags.BOTH ||
|
||||
type == Meta.WindowType.DOCK ||
|
||||
type == Meta.WindowType.DESKTOP ||
|
||||
@ -93,7 +93,7 @@ const WindowMenu = new Lang.Class({
|
||||
window.stick();
|
||||
}));
|
||||
if (isSticky)
|
||||
item.setOrnament(PopupMenu.Ornament.DOT);
|
||||
item.setOrnament(PopupMenu.Ornament.CHECK);
|
||||
if (window.is_always_on_all_workspaces())
|
||||
item.setSensitive(false);
|
||||
|
||||
@ -101,13 +101,22 @@ const WindowMenu = new Lang.Class({
|
||||
|
||||
if (!isSticky) {
|
||||
let workspace = window.get_workspace();
|
||||
let idx = workspace.index();
|
||||
if (idx > 0) {
|
||||
if (workspace != workspace.get_neighbor(Meta.MotionDirection.LEFT)) {
|
||||
this.addAction(_("Move to Workspace Left"), Lang.bind(this, function(event) {
|
||||
window.change_workspace(workspace.get_neighbor(Meta.MotionDirection.LEFT));
|
||||
}));
|
||||
}
|
||||
if (workspace != workspace.get_neighbor(Meta.MotionDirection.RIGHT)) {
|
||||
this.addAction(_("Move to Workspace Right"), Lang.bind(this, function(event) {
|
||||
window.change_workspace(workspace.get_neighbor(Meta.MotionDirection.RIGHT));
|
||||
}));
|
||||
}
|
||||
if (workspace != workspace.get_neighbor(Meta.MotionDirection.UP)) {
|
||||
this.addAction(_("Move to Workspace Up"), Lang.bind(this, function(event) {
|
||||
window.change_workspace(workspace.get_neighbor(Meta.MotionDirection.UP));
|
||||
}));
|
||||
}
|
||||
if (idx < nWorkspaces) {
|
||||
if (workspace != workspace.get_neighbor(Meta.MotionDirection.DOWN)) {
|
||||
this.addAction(_("Move to Workspace Down"), Lang.bind(this, function(event) {
|
||||
window.change_workspace(workspace.get_neighbor(Meta.MotionDirection.DOWN));
|
||||
}));
|
||||
@ -115,6 +124,39 @@ const WindowMenu = new Lang.Class({
|
||||
}
|
||||
}
|
||||
|
||||
let screen = global.screen;
|
||||
let nMonitors = screen.get_n_monitors();
|
||||
if (nMonitors > 1) {
|
||||
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
|
||||
let monitorIndex = window.get_monitor();
|
||||
|
||||
let upMonitorIndex = screen.get_monitor_neighbor_index(monitorIndex, Meta.ScreenDirection.UP);
|
||||
if (upMonitorIndex != -1) {
|
||||
this.addAction(_("Move to Monitor Up"), Lang.bind(this, function(event) {
|
||||
window.move_to_monitor(upMonitorIndex);
|
||||
}));
|
||||
}
|
||||
let downMonitorIndex = screen.get_monitor_neighbor_index(monitorIndex, Meta.ScreenDirection.DOWN);
|
||||
if (downMonitorIndex != -1) {
|
||||
this.addAction(_("Move to Monitor Down"), Lang.bind(this, function(event) {
|
||||
window.move_to_monitor(downMonitorIndex);
|
||||
}));
|
||||
}
|
||||
let leftMonitorIndex = screen.get_monitor_neighbor_index(monitorIndex, Meta.ScreenDirection.LEFT);
|
||||
if (leftMonitorIndex != -1) {
|
||||
this.addAction(_("Move to Monitor Left"), Lang.bind(this, function(event) {
|
||||
window.move_to_monitor(leftMonitorIndex);
|
||||
}));
|
||||
}
|
||||
let rightMonitorIndex = screen.get_monitor_neighbor_index(monitorIndex, Meta.ScreenDirection.RIGHT);
|
||||
if (rightMonitorIndex != -1) {
|
||||
this.addAction(_("Move to Monitor Right"), Lang.bind(this, function(event) {
|
||||
window.move_to_monitor(rightMonitorIndex);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
|
||||
item = this.addAction(_("Close"), Lang.bind(this, function(event) {
|
||||
@ -167,6 +209,10 @@ const WindowMenuManager = new Lang.Class({
|
||||
menu.connect('activate', function() {
|
||||
window.check_alive(global.get_current_time());
|
||||
});
|
||||
let destroyId = window.connect('unmanaged',
|
||||
function() {
|
||||
menu.close();
|
||||
});
|
||||
|
||||
this._sourceActor.set_size(rect.width, rect.height);
|
||||
this._sourceActor.set_position(rect.x, rect.y);
|
||||
@ -180,6 +226,7 @@ const WindowMenuManager = new Lang.Class({
|
||||
|
||||
this._sourceActor.hide();
|
||||
menu.destroy();
|
||||
window.disconnect(destroyId);
|
||||
}));
|
||||
}
|
||||
});
|
||||
|