Compare commits
499 Commits
2.91.91
...
goa-client
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a69e45b5eb | ||
|
|
a355398b0f | ||
|
|
4bfc3bafcb | ||
|
|
898b2b903d | ||
|
|
7921954a31 | ||
|
|
0e42de9149 | ||
|
|
8e4a5f1ac5 | ||
|
|
61577e176e | ||
|
|
4b008b1ada | ||
|
|
bee37b5bc4 | ||
|
|
b5ab8b6ed5 | ||
|
|
4d6bd91d16 | ||
|
|
5428db5385 | ||
|
|
6e6b1e6052 | ||
|
|
bc2b47974d | ||
|
|
2244b6ff1b | ||
|
|
fb384fc291 | ||
|
|
73cae8ce9a | ||
|
|
dcd07eb23f | ||
|
|
fa24448489 | ||
|
|
c975740f92 | ||
|
|
1e0187fa57 | ||
|
|
cbdf060bca | ||
|
|
19a8dff975 | ||
|
|
72f9f482d6 | ||
|
|
88de26138a | ||
|
|
57bd964cb3 | ||
|
|
74a39ae57c | ||
|
|
5090a4ccce | ||
|
|
ae0652d13f | ||
|
|
101a07a3d7 | ||
|
|
b012e93121 | ||
|
|
c31109800b | ||
|
|
c0dc363a3d | ||
|
|
739bb28220 | ||
|
|
aab2794e05 | ||
|
|
75c8c1bfb6 | ||
|
|
6f8bd96195 | ||
|
|
25f0d098bd | ||
|
|
56d584b7c6 | ||
|
|
20bf53add1 | ||
|
|
0d440bb0a2 | ||
|
|
8ec62ce46b | ||
|
|
79927faaec | ||
|
|
e4c7f1f3c4 | ||
|
|
68710c4647 | ||
|
|
7d7cbde1f3 | ||
|
|
bafd9c777a | ||
|
|
42a5531f15 | ||
|
|
227da25776 | ||
|
|
2028f33e38 | ||
|
|
145bf19636 | ||
|
|
d1675c44e2 | ||
|
|
6934e4db26 | ||
|
|
cae3414854 | ||
|
|
90d061edaf | ||
|
|
2e02918323 | ||
|
|
e77a1fd33b | ||
|
|
dd01c24c34 | ||
|
|
f88fbee80d | ||
|
|
fe08edbe2b | ||
|
|
d2a16bca10 | ||
|
|
a87f51487e | ||
|
|
76fce94b66 | ||
|
|
d104f9210a | ||
|
|
d0780d1622 | ||
|
|
9d5906dae3 | ||
|
|
07a0960265 | ||
|
|
72bee6d7ca | ||
|
|
249f26d23c | ||
|
|
7813c5b93f | ||
|
|
e38d83fd44 | ||
|
|
d97657b151 | ||
|
|
7e857dede3 | ||
|
|
c3218f6b03 | ||
|
|
1060d0db60 | ||
|
|
b8925a091c | ||
|
|
79cca07a41 | ||
|
|
c1d189c9ad | ||
|
|
b1a973ee5a | ||
|
|
93ef560779 | ||
|
|
c28d35ad86 | ||
|
|
9c654a6ab5 | ||
|
|
64a54e379c | ||
|
|
8f4ec8583b | ||
|
|
f4852d7264 | ||
|
|
092e1a691d | ||
|
|
16ac42421d | ||
|
|
1d2eadb9c0 | ||
|
|
35c85d9fac | ||
|
|
f0622c1896 | ||
|
|
6d11247417 | ||
|
|
59c3e3a179 | ||
|
|
42e26a8682 | ||
|
|
db6caac9cc | ||
|
|
ba4a57ba0b | ||
|
|
018e3bc35f | ||
|
|
a56bc9d933 | ||
|
|
5b93525ce8 | ||
|
|
6abb86dff6 | ||
|
|
6a27d5ed80 | ||
|
|
8232684672 | ||
|
|
2d855ce5cf | ||
|
|
b2b685e46d | ||
|
|
ef552846d1 | ||
|
|
c7dfd0894e | ||
|
|
5b1a76aeff | ||
|
|
529b6ca935 | ||
|
|
625a4c0766 | ||
|
|
3c3ea2f575 | ||
|
|
57a332bb08 | ||
|
|
73ac98b193 | ||
|
|
59e3cbb36b | ||
|
|
fb019a7cbf | ||
|
|
09607f6aa7 | ||
|
|
1c4a33eb78 | ||
|
|
b7513097ea | ||
|
|
a35677a9bf | ||
|
|
89de3a81c6 | ||
|
|
b9828bf5de | ||
|
|
d6c3868a7c | ||
|
|
a73f02ac23 | ||
|
|
7e9594456b | ||
|
|
d25418ba04 | ||
|
|
a7df1a3d77 | ||
|
|
50951d15ea | ||
|
|
30076884ae | ||
|
|
1eff22a90b | ||
|
|
41bdbc203d | ||
|
|
7932585656 | ||
|
|
68bf4e7b70 | ||
|
|
92f09a60f6 | ||
|
|
d19f2bb6d2 | ||
|
|
b06dce5bf8 | ||
|
|
82e2ab89c5 | ||
|
|
db198b183c | ||
|
|
90bab650e2 | ||
|
|
fa1cc556f9 | ||
|
|
69b23b0e48 | ||
|
|
af69945e5b | ||
|
|
f36f7644c8 | ||
|
|
20f1457d15 | ||
|
|
38bcd52065 | ||
|
|
38219fec99 | ||
|
|
6c3300bc2f | ||
|
|
d1a110d4ca | ||
|
|
5b61485143 | ||
|
|
6b95a357eb | ||
|
|
60bdc726ce | ||
|
|
429f809b71 | ||
|
|
9396d736f2 | ||
|
|
cc9b812466 | ||
|
|
5b0f2dc0cf | ||
|
|
7ffea1606d | ||
|
|
342bc1e72d | ||
|
|
0127eb5892 | ||
|
|
39023269d6 | ||
|
|
35e3cd97fe | ||
|
|
a63a171ec3 | ||
|
|
7f1763f32f | ||
|
|
2d6326815c | ||
|
|
ee4c8cca8c | ||
|
|
2104e0f411 | ||
|
|
84e69f57ea | ||
|
|
aba43125f3 | ||
|
|
de5fc58fcb | ||
|
|
4831dde3fb | ||
|
|
b5cbfc5e7a | ||
|
|
1124d164ec | ||
|
|
9d9391bd95 | ||
|
|
0121d74b92 | ||
|
|
f81af32963 | ||
|
|
8f5198821e | ||
|
|
96c2b5ef32 | ||
|
|
c5eb324cf0 | ||
|
|
f117d9bfd3 | ||
|
|
b470736246 | ||
|
|
b2a2a00cd8 | ||
|
|
659130856c | ||
|
|
9a21008177 | ||
|
|
8f58bc5b19 | ||
|
|
3a0220a875 | ||
|
|
9f438d0ec6 | ||
|
|
22c22e0d7a | ||
|
|
bc48bd5f4a | ||
|
|
905c4bb4a5 | ||
|
|
94bfaf6896 | ||
|
|
25b743b03c | ||
|
|
8da4e6ce5e | ||
|
|
cedd297ba6 | ||
|
|
b6e0c5e0ea | ||
|
|
bf3f7d0dc4 | ||
|
|
7b42a84422 | ||
|
|
8b7c065706 | ||
|
|
c6a4b3d9b0 | ||
|
|
0ef32f2b8d | ||
|
|
f7fdcb7bf1 | ||
|
|
848d36ff39 | ||
|
|
07ce3e7cdf | ||
|
|
cfec145ae2 | ||
|
|
641d7a4ea4 | ||
|
|
da0650fda6 | ||
|
|
6724133927 | ||
|
|
c0ded8ef5f | ||
|
|
7382de51dc | ||
|
|
96a1121e6b | ||
|
|
323bbb0692 | ||
|
|
59e235623a | ||
|
|
40dc85d975 | ||
|
|
6006a42cbb | ||
|
|
c2e0278bd9 | ||
|
|
c1ba920c86 | ||
|
|
7b997e9374 | ||
|
|
dfb97c1ed7 | ||
|
|
fc49fb2f4f | ||
|
|
63078fba5b | ||
|
|
b0176546c2 | ||
|
|
a234ba91a4 | ||
|
|
526d11809f | ||
|
|
3bbdecc6b3 | ||
|
|
00fc4a2eb7 | ||
|
|
924b31233b | ||
|
|
475161f716 | ||
|
|
31b12635d1 | ||
|
|
d2de0865bf | ||
|
|
9b4dbd0e83 | ||
|
|
4577cd7497 | ||
|
|
4ebf07c725 | ||
|
|
da852a94bd | ||
|
|
9b51ff7241 | ||
|
|
aa0137e7ce | ||
|
|
3889ae7627 | ||
|
|
c97a8602a1 | ||
|
|
affc9f9058 | ||
|
|
1582819259 | ||
|
|
05e8ae33dc | ||
|
|
219d5fb66b | ||
|
|
92ff57c0ea | ||
|
|
5233429b6f | ||
|
|
475cf7179e | ||
|
|
f608c65962 | ||
|
|
6cf0a35b4c | ||
|
|
bac006ebc1 | ||
|
|
be5f74e37f | ||
|
|
5c29bff23d | ||
|
|
68968d2b40 | ||
|
|
038f4e8bde | ||
|
|
f8874fec0f | ||
|
|
ee6693e6e3 | ||
|
|
bfba97647e | ||
|
|
82d5194afe | ||
|
|
bf449b9f61 | ||
|
|
9530048867 | ||
|
|
090d54516e | ||
|
|
c91b716a63 | ||
|
|
80cdb0dc4e | ||
|
|
aaa6b54673 | ||
|
|
a3b61ec8c8 | ||
|
|
6c41d6b66a | ||
|
|
1838ab1412 | ||
|
|
72e8d38586 | ||
|
|
9259e2221d | ||
|
|
42ea979b06 | ||
|
|
46824adb97 | ||
|
|
3758f4952e | ||
|
|
8fdbbe78f4 | ||
|
|
5a86b0f9e3 | ||
|
|
604722b775 | ||
|
|
812812d817 | ||
|
|
f07fe0a8e7 | ||
|
|
1d7cef5bfe | ||
|
|
34b12e6a6a | ||
|
|
eb6ba563bd | ||
|
|
281b2e9b0e | ||
|
|
5437629e89 | ||
|
|
e1df2f8ff5 | ||
|
|
12fad6f05f | ||
|
|
4208078750 | ||
|
|
dba02f8f08 | ||
|
|
35e410fe96 | ||
|
|
7dcd2313d8 | ||
|
|
40750f2dc6 | ||
|
|
85c007431b | ||
|
|
cbd187369e | ||
|
|
d20d89a0b9 | ||
|
|
80eb37ef60 | ||
|
|
d19cdc206b | ||
|
|
02078255ea | ||
|
|
bea2d40f79 | ||
|
|
a5d3259cfe | ||
|
|
4a93ce703e | ||
|
|
661ea906d9 | ||
|
|
b382b4cb94 | ||
|
|
087e86fb32 | ||
|
|
afffa76c17 | ||
|
|
69ca18f36b | ||
|
|
f84c62f0be | ||
|
|
90c554ad42 | ||
|
|
e2cb6cc4da | ||
|
|
02da366cc2 | ||
|
|
54e3a54489 | ||
|
|
8798ec653d | ||
|
|
d1ffd3cf35 | ||
|
|
133b854f1b | ||
|
|
33125e78c8 | ||
|
|
4118bf1a5e | ||
|
|
8282db456b | ||
|
|
7b5eacf671 | ||
|
|
12bd374477 | ||
|
|
9ef4cc0ab9 | ||
|
|
528fc9bc47 | ||
|
|
c58b8498b3 | ||
|
|
c81c564941 | ||
|
|
b16de0e374 | ||
|
|
d38f41a459 | ||
|
|
30346884fe | ||
|
|
1518dc9b60 | ||
|
|
fd3f2289c3 | ||
|
|
22bfd4f7c3 | ||
|
|
2782011ce8 | ||
|
|
7f17fcfafc | ||
|
|
a40daa3c22 | ||
|
|
1e366aa56e | ||
|
|
bad8dbc2d2 | ||
|
|
d0dd37fe94 | ||
|
|
b2df3fcd1d | ||
|
|
96f89ce4ae | ||
|
|
e886a3d891 | ||
|
|
0eaf141ae4 | ||
|
|
291ef07cf3 | ||
|
|
b9066ac997 | ||
|
|
206f4604a4 | ||
|
|
adbc1d97a0 | ||
|
|
70ae700461 | ||
|
|
b81ad3ed39 | ||
|
|
77cdb17cee | ||
|
|
d4e329b76d | ||
|
|
fb24585dd8 | ||
|
|
bd5efd5968 | ||
|
|
650f35c1f3 | ||
|
|
14e65168c9 | ||
|
|
f00c47c21a | ||
|
|
547d105b2e | ||
|
|
de671103ca | ||
|
|
2c48efa3fd | ||
|
|
7f35b2dc43 | ||
|
|
6ae914da2f | ||
|
|
06ea78af1b | ||
|
|
2ea12a7699 | ||
|
|
8ab25de6c6 | ||
|
|
e0424a7017 | ||
|
|
f259162d64 | ||
|
|
6bb5cdeb2f | ||
|
|
384c30b6fd | ||
|
|
67a75d4439 | ||
|
|
0d963df7b3 | ||
|
|
99efde5673 | ||
|
|
c8ff699c4b | ||
|
|
0718a888d0 | ||
|
|
b7be4df603 | ||
|
|
8bece0b49e | ||
|
|
47d6edc3c8 | ||
|
|
26bb56396d | ||
|
|
dd99ed73a9 | ||
|
|
36ce460a39 | ||
|
|
e92c845dfd | ||
|
|
492263c2e9 | ||
|
|
0c99f66547 | ||
|
|
df440496ee | ||
|
|
09f2028d6a | ||
|
|
05736ba0a1 | ||
|
|
e5f05bc9d8 | ||
|
|
cdd1209b55 | ||
|
|
0e6458a630 | ||
|
|
a1a068a377 | ||
|
|
2c5657e8a9 | ||
|
|
87fbd715a3 | ||
|
|
fc8cba9598 | ||
|
|
147725bf7a | ||
|
|
06d2c0af35 | ||
|
|
708f1a97dd | ||
|
|
d8bd9f5a66 | ||
|
|
079953c3ee | ||
|
|
fea8b6da2f | ||
|
|
4bf1df0894 | ||
|
|
b4f16c4df8 | ||
|
|
61282737c5 | ||
|
|
d8c2290099 | ||
|
|
830ab599df | ||
|
|
0de5c5e8a3 | ||
|
|
c6170ed751 | ||
|
|
2ea762cfc9 | ||
|
|
2646741297 | ||
|
|
f5df5faf71 | ||
|
|
cab9a580e8 | ||
|
|
c8ac3fd4f5 | ||
|
|
7f67c34b39 | ||
|
|
e27293edbc | ||
|
|
8d57c5052c | ||
|
|
1314559833 | ||
|
|
735397aa89 | ||
|
|
c0d0c792e1 | ||
|
|
43020b20b7 | ||
|
|
0a3d80b86e | ||
|
|
a9505d0426 | ||
|
|
4d804c2a29 | ||
|
|
e8eec2d357 | ||
|
|
971e3f679f | ||
|
|
7c90f078e7 | ||
|
|
5957bd1abb | ||
|
|
b16380e7e5 | ||
|
|
b72a32c70d | ||
|
|
90f15b3c5a | ||
|
|
44bbf26cb2 | ||
|
|
fcfd17e973 | ||
|
|
73853cf147 | ||
|
|
ddbc263da2 | ||
|
|
982d8a0dc0 | ||
|
|
5a269db9d5 | ||
|
|
525da01a62 | ||
|
|
12df10b2d0 | ||
|
|
e6aee5d7ea | ||
|
|
6ff69da0de | ||
|
|
ebcb87c163 | ||
|
|
79d9df9bb1 | ||
|
|
8c40c2086a | ||
|
|
f4a000cb59 | ||
|
|
4029202635 | ||
|
|
29d473f2fa | ||
|
|
7ad89dc46b | ||
|
|
4b2d6f8a99 | ||
|
|
9b55de1c6b | ||
|
|
8b45211a8f | ||
|
|
f079501cff | ||
|
|
e375e1789b | ||
|
|
30d2cfdf56 | ||
|
|
44d61e6857 | ||
|
|
3466829766 | ||
|
|
d3703516d9 | ||
|
|
bdebaa986b | ||
|
|
c2d400846b | ||
|
|
034e147910 | ||
|
|
25015c9c3a | ||
|
|
43cf60f563 | ||
|
|
057348763b | ||
|
|
7230452e23 | ||
|
|
438317c1e9 | ||
|
|
cfe719c962 | ||
|
|
44e2d88628 | ||
|
|
6e50e77709 | ||
|
|
02ed28d68d | ||
|
|
73274e201b | ||
|
|
f6fc88cc2d | ||
|
|
d16acc43d9 | ||
|
|
239aa7b8d5 | ||
|
|
44a1bc5396 | ||
|
|
821583acae | ||
|
|
c6a2814881 | ||
|
|
1954a02352 | ||
|
|
8a28022a6b | ||
|
|
43a243b24a | ||
|
|
7c937c8704 | ||
|
|
bdd1f82777 | ||
|
|
cbb8876815 | ||
|
|
f8cdaaae30 | ||
|
|
74314bacd7 | ||
|
|
04473f607b | ||
|
|
88958270cb | ||
|
|
856f7ecee9 | ||
|
|
9f5584a157 | ||
|
|
eda8a94d5b | ||
|
|
5956b13588 | ||
|
|
162d029c81 | ||
|
|
7f3920dbb7 | ||
|
|
6d07c3a1df | ||
|
|
a0a83428cf | ||
|
|
dc2cae07b2 | ||
|
|
f8b44cd30e | ||
|
|
c3eca3d754 | ||
|
|
1ea005f6a6 | ||
|
|
16a675b7ce | ||
|
|
df2f939f3a | ||
|
|
5743224817 | ||
|
|
a80e88e33e | ||
|
|
0207f1f29b | ||
|
|
72120bb87f | ||
|
|
7eaca86bf1 | ||
|
|
db5f72c868 | ||
|
|
69d6ae4141 | ||
|
|
edabafc0fc | ||
|
|
e9f2aa6010 | ||
|
|
e054dd7813 | ||
|
|
76d788a186 | ||
|
|
3944df1bd2 | ||
|
|
49f6280645 | ||
|
|
84eb66d5aa | ||
|
|
026fc531ba | ||
|
|
8d14df0ced | ||
|
|
f27547dcff |
4
.gitignore
vendored
@@ -7,7 +7,6 @@ ChangeLog
|
||||
INSTALL
|
||||
Makefile
|
||||
Makefile.in
|
||||
NEWS
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
config.h
|
||||
@@ -44,8 +43,9 @@ src/calendar-server/org.gnome.Shell.CalendarServer.service
|
||||
src/gnome-shell
|
||||
src/gnome-shell-calendar-server
|
||||
src/gnome-shell-extension-tool
|
||||
src/gnome-shell-real
|
||||
src/gnome-shell-jhbuild
|
||||
src/gnome-shell-perf-helper
|
||||
src/gnome-shell-real
|
||||
src/run-js-test
|
||||
src/test-recorder
|
||||
src/test-recorder.ogg
|
||||
|
||||
146
NEWS
Normal file
@@ -0,0 +1,146 @@
|
||||
3.0.1
|
||||
=====
|
||||
|
||||
* Network menu
|
||||
- Fix problems updating the menu for mobile broadband devices [Giovanni]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=646395
|
||||
- Fix missing device descriptions with multiple devices of the
|
||||
same type [Giovanni]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=646074
|
||||
- Label ad-hoc neworks with an appropriate icon [Dan]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=646141
|
||||
- Fix displaying some devices states as "invalid" [Dan]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=646946
|
||||
- Fix problems with access points that don't report a SSID [Giovanni]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=647040
|
||||
- Miscellaneous minor bug fixes [Dan, Giovanni, Owen]
|
||||
645981, 646558, 646443, 646708, 646968
|
||||
* Application menu and icon
|
||||
- Fix bug where application menu icon was missing at GNOME Shell
|
||||
startup. [Florian]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=644122
|
||||
- Fix missing application menu for dialog windows [Colin]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=647082
|
||||
- When launching an application through an alternate launcher
|
||||
(like for a System Settings pane), association the windows with
|
||||
the application, not the launcher. [Colin]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=646689
|
||||
* Activities overview
|
||||
- Load the applications view incrementally to avoid potentially freezing
|
||||
for multiple seconds [Colin]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=647778
|
||||
- Fix bug where package installation while the overview
|
||||
was up could result in a corrupted application display. [Giovanni]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=645801
|
||||
- Fix dragging from the search results to launch apps and docs [Florian]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=645990
|
||||
- Fix flickering of selection when searching in the overview [Florian]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=646019
|
||||
- Fix bug when typing into the search box when text was already
|
||||
selected [Nohemi]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=636341
|
||||
* Fix layout of notifications for right-to-left languages [Florian]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=646921
|
||||
* Remove a confusing special case where Alt-Tab sometimes switched
|
||||
to a different window of the same application rather than to
|
||||
a different application. [Rui]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=648132
|
||||
* Fix a crash that could happen when a window was opened on a
|
||||
workspace that was immediately removed [Dan]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=648132
|
||||
* Fix keyboard navigation in logout/reboot dialogs [Dan]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=646740
|
||||
* Fix missing inspector icon in Looking Glass console [Dan]
|
||||
* Miscellaneous minor bug fixes [Adel, Colin, Dan, Florian, Nohemi]
|
||||
645648, 646205, 646257, 646855, 647098, 646730
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Nohemi Fernandez, Adel Gadllah, Rui Matos, Florian Müllner,
|
||||
Owen Taylor, Colin Walters, Dan Winship
|
||||
|
||||
Translations:
|
||||
Hendrik Richter [de], Jorge González [es], Arash Mousavi [fa],
|
||||
Fran Diéguez [gl], Jiro Matsuzawa [ja], Piotr Drąg [pl], Daniel Nylander [sv],
|
||||
Sira Nokyoongtong [th], Muhammet Kara [tr], Nguyễn Thái Ngọc Duy [vi],
|
||||
Aron Xu [zh_CN], Chao-Hsiung Liao [zh_HK, zh_TW]
|
||||
|
||||
3.0.0.2
|
||||
=======
|
||||
|
||||
* Fix missing import that was preventing extensions from loading.
|
||||
[Maxim Ermilov]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=646333
|
||||
|
||||
Translations:
|
||||
Timo Jyrinki [fi]
|
||||
|
||||
3.0.0.1
|
||||
=======
|
||||
|
||||
* Fix problem with stuck event handling if network menu pops down while
|
||||
user is using the scrollbar. [Owen Taylor]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=646825
|
||||
|
||||
Contributors to GNOME Shell 3.0
|
||||
===============================
|
||||
|
||||
Code:
|
||||
|
||||
Josh Adams, Kiyoshi Aman, Nuno Araujo, Emmanuele Bassi, Dirk-Jan C. Binnema,
|
||||
Wouter Bolsterlee, Raphael Bosshard, Milan Bouchet-Valat, Christina Boumpouka,
|
||||
Mathieu Bridon, Alban Browaeys, Phil Bull, Micro Cai, Giovanni Campagna,
|
||||
Cosimo Cecchi, Tor-björn Claesson, Matthias Clasen, Jason D. Clinton,
|
||||
Frederic Crozat, Guillaume Desmottes, Sander Dijkhuis, Neha Doijode,
|
||||
Maxim Ermilov, Diego Escalante Urrelo, Luca Ferretti, Steve Frécinaux,
|
||||
Takao Fujiwara, Adel Gadllah, Vadim Girlin, Nick Glynn, Guido Günther,
|
||||
Leon Handreke, Lex Hider, Richard Hughes, Javier Jardón, Abderrahim Kitouni,
|
||||
Andre Klapper, Alexander Larsson, Nickolas Lloyd, Ryan Lortie, Kjartan Maraas,
|
||||
Koop Mast, Rui Matos, Jonathan Matthew, William Jon McCann, Morten Mjelva,
|
||||
Federico Mena Quintero, Florian Müllner, Jon Nettleton, Hellyna Ng,
|
||||
Discardi Nicola, Carlos Martín Nieto, Bastien Nocera, Bill Nottingham,
|
||||
Matt Novenstern, Marc-Antoine Perennou, Neil Perry, Frédéric Péters,
|
||||
Alejandro Piñeiro, Siegfried-Angel Gevatter Pujals, "res", Neil Roberts,
|
||||
"Sardem FF7", Florian Scandella, Joseph Scheuhammer, Christian Schramm,
|
||||
Gustavo Noronha Silva, Jasper St. Pierre, Eric Springer, Jakub Steiner,
|
||||
Jonathan Strander, Ray Strode, Owen Taylor, Rico Tzschichholz,
|
||||
Sergey V. Udaltsov, Daiki Ueno, Vincent Untz, Marcelo Jorge Vieira,
|
||||
Mads Villadsen, Colin Walters, Dan Winship, William Wolf, Thomas Wood,
|
||||
Pierre Yager, David Zeuthen, Marina Zhurakhinskaya
|
||||
|
||||
Design:
|
||||
|
||||
Allan Day, William Jon McCann, Jeremy Perry, Jakub Steiner
|
||||
2008 Boston GNOME design hackfest participants (especially Neil J. Patel
|
||||
for turning the resulting sketches into our first mockups.)
|
||||
Everybody on irc.gnome.org:#gnome-design
|
||||
|
||||
Translations:
|
||||
|
||||
Friedel Wolff (af), Khaled Hosny (ar), Ivaylo Valkov (bg), Jamil Ahmed (bn)
|
||||
Runa Bhattacharjee (bn_IN), Gil Forcada, Siegfried-Angel Gevatter Pujals,
|
||||
Jordi Serratosa (ca), Andre Klapper, Petr Kovar (cs), Kenneth Nielsen,
|
||||
Kris Thomsen (da), Mario Blättermann, Hendrik Brandt, Christian Kirbach,
|
||||
Hendrik Richter, Wolfgang Stöggl (de), Michael Kotsarinis, Kostas Papadimas,
|
||||
Jennie Petoumenou, Sterios Prosiniklis, Fotis Tsamis, Simos Xenitellis (el),
|
||||
Bruce Cowan, Philip Withnall (en_GB), Jorge Gonzalez, Daniel Mustieles (es),
|
||||
Mattias Põldaru, Ivar Smolin (et), Inaki Larranaga Murgoitio (eu),
|
||||
Mahyar Moghimi (fa), Timo Jyrinki (fi), Cyril Arnaud, Bruno Brouard,
|
||||
Pablo Martin-Gomez, Claude Paroz, Frédéric Peters (fr), Seán de Búrca (ga)
|
||||
Francisco Diéguez, Antón Méixome (gl), Sweta Kothari (gu), Liel Fridman,
|
||||
Yaron Shahrabani (he), Rajesh Ranjan (hi), Gabor Kelemen (hu), Milo Casagrande,
|
||||
Luca Ferretti (it), Dirgita, Andika Triwidada (id), Takayuki KUSANO,
|
||||
Takayoshi OKANO, Kiyotaka NISHIBORI, Futoshi NISHIO (ja), Shankar Prasad (kn),
|
||||
Young-Ho Cha, Changwoo Ryu (ko), Žygimantas Beručka, Gintautas Miliauskas (lt),
|
||||
Rudolfs Mazurs (lv), Sandeep Shedmake (mr), Kjartan Maraas (nb),
|
||||
Wouter Bolsterlee, Sander Dijkhuis, Reinout van Schouwen (nl),
|
||||
Torstein Winterseth (nn), A S Alam (pa), Tomasz Dominikowski, Piotr Drąg (pl),
|
||||
Duarte Loreto (pt), Felipe Borges, Rodrigo Padula de Oliveira,
|
||||
Rodrigo L. M. Flores, Amanda Magalhães, Og B. Maciel, Gabriel F. Vilar,
|
||||
Jonh Wendell (pt_BR), Lucian Adrian Grijincu, Daniel Șerbănescu (ro),
|
||||
Sergey V. Kovylov, Andrey Korzinev, Yuri Myasoedov, Marina Zhurakhinskaya (ru),
|
||||
Daniel Nylander (se), Matej Urbančič, Andrej Žnidaršič (sl),
|
||||
Miloš Popović (sr, sr@latin), Miroslav Nikolić (sr), Tirumurti Vasudevan (ta),
|
||||
Sira Nokyoongtong (th), Baris Cicek (tr), Abduxukur Abdurixit,
|
||||
Gheyret T. Kenji (ug), Maxim V. Dziumanenko, Daniel Korostil (uk),
|
||||
Nguyễn Thái Ngọc Duy (vi), Jessica Ban, 'jiero', Wei Li, YunQiang Su, Ray Wang,
|
||||
Aron Xu (zh_CN), Chao-Hsiung Liao (zh_HK, zh_TW)
|
||||
47
configure.ac
@@ -1,5 +1,5 @@
|
||||
AC_PREREQ(2.63)
|
||||
AC_INIT([gnome-shell],[2.91.91],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||
AC_INIT([gnome-shell],[3.0.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_SRCDIR([src/shell-global.c])
|
||||
@@ -52,8 +52,8 @@ AC_MSG_CHECKING([for GStreamer (needed for recording functionality)])
|
||||
if $PKG_CONFIG --exists gstreamer-0.10 '>=' $GSTREAMER_MIN_VERSION ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
build_recorder=true
|
||||
recorder_modules="gstreamer-0.10 gstreamer-base-0.10 xfixes x11"
|
||||
PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0)
|
||||
recorder_modules="gstreamer-0.10 gstreamer-base-0.10 x11"
|
||||
PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0 xfixes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
@@ -63,7 +63,7 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
|
||||
CLUTTER_MIN_VERSION=1.5.15
|
||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
|
||||
GJS_MIN_VERSION=0.7.11
|
||||
MUTTER_MIN_VERSION=2.91.91
|
||||
MUTTER_MIN_VERSION=3.0.0
|
||||
GTK_MIN_VERSION=3.0.0
|
||||
GIO_MIN_VERSION=2.25.9
|
||||
LIBECAL_MIN_VERSION=2.32.0
|
||||
@@ -71,13 +71,14 @@ LIBEDATASERVER_MIN_VERSION=1.2.0
|
||||
LIBEDATASERVERUI2_MIN_VERSION=1.2.0
|
||||
LIBEDATASERVERUI3_MIN_VERSION=2.91.6
|
||||
TELEPATHY_GLIB_MIN_VERSION=0.13.12
|
||||
TELEPATHY_LOGGER_MIN_VERSION=0.2.4
|
||||
POLKIT_MIN_VERSION=0.100
|
||||
|
||||
# Collect more than 20 libraries for a prize!
|
||||
PKG_CHECK_MODULES(GNOME_SHELL, gio-2.0 >= $GIO_MIN_VERSION
|
||||
gio-unix-2.0 dbus-glib-1 libxml-2.0
|
||||
gtk+-3.0 >= $GTK_MIN_VERSION
|
||||
libmutter-wm >= $MUTTER_MIN_VERSION
|
||||
libmutter >= $MUTTER_MIN_VERSION
|
||||
gjs-internals-1.0 >= $GJS_MIN_VERSION
|
||||
libgnome-menu $recorder_modules gconf-2.0
|
||||
gdk-x11-3.0
|
||||
@@ -87,28 +88,38 @@ PKG_CHECK_MODULES(GNOME_SHELL, gio-2.0 >= $GIO_MIN_VERSION
|
||||
gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION
|
||||
libcanberra
|
||||
telepathy-glib >= $TELEPATHY_GLIB_MIN_VERSION
|
||||
polkit-agent-1 >= $POLKIT_MIN_VERSION)
|
||||
telepathy-logger-0.2 >= $TELEPATHY_LOGGER_MIN_VERSION
|
||||
polkit-agent-1 >= $POLKIT_MIN_VERSION xfixes)
|
||||
|
||||
PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
|
||||
|
||||
GJS_VERSION=`$PKG_CONFIG --modversion gjs-internals-1.0`
|
||||
AC_DEFINE_UNQUOTED([GJS_VERSION], ["$GJS_VERSION"], [The version of GJS we're linking to])
|
||||
AC_SUBST([GJS_VERSION], ["$GJS_VERSION"])
|
||||
|
||||
GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION])
|
||||
JHBUILD_TYPELIBDIR="$INTROSPECTION_TYPELIBDIR"
|
||||
# NM is the only typelib we use that we don't jhbuild
|
||||
PKG_CHECK_EXISTS([libnm-glib >= 0.8.999],
|
||||
[NM_TYPELIBDIR=`$PKG_CONFIG --variable=libdir libnm-glib`/girepository-1.0
|
||||
if test "$INTROSPECTION_TYPELIBDIR" != "$NM_TYPELIBDIR"; then
|
||||
JHBUILD_TYPELIBDIR="$JHBUILD_TYPELIBDIR:$NM_TYPELIBDIR"
|
||||
fi])
|
||||
AC_SUBST(JHBUILD_TYPELIBDIR)
|
||||
|
||||
saved_CFLAGS=$CFLAGS
|
||||
saved_LIBS=$LIBS
|
||||
CFLAGS=$GNOME_SHELL_CFLAGS
|
||||
LIBS=$GNOME_SHELL_LIBS
|
||||
# sn_startup_sequence_get_application_id, we can replace with a version check later
|
||||
AC_CHECK_FUNCS(JS_NewGlobalObject sn_startup_sequence_get_application_id)
|
||||
AC_CHECK_FUNCS(JS_NewGlobalObject sn_startup_sequence_get_application_id XFixesCreatePointerBarrier)
|
||||
CFLAGS=$saved_CFLAGS
|
||||
LIBS=$saved_LIBS
|
||||
|
||||
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 gnome-desktop-3.0 >= 2.90.0 x11)
|
||||
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.2 gnome-desktop-3.0 >= 2.90.0 x11)
|
||||
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-3.0)
|
||||
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
|
||||
PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0)
|
||||
PKG_CHECK_MODULES(JS_TEST, clutter-x11-1.0 gjs-1.0 gobject-introspection-1.0 gtk+-3.0)
|
||||
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 0.1.7)
|
||||
|
||||
AC_MSG_CHECKING([for bluetooth support])
|
||||
@@ -134,8 +145,8 @@ PKG_CHECK_MODULES(CALENDAR_SERVER, libecal-1.2 >= $LIBECAL_MIN_VERSION libedatas
|
||||
AC_SUBST(CALENDAR_SERVER_CFLAGS)
|
||||
AC_SUBST(CALENDAR_SERVER_LIBS)
|
||||
|
||||
MUTTER_GIR_DIR=`$PKG_CONFIG --variable=girdir libmutter-wm`
|
||||
MUTTER_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter-wm`
|
||||
MUTTER_GIR_DIR=`$PKG_CONFIG --variable=girdir libmutter`
|
||||
MUTTER_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter`
|
||||
AC_SUBST(MUTTER_GIR_DIR)
|
||||
AC_SUBST(MUTTER_TYPELIB_DIR)
|
||||
|
||||
@@ -190,20 +201,6 @@ AC_ARG_ENABLE(jhbuild-wrapper-script,
|
||||
AS_HELP_STRING([--jhbuild-wrapper-script=yes],[Make "gnome-shell" script work for jhbuild]),,enable_jhbuild_wrapper_script=no)
|
||||
AM_CONDITIONAL(USE_JHBUILD_WRAPPER_SCRIPT, test "x$enable_jhbuild_wrapper_script" = xyes)
|
||||
|
||||
AC_MSG_CHECKING([for Ubuntu])
|
||||
if test -f /etc/ubuntu_version; then
|
||||
enable_dynamic_mozjs_hack_default=yes
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
enable_dynamic_mozjs_hack_default=no
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(dynamic-mozjs-hack,
|
||||
AS_HELP_STRING([--dynamic-mozjs-hack=no],[Look for libmozjs.so using pkg-config]),,enable_dynamic_mozjs_hack=$enable_dynamic_mozjs_hack_default)
|
||||
ENABLE_DYNAMIC_MOZJS_HACK=$enable_dynamic_mozjs_hack
|
||||
AC_SUBST(ENABLE_DYNAMIC_MOZJS_HACK)
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
data/Makefile
|
||||
|
||||
@@ -24,31 +24,21 @@ dist_theme_DATA = \
|
||||
theme/calendar-today.svg \
|
||||
theme/close-window.svg \
|
||||
theme/close.svg \
|
||||
theme/corner-ripple.png \
|
||||
theme/corner-ripple-ltr.png \
|
||||
theme/corner-ripple-rtl.png \
|
||||
theme/dash-placeholder.svg \
|
||||
theme/filter-selected-ltr.svg \
|
||||
theme/filter-selected-rtl.svg \
|
||||
theme/gnome-shell.css \
|
||||
theme/mosaic-view-active.svg \
|
||||
theme/mosaic-view.svg \
|
||||
theme/move-window-on-new.svg \
|
||||
theme/panel-border.svg \
|
||||
theme/panel-button-border.svg \
|
||||
theme/panel-button-highlight-narrow.svg \
|
||||
theme/panel-button-highlight-wide.svg \
|
||||
theme/process-working.svg \
|
||||
theme/running-indicator.svg \
|
||||
theme/scroll-button-down-hover.png \
|
||||
theme/scroll-button-down.png \
|
||||
theme/scroll-button-up-hover.png \
|
||||
theme/scroll-button-up.png \
|
||||
theme/scroll-hhandle.svg \
|
||||
theme/scroll-vhandle.svg \
|
||||
theme/section-more.svg \
|
||||
theme/section-more-open.svg \
|
||||
theme/separator-white.png \
|
||||
theme/single-view-active.svg \
|
||||
theme/single-view.svg \
|
||||
theme/source-button-border.svg \
|
||||
theme/toggle-off-us.svg \
|
||||
theme/toggle-off-intl.svg \
|
||||
theme/toggle-on-us.svg \
|
||||
|
||||
@@ -13,3 +13,4 @@ NoDisplay=true
|
||||
X-GNOME-Autostart-Phase=WindowManager
|
||||
X-GNOME-Provides=panel;windowmanager;
|
||||
X-GNOME-Autostart-Notify=true
|
||||
X-GNOME-AutoRestart=true
|
||||
|
||||
@@ -81,5 +81,20 @@
|
||||
</locale>
|
||||
</schema>
|
||||
|
||||
<schema>
|
||||
<key>/schemas/desktop/gnome/shell/windows/workspaces_only_on_primary</key>
|
||||
<applyto>/desktop/gnome/shell/windows/workspaces_only_on_primary</applyto>
|
||||
<owner>gnome-shell</owner>
|
||||
<type>bool</type>
|
||||
<default>true</default>
|
||||
<locale name="C">
|
||||
<short>Workspaces only on primary monitor</short>
|
||||
<long>
|
||||
This key overrides /apps/mutter/general/workspaces_only_on_primary when
|
||||
running GNOME Shell.
|
||||
</long>
|
||||
</locale>
|
||||
</schema>
|
||||
|
||||
</schemalist>
|
||||
</gconfschemafile>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<schemalist>
|
||||
<schema id="org.gnome.shell" path="/apps/gnome-shell/"
|
||||
<schema id="org.gnome.shell" path="/org/gnome/shell/"
|
||||
gettext-domain="@GETTEXT_PACKAGE@">
|
||||
<key name="development-tools" type="b">
|
||||
<default>true</default>
|
||||
@@ -54,7 +54,7 @@
|
||||
<child name="recorder" schema="org.gnome.shell.recorder"/>
|
||||
</schema>
|
||||
|
||||
<schema id="org.gnome.shell.calendar" path="/apps/gnome-shell/calendar/"
|
||||
<schema id="org.gnome.shell.calendar" path="/org/gnome/shell/calendar/"
|
||||
gettext-domain="@GETTEXT_PACKAGE@">
|
||||
<key name="show-weekdate" type="b">
|
||||
<default>false</default>
|
||||
@@ -65,7 +65,7 @@
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<schema id="org.gnome.shell.clock" path="/apps/gnome-shell/clock/"
|
||||
<schema id="org.gnome.shell.clock" path="/org/gnome/shell/clock/"
|
||||
gettext-domain="@GETTEXT_PACKAGE@">
|
||||
<key name="show-seconds" type="b">
|
||||
<default>false</default>
|
||||
@@ -83,7 +83,7 @@
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<schema id="org.gnome.shell.recorder" path="/apps/gnome-shell/recorder/"
|
||||
<schema id="org.gnome.shell.recorder" path="/org/gnome/shell/recorder/"
|
||||
gettext-domain="@GETTEXT_PACKAGE@">
|
||||
<key name="framerate" type="i">
|
||||
<default>15</default>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
BIN
data/theme/corner-ripple-rtl.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
@@ -34,13 +34,6 @@ stage {
|
||||
color: rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.label-real-shadow {
|
||||
background-gradient-direction: horizontal;
|
||||
background-gradient-start: rgba(0, 0, 0, 0);
|
||||
background-gradient-end: rgba(0, 0, 0, 255);
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
StScrollBar
|
||||
{
|
||||
padding: 0px;
|
||||
@@ -82,10 +75,10 @@ StScrollBar StButton#vhandle:hover
|
||||
}
|
||||
|
||||
StTooltip StLabel {
|
||||
border: 1px solid rgba(79,111,173,1);
|
||||
border: 1px solid rgba(255,255,255,0.6);
|
||||
border-radius: 5px;
|
||||
padding: 4px;
|
||||
background-color: rgba(79,111,173,0.9);
|
||||
padding: 2px 12px;
|
||||
background-color: rgba(0,0,0,0.9);
|
||||
color: #ffffff;
|
||||
font-size: 0.8em;
|
||||
font-weight: normal;
|
||||
@@ -105,12 +98,40 @@ StTooltip StLabel {
|
||||
|
||||
.popup-menu {
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
font-size: 10.5pt;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.popup-submenu-menu-item:open {
|
||||
background-color: #4c4c4c;
|
||||
}
|
||||
|
||||
.popup-sub-menu {
|
||||
background-color: #606060;
|
||||
background-gradient-start: rgba(80,80,80,0.3);
|
||||
background-gradient-end: rgba(80,80,80,0.7);
|
||||
background-gradient-direction: vertical;
|
||||
box-shadow: inset 0px 2px 4px rgba(0,0,0,0.9);
|
||||
}
|
||||
|
||||
.popup-sub-menu .popup-menu-item:ltr {
|
||||
padding-right: 0em;
|
||||
}
|
||||
|
||||
.popup-sub-menu .popup-menu-item:rtl {
|
||||
padding-left: 0em;
|
||||
}
|
||||
|
||||
.popup-sub-menu StScrollBar {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.popup-sub-menu StScrollBar StBin#trough {
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
.popup-sub-menu StScrollBar StBin#vhandle {
|
||||
background-color: #4c4c4c;
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
/* The remaining popup-menu sizing is all done in ems, so that if you
|
||||
@@ -150,6 +171,8 @@ StTooltip StLabel {
|
||||
-slider-height: 0.3em;
|
||||
-slider-background-color: #333333;
|
||||
-slider-border-color: #5f5f5f;
|
||||
-slider-active-background-color: #76b0ec;
|
||||
-slider-active-border-color: #1f6dbc;
|
||||
-slider-border-width: 1px;
|
||||
-slider-handle-radius: 0.5em;
|
||||
}
|
||||
@@ -158,14 +181,22 @@ StTooltip StLabel {
|
||||
spacing: .5em;
|
||||
}
|
||||
|
||||
.popup-inactive-menu-item {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.popup-subtitle-menu-item {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.popup-menu-icon {
|
||||
icon-size: 1.14em;
|
||||
}
|
||||
|
||||
/* Switches (to be used in menus) */
|
||||
.toggle-switch {
|
||||
width: 4.5em;
|
||||
height: 1.5em;
|
||||
width: 65px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.toggle-switch-us {
|
||||
@@ -182,12 +213,18 @@ StTooltip StLabel {
|
||||
background-image: url("toggle-on-intl.svg");
|
||||
}
|
||||
|
||||
.nm-menu-item-icons {
|
||||
spacing: .5em;
|
||||
}
|
||||
|
||||
/* Panel */
|
||||
|
||||
#panel {
|
||||
color: #ffffff;
|
||||
background-color: black;
|
||||
border-image: url("panel-border.svg") 1;
|
||||
font-size: 10.5pt;
|
||||
height: 1.86em;
|
||||
}
|
||||
|
||||
#panelLeft, #panelCenter, #panelRight {
|
||||
@@ -247,12 +284,16 @@ StTooltip StLabel {
|
||||
|
||||
.panel-button {
|
||||
padding: 0px 12px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #ccc;
|
||||
transition-duration: 100;
|
||||
}
|
||||
|
||||
.panel-button:hover {
|
||||
color: white;
|
||||
text-shadow: black 0px 2px 2px;
|
||||
}
|
||||
|
||||
.panel-button:active,
|
||||
.panel-button:checked,
|
||||
.panel-button:focus {
|
||||
@@ -315,7 +356,7 @@ StTooltip StLabel {
|
||||
background-color: rgba(0,0,0,0.6);
|
||||
}
|
||||
|
||||
.workspaces-view {
|
||||
.window-caption {
|
||||
color: white;
|
||||
spacing: 25px;
|
||||
}
|
||||
@@ -344,13 +385,14 @@ StTooltip StLabel {
|
||||
|
||||
.workspace-thumbnail-indicator {
|
||||
outline: 2px solid white;
|
||||
border: 1px solid #888;
|
||||
}
|
||||
|
||||
.window-caption {
|
||||
background: rgba(0,0,0,0.8);
|
||||
border: 1px solid rgba(128,128,128,0.40);
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
font-size: 9pt;
|
||||
padding: 2px 8px;
|
||||
-shell-caption-spacing: 4px;
|
||||
}
|
||||
@@ -370,7 +412,7 @@ StTooltip StLabel {
|
||||
|
||||
#dash {
|
||||
color: #5f5f5f;
|
||||
font-size: 12px;
|
||||
font-size: 9pt;
|
||||
padding: 4px 0px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
border: 1px solid rgba(128, 128, 128, 0.4);
|
||||
@@ -396,12 +438,12 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
#viewSelector {
|
||||
spacing: 16px;
|
||||
font-size: 16px;
|
||||
spacing: 1em;
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
#viewSelectorTabBar {
|
||||
padding: 16px;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
#searchArea {
|
||||
@@ -449,8 +491,8 @@ StTooltip StLabel {
|
||||
.view-tab-title {
|
||||
color: #888a85;
|
||||
font-weight: bold;
|
||||
padding: 0px 12px;
|
||||
height: 24px;
|
||||
padding: 0px 0.75em;
|
||||
height: 1.5em;
|
||||
}
|
||||
|
||||
.view-tab-title:hover {
|
||||
@@ -460,17 +502,7 @@ StTooltip StLabel {
|
||||
.view-tab-title:selected {
|
||||
color: #000000;
|
||||
background-color: #c2c7cd;
|
||||
border-radius: 4px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.view-tab-boxpointer {
|
||||
-arrow-border-radius: 9px;
|
||||
-arrow-background-color: rgba(0,0,0,0.5);
|
||||
-arrow-border-width: 2px;
|
||||
-arrow-border-color: rgba(255,255,255,0.5);
|
||||
-arrow-base: 30px;
|
||||
-arrow-rise: 15px;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
#searchResults {
|
||||
@@ -533,7 +565,7 @@ StTooltip StLabel {
|
||||
|
||||
.dash-search-button-label {
|
||||
color: #cccccc;
|
||||
font-size: 16px;
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
/* Apps */
|
||||
@@ -558,9 +590,9 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.app-filter {
|
||||
font-size: 14px;
|
||||
font-size: 10.5pt;
|
||||
font-weight: bold;
|
||||
height: 40px;
|
||||
height: 2.85em;
|
||||
color: #aaa;
|
||||
width: 200px;
|
||||
}
|
||||
@@ -603,7 +635,7 @@ StTooltip StLabel {
|
||||
border-radius: 4px;
|
||||
padding: 3px;
|
||||
border: 1px rgba(0,0,0,0);
|
||||
font-size: 10px;
|
||||
font-size: 7.5pt;
|
||||
color: white;
|
||||
transition-duration: 100;
|
||||
text-align: center;
|
||||
@@ -633,7 +665,7 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.app-well-menu {
|
||||
font-size: 12px
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
/* LookingGlass */
|
||||
@@ -761,7 +793,7 @@ StTooltip StLabel {
|
||||
|
||||
#calendarArea {
|
||||
/* this is the width of the entire popup */
|
||||
width: 600px;
|
||||
min-width: 600px;
|
||||
}
|
||||
|
||||
.calendar-vertical-separator {
|
||||
@@ -789,7 +821,7 @@ StTooltip StLabel {
|
||||
|
||||
.calendar-month-label {
|
||||
color: #666666;
|
||||
font-size: 10px;
|
||||
font-size: 7.5pt;
|
||||
padding: 2px;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -832,16 +864,16 @@ StTooltip StLabel {
|
||||
|
||||
.datemenu-date-label {
|
||||
padding: .4em 1.75em;
|
||||
font-size: 14px;
|
||||
font-size: 10.5pt;
|
||||
color: #cccccc;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.calendar-day-base {
|
||||
font-size: 10px;
|
||||
font-size: 7.5pt;
|
||||
text-align: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
width: 2.4em;
|
||||
height: 2.4em;
|
||||
}
|
||||
|
||||
.calendar-day-base:hover {
|
||||
@@ -899,11 +931,13 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.events-header-vbox {
|
||||
spacing: 8px;
|
||||
spacing: 6pt;
|
||||
padding-right: 1.75em;
|
||||
}
|
||||
|
||||
.events-header {
|
||||
height: 40px;
|
||||
.events-header-vbox:rtl {
|
||||
padding-right: 0em;
|
||||
padding-left: 1.75em;
|
||||
}
|
||||
|
||||
.events-header-hbox {
|
||||
@@ -911,7 +945,7 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.events-day-header {
|
||||
font-size: 12px;
|
||||
font-size: 9pt;
|
||||
font-weight: bold;
|
||||
color: rgba(153, 153, 153, 1.0);
|
||||
padding-left: 0.3em;
|
||||
@@ -923,7 +957,7 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.events-day-dayname {
|
||||
font-size: 12px;
|
||||
font-size: 9pt;
|
||||
color: rgba(153, 153, 153, 1.0);
|
||||
text-align: left;
|
||||
}
|
||||
@@ -933,7 +967,7 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.events-day-time {
|
||||
font-size: 12px;
|
||||
font-size: 9pt;
|
||||
color: #fff;
|
||||
text-align: right;
|
||||
}
|
||||
@@ -943,22 +977,22 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.events-day-task {
|
||||
font-size: 12px;
|
||||
font-size: 9pt;
|
||||
color: rgba(153, 153, 153, 1.0);
|
||||
}
|
||||
|
||||
.events-day-name-box {
|
||||
width: 20px;
|
||||
min-width: 15pt;
|
||||
}
|
||||
|
||||
.events-time-box {
|
||||
width: 70px;
|
||||
padding-right: 8px;
|
||||
min-width: 53pt;
|
||||
padding-right: 6pt;
|
||||
}
|
||||
|
||||
.events-time-box:rtl {
|
||||
padding-right: 0px;
|
||||
padding-left: 8px;
|
||||
padding-left: 6pt;
|
||||
}
|
||||
|
||||
.events-event-box {
|
||||
@@ -972,13 +1006,13 @@ StTooltip StLabel {
|
||||
#message-tray {
|
||||
background-gradient-direction: vertical;
|
||||
background-gradient-start: rgba(0,0,0,0.01);
|
||||
background-gradient-end: rgba(0,0,0,0.95);
|
||||
background-gradient-end: rgba(0,0,0,0.82);
|
||||
height: 36px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#notification {
|
||||
font-size: 16px;
|
||||
font-size: 12pt;
|
||||
border-radius: 5px 5px 0px 0px;
|
||||
background: rgba(0,0,0,0.9);
|
||||
padding: 8px 8px 4px 8px;
|
||||
@@ -1007,11 +1041,29 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.summary-boxpointer #summary-right-click-menu {
|
||||
font-size: 14px;
|
||||
font-size: 10.5pt;
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
#summary-notification-stack-scrollview {
|
||||
max-height: 18em;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
#summary-notification-stack-scrollview > .top-shadow, #summary-notification-stack-scrollview > .bottom-shadow {
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
#summary-notification-stack-scrollview:ltr {
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
#summary-notification-stack-scrollview:rtl {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
#notification-scrollview {
|
||||
max-height: 10em;
|
||||
}
|
||||
@@ -1078,6 +1130,10 @@ StTooltip StLabel {
|
||||
icon-size: 36px;
|
||||
}
|
||||
|
||||
.chat-log-message {
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.chat-received {
|
||||
background-gradient-direction: horizontal;
|
||||
background-gradient-start: rgba(255, 255, 255, 0.2);
|
||||
@@ -1109,7 +1165,7 @@ StTooltip StLabel {
|
||||
.chat-meta-message {
|
||||
padding-left: 4px;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
font-size: 10.5pt;
|
||||
color: #bbbbbb;
|
||||
}
|
||||
|
||||
@@ -1158,14 +1214,32 @@ StTooltip StLabel {
|
||||
padding: 2px 4px 0px 0px;
|
||||
}
|
||||
|
||||
.summary-source-button {
|
||||
color: #fff;
|
||||
text-shadow: black 0px 2px 2px;
|
||||
}
|
||||
|
||||
.summary-source-button:ltr {
|
||||
padding-left: 4px;
|
||||
padding-right: 16px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.summary-source-button:selected .summary-source {
|
||||
background-image: url("panel-button-highlight-narrow.svg");
|
||||
border-image: url("source-button-border.svg") 10 10 0 1;
|
||||
}
|
||||
|
||||
.summary-source-button:expanded:selected .summary-source {
|
||||
background-image: none;
|
||||
border-image: none;
|
||||
}
|
||||
|
||||
.summary-source-button:expanded:selected {
|
||||
background-image: url("panel-button-highlight-wide.svg");
|
||||
border-image: url("source-button-border.svg") 10 10 0 1;
|
||||
}
|
||||
|
||||
.summary-source-button:rtl {
|
||||
padding-right: 4px;
|
||||
padding-left: 16px;
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.summary-source-button:last-child:ltr {
|
||||
@@ -1176,8 +1250,13 @@ StTooltip StLabel {
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.summary-source {
|
||||
padding-right: 4px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.source-title {
|
||||
font-size: 12px;
|
||||
font-size: 9pt;
|
||||
font-weight: bold;
|
||||
padding-left: 4px;
|
||||
}
|
||||
@@ -1199,7 +1278,7 @@ StTooltip StLabel {
|
||||
border-radius: 24px;
|
||||
padding: 20px;
|
||||
|
||||
font-size: 12px;
|
||||
font-size: 9pt;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@@ -1258,7 +1337,11 @@ StTooltip StLabel {
|
||||
.ripple-box {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
background-image: url("corner-ripple.png");
|
||||
background-image: url("corner-ripple-ltr.png");
|
||||
}
|
||||
|
||||
.ripple-box:rtl {
|
||||
background-image: url("corner-ripple-rtl.png");
|
||||
}
|
||||
|
||||
.switcher-arrow {
|
||||
@@ -1328,10 +1411,14 @@ StTooltip StLabel {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.modal-dialog-button-box {
|
||||
spacing: 21px;
|
||||
}
|
||||
|
||||
.modal-dialog-button {
|
||||
border: 1px solid #8b8b8b;
|
||||
border-radius: 18px;
|
||||
font-size: 14px;
|
||||
font-size: 10.5pt;
|
||||
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
@@ -1364,12 +1451,12 @@ StTooltip StLabel {
|
||||
|
||||
/* Run Dialog */
|
||||
.run-dialog-label {
|
||||
font-size: 12px;
|
||||
font-size: 9pt;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.run-dialog-error-label {
|
||||
font-size: 12px;
|
||||
font-size: 9pt;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@@ -1379,9 +1466,9 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.run-dialog-entry {
|
||||
font-size: 14px;
|
||||
font-size: 10.5pt;
|
||||
font-weight: bold;
|
||||
width: 320px;
|
||||
width: 23em;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@@ -1399,6 +1486,10 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
/* End Session Dialog */
|
||||
.end-session-dialog {
|
||||
spacing: 42px;
|
||||
}
|
||||
|
||||
.end-session-dialog-subject {
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
@@ -1417,13 +1508,11 @@ StTooltip StLabel {
|
||||
font-size: 10pt;
|
||||
color: white;
|
||||
padding-left: 17px;
|
||||
padding-right: 40px;
|
||||
width: 16em;
|
||||
width: 28em;
|
||||
}
|
||||
|
||||
.end-session-dialog-description:rtl {
|
||||
padding-right: 17px;
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.end-session-dialog-logout-icon {
|
||||
@@ -1442,16 +1531,23 @@ StTooltip StLabel {
|
||||
font-size: 10pt;
|
||||
max-height: 200px;
|
||||
padding-top: 42px;
|
||||
padding-bottom: 42px;
|
||||
padding-left: 17px;
|
||||
padding-left: 49px;
|
||||
padding-right: 32px;
|
||||
}
|
||||
|
||||
.end-session-dialog-app-list:rtl {
|
||||
padding-right: 17px;
|
||||
padding-right: 49px;
|
||||
padding-left: 32px;
|
||||
}
|
||||
|
||||
.end-session-dialog-app-list-item {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.end-session-dialog-app-list-item:hover {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.end-session-dialog-app-list-item:ltr {
|
||||
padding-right: 1em;
|
||||
}
|
||||
@@ -1484,12 +1580,12 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.polkit-dialog-main-layout {
|
||||
spacing: 10px;
|
||||
spacing: 24px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.polkit-dialog-message-layout {
|
||||
spacing: 10px;
|
||||
spacing: 16px;
|
||||
}
|
||||
|
||||
.polkit-dialog-headline {
|
||||
@@ -1513,6 +1609,10 @@ StTooltip StLabel {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.polkit-dialog-user-root-label {
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
.polkit-dialog-password-label:ltr {
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
@@ -1528,33 +1628,21 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.polkit-dialog-error-label {
|
||||
font-size: 12px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.polkit-dialog-error-box {
|
||||
padding-top: 15px;
|
||||
spacing: 5px;
|
||||
}
|
||||
|
||||
.polkit-dialog-checking-label {
|
||||
font-size: 12px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.polkit-dialog-checking-box {
|
||||
padding-top: 15px;
|
||||
spacing: 5px;
|
||||
font-size: 10pt;
|
||||
color: #ffff00;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.polkit-dialog-info-label {
|
||||
font-size: 12px;
|
||||
color: white;
|
||||
font-size: 10pt;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.polkit-dialog-info-box {
|
||||
padding-top: 15px;
|
||||
spacing: 5px;
|
||||
/* intentionally left transparent to avoid dialog changing size */
|
||||
.polkit-dialog-null-label {
|
||||
font-size: 10pt;
|
||||
color: rgba(0,0,0,0);
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
|
||||
@@ -1567,3 +1655,49 @@ StTooltip StLabel {
|
||||
.magnifier-zoom-region.full-screen {
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
|
||||
/* goa message popup */
|
||||
|
||||
.goa-message-table {
|
||||
}
|
||||
|
||||
.goa-message-base {
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
.goa-message-from-header {
|
||||
color: #666666;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.goa-message-subject-header {
|
||||
color: #666666;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.goa-message-date-header {
|
||||
color: #666666;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.goa-message-from {
|
||||
font-weight: bold;
|
||||
min-width: 125px;
|
||||
}
|
||||
|
||||
.goa-message-hbox {
|
||||
spacing: 0.25em;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.goa-message-subject {
|
||||
}
|
||||
|
||||
.goa-message-excerpt {
|
||||
color: rgba(153, 153, 153, 1.0);
|
||||
}
|
||||
|
||||
.goa-message-date {
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
<?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="24"
|
||||
height="16"
|
||||
id="svg6503"
|
||||
version="1.1"
|
||||
inkscape:version="0.47pre4 r22446"
|
||||
sodipodi:docname="mosaic-view-active.svg">
|
||||
<defs
|
||||
id="defs6505">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 16 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="32 : 16 : 1"
|
||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||
id="perspective6511" />
|
||||
<inkscape:perspective
|
||||
id="perspective6494"
|
||||
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" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.197802"
|
||||
inkscape:cx="-15.97056"
|
||||
inkscape:cy="16"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="997"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="26"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata6508">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
transform="translate(0,-16)">
|
||||
<g
|
||||
style="display:inline;fill:#cbcbcb;fill-opacity:1"
|
||||
transform="translate(-449.85476,-685.85869)"
|
||||
id="g5306">
|
||||
<rect
|
||||
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none"
|
||||
id="rect5308"
|
||||
width="11"
|
||||
height="7"
|
||||
x="450.5"
|
||||
y="710.5"
|
||||
rx="0.99999958"
|
||||
ry="1" />
|
||||
<rect
|
||||
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
|
||||
id="rect5310"
|
||||
width="11"
|
||||
height="7"
|
||||
x="462.5"
|
||||
y="702.5"
|
||||
rx="0.99999958"
|
||||
ry="1" />
|
||||
<rect
|
||||
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999976000000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
|
||||
id="rect5312"
|
||||
width="11"
|
||||
height="7"
|
||||
x="450.5"
|
||||
y="702.5"
|
||||
rx="0.99999958"
|
||||
ry="1" />
|
||||
<rect
|
||||
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
|
||||
id="rect5314"
|
||||
width="11"
|
||||
height="7"
|
||||
x="462.5"
|
||||
y="710.5"
|
||||
rx="0.99999958"
|
||||
ry="1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.7 KiB |
@@ -1,113 +0,0 @@
|
||||
<?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="24"
|
||||
height="16"
|
||||
id="svg6503"
|
||||
version="1.1"
|
||||
inkscape:version="0.47pre4 r22446"
|
||||
sodipodi:docname="New document 19">
|
||||
<defs
|
||||
id="defs6505">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 16 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="32 : 16 : 1"
|
||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||
id="perspective6511" />
|
||||
<inkscape:perspective
|
||||
id="perspective6494"
|
||||
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" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.197802"
|
||||
inkscape:cx="16"
|
||||
inkscape:cy="16"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="997"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="26"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata6508">
|
||||
<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"
|
||||
transform="translate(0,-16)">
|
||||
<g
|
||||
style="display:inline"
|
||||
transform="translate(-449.85476,-685.85869)"
|
||||
id="g5306">
|
||||
<rect
|
||||
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none"
|
||||
id="rect5308"
|
||||
width="11"
|
||||
height="7"
|
||||
x="450.5"
|
||||
y="710.5"
|
||||
rx="0.99999958"
|
||||
ry="1" />
|
||||
<rect
|
||||
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
|
||||
id="rect5310"
|
||||
width="11"
|
||||
height="7"
|
||||
x="462.5"
|
||||
y="702.5"
|
||||
rx="0.99999958"
|
||||
ry="1" />
|
||||
<rect
|
||||
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.99999976;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
|
||||
id="rect5312"
|
||||
width="11"
|
||||
height="7"
|
||||
x="450.5"
|
||||
y="702.5"
|
||||
rx="0.99999958"
|
||||
ry="1" />
|
||||
<rect
|
||||
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
|
||||
id="rect5314"
|
||||
width="11"
|
||||
height="7"
|
||||
x="462.5"
|
||||
y="710.5"
|
||||
rx="0.99999958"
|
||||
ry="1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.6 KiB |
@@ -1,89 +0,0 @@
|
||||
<?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="98"
|
||||
height="98"
|
||||
id="svg6375"
|
||||
version="1.1"
|
||||
inkscape:version="0.47 r22583"
|
||||
sodipodi:docname="add-workspace.svg">
|
||||
<defs
|
||||
id="defs6377">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 16 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="32 : 16 : 1"
|
||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||
id="perspective6383" />
|
||||
<inkscape:perspective
|
||||
id="perspective6366"
|
||||
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" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.9590209"
|
||||
inkscape:cx="56.650687"
|
||||
inkscape:cy="20.635343"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="997"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="26"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata6380">
|
||||
<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"
|
||||
transform="translate(0,66)">
|
||||
<g
|
||||
id="g2824"
|
||||
transform="matrix(11.568551,0,0,11.698271,-78.828159,-304.81518)">
|
||||
<path
|
||||
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 11.07363,21.36834 0,6.43903"
|
||||
id="path5322" />
|
||||
<path
|
||||
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||
d="m 14.29314,24.58786 -6.43902,0"
|
||||
id="path5324" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:0.98823529"
|
||||
d="m 48.239516,97.908047 c -0.41677,-0.05102 -1.269253,-0.222408 -1.894408,-0.380859 -4.088493,-1.036262 -7.520781,-4.753234 -8.330163,-9.021094 -0.154947,-0.817026 -0.257819,-6.68112 -0.257819,-14.696556 l 0,-13.337088 -13.829177,-0.08909 C 10.802042,60.298796 10.026884,60.268266 8.6851548,59.783022 3.6288503,57.954375 0.62673331,53.828648 0.62673331,48.708554 c 0,-5.625522 4.25936019,-10.425065 9.97721469,-11.242548 0.987903,-0.141242 7.368912,-0.254994 14.460646,-0.257791 l 12.692532,-0.005 0,-13.586668 c 0,-14.6441583 0.03287,-15.0698926 1.364686,-17.6753047 2.185477,-4.2754229 6.938193,-6.75739913 11.687647,-6.10355607 3.382776,0.46569661 6.737962,2.72496967 8.414081,5.66577137 1.480816,2.5981315 1.519067,3.0522448 1.519067,18.0333334 l 0,13.666424 12.692533,0.005 c 7.091733,0.0028 13.472742,0.116549 14.460646,0.257791 6.395303,0.914337 10.804785,6.623716 9.941157,12.871766 -0.698243,5.051565 -4.792685,9.104635 -9.941157,9.840713 -0.987904,0.141242 -7.368913,0.254995 -14.460646,0.257791 l -12.692533,0.005 0,13.801945 c 0,13.031417 -0.02798,13.895893 -0.501177,15.484801 -1.526902,5.127058 -6.919246,8.802262 -12.001914,8.18002 z"
|
||||
id="path2828"
|
||||
transform="translate(0,-66)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 225 B |
|
Before Width: | Height: | Size: 225 B |
|
Before Width: | Height: | Size: 211 B |
|
Before Width: | Height: | Size: 211 B |
@@ -1,87 +0,0 @@
|
||||
<?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="5.8600588"
|
||||
height="9"
|
||||
id="svg3647"
|
||||
version="1.1"
|
||||
inkscape:version="0.47 r22583"
|
||||
sodipodi:docname="section-more.svg">
|
||||
<defs
|
||||
id="defs3649">
|
||||
<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="perspective3655" />
|
||||
<inkscape:perspective
|
||||
id="perspective3603"
|
||||
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" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="82.777778"
|
||||
inkscape:cx="2.9300294"
|
||||
inkscape:cy="5.466443"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="997"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="26"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata3652">
|
||||
<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(-262.78425,-490.71933)">
|
||||
<path
|
||||
transform="matrix(0,-0.98149546,0.71467449,0,25.404986,578.15569)"
|
||||
d="M 88.830127,340 80.169873,340 84.5,332.5 88.830127,340 z"
|
||||
inkscape:randomized="0"
|
||||
inkscape:rounded="0"
|
||||
inkscape:flatsided="true"
|
||||
sodipodi:arg2="1.5707963"
|
||||
sodipodi:arg1="0.52359878"
|
||||
sodipodi:r2="2.5"
|
||||
sodipodi:r1="5"
|
||||
sodipodi:cy="337.5"
|
||||
sodipodi:cx="84.5"
|
||||
sodipodi:sides="3"
|
||||
id="path5497-5"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.59699643;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||
sodipodi:type="star" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
@@ -1,87 +0,0 @@
|
||||
<?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="5.8600588"
|
||||
height="9"
|
||||
id="svg3647"
|
||||
version="1.1"
|
||||
inkscape:version="0.46+devel"
|
||||
sodipodi:docname="New document 6">
|
||||
<defs
|
||||
id="defs3649">
|
||||
<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="perspective3655" />
|
||||
<inkscape:perspective
|
||||
id="perspective3603"
|
||||
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" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.35"
|
||||
inkscape:cx="112.21575"
|
||||
inkscape:cy="-32.642856"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="609"
|
||||
inkscape:window-height="501"
|
||||
inkscape:window-x="164"
|
||||
inkscape:window-y="26"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata3652">
|
||||
<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(-262.78425,-490.71933)">
|
||||
<path
|
||||
transform="matrix(0,0.98149546,-0.71467449,0,506.02358,412.28296)"
|
||||
d="M 88.830127,340 80.169873,340 84.5,332.5 88.830127,340 z"
|
||||
inkscape:randomized="0"
|
||||
inkscape:rounded="0"
|
||||
inkscape:flatsided="true"
|
||||
sodipodi:arg2="1.5707963"
|
||||
sodipodi:arg1="0.52359878"
|
||||
sodipodi:r2="2.5"
|
||||
sodipodi:r1="5"
|
||||
sodipodi:cy="337.5"
|
||||
sodipodi:cx="84.5"
|
||||
sodipodi:sides="3"
|
||||
id="path5497-5"
|
||||
style="fill:#5f5f5f;fill-opacity:1;stroke:#5f5f5f;stroke-width:0.59699643;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||
sodipodi:type="star" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 531 B |
@@ -1,81 +0,0 @@
|
||||
<?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="24"
|
||||
height="16"
|
||||
id="svg6446"
|
||||
version="1.1"
|
||||
inkscape:version="0.47pre4 r22446"
|
||||
sodipodi:docname="single-view-active.svg">
|
||||
<defs
|
||||
id="defs6448">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 16 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="32 : 16 : 1"
|
||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||
id="perspective6454" />
|
||||
<inkscape:perspective
|
||||
id="perspective6441"
|
||||
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" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.197802"
|
||||
inkscape:cx="0.014720032"
|
||||
inkscape:cy="16"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="997"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="26"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata6451">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
transform="translate(0,-17)">
|
||||
<rect
|
||||
ry="0.5"
|
||||
rx="0.49999979"
|
||||
y="17.483809"
|
||||
x="0.53483802"
|
||||
height="15"
|
||||
width="23"
|
||||
id="rect5304"
|
||||
style="fill:#cccccc;fill-opacity:1;stroke:#cccccc;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.4 KiB |
@@ -1,81 +0,0 @@
|
||||
<?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="24"
|
||||
height="16"
|
||||
id="svg6446"
|
||||
version="1.1"
|
||||
inkscape:version="0.47pre4 r22446"
|
||||
sodipodi:docname="single-view.svg">
|
||||
<defs
|
||||
id="defs6448">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 16 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="32 : 16 : 1"
|
||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||
id="perspective6454" />
|
||||
<inkscape:perspective
|
||||
id="perspective6441"
|
||||
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" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.197802"
|
||||
inkscape:cx="0.014720032"
|
||||
inkscape:cy="16"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="997"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="26"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata6451">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
transform="translate(0,-17)">
|
||||
<rect
|
||||
ry="0.5"
|
||||
rx="0.49999979"
|
||||
y="17.483809"
|
||||
x="0.53483802"
|
||||
height="15"
|
||||
width="23"
|
||||
id="rect5304"
|
||||
style="fill:#626262;fill-opacity:1;stroke:#cccccc;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.4 KiB |
74
data/theme/source-button-border.svg
Normal file
@@ -0,0 +1,74 @@
|
||||
<?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="21"
|
||||
height="10"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.0 r9654"
|
||||
sodipodi:docname="source-button-border.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="44.8"
|
||||
inkscape:cx="8.704132"
|
||||
inkscape:cy="5.7029946"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1600"
|
||||
inkscape:window-height="1145"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="26"
|
||||
inkscape:window-maximized="1"
|
||||
guidetolerance="10000"
|
||||
objecttolerance="10000">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3792"
|
||||
empspacing="10"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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">
|
||||
<rect
|
||||
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke-width:0.43599999;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="rect3796"
|
||||
width="19"
|
||||
height="2"
|
||||
x="1"
|
||||
y="8" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -6,6 +6,22 @@
|
||||
|
||||
<name xml:lang="en">GNOME Shell</name>
|
||||
<shortdesc xml:lang="en">Next generation GNOME desktop shell</shortdesc>
|
||||
<description>GNOME Shell provides core user interface functions for the GNOME 3
|
||||
desktop, like switching to windows and launching applications.
|
||||
GNOME Shell takes advantage of the capabilities of modern graphics
|
||||
hardware and introduces innovative user interface concepts to
|
||||
provide a visually attractive and easy to use experience.
|
||||
|
||||
Tarball releases are provided largely for distributions to build
|
||||
packages. If you are interested in building GNOME Shell from source,
|
||||
we would recommend building from version control using the build
|
||||
script described at:
|
||||
|
||||
http://live.gnome.org/GnomeShell
|
||||
|
||||
Not only will that give you the very latest version of this rapidly
|
||||
changing project, it will be much easier than get GNOME Shell and
|
||||
its dependencies to build from tarballs.</description>
|
||||
<!--
|
||||
<homepage rdf:resource="http://live.gnome.org/GnomeShell" />
|
||||
-->
|
||||
|
||||
@@ -8,6 +8,7 @@ nobase_dist_js_DATA = \
|
||||
misc/format.js \
|
||||
misc/gnomeSession.js \
|
||||
misc/history.js \
|
||||
misc/modemManager.js \
|
||||
misc/params.js \
|
||||
misc/util.js \
|
||||
perf/core.js \
|
||||
@@ -25,6 +26,7 @@ nobase_dist_js_DATA = \
|
||||
ui/endSessionDialog.js \
|
||||
ui/environment.js \
|
||||
ui/extensionSystem.js \
|
||||
ui/goaClient.js \
|
||||
ui/iconGrid.js \
|
||||
ui/lightbox.js \
|
||||
ui/link.js \
|
||||
@@ -50,6 +52,7 @@ nobase_dist_js_DATA = \
|
||||
ui/statusMenu.js \
|
||||
ui/status/accessibility.js \
|
||||
ui/status/keyboard.js \
|
||||
ui/status/network.js \
|
||||
ui/status/power.js \
|
||||
ui/status/volume.js \
|
||||
ui/status/bluetooth.js \
|
||||
|
||||
@@ -102,3 +102,24 @@ Inhibitor.prototype = {
|
||||
};
|
||||
DBus.proxifyPrototype(Inhibitor.prototype, InhibitorIface);
|
||||
Signals.addSignalMethods(Inhibitor.prototype);
|
||||
|
||||
|
||||
// Not the full interface, only the methods we use
|
||||
const SessionManagerIface = {
|
||||
name: 'org.gnome.SessionManager',
|
||||
methods: [
|
||||
{ name: 'Logout', inSignature: 'u', outSignature: '' },
|
||||
{ name: 'Shutdown', inSignature: '', outSignature: '' }
|
||||
]
|
||||
};
|
||||
|
||||
function SessionManager() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
SessionManager.prototype = {
|
||||
_init: function() {
|
||||
DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager');
|
||||
}
|
||||
};
|
||||
DBus.proxifyPrototype(SessionManager.prototype, SessionManagerIface);
|
||||
@@ -77,9 +77,9 @@ HistoryManager.prototype = {
|
||||
this._history[this._history.length - 1] != input) {
|
||||
|
||||
this._history.push(input);
|
||||
this._historyIndex = this._history.length;
|
||||
this._save();
|
||||
}
|
||||
}
|
||||
this._historyIndex = this._history.length;
|
||||
},
|
||||
|
||||
_onEntryKeyPress: function(entry, event) {
|
||||
|
||||
225
js/misc/modemManager.js
Normal file
@@ -0,0 +1,225 @@
|
||||
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
|
||||
|
||||
const DBus = imports.dbus;
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
|
||||
// The following are not the complete interfaces, just the methods we need
|
||||
// (or may need in the future)
|
||||
|
||||
const ModemGsmNetworkInterface = {
|
||||
name: 'org.freedesktop.ModemManager.Modem.Gsm.Network',
|
||||
methods: [
|
||||
{ name: 'GetRegistrationInfo', inSignature: '', outSignature: 'uss' },
|
||||
{ name: 'GetSignalQuality', inSignature: '', outSignature: 'u' }
|
||||
],
|
||||
properties: [
|
||||
{ name: 'AccessTechnology', signature: 'u', access: 'read' }
|
||||
],
|
||||
signals: [
|
||||
{ name: 'SignalQuality', inSignature: 'u' },
|
||||
{ name: 'RegistrationInfo', inSignature: 'uss' }
|
||||
]
|
||||
};
|
||||
const ModemGsmNetworkProxy = DBus.makeProxyClass(ModemGsmNetworkInterface);
|
||||
|
||||
const ModemCdmaInterface = {
|
||||
name: 'org.freedesktop.ModemManager.Modem.Cdma',
|
||||
methods: [
|
||||
{ name: 'GetSignalQuality', inSignature: '', outSignature: 'u' },
|
||||
{ name: 'GetServingSystem', inSignature: '', outSignature: 'usu' }
|
||||
],
|
||||
signals: [
|
||||
{ name: 'SignalQuality', inSignature: 'u' }
|
||||
]
|
||||
};
|
||||
const ModemCdmaProxy = DBus.makeProxyClass(ModemCdmaInterface);
|
||||
|
||||
let _providersTable;
|
||||
function _getProvidersTable() {
|
||||
if (_providersTable)
|
||||
return _providersTable;
|
||||
let [providers, countryCodes] = Shell.mobile_providers_parse();
|
||||
return _providersTable = providers;
|
||||
}
|
||||
|
||||
function ModemGsm() {
|
||||
this._init.apply(this, arguments);
|
||||
}
|
||||
|
||||
ModemGsm.prototype = {
|
||||
_init: function(path) {
|
||||
this._proxy = new ModemGsmNetworkProxy(DBus.system, 'org.freedesktop.ModemManager', path);
|
||||
|
||||
this.signal_quality = 0;
|
||||
this.operator_name = null;
|
||||
|
||||
// Code is duplicated because the function have different signatures
|
||||
this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, quality) {
|
||||
this.signal_quality = quality;
|
||||
this.emit('notify::signal-quality');
|
||||
}));
|
||||
this._proxy.connect('RegistrationInfo', Lang.bind(this, function(proxy, status, code, name) {
|
||||
this.operator_name = this._findOperatorName(name, code);
|
||||
this.emit('notify::operator-name');
|
||||
}));
|
||||
this._proxy.GetRegistrationInfoRemote(Lang.bind(this, function(result, err) {
|
||||
if (err) {
|
||||
log(err);
|
||||
return;
|
||||
}
|
||||
|
||||
let [status, code, name] = result;
|
||||
this.operator_name = this._findOperatorName(name, code);
|
||||
this.emit('notify::operator-name');
|
||||
}));
|
||||
this._proxy.GetSignalQualityRemote(Lang.bind(this, function(result, err) {
|
||||
if (err) {
|
||||
// it will return an error if the device is not connected
|
||||
this.signal_quality = 0;
|
||||
} else {
|
||||
let [quality] = result;
|
||||
this.signal_quality = quality;
|
||||
}
|
||||
this.emit('notify::signal-quality');
|
||||
}));
|
||||
},
|
||||
|
||||
_findOperatorName: function(name, opCode) {
|
||||
if (name.length != 0 && (name.length > 6 || name.length < 5)) {
|
||||
// this looks like a valid name, i.e. not an MCCMNC (that some
|
||||
// devices return when not yet connected
|
||||
return name;
|
||||
}
|
||||
if (isNaN(parseInt(name))) {
|
||||
// name is definitely not a MCCMNC, so it may be a name
|
||||
// after all; return that
|
||||
return name;
|
||||
}
|
||||
|
||||
let needle;
|
||||
if (name.length == 0 && opCode)
|
||||
needle = opCode;
|
||||
else if (name.length == 6 || name.length == 5)
|
||||
needle = name;
|
||||
else // nothing to search
|
||||
return null;
|
||||
|
||||
return this._findProviderForMCCMNC(needle);
|
||||
},
|
||||
|
||||
_findProviderForMCCMNC: function(needle) {
|
||||
let table = _getProvidersTable();
|
||||
let needlemcc = needle.substring(0, 3);
|
||||
let needlemnc = needle.substring(3, needle.length);
|
||||
|
||||
let name2, name3;
|
||||
for (let iter in table) {
|
||||
let providers = table[iter];
|
||||
|
||||
// Search through each country's providers
|
||||
for (let i = 0; i < providers.length; i++) {
|
||||
let provider = providers[i];
|
||||
|
||||
// Search through MCC/MNC list
|
||||
let list = provider.get_gsm_mcc_mnc();
|
||||
for (let j = 0; j < list.length; j++) {
|
||||
let mccmnc = list[j];
|
||||
|
||||
// Match both 2-digit and 3-digit MNC; prefer a
|
||||
// 3-digit match if found, otherwise a 2-digit one.
|
||||
if (mccmnc.mcc != needlemcc)
|
||||
continue; // MCC was wrong
|
||||
|
||||
if (!name3 && needle.length == 6 && needlemnc == mccmnc.mnc)
|
||||
name3 = provider.name;
|
||||
|
||||
if (!name2 && needlemnc.substring(0, 2) == mccmnc.mnc.substring(0, 2))
|
||||
name2 = provider.name;
|
||||
|
||||
if (name2 && name3)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return name3 || name2 || null;
|
||||
}
|
||||
}
|
||||
Signals.addSignalMethods(ModemGsm.prototype);
|
||||
|
||||
function ModemCdma() {
|
||||
this._init.apply(this, arguments);
|
||||
}
|
||||
|
||||
ModemCdma.prototype = {
|
||||
_init: function(path) {
|
||||
this._proxy = new ModemCdmaProxy(DBus.system, 'org.freedesktop.ModemManager', path);
|
||||
|
||||
this.signal_quality = 0;
|
||||
this.operator_name = null;
|
||||
this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, quality) {
|
||||
this.signal_quality = quality;
|
||||
this.emit('notify::signal-quality');
|
||||
|
||||
// receiving this signal means the device got activated
|
||||
// and we can finally call GetServingSystem
|
||||
if (this.operator_name == null)
|
||||
this._refreshServingSystem();
|
||||
}));
|
||||
this._proxy.GetSignalQualityRemote(Lang.bind(this, function(result, err) {
|
||||
if (err) {
|
||||
// it will return an error if the device is not connected
|
||||
this.signal_quality = 0;
|
||||
} else {
|
||||
let [quality] = result;
|
||||
this.signal_quality = quality;
|
||||
}
|
||||
this.emit('notify::signal-quality');
|
||||
}));
|
||||
},
|
||||
|
||||
_refreshServingSystem: function() {
|
||||
this._proxy.GetServingSystemRemote(Lang.bind(this, function(result, err) {
|
||||
if (err) {
|
||||
// it will return an error if the device is not connected
|
||||
this.operator_name = null;
|
||||
} else {
|
||||
let [bandClass, band, id] = result;
|
||||
if (name.length > 0)
|
||||
this.operator_name = this._findProviderForSid(id);
|
||||
else
|
||||
this.operator_name = null;
|
||||
}
|
||||
this.emit('notify::operator-name');
|
||||
}));
|
||||
},
|
||||
|
||||
_findProviderForSid: function(sid) {
|
||||
if (sid == 0)
|
||||
return null;
|
||||
|
||||
let table = _getProvidersTable();
|
||||
|
||||
// Search through each country
|
||||
for (let iter in table) {
|
||||
let providers = table[iter];
|
||||
|
||||
// Search through each country's providers
|
||||
for (let i = 0; i < providers.length; i++) {
|
||||
let provider = providers[i];
|
||||
let cdma_sid = provider.get_cdma_sid();
|
||||
|
||||
// Search through CDMA SID list
|
||||
for (let j = 0; j < cdma_sid.length; j++) {
|
||||
if (cdma_sid[j] == sid)
|
||||
return provider.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(ModemCdma.prototype);
|
||||
132
js/misc/util.js
@@ -6,10 +6,6 @@ const GLib = imports.gi.GLib;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
/* http://daringfireball.net/2010/07/improved_regex_for_matching_urls */
|
||||
const _urlRegexp = new RegExp('\\b(([a-z][\\w-]+:(/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)([^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:\'\\".,<>?«»“”‘’]))', 'gi');
|
||||
@@ -56,20 +52,6 @@ function spawnCommandLine(command_line) {
|
||||
}
|
||||
}
|
||||
|
||||
// spawnDesktop:
|
||||
// @id: a desktop file ID
|
||||
//
|
||||
// Spawns the desktop file identified by @id using startup notification,
|
||||
// etc, handling any errors that occur when trying to find or start
|
||||
// the program.
|
||||
function spawnDesktop(id) {
|
||||
try {
|
||||
trySpawnDesktop(id);
|
||||
} catch (err) {
|
||||
_handleSpawnError(id, err);
|
||||
}
|
||||
}
|
||||
|
||||
// trySpawn:
|
||||
// @argv: an argv array
|
||||
//
|
||||
@@ -117,41 +99,9 @@ function trySpawnCommandLine(command_line) {
|
||||
trySpawn(argv);
|
||||
}
|
||||
|
||||
// trySpawnDesktop:
|
||||
// @id: a desktop file ID
|
||||
//
|
||||
// Spawns the desktop file identified by @id using startup notification.
|
||||
// On error, throws an exception.
|
||||
function trySpawnDesktop(id) {
|
||||
let app;
|
||||
|
||||
// shell_app_system_load_from_desktop_file() will end up returning
|
||||
// a stupid error message if the desktop file doesn't exist, but
|
||||
// that's the only case it returns an error for, so we just
|
||||
// substitute our own error in instead
|
||||
try {
|
||||
app = Shell.AppSystem.get_default().load_from_desktop_file(id + '.desktop');
|
||||
} catch (err) {
|
||||
throw new Error(_("No such application"));
|
||||
}
|
||||
|
||||
try {
|
||||
app.launch();
|
||||
} catch(err) {
|
||||
// see trySpawn
|
||||
err.message = err.message.replace(/.*\((.+)\)/, '$1');
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
function _handleSpawnError(command, err) {
|
||||
let title = _("Execution of '%s' failed:").format(command);
|
||||
|
||||
let source = new MessageTray.SystemNotificationSource();
|
||||
Main.messageTray.add(source);
|
||||
let notification = new MessageTray.Notification(source, title, err.message);
|
||||
notification.setTransient(true);
|
||||
source.notify(notification);
|
||||
Main.notifyError(title, err.message);
|
||||
}
|
||||
|
||||
// killall:
|
||||
@@ -178,3 +128,83 @@ function killall(processName) {
|
||||
logError(e, 'Failed to kill ' + processName);
|
||||
}
|
||||
}
|
||||
|
||||
// This was ported from network-manager-applet
|
||||
// Copyright 2007 - 2011 Red Hat, Inc.
|
||||
// Author: Dan Williams <dcbw@redhat.com>
|
||||
|
||||
const _IGNORED_WORDS = [
|
||||
'Semiconductor',
|
||||
'Components',
|
||||
'Corporation',
|
||||
'Communications',
|
||||
'Company',
|
||||
'Corp.',
|
||||
'Corp',
|
||||
'Co.',
|
||||
'Inc.',
|
||||
'Inc',
|
||||
'Incorporated',
|
||||
'Ltd.',
|
||||
'Limited.',
|
||||
'Intel',
|
||||
'chipset',
|
||||
'adapter',
|
||||
'[hex]',
|
||||
'NDIS',
|
||||
'Module'
|
||||
];
|
||||
|
||||
const _IGNORED_PHRASES = [
|
||||
'Multiprotocol MAC/baseband processor',
|
||||
'Wireless LAN Controller',
|
||||
'Wireless LAN Adapter',
|
||||
'Wireless Adapter',
|
||||
'Network Connection',
|
||||
'Wireless Cardbus Adapter',
|
||||
'Wireless CardBus Adapter',
|
||||
'54 Mbps Wireless PC Card',
|
||||
'Wireless PC Card',
|
||||
'Wireless PC',
|
||||
'PC Card with XJACK(r) Antenna',
|
||||
'Wireless cardbus',
|
||||
'Wireless LAN PC Card',
|
||||
'Technology Group Ltd.',
|
||||
'Communication S.p.A.',
|
||||
'Business Mobile Networks BV',
|
||||
'Mobile Broadband Minicard Composite Device',
|
||||
'Mobile Communications AB',
|
||||
'(PC-Suite Mode)'
|
||||
];
|
||||
|
||||
function fixupPCIDescription(desc) {
|
||||
desc = desc.replace(/[_,]/, ' ');
|
||||
|
||||
/* Attempt to shorten ID by ignoring certain phrases */
|
||||
for (let i = 0; i < _IGNORED_PHRASES.length; i++) {
|
||||
let item = _IGNORED_PHRASES[i];
|
||||
let pos = desc.indexOf(item);
|
||||
if (pos != -1) {
|
||||
let before = desc.substring(0, pos);
|
||||
let after = desc.substring(pos + item.length, desc.length);
|
||||
desc = before + after;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attmept to shorten ID by ignoring certain individual words */
|
||||
let words = desc.split(' ');
|
||||
let out = [ ];
|
||||
for (let i = 0; i < words.length; i++) {
|
||||
let item = words[i];
|
||||
|
||||
// skip empty items (that come out from consecutive spaces)
|
||||
if (item.length == 0)
|
||||
continue;
|
||||
|
||||
if (_IGNORED_WORDS.indexOf(item) == -1) {
|
||||
out.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return out.join(' ');
|
||||
}
|
||||
|
||||
@@ -21,26 +21,77 @@ let METRICS = {
|
||||
overviewFpsSubsequent:
|
||||
{ description: "Frames rate when going to the overview, second time",
|
||||
units: "frames / s" },
|
||||
overviewFps5Windows:
|
||||
{ description: "Frames rate when going to the overview, 5 windows open",
|
||||
units: "frames / s" },
|
||||
overviewFps10Windows:
|
||||
{ description: "Frames rate when going to the overview, 10 windows open",
|
||||
units: "frames / s" },
|
||||
overviewFps5Maximized:
|
||||
{ description: "Frames rate when going to the overview, 5 maximized windows open",
|
||||
units: "frames / s" },
|
||||
overviewFps10Maximized:
|
||||
{ description: "Frames rate when going to the overview, 10 maximized windows open",
|
||||
units: "frames / s" },
|
||||
overviewFps5Alpha:
|
||||
{ description: "Frames rate when going to the overview, 5 alpha-transparent windows open",
|
||||
units: "frames / s" },
|
||||
overviewFps10Alpha:
|
||||
{ description: "Frames rate when going to the overview, 10 alpha-transparent windows open",
|
||||
units: "frames / s" },
|
||||
usedAfterOverview:
|
||||
{ description: "Malloc'ed bytes after the overview is shown once",
|
||||
units: "B" },
|
||||
leakedAfterOverview:
|
||||
{ description: "Additional malloc'ed bytes the second time the overview is shown",
|
||||
units: "B" }
|
||||
units: "B" },
|
||||
applicationsShowTimeFirst:
|
||||
{ description: "Time to switch to applications view, first time",
|
||||
units: "us" },
|
||||
applicationsShowTimeSubsequent:
|
||||
{ description: "Time to switch to applications view, second time",
|
||||
units: "us"}
|
||||
};
|
||||
|
||||
let WINDOW_CONFIGS = [
|
||||
{ width: 640, height: 480, alpha: false, maximized: false, count: 1, metric: 'overviewFpsSubsequent' },
|
||||
{ width: 640, height: 480, alpha: false, maximized: false, count: 5, metric: 'overviewFps5Windows' },
|
||||
{ width: 640, height: 480, alpha: false, maximized: false, count: 10, metric: 'overviewFps10Windows' },
|
||||
{ width: 640, height: 480, alpha: false, maximized: true, count: 5, metric: 'overviewFps5Maximized' },
|
||||
{ width: 640, height: 480, alpha: false, maximized: true, count: 10, metric: 'overviewFps10Maximized' },
|
||||
{ width: 640, height: 480, alpha: true, maximized: false, count: 5, metric: 'overviewFps5Alpha' },
|
||||
{ width: 640, height: 480, alpha: true, maximized: false, count: 10, metric: 'overviewFps10Alpha' }
|
||||
];
|
||||
|
||||
function run() {
|
||||
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
|
||||
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
|
||||
Scripting.defineScriptEvent("afterShowHide", "After a show/hide cycle for the overview");
|
||||
Scripting.defineScriptEvent("applicationsShowStart", "Starting to switch to applications view");
|
||||
Scripting.defineScriptEvent("applicationsShowDone", "Done switching to applications view");
|
||||
|
||||
Main.overview.connect('shown', function() {
|
||||
Scripting.scriptEvent('overviewShowDone');
|
||||
});
|
||||
|
||||
yield Scripting.sleep(1000);
|
||||
yield Scripting.waitLeisure();
|
||||
for (let i = 0; i < 2; i++) {
|
||||
|
||||
for (let i = 0; i < 2 * WINDOW_CONFIGS.length; i++) {
|
||||
// We go to the overview twice for each configuration; the first time
|
||||
// to calculate the mipmaps for the windows, the second time to get
|
||||
// a clean set of numbers.
|
||||
if ((i % 2) == 0) {
|
||||
let config = WINDOW_CONFIGS[i / 2];
|
||||
yield Scripting.destroyTestWindows();
|
||||
|
||||
for (let k = 0; k < config.count; k++)
|
||||
yield Scripting.createTestWindow(config.width, config.height, config.alpha, config.maximized);
|
||||
|
||||
yield Scripting.waitTestWindows();
|
||||
yield Scripting.sleep(1000);
|
||||
yield Scripting.waitLeisure();
|
||||
}
|
||||
|
||||
Scripting.scriptEvent('overviewShowStart');
|
||||
Main.overview.show();
|
||||
|
||||
@@ -53,6 +104,21 @@ function run() {
|
||||
Scripting.collectStatistics();
|
||||
Scripting.scriptEvent('afterShowHide');
|
||||
}
|
||||
|
||||
yield Scripting.destroyTestWindows();
|
||||
yield Scripting.sleep(1000);
|
||||
|
||||
Main.overview.show();
|
||||
yield Scripting.waitLeisure();
|
||||
|
||||
for (let i = 0; i < 2; i++) {
|
||||
Scripting.scriptEvent('applicationsShowStart');
|
||||
Main.overview.viewSelector.switchTab('applications');
|
||||
yield Scripting.waitLeisure();
|
||||
Scripting.scriptEvent('applicationsShowDone');
|
||||
Main.overview.viewSelector.switchTab('windows');
|
||||
yield Scripting.waitLeisure();
|
||||
}
|
||||
}
|
||||
|
||||
let showingOverview = false;
|
||||
@@ -64,6 +130,8 @@ let mallocUsedSize = 0;
|
||||
let overviewShowCount = 0;
|
||||
let firstOverviewUsedSize;
|
||||
let haveSwapComplete = false;
|
||||
let applicationsShowStart;
|
||||
let applicationsShowCount = 0;
|
||||
|
||||
function script_overviewShowStart(time) {
|
||||
showingOverview = true;
|
||||
@@ -79,6 +147,18 @@ function script_overviewShowDone(time) {
|
||||
finishedShowingOverview = true;
|
||||
}
|
||||
|
||||
function script_applicationsShowStart(time) {
|
||||
applicationsShowStart = time;
|
||||
}
|
||||
|
||||
function script_applicationsShowDone(time) {
|
||||
applicationsShowCount++;
|
||||
if (applicationsShowCount == 1)
|
||||
METRICS.applicationsShowTimeFirst.value = time - applicationsShowStart;
|
||||
else
|
||||
METRICS.applicationsShowTimeSubsequent.value = time - applicationsShowStart;
|
||||
}
|
||||
|
||||
function script_afterShowHide(time) {
|
||||
if (overviewShowCount == 1) {
|
||||
METRICS.usedAfterOverview.value = mallocUsedSize;
|
||||
@@ -113,9 +193,15 @@ function _frameDone(time) {
|
||||
if (overviewShowCount == 1) {
|
||||
METRICS.overviewLatencyFirst.value = overviewLatency;
|
||||
METRICS.overviewFpsFirst.value = fps;
|
||||
} else {
|
||||
} else if (overviewShowCount == 2) {
|
||||
METRICS.overviewLatencySubsequent.value = overviewLatency;
|
||||
METRICS.overviewFpsSubsequent.value = fps;
|
||||
}
|
||||
|
||||
// Other than overviewFpsFirst, we collect FPS metrics the second
|
||||
// we show each window configuration. overviewShowCount is 1,2,3...
|
||||
if (overviewShowCount % 2 == 0) {
|
||||
let config = WINDOW_CONFIGS[(overviewShowCount / 2) - 1];
|
||||
METRICS[config.metric].value = fps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ AltTabPopup.prototype = {
|
||||
let [childMinHeight, childNaturalHeight] = this._appSwitcher.actor.get_preferred_height(primary.width - hPadding);
|
||||
let [childMinWidth, childNaturalWidth] = this._appSwitcher.actor.get_preferred_width(childNaturalHeight);
|
||||
childBox.x1 = Math.max(primary.x + leftPadding, primary.x + Math.floor((primary.width - childNaturalWidth) / 2));
|
||||
childBox.x2 = Math.min(primary.width - hPadding, childBox.x1 + childNaturalWidth);
|
||||
childBox.x2 = Math.min(primary.x + primary.width - rightPadding, childBox.x1 + childNaturalWidth);
|
||||
childBox.y1 = primary.y + Math.floor((primary.height - childNaturalHeight) / 2);
|
||||
childBox.y2 = childBox.y1 + childNaturalHeight;
|
||||
this._appSwitcher.actor.allocate(childBox, flags);
|
||||
@@ -145,6 +145,12 @@ AltTabPopup.prototype = {
|
||||
|
||||
this._appIcons = this._appSwitcher.icons;
|
||||
|
||||
// Need to force an allocation so we can figure out whether we
|
||||
// need to scroll when selecting
|
||||
this.actor.opacity = 0;
|
||||
this.actor.show();
|
||||
this.actor.get_allocation_box();
|
||||
|
||||
// Make the initial selection
|
||||
if (switch_group) {
|
||||
if (backward) {
|
||||
@@ -156,29 +162,11 @@ AltTabPopup.prototype = {
|
||||
this._select(0, 0);
|
||||
}
|
||||
} else if (this._appIcons.length == 1) {
|
||||
if (!backward && this._appIcons[0].cachedWindows.length > 1) {
|
||||
// For compatibility with the multi-app case below
|
||||
this._select(0, 1, true);
|
||||
} else
|
||||
this._select(0);
|
||||
this._select(0);
|
||||
} else if (backward) {
|
||||
this._select(this._appIcons.length - 1);
|
||||
} else {
|
||||
let firstWindows = this._appIcons[0].cachedWindows;
|
||||
if (firstWindows.length > 1) {
|
||||
let curAppNextWindow = firstWindows[1];
|
||||
let nextAppWindow = this._appIcons[1].cachedWindows[0];
|
||||
|
||||
// If the next window of the current app is more-recently-used
|
||||
// than the first window of the next app, then select it.
|
||||
if (curAppNextWindow.get_workspace() == global.screen.get_active_workspace() &&
|
||||
curAppNextWindow.get_user_time() > nextAppWindow.get_user_time())
|
||||
this._select(0, 1, true);
|
||||
else
|
||||
this._select(1);
|
||||
} else {
|
||||
this._select(1);
|
||||
}
|
||||
this._select(1);
|
||||
}
|
||||
|
||||
// There's a race condition; if the user released Alt before
|
||||
@@ -192,8 +180,6 @@ AltTabPopup.prototype = {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.actor.opacity = 0;
|
||||
this.actor.show();
|
||||
Tweener.addTween(this.actor,
|
||||
{ opacity: 255,
|
||||
time: POPUP_FADE_TIME,
|
||||
@@ -376,7 +362,15 @@ AltTabPopup.prototype = {
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
_popModal: function() {
|
||||
if (this._haveModal) {
|
||||
Main.popModal(this.actor);
|
||||
this._haveModal = false;
|
||||
}
|
||||
},
|
||||
|
||||
destroy : function() {
|
||||
this._popModal();
|
||||
if (this.actor.visible) {
|
||||
Tweener.addTween(this.actor,
|
||||
{ opacity: 0,
|
||||
@@ -392,8 +386,7 @@ AltTabPopup.prototype = {
|
||||
},
|
||||
|
||||
_onDestroy : function() {
|
||||
if (this._haveModal)
|
||||
Main.popModal(this.actor);
|
||||
this._popModal();
|
||||
|
||||
if (this._thumbnails)
|
||||
this._destroyThumbnails();
|
||||
@@ -594,7 +587,7 @@ SwitcherList.prototype = {
|
||||
this._rightArrow.opacity = this._rightGradient.opacity;
|
||||
},
|
||||
|
||||
addItem : function(item) {
|
||||
addItem : function(item, label) {
|
||||
let bbox = new St.Button({ style_class: 'item-box',
|
||||
reactive: true });
|
||||
|
||||
@@ -605,6 +598,8 @@ SwitcherList.prototype = {
|
||||
bbox.connect('clicked', Lang.bind(this, function() { this._onItemClicked(n); }));
|
||||
bbox.connect('enter-event', Lang.bind(this, function() { this._onItemEnter(n); }));
|
||||
|
||||
bbox.label_actor = label;
|
||||
|
||||
this._items.push(bbox);
|
||||
},
|
||||
|
||||
@@ -990,7 +985,7 @@ AppSwitcher.prototype = {
|
||||
|
||||
_addIcon : function(appIcon) {
|
||||
this.icons.push(appIcon);
|
||||
this.addItem(appIcon.actor);
|
||||
this.addItem(appIcon.actor, appIcon.label);
|
||||
|
||||
let n = this._arrows.length;
|
||||
let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' });
|
||||
@@ -1060,9 +1055,12 @@ ThumbnailList.prototype = {
|
||||
this._labels.push(bin);
|
||||
bin.add_actor(name);
|
||||
box.add_actor(bin);
|
||||
|
||||
this.addItem(box, name);
|
||||
} else {
|
||||
this.addItem(box, null);
|
||||
}
|
||||
|
||||
this.addItem(box);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -6,10 +6,9 @@ const Gtk = imports.gi.Gtk;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
const Meta = imports.gi.Meta;
|
||||
const St = imports.gi.St;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const AppFavorites = imports.ui.appFavorites;
|
||||
const DND = imports.ui.dnd;
|
||||
@@ -22,6 +21,7 @@ const Tweener = imports.ui.tweener;
|
||||
const Workspace = imports.ui.workspace;
|
||||
const Params = imports.misc.params;
|
||||
|
||||
const MAX_APPLICATION_WORK_MILLIS = 75;
|
||||
const MENU_POPUP_TIMEOUT = 600;
|
||||
const SCROLL_TIME = 0.1;
|
||||
|
||||
@@ -34,6 +34,8 @@ AlphabeticalView.prototype = {
|
||||
this._grid = new IconGrid.IconGrid({ xAlign: St.Align.START });
|
||||
this._appSystem = Shell.AppSystem.get_default();
|
||||
|
||||
this._pendingAppLaterId = 0;
|
||||
this._apps = [];
|
||||
this._filterApp = null;
|
||||
|
||||
let box = new St.BoxLayout({ vertical: true });
|
||||
@@ -86,10 +88,14 @@ AlphabeticalView.prototype = {
|
||||
if (vfade)
|
||||
offset = vfade.fade_offset;
|
||||
|
||||
if (icon.y < value + offset)
|
||||
value = Math.max(0, icon.y - offset);
|
||||
else if (icon.y + icon.height > value + pageSize - offset)
|
||||
value = Math.min(upper, icon.y + icon.height + offset - pageSize);
|
||||
// If this gets called as part of a right-click, the actor
|
||||
// will be needs_allocation, and so "icon.y" would return 0
|
||||
let box = icon.get_allocation_box();
|
||||
|
||||
if (box.y1 < value + offset)
|
||||
value = Math.max(0, box.y1 - offset);
|
||||
else if (box.y2 > value + pageSize - offset)
|
||||
value = Math.min(upper, box.y2 + offset - pageSize);
|
||||
else
|
||||
return;
|
||||
|
||||
@@ -105,6 +111,30 @@ AlphabeticalView.prototype = {
|
||||
this._apps[i].actor.visible = filter(this._apps[i]._appInfo);
|
||||
},
|
||||
|
||||
// Create actors for the applications in an idle to avoid blocking
|
||||
// for too long; see bug 647778
|
||||
_addPendingApps: function() {
|
||||
let i;
|
||||
let startTimeMillis = new Date().getTime();
|
||||
for (i = 0; i < this._pendingAppIds.length; i++) {
|
||||
let id = this._pendingAppIds[i];
|
||||
this._addApp(this._pendingApps[id]);
|
||||
|
||||
let currentTimeMillis = new Date().getTime();
|
||||
if (currentTimeMillis - startTimeMillis > MAX_APPLICATION_WORK_MILLIS)
|
||||
break;
|
||||
}
|
||||
this._pendingAppIds.splice(0, i + 1);
|
||||
if (this._pendingAppIds.length > 0) {
|
||||
return true;
|
||||
} else {
|
||||
this._pendingAppLaterId = 0;
|
||||
this._pendingAppIds = null;
|
||||
this._pendingApps = null;
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function(apps) {
|
||||
let ids = [];
|
||||
for (let i in apps)
|
||||
@@ -115,9 +145,12 @@ AlphabeticalView.prototype = {
|
||||
|
||||
this._removeAll();
|
||||
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
this._addApp(apps[ids[i]]);
|
||||
}
|
||||
this._pendingAppIds = ids;
|
||||
this._pendingApps = apps;
|
||||
if (this._pendingAppLaterId)
|
||||
Meta.later_remove(this._pendingAppLaterId);
|
||||
this._pendingAppLaterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
|
||||
Lang.bind(this, this._addPendingApps));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -220,7 +253,6 @@ ViewByCategories.prototype = {
|
||||
|
||||
let sections = this._appSystem.get_sections();
|
||||
this._apps = apps;
|
||||
this._view.refresh(apps);
|
||||
|
||||
/* Translators: Filter to display all applications */
|
||||
this._addFilter(_("All"), -1);
|
||||
@@ -232,6 +264,7 @@ ViewByCategories.prototype = {
|
||||
this._addFilter(sections[i], i);
|
||||
|
||||
this._selectCategory(-1);
|
||||
this._view.refresh(apps);
|
||||
|
||||
if (this._focusDummy) {
|
||||
let focused = this._focusDummy.has_key_focus();
|
||||
@@ -309,7 +342,7 @@ BaseAppSearchProvider.prototype = {
|
||||
timestamp: null });
|
||||
|
||||
let app = this._appSys.get_app(id);
|
||||
app.open_new_window(params.workspace ? params.workspace.get_index() : -1);
|
||||
app.open_new_window(params.workspace ? params.workspace.index() : -1);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -399,6 +432,8 @@ AppWellIcon.prototype = {
|
||||
this.icon = new AppIcon(app, iconParams);
|
||||
this.actor.set_child(this.icon.actor);
|
||||
|
||||
this.actor.label_actor = this.icon.label;
|
||||
|
||||
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
||||
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
|
||||
this.actor.connect('popup-menu', Lang.bind(this, this._onKeyboardPopupMenu));
|
||||
@@ -412,6 +447,10 @@ AppWellIcon.prototype = {
|
||||
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);
|
||||
@@ -505,6 +544,8 @@ AppWellIcon.prototype = {
|
||||
this._menuManager.addMenu(this._menu);
|
||||
}
|
||||
|
||||
this.actor.set_hover(true);
|
||||
this.actor.show_tooltip();
|
||||
this._menu.popup();
|
||||
|
||||
return false;
|
||||
@@ -568,6 +609,9 @@ AppIconMenu.prototype = {
|
||||
|
||||
PopupMenu.PopupMenu.prototype._init.call(this, source.actor, 0.5, side, 0);
|
||||
|
||||
// We want to keep the item hovered while the menu is up
|
||||
this.blockSourceEvents = true;
|
||||
|
||||
this._source = source;
|
||||
|
||||
this.connect('activate', Lang.bind(this, this._onActivate));
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
const Shell = imports.gi.Shell;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
@@ -40,80 +41,80 @@ BoxPointer.prototype = {
|
||||
this._border.connect('repaint', Lang.bind(this, this._drawBorder));
|
||||
this._container.add_actor(this._border);
|
||||
this.bin.raise(this._border);
|
||||
this._xOffset = 0;
|
||||
this._yOffset = 0;
|
||||
this._xPosition = 0;
|
||||
this._yPosition = 0;
|
||||
},
|
||||
|
||||
show: function(animate, onComplete) {
|
||||
let x = this.actor.x;
|
||||
let y = this.actor.y;
|
||||
let themeNode = this.actor.get_theme_node();
|
||||
let rise = themeNode.get_length('-arrow-rise');
|
||||
|
||||
this.actor.opacity = 0;
|
||||
this.opacity = 0;
|
||||
this.actor.show();
|
||||
|
||||
if (animate) {
|
||||
switch (this._arrowSide) {
|
||||
case St.Side.TOP:
|
||||
this.actor.y -= rise;
|
||||
this.yOffset = -rise;
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
this.actor.y += rise;
|
||||
this.yOffset = rise;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
this.actor.x -= rise;
|
||||
this.xOffset = -rise;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
this.actor.x += rise;
|
||||
this.xOffset = rise;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Tweener.addTween(this.actor, { opacity: 255,
|
||||
x: x,
|
||||
y: y,
|
||||
transition: "linear",
|
||||
onComplete: onComplete,
|
||||
time: POPUP_ANIMATION_TIME });
|
||||
Tweener.addTween(this, { opacity: 255,
|
||||
xOffset: 0,
|
||||
yOffset: 0,
|
||||
transition: "linear",
|
||||
onComplete: onComplete,
|
||||
time: POPUP_ANIMATION_TIME });
|
||||
},
|
||||
|
||||
hide: function(animate, onComplete) {
|
||||
let x = this.actor.x;
|
||||
let y = this.actor.y;
|
||||
let originalX = this.actor.x;
|
||||
let originalY = this.actor.y;
|
||||
let xOffset = 0;
|
||||
let yOffset = 0;
|
||||
let themeNode = this.actor.get_theme_node();
|
||||
let rise = themeNode.get_length('-arrow-rise');
|
||||
|
||||
if (animate) {
|
||||
switch (this._arrowSide) {
|
||||
case St.Side.TOP:
|
||||
y += rise;
|
||||
yOffset = rise;
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
y -= rise;
|
||||
yOffset = -rise;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
x += rise;
|
||||
xOffset = rise;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
x -= rise;
|
||||
xOffset = -rise;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Tweener.addTween(this.actor, { opacity: 0,
|
||||
x: x,
|
||||
y: y,
|
||||
transition: "linear",
|
||||
time: POPUP_ANIMATION_TIME,
|
||||
onComplete: Lang.bind(this, function () {
|
||||
this.actor.hide();
|
||||
this.actor.x = originalX;
|
||||
this.actor.y = originalY;
|
||||
if (onComplete)
|
||||
onComplete();
|
||||
})
|
||||
});
|
||||
Tweener.addTween(this, { opacity: 0,
|
||||
xOffset: xOffset,
|
||||
yOffset: yOffset,
|
||||
transition: "linear",
|
||||
time: POPUP_ANIMATION_TIME,
|
||||
onComplete: Lang.bind(this, function () {
|
||||
this.actor.hide();
|
||||
this.xOffset = 0;
|
||||
this.yOffset = 0;
|
||||
if (onComplete)
|
||||
onComplete();
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
_adjustAllocationForArrow: function(isWidth, alloc) {
|
||||
@@ -176,6 +177,9 @@ BoxPointer.prototype = {
|
||||
break;
|
||||
}
|
||||
this.bin.allocate(childBox, flags);
|
||||
|
||||
if (this._sourceActor && this._sourceActor.mapped)
|
||||
this._reposition(this._sourceActor, this._gap, this._alignment);
|
||||
},
|
||||
|
||||
_drawBorder: function(area) {
|
||||
@@ -306,13 +310,20 @@ BoxPointer.prototype = {
|
||||
// so that we can query the correct size.
|
||||
this.actor.show();
|
||||
|
||||
this._sourceActor = sourceActor;
|
||||
this._gap = gap;
|
||||
this._alignment = alignment;
|
||||
|
||||
this._reposition(sourceActor, gap, alignment);
|
||||
},
|
||||
|
||||
_reposition: function(sourceActor, gap, alignment) {
|
||||
// Position correctly relative to the sourceActor
|
||||
let sourceNode = sourceActor.get_theme_node();
|
||||
let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box());
|
||||
let [sourceX, sourceY] = sourceActor.get_transformed_position();
|
||||
let [sourceWidth, sourceHeight] = sourceActor.get_transformed_size();
|
||||
let sourceCenterX = sourceX + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) / 2;
|
||||
let sourceCenterY = sourceY + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) / 2;
|
||||
let sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
|
||||
let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) / 2;
|
||||
let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) / 2;
|
||||
let [minWidth, minHeight, natWidth, natHeight] = this.actor.get_preferred_size();
|
||||
|
||||
// We also want to keep it onscreen, and separated from the
|
||||
@@ -330,16 +341,16 @@ BoxPointer.prototype = {
|
||||
|
||||
switch (this._arrowSide) {
|
||||
case St.Side.TOP:
|
||||
resY = sourceY + sourceHeight + gap;
|
||||
resY = sourceAllocation.y2 + gap;
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
resY = sourceY - natHeight - gap;
|
||||
resY = sourceAllocation.y1 - natHeight - gap;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
resX = sourceX + sourceWidth + gap;
|
||||
resX = sourceAllocation.x2 + gap;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
resX = sourceX - natWidth - gap;
|
||||
resX = sourceAllocation.x1 - natWidth - gap;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -373,9 +384,9 @@ BoxPointer.prototype = {
|
||||
parent = parent.get_parent();
|
||||
}
|
||||
|
||||
// Actually set the position
|
||||
this.actor.x = Math.floor(x);
|
||||
this.actor.y = Math.floor(y);
|
||||
this._xPosition = Math.floor(x);
|
||||
this._yPosition = Math.floor(y);
|
||||
this._shiftActor();
|
||||
},
|
||||
|
||||
// @origin: Coordinate specifying middle of the arrow, along
|
||||
@@ -386,5 +397,42 @@ BoxPointer.prototype = {
|
||||
this._arrowOrigin = origin;
|
||||
this._border.queue_repaint();
|
||||
}
|
||||
},
|
||||
|
||||
_shiftActor : function() {
|
||||
// Since the position of the BoxPointer depends on the allocated size
|
||||
// of the BoxPointer and the position of the source actor, trying
|
||||
// to position the BoxPoiner via the x/y properties will result in
|
||||
// allocation loops and warnings. Instead we do the positioning via
|
||||
// the anchor point, which is independent of allocation, and leave
|
||||
// x == y == 0.
|
||||
this.actor.set_anchor_point(-(this._xPosition + this._xOffset),
|
||||
-(this._yPosition + this._yOffset));
|
||||
},
|
||||
|
||||
set xOffset(offset) {
|
||||
this._xOffset = offset;
|
||||
this._shiftActor();
|
||||
},
|
||||
|
||||
get xOffset() {
|
||||
return this._xOffset;
|
||||
},
|
||||
|
||||
set yOffset(offset) {
|
||||
this._yOffset = offset;
|
||||
this._shiftActor();
|
||||
},
|
||||
|
||||
get yOffset() {
|
||||
return this._yOffset;
|
||||
},
|
||||
|
||||
set opacity(opacity) {
|
||||
this.actor.opacity = opacity;
|
||||
},
|
||||
|
||||
get opacity() {
|
||||
return this.actor.opacity;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -8,9 +8,6 @@ const St = imports.gi.St;
|
||||
const Signals = imports.signals;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Gettext_gtk30 = imports.gettext.domain('gtk30');
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
const C_ = Gettext.pgettext;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
|
||||
@@ -36,8 +36,8 @@ Chrome.prototype = {
|
||||
|
||||
this._trackedActors = [];
|
||||
|
||||
global.gdk_screen.connect('monitors-changed',
|
||||
Lang.bind(this, this._monitorsChanged));
|
||||
global.screen.connect('monitors-changed',
|
||||
Lang.bind(this, this._monitorsChanged));
|
||||
global.screen.connect('restacked',
|
||||
Lang.bind(this, this._windowsRestacked));
|
||||
|
||||
@@ -335,6 +335,11 @@ Chrome.prototype = {
|
||||
this._updateVisibility();
|
||||
this._queueUpdateRegions();
|
||||
}
|
||||
|
||||
// Figure out where the pointer is in case we lost track of
|
||||
// it during a grab. (In particular, if a trayicon popup menu
|
||||
// is dismissed, see if we need to close the message tray.)
|
||||
global.sync_pointer();
|
||||
},
|
||||
|
||||
_updateRegions: function() {
|
||||
|
||||
@@ -281,6 +281,7 @@ CtrlAltTabPopup.prototype = {
|
||||
},
|
||||
|
||||
_onDestroy : function() {
|
||||
this._popModal();
|
||||
if (this._keyPressEventId)
|
||||
this.actor.disconnect(this._keyPressEventId);
|
||||
if (this._keyReleaseEventId)
|
||||
@@ -322,6 +323,6 @@ CtrlAltTabSwitcher.prototype = {
|
||||
let text = new St.Label({ text: item.name });
|
||||
box.add(text, { x_fill: false });
|
||||
|
||||
this.addItem(box);
|
||||
this.addItem(box, text);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,8 +6,6 @@ const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const AppDisplay = imports.ui.appDisplay;
|
||||
const AppFavorites = imports.ui.appFavorites;
|
||||
@@ -283,20 +281,37 @@ Dash.prototype = {
|
||||
Lang.bind(this, this._onDragBegin));
|
||||
Main.overview.connect('item-drag-end',
|
||||
Lang.bind(this, this._onDragEnd));
|
||||
Main.overview.connect('item-drag-cancelled',
|
||||
Lang.bind(this, this._onDragCancelled));
|
||||
Main.overview.connect('window-drag-begin',
|
||||
Lang.bind(this, this._onDragBegin));
|
||||
Main.overview.connect('window-drag-cancelled',
|
||||
Lang.bind(this, this._onDragCancelled));
|
||||
Main.overview.connect('window-drag-end',
|
||||
Lang.bind(this, this._onDragEnd));
|
||||
},
|
||||
|
||||
_onDragBegin: function() {
|
||||
this._dragCancelled = false;
|
||||
this._dragMonitor = {
|
||||
dragMotion: Lang.bind(this, this._onDragMotion)
|
||||
};
|
||||
DND.addDragMonitor(this._dragMonitor);
|
||||
},
|
||||
|
||||
_onDragCancelled: function() {
|
||||
this._dragCancelled = true;
|
||||
this._endDrag();
|
||||
},
|
||||
|
||||
_onDragEnd: function() {
|
||||
if (this._dragCancelled)
|
||||
return;
|
||||
|
||||
this._endDrag();
|
||||
},
|
||||
|
||||
_endDrag: function() {
|
||||
this._clearDragPlaceholder();
|
||||
if (this._favRemoveTarget) {
|
||||
this._favRemoveTarget.actor.hide();
|
||||
@@ -372,6 +387,8 @@ Dash.prototype = {
|
||||
Lang.bind(this, function() {
|
||||
display.actor.opacity = 255;
|
||||
}));
|
||||
display.actor.set_tooltip_text(app.get_name());
|
||||
|
||||
let item = new DashItemContainer();
|
||||
item.setChild(display.actor);
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@ const Cairo = imports.cairo;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Util = imports.misc.util;
|
||||
const Main = imports.ui.main;
|
||||
@@ -185,21 +183,6 @@ DateMenuButton.prototype = {
|
||||
}
|
||||
|
||||
let displayDate = new Date();
|
||||
let msecRemaining;
|
||||
if (showSeconds) {
|
||||
msecRemaining = 1000 - displayDate.getMilliseconds();
|
||||
if (msecRemaining < 50) {
|
||||
displayDate.setSeconds(displayDate.getSeconds() + 1);
|
||||
msecRemaining += 1000;
|
||||
}
|
||||
} else {
|
||||
msecRemaining = 60000 - (1000 * displayDate.getSeconds() +
|
||||
displayDate.getMilliseconds());
|
||||
if (msecRemaining < 500) {
|
||||
displayDate.setMinutes(displayDate.getMinutes() + 1);
|
||||
msecRemaining += 60000;
|
||||
}
|
||||
}
|
||||
|
||||
this._clock.set_text(displayDate.toLocaleFormat(clockFormat));
|
||||
|
||||
@@ -209,19 +192,19 @@ DateMenuButton.prototype = {
|
||||
dateFormat = _("%A %B %e, %Y");
|
||||
this._date.set_text(displayDate.toLocaleFormat(dateFormat));
|
||||
|
||||
Mainloop.timeout_add(msecRemaining, Lang.bind(this, this._updateClockAndDate));
|
||||
Mainloop.timeout_add_seconds(1, Lang.bind(this, this._updateClockAndDate));
|
||||
return false;
|
||||
},
|
||||
|
||||
_onPreferencesActivate: function() {
|
||||
this.menu.close();
|
||||
Util.spawnDesktop('gnome-datetime-panel');
|
||||
let app = Shell.AppSystem.get_default().get_app('gnome-datetime-panel.desktop');
|
||||
app.activate(-1);
|
||||
},
|
||||
|
||||
_onOpenCalendarActivate: function() {
|
||||
this.menu.close();
|
||||
// TODO: pass '-c calendar' (to force the calendar at startup)
|
||||
// TODO: pass the selected day
|
||||
Util.spawnDesktop('evolution');
|
||||
},
|
||||
Util.spawn(['evolution', '-c', 'calendar']);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -480,7 +480,9 @@ _Draggable.prototype = {
|
||||
let [parentX, parentY] = this._dragOrigParent.get_transformed_position();
|
||||
let [parentWidth, parentHeight] = this._dragOrigParent.get_size();
|
||||
let [parentScaledWidth, parentScaledHeight] = this._dragOrigParent.get_transformed_size();
|
||||
let parentScale = parentScaledWidth / parentWidth;
|
||||
let parentScale = 1.0;
|
||||
if (parentWidth != 0)
|
||||
parentScale = parentScaledWidth / parentWidth;
|
||||
|
||||
x = parentX + parentScale * this._dragOrigX;
|
||||
y = parentY + parentScale * this._dragOrigY;
|
||||
@@ -496,6 +498,7 @@ _Draggable.prototype = {
|
||||
},
|
||||
|
||||
_cancelDrag: function(eventTime) {
|
||||
this.emit('drag-cancelled', eventTime);
|
||||
this._dragInProgress = false;
|
||||
let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
|
||||
|
||||
@@ -504,6 +507,9 @@ _Draggable.prototype = {
|
||||
if (!this._buttonDown)
|
||||
this._dragComplete();
|
||||
this.emit('drag-end', eventTime, false);
|
||||
if (!this._dragOrigParent)
|
||||
this._dragActor.destroy();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const DocInfo = imports.misc.docInfo;
|
||||
const Params = imports.misc.params;
|
||||
const Search = imports.ui.search;
|
||||
|
||||
@@ -22,9 +22,6 @@ const DBus = imports.dbus;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gdm = imports.gi.Gdm;
|
||||
const GLib = imports.gi.GLib;
|
||||
@@ -66,16 +63,20 @@ const logoutDialogContent = {
|
||||
uninhibitedDescriptionWithUser: _("%s will be logged out automatically in %d seconds."),
|
||||
uninhibitedDescription: _("You will be logged out automatically in %d seconds."),
|
||||
endDescription: _("Logging out of the system."),
|
||||
confirmButtonText: _("Log Out"),
|
||||
confirmButtons: [{ signal: 'ConfirmedLogout',
|
||||
label: _("Log Out") }],
|
||||
iconStyleClass: 'end-session-dialog-logout-icon'
|
||||
};
|
||||
|
||||
const shutdownDialogContent = {
|
||||
subject: _("Shut Down"),
|
||||
inhibitedDescription: _("Click Shut Down to quit these applications and shut down the system."),
|
||||
uninhibitedDescription: _("The system will shut down automatically in %d seconds."),
|
||||
endDescription: _("Shutting down the system."),
|
||||
confirmButtonText: _("Shut Down"),
|
||||
subject: _("Power Off"),
|
||||
inhibitedDescription: _("Click Power Off to quit these applications and power off the system."),
|
||||
uninhibitedDescription: _("The system will power off automatically in %d seconds."),
|
||||
endDescription: _("Powering off the system."),
|
||||
confirmButtons: [{ signal: 'ConfirmedReboot',
|
||||
label: _("Restart") },
|
||||
{ signal: 'ConfirmedShutdown',
|
||||
label: _("Power Off") }],
|
||||
iconName: 'system-shutdown',
|
||||
iconStyleClass: 'end-session-dialog-shutdown-icon'
|
||||
};
|
||||
@@ -85,7 +86,8 @@ const restartDialogContent = {
|
||||
inhibitedDescription: _("Click Restart to quit these applications and restart the system."),
|
||||
uninhibitedDescription: _("The system will restart automatically in %d seconds."),
|
||||
endDescription: _("Restarting the system."),
|
||||
confirmButtonText: _("Restart"),
|
||||
confirmButtons: [{ signal: 'ConfirmedReboot',
|
||||
label: _("Restart") }],
|
||||
iconName: 'system-shutdown',
|
||||
iconStyleClass: 'end-session-dialog-shutdown-icon'
|
||||
};
|
||||
@@ -233,7 +235,7 @@ EndSessionDialog.prototype = {
|
||||
__proto__: ModalDialog.ModalDialog.prototype,
|
||||
|
||||
_init: function() {
|
||||
ModalDialog.ModalDialog.prototype._init.call(this);
|
||||
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'end-session-dialog' });
|
||||
|
||||
this._user = Gdm.UserManager.ref_default().get_user(GLib.get_user_name());
|
||||
|
||||
@@ -288,12 +290,26 @@ EndSessionDialog.prototype = {
|
||||
this.contentLayout.add(scrollView,
|
||||
{ x_fill: true,
|
||||
y_fill: true });
|
||||
scrollView.hide();
|
||||
|
||||
this._applicationList = new St.BoxLayout({ vertical: true });
|
||||
scrollView.add_actor(this._applicationList,
|
||||
{ x_fill: true,
|
||||
y_fill: true,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.MIDDLE });
|
||||
|
||||
this._applicationList.connect('actor-added',
|
||||
Lang.bind(this, function() {
|
||||
if (this._applicationList.get_children().length == 1)
|
||||
scrollView.show();
|
||||
}));
|
||||
|
||||
this._applicationList.connect('actor-removed',
|
||||
Lang.bind(this, function() {
|
||||
if (this._applicationList.get_children().length == 0)
|
||||
scrollView.hide();
|
||||
}));
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
@@ -347,8 +363,10 @@ EndSessionDialog.prototype = {
|
||||
|
||||
if (this._user.is_loaded && !dialogContent.iconName) {
|
||||
let iconFile = this._user.get_icon_file();
|
||||
|
||||
this._setIconFromFile(iconFile, dialogContent.iconStyleClass);
|
||||
if (GLib.file_test(iconFile, GLib.FileTest.EXISTS))
|
||||
this._setIconFromFile(iconFile, dialogContent.iconStyleClass);
|
||||
else
|
||||
this._setIconFromName('avatar-default', dialogContent.iconStyleClass);
|
||||
} else if (dialogContent.iconName) {
|
||||
this._setIconFromName(dialogContent.iconName,
|
||||
dialogContent.iconStyleClass);
|
||||
@@ -387,23 +405,28 @@ EndSessionDialog.prototype = {
|
||||
},
|
||||
|
||||
_updateButtons: function() {
|
||||
if (this.state != ModalDialog.State.OPENING &&
|
||||
this.state != ModalDialog.State.OPENED)
|
||||
return;
|
||||
|
||||
let dialogContent = DialogContent[this._type];
|
||||
let confirmButtonText = _("Confirm");
|
||||
let buttons = [{ action: Lang.bind(this, this.cancel),
|
||||
label: _("Cancel"),
|
||||
key: Clutter.Escape }];
|
||||
|
||||
if (dialogContent.confirmButtonText)
|
||||
confirmButtonText = dialogContent.confirmButtonText;
|
||||
for (let i = 0; i < dialogContent.confirmButtons.length; i++) {
|
||||
let signal = dialogContent.confirmButtons[i].signal;
|
||||
let label = dialogContent.confirmButtons[i].label;
|
||||
buttons.push({ action: Lang.bind(this, function() {
|
||||
this._confirm(signal);
|
||||
}),
|
||||
label: label });
|
||||
}
|
||||
|
||||
this.setButtons([{ label: _("Cancel"),
|
||||
action: Lang.bind(this, this.cancel),
|
||||
key: Clutter.Escape
|
||||
},
|
||||
{ label: confirmButtonText,
|
||||
action: Lang.bind(this, this._confirm)
|
||||
}]);
|
||||
this.setButtons(buttons);
|
||||
},
|
||||
|
||||
close: function() {
|
||||
ModalDialog.ModalDialog.prototype.close.call(this);
|
||||
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
|
||||
'org.gnome.SessionManager.EndSessionDialog',
|
||||
'Closed', '', []);
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
@@ -414,12 +437,12 @@ EndSessionDialog.prototype = {
|
||||
this.close(global.get_current_time());
|
||||
},
|
||||
|
||||
_confirm: function() {
|
||||
_confirm: function(signal) {
|
||||
this._fadeOutDialog();
|
||||
this._stopTimer();
|
||||
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
|
||||
'org.gnome.SessionManager.EndSessionDialog',
|
||||
'Confirmed', '', []);
|
||||
signal, '', []);
|
||||
},
|
||||
|
||||
_onOpened: function() {
|
||||
@@ -434,7 +457,11 @@ EndSessionDialog.prototype = {
|
||||
time: this._secondsLeft,
|
||||
transition: 'linear',
|
||||
onUpdate: Lang.bind(this, this._updateContent),
|
||||
onComplete: Lang.bind(this, this._confirm),
|
||||
onComplete: Lang.bind(this, function() {
|
||||
let dialogContent = DialogContent[this._type];
|
||||
let button = dialogContent.confirmButtons[dialogContent.confirmButtons.length - 1];
|
||||
this._confirm(button.signal);
|
||||
}),
|
||||
});
|
||||
},
|
||||
|
||||
@@ -487,11 +514,12 @@ EndSessionDialog.prototype = {
|
||||
this._inhibitors.push(inhibitor);
|
||||
}
|
||||
|
||||
this._updateButtons();
|
||||
|
||||
if (!this.open(timestamp))
|
||||
throw new DBus.DBusError('org.gnome.Shell.ModalDialog.GrabError',
|
||||
"Cannot grab pointer and keyboard");
|
||||
|
||||
this._updateButtons();
|
||||
this._updateContent();
|
||||
|
||||
let signalId = this.connect('opened',
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
imports.gi.versions.Clutter = '1.0';
|
||||
imports.gi.versions.Gio = '2.0';
|
||||
imports.gi.versions.Gdk = '3.0';
|
||||
imports.gi.versions.GdkPixbuf = '2.0';
|
||||
imports.gi.versions.Gtk = '3.0';
|
||||
|
||||
const Clutter = imports.gi.Clutter;;
|
||||
const Gettext = imports.gettext;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const Gettext_gtk30 = imports.gettext.domain('gtk30');
|
||||
|
||||
const Tweener = imports.ui.tweener;
|
||||
// We can't import shell JS modules yet, because they may have
|
||||
// variable initializations, etc, that depend on init() already having
|
||||
// been run.
|
||||
|
||||
const Format = imports.misc.format;
|
||||
|
||||
// "monkey patch" in some varargs ClutterContainer methods; we need
|
||||
// to do this per-container class since there is no representation
|
||||
@@ -61,21 +69,20 @@ function _blockMethod(method, replacement, reason) {
|
||||
}
|
||||
|
||||
function init() {
|
||||
Tweener.init();
|
||||
String.prototype.format = Format.format;
|
||||
// Add some bindings to the global JS namespace; (gjs keeps the web
|
||||
// browser convention of having that namespace be called 'window'.)
|
||||
window.global = Shell.Global.get();
|
||||
|
||||
window._ = Gettext.gettext;
|
||||
window.C_ = Gettext.pgettext;
|
||||
window.ngettext = Gettext.ngettext;
|
||||
|
||||
// Set the default direction for St widgets (this needs to be done before any use of St)
|
||||
if (Gettext_gtk30.gettext('default:LTR') == 'default:RTL') {
|
||||
if (Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL) {
|
||||
St.Widget.set_default_direction(St.TextDirection.RTL);
|
||||
}
|
||||
|
||||
let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');
|
||||
if (slowdownEnv) {
|
||||
let factor = parseFloat(slowdownEnv);
|
||||
if (!isNaN(factor) && factor > 0.0)
|
||||
St.set_slow_down_factor(factor);
|
||||
}
|
||||
|
||||
// Miscellaneous monkeypatching
|
||||
_patchContainerClass(St.BoxLayout);
|
||||
_patchContainerClass(St.Table);
|
||||
|
||||
@@ -83,8 +90,14 @@ function init() {
|
||||
return St.describe_actor(this);
|
||||
};
|
||||
|
||||
if (window.global === undefined) // test environment
|
||||
return;
|
||||
let origToString = Object.prototype.toString;
|
||||
Object.prototype.toString = function() {
|
||||
let base = origToString.call(this);
|
||||
if ('actor' in this && this.actor instanceof Clutter.Actor)
|
||||
return base.replace(/\]$/, ' delegate for ' + this.actor.toString().substring(1));
|
||||
else
|
||||
return base;
|
||||
};
|
||||
|
||||
_blockMethod('Clutter.Event.get_state', 'Shell.get_event_state',
|
||||
'gjs\'s handling of Clutter.ModifierType is broken. See bug 597292.');
|
||||
@@ -96,4 +109,23 @@ function init() {
|
||||
// Shell.Global.prototype itself is read-only.
|
||||
global.set_property_mutable('imports.gi.Shell.Global.prototype', 'set_property_mutable', true);
|
||||
Shell.Global.prototype.set_property_mutable = undefined;
|
||||
|
||||
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783
|
||||
Date.prototype.toLocaleFormat = function(format) {
|
||||
return Shell.util_format_date(format, this.getTime());
|
||||
};
|
||||
|
||||
let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');
|
||||
if (slowdownEnv) {
|
||||
let factor = parseFloat(slowdownEnv);
|
||||
if (!isNaN(factor) && factor > 0.0)
|
||||
St.set_slow_down_factor(factor);
|
||||
}
|
||||
|
||||
// OK, now things are initialized enough that we can import shell JS
|
||||
const Format = imports.misc.format;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
Tweener.init();
|
||||
String.prototype.format = Format.format;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
const Config = imports.misc.config;
|
||||
|
||||
@@ -67,7 +68,13 @@ function loadExtension(dir, enabled, type) {
|
||||
return;
|
||||
}
|
||||
|
||||
let [success, metadataContents, len, etag] = metadataFile.load_contents(null);
|
||||
let metadataContents;
|
||||
try {
|
||||
metadataContents = Shell.get_file_contents_utf8_sync(metadataFile.get_path());
|
||||
} catch (e) {
|
||||
global.logError(baseErrorString + 'Failed to load metadata.json: ' + e);
|
||||
return;
|
||||
}
|
||||
let meta;
|
||||
try {
|
||||
meta = JSON.parse(metadataContents);
|
||||
|
||||
500
js/ui/goaClient.js
Normal file
@@ -0,0 +1,500 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Goa = imports.gi.Goa;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
const C_ = Gettext.pgettext;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Pango = imports.gi.Pango;
|
||||
|
||||
const History = imports.misc.history;
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
|
||||
function Client() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
Client.prototype = {
|
||||
_init : function() {
|
||||
this._client = null;
|
||||
|
||||
this._accountIdToMailMonitor = {}
|
||||
this._mailSource = null;
|
||||
|
||||
// TODO: need to call refreshAllMonitors() when network-connectivity changes
|
||||
|
||||
Goa.Client.new(null, /* cancellable */
|
||||
Lang.bind(this, this._onClientConstructed));
|
||||
},
|
||||
|
||||
_onClientConstructed : function(object, asyncRes) {
|
||||
this._client = object.new_finish(asyncRes);
|
||||
this._updateAccounts();
|
||||
this._client.connect('account-added', Lang.bind(this, this._updateAccounts));
|
||||
this._client.connect('account-removed', Lang.bind(this, this._updateAccounts));
|
||||
this._client.connect('account-changed', Lang.bind(this, this._updateAccounts));
|
||||
},
|
||||
|
||||
_updateAccounts : function () {
|
||||
|
||||
let objects = this._client.get_accounts();
|
||||
let mailIds = {};
|
||||
|
||||
// Add monitors for accounts that now exist
|
||||
for (let n = 0; n < objects.length; n++) {
|
||||
let object = objects[n];
|
||||
let id = object.account.id;
|
||||
|
||||
if (object.mail) {
|
||||
mailIds[id] = true;
|
||||
if (!(id in this._accountIdToMailMonitor)) {
|
||||
let monitor = new MailMonitor(this, object);
|
||||
this._accountIdToMailMonitor[id] = monitor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nuke monitors for accounts that are now non-existant
|
||||
let monitorsToRemove = []
|
||||
for (let existingMonitorId in this._accountIdToMailMonitor) {
|
||||
if (!(existingMonitorId in mailIds)) {
|
||||
monitorsToRemove.push(existingMonitorId);
|
||||
}
|
||||
}
|
||||
for (let n = 0; n < monitorsToRemove.length; n++) {
|
||||
let id = monitorsToRemove[n];
|
||||
let monitor = this._accountIdToMailMonitor[id];
|
||||
delete this._accountIdToMailMonitor[id]
|
||||
monitor.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
_ensureMailSource: function() {
|
||||
if (!this._mailSource) {
|
||||
this._mailSource = new MailSource(this);
|
||||
this._mailSource.connect('destroy', Lang.bind(this,
|
||||
function () {
|
||||
this._mailSource = null;
|
||||
}));
|
||||
Main.messageTray.add(this._mailSource);
|
||||
}
|
||||
},
|
||||
|
||||
addPendingMessage: function(message) {
|
||||
this._ensureMailSource();
|
||||
this._mailSource.addMessage(message);
|
||||
},
|
||||
|
||||
refreshAllMonitors: function() {
|
||||
log('Refreshing all mail monitors');
|
||||
for (let id in this._accountIdToMailMonitor) {
|
||||
let monitor = this._accountIdToMailMonitor[id];
|
||||
monitor.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
|
||||
function Message(uid, from, subject, excerpt, uri, can_be_marked_as_spam, can_be_starred) {
|
||||
this._init(uid, from, subject, excerpt, uri, can_be_marked_as_spam, can_be_starred);
|
||||
}
|
||||
|
||||
Message.prototype = {
|
||||
_init: function(uid, from, subject, excerpt, uri, can_be_marked_as_spam, can_be_starred) {
|
||||
this.uid = uid;
|
||||
this.from = from;
|
||||
this.subject = subject;
|
||||
this.excerpt = excerpt;
|
||||
this.uri = uri;
|
||||
this.can_be_marked_as_spam = can_be_marked_as_spam;
|
||||
this.can_be_starred = can_be_starred;
|
||||
this.receivedAt = new Date();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
|
||||
function MailMonitor(client, accountObject) {
|
||||
this._init(client, accountObject);
|
||||
}
|
||||
|
||||
MailMonitor.prototype = {
|
||||
_init : function(client, accountObject) {
|
||||
this._client = client;
|
||||
this._accountObject = accountObject;
|
||||
this._account = this._accountObject.get_account();
|
||||
this._mail = this._accountObject.get_mail();
|
||||
|
||||
// Create the remote monitor object
|
||||
this._proxy = null;
|
||||
this._cancellable = new Gio.Cancellable();
|
||||
this._mail.call_create_monitor(this._cancellable, Lang.bind(this, this._onMonitorCreated));
|
||||
},
|
||||
|
||||
destroy : function() {
|
||||
this._cancellable.cancel();
|
||||
if (this._proxy) {
|
||||
// We don't really care if this fails or not
|
||||
this._proxy.call_close(null, Lang.bind(this, function() { }));
|
||||
this._proxy.disconnect(this._messageReceivedId);
|
||||
this._proxy = null;
|
||||
}
|
||||
},
|
||||
|
||||
refresh : function() {
|
||||
if (this._proxy) {
|
||||
// We don't really care if this fails or not
|
||||
log('Refreshing mail monitor for account ' + this._account.name);
|
||||
this._proxy.call_refresh(null, Lang.bind(this, function() { }));
|
||||
}
|
||||
},
|
||||
|
||||
_onMonitorCreated : function(mail, asyncRes) {
|
||||
// TODO: a (gboolean, object_path) tuple is returned here
|
||||
// See https://bugzilla.gnome.org/show_bug.cgi?id=649657
|
||||
let ret = mail.call_create_monitor_finish(asyncRes);
|
||||
let object_path = ret[1];
|
||||
Goa.MailMonitorProxy.new_for_bus(Gio.BusType.SESSION,
|
||||
Gio.DBusProxyFlags.NONE,
|
||||
'org.gnome.OnlineAccounts',
|
||||
object_path,
|
||||
null, /* cancellable */
|
||||
Lang.bind(this, this._onMonitorProxyConstructed));
|
||||
},
|
||||
|
||||
_onMonitorProxyConstructed : function(monitor, asyncRes) {
|
||||
this._proxy = monitor.new_for_bus_finish(asyncRes);
|
||||
|
||||
// Now listen for changes on the mail monitor proxy
|
||||
this._messageReceivedId = this._proxy.connect('message-received',
|
||||
Lang.bind(this, this._onMessageReceived));
|
||||
},
|
||||
|
||||
_onMessageReceived : function(monitor, uid, from, subject, excerpt, uri, can_be_marked_as_spam, can_be_starred) {
|
||||
let message = new Message(uid, from, subject, excerpt, uri, can_be_marked_as_spam, can_be_starred);
|
||||
if (!Main.messageTray.getBusy()) {
|
||||
let source = new Source(this._client, message);
|
||||
let notification = new Notification(source, this._client, this, message);
|
||||
// If the user is not marked as busy, present the notification to the user
|
||||
Main.messageTray.add(source);
|
||||
source.notify(notification);
|
||||
} else {
|
||||
// ... otherwise, if the user is busy, just add it to the MailSource's list
|
||||
// of pending messages
|
||||
this._client.addPendingMessage(message);
|
||||
}
|
||||
},
|
||||
|
||||
MessageAddStar: function (message) {
|
||||
this._proxy.call_add_star(message.uid,
|
||||
null, /* cancellable */
|
||||
Lang.bind(this,
|
||||
function(object, asyncRes) {
|
||||
this._proxy.call_add_star_finish(asyncRes);
|
||||
}));
|
||||
},
|
||||
|
||||
MessageMarkAsSpam: function (message) {
|
||||
this._proxy.call_mark_as_spam(message.uid,
|
||||
null, /* cancellable */
|
||||
Lang.bind(this,
|
||||
function(object, asyncRes) {
|
||||
this._proxy.call_add_star_finish(asyncRes);
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
|
||||
function Source(client, message) {
|
||||
this._init(client, message);
|
||||
}
|
||||
|
||||
Source.prototype = {
|
||||
__proto__: MessageTray.Source.prototype,
|
||||
|
||||
_init : function(client, message) {
|
||||
this._client = client;
|
||||
this._message = message;
|
||||
|
||||
// Init super class and add ourselves to the message tray
|
||||
MessageTray.Source.prototype._init.call(this, 'Message from ' + _stripEmailAddress(this._message.from));
|
||||
this.setTransient(true);
|
||||
this.isChat = true;
|
||||
this._setSummaryIcon(this.createNotificationIcon());
|
||||
},
|
||||
|
||||
createNotificationIcon : function() {
|
||||
// TODO: use account icon
|
||||
let icon = new St.Icon({ icon_type: St.IconType.FULLCOLOR,
|
||||
icon_size: this.ICON_SIZE,
|
||||
icon_name: 'mail-send'});
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
|
||||
function _stripEmailAddress(name_and_addr) {
|
||||
let bracketStartPos = name_and_addr.indexOf(' <');
|
||||
if (bracketStartPos == -1) {
|
||||
return name_and_addr;
|
||||
} else {
|
||||
return name_and_addr.slice(0, bracketStartPos);
|
||||
}
|
||||
}
|
||||
|
||||
function Notification(source, client, monitor, message) {
|
||||
this._init(source, client, monitor, message);
|
||||
}
|
||||
|
||||
Notification.prototype = {
|
||||
__proto__: MessageTray.Notification.prototype,
|
||||
|
||||
_init : function(source, client, monitor, message) {
|
||||
this._client = client;
|
||||
this._monitor = monitor
|
||||
this._message = message;
|
||||
this._ignore = false;
|
||||
this._alreadyExpanded = false;
|
||||
|
||||
this._strippedFrom = _stripEmailAddress(this._message.from);
|
||||
|
||||
let title = this._strippedFrom;
|
||||
let banner = this._message.subject + ' \u2014 ' + this._message.excerpt; // — U+2014 EM DASH
|
||||
|
||||
// Init super class
|
||||
MessageTray.Notification.prototype._init.call(this, source, title, banner);
|
||||
|
||||
// Change the contents once expanded
|
||||
this.connect('expanded', Lang.bind (this, this._onExpanded));
|
||||
|
||||
this.update(title, banner);
|
||||
this.setUrgency(MessageTray.Urgency.NORMAL);
|
||||
this.setTransient(true);
|
||||
|
||||
this.addButton('ignore', 'Ignore');
|
||||
if (message.can_be_starred)
|
||||
this.addButton('star', 'Star');
|
||||
if (message.can_be_marked_as_spam)
|
||||
this.addButton('spam', 'Junk');
|
||||
if (this._message.uri.length > 0) {
|
||||
this.addButton('open', 'Open');
|
||||
}
|
||||
this.connect('action-invoked', Lang.bind(this,
|
||||
function(notification, id) {
|
||||
if (id == 'ignore') {
|
||||
this._actionIgnore();
|
||||
} else if (id == 'star') {
|
||||
this._actionStar();
|
||||
} else if (id == 'spam') {
|
||||
this._actionSpam();
|
||||
} else if (id == 'open') {
|
||||
this._actionOpen();
|
||||
}
|
||||
}));
|
||||
this.connect('clicked', Lang.bind(this,
|
||||
function() {
|
||||
if (this._message.uri.length > 0) {
|
||||
this._actionOpen();
|
||||
}
|
||||
}));
|
||||
// Hmm, should be ::done-displaying instead?
|
||||
this.connect('destroy', Lang.bind(this, this._onDestroyed));
|
||||
},
|
||||
|
||||
_onExpanded : function() {
|
||||
if (this._alreadyExpanded)
|
||||
return;
|
||||
this._alreadyExpanded = true;
|
||||
let escapedExcerpt = GLib.markup_escape_text(this._message.excerpt, -1);
|
||||
let bannerMarkup = '<b>Subject:</b> ' + this._message.subject + '\n';
|
||||
// TODO: if available, insert other headers such as Cc
|
||||
bannerMarkup += '\n' + escapedExcerpt;
|
||||
this.update(this._strippedFrom, bannerMarkup, {bannerMarkup: true});
|
||||
},
|
||||
|
||||
_onDestroyed : function(reason) {
|
||||
// If not ignoring the message, push it onto the Mail source
|
||||
if (!this._ignore) {
|
||||
this._client.addPendingMessage(this._message);
|
||||
}
|
||||
},
|
||||
|
||||
_actionIgnore : function() {
|
||||
this._ignore = true;
|
||||
},
|
||||
|
||||
_actionStar : function() {
|
||||
this._ignore = true;
|
||||
this._monitor.MessageAddStar(this._message);
|
||||
},
|
||||
|
||||
_actionSpam : function() {
|
||||
this._ignore = true;
|
||||
this._monitor.MessageMarkAsSpam(this._message);
|
||||
},
|
||||
|
||||
_actionOpen : function() {
|
||||
this._ignore = true;
|
||||
Gio.app_info_launch_default_for_uri(this._message.uri,
|
||||
global.create_app_launch_context());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
|
||||
function _sameDay(dateA, dateB) {
|
||||
return (dateA.getDate() == dateB.getDate() &&
|
||||
dateA.getMonth() == dateB.getMonth() &&
|
||||
dateA.getYear() == dateB.getYear());
|
||||
}
|
||||
|
||||
function _sameYear(dateA, dateB) {
|
||||
return (dateA.getYear() == dateB.getYear());
|
||||
}
|
||||
|
||||
function _formatRelativeDate(date) {
|
||||
let ret = ''
|
||||
let now = new Date();
|
||||
if (_sameDay(date, now)) {
|
||||
ret = date.toLocaleFormat("%l:%M %p");
|
||||
} else {
|
||||
if (_sameYear(date, now)) {
|
||||
ret = date.toLocaleFormat("%B %e");
|
||||
} else {
|
||||
ret = date.toLocaleFormat("%B %e, %Y");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function _addMessageToTable(table, message) {
|
||||
let formattedExcerpt = message.excerpt.replace(/\r/g, '').replace(/\n/g, ' ');
|
||||
let formattedDate = _formatRelativeDate(message.receivedAt);
|
||||
|
||||
let fromLabel = new St.Label({ style_class: 'goa-message-base goa-message-from',
|
||||
text: _stripEmailAddress(message.from)});
|
||||
let hbox = new St.BoxLayout({ style_class: 'goa-message-hbox', vertical: false });
|
||||
let subjectLabel = new St.Label({ style_class: 'goa-message-base goa-message-subject',
|
||||
text: message.subject });
|
||||
let excerptLabel = new St.Label({ style_class: 'goa-message-base goa-message-excerpt',
|
||||
text: formattedExcerpt });
|
||||
let dateLabel = new St.Label({ style_class: 'goa-message-base goa-message-date',
|
||||
text: formattedDate });
|
||||
|
||||
excerptLabel.clutter_text.line_wrap = false;
|
||||
excerptLabel.clutter_text.ellipsize = Pango.EllipsizeMode.END;
|
||||
|
||||
hbox.add(subjectLabel, { x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.START });
|
||||
hbox.add(excerptLabel, { x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.START });
|
||||
|
||||
let n = table.get_row_count();
|
||||
table.add(fromLabel, { x_fill: true, x_expand: true, row: n, col: 0 });
|
||||
table.add(hbox, { row: n, col: 1 });
|
||||
table.add(dateLabel, { row: n, col: 2 });
|
||||
}
|
||||
|
||||
function MailSource(client) {
|
||||
this._init(client);
|
||||
}
|
||||
|
||||
MailSource.prototype = {
|
||||
__proto__: MessageTray.Source.prototype,
|
||||
|
||||
_init : function(client) {
|
||||
this._client = client;
|
||||
this._pendingMessages = [];
|
||||
|
||||
// Init super class and add ourselves to the message tray
|
||||
MessageTray.Source.prototype._init.call(this, 'Mail');
|
||||
|
||||
// Create the notification
|
||||
this._notification = new MessageTray.Notification(this)
|
||||
this._notification.setUrgency(MessageTray.Urgency.NORMAL);
|
||||
this._notification.setResident(true);
|
||||
this._updateNotification();
|
||||
this.pushNotification(this._notification);
|
||||
// Refresh all monitors everytime the "Mail" notification is displayed
|
||||
this._notification.connect('expanded', Lang.bind(this,
|
||||
function() {
|
||||
this._client.refreshAllMonitors();
|
||||
}));
|
||||
},
|
||||
|
||||
createNotificationIcon : function() {
|
||||
let numPending = this._pendingMessages.length;
|
||||
let baseIcon = new Gio.ThemedIcon({ name: 'mail-mark-unread'});
|
||||
let numerableIcon = new Gtk.NumerableIcon({ gicon: baseIcon });
|
||||
numerableIcon.set_count(numPending);
|
||||
let icon = new St.Icon({ icon_type: St.IconType.FULLCOLOR,
|
||||
icon_size: this.ICON_SIZE });
|
||||
icon.set_gicon(numerableIcon);
|
||||
return icon;
|
||||
},
|
||||
|
||||
_updateNotification: function() {
|
||||
if (!this._notification)
|
||||
return
|
||||
|
||||
let title = 'Mail';
|
||||
let banner = ''
|
||||
let table = new St.Table({ homogeneous: false,
|
||||
style_class: 'goa-message-table',
|
||||
reactive: true });
|
||||
|
||||
for (let n = 0; n < this._pendingMessages.length; n++)
|
||||
_addMessageToTable (table, this._pendingMessages[n]);
|
||||
|
||||
this._notification.update(title, banner, { clear: true,
|
||||
icon: this.createNotificationIcon() });
|
||||
this._notification.addActor(table);
|
||||
this._notification.addButton('close', 'Close');
|
||||
this._notification.addButton('ignore-all', 'Ignore All');
|
||||
this._notification.connect('action-invoked', Lang.bind(this,
|
||||
function(notification, id) {
|
||||
if (id == 'close') {
|
||||
// TODO: Can't find another way hide it
|
||||
notification._onClicked();
|
||||
} else if (id == 'ignore-all') {
|
||||
this.clearMessages();
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
addMessage: function(message) {
|
||||
this._pendingMessages.push(message);
|
||||
// Update notification
|
||||
this._updateNotification();
|
||||
// Update icon with latest pending count
|
||||
this._setSummaryIcon(this.createNotificationIcon());
|
||||
},
|
||||
|
||||
clearMessages: function() {
|
||||
let notification = this._notification;
|
||||
this._notification = null;
|
||||
if (notification)
|
||||
notification.destroy();
|
||||
this.destroy();
|
||||
},
|
||||
}
|
||||
|
||||
@@ -42,10 +42,10 @@ BaseIcon.prototype = {
|
||||
box.add_actor(this._iconBin);
|
||||
|
||||
if (params.showLabel) {
|
||||
this._name = new St.Label({ text: label });
|
||||
box.add_actor(this._name);
|
||||
this.label = new St.Label({ text: label });
|
||||
box.add_actor(this.label);
|
||||
} else {
|
||||
this._name = null;
|
||||
this.label = null;
|
||||
}
|
||||
|
||||
if (params.createIcon)
|
||||
@@ -67,8 +67,8 @@ BaseIcon.prototype = {
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
|
||||
if (this._name) {
|
||||
let [labelMinHeight, labelNatHeight] = this._name.get_preferred_height(-1);
|
||||
if (this.label) {
|
||||
let [labelMinHeight, labelNatHeight] = this.label.get_preferred_height(-1);
|
||||
preferredHeight += this._spacing + labelNatHeight;
|
||||
|
||||
let labelHeight = availHeight >= preferredHeight ? labelNatHeight
|
||||
@@ -79,7 +79,7 @@ BaseIcon.prototype = {
|
||||
childBox.x2 = availWidth;
|
||||
childBox.y1 = iconSize + this._spacing;
|
||||
childBox.y2 = childBox.y1 + labelHeight;
|
||||
this._name.allocate(childBox, flags);
|
||||
this.label.allocate(childBox, flags);
|
||||
}
|
||||
|
||||
childBox.x1 = Math.floor((availWidth - iconNatWidth) / 2);
|
||||
@@ -98,8 +98,8 @@ BaseIcon.prototype = {
|
||||
alloc.min_size = iconMinHeight;
|
||||
alloc.natural_size = iconNatHeight;
|
||||
|
||||
if (this._name) {
|
||||
let [labelMinHeight, labelNatHeight] = this._name.get_preferred_height(forWidth);
|
||||
if (this.label) {
|
||||
let [labelMinHeight, labelNatHeight] = this.label.get_preferred_height(forWidth);
|
||||
alloc.min_size += this._spacing + labelMinHeight;
|
||||
alloc.natural_size += this._spacing + labelNatHeight;
|
||||
}
|
||||
@@ -281,8 +281,11 @@ IconGrid.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
childrenInRow: function(rowWidth) {
|
||||
return this._computeLayout(rowWidth)[0];
|
||||
},
|
||||
|
||||
_computeLayout: function (forWidth) {
|
||||
let children = this._grid.get_children();
|
||||
let nColumns = 0;
|
||||
let usedWidth = 0;
|
||||
while ((this._colLimit == null || nColumns < this._colLimit) &&
|
||||
|
||||
@@ -5,14 +5,13 @@ const Cogl = imports.gi.Cogl;
|
||||
const GConf = imports.gi.GConf;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Pango = imports.gi.Pango;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const History = imports.misc.history;
|
||||
const ExtensionSystem = imports.ui.extensionSystem;
|
||||
@@ -100,12 +99,19 @@ Notebook.prototype = {
|
||||
selectIndex: function(index) {
|
||||
if (index == this._selectedIndex)
|
||||
return;
|
||||
this._unselect();
|
||||
if (index < 0) {
|
||||
this._unselect();
|
||||
this.emit('selection', null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Focus the new tab before unmapping the old one
|
||||
let tabData = this._tabs[index];
|
||||
if (!tabData.scrollView.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false))
|
||||
this.actor.grab_key_focus();
|
||||
|
||||
this._unselect();
|
||||
|
||||
tabData.labelBox.add_style_pseudo_class('selected');
|
||||
tabData.scrollView.show();
|
||||
this._selectedIndex = index;
|
||||
@@ -707,6 +713,7 @@ LookingGlass.prototype = {
|
||||
let toolbar = new St.BoxLayout({ name: 'Toolbar' });
|
||||
this.actor.add_actor(toolbar);
|
||||
let inspectIcon = new St.Icon({ icon_name: 'gtk-color-picker',
|
||||
icon_type: St.IconType.FULLCOLOR,
|
||||
icon_size: 24 });
|
||||
toolbar.add_actor(inspectIcon);
|
||||
inspectIcon.reactive = true;
|
||||
@@ -744,12 +751,7 @@ LookingGlass.prototype = {
|
||||
let label = new St.Label({ text: 'js>>> ' });
|
||||
entryArea.add(label);
|
||||
|
||||
this._entry = new St.Entry();
|
||||
/* unmapping the edit box will un-focus it, undo that */
|
||||
notebook.connect('selection', Lang.bind(this, function (nb, child) {
|
||||
if (child == this._evalBox)
|
||||
global.stage.set_key_focus(this._entry);
|
||||
}));
|
||||
this._entry = new St.Entry({ can_focus: true });
|
||||
entryArea.add(this._entry, { expand: true });
|
||||
|
||||
this._windowList = new WindowList();
|
||||
@@ -908,6 +910,7 @@ LookingGlass.prototype = {
|
||||
if (!Main.pushModal(this._entry))
|
||||
return;
|
||||
|
||||
this._notebook.selectIndex(0);
|
||||
this.actor.show();
|
||||
this.actor.lower(Main.chrome.actor);
|
||||
this._open = true;
|
||||
|
||||
148
js/ui/main.js
@@ -1,11 +1,5 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
imports.gi.versions.Clutter = '1.0';
|
||||
imports.gi.versions.Gio = '2.0';
|
||||
imports.gi.versions.Gdk = '3.0';
|
||||
imports.gi.versions.GdkPixbuf = '2.0';
|
||||
imports.gi.versions.Gtk = '3.0';
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const DBus = imports.dbus;
|
||||
const Gdk = imports.gi.Gdk;
|
||||
@@ -17,8 +11,6 @@ const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Chrome = imports.ui.chrome;
|
||||
const CtrlAltTab = imports.ui.ctrlAltTab;
|
||||
@@ -37,6 +29,7 @@ const WindowAttentionHandler = imports.ui.windowAttentionHandler;
|
||||
const Scripting = imports.ui.scripting;
|
||||
const ShellDBus = imports.ui.shellDBus;
|
||||
const TelepathyClient = imports.ui.telepathyClient;
|
||||
const GoaClient = imports.ui.goaClient;
|
||||
const WindowManager = imports.ui.windowManager;
|
||||
const Magnifier = imports.ui.magnifier;
|
||||
const XdndHandler = imports.ui.xdndHandler;
|
||||
@@ -58,6 +51,7 @@ let messageTray = null;
|
||||
let notificationDaemon = null;
|
||||
let windowAttentionHandler = null;
|
||||
let telepathyClient = null;
|
||||
let goaClient = null;
|
||||
let ctrlAltTabManager = null;
|
||||
let recorder = null;
|
||||
let shellDBusService = null;
|
||||
@@ -75,17 +69,15 @@ let _cssStylesheet = null;
|
||||
let background = null;
|
||||
|
||||
function start() {
|
||||
// Add a binding for 'global' in the global JS namespace; (gjs
|
||||
// keeps the web browser convention of having that namespace be
|
||||
// called 'window'.)
|
||||
window.global = Shell.Global.get();
|
||||
|
||||
// Now monkey patch utility functions into the global proxy;
|
||||
// Monkey patch utility functions into the global proxy;
|
||||
// This is easier and faster than indirecting down into global
|
||||
// if we want to call back up into JS.
|
||||
global.logError = _logError;
|
||||
global.log = _logDebug;
|
||||
|
||||
// Chain up async errors reported from C
|
||||
global.connect('notify-error', function (global, msg, detail) { notifyError(msg, detail); });
|
||||
|
||||
Gio.DesktopAppInfo.set_desktop_env('GNOME');
|
||||
|
||||
shellDBusService = new ShellDBus.GnomeShell();
|
||||
@@ -99,8 +91,6 @@ function start() {
|
||||
// not loading any events until the user presses the clock
|
||||
global.launch_calendar_server();
|
||||
|
||||
Environment.init();
|
||||
|
||||
// Ensure ShellWindowTracker and ShellAppUsage are initialized; this will
|
||||
// also initialize ShellAppSystem first. ShellAppSystem
|
||||
// needs to load all the .desktop files, and ShellWindowTracker
|
||||
@@ -133,6 +123,7 @@ function start() {
|
||||
|
||||
// Set up stage hierarchy to group all UI actors under one container.
|
||||
uiGroup = new Clutter.Group();
|
||||
St.set_ui_root(global.stage, uiGroup);
|
||||
global.window_group.reparent(uiGroup);
|
||||
global.overlay_group.reparent(uiGroup);
|
||||
global.stage.add_actor(uiGroup);
|
||||
@@ -150,6 +141,7 @@ function start() {
|
||||
notificationDaemon = new NotificationDaemon.NotificationDaemon();
|
||||
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
|
||||
telepathyClient = new TelepathyClient.Client();
|
||||
goaClient = new GoaClient.Client();
|
||||
|
||||
overview.init();
|
||||
statusIconDispatcher.start(messageTray.actor);
|
||||
@@ -189,7 +181,7 @@ function start() {
|
||||
// Attempt to become a PolicyKit authentication agent
|
||||
PolkitAuthenticationAgent.init()
|
||||
|
||||
global.gdk_screen.connect('monitors-changed', _relayout);
|
||||
global.screen.connect('monitors-changed', _relayout);
|
||||
|
||||
ExtensionSystem.init();
|
||||
ExtensionSystem.loadExtensions();
|
||||
@@ -216,7 +208,11 @@ function start() {
|
||||
}
|
||||
|
||||
global.screen.connect('notify::n-workspaces', _nWorkspacesChanged);
|
||||
Mainloop.idle_add(_nWorkspacesChanged);
|
||||
|
||||
global.screen.connect('window-entered-monitor', _windowEnteredMonitor);
|
||||
global.screen.connect('window-left-monitor', _windowLeftMonitor);
|
||||
|
||||
_nWorkspacesChanged();
|
||||
}
|
||||
|
||||
let _workspaces = [];
|
||||
@@ -262,12 +258,32 @@ function _checkWorkspaces() {
|
||||
emptyWorkspaces.push(false);
|
||||
}
|
||||
|
||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||
let removingCurrentWorkspace = (emptyWorkspaces[activeWorkspaceIndex] &&
|
||||
activeWorkspaceIndex < emptyWorkspaces.length - 1);
|
||||
// Don't enter the overview when removing multiple empty workspaces at startup
|
||||
let showOverview = (removingCurrentWorkspace &&
|
||||
!emptyWorkspaces.every(function(x) { return x; }));
|
||||
|
||||
if (removingCurrentWorkspace) {
|
||||
// "Merge" the empty workspace we are removing with the one at the end
|
||||
wm.blockAnimations();
|
||||
}
|
||||
|
||||
// Delete other empty workspaces; do it from the end to avoid index changes
|
||||
for (i = emptyWorkspaces.length - 2; i >= 0; i--) {
|
||||
if (emptyWorkspaces[i])
|
||||
global.screen.remove_workspace(_workspaces[i], global.get_current_time());
|
||||
}
|
||||
|
||||
if (removingCurrentWorkspace) {
|
||||
global.screen.get_workspace_by_index(global.screen.n_workspaces - 1).activate(global.get_current_time());
|
||||
wm.unblockAnimations();
|
||||
|
||||
if (!overview.visible && showOverview)
|
||||
overview.show();
|
||||
}
|
||||
|
||||
_checkWorkspacesId = 0;
|
||||
return false;
|
||||
}
|
||||
@@ -283,6 +299,20 @@ function _windowRemoved(workspace, window) {
|
||||
});
|
||||
}
|
||||
|
||||
function _windowLeftMonitor(metaScreen, monitorIndex, metaWin) {
|
||||
// If the window left the primary monitor, that
|
||||
// might make that workspace empty
|
||||
if (monitorIndex == global.get_primary_monitor_index())
|
||||
_queueCheckWorkspaces();
|
||||
}
|
||||
|
||||
function _windowEnteredMonitor(metaScreen, monitorIndex, metaWin) {
|
||||
// If the window entered the primary monitor, that
|
||||
// might make that workspace non-empty
|
||||
if (monitorIndex == global.get_primary_monitor_index())
|
||||
_queueCheckWorkspaces();
|
||||
}
|
||||
|
||||
function _queueCheckWorkspaces() {
|
||||
if (_checkWorkspacesId == 0)
|
||||
_checkWorkspacesId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, _checkWorkspaces);
|
||||
@@ -375,6 +405,27 @@ function loadTheme() {
|
||||
themeContext.set_theme (theme);
|
||||
}
|
||||
|
||||
/**
|
||||
* notifyError:
|
||||
* @msg: An error message
|
||||
* @details: Additional information
|
||||
*
|
||||
* See shell_global_notify_problem().
|
||||
*/
|
||||
function notifyError(msg, details) {
|
||||
// Also print to stderr so it's logged somewhere
|
||||
if (details)
|
||||
log("error: " + msg + ": " + details);
|
||||
else
|
||||
log("error: " + msg)
|
||||
|
||||
let source = new MessageTray.SystemNotificationSource();
|
||||
messageTray.add(source);
|
||||
let notification = new MessageTray.Notification(source, msg, details);
|
||||
notification.setTransient(true);
|
||||
source.notify(notification);
|
||||
}
|
||||
|
||||
/**
|
||||
* _log:
|
||||
* @category: string message type ('info', 'error')
|
||||
@@ -418,28 +469,67 @@ function _getAndClearErrorStack() {
|
||||
|
||||
function _relayout() {
|
||||
let monitors = global.get_monitors();
|
||||
if (monitors.length != hotCorners.length) {
|
||||
// destroy old corners
|
||||
for (let i = 0; i < hotCorners.length; i++)
|
||||
hotCorners[i].destroy();
|
||||
hotCorners = [];
|
||||
for (let i = 0; i < monitors.length; i++)
|
||||
hotCorners[i] = new Panel.HotCorner();
|
||||
}
|
||||
// destroy old corners
|
||||
for (let i = 0; i < hotCorners.length; i++)
|
||||
hotCorners[i].destroy();
|
||||
hotCorners = [];
|
||||
|
||||
|
||||
let primary = global.get_primary_monitor();
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
let monitor = monitors[i];
|
||||
let corner = hotCorners[i];
|
||||
let isPrimary = (monitor.x == primary.x &&
|
||||
monitor.y == primary.y &&
|
||||
monitor.width == primary.width &&
|
||||
monitor.height == primary.height);
|
||||
|
||||
let cornerX = monitor.x;
|
||||
let cornerY = monitor.y;
|
||||
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
|
||||
corner.actor.set_position(monitor.x + monitor.width, monitor.y);
|
||||
cornerX += monitor.width;
|
||||
|
||||
|
||||
let haveTopLeftCorner = true;
|
||||
|
||||
/* Check if we have a top left (right for RTL) corner.
|
||||
* I.e. if there is no monitor directly above or to the left(right) */
|
||||
let besideX;
|
||||
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
|
||||
besideX = monitor.x + 1;
|
||||
else
|
||||
corner.actor.set_position(monitor.x, monitor.y);
|
||||
besideX = cornerX - 1;
|
||||
let besideY = cornerY;
|
||||
let aboveX = cornerX;
|
||||
let aboveY = cornerY - 1;
|
||||
|
||||
for (let j = 0; j < monitors.length; j++) {
|
||||
if (i == j)
|
||||
continue;
|
||||
let otherMonitor = monitors[j];
|
||||
if (besideX >= otherMonitor.x &&
|
||||
besideX < otherMonitor.x + otherMonitor.width &&
|
||||
besideY >= otherMonitor.y &&
|
||||
besideY < otherMonitor.y + otherMonitor.height) {
|
||||
haveTopLeftCorner = false;
|
||||
break;
|
||||
}
|
||||
if (aboveX >= otherMonitor.x &&
|
||||
aboveX < otherMonitor.x + otherMonitor.width &&
|
||||
aboveY >= otherMonitor.y &&
|
||||
aboveY < otherMonitor.y + otherMonitor.height) {
|
||||
haveTopLeftCorner = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We only want hot corners where there is a natural top-left
|
||||
* corner, and on the primary monitor */
|
||||
if (!isPrimary && !haveTopLeftCorner)
|
||||
continue;
|
||||
|
||||
let corner = new Panel.HotCorner(isPrimary ? panel.button : null);
|
||||
hotCorners.push(corner);
|
||||
corner.actor.set_position(cornerX, cornerY);
|
||||
if (isPrimary)
|
||||
panel.setHotCorner(corner);
|
||||
}
|
||||
|
||||
@@ -20,9 +20,6 @@ const Params = imports.misc.params;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const ANIMATION_TIME = 0.2;
|
||||
const NOTIFICATION_TIMEOUT = 4;
|
||||
const SUMMARY_TIMEOUT = 1;
|
||||
@@ -108,6 +105,12 @@ URLHighlighter.prototype = {
|
||||
}
|
||||
|
||||
this.setMarkup(text, allowMarkup);
|
||||
this.actor.connect('button-press-event', Lang.bind(this, function(actor, event) {
|
||||
// Keep Notification.actor from seeing this and taking
|
||||
// a pointer grab, which would block our button-release-event
|
||||
// handler, if an URL is clicked
|
||||
return this._findUrlAtPos(event) != -1;
|
||||
}));
|
||||
this.actor.connect('button-release-event', Lang.bind(this, function (actor, event) {
|
||||
let urlId = this._findUrlAtPos(event);
|
||||
if (urlId != -1) {
|
||||
@@ -405,25 +408,25 @@ Notification.prototype = {
|
||||
this._bannerBodyText = null;
|
||||
this._bannerBodyMarkup = false;
|
||||
this._titleFitsInBannerMode = true;
|
||||
this._titleDirection = St.TextDirection.NONE;
|
||||
this._spacing = 0;
|
||||
this._scrollPolicy = Gtk.PolicyType.AUTOMATIC;
|
||||
|
||||
source.connect('destroy', Lang.bind(this,
|
||||
// Avoid passing 'source' as an argument to this.destroy()
|
||||
function () {
|
||||
this.destroy();
|
||||
function (source, reason) {
|
||||
this.destroy(reason);
|
||||
}));
|
||||
|
||||
this.actor = new St.Table({ name: 'notification',
|
||||
reactive: true });
|
||||
this.actor.connect('style-changed', Lang.bind(this, this._styleChanged));
|
||||
this.actor.connect('button-release-event', Lang.bind(this,
|
||||
function (actor, event) {
|
||||
if (!this._actionArea ||
|
||||
!this._actionArea.contains(event.get_source()))
|
||||
this._onClicked();
|
||||
}));
|
||||
this.actor = new St.Button();
|
||||
this.actor._delegate = this;
|
||||
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
||||
this._table = new St.Table({ name: 'notification',
|
||||
reactive: true });
|
||||
this._table.connect('style-changed', Lang.bind(this, this._styleChanged));
|
||||
this.actor.set_child(this._table);
|
||||
|
||||
this._buttonFocusManager = St.FocusManager.get_for_stage(global.stage);
|
||||
|
||||
// The first line should have the title, followed by the
|
||||
@@ -435,10 +438,10 @@ Notification.prototype = {
|
||||
this._bannerBox.connect('get-preferred-width', Lang.bind(this, this._bannerBoxGetPreferredWidth));
|
||||
this._bannerBox.connect('get-preferred-height', Lang.bind(this, this._bannerBoxGetPreferredHeight));
|
||||
this._bannerBox.connect('allocate', Lang.bind(this, this._bannerBoxAllocate));
|
||||
this.actor.add(this._bannerBox, { row: 0,
|
||||
col: 1,
|
||||
y_expand: false,
|
||||
y_fill: false });
|
||||
this._table.add(this._bannerBox, { row: 0,
|
||||
col: 1,
|
||||
y_expand: false,
|
||||
y_fill: false });
|
||||
|
||||
this._titleLabel = new St.Label();
|
||||
this._bannerBox.add_actor(this._titleLabel);
|
||||
@@ -468,35 +471,56 @@ Notification.prototype = {
|
||||
|
||||
this._customContent = params.customContent;
|
||||
|
||||
let oldFocus = global.stage.key_focus;
|
||||
|
||||
if (this._icon)
|
||||
this._icon.destroy();
|
||||
// We always clear the content area if we don't have custom
|
||||
// content because it might contain the @banner that didn't
|
||||
// fit in the banner mode.
|
||||
if (this._scrollArea && (!this._customContent || params.clear)) {
|
||||
if (oldFocus && this._scrollArea.contains(oldFocus))
|
||||
this.actor.grab_key_focus();
|
||||
|
||||
this._scrollArea.destroy();
|
||||
this._scrollArea = null;
|
||||
this._contentArea = null;
|
||||
}
|
||||
if (this._actionArea && params.clear) {
|
||||
if (oldFocus && this._actionArea.contains(oldFocus))
|
||||
this.actor.grab_key_focus();
|
||||
|
||||
this._actionArea.destroy();
|
||||
this._actionArea = null;
|
||||
this._buttonBox = null;
|
||||
}
|
||||
if (!this._scrollArea && !this._actionArea)
|
||||
this.actor.remove_style_class_name('multi-line-notification');
|
||||
this._table.remove_style_class_name('multi-line-notification');
|
||||
|
||||
this._icon = params.icon || this.source.createNotificationIcon();
|
||||
this.actor.add(this._icon, { row: 0,
|
||||
col: 0,
|
||||
x_expand: false,
|
||||
y_expand: false,
|
||||
y_fill: false,
|
||||
y_align: St.Align.START });
|
||||
this._table.add(this._icon, { row: 0,
|
||||
col: 0,
|
||||
x_expand: false,
|
||||
y_expand: false,
|
||||
y_fill: false,
|
||||
y_align: St.Align.START });
|
||||
|
||||
title = title ? _fixMarkup(title.replace(/\n/g, ' '), params.titleMarkup) : '';
|
||||
this._titleLabel.clutter_text.set_markup('<b>' + title + '</b>');
|
||||
|
||||
if (Pango.find_base_dir(title, -1) == Pango.Direction.RTL)
|
||||
this._titleDirection = St.TextDirection.RTL;
|
||||
else
|
||||
this._titleDirection = St.TextDirection.LTR;
|
||||
|
||||
// Let the title's text direction control the overall direction
|
||||
// of the notification - in case where different scripts are used
|
||||
// in the notification, this is the right thing for the icon, and
|
||||
// arguably for action buttons as well. Labels other than the title
|
||||
// will be allocated at the available width, so that their alignment
|
||||
// is done correctly automatically.
|
||||
this._table.set_direction(this._titleDirection);
|
||||
|
||||
// Unless the notification has custom content, we save this._bannerBodyText
|
||||
// to add it to the content of the notification if the notification is
|
||||
// expandable due to other elements in its content area or due to the banner
|
||||
@@ -518,25 +542,38 @@ Notification.prototype = {
|
||||
this._updated();
|
||||
},
|
||||
|
||||
setIconVisible: function(visible) {
|
||||
this._icon.visible = visible;
|
||||
},
|
||||
|
||||
enableScrolling: function(enableScrolling) {
|
||||
this._scrollPolicy = enableScrolling ? Gtk.PolicyType.AUTOMATIC : Gtk.PolicyType.NEVER;
|
||||
if (this._scrollArea)
|
||||
this._scrollArea.vscrollbar_policy = this._scrollPolicy;
|
||||
},
|
||||
|
||||
_createScrollArea: function() {
|
||||
this._table.add_style_class_name('multi-line-notification');
|
||||
this._scrollArea = new St.ScrollView({ name: 'notification-scrollview',
|
||||
vscrollbar_policy: this._scrollPolicy,
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER,
|
||||
vfade: true });
|
||||
this._table.add(this._scrollArea, { row: 1, col: 1 });
|
||||
this._contentArea = new St.BoxLayout({ name: 'notification-body',
|
||||
vertical: true });
|
||||
this._scrollArea.add_actor(this._contentArea);
|
||||
// If we know the notification will be expandable, we need to add
|
||||
// the banner text to the body as the first element.
|
||||
this._addBannerBody();
|
||||
},
|
||||
|
||||
// addActor:
|
||||
// @actor: actor to add to the body of the notification
|
||||
//
|
||||
// Appends @actor to the notification's body
|
||||
addActor: function(actor, style) {
|
||||
if (!this._scrollArea) {
|
||||
this.actor.add_style_class_name('multi-line-notification');
|
||||
this._scrollArea = new St.ScrollView({ name: 'notification-scrollview',
|
||||
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER,
|
||||
vfade: true });
|
||||
this.actor.add(this._scrollArea, { row: 1,
|
||||
col: 1 });
|
||||
this._contentArea = new St.BoxLayout({ name: 'notification-body',
|
||||
vertical: true });
|
||||
this._scrollArea.add_actor(this._contentArea);
|
||||
// If we know the notification will be expandable, we need to add
|
||||
// the banner text to the body as the first element.
|
||||
this._addBannerBody();
|
||||
this._createScrollArea();
|
||||
}
|
||||
|
||||
this._contentArea.add(actor, style ? style : {});
|
||||
@@ -571,11 +608,6 @@ Notification.prototype = {
|
||||
//
|
||||
// Scrolls the content area (if scrollable) to the indicated edge
|
||||
scrollTo: function(side) {
|
||||
// Hack to force a relayout, since the caller probably
|
||||
// just added or removed something to scrollArea, and
|
||||
// the adjustment needs to reflect that.
|
||||
global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, 0, 0);
|
||||
|
||||
let adjustment = this._scrollArea.vscroll.adjustment;
|
||||
if (side == St.Side.TOP)
|
||||
adjustment.value = adjustment.lower;
|
||||
@@ -605,8 +637,8 @@ Notification.prototype = {
|
||||
props.row = 2;
|
||||
props.col = 1;
|
||||
|
||||
this.actor.add_style_class_name('multi-line-notification');
|
||||
this.actor.add(this._actionArea, props);
|
||||
this._table.add_style_class_name('multi-line-notification');
|
||||
this._table.add(this._actionArea, props);
|
||||
this._updated();
|
||||
},
|
||||
|
||||
@@ -667,7 +699,7 @@ Notification.prototype = {
|
||||
},
|
||||
|
||||
_styleChanged: function() {
|
||||
this._spacing = this.actor.get_theme_node().get_length('spacing-columns');
|
||||
this._spacing = this._table.get_theme_node().get_length('spacing-columns');
|
||||
},
|
||||
|
||||
_bannerBoxGetPreferredWidth: function(actor, forHeight, alloc) {
|
||||
@@ -690,44 +722,67 @@ Notification.prototype = {
|
||||
let availWidth = box.x2 - box.x1;
|
||||
|
||||
let titleBox = new Clutter.ActorBox();
|
||||
titleBox.x1 = titleBox.y1 = 0;
|
||||
titleBox.x2 = Math.min(titleNatW, availWidth);
|
||||
let titleBoxW = Math.min(titleNatW, availWidth);
|
||||
if (this._titleDirection == St.TextDirection.RTL) {
|
||||
titleBox.x1 = availWidth - titleBoxW;
|
||||
titleBox.x2 = availWidth;
|
||||
} else {
|
||||
titleBox.x1 = 0;
|
||||
titleBox.x2 = titleBoxW;
|
||||
}
|
||||
titleBox.y1 = 0;
|
||||
titleBox.y2 = titleNatH;
|
||||
this._titleLabel.allocate(titleBox, flags);
|
||||
this._titleFitsInBannerMode = (titleNatW <= availWidth);
|
||||
|
||||
let bannerFits = true;
|
||||
if (titleBox.x2 + this._spacing > availWidth) {
|
||||
if (titleBoxW + this._spacing > availWidth) {
|
||||
this._bannerLabel.opacity = 0;
|
||||
bannerFits = false;
|
||||
} else {
|
||||
let bannerBox = new Clutter.ActorBox();
|
||||
bannerBox.x1 = titleBox.x2 + this._spacing;
|
||||
|
||||
if (this._titleDirection == St.TextDirection.RTL) {
|
||||
bannerBox.x1 = 0;
|
||||
bannerBox.x2 = titleBox.x1 - this._spacing;
|
||||
|
||||
bannerFits = (bannerBox.x2 - bannerNatW >= 0);
|
||||
} else {
|
||||
bannerBox.x1 = titleBox.x2 + this._spacing;
|
||||
bannerBox.x2 = availWidth;
|
||||
|
||||
bannerFits = (bannerBox.x1 + bannerNatW <= availWidth);
|
||||
}
|
||||
bannerBox.y1 = 0;
|
||||
bannerBox.x2 = Math.min(bannerBox.x1 + bannerNatW, availWidth);
|
||||
bannerBox.y2 = titleNatH;
|
||||
bannerFits = (bannerBox.x1 + bannerNatW <= availWidth);
|
||||
this._bannerLabel.allocate(bannerBox, flags);
|
||||
|
||||
// Make _bannerLabel visible if the entire notification
|
||||
// fits on one line, or if the notification is currently
|
||||
// unexpanded and only showing one line anyway.
|
||||
if (!this.expanded || (bannerFits && this.actor.row_count == 1))
|
||||
if (!this.expanded || (bannerFits && this._table.row_count == 1))
|
||||
this._bannerLabel.opacity = 255;
|
||||
}
|
||||
|
||||
// If the banner doesn't fully fit in the banner box, we possibly need to add the
|
||||
// banner to the body. We can't do that from here though since that will force a
|
||||
// relayout, so we add it to the main loop.
|
||||
if (!bannerFits)
|
||||
Mainloop.idle_add(Lang.bind(this,
|
||||
function() {
|
||||
if (!bannerFits && this._canExpandContent())
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
|
||||
Lang.bind(this,
|
||||
function() {
|
||||
if (this._canExpandContent()) {
|
||||
this._addBannerBody();
|
||||
if (!this._titleFitsInBannerMode)
|
||||
this.actor.add_style_class_name('multi-line-notification');
|
||||
this._table.add_style_class_name('multi-line-notification');
|
||||
this._updated();
|
||||
return false;
|
||||
}));
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
},
|
||||
|
||||
_canExpandContent: function() {
|
||||
return this._bannerBodyText ||
|
||||
(!this._titleFitsInBannerMode && !this._table.has_style_class_name('multi-line-notification'));
|
||||
},
|
||||
|
||||
_updated: function() {
|
||||
@@ -745,7 +800,7 @@ Notification.prototype = {
|
||||
this._titleLabel.clutter_text.line_wrap = true;
|
||||
this._titleLabel.clutter_text.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
|
||||
this._titleLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
} else if (this.actor.row_count > 1 && this._bannerLabel.opacity != 0) {
|
||||
} else if (this._table.row_count > 1 && this._bannerLabel.opacity != 0) {
|
||||
// We always hide the banner if the notification has additional content.
|
||||
//
|
||||
// We don't need to wrap the banner that doesn't fit the way we wrap the
|
||||
@@ -810,6 +865,7 @@ Notification.prototype = {
|
||||
destroy: function(reason) {
|
||||
this._destroyedReason = reason;
|
||||
this.actor.destroy();
|
||||
this.actor._delegate = null;
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(Notification.prototype);
|
||||
@@ -824,9 +880,13 @@ Source.prototype = {
|
||||
_init: function(title) {
|
||||
this.title = title;
|
||||
this._iconBin = new St.Bin({ width: this.ICON_SIZE,
|
||||
height: this.ICON_SIZE });
|
||||
height: this.ICON_SIZE,
|
||||
x_fill: true,
|
||||
y_fill: true });
|
||||
this.isTransient = false;
|
||||
this.isChat = false;
|
||||
|
||||
this.notifications = [];
|
||||
},
|
||||
|
||||
setTransient: function(isTransient) {
|
||||
@@ -846,30 +906,40 @@ Source.prototype = {
|
||||
return this._iconBin;
|
||||
},
|
||||
|
||||
notify: function(notification) {
|
||||
if (this.notification) {
|
||||
this.notification.disconnect(this._notificationClickedId);
|
||||
this.notification.disconnect(this._notificationDestroyedId);
|
||||
pushNotification: function(notification) {
|
||||
if (this.notifications.indexOf(notification) < 0) {
|
||||
this.notifications.push(notification);
|
||||
this.emit('notification-added', notification);
|
||||
}
|
||||
|
||||
this.notification = notification;
|
||||
|
||||
this._notificationClickedId = notification.connect('clicked', Lang.bind(this, this.open));
|
||||
this._notificationDestroyedId = notification.connect('destroy', Lang.bind(this,
|
||||
notification.connect('clicked', Lang.bind(this, this.open));
|
||||
notification.connect('destroy', Lang.bind(this,
|
||||
function () {
|
||||
if (this.notification == notification) {
|
||||
this.notification = null;
|
||||
this._notificationDestroyedId = 0;
|
||||
this._notificationClickedId = 0;
|
||||
this._notificationRemoved();
|
||||
}
|
||||
}));
|
||||
let index = this.notifications.indexOf(notification);
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
this.notifications.splice(index, 1);
|
||||
if (this.notifications.length == 0)
|
||||
this._lastNotificationRemoved();
|
||||
}));
|
||||
},
|
||||
|
||||
notify: function(notification) {
|
||||
this.pushNotification(notification);
|
||||
this.emit('notify', notification);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.emit('destroy');
|
||||
destroy: function(reason) {
|
||||
this.emit('destroy', reason);
|
||||
},
|
||||
|
||||
// A subclass can redefine this to "steal" clicks from the
|
||||
// summaryitem; Use Clutter.get_current_event() to get the
|
||||
// details, return true to prevent the default handling from
|
||||
// ocurring.
|
||||
handleSummaryClick: function() {
|
||||
return false;
|
||||
},
|
||||
|
||||
//// Protected methods ////
|
||||
@@ -885,8 +955,14 @@ Source.prototype = {
|
||||
open: function(notification) {
|
||||
},
|
||||
|
||||
destroyNonResidentNotifications: function() {
|
||||
for (let i = this.notifications.length - 1; i >= 0; i--)
|
||||
if (!this.notifications[i].resident)
|
||||
this.notifications[i].destroy();
|
||||
},
|
||||
|
||||
// Default implementation is to destroy this source, but subclasses can override
|
||||
_notificationRemoved: function() {
|
||||
_lastNotificationRemoved: function() {
|
||||
this.destroy();
|
||||
}
|
||||
};
|
||||
@@ -899,8 +975,12 @@ function SummaryItem(source) {
|
||||
SummaryItem.prototype = {
|
||||
_init: function(source) {
|
||||
this.source = source;
|
||||
this.source.connect('notification-added', Lang.bind(this, this._notificationAddedToSource));
|
||||
|
||||
this.actor = new St.Button({ style_class: 'summary-source-button',
|
||||
y_fill: true,
|
||||
reactive: true,
|
||||
button_mask: St.ButtonMask.ONE | St.ButtonMask.TWO | St.ButtonMask.THREE,
|
||||
track_hover: true });
|
||||
|
||||
this._sourceBox = new St.BoxLayout({ style_class: 'summary-source' });
|
||||
@@ -915,9 +995,30 @@ SummaryItem.prototype = {
|
||||
this._sourceTitleBin.child = this._sourceTitle;
|
||||
this._sourceTitleBin.width = 0;
|
||||
|
||||
this._sourceBox.add_actor(this._sourceIcon);
|
||||
this._sourceBox.add_actor(this._sourceTitleBin, { expand: true });
|
||||
this._sourceBox.add(this._sourceIcon, { y_fill: false });
|
||||
this._sourceBox.add(this._sourceTitleBin, { expand: true, y_fill: false });
|
||||
this.actor.child = this._sourceBox;
|
||||
|
||||
this.notificationStackView = new St.ScrollView({ name: source.isChat ? '' : 'summary-notification-stack-scrollview',
|
||||
vscrollbar_policy: source.isChat ? Gtk.PolicyType.NEVER : Gtk.PolicyType.AUTOMATIC,
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER,
|
||||
vfade: true });
|
||||
this.notificationStack = new St.BoxLayout({ name: 'summary-notification-stack',
|
||||
vertical: true });
|
||||
this.notificationStackView.add_actor(this.notificationStack);
|
||||
this._notificationExpandedIds = [];
|
||||
this._notificationDoneDisplayingIds = [];
|
||||
this._notificationDestroyedIds = [];
|
||||
|
||||
this._oldMaxScrollAdjustment = 0;
|
||||
|
||||
this.notificationStackView.vscroll.adjustment.connect('changed', Lang.bind(this, function(adjustment) {
|
||||
let currentValue = adjustment.value + adjustment.page_size;
|
||||
if (currentValue == this._oldMaxScrollAdjustment)
|
||||
this.scrollTo(St.Side.BOTTOM);
|
||||
this._oldMaxScrollAdjustment = adjustment.upper;
|
||||
}));
|
||||
|
||||
this.rightClickMenu = new St.BoxLayout({ name: 'summary-right-click-menu',
|
||||
vertical: true });
|
||||
|
||||
@@ -926,14 +1027,14 @@ SummaryItem.prototype = {
|
||||
item = new PopupMenu.PopupMenuItem(_("Open"));
|
||||
item.connect('activate', Lang.bind(this, function() {
|
||||
source.open();
|
||||
this.emit('right-click-menu-done-displaying');
|
||||
this.emit('done-displaying-content');
|
||||
}));
|
||||
this.rightClickMenu.add(item.actor);
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_("Remove"));
|
||||
item.connect('activate', Lang.bind(this, function() {
|
||||
source.destroy();
|
||||
this.emit('right-click-menu-done-displaying');
|
||||
this.emit('done-displaying-content');
|
||||
}));
|
||||
this.rightClickMenu.add(item.actor);
|
||||
|
||||
@@ -963,6 +1064,87 @@ SummaryItem.prototype = {
|
||||
|
||||
setEllipsization: function(mode) {
|
||||
this._sourceTitle.clutter_text.ellipsize = mode;
|
||||
},
|
||||
|
||||
prepareNotificationStackForShowing: function() {
|
||||
if (this.notificationStack.get_children().length > 0)
|
||||
return;
|
||||
|
||||
for (let i = 0; i < this.source.notifications.length; i++) {
|
||||
this._appendNotificationToStack(this.source.notifications[i]);
|
||||
}
|
||||
},
|
||||
|
||||
doneShowingNotificationStack: function() {
|
||||
let notificationActors = this.notificationStack.get_children();
|
||||
for (let i = 0; i < notificationActors.length; i++) {
|
||||
notificationActors[i]._delegate.collapseCompleted();
|
||||
notificationActors[i]._delegate.disconnect(this._notificationExpandedIds[i]);
|
||||
notificationActors[i]._delegate.disconnect(this._notificationDoneDisplayingIds[i]);
|
||||
notificationActors[i]._delegate.disconnect(this._notificationDestroyedIds[i]);
|
||||
this.notificationStack.remove_actor(notificationActors[i]);
|
||||
notificationActors[i]._delegate.setIconVisible(true);
|
||||
notificationActors[i]._delegate.enableScrolling(true);
|
||||
}
|
||||
this._notificationExpandedIds = [];
|
||||
this._notificationDoneDisplayingIds = [];
|
||||
this._notificationDestroyedIds = [];
|
||||
},
|
||||
|
||||
_notificationAddedToSource: function(source, notification) {
|
||||
if (this.notificationStack.mapped)
|
||||
this._appendNotificationToStack(notification);
|
||||
},
|
||||
|
||||
_appendNotificationToStack: function(notification) {
|
||||
let notificationExpandedId = notification.connect('expanded', Lang.bind(this, this._contentUpdated));
|
||||
this._notificationExpandedIds.push(notificationExpandedId);
|
||||
let notificationDoneDisplayingId = notification.connect('done-displaying', Lang.bind(this, this._notificationDoneDisplaying));
|
||||
this._notificationDoneDisplayingIds.push(notificationDoneDisplayingId);
|
||||
let notificationDestroyedId = notification.connect('destroy', Lang.bind(this, this._notificationDestroyed));
|
||||
this._notificationDestroyedIds.push(notificationDestroyedId);
|
||||
if (!this.source.isChat)
|
||||
notification.enableScrolling(false);
|
||||
if (this.notificationStack.get_children().length > 0)
|
||||
notification.setIconVisible(false);
|
||||
this.notificationStack.add(notification.actor);
|
||||
notification.expand(false);
|
||||
},
|
||||
|
||||
// scrollTo:
|
||||
// @side: St.Side.TOP or St.Side.BOTTOM
|
||||
//
|
||||
// Scrolls the notifiction stack to the indicated edge
|
||||
scrollTo: function(side) {
|
||||
let adjustment = this.notificationStackView.vscroll.adjustment;
|
||||
if (side == St.Side.TOP)
|
||||
adjustment.value = adjustment.lower;
|
||||
else if (side == St.Side.BOTTOM)
|
||||
adjustment.value = adjustment.upper;
|
||||
},
|
||||
|
||||
_contentUpdated: function() {
|
||||
this.emit('content-updated');
|
||||
},
|
||||
|
||||
_notificationDoneDisplaying: function() {
|
||||
this.emit('done-displaying-content');
|
||||
},
|
||||
|
||||
_notificationDestroyed: function(notification) {
|
||||
let index = this.notificationStack.get_children().indexOf(notification.actor);
|
||||
if (index >= 0) {
|
||||
notification.disconnect(this._notificationExpandedIds[index]);
|
||||
this._notificationExpandedIds.splice(index, 1);
|
||||
notification.disconnect(this._notificationDoneDisplayingIds[index]);
|
||||
this._notificationDoneDisplayingIds.splice(index, 1);
|
||||
notification.disconnect(this._notificationDestroyedIds[index]);
|
||||
this._notificationDestroyedIds.splice(index, 1);
|
||||
this.notificationStack.remove_actor(notification.actor);
|
||||
this._contentUpdated();
|
||||
}
|
||||
if (this.notificationStack.get_children().length > 0)
|
||||
this.notificationStack.get_children()[0]._delegate.setIconVisible(true);
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(SummaryItem.prototype);
|
||||
@@ -1011,14 +1193,15 @@ MessageTray.prototype = {
|
||||
this._summaryBoxPointer.actor.lower_bottom();
|
||||
this._summaryBoxPointer.actor.hide();
|
||||
|
||||
this._summaryNotification = null;
|
||||
this._summaryNotificationClickedId = 0;
|
||||
this._summaryRightClickMenuClickedId = 0;
|
||||
this._summaryBoxPointerItem = null;
|
||||
this._summaryBoxPointerContentUpdatedId = 0;
|
||||
this._summaryBoxPointerDoneDisplayingId = 0;
|
||||
this._clickedSummaryItem = null;
|
||||
this._clickedSummaryItemMouseButton = -1;
|
||||
this._clickedSummaryItemAllocationChangedId = 0;
|
||||
this._expandedSummaryItem = null;
|
||||
this._summaryItemTitleWidth = 0;
|
||||
this._pointerBarrier = 0;
|
||||
|
||||
// To simplify the summary item animation code, we pretend
|
||||
// that there's an invisible SummaryItem to the left of the
|
||||
@@ -1053,18 +1236,17 @@ MessageTray.prototype = {
|
||||
this._notificationTimeoutId = 0;
|
||||
this._notificationExpandedId = 0;
|
||||
this._summaryBoxPointerState = State.HIDDEN;
|
||||
this._summaryNotificationTimeoutId = 0;
|
||||
this._summaryNotificationExpandedId = 0;
|
||||
this._summaryBoxPointerTimeoutId = 0;
|
||||
this._overviewVisible = Main.overview.visible;
|
||||
this._notificationRemoved = false;
|
||||
this._reNotifyWithSummaryNotificationAfterHide = false;
|
||||
this._reNotifyAfterHideNotification = null;
|
||||
|
||||
Main.chrome.addActor(this.actor, { affectsStruts: false,
|
||||
visibleInOverview: true });
|
||||
Main.chrome.trackActor(this._notificationBin);
|
||||
Main.chrome.trackActor(this._summaryBoxPointer.actor);
|
||||
|
||||
global.gdk_screen.connect('monitors-changed', Lang.bind(this, this._setSizePosition));
|
||||
global.screen.connect('monitors-changed', Lang.bind(this, this._setSizePosition));
|
||||
|
||||
this._setSizePosition();
|
||||
|
||||
@@ -1108,6 +1290,19 @@ MessageTray.prototype = {
|
||||
this._notificationBin.width = primary.width;
|
||||
this._summaryBin.x = 0;
|
||||
this._summaryBin.width = primary.width;
|
||||
|
||||
if (this._pointerBarrier)
|
||||
global.destroy_pointer_barrier(this._pointerBarrier);
|
||||
this._pointerBarrier =
|
||||
global.create_pointer_barrier(primary.x + primary.width, primary.y + primary.height - this.actor.height,
|
||||
primary.x + primary.width, primary.y + primary.height,
|
||||
4 /* BarrierNegativeX */);
|
||||
|
||||
|
||||
},
|
||||
|
||||
getBusy: function(source) {
|
||||
return this._busy;
|
||||
},
|
||||
|
||||
contains: function(source) {
|
||||
@@ -1163,9 +1358,9 @@ MessageTray.prototype = {
|
||||
this._onSummaryItemHoverChanged(summaryItem);
|
||||
}));
|
||||
|
||||
summaryItem.actor.connect('button-press-event', Lang.bind(this,
|
||||
function (actor, event) {
|
||||
this._onSummaryItemClicked(summaryItem, event);
|
||||
summaryItem.actor.connect('clicked', Lang.bind(this,
|
||||
function (actor, button) {
|
||||
this._onSummaryItemClicked(summaryItem, button);
|
||||
}));
|
||||
|
||||
source.connect('destroy', Lang.bind(this, this._onSourceDestroy));
|
||||
@@ -1229,13 +1424,6 @@ MessageTray.prototype = {
|
||||
|
||||
if (needUpdate);
|
||||
this._updateState();
|
||||
|
||||
// remove all notifications with this source from the queue
|
||||
let newNotificationQueue = [];
|
||||
for (let i = this._notificationQueue.length - 1; i >= 0; i--) {
|
||||
if (this._notificationQueue[i].source == source)
|
||||
this._notificationQueue[i].destroy();
|
||||
}
|
||||
},
|
||||
|
||||
_onNotificationDestroy: function(notification) {
|
||||
@@ -1260,18 +1448,23 @@ MessageTray.prototype = {
|
||||
if (!this._locked)
|
||||
return;
|
||||
this._locked = false;
|
||||
this._pointerInTray = this.actor.hover && !this._summaryBoxPointer.bin.hover;
|
||||
this._updateState();
|
||||
},
|
||||
|
||||
_onNotify: function(source, notification) {
|
||||
if (notification == this._summaryNotification) {
|
||||
if (!this._summaryNotificationExpandedId)
|
||||
// We must be in the process of hiding the summary notification.
|
||||
// If the summary notification is updated while it is being
|
||||
// hidden, we show the update as a new notification. However,
|
||||
// we must first wait till the hide is complete and the
|
||||
// notification actor is not part of the stage.
|
||||
this._reNotifyWithSummaryNotificationAfterHide = true;
|
||||
if (this._summaryBoxPointerItem && this._summaryBoxPointerItem.source == source) {
|
||||
if (this._summaryBoxPointerState == State.HIDING)
|
||||
// We are in the process of hiding the summary box pointer.
|
||||
// If there is an update for one of the notifications or
|
||||
// a new notification to be added to the notification stack
|
||||
// while it is in the process of being hidden, we show it as
|
||||
// a new notification. However, we first wait till the hide
|
||||
// is complete. This is especially important if one of the
|
||||
// notifications in the stack was updated because we will
|
||||
// need to be able to re-parent its actor to a different
|
||||
// part of the stage.
|
||||
this._reNotifyAfterHideNotification = notification;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1310,12 +1503,18 @@ MessageTray.prototype = {
|
||||
// Turn off ellipsization for the previously expanded item that is
|
||||
// collapsing and for the item that is expanding because it looks
|
||||
// better that way.
|
||||
if (this._expandedSummaryItem)
|
||||
if (this._expandedSummaryItem) {
|
||||
// Ideally, we would remove 'expanded' pseudo class when the item
|
||||
// is done collapsing, but we don't track when that happens.
|
||||
this._expandedSummaryItem.actor.remove_style_pseudo_class('expanded');
|
||||
this._expandedSummaryItem.setEllipsization(Pango.EllipsizeMode.NONE);
|
||||
}
|
||||
|
||||
this._expandedSummaryItem = summaryItem;
|
||||
if (this._expandedSummaryItem)
|
||||
if (this._expandedSummaryItem) {
|
||||
this._expandedSummaryItem.actor.add_style_pseudo_class('expanded');
|
||||
this._expandedSummaryItem.setEllipsization(Pango.EllipsizeMode.NONE);
|
||||
}
|
||||
|
||||
// We tween on a "_expandedSummaryItemTitleWidth" pseudo-property
|
||||
// that represents the current title width of the
|
||||
@@ -1337,6 +1536,8 @@ MessageTray.prototype = {
|
||||
},
|
||||
|
||||
set _expandedSummaryItemTitleWidth(expansion) {
|
||||
expansion = Math.round(expansion);
|
||||
|
||||
// Expand the expanding item to its new width
|
||||
if (this._expandedSummaryItem)
|
||||
this._expandedSummaryItem.setTitleWidth(expansion);
|
||||
@@ -1367,11 +1568,32 @@ MessageTray.prototype = {
|
||||
if (this._summaryItems[i] == this._expandedSummaryItem)
|
||||
continue;
|
||||
|
||||
let width = this._summaryItems[i].getTitleWidth();
|
||||
this._summaryItems[i].setTitleWidth(width * shrinkage);
|
||||
let oldWidth = this._summaryItems[i].getTitleWidth();
|
||||
let newWidth = Math.floor(oldWidth * shrinkage);
|
||||
excess -= newWidth;
|
||||
this._summaryItems[i].setTitleWidth(newWidth);
|
||||
}
|
||||
if (this._expandedSummaryItem) {
|
||||
let oldWidth = this._imaginarySummaryItemTitleWidth;
|
||||
let newWidth = Math.floor(oldWidth * shrinkage);
|
||||
excess -= newWidth;
|
||||
this._imaginarySummaryItemTitleWidth = newWidth;
|
||||
}
|
||||
|
||||
// If the tray as a whole is fully-expanded, make sure the
|
||||
// left edge doesn't wobble during animation due to rounding.
|
||||
if (this._imaginarySummaryItemTitleWidth == 0 && excess != 0) {
|
||||
for (let i = 0; i < this._summaryItems.length; i++) {
|
||||
if (this._summaryItems[i] == this._expandedSummaryItem)
|
||||
continue;
|
||||
|
||||
let oldWidth = this._summaryItems[i].getTitleWidth();
|
||||
if (oldWidth != 0) {
|
||||
this._summaryItems[i].setTitleWidth (oldWidth + excess);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this._expandedSummaryItem)
|
||||
this._imaginarySummaryItemTitleWidth *= shrinkage;
|
||||
},
|
||||
|
||||
_expandSummaryItemCompleted: function() {
|
||||
@@ -1379,13 +1601,14 @@ MessageTray.prototype = {
|
||||
this._expandedSummaryItem.setEllipsization(Pango.EllipsizeMode.END);
|
||||
},
|
||||
|
||||
_onSummaryItemClicked: function(summaryItem, event) {
|
||||
let clickedButton = event.get_button();
|
||||
if (!this._clickedSummaryItem ||
|
||||
this._clickedSummaryItem != summaryItem ||
|
||||
this._clickedSummaryItemMouseButton != clickedButton) {
|
||||
_onSummaryItemClicked: function(summaryItem, button) {
|
||||
if (summaryItem.source.handleSummaryClick())
|
||||
this._unsetClickedSummaryItem();
|
||||
else if (!this._clickedSummaryItem ||
|
||||
this._clickedSummaryItem != summaryItem ||
|
||||
this._clickedSummaryItemMouseButton != button) {
|
||||
this._clickedSummaryItem = summaryItem;
|
||||
this._clickedSummaryItemMouseButton = clickedButton;
|
||||
this._clickedSummaryItemMouseButton = button;
|
||||
} else {
|
||||
this._unsetClickedSummaryItem();
|
||||
}
|
||||
@@ -1521,14 +1744,15 @@ MessageTray.prototype = {
|
||||
// at the present time.
|
||||
_updateState: function() {
|
||||
// Notifications
|
||||
let notificationsPending = this._notificationQueue.length > 0 &&
|
||||
(!this._busy || this._notificationQueue[0].urgency == Urgency.CRITICAL);
|
||||
let notificationUrgent = this._notificationQueue.length > 0 && this._notificationQueue[0].urgency == Urgency.CRITICAL;
|
||||
let notificationsPending = this._notificationQueue.length > 0 && (!this._busy || notificationUrgent);
|
||||
let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved;
|
||||
let notificationExpanded = this._notificationBin.y < 0;
|
||||
let notificationExpired = (this._notificationTimeoutId == 0 && !(this._notification && this._notification.urgency == Urgency.CRITICAL) && !this._pointerInTray && !this._locked) || this._notificationRemoved;
|
||||
let canShowNotification = notificationsPending && this._summaryState == State.HIDDEN;
|
||||
|
||||
if (this._notificationState == State.HIDDEN) {
|
||||
if (notificationsPending)
|
||||
if (canShowNotification)
|
||||
this._showNotification();
|
||||
} else if (this._notificationState == State.SHOWN) {
|
||||
if (notificationExpired)
|
||||
@@ -1550,7 +1774,11 @@ MessageTray.prototype = {
|
||||
this._notificationState == State.SHOWN);
|
||||
let notificationsDone = !notificationsVisible && !notificationsPending;
|
||||
|
||||
if (this._summaryState == State.HIDDEN) {
|
||||
let summaryOptionalInOverview = this._overviewVisible && !this._locked && !summaryHovered;
|
||||
let mustHideSummary = (notificationsPending && (notificationUrgent || summaryOptionalInOverview))
|
||||
|| notificationsVisible;
|
||||
|
||||
if (this._summaryState == State.HIDDEN && !mustHideSummary) {
|
||||
if (this._backFromAway) {
|
||||
// Immediately set this to false, so that we don't schedule a timeout later
|
||||
this._backFromAway = false;
|
||||
@@ -1562,7 +1790,7 @@ MessageTray.prototype = {
|
||||
this._showSummary(0);
|
||||
}
|
||||
} else if (this._summaryState == State.SHOWN) {
|
||||
if (!summaryPinned)
|
||||
if (!summaryPinned || mustHideSummary)
|
||||
this._hideSummary();
|
||||
else if (summaryVisibleWithNoHover && !summaryNotificationIsForExpandedSummaryItem)
|
||||
// If we are hiding the summary, we'll collapse the expanded summary item when we are done
|
||||
@@ -1577,18 +1805,21 @@ MessageTray.prototype = {
|
||||
let summarySourceIsMainNotificationSource = (haveClickedSummaryItem && this._notification &&
|
||||
this._clickedSummaryItem.source == this._notification.source);
|
||||
let canShowSummaryBoxPointer = this._summaryState == State.SHOWN;
|
||||
let wrongSummaryNotification = (this._clickedSummaryItemMouseButton == 1 &&
|
||||
this._summaryNotification != this._clickedSummaryItem.source.notification);
|
||||
// We only have sources with empty notification stacks for legacy tray icons. Currently, we never attempt
|
||||
// to show notifications for legacy tray icons, but this would be necessary if we did.
|
||||
let requestedNotificationStackIsEmpty = (this._clickedSummaryItemMouseButton == 1 && this._clickedSummaryItem.source.notifications.length == 0);
|
||||
let wrongSummaryNotificationStack = (this._clickedSummaryItemMouseButton == 1 &&
|
||||
this._summaryBoxPointer.bin.child != this._clickedSummaryItem.notificationStackView);
|
||||
let wrongSummaryRightClickMenu = (this._clickedSummaryItemMouseButton == 3 &&
|
||||
this._summaryBoxPointer.bin.child != this._clickedSummaryItem.rightClickMenu);
|
||||
let wrongSummaryBoxPointer = (haveClickedSummaryItem &&
|
||||
(wrongSummaryNotification || wrongSummaryRightClickMenu));
|
||||
(wrongSummaryNotificationStack || wrongSummaryRightClickMenu));
|
||||
|
||||
if (this._summaryBoxPointerState == State.HIDDEN) {
|
||||
if (haveClickedSummaryItem && !summarySourceIsMainNotificationSource && canShowSummaryBoxPointer)
|
||||
if (haveClickedSummaryItem && !summarySourceIsMainNotificationSource && canShowSummaryBoxPointer && !requestedNotificationStackIsEmpty)
|
||||
this._showSummaryBoxPointer();
|
||||
} else if (this._summaryBoxPointerState == State.SHOWN) {
|
||||
if (!haveClickedSummaryItem || !canShowSummaryBoxPointer || wrongSummaryBoxPointer)
|
||||
if (!haveClickedSummaryItem || !canShowSummaryBoxPointer || wrongSummaryBoxPointer || mustHideSummary)
|
||||
this._hideSummaryBoxPointer();
|
||||
}
|
||||
|
||||
@@ -1843,38 +2074,33 @@ MessageTray.prototype = {
|
||||
},
|
||||
|
||||
_hideSummaryCompleted: function() {
|
||||
this._expandedSummaryItem = null;
|
||||
this._expandedSummaryItemTitleWidth = this._summaryItemTitleWidth;
|
||||
this._setExpandedSummaryItem(null);
|
||||
},
|
||||
|
||||
_showSummaryBoxPointer: function() {
|
||||
this._summaryBoxPointerItem = this._clickedSummaryItem;
|
||||
this._summaryBoxPointerContentUpdatedId = this._summaryBoxPointerItem.connect('content-updated',
|
||||
Lang.bind(this, this._adjustSummaryBoxPointerPosition));
|
||||
this._summaryBoxPointerDoneDisplayingId = this._summaryBoxPointerItem.connect('done-displaying-content',
|
||||
Lang.bind(this, this._escapeTray));
|
||||
if (this._clickedSummaryItemMouseButton == 1) {
|
||||
let clickedSummaryItemNotification = this._clickedSummaryItem.source.notification;
|
||||
let index = this._notificationQueue.indexOf(clickedSummaryItemNotification);
|
||||
if (index != -1)
|
||||
this._notificationQueue.splice(index, 1);
|
||||
|
||||
this._summaryNotification = clickedSummaryItemNotification;
|
||||
this._summaryNotificationClickedId = this._summaryNotification.connect('done-displaying',
|
||||
Lang.bind(this, this._escapeTray));
|
||||
this._summaryBoxPointer.bin.child = this._summaryNotification.actor;
|
||||
if (!this._summaryNotificationExpandedId)
|
||||
this._summaryNotificationExpandedId = this._summaryNotification.connect('expanded',
|
||||
Lang.bind(this, this._onSummaryBoxPointerExpanded));
|
||||
this._summaryNotification.expand(false);
|
||||
this._notificationQueue = this._notificationQueue.filter( Lang.bind(this,
|
||||
function(notification) {
|
||||
return this._summaryBoxPointerItem.source != notification.source;
|
||||
}));
|
||||
this._summaryBoxPointerItem.prepareNotificationStackForShowing();
|
||||
this._summaryBoxPointer.bin.child = this._summaryBoxPointerItem.notificationStackView;
|
||||
this._summaryBoxPointerItem.scrollTo(St.Side.BOTTOM);
|
||||
} else if (this._clickedSummaryItemMouseButton == 3) {
|
||||
this._summaryRightClickMenuClickedId = this._clickedSummaryItem.connect('right-click-menu-done-displaying',
|
||||
Lang.bind(this, this._escapeTray));
|
||||
this._summaryBoxPointer.bin.child = this._clickedSummaryItem.rightClickMenu;
|
||||
}
|
||||
|
||||
this._focusGrabber.grabFocus(this._summaryBoxPointer.bin.child);
|
||||
|
||||
|
||||
this._clickedSummaryItemAllocationChangedId =
|
||||
this._clickedSummaryItem.actor.connect('allocation-changed',
|
||||
Lang.bind(this, this._adjustSummaryBoxPointerPosition));
|
||||
// _clickedSummaryItem.actor can change absolute postiion without changing allocation
|
||||
// _clickedSummaryItem.actor can change absolute position without changing allocation
|
||||
this._summaryMotionId = this._summary.connect('allocation-changed',
|
||||
Lang.bind(this, this._adjustSummaryBoxPointerPosition));
|
||||
|
||||
@@ -1883,6 +2109,7 @@ MessageTray.prototype = {
|
||||
this._adjustSummaryBoxPointerPosition();
|
||||
|
||||
this._summaryBoxPointerState = State.SHOWING;
|
||||
this._clickedSummaryItem.actor.add_style_pseudo_class('selected');
|
||||
this._summaryBoxPointer.show(true, Lang.bind(this, function() {
|
||||
this._summaryBoxPointerState = State.SHOWN;
|
||||
}));
|
||||
@@ -1904,49 +2131,54 @@ MessageTray.prototype = {
|
||||
this._summaryMotionId = 0;
|
||||
}
|
||||
|
||||
if (this._summaryRightClickMenuClickedId) {
|
||||
this._clickedSummaryItem.disconnect(this._summaryRightClickMenuClickedId);
|
||||
this._summaryRightClickMenuClickedId = 0;
|
||||
}
|
||||
|
||||
if (this._clickedSummaryItem)
|
||||
this._clickedSummaryItem.actor.remove_style_pseudo_class('selected');
|
||||
this._clickedSummaryItem = null;
|
||||
this._clickedSummaryItemMouseButton = -1;
|
||||
},
|
||||
|
||||
_onSummaryBoxPointerExpanded: function() {
|
||||
this._adjustSummaryBoxPointerPosition();
|
||||
},
|
||||
|
||||
_hideSummaryBoxPointer: function() {
|
||||
if (this._summaryNotificationExpandedId) {
|
||||
this._summaryNotification.disconnect(this._summaryNotificationExpandedId);
|
||||
this._summaryNotificationExpandedId = 0;
|
||||
}
|
||||
this._summaryBoxPointerState = State.HIDING;
|
||||
// Unset this._clickedSummaryItem if we are no longer showing the summary
|
||||
if (this._summaryState != State.SHOWN)
|
||||
this._unsetClickedSummaryItem();
|
||||
|
||||
this._focusGrabber.ungrabFocus();
|
||||
this._summaryBoxPointerState = State.HIDING;
|
||||
this._summaryBoxPointer.hide(true, Lang.bind(this, this._hideSummaryBoxPointerCompleted));
|
||||
if (this._summaryBoxPointerItem.source.notifications.length == 0) {
|
||||
this._summaryBoxPointer.actor.hide();
|
||||
this._hideSummaryBoxPointerCompleted();
|
||||
} else {
|
||||
this._summaryBoxPointer.hide(true, Lang.bind(this, this._hideSummaryBoxPointerCompleted));
|
||||
}
|
||||
},
|
||||
|
||||
_hideSummaryBoxPointerCompleted: function() {
|
||||
let doneShowingNotificationStack = (this._summaryBoxPointer.bin.child == this._summaryBoxPointerItem.notificationStackView);
|
||||
|
||||
this._summaryBoxPointerState = State.HIDDEN;
|
||||
this._summaryBoxPointer.bin.child = null;
|
||||
if (this._summaryNotification != null) {
|
||||
this._summaryNotification.collapseCompleted();
|
||||
this._summaryNotification.disconnect(this._summaryNotificationClickedId);
|
||||
this._summaryNotificationClickedId = 0;
|
||||
let summaryNotification = this._summaryNotification;
|
||||
this._summaryNotification = null;
|
||||
if (summaryNotification.isTransient && !this._reNotifyWithSummaryNotificationAfterHide)
|
||||
summaryNotification.destroy(NotificationDestroyedReason.EXPIRED);
|
||||
if (this._reNotifyWithSummaryNotificationAfterHide) {
|
||||
this._onNotify(summaryNotification.source, summaryNotification);
|
||||
this._reNotifyWithSummaryNotificationAfterHide = false;
|
||||
this._summaryBoxPointerItem.disconnect(this._summaryBoxPointerContentUpdatedId);
|
||||
this._summaryBoxPointerContentUpdatedId = 0;
|
||||
this._summaryBoxPointerItem.disconnect(this._summaryBoxPointerDoneDisplayingId);
|
||||
this._summaryBoxPointerDoneDisplayingId = 0;
|
||||
|
||||
let sourceNotificationStackDoneShowing = null;
|
||||
if (doneShowingNotificationStack) {
|
||||
this._summaryBoxPointerItem.doneShowingNotificationStack();
|
||||
sourceNotificationStackDoneShowing = this._summaryBoxPointerItem.source;
|
||||
}
|
||||
|
||||
this._summaryBoxPointerItem = null;
|
||||
|
||||
if (sourceNotificationStackDoneShowing) {
|
||||
if (sourceNotificationStackDoneShowing.isTransient && !this._reNotifyAfterHideNotification)
|
||||
sourceNotificationStackDoneShowing.destroy(NotificationDestroyedReason.EXPIRED);
|
||||
if (this._reNotifyAfterHideNotification) {
|
||||
this._onNotify(this._reNotifyAfterHideNotification.source, this._reNotifyAfterHideNotification);
|
||||
this._reNotifyAfterHideNotification = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._clickedSummaryItem)
|
||||
this._updateState();
|
||||
}
|
||||
|
||||
@@ -10,8 +10,6 @@ const Pango = imports.gi.Pango;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Params = imports.misc.params;
|
||||
|
||||
@@ -39,13 +37,16 @@ ModalDialog.prototype = {
|
||||
params = Params.parse(params, { styleClass: null });
|
||||
|
||||
this.state = State.CLOSED;
|
||||
this._hasModal = false;
|
||||
|
||||
this._group = new St.Group({ visible: false,
|
||||
x: 0,
|
||||
y: 0 });
|
||||
Main.uiGroup.add_actor(this._group);
|
||||
global.focus_manager.add_group(this._group);
|
||||
this._initialKeyFocus = this._group;
|
||||
|
||||
let constraint = new Clutter.BindConstraint({ source: global.stage,
|
||||
coordinate: Clutter.BindCoordinate.POSITION | Clutter.BindCoordinate.SIZE });
|
||||
this._group.add_constraint(constraint);
|
||||
|
||||
this._group.connect('destroy', Lang.bind(this, this._onGroupDestroy));
|
||||
|
||||
@@ -60,12 +61,18 @@ ModalDialog.prototype = {
|
||||
this._group.add_actor(this._backgroundBin);
|
||||
this._lightbox.highlight(this._backgroundBin);
|
||||
|
||||
this._backgroundStack = new Shell.Stack();
|
||||
this._backgroundBin.child = this._backgroundStack;
|
||||
|
||||
this._eventBlocker = new Clutter.Group({ reactive: true });
|
||||
this._backgroundStack.add_actor(this._eventBlocker);
|
||||
|
||||
this._dialogLayout = new St.BoxLayout({ style_class: 'modal-dialog',
|
||||
vertical: true });
|
||||
if (params.styleClass != null) {
|
||||
this._dialogLayout.add_style_class_name(params.styleClass);
|
||||
}
|
||||
this._backgroundBin.child = this._dialogLayout;
|
||||
this._backgroundStack.add_actor(this._dialogLayout);
|
||||
|
||||
this.contentLayout = new St.BoxLayout({ vertical: true });
|
||||
this._dialogLayout.add(this.contentLayout,
|
||||
@@ -74,12 +81,17 @@ ModalDialog.prototype = {
|
||||
x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.START });
|
||||
|
||||
this._buttonLayout = new St.BoxLayout({ opacity: 220,
|
||||
vertical: false });
|
||||
this._buttonLayout = new St.BoxLayout({ style_class: 'modal-dialog-button-box',
|
||||
opacity: 220,
|
||||
vertical: false });
|
||||
this._dialogLayout.add(this._buttonLayout,
|
||||
{ expand: true,
|
||||
x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.END });
|
||||
|
||||
global.focus_manager.add_group(this._dialogLayout);
|
||||
this._initialKeyFocus = this._dialogLayout;
|
||||
this._savedKeyFocus = null;
|
||||
},
|
||||
|
||||
setButtons: function(buttons) {
|
||||
@@ -154,22 +166,23 @@ ModalDialog.prototype = {
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this,
|
||||
function() {
|
||||
this._initialKeyFocus.grab_key_focus();
|
||||
this.state = State.OPENED;
|
||||
this.emit('opened');
|
||||
}),
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
setInitialKeyFocus: function(actor) {
|
||||
this._initialKeyFocus = actor;
|
||||
},
|
||||
|
||||
open: function(timestamp) {
|
||||
if (this.state == State.OPENED || this.state == State.OPENING)
|
||||
return true;
|
||||
|
||||
if (!Main.pushModal(this._group, timestamp))
|
||||
if (!this.pushModal(timestamp))
|
||||
return false;
|
||||
|
||||
global.stage.set_key_focus(this._group);
|
||||
|
||||
this._fadeOpen();
|
||||
return true;
|
||||
},
|
||||
@@ -178,14 +191,9 @@ ModalDialog.prototype = {
|
||||
if (this.state == State.CLOSED || this.state == State.CLOSING)
|
||||
return;
|
||||
|
||||
let needsPopModal;
|
||||
|
||||
if (this.state == State.OPENED || this.state == State.OPENING)
|
||||
needsPopModal = true;
|
||||
else
|
||||
needsPopModal = false;
|
||||
|
||||
this.state = State.CLOSING;
|
||||
this.popModal(timestamp);
|
||||
this._savedKeyFocus = null;
|
||||
|
||||
Tweener.addTween(this._group,
|
||||
{ opacity: 0,
|
||||
@@ -195,13 +203,46 @@ ModalDialog.prototype = {
|
||||
function() {
|
||||
this.state = State.CLOSED;
|
||||
this._group.hide();
|
||||
|
||||
if (needsPopModal)
|
||||
Main.popModal(this._group, timestamp);
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
// Drop modal status without closing the dialog; this makes the
|
||||
// dialog insensitive as well, so it needs to be followed shortly
|
||||
// by either a close() or a pushModal()
|
||||
popModal: function(timestamp) {
|
||||
if (!this._hasModal)
|
||||
return;
|
||||
|
||||
let focus = global.stage.key_focus;
|
||||
if (focus && this._group.contains(focus))
|
||||
this._savedKeyFocus = focus;
|
||||
else
|
||||
this._savedKeyFocus = null;
|
||||
Main.popModal(this._group, timestamp);
|
||||
global.gdk_screen.get_display().sync();
|
||||
this._hasModal = false;
|
||||
|
||||
this._eventBlocker.raise_top();
|
||||
},
|
||||
|
||||
pushModal: function (timestamp) {
|
||||
if (this._hasModal)
|
||||
return true;
|
||||
if (!Main.pushModal(this._group, timestamp))
|
||||
return false;
|
||||
|
||||
this._hasModal = true;
|
||||
if (this._savedKeyFocus) {
|
||||
this._savedKeyFocus.grab_key_focus();
|
||||
this._savedKeyFocus = null;
|
||||
} else
|
||||
this._initialKeyFocus.grab_key_focus();
|
||||
|
||||
this._eventBlocker.lower_bottom();
|
||||
return true;
|
||||
},
|
||||
|
||||
// This method is like close, but fades the dialog out much slower,
|
||||
// and leaves the lightbox in place. Once in the faded out state,
|
||||
// the dialog can be brought back by an open call, or the lightbox
|
||||
@@ -220,6 +261,7 @@ ModalDialog.prototype = {
|
||||
if (this.state == State.FADED_OUT)
|
||||
return;
|
||||
|
||||
this.popModal(timestamp);
|
||||
Tweener.addTween(this._dialogLayout,
|
||||
{ opacity: 0,
|
||||
time: FADE_OUT_DIALOG_TIME,
|
||||
@@ -227,7 +269,6 @@ ModalDialog.prototype = {
|
||||
onComplete: Lang.bind(this,
|
||||
function() {
|
||||
this.state = State.FADED_OUT;
|
||||
Main.popModal(this._group, timestamp);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const DBus = imports.dbus;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Mainloop = imports.mainloop;
|
||||
const St = imports.gi.St;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Config = imports.misc.config;
|
||||
const Main = imports.ui.main;
|
||||
@@ -188,9 +187,11 @@ NotificationDaemon.prototype = {
|
||||
actions, hints, timeout) {
|
||||
let id;
|
||||
|
||||
// Filter out notifications from Empathy, since we
|
||||
// Filter out chat and presence notifications from Empathy, since we
|
||||
// handle that information from telepathyClient.js
|
||||
if (appName == 'Empathy') {
|
||||
if (appName == 'Empathy' && (hints['category'] == 'im.received' ||
|
||||
hints['category'] == 'presence.online' ||
|
||||
hints['category'] == 'presence.offline')) {
|
||||
// Ignore replacesId since we already sent back a
|
||||
// NotificationClosed for that id.
|
||||
id = nextNotificationId++;
|
||||
@@ -345,7 +346,7 @@ NotificationDaemon.prototype = {
|
||||
notification.setTransient(hints['transient'] == true);
|
||||
|
||||
let sourceIconActor = source.useNotificationIcon ? this._iconForNotificationData(icon, hints, source.ICON_SIZE) : null;
|
||||
source.notify(notification, sourceIconActor);
|
||||
source.processNotification(notification, sourceIconActor);
|
||||
},
|
||||
|
||||
CloseNotification: function(id) {
|
||||
@@ -389,8 +390,7 @@ NotificationDaemon.prototype = {
|
||||
for (let id in this._sources) {
|
||||
let source = this._sources[id];
|
||||
if (source.app == tracker.focus_app) {
|
||||
if (source.notification && !source.notification.resident)
|
||||
source.notification.destroy();
|
||||
source.destroyNonResidentNotifications();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -441,15 +441,51 @@ Source.prototype = {
|
||||
this.title = this.app.get_name();
|
||||
else
|
||||
this.useNotificationIcon = true;
|
||||
this._isTrayIcon = false;
|
||||
this._trayIcon = null;
|
||||
},
|
||||
|
||||
notify: function(notification, icon) {
|
||||
processNotification: function(notification, icon) {
|
||||
if (!this.app)
|
||||
this._setApp();
|
||||
if (!this.app && icon)
|
||||
this._setSummaryIcon(icon);
|
||||
MessageTray.Source.prototype.notify.call(this, notification);
|
||||
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
if (notification.resident && this.app && tracker.focus_app == this.app)
|
||||
this.pushNotification(notification);
|
||||
else
|
||||
this.notify(notification);
|
||||
},
|
||||
|
||||
handleSummaryClick: function() {
|
||||
if (!this._trayIcon)
|
||||
return false;
|
||||
|
||||
let event = Clutter.get_current_event();
|
||||
if (event.type() != Clutter.EventType.BUTTON_RELEASE)
|
||||
return false;
|
||||
|
||||
// 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 (event.get_button() == 1 &&
|
||||
this.notifications.length > 0)
|
||||
return false;
|
||||
|
||||
if (Main.overview.visible) {
|
||||
// We can't just connect to Main.overview's 'hidden' signal,
|
||||
// because it's emitted *before* it calls popModal()...
|
||||
let id = global.connect('notify::stage-input-mode', Lang.bind(this,
|
||||
function () {
|
||||
global.disconnect(id);
|
||||
this._trayIcon.click(event);
|
||||
}));
|
||||
Main.overview.hide();
|
||||
} else {
|
||||
this._trayIcon.click(event);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
_setApp: function() {
|
||||
@@ -466,7 +502,7 @@ Source.prototype = {
|
||||
|
||||
// Only override the icon if we were previously using
|
||||
// notification-based icons (ie, not a trayicon) or if it was unset before
|
||||
if (!this._isTrayIcon) {
|
||||
if (!this._trayIcon) {
|
||||
this.useNotificationIcon = false;
|
||||
this._setSummaryIcon(this.app.create_icon_texture (this.ICON_SIZE));
|
||||
}
|
||||
@@ -475,25 +511,29 @@ Source.prototype = {
|
||||
setTrayIcon: function(icon) {
|
||||
this._setSummaryIcon(icon);
|
||||
this.useNotificationIcon = false;
|
||||
this._isTrayIcon = true;
|
||||
this._trayIcon = icon;
|
||||
},
|
||||
|
||||
open: function(notification) {
|
||||
this.destroyNonResidentNotifications();
|
||||
this.openApp();
|
||||
},
|
||||
|
||||
_notificationRemoved: function() {
|
||||
if (!this._isTrayIcon)
|
||||
_lastNotificationRemoved: function() {
|
||||
if (!this._trayIcon)
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
_appStateChanged: function() {
|
||||
// Destroy notification sources when their apps exit.
|
||||
// The app exiting would normally result in a tray icon being removed,
|
||||
// so it should be ok to destroy the source associated with a tray icon
|
||||
// here too, however we just let that happen through the code path
|
||||
// associated with the tray icon being removed.
|
||||
if (!this._isTrayIcon && this.app.get_state() == Shell.AppState.STOPPED)
|
||||
// so the associated source would be destroyed through the code path
|
||||
// that handles the tray icon being removed. We should not destroy
|
||||
// the source associated with a tray icon when the application state
|
||||
// is Shell.AppState.STOPPED because running applications that have
|
||||
// no open windows would also have that state. This is often the case
|
||||
// for applications that use tray icons.
|
||||
if (!this._trayIcon && this.app.get_state() == Shell.AppState.STOPPED)
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@ const Signals = imports.signals;
|
||||
const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
const Gdk = imports.gi.Gdk;
|
||||
|
||||
const AppDisplay = imports.ui.appDisplay;
|
||||
@@ -24,6 +22,7 @@ const PlaceDisplay = imports.ui.placeDisplay;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const ViewSelector = imports.ui.viewSelector;
|
||||
const WorkspacesView = imports.ui.workspacesView;
|
||||
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
|
||||
|
||||
// Time for initial animation going into Overview mode
|
||||
const ANIMATION_TIME = 0.25;
|
||||
@@ -74,11 +73,13 @@ ShellInfo.prototype = {
|
||||
Main.messageTray.add(this._source);
|
||||
}
|
||||
|
||||
let notification = this._source.notification;
|
||||
if (notification == null)
|
||||
let notification = null;
|
||||
if (this._source.notifications.length == 0) {
|
||||
notification = new MessageTray.Notification(this._source, text, null);
|
||||
else
|
||||
} else {
|
||||
notification = this._source.notifications[0];
|
||||
notification.update(text, null, { clear: true });
|
||||
}
|
||||
|
||||
notification.setTransient(true);
|
||||
|
||||
@@ -180,10 +181,10 @@ Overview.prototype = {
|
||||
this._group.add_actor(this.viewSelector.actor);
|
||||
|
||||
this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
|
||||
this.viewSelector.addViewTab(_("Windows"), this._workspacesDisplay.actor, 'text-x-generic');
|
||||
this.viewSelector.addViewTab('windows', _("Windows"), this._workspacesDisplay.actor, 'text-x-generic');
|
||||
|
||||
let appView = new AppDisplay.AllAppDisplay();
|
||||
this.viewSelector.addViewTab(_("Applications"), appView.actor, 'system-run');
|
||||
this.viewSelector.addViewTab('applications', _("Applications"), appView.actor, 'system-run');
|
||||
|
||||
// Default search providers
|
||||
this.viewSelector.addSearchProvider(new AppDisplay.AppSearchProvider());
|
||||
@@ -220,6 +221,7 @@ Overview.prototype = {
|
||||
this._resetWindowSwitchTimeout();
|
||||
this._lastHoveredWindow = null;
|
||||
DND.removeMonitor(this._dragMonitor);
|
||||
this.endItemDrag();
|
||||
},
|
||||
|
||||
_resetWindowSwitchTimeout: function() {
|
||||
@@ -242,7 +244,8 @@ Overview.prototype = {
|
||||
_onDragMotion: function(dragEvent) {
|
||||
let targetIsWindow = dragEvent.targetActor &&
|
||||
dragEvent.targetActor._delegate &&
|
||||
dragEvent.targetActor._delegate.metaWindow;
|
||||
dragEvent.targetActor._delegate.metaWindow &&
|
||||
!(dragEvent.targetActor._delegate instanceof WorkspaceThumbnail.WindowClone);
|
||||
|
||||
this._windowSwitchTimestamp = global.get_current_time();
|
||||
|
||||
@@ -438,7 +441,7 @@ Overview.prototype = {
|
||||
let primary = global.get_primary_monitor();
|
||||
let rtl = (St.Widget.get_default_direction () == St.TextDirection.RTL);
|
||||
|
||||
let contentY = Panel.PANEL_HEIGHT;
|
||||
let contentY = Main.panel.actor.height;
|
||||
let contentHeight = primary.height - contentY - Main.messageTray.actor.height;
|
||||
|
||||
this._group.set_position(primary.x, primary.y);
|
||||
@@ -473,6 +476,10 @@ Overview.prototype = {
|
||||
this.emit('item-drag-begin');
|
||||
},
|
||||
|
||||
cancelledItemDrag: function(source) {
|
||||
this.emit('item-drag-cancelled');
|
||||
},
|
||||
|
||||
endItemDrag: function(source) {
|
||||
this.emit('item-drag-end');
|
||||
},
|
||||
@@ -481,35 +488,14 @@ Overview.prototype = {
|
||||
this.emit('window-drag-begin');
|
||||
},
|
||||
|
||||
cancelledWindowDrag: function(source) {
|
||||
this.emit('window-drag-cancelled');
|
||||
},
|
||||
|
||||
endWindowDrag: function(source) {
|
||||
this.emit('window-drag-end');
|
||||
},
|
||||
|
||||
// Returns the scale the Overview has when we just start zooming out
|
||||
// to overview mode. That is, when just the active workspace is showing.
|
||||
getZoomedInScale : function() {
|
||||
return 1 / this.workspaces.getScale();
|
||||
},
|
||||
|
||||
// Returns the position the Overview has when we just start zooming out
|
||||
// to overview mode. That is, when just the active workspace is showing.
|
||||
getZoomedInPosition : function() {
|
||||
let [posX, posY] = this.workspaces.getActiveWorkspacePosition();
|
||||
let scale = this.getZoomedInScale();
|
||||
|
||||
return [- posX * scale, - posY * scale];
|
||||
},
|
||||
|
||||
// Returns the current scale of the Overview.
|
||||
getScale : function() {
|
||||
return this.workspaces.actor.scaleX;
|
||||
},
|
||||
|
||||
// Returns the current position of the Overview.
|
||||
getPosition : function() {
|
||||
return [this.workspaces.actor.x, this.workspaces.actor.y];
|
||||
},
|
||||
|
||||
// show:
|
||||
//
|
||||
// Animates the overview visible and grabs mouse and keyboard input
|
||||
@@ -563,30 +549,13 @@ Overview.prototype = {
|
||||
});
|
||||
}
|
||||
|
||||
// Create a zoom out effect. First scale the workspaces view up and
|
||||
// position it so that the active workspace fills up the whole screen,
|
||||
// then transform it to its normal dimensions and position.
|
||||
// The opposite transition is used in hide().
|
||||
this.workspaces.actor.scaleX = this.workspaces.actor.scaleY = this.getZoomedInScale();
|
||||
[this.workspaces.actor.x, this.workspaces.actor.y] = this.getZoomedInPosition();
|
||||
let primary = global.get_primary_monitor();
|
||||
Tweener.addTween(this.workspaces.actor,
|
||||
{ x: primary.x - this._group.x,
|
||||
y: primary.y - this._group.y,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
transition: 'easeOutQuad',
|
||||
time: ANIMATION_TIME,
|
||||
onComplete: this._showDone,
|
||||
onCompleteScope: this
|
||||
});
|
||||
|
||||
// Make the other elements fade in.
|
||||
this._group.opacity = 0;
|
||||
Tweener.addTween(this._group,
|
||||
{ opacity: 255,
|
||||
transition: 'easeOutQuad',
|
||||
time: ANIMATION_TIME
|
||||
time: ANIMATION_TIME,
|
||||
onComplete: this._showDone,
|
||||
onCompleteScope: this
|
||||
});
|
||||
|
||||
this._coverPane.raise_top();
|
||||
@@ -698,27 +667,13 @@ Overview.prototype = {
|
||||
|
||||
this.workspaces.hide();
|
||||
|
||||
// Create a zoom in effect by transforming the workspaces view so that
|
||||
// the active workspace fills up the whole screen. The opposite
|
||||
// transition is used in show().
|
||||
let scale = this.getZoomedInScale();
|
||||
let [posX, posY] = this.getZoomedInPosition();
|
||||
Tweener.addTween(this.workspaces.actor,
|
||||
{ x: posX,
|
||||
y: posY,
|
||||
scaleX: scale,
|
||||
scaleY: scale,
|
||||
transition: 'easeOutQuad',
|
||||
time: ANIMATION_TIME,
|
||||
onComplete: this._hideDone,
|
||||
onCompleteScope: this
|
||||
});
|
||||
|
||||
// Make other elements fade out.
|
||||
Tweener.addTween(this._group,
|
||||
{ opacity: 0,
|
||||
transition: 'easeOutQuad',
|
||||
time: ANIMATION_TIME
|
||||
time: ANIMATION_TIME,
|
||||
onComplete: this._hideDone,
|
||||
onCompleteScope: this
|
||||
});
|
||||
|
||||
this._coverPane.raise_top();
|
||||
@@ -737,6 +692,7 @@ Overview.prototype = {
|
||||
this._animateNotVisible();
|
||||
|
||||
this._syncInputMode();
|
||||
global.sync_pointer();
|
||||
},
|
||||
|
||||
_hideDone: function() {
|
||||
|
||||
247
js/ui/panel.js
@@ -9,8 +9,6 @@ const Pango = imports.gi.Pango;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const Signals = imports.signals;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Config = imports.misc.config;
|
||||
const CtrlAltTab = imports.ui.ctrlAltTab;
|
||||
@@ -22,8 +20,6 @@ const DateMenu = imports.ui.dateMenu;
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const PANEL_HEIGHT = 26;
|
||||
|
||||
const PANEL_ICON_SIZE = 24;
|
||||
|
||||
const STARTUP_ANIMATION_TIME = 0.2;
|
||||
@@ -33,8 +29,7 @@ const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5;
|
||||
const BUTTON_DND_ACTIVATION_TIMEOUT = 250;
|
||||
|
||||
const ANIMATED_ICON_UPDATE_TIMEOUT = 100;
|
||||
const SPINNER_UPDATE_TIMEOUT = 130;
|
||||
const SPINNER_SPEED = 0.02;
|
||||
const SPINNER_ANIMATION_TIME = 0.2;
|
||||
|
||||
const STANDARD_TRAY_ICON_ORDER = ['a11y', 'display', 'keyboard', 'volume', 'bluetooth', 'network', 'battery'];
|
||||
const STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION = {
|
||||
@@ -47,6 +42,12 @@ const STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION = {
|
||||
if (Config.HAVE_BLUETOOTH)
|
||||
STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['bluetooth'] = imports.ui.status.bluetooth.Indicator;
|
||||
|
||||
try {
|
||||
STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['network'] = imports.ui.status.network.NMApplet;
|
||||
} catch(e) {
|
||||
log('NMApplet is not supported. It is possible that your NetworkManager version is too old');
|
||||
}
|
||||
|
||||
// To make sure the panel corners blend nicely with the panel,
|
||||
// we draw background and borders the same way, e.g. drawing
|
||||
// them as filled shapes from the outside inwards instead of
|
||||
@@ -244,6 +245,10 @@ AppMenuButton.prototype = {
|
||||
|
||||
let bin = new St.Bin({ name: 'appMenu' });
|
||||
this.actor.set_child(bin);
|
||||
|
||||
this.actor.reactive = false;
|
||||
this._targetIsCurrent = false;
|
||||
|
||||
this._container = new Shell.GenericContainer();
|
||||
bin.set_child(this._container);
|
||||
this._container.connect('get-preferred-width', Lang.bind(this, this._getContentPreferredWidth));
|
||||
@@ -253,10 +258,14 @@ AppMenuButton.prototype = {
|
||||
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._container.add_actor(this._iconBox);
|
||||
this._label = new TextShadower();
|
||||
this._container.add_actor(this._label.actor);
|
||||
|
||||
this._iconBottomClip = 0;
|
||||
|
||||
this._quitMenu = new PopupMenu.PopupMenuItem('');
|
||||
this.menu.addMenuItem(this._quitMenu);
|
||||
this._quitMenu.connect('activate', Lang.bind(this, this._onQuit));
|
||||
@@ -271,20 +280,13 @@ AppMenuButton.prototype = {
|
||||
this.hide();
|
||||
}));
|
||||
|
||||
this._updateId = 0;
|
||||
this._animationStep = 0;
|
||||
this._clipWidth = PANEL_ICON_SIZE;
|
||||
this._direction = SPINNER_SPEED;
|
||||
this._stop = true;
|
||||
|
||||
this._spinner = new AnimatedIcon('process-working.svg',
|
||||
PANEL_ICON_SIZE);
|
||||
this._container.add_actor(this._spinner.actor);
|
||||
this._spinner.actor.lower_bottom();
|
||||
|
||||
this._shadow = new St.Bin({ style_class: 'label-real-shadow' });
|
||||
this._shadow.hide();
|
||||
this._container.add_actor(this._shadow);
|
||||
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
tracker.connect('notify::focus-app', Lang.bind(this, this._sync));
|
||||
tracker.connect('app-state-changed', Lang.bind(this, this._onAppStateChanged));
|
||||
@@ -300,6 +302,10 @@ AppMenuButton.prototype = {
|
||||
|
||||
this._visible = true;
|
||||
this.actor.show();
|
||||
|
||||
if (!this._targetIsCurrent)
|
||||
return;
|
||||
|
||||
Tweener.removeTweens(this.actor);
|
||||
Tweener.addTween(this.actor,
|
||||
{ opacity: 255,
|
||||
@@ -312,6 +318,11 @@ AppMenuButton.prototype = {
|
||||
return;
|
||||
|
||||
this._visible = false;
|
||||
if (!this._targetIsCurrent) {
|
||||
this.actor.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
Tweener.removeTweens(this.actor);
|
||||
Tweener.addTween(this.actor,
|
||||
{ opacity: 0,
|
||||
@@ -325,71 +336,40 @@ AppMenuButton.prototype = {
|
||||
|
||||
_onIconBoxStyleChanged: function() {
|
||||
let node = this._iconBox.get_theme_node();
|
||||
let bottomClip = node.get_length('app-icon-bottom-clip');
|
||||
if (bottomClip > 0)
|
||||
this._iconBottomClip = node.get_length('app-icon-bottom-clip');
|
||||
this._updateIconBoxClip();
|
||||
},
|
||||
|
||||
_updateIconBoxClip: function() {
|
||||
let allocation = this._iconBox.allocation;
|
||||
if (this._iconBottomClip > 0)
|
||||
this._iconBox.set_clip(0, 0,
|
||||
this._iconBox.width,
|
||||
this._iconBox.height - bottomClip);
|
||||
allocation.x2 - allocation.x1,
|
||||
allocation.y2 - allocation.y1 - this._iconBottomClip);
|
||||
else
|
||||
this._iconBox.remove_clip();
|
||||
},
|
||||
|
||||
_stopAnimation: function(animate) {
|
||||
this._label.actor.remove_clip();
|
||||
if (this._updateId) {
|
||||
this._shadow.hide();
|
||||
if (animate) {
|
||||
Tweener.addTween(this._spinner.actor,
|
||||
{ opacity: 0,
|
||||
time: 0.2,
|
||||
transition: "easeOutQuad",
|
||||
onCompleteScope: this,
|
||||
onComplete: function() {
|
||||
this._spinner.actor.opacity = 255;
|
||||
this._spinner.actor.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
Mainloop.source_remove(this._updateId);
|
||||
this._updateId = 0;
|
||||
}
|
||||
if (!animate)
|
||||
this._spinner.actor.hide();
|
||||
},
|
||||
|
||||
stopAnimation: function() {
|
||||
this._direction = SPINNER_SPEED * 3;
|
||||
this._stop = true;
|
||||
},
|
||||
if (this._stop)
|
||||
return;
|
||||
|
||||
_update: function() {
|
||||
this._animationStep += this._direction;
|
||||
if (this._animationStep > 1 && this._stop) {
|
||||
this._animationStep = 1;
|
||||
this._stopAnimation(true);
|
||||
return false;
|
||||
}
|
||||
if (this._animationStep > 1)
|
||||
this._animationStep = 1;
|
||||
this._clipWidth = this._label.actor.width - (this._label.actor.width - PANEL_ICON_SIZE) * (1 - this._animationStep);
|
||||
if (this.actor.get_direction() == St.TextDirection.LTR) {
|
||||
this._label.actor.set_clip(0, 0, this._clipWidth + this._shadow.width, this.actor.height);
|
||||
} else {
|
||||
this._label.actor.set_clip(this._label.actor.width - this._clipWidth, 0, this._clipWidth, this.actor.height);
|
||||
}
|
||||
this._container.queue_relayout();
|
||||
return true;
|
||||
this._stop = true;
|
||||
Tweener.addTween(this._spinner.actor,
|
||||
{ opacity: 0,
|
||||
time: SPINNER_ANIMATION_TIME,
|
||||
transition: "easeOutQuad",
|
||||
onCompleteScope: this,
|
||||
onComplete: function() {
|
||||
this._spinner.actor.opacity = 255;
|
||||
this._spinner.actor.hide();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
startAnimation: function() {
|
||||
this._direction = SPINNER_SPEED;
|
||||
this._stopAnimation(false);
|
||||
this._animationStep = 0;
|
||||
this._update();
|
||||
this._stop = false;
|
||||
this._updateId = Mainloop.timeout_add(SPINNER_UPDATE_TIMEOUT, Lang.bind(this, this._update));
|
||||
this._spinner.actor.show();
|
||||
this._shadow.show();
|
||||
},
|
||||
|
||||
_getContentPreferredWidth: function(actor, forHeight, alloc) {
|
||||
@@ -451,18 +431,13 @@ AppMenuButton.prototype = {
|
||||
this._label.actor.allocate(childBox, flags);
|
||||
|
||||
if (direction == St.TextDirection.LTR) {
|
||||
childBox.x1 = Math.floor(iconWidth / 2) + this._clipWidth + this._shadow.width;
|
||||
childBox.x1 = Math.floor(iconWidth / 2) + this._label.actor.width;
|
||||
childBox.x2 = childBox.x1 + this._spinner.actor.width;
|
||||
childBox.y1 = box.y1;
|
||||
childBox.y2 = box.y2 - 1;
|
||||
this._spinner.actor.allocate(childBox, flags);
|
||||
childBox.x1 = Math.floor(iconWidth / 2) + this._clipWidth + 2;
|
||||
childBox.x2 = childBox.x1 + this._shadow.width;
|
||||
childBox.y1 = box.y1;
|
||||
childBox.y2 = box.y2 - 1;
|
||||
this._shadow.allocate(childBox, flags);
|
||||
} else {
|
||||
childBox.x1 = this._label.actor.width - this._clipWidth - this._spinner.actor.width;
|
||||
childBox.x1 = -this._spinner.actor.width;
|
||||
childBox.x2 = childBox.x1 + this._spinner.actor.width;
|
||||
childBox.y1 = box.y1;
|
||||
childBox.y2 = box.y2 - 1;
|
||||
@@ -501,13 +476,6 @@ AppMenuButton.prototype = {
|
||||
lastStartedApp = this._startingApps[i];
|
||||
|
||||
let focusedApp = tracker.focus_app;
|
||||
let targetApp = focusedApp != null ? focusedApp : lastStartedApp;
|
||||
if (targetApp == this._targetApp) {
|
||||
if (targetApp && targetApp.get_state() != Shell.AppState.STARTING)
|
||||
this.stopAnimation();
|
||||
return;
|
||||
}
|
||||
this._stopAnimation();
|
||||
|
||||
if (!focusedApp) {
|
||||
// If the app has just lost focus to the panel, pretend
|
||||
@@ -517,27 +485,56 @@ AppMenuButton.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
let targetApp = focusedApp != null ? focusedApp : lastStartedApp;
|
||||
|
||||
if (targetApp == null) {
|
||||
if (!this._targetIsCurrent)
|
||||
return;
|
||||
|
||||
this.actor.reactive = false;
|
||||
this._targetIsCurrent = false;
|
||||
|
||||
Tweener.removeTweens(this.actor);
|
||||
Tweener.addTween(this.actor, { opacity: 0,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._targetIsCurrent) {
|
||||
this.actor.reactive = true;
|
||||
this._targetIsCurrent = true;
|
||||
|
||||
Tweener.removeTweens(this.actor);
|
||||
Tweener.addTween(this.actor, { opacity: 255,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
}
|
||||
|
||||
if (targetApp == this._targetApp) {
|
||||
if (targetApp && targetApp.get_state() != Shell.AppState.STARTING)
|
||||
this.stopAnimation();
|
||||
return;
|
||||
}
|
||||
|
||||
this._spinner.actor.hide();
|
||||
if (this._iconBox.child != null)
|
||||
this._iconBox.child.destroy();
|
||||
this._iconBox.hide();
|
||||
this._label.setText('');
|
||||
this.actor.reactive = false;
|
||||
|
||||
this._targetApp = targetApp;
|
||||
if (targetApp != null) {
|
||||
let icon = targetApp.get_faded_icon(2 * PANEL_ICON_SIZE);
|
||||
let icon = targetApp.get_faded_icon(2 * PANEL_ICON_SIZE);
|
||||
|
||||
this._label.setText(targetApp.get_name());
|
||||
// TODO - _quit() doesn't really work on apps in state STARTING yet
|
||||
this._quitMenu.label.set_text(_("Quit %s").format(targetApp.get_name()));
|
||||
this._label.setText(targetApp.get_name());
|
||||
// TODO - _quit() doesn't really work on apps in state STARTING yet
|
||||
this._quitMenu.label.set_text(_("Quit %s").format(targetApp.get_name()));
|
||||
|
||||
this.actor.reactive = true;
|
||||
this._iconBox.set_child(icon);
|
||||
this._iconBox.show();
|
||||
this._iconBox.set_child(icon);
|
||||
this._iconBox.show();
|
||||
|
||||
if (targetApp.get_state() == Shell.AppState.STARTING)
|
||||
this.startAnimation();
|
||||
}
|
||||
if (targetApp.get_state() == Shell.AppState.STARTING)
|
||||
this.startAnimation();
|
||||
|
||||
this.emit('changed');
|
||||
}
|
||||
@@ -641,12 +638,17 @@ PanelCorner.prototype = {
|
||||
* This class manages the "hot corner" that can toggle switching to
|
||||
* overview.
|
||||
*/
|
||||
function HotCorner() {
|
||||
this._init();
|
||||
function HotCorner(button) {
|
||||
this._init(button);
|
||||
}
|
||||
|
||||
HotCorner.prototype = {
|
||||
_init : function() {
|
||||
_init : function(button) {
|
||||
// This is the activities button associated with this hot corner,
|
||||
// if this is on the primary monitor (or null with the corner is
|
||||
// on a different monitor)
|
||||
this._button = button;
|
||||
|
||||
// We use this flag to mark the case where the user has entered the
|
||||
// hot corner and has not left both the hot corner and a surrounding
|
||||
// guard area (the "environs"). This avoids triggering the hot corner
|
||||
@@ -673,6 +675,8 @@ HotCorner.prototype = {
|
||||
|
||||
this._activationTime = 0;
|
||||
|
||||
this.actor.connect('enter-event',
|
||||
Lang.bind(this, this._onEnvironsEntered));
|
||||
this.actor.connect('leave-event',
|
||||
Lang.bind(this, this._onEnvironsLeft));
|
||||
// Clicking on the hot corner environs should result in the same bahavior
|
||||
@@ -725,6 +729,8 @@ HotCorner.prototype = {
|
||||
x: x,
|
||||
y: y });
|
||||
ripple._opacity = startOpacity;
|
||||
if (ripple.get_direction() == St.TextDirection.RTL)
|
||||
ripple.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
|
||||
Tweener.addTween(ripple, { _opacity: finalOpacity,
|
||||
scale_x: finalScale,
|
||||
scale_y: finalScale,
|
||||
@@ -747,6 +753,11 @@ HotCorner.prototype = {
|
||||
this._addRipple(0.35, 1.0, 0.0, 0.3, 1, 0.0);
|
||||
},
|
||||
|
||||
_onEnvironsEntered : function() {
|
||||
if (this._button)
|
||||
this._button.hover = true;
|
||||
},
|
||||
|
||||
_onCornerEntered : function() {
|
||||
if (!this._entered) {
|
||||
this._entered = true;
|
||||
@@ -774,6 +785,9 @@ HotCorner.prototype = {
|
||||
},
|
||||
|
||||
_onEnvironsLeft : function(actor, event) {
|
||||
if (this._button)
|
||||
this._button.hover = false;
|
||||
|
||||
if (event.get_related() != this._corner)
|
||||
this._entered = false;
|
||||
return false;
|
||||
@@ -801,6 +815,8 @@ Panel.prototype = {
|
||||
reactive: true });
|
||||
this.actor._delegate = this;
|
||||
|
||||
this._statusArea = {};
|
||||
|
||||
Main.overview.connect('shown', Lang.bind(this, function () {
|
||||
this.actor.add_style_class_name('in-overview');
|
||||
}));
|
||||
@@ -808,6 +824,8 @@ Panel.prototype = {
|
||||
this.actor.remove_style_class_name('in-overview');
|
||||
}));
|
||||
|
||||
this._leftPointerBarrier = 0;
|
||||
this._rightPointerBarrier = 0;
|
||||
this._menus = new PopupMenu.PopupMenuManager(this);
|
||||
|
||||
this._leftBox = new St.BoxLayout({ name: 'panelLeft' });
|
||||
@@ -895,6 +913,7 @@ Panel.prototype = {
|
||||
style_class: 'panel-button',
|
||||
reactive: true,
|
||||
can_focus: true });
|
||||
this._activities = this.button;
|
||||
this.button.set_child(label);
|
||||
this.button._delegate = this.button;
|
||||
this.button._xdndTimeOut = 0;
|
||||
@@ -923,10 +942,10 @@ Panel.prototype = {
|
||||
|
||||
this._hotCorner = null;
|
||||
|
||||
let appMenuButton = new AppMenuButton();
|
||||
this._leftBox.add(appMenuButton.actor);
|
||||
this._appMenu = new AppMenuButton();
|
||||
this._leftBox.add(this._appMenu.actor);
|
||||
|
||||
this._menus.addMenu(appMenuButton.menu);
|
||||
this._menus.addMenu(this._appMenu.menu);
|
||||
|
||||
/* center */
|
||||
this._dateMenu = new DateMenu.DateMenuButton();
|
||||
@@ -945,12 +964,12 @@ Panel.prototype = {
|
||||
this._rightBox.add(this._trayBox);
|
||||
this._rightBox.add(this._statusBox);
|
||||
|
||||
this._statusmenu = new StatusMenu.StatusMenuButton();
|
||||
this._statusmenu.actor.name = 'panelStatus';
|
||||
this._rightBox.add(this._statusmenu.actor);
|
||||
this._userMenu = new StatusMenu.StatusMenuButton();
|
||||
this._userMenu.actor.name = 'panelStatus';
|
||||
this._rightBox.add(this._userMenu.actor);
|
||||
|
||||
// Synchronize the buttons pseudo classes with its corner
|
||||
this._statusmenu.actor.connect('style-changed', Lang.bind(this,
|
||||
this._userMenu.actor.connect('style-changed', Lang.bind(this,
|
||||
function(actor) {
|
||||
let rtl = actor.get_direction() == St.TextDirection.RTL;
|
||||
let corner = rtl ? this._leftCorner : this._rightCorner;
|
||||
@@ -991,7 +1010,7 @@ Panel.prototype = {
|
||||
affectsStruts: false,
|
||||
affectsInputRegion: false });
|
||||
|
||||
Main.ctrlAltTabManager.addGroup(this.actor, _("Panel"), 'start-here',
|
||||
Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'start-here',
|
||||
{ sortGroup: CtrlAltTab.SortGroup.TOP });
|
||||
},
|
||||
|
||||
@@ -1033,11 +1052,13 @@ Panel.prototype = {
|
||||
let indicator = new constructor();
|
||||
this._statusBox.add(indicator.actor);
|
||||
this._menus.addMenu(indicator.menu);
|
||||
|
||||
this._statusArea[role] = indicator;
|
||||
}
|
||||
|
||||
// PopupMenuManager depends on menus being added in order for
|
||||
// keyboard navigation
|
||||
this._menus.addMenu(this._statusmenu.menu);
|
||||
this._menus.addMenu(this._userMenu.menu);
|
||||
},
|
||||
|
||||
startupAnimation: function() {
|
||||
@@ -1068,7 +1089,21 @@ Panel.prototype = {
|
||||
let primary = global.get_primary_monitor();
|
||||
|
||||
this.actor.set_position(primary.x, primary.y);
|
||||
this.actor.set_size(primary.width, PANEL_HEIGHT);
|
||||
this.actor.set_size(primary.width, -1);
|
||||
|
||||
if (this._leftPointerBarrier)
|
||||
global.destroy_pointer_barrier(this._leftPointerBarrier);
|
||||
if (this._rightPointerBarrier)
|
||||
global.destroy_pointer_barrier(this._rightPointerBarrier);
|
||||
|
||||
this._leftPointerBarrier =
|
||||
global.create_pointer_barrier(primary.x, primary.y,
|
||||
primary.x, primary.y + this.actor.height,
|
||||
1 /* BarrierPositiveX */);
|
||||
this._rightPointerBarrier =
|
||||
global.create_pointer_barrier(primary.x + primary.width, primary.y,
|
||||
primary.x + primary.width, primary.y + this.actor.height,
|
||||
4 /* BarrierNegativeX */);
|
||||
|
||||
this._leftCorner.relayout();
|
||||
this._rightCorner.relayout();
|
||||
|
||||
@@ -32,6 +32,15 @@ Button.prototype = {
|
||||
},
|
||||
|
||||
_onButtonPress: function(actor, event) {
|
||||
if (!this.menu.isOpen) {
|
||||
// Setting the max-height won't do any good if the minimum height of the
|
||||
// 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 monitor = global.get_primary_monitor();
|
||||
this.menu.actor.style = ('max-height: ' +
|
||||
Math.round(monitor.height - Main.panel.actor.height) +
|
||||
'px;');
|
||||
}
|
||||
this.menu.toggle();
|
||||
},
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
const Main = imports.ui.main;
|
||||
@@ -176,37 +174,8 @@ PlacesManager.prototype = {
|
||||
Util.spawn(['nautilus-connect-server']);
|
||||
});
|
||||
|
||||
let networkApp = null;
|
||||
try {
|
||||
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('gnome-network-scheme.desktop');
|
||||
} catch(e) {
|
||||
try {
|
||||
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('network-scheme.desktop');
|
||||
} catch(e) {
|
||||
log('Cannot create "Network" item, .desktop file not found or corrupt.');
|
||||
}
|
||||
}
|
||||
|
||||
if (networkApp != null) {
|
||||
this._network = new PlaceInfo('special:network', networkApp.get_name(),
|
||||
function(size) {
|
||||
return networkApp.create_icon_texture(size);
|
||||
},
|
||||
function (params) {
|
||||
params = Params.parse(params, { workspace: null,
|
||||
timestamp: 0 });
|
||||
|
||||
networkApp.launch_full(params.timestamp, [],
|
||||
params.workspace ? params.workspace.index() : -1);
|
||||
});
|
||||
}
|
||||
|
||||
this._defaultPlaces.push(this._home);
|
||||
this._defaultPlaces.push(this._desktopMenu);
|
||||
|
||||
if (this._network)
|
||||
this._defaultPlaces.push(this._network);
|
||||
|
||||
this._defaultPlaces.push(this._connect);
|
||||
|
||||
/*
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const St = imports.gi.St;
|
||||
@@ -49,6 +47,8 @@ AuthenticationDialog.prototype = {
|
||||
this.actionId = actionId;
|
||||
this.message = message;
|
||||
this.userNames = userNames;
|
||||
this._wasDismissed = false;
|
||||
this._completed = false;
|
||||
|
||||
let mainContentBox = new St.BoxLayout({ style_class: 'polkit-dialog-main-layout',
|
||||
vertical: false });
|
||||
@@ -69,7 +69,7 @@ AuthenticationDialog.prototype = {
|
||||
{ y_align: St.Align.START });
|
||||
|
||||
this._subjectLabel = new St.Label({ style_class: 'polkit-dialog-headline',
|
||||
text: _('Authentication Required') });
|
||||
text: _("Authentication Required") });
|
||||
|
||||
messageBox.add(this._subjectLabel,
|
||||
{ y_fill: false,
|
||||
@@ -100,32 +100,35 @@ AuthenticationDialog.prototype = {
|
||||
Lang.bind(this, this._onUserChanged));
|
||||
|
||||
// Special case 'root'
|
||||
if (userName == 'root')
|
||||
userRealName = _('Administrator');
|
||||
let userIsRoot = false;
|
||||
if (userName == 'root') {
|
||||
userIsRoot = true;
|
||||
userRealName = _("Administrator");
|
||||
}
|
||||
|
||||
// Work around Gdm.UserManager returning an empty string for the real name
|
||||
if (userRealName.length == 0)
|
||||
userRealName = userName;
|
||||
|
||||
let userBox = new St.BoxLayout({ style_class: 'polkit-dialog-user-layout',
|
||||
vertical: false });
|
||||
messageBox.add(userBox);
|
||||
|
||||
this._userIcon = new St.Icon();
|
||||
this._userIcon.hide();
|
||||
userBox.add(this._userIcon,
|
||||
{ x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.START });
|
||||
|
||||
let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-label',
|
||||
text: userRealName }));
|
||||
userBox.add(userLabel,
|
||||
{ x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.MIDDLE });
|
||||
if (userIsRoot) {
|
||||
let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-root-label',
|
||||
text: userRealName }));
|
||||
messageBox.add(userLabel);
|
||||
} else {
|
||||
let userBox = new St.BoxLayout({ style_class: 'polkit-dialog-user-layout',
|
||||
vertical: false });
|
||||
messageBox.add(userBox);
|
||||
this._userIcon = new St.Icon();
|
||||
this._userIcon.hide();
|
||||
userBox.add(this._userIcon,
|
||||
{ x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.START });
|
||||
let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-label',
|
||||
text: userRealName }));
|
||||
userBox.add(userLabel,
|
||||
{ x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.MIDDLE });
|
||||
}
|
||||
|
||||
this._onUserChanged();
|
||||
|
||||
@@ -134,45 +137,41 @@ AuthenticationDialog.prototype = {
|
||||
this._passwordLabel = new St.Label(({ style_class: 'polkit-dialog-password-label' }));
|
||||
this._passwordBox.add(this._passwordLabel);
|
||||
this._passwordEntry = new St.Entry({ style_class: 'polkit-dialog-password-entry',
|
||||
text: _(''),
|
||||
text: "",
|
||||
can_focus: true});
|
||||
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivate));
|
||||
this._passwordBox.add(this._passwordEntry,
|
||||
{expand: true });
|
||||
this._passwordBox.hide();
|
||||
|
||||
this._errorBox = new St.BoxLayout({ style_class: 'polkit-dialog-error-box' });
|
||||
messageBox.add(this._errorBox);
|
||||
let errorIcon = new St.Icon({ icon_name: 'dialog-error',
|
||||
icon_size: 24,
|
||||
style_class: 'polkit-dialog-error-icon' });
|
||||
this._errorBox.add(errorIcon, { y_align: St.Align.MIDDLE });
|
||||
this._errorMessage = new St.Label({ style_class: 'polkit-dialog-error-label' });
|
||||
this._errorMessage.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
this._errorMessage.clutter_text.line_wrap = true;
|
||||
this._errorBox.add(this._errorMessage, { expand: true,
|
||||
y_align: St.Align.MIDDLE,
|
||||
y_fill: true });
|
||||
this._errorBox.hide();
|
||||
this._errorMessageLabel = new St.Label({ style_class: 'polkit-dialog-error-label' });
|
||||
this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
this._errorMessageLabel.clutter_text.line_wrap = true;
|
||||
messageBox.add(this._errorMessageLabel);
|
||||
this._errorMessageLabel.hide();
|
||||
|
||||
this._infoBox = new St.BoxLayout({ style_class: 'polkit-dialog-info-box' });
|
||||
messageBox.add(this._infoBox);
|
||||
let infoIcon = new St.Icon({ icon_name: 'dialog-information',
|
||||
icon_size: 24,
|
||||
style_class: 'polkit-dialog-info-icon' });
|
||||
this._infoBox.add(infoIcon, { y_align: St.Align.MIDDLE });
|
||||
this._infoMessage = new St.Label({ style_class: 'polkit-dialog-info-label'});
|
||||
this._infoMessage.clutter_text.line_wrap = true;
|
||||
this._infoBox.add(this._infoMessage, { expand: true,
|
||||
y_align: St.Align.MIDDLE,
|
||||
y_fill: true });
|
||||
this._infoBox.hide();
|
||||
this._infoMessageLabel = new St.Label({ style_class: 'polkit-dialog-info-label' });
|
||||
this._infoMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
this._infoMessageLabel.clutter_text.line_wrap = true;
|
||||
messageBox.add(this._infoMessageLabel);
|
||||
this._infoMessageLabel.hide();
|
||||
|
||||
this.setButtons([{ label: _('Cancel'),
|
||||
/* text is intentionally non-blank otherwise the height is not the same as for
|
||||
* infoMessage and errorMessageLabel - but it is still invisible because
|
||||
* gnome-shell.css sets the color to be transparent
|
||||
*/
|
||||
this._nullMessageLabel = new St.Label({ style_class: 'polkit-dialog-null-label',
|
||||
text: 'abc'});
|
||||
this._nullMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
this._nullMessageLabel.clutter_text.line_wrap = true;
|
||||
messageBox.add(this._nullMessageLabel);
|
||||
this._nullMessageLabel.show();
|
||||
|
||||
this.setButtons([{ label: _("Cancel"),
|
||||
action: Lang.bind(this, this.cancel),
|
||||
key: Clutter.Escape
|
||||
},
|
||||
{ label: _('Authenticate'),
|
||||
{ label: _("Authenticate"),
|
||||
action: Lang.bind(this, this._onAuthenticateButtonPressed)
|
||||
}]);
|
||||
|
||||
@@ -234,8 +233,9 @@ AuthenticationDialog.prototype = {
|
||||
this._session.response(response);
|
||||
// When the user responds, dismiss already shown info and
|
||||
// error texts (if any)
|
||||
this._errorBox.hide();
|
||||
this._infoBox.hide();
|
||||
this._errorMessageLabel.hide();
|
||||
this._infoMessageLabel.hide();
|
||||
this._nullMessageLabel.show();
|
||||
},
|
||||
|
||||
_onAuthenticateButtonPressed: function() {
|
||||
@@ -243,14 +243,35 @@ AuthenticationDialog.prototype = {
|
||||
},
|
||||
|
||||
_onSessionCompleted: function(session, gainedAuthorization) {
|
||||
this._passwordBox.hide();
|
||||
if (this._completed)
|
||||
return;
|
||||
|
||||
this._completed = true;
|
||||
|
||||
if (!gainedAuthorization) {
|
||||
/* Unless we are showing an existing error message from the PAM
|
||||
* module (the PAM module could be reporting the authentication
|
||||
* error providing authentication-method specific information),
|
||||
* show "Sorry, that didn't work. Please try again."
|
||||
*/
|
||||
if (!this._errorMessageLabel.visible && !this._wasDismissed) {
|
||||
/* Translators: "that didn't work" refers to the fact that the
|
||||
* requested authentication was not gained; this can happen
|
||||
* because of an authentication error (like invalid password),
|
||||
* for instance. */
|
||||
this._errorMessageLabel.set_text(_("Sorry, that didn\'t work. Please try again."));
|
||||
this._errorMessageLabel.show();
|
||||
this._infoMessageLabel.hide();
|
||||
this._nullMessageLabel.hide();
|
||||
}
|
||||
}
|
||||
this._emitDone(!gainedAuthorization, false);
|
||||
},
|
||||
|
||||
_onSessionRequest: function(session, request, echo_on) {
|
||||
// Cheap localization trick
|
||||
if (request == 'Password:')
|
||||
this._passwordLabel.set_text(_('Password:'));
|
||||
this._passwordLabel.set_text(_("Password:"));
|
||||
else
|
||||
this._passwordLabel.set_text(request);
|
||||
|
||||
@@ -267,41 +288,49 @@ AuthenticationDialog.prototype = {
|
||||
|
||||
_onSessionShowError: function(session, text) {
|
||||
this._passwordEntry.set_text('');
|
||||
this._errorMessage.set_text(text);
|
||||
this._errorBox.show();
|
||||
this._errorMessageLabel.set_text(text);
|
||||
this._errorMessageLabel.show();
|
||||
this._infoMessageLabel.hide();
|
||||
this._nullMessageLabel.hide();
|
||||
this._ensureOpen();
|
||||
},
|
||||
|
||||
_onSessionShowInfo: function(session, text) {
|
||||
this._passwordEntry.set_text('');
|
||||
this._infoMessage.set_text(text);
|
||||
this._infoBox.show();
|
||||
this._infoMessageLabel.set_text(text);
|
||||
this._infoMessageLabel.show();
|
||||
this._errorMessageLabel.hide();
|
||||
this._nullMessageLabel.hide();
|
||||
this._ensureOpen();
|
||||
},
|
||||
|
||||
destroySession: function() {
|
||||
if (this._session) {
|
||||
this._session.cancel();
|
||||
if (!this._completed)
|
||||
this._session.cancel();
|
||||
this._session = null;
|
||||
}
|
||||
},
|
||||
|
||||
_onUserChanged: function() {
|
||||
if (this._user.is_loaded) {
|
||||
let iconFileName = this._user.get_icon_file();
|
||||
let iconFile = Gio.file_new_for_path(iconFileName);
|
||||
let icon;
|
||||
if (iconFile.query_exists(null)) {
|
||||
icon = new Gio.FileIcon({file: iconFile});
|
||||
} else {
|
||||
icon = new Gio.ThemedIcon({name: 'avatar-default'});
|
||||
if (this._userIcon) {
|
||||
let iconFileName = this._user.get_icon_file();
|
||||
let iconFile = Gio.file_new_for_path(iconFileName);
|
||||
let icon;
|
||||
if (iconFile.query_exists(null)) {
|
||||
icon = new Gio.FileIcon({file: iconFile});
|
||||
} else {
|
||||
icon = new Gio.ThemedIcon({name: 'avatar-default'});
|
||||
}
|
||||
this._userIcon.set_gicon (icon);
|
||||
this._userIcon.show();
|
||||
}
|
||||
this._userIcon.set_gicon (icon);
|
||||
this._userIcon.show();
|
||||
}
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
this._wasDismissed = true;
|
||||
this.close(global.get_current_time());
|
||||
this._emitDone(false, true);
|
||||
},
|
||||
|
||||
@@ -13,9 +13,6 @@ const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const SLIDER_SCROLL_STEP = 0.05; /* Slider scrolling step in % */
|
||||
|
||||
function PopupBaseMenuItem(params) {
|
||||
@@ -61,7 +58,7 @@ PopupBaseMenuItem.prototype = {
|
||||
},
|
||||
|
||||
_onStyleChanged: function (actor) {
|
||||
this._spacing = actor.get_theme_node().get_length('spacing');
|
||||
this._spacing = Math.round(actor.get_theme_node().get_length('spacing'));
|
||||
},
|
||||
|
||||
_onButtonReleaseEvent: function (actor, event) {
|
||||
@@ -173,6 +170,8 @@ PopupBaseMenuItem.prototype = {
|
||||
cr.fill();
|
||||
},
|
||||
|
||||
// This returns column widths in logical order (i.e. from the dot
|
||||
// to the image), not in visual order (left to right)
|
||||
getColumnWidths: function() {
|
||||
let widths = [];
|
||||
for (let i = 0, col = 0; i < this._children.length; i++) {
|
||||
@@ -224,19 +223,36 @@ PopupBaseMenuItem.prototype = {
|
||||
|
||||
_allocate: function(actor, box, flags) {
|
||||
let height = box.y2 - box.y1;
|
||||
let direction = this.actor.get_direction();
|
||||
|
||||
if (this._dot) {
|
||||
// The dot is placed outside box
|
||||
// one quarter of padding from the border of the container
|
||||
// (so 3/4 from the inner border)
|
||||
// (padding is box.x1)
|
||||
let dotBox = new Clutter.ActorBox();
|
||||
let dotWidth = Math.round(box.x1 / 2);
|
||||
|
||||
dotBox.x1 = Math.round(box.x1 / 4);
|
||||
dotBox.x2 = dotBox.x1 + dotWidth;
|
||||
if (direction == St.TextDirection.LTR) {
|
||||
dotBox.x1 = Math.round(box.x1 / 4);
|
||||
dotBox.x2 = dotBox.x1 + dotWidth;
|
||||
} else {
|
||||
dotBox.x2 = box.x2 + 3 * Math.round(box.x1 / 4);
|
||||
dotBox.x1 = dotBox.x2 - dotWidth;
|
||||
}
|
||||
dotBox.y1 = Math.round(box.y1 + (height - dotWidth) / 2);
|
||||
dotBox.y2 = dotBox.y1 + dotWidth;
|
||||
this._dot.allocate(dotBox, flags);
|
||||
}
|
||||
|
||||
let x = box.x1;
|
||||
let x;
|
||||
if (direction == St.TextDirection.LTR)
|
||||
x = box.x1;
|
||||
else
|
||||
x = box.x2;
|
||||
// if direction is ltr, x is the right edge of the last added
|
||||
// actor, and it's constantly increasing, whereas if rtl, x is
|
||||
// the left edge and it decreases
|
||||
for (let i = 0, col = 0; i < this._children.length; i++) {
|
||||
let child = this._children[i];
|
||||
let childBox = new Clutter.ActorBox();
|
||||
@@ -244,9 +260,12 @@ PopupBaseMenuItem.prototype = {
|
||||
let [minWidth, naturalWidth] = child.actor.get_preferred_width(-1);
|
||||
let availWidth, extraWidth;
|
||||
if (this._columnWidths) {
|
||||
if (child.span == -1)
|
||||
availWidth = box.x2 - x;
|
||||
else {
|
||||
if (child.span == -1) {
|
||||
if (direction == St.TextDirection.LTR)
|
||||
availWidth = box.x2 - x;
|
||||
else
|
||||
availWidth = x - box.x1;
|
||||
} else {
|
||||
availWidth = 0;
|
||||
for (let j = 0; j < child.span; j++)
|
||||
availWidth += this._columnWidths[col++];
|
||||
@@ -257,18 +276,36 @@ PopupBaseMenuItem.prototype = {
|
||||
extraWidth = 0;
|
||||
}
|
||||
|
||||
if (child.expand) {
|
||||
childBox.x1 = x;
|
||||
childBox.x2 = x + availWidth;
|
||||
} else if (child.align === St.Align.CENTER) {
|
||||
childBox.x1 = x + Math.round(extraWidth / 2);
|
||||
childBox.x2 = childBox.x1 + naturalWidth;
|
||||
} else if (child.align === St.Align.END) {
|
||||
childBox.x2 = x + availWidth;
|
||||
childBox.x1 = childBox.x2 - naturalWidth;
|
||||
if (direction == St.TextDirection.LTR) {
|
||||
if (child.expand) {
|
||||
childBox.x1 = x;
|
||||
childBox.x2 = x + availWidth;
|
||||
} else if (child.align === St.Align.CENTER) {
|
||||
childBox.x1 = x + Math.round(extraWidth / 2);
|
||||
childBox.x2 = childBox.x1 + naturalWidth;
|
||||
} else if (child.align === St.Align.END) {
|
||||
childBox.x2 = x + availWidth;
|
||||
childBox.x1 = childBox.x2 - naturalWidth;
|
||||
} else {
|
||||
childBox.x1 = x;
|
||||
childBox.x2 = x + naturalWidth;
|
||||
}
|
||||
} else {
|
||||
childBox.x1 = x;
|
||||
childBox.x2 = x + naturalWidth;
|
||||
if (child.expand) {
|
||||
childBox.x1 = x - availWidth;
|
||||
childBox.x2 = x;
|
||||
} else if (child.align === St.Align.CENTER) {
|
||||
childBox.x1 = x - Math.round(extraWidth / 2);
|
||||
childBox.x2 = childBox.x1 + naturalWidth;
|
||||
} else if (child.align === St.Align.END) {
|
||||
// align to the left
|
||||
childBox.x1 = x - availWidth;
|
||||
childBox.x2 = childBox.x1 + naturalWidth;
|
||||
} else {
|
||||
// align to the right
|
||||
childBox.x2 = x;
|
||||
childBox.x1 = x - naturalWidth;
|
||||
}
|
||||
}
|
||||
|
||||
let [minHeight, naturalHeight] = child.actor.get_preferred_height(-1);
|
||||
@@ -277,7 +314,10 @@ PopupBaseMenuItem.prototype = {
|
||||
|
||||
child.actor.allocate(childBox, flags);
|
||||
|
||||
x += availWidth + this._spacing;
|
||||
if (direction == St.TextDirection.LTR)
|
||||
x += availWidth + this._spacing;
|
||||
else
|
||||
x -= availWidth + this._spacing;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -455,7 +495,7 @@ PopupSliderMenuItem.prototype = {
|
||||
this._slider = new St.DrawingArea({ style_class: 'popup-slider-menu-item', reactive: true });
|
||||
this.addActor(this._slider, { span: -1, expand: true });
|
||||
this._slider.connect('repaint', Lang.bind(this, this._sliderRepaint));
|
||||
this._slider.connect('button-press-event', Lang.bind(this, this._startDragging));
|
||||
this.actor.connect('button-press-event', Lang.bind(this, this._startDragging));
|
||||
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
|
||||
|
||||
this._releaseId = this._motionId = 0;
|
||||
@@ -485,12 +525,30 @@ PopupSliderMenuItem.prototype = {
|
||||
let sliderBorderColor = themeNode.get_color('-slider-border-color');
|
||||
let sliderColor = themeNode.get_color('-slider-background-color');
|
||||
|
||||
let sliderActiveBorderColor = themeNode.get_color('-slider-active-border-color');
|
||||
let sliderActiveColor = themeNode.get_color('-slider-active-background-color');
|
||||
|
||||
cr.setSourceRGBA (
|
||||
sliderActiveColor.red / 255,
|
||||
sliderActiveColor.green / 255,
|
||||
sliderActiveColor.blue / 255,
|
||||
sliderActiveColor.alpha / 255);
|
||||
cr.rectangle(handleRadius, (height - sliderHeight) / 2, sliderWidth * this._value, sliderHeight);
|
||||
cr.fillPreserve();
|
||||
cr.setSourceRGBA (
|
||||
sliderActiveBorderColor.red / 255,
|
||||
sliderActiveBorderColor.green / 255,
|
||||
sliderActiveBorderColor.blue / 255,
|
||||
sliderActiveBorderColor.alpha / 255);
|
||||
cr.setLineWidth(sliderBorderWidth);
|
||||
cr.stroke();
|
||||
|
||||
cr.setSourceRGBA (
|
||||
sliderColor.red / 255,
|
||||
sliderColor.green / 255,
|
||||
sliderColor.blue / 255,
|
||||
sliderColor.alpha / 255);
|
||||
cr.rectangle(handleRadius, (height - sliderHeight) / 2, sliderWidth, sliderHeight);
|
||||
cr.rectangle(handleRadius + sliderWidth * this._value, (height - sliderHeight) / 2, sliderWidth * (1 - this._value), sliderHeight);
|
||||
cr.fillPreserve();
|
||||
cr.setSourceRGBA (
|
||||
sliderBorderColor.red / 255,
|
||||
@@ -704,8 +762,19 @@ PopupMenuBase.prototype = {
|
||||
} else {
|
||||
this.box = new St.BoxLayout({ vertical: true });
|
||||
}
|
||||
this.box.connect_after('queue-relayout', Lang.bind(this, this._menuQueueRelayout));
|
||||
this.length = 0;
|
||||
|
||||
this.isOpen = false;
|
||||
|
||||
// If set, we don't send events (including crossing events) to the source actor
|
||||
// for the menu which causes its prelight state to freeze
|
||||
this.blockSourceEvents = false;
|
||||
|
||||
// Can be set while a menu is up to let all events through without special
|
||||
// menu handling useful for scrollbars in menus, and probably not otherwise.
|
||||
this.passEvents = false;
|
||||
|
||||
this._activeMenuItem = null;
|
||||
},
|
||||
|
||||
@@ -784,6 +853,8 @@ PopupMenuBase.prototype = {
|
||||
menuItem.connect('destroy', Lang.bind(this, function() {
|
||||
menuItem.disconnect(menuItem._subMenuActivateId);
|
||||
menuItem.disconnect(menuItem._subMenuActiveChangeId);
|
||||
|
||||
this.length--;
|
||||
}));
|
||||
} else if (menuItem instanceof PopupSubMenuMenuItem) {
|
||||
if (before_item == null)
|
||||
@@ -800,12 +871,16 @@ PopupMenuBase.prototype = {
|
||||
this._connectItemSignals(menuItem);
|
||||
else
|
||||
throw TypeError("Invalid argument to PopupMenuBase.addMenuItem()");
|
||||
|
||||
this.length++;
|
||||
},
|
||||
|
||||
getColumnWidths: function() {
|
||||
let columnWidths = [];
|
||||
let items = this.box.get_children();
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (!items[i].visible)
|
||||
continue;
|
||||
if (items[i]._delegate instanceof PopupBaseMenuItem || items[i]._delegate instanceof PopupMenuBase) {
|
||||
let itemColumnWidths = items[i]._delegate.getColumnWidths();
|
||||
for (let j = 0; j < itemColumnWidths.length; j++) {
|
||||
@@ -825,6 +900,16 @@ PopupMenuBase.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
// Because of the above column-width funniness, we need to do a
|
||||
// queue-relayout on every item whenever the menu itself changes
|
||||
// size, to force clutter to drop its cached size requests. (The
|
||||
// menuitems will in turn call queue_relayout on their parent, the
|
||||
// menu, but that call will be a no-op since the menu already
|
||||
// has a relayout queued, so we won't get stuck in a loop.
|
||||
_menuQueueRelayout: function() {
|
||||
this.box.get_children().map(function (actor) { actor.queue_relayout(); });
|
||||
},
|
||||
|
||||
addActor: function(actor) {
|
||||
this.box.add(actor);
|
||||
},
|
||||
@@ -959,45 +1044,109 @@ PopupSubMenu.prototype = {
|
||||
__proto__: PopupMenuBase.prototype,
|
||||
|
||||
_init: function(sourceActor, sourceArrow) {
|
||||
PopupMenuBase.prototype._init.call(this, sourceActor, 'popup-sub-menu');
|
||||
PopupMenuBase.prototype._init.call(this, sourceActor);
|
||||
|
||||
this._arrow = sourceArrow;
|
||||
this._arrow.rotation_center_z_gravity = Clutter.Gravity.CENTER;
|
||||
|
||||
this.actor = this.box;
|
||||
// Since a function of a submenu might be to provide a "More.." expander
|
||||
// with long content, we make it scrollable - the scrollbar will only take
|
||||
// effect if a CSS max-height is set on the top menu.
|
||||
this.actor = new St.ScrollView({ style_class: 'popup-sub-menu',
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER,
|
||||
vscrollbar_policy: Gtk.PolicyType.NEVER });
|
||||
|
||||
// StScrollbar plays dirty tricks with events, calling
|
||||
// clutter_set_motion_events_enabled (FALSE) during the scroll; this
|
||||
// confuses our event tracking, so we just turn it off during the
|
||||
// scroll.
|
||||
let vscroll = this.actor.get_vscroll_bar();
|
||||
vscroll.connect('scroll-start',
|
||||
Lang.bind(this, function() {
|
||||
let topMenu = this._getTopMenu();
|
||||
if (topMenu)
|
||||
topMenu.passEvents = true;
|
||||
}));
|
||||
vscroll.connect('scroll-stop',
|
||||
Lang.bind(this, function() {
|
||||
let topMenu = this._getTopMenu();
|
||||
if (topMenu)
|
||||
topMenu.passEvents = false;
|
||||
}));
|
||||
|
||||
this.actor.add_actor(this.box);
|
||||
this.actor._delegate = this;
|
||||
this.actor.clip_to_allocation = true;
|
||||
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
|
||||
this.actor.hide();
|
||||
},
|
||||
|
||||
_getTopMenu: function() {
|
||||
let actor = this.actor.get_parent();
|
||||
while (actor) {
|
||||
if (actor._delegate && actor._delegate instanceof PopupMenu)
|
||||
return actor._delegate;
|
||||
|
||||
actor = actor.get_parent();
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
_needsScrollbar: function() {
|
||||
let topMenu = this._getTopMenu();
|
||||
let [topMinHeight, topNaturalHeight] = topMenu.actor.get_preferred_height(-1);
|
||||
let topThemeNode = topMenu.actor.get_theme_node();
|
||||
|
||||
let topMaxHeight = topThemeNode.get_max_height();
|
||||
return topMaxHeight >= 0 && topNaturalHeight >= topMaxHeight;
|
||||
},
|
||||
|
||||
open: function(animate) {
|
||||
if (this.isOpen)
|
||||
return;
|
||||
|
||||
this.isOpen = true;
|
||||
|
||||
// we don't implement the !animate case because that doesn't
|
||||
// currently get used...
|
||||
|
||||
let [naturalHeight, minHeight] = this.actor.get_preferred_height(-1);
|
||||
this.actor.height = 0;
|
||||
this.actor.show();
|
||||
this.actor._arrow_rotation = this._arrow.rotation_angle_z;
|
||||
Tweener.addTween(this.actor,
|
||||
{ _arrow_rotation: 90,
|
||||
height: naturalHeight,
|
||||
time: 0.25,
|
||||
onUpdateScope: this,
|
||||
onUpdate: function() {
|
||||
this._arrow.rotation_angle_z = this.actor._arrow_rotation;
|
||||
},
|
||||
onCompleteScope: this,
|
||||
onComplete: function() {
|
||||
this.actor.set_height(-1);
|
||||
this.emit('open-state-changed', true);
|
||||
}
|
||||
});
|
||||
|
||||
let needsScrollbar = this._needsScrollbar();
|
||||
|
||||
// St.ScrollView always requests space horizontally for a possible vertical
|
||||
// scrollbar if in AUTOMATIC mode. Doing better would require implementation
|
||||
// of width-for-height in St.BoxLayout and St.ScrollView. This looks bad
|
||||
// when we *don't* need it, so turn off the scrollbar when that's true.
|
||||
// Dynamic changes in whether we need it aren't handled properly.
|
||||
this.actor.vscrollbar_policy =
|
||||
needsScrollbar ? Gtk.PolicyType.AUTOMATIC : Gtk.PolicyType.NEVER;
|
||||
|
||||
// It looks funny if we animate with a scrollbar (at what point is
|
||||
// the scrollbar added?) so just skip that case
|
||||
if (animate && needsScrollbar)
|
||||
animate = false;
|
||||
|
||||
if (animate) {
|
||||
let [minHeight, naturalHeight] = this.actor.get_preferred_height(-1);
|
||||
this.actor.height = 0;
|
||||
this.actor._arrow_rotation = this._arrow.rotation_angle_z;
|
||||
Tweener.addTween(this.actor,
|
||||
{ _arrow_rotation: 90,
|
||||
height: naturalHeight,
|
||||
time: 0.25,
|
||||
onUpdateScope: this,
|
||||
onUpdate: function() {
|
||||
this._arrow.rotation_angle_z = this.actor._arrow_rotation;
|
||||
},
|
||||
onCompleteScope: this,
|
||||
onComplete: function() {
|
||||
this.actor.set_height(-1);
|
||||
this.emit('open-state-changed', true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this._arrow.rotation_angle_z = 90;
|
||||
this.emit('open-state-changed', true);
|
||||
}
|
||||
},
|
||||
|
||||
close: function(animate) {
|
||||
@@ -1009,6 +1158,9 @@ PopupSubMenu.prototype = {
|
||||
if (this._activeMenuItem)
|
||||
this._activeMenuItem.setActive(false);
|
||||
|
||||
if (animate && this._needsScrollbar())
|
||||
animate = false;
|
||||
|
||||
if (animate) {
|
||||
this.actor._arrow_rotation = this._arrow.rotation_angle_z;
|
||||
Tweener.addTween(this.actor,
|
||||
@@ -1311,14 +1463,20 @@ PopupMenuManager.prototype = {
|
||||
return this._activeMenuContains(event.get_source());
|
||||
},
|
||||
|
||||
_eventIsOnAnyMenuSource: function(event) {
|
||||
_shouldBlockEvent: function(event) {
|
||||
let src = event.get_source();
|
||||
|
||||
if (this._activeMenu != null && this._activeMenu.actor.contains(src))
|
||||
return false;
|
||||
|
||||
for (let i = 0; i < this._menus.length; i++) {
|
||||
let menu = this._menus[i].menu;
|
||||
if (menu.sourceActor && menu.sourceActor.contains(src))
|
||||
return true;
|
||||
if (menu.sourceActor && !menu.blockSourceEvents && menu.sourceActor.contains(src)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
_findMenu: function(item) {
|
||||
@@ -1338,8 +1496,12 @@ PopupMenuManager.prototype = {
|
||||
this._owner.menuEventFilter(event))
|
||||
return true;
|
||||
|
||||
if (this._activeMenu != null && this._activeMenu.passEvents)
|
||||
return false;
|
||||
|
||||
let activeMenuContains = this._eventIsOnActiveMenu(event);
|
||||
let eventType = event.type();
|
||||
|
||||
if (eventType == Clutter.EventType.BUTTON_RELEASE) {
|
||||
if (activeMenuContains) {
|
||||
return false;
|
||||
@@ -1350,7 +1512,7 @@ PopupMenuManager.prototype = {
|
||||
} else if (eventType == Clutter.EventType.BUTTON_PRESS && !activeMenuContains) {
|
||||
this._closeMenu();
|
||||
return true;
|
||||
} else if (activeMenuContains || this._eventIsOnAnyMenuSource(event)) {
|
||||
} else if (!this._shouldBlockEvent(event)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@ const Meta = imports.gi.Meta;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const FileUtils = imports.misc.fileUtils;
|
||||
const Main = imports.ui.main;
|
||||
@@ -22,6 +20,9 @@ const MAX_FILE_DELETED_BEFORE_INVALID = 10;
|
||||
|
||||
const HISTORY_KEY = 'command-history';
|
||||
|
||||
const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown';
|
||||
const DISABLE_COMMAND_LINE_KEY = 'disable-command-line';
|
||||
|
||||
const DIALOG_GROW_TIME = 0.1;
|
||||
|
||||
function CommandCompleter() {
|
||||
@@ -167,6 +168,7 @@ __proto__: ModalDialog.ModalDialog.prototype,
|
||||
_init : function() {
|
||||
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'run-dialog' });
|
||||
|
||||
this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
|
||||
global.settings.connect('changed::development-tools', Lang.bind(this, function () {
|
||||
this._enableInternalCommands = global.settings.get_boolean('development-tools');
|
||||
}));
|
||||
@@ -206,10 +208,7 @@ __proto__: ModalDialog.ModalDialog.prototype,
|
||||
|
||||
this._entryText = entry.clutter_text;
|
||||
this.contentLayout.add(entry, { y_align: St.Align.START });
|
||||
this.connect('opened',
|
||||
Lang.bind(this, function() {
|
||||
this._entryText.grab_key_focus();
|
||||
}));
|
||||
this.setInitialKeyFocus(this._entryText);
|
||||
|
||||
this._errorBox = new St.BoxLayout({ style_class: 'run-dialog-error-box' });
|
||||
|
||||
@@ -239,15 +238,21 @@ __proto__: ModalDialog.ModalDialog.prototype,
|
||||
this._entryText.connect('key-press-event', Lang.bind(this, function(o, e) {
|
||||
let symbol = e.get_key_symbol();
|
||||
if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
|
||||
this.popModal();
|
||||
if (Shell.get_event_state(e) & Clutter.ModifierType.CONTROL_MASK)
|
||||
this._run(o.get_text(), true);
|
||||
else
|
||||
this._run(o.get_text(), false);
|
||||
if (!this._commandError)
|
||||
this.close(global.get_current_time());
|
||||
this.close();
|
||||
else {
|
||||
if (!this.pushModal())
|
||||
this.close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (symbol == Clutter.Escape) {
|
||||
this.close(global.get_current_time());
|
||||
this.close();
|
||||
return true;
|
||||
}
|
||||
if (symbol == Clutter.slash) {
|
||||
@@ -353,6 +358,9 @@ __proto__: ModalDialog.ModalDialog.prototype,
|
||||
this._entryText.set_text('');
|
||||
this._commandError = false;
|
||||
|
||||
if (this._lockdownSettings.get_boolean(DISABLE_COMMAND_LINE_KEY))
|
||||
return;
|
||||
|
||||
ModalDialog.ModalDialog.prototype.open.call(this);
|
||||
},
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const DBus = imports.dbus;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Mainloop = imports.mainloop;
|
||||
|
||||
@@ -68,6 +69,104 @@ function waitLeisure() {
|
||||
};
|
||||
}
|
||||
|
||||
const PerfHelperIface = {
|
||||
name: 'org.gnome.Shell.PerfHelper',
|
||||
methods: [{ name: 'CreateWindow', inSignature: 'iibb', outSignature: '' },
|
||||
{ name: 'WaitWindows', inSignature: '', outSignature: '' },
|
||||
{ name: 'DestroyWindows', inSignature: '', outSignature: ''}]
|
||||
};
|
||||
|
||||
const PerfHelper = function () {
|
||||
this._init();
|
||||
};
|
||||
|
||||
PerfHelper.prototype = {
|
||||
_init: function() {
|
||||
DBus.session.proxifyObject(this, 'org.gnome.Shell.PerfHelper', '/org/gnome/Shell/PerfHelper');
|
||||
}
|
||||
};
|
||||
|
||||
DBus.proxifyPrototype(PerfHelper.prototype, PerfHelperIface);
|
||||
|
||||
let _perfHelper = null;
|
||||
function _getPerfHelper() {
|
||||
if (_perfHelper == null)
|
||||
_perfHelper = new PerfHelper();
|
||||
|
||||
return _perfHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* createTestWindow:
|
||||
* @width: width of window, in pixels
|
||||
* @height: height of window, in pixels
|
||||
* @alpha: whether the window should be alpha transparent
|
||||
* @maximized: whethe the window should be created maximized
|
||||
*
|
||||
* Creates a window using gnome-shell-perf-helper for testing purposes.
|
||||
* While this function can be used with yield in an automation
|
||||
* script to pause until the D-Bus call to the helper process returns,
|
||||
* because of the normal X asynchronous mapping process, to actually wait
|
||||
* until the window has been mapped and exposed, use waitTestWindows().
|
||||
*/
|
||||
function createTestWindow(width, height, alpha, maximized) {
|
||||
let cb;
|
||||
let perfHelper = _getPerfHelper();
|
||||
|
||||
perfHelper.CreateWindowRemote(width, height, alpha, maximized,
|
||||
function(result, excp) {
|
||||
if (cb)
|
||||
cb();
|
||||
});
|
||||
|
||||
return function(callback) {
|
||||
cb = callback;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* waitTestWindows:
|
||||
*
|
||||
* Used within an automation script to pause until all windows previously
|
||||
* created with createTestWindow have been mapped and exposed.
|
||||
*/
|
||||
function waitTestWindows() {
|
||||
let cb;
|
||||
let perfHelper = _getPerfHelper();
|
||||
|
||||
perfHelper.WaitWindowsRemote(function(result, excp) {
|
||||
if (cb)
|
||||
cb();
|
||||
});
|
||||
|
||||
return function(callback) {
|
||||
cb = callback;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* destroyTestWindows:
|
||||
*
|
||||
* Destroys all windows previously created with createTestWindow().
|
||||
* While this function can be used with yield in an automation
|
||||
* script to pause until the D-Bus call to the helper process returns,
|
||||
* this doesn't guarantee that Mutter has actually finished the destroy
|
||||
* process because of normal X asynchronicity.
|
||||
*/
|
||||
function destroyTestWindows() {
|
||||
let cb;
|
||||
let perfHelper = _getPerfHelper();
|
||||
|
||||
perfHelper.DestroyWindowsRemote(function(result, excp) {
|
||||
if (cb)
|
||||
cb();
|
||||
});
|
||||
|
||||
return function(callback) {
|
||||
cb = callback;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* defineScriptEvent
|
||||
* @name: The event will be called script.<name>
|
||||
@@ -147,8 +246,8 @@ function _collect(scriptModule, outputFile) {
|
||||
Shell.write_string_to_stream(out, '"events":\n');
|
||||
Shell.PerfLog.get_default().dump_events(out);
|
||||
|
||||
let monitors = global.get_monitors()
|
||||
let primary = global.get_primary_monitor()
|
||||
let monitors = global.get_monitors();
|
||||
let primary = global.get_primary_monitor();
|
||||
Shell.write_string_to_stream(out, ',\n"monitors":\n[');
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
let monitor = monitors[i];
|
||||
@@ -167,7 +266,21 @@ function _collect(scriptModule, outputFile) {
|
||||
Shell.write_string_to_stream(out, ',\n"metrics":\n[ ');
|
||||
let first = true;
|
||||
for (let name in scriptModule.METRICS) {
|
||||
let metric = scriptModule.METRICS[name];
|
||||
let metric = scriptModule.METRICS[name];
|
||||
// Extra checks here because JSON.stringify generates
|
||||
// invalid JSON for undefined values
|
||||
if (metric.description == null) {
|
||||
log("Error: No description found for metric " + name);
|
||||
continue;
|
||||
}
|
||||
if (metric.units == null) {
|
||||
log("Error: No units found for metric " + name);
|
||||
continue;
|
||||
}
|
||||
if (metric.value == null) {
|
||||
log("Error: No value found for metric " + name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!first)
|
||||
Shell.write_string_to_stream(out, ',\n ');
|
||||
|
||||
@@ -7,9 +7,6 @@ const Signals = imports.signals;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const FileUtils = imports.misc.fileUtils;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
@@ -274,24 +271,18 @@ OpenSearchSystem.prototype = {
|
||||
},
|
||||
|
||||
_addProvider: function(fileName) {
|
||||
let file = Gio.file_new_for_path(global.datadir + '/search_providers/' + fileName);
|
||||
let source = '';
|
||||
|
||||
file.load_contents_async(null, Lang.bind(this, function (obj, res) {
|
||||
let [success, source] = file.load_contents_finish(res);
|
||||
if (source) {
|
||||
let [success, name, url, langs, icon_uri] = global.parse_search_provider(source);
|
||||
let provider ={ name: name,
|
||||
url: url,
|
||||
id: this._providers.length,
|
||||
icon_uri: icon_uri,
|
||||
langs: langs };
|
||||
if (this._checkSupportedProviderLanguage(provider)) {
|
||||
this._providers.push(provider);
|
||||
this.emit('changed');
|
||||
}
|
||||
}
|
||||
}));
|
||||
let path = global.datadir + '/search_providers/' + fileName;
|
||||
let source = Shell.get_file_contents_utf8_sync(path);
|
||||
let [success, name, url, langs, icon_uri] = Shell.parse_search_provider(source);
|
||||
let provider ={ name: name,
|
||||
url: url,
|
||||
id: this._providers.length,
|
||||
icon_uri: icon_uri,
|
||||
langs: langs };
|
||||
if (this._checkSupportedProviderLanguage(provider)) {
|
||||
this._providers.push(provider);
|
||||
this.emit('changed');
|
||||
}
|
||||
},
|
||||
|
||||
_refresh: function() {
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Meta = imports.gi.Meta;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
@@ -38,6 +37,7 @@ SearchResult.prototype = {
|
||||
let icon = new IconGrid.BaseIcon(this.metaInfo['name'],
|
||||
{ createIcon: this.metaInfo['createIcon'] });
|
||||
content.set_child(icon.actor);
|
||||
this.actor.label_actor = icon.label;
|
||||
}
|
||||
this._content = content;
|
||||
this.actor.set_child(content);
|
||||
@@ -49,6 +49,10 @@ SearchResult.prototype = {
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.beginItemDrag(this);
|
||||
}));
|
||||
draggable.connect('drag-cancelled',
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.cancelledItemDrag(this);
|
||||
}));
|
||||
draggable.connect('drag-end',
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.endItemDrag(this);
|
||||
@@ -72,11 +76,12 @@ SearchResult.prototype = {
|
||||
},
|
||||
|
||||
getDragActorSource: function() {
|
||||
return this.metaInfo['icon'];
|
||||
// not exactly right, but alignment problems are hard to notice
|
||||
return this._content;
|
||||
},
|
||||
|
||||
getDragActor: function(stageX, stageY) {
|
||||
return new Clutter.Clone({ source: this.metaInfo['icon'] });
|
||||
return this.metaInfo['createIcon'](Main.overview.dash.iconSize);
|
||||
},
|
||||
|
||||
shellWorkspaceLaunch: function(params) {
|
||||
@@ -100,8 +105,30 @@ GridSearchResults.prototype = {
|
||||
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_SEARCH_RESULTS_ROWS,
|
||||
xAlign: St.Align.START });
|
||||
this.actor = new St.Bin({ x_align: St.Align.START });
|
||||
|
||||
this.actor.set_child(this._grid.actor);
|
||||
this.selectionIndex = -1;
|
||||
this._width = 0;
|
||||
this.actor.connect('notify::width', Lang.bind(this, function() {
|
||||
this._width = this.actor.width;
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
|
||||
this._tryAddResults();
|
||||
}));
|
||||
}));
|
||||
this._notDisplayedResult = [];
|
||||
this._terms = [];
|
||||
},
|
||||
|
||||
_tryAddResults: function() {
|
||||
let canDisplay = this._grid.childrenInRow(this._width) * MAX_SEARCH_RESULTS_ROWS
|
||||
- this._grid.visibleItemsCount();
|
||||
|
||||
for (let i = Math.min(this._notDisplayedResult.length, canDisplay); i > 0; i--) {
|
||||
let result = this._notDisplayedResult.shift();
|
||||
let meta = this.provider.getResultMeta(result);
|
||||
let display = new SearchResult(this.provider, meta, this._terms);
|
||||
this._grid.addItem(display.actor);
|
||||
}
|
||||
},
|
||||
|
||||
getVisibleResultCount: function() {
|
||||
@@ -109,15 +136,15 @@ GridSearchResults.prototype = {
|
||||
},
|
||||
|
||||
renderResults: function(results, terms) {
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
let result = results[i];
|
||||
let meta = this.provider.getResultMeta(result);
|
||||
let display = new SearchResult(this.provider, meta, terms);
|
||||
this._grid.addItem(display.actor);
|
||||
}
|
||||
// copy the lists
|
||||
this._notDisplayedResult = results.slice(0);
|
||||
this._terms = terms.slice(0);
|
||||
this._tryAddResults();
|
||||
},
|
||||
|
||||
clear: function () {
|
||||
this._terms = [];
|
||||
this._notDisplayedResult = [];
|
||||
this._grid.removeAll();
|
||||
this.selectionIndex = -1;
|
||||
},
|
||||
@@ -231,6 +258,7 @@ SearchResults.prototype = {
|
||||
let title = new St.Label({ text: provider.name,
|
||||
style_class: 'dash-search-button-label' });
|
||||
|
||||
button.label_actor = title;
|
||||
bin.set_child(title);
|
||||
button.set_child(bin);
|
||||
provider.actor = button;
|
||||
@@ -305,6 +333,13 @@ SearchResults.prototype = {
|
||||
let terms = this._searchSystem.getTerms();
|
||||
this._openSearchSystem.setSearchTerms(terms);
|
||||
|
||||
// To avoid CSS transitions causing flickering
|
||||
// of the selection when the first search result
|
||||
// stays the same, we hide the content while
|
||||
// filling in the results and setting the initial
|
||||
// selection.
|
||||
this._content.hide();
|
||||
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
let [provider, providerResults] = results[i];
|
||||
let meta = this._metaForProvider(provider);
|
||||
@@ -315,6 +350,8 @@ SearchResults.prototype = {
|
||||
if (this._selectedOpenSearchButton == -1)
|
||||
this.selectDown(false);
|
||||
|
||||
this._content.show();
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
|
||||
@@ -14,9 +14,6 @@ const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
|
||||
const KEY_STICKY_KEYS_ENABLED = 'stickykeys-enable';
|
||||
const KEY_BOUNCE_KEYS_ENABLED = 'bouncekeys-enable';
|
||||
@@ -66,13 +63,13 @@ ATIndicator.prototype = {
|
||||
let textZoom = this._buildFontItem();
|
||||
this.menu.addMenuItem(textZoom);
|
||||
|
||||
let screenReader = this._buildItem(_("Screen Reader"), APPLICATIONS_SCHEMA,
|
||||
'screen-reader-enabled');
|
||||
this.menu.addMenuItem(screenReader);
|
||||
// let screenReader = this._buildItem(_("Screen Reader"), APPLICATIONS_SCHEMA,
|
||||
// 'screen-reader-enabled');
|
||||
// this.menu.addMenuItem(screenReader);
|
||||
|
||||
let screenKeyboard = this._buildItem(_("Screen Keyboard"), APPLICATIONS_SCHEMA,
|
||||
'screen-keyboard-enabled');
|
||||
this.menu.addMenuItem(screenKeyboard);
|
||||
// let screenKeyboard = this._buildItem(_("Screen Keyboard"), APPLICATIONS_SCHEMA,
|
||||
// 'screen-keyboard-enabled');
|
||||
// this.menu.addMenuItem(screenKeyboard);
|
||||
|
||||
let visualBell = this._buildItemGConf(_("Visual Alerts"), client, KEY_VISUAL_BELL);
|
||||
this.menu.addMenuItem(visualBell);
|
||||
@@ -91,7 +88,8 @@ ATIndicator.prototype = {
|
||||
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this.menu.addAction(_("Universal Access Settings"), function() {
|
||||
Util.spawnDesktop('gnome-universal-access-panel');
|
||||
let app = Shell.AppSystem.get_default().get_app('gnome-universal-access-panel.desktop');
|
||||
app.activate(-1);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -16,9 +16,6 @@ const MessageTray = imports.ui.messageTray;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const ConnectionState = {
|
||||
DISCONNECTED: 0,
|
||||
CONNECTED: 1,
|
||||
@@ -67,7 +64,7 @@ Indicator.prototype = {
|
||||
|
||||
this._fullMenuItems = [new PopupMenu.PopupSeparatorMenuItem(),
|
||||
new PopupMenu.PopupMenuItem(_("Send Files to Device...")),
|
||||
new PopupMenu.PopupMenuItem(_("Setup a New Device...")),
|
||||
new PopupMenu.PopupMenuItem(_("Set up a New Device...")),
|
||||
new PopupMenu.PopupSeparatorMenuItem()];
|
||||
this._hasDevices = false;
|
||||
this._deviceSep = this._fullMenuItems[0]; // hidden if no device exists
|
||||
@@ -93,7 +90,8 @@ Indicator.prototype = {
|
||||
this._updateFullMenu();
|
||||
|
||||
this.menu.addAction(_("Bluetooth Settings"), function() {
|
||||
GLib.spawn_command_line_async('gnome-control-center bluetooth');
|
||||
let app = Shell.AppSystem.get_default().get_app('bluetooth-properties.desktop');
|
||||
app.activate(-1);
|
||||
});
|
||||
|
||||
this._applet.connect('pincode-request', Lang.bind(this, this._pinRequest));
|
||||
@@ -126,47 +124,31 @@ Indicator.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_deviceCompare: function(d1, d2) {
|
||||
return d1.device_path == d2.device_path &&
|
||||
d1.bdaddr == d2.bdaddr &&
|
||||
d1.can_connect == d2.can_connect &&
|
||||
d1.capabilities == d2.capabilities;
|
||||
},
|
||||
|
||||
_updateDevices: function() {
|
||||
let devices = this._applet.get_devices();
|
||||
|
||||
for (let i = 0; i < this._deviceItems.length; i++) {
|
||||
let item = this._deviceItems[i];
|
||||
let destroy = true;
|
||||
for (let j = 0; j < devices.length; j++) {
|
||||
// we need to deep compare because BluetoothSimpleDevice is a boxed type
|
||||
// (but we take advantage of that, because _skip will disappear the next
|
||||
// time get_devices() is called)
|
||||
if (this._deviceCompare(item._device, devices[i])) {
|
||||
item.label.text = devices[i].alias;
|
||||
devices[i]._skip = true;
|
||||
destroy = false;
|
||||
}
|
||||
}
|
||||
if (destroy) {
|
||||
item.destroy();
|
||||
item._destroyed = true;
|
||||
}
|
||||
}
|
||||
|
||||
let newlist = [ ];
|
||||
for (let i = 0; i < this._deviceItems.length; i++) {
|
||||
let item = this._deviceItems[i];
|
||||
if (!item._destroyed)
|
||||
let destroy = true;
|
||||
for (let j = 0; j < devices.length; j++) {
|
||||
if (item._device.device_path == devices[j].device_path) {
|
||||
this._updateDeviceItem(item, devices[j]);
|
||||
destroy = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (destroy)
|
||||
item.destroy();
|
||||
else
|
||||
newlist.push(item);
|
||||
}
|
||||
this._deviceItems = newlist;
|
||||
|
||||
this._deviceItems = newlist;
|
||||
this._hasDevices = newlist.length > 0;
|
||||
for (let i = 0; i < devices.length; i++) {
|
||||
let d = devices[i];
|
||||
if (d._skip)
|
||||
if (d._item)
|
||||
continue;
|
||||
let item = this._createDeviceItem(d);
|
||||
if (item) {
|
||||
@@ -181,17 +163,55 @@ Indicator.prototype = {
|
||||
this._deviceSep.actor.hide();
|
||||
},
|
||||
|
||||
_updateDeviceItem: function(item, device) {
|
||||
if (!device.can_connect && device.capabilities == GnomeBluetoothApplet.Capabilities.NONE) {
|
||||
item.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
let prevDevice = item._device;
|
||||
let prevCapabilities = prevDevice.capabilities;
|
||||
let prevCanConnect = prevDevice.can_connect;
|
||||
|
||||
// adopt the new device object
|
||||
item._device = device;
|
||||
device._item = item;
|
||||
|
||||
// update properties
|
||||
item.label.text = device.alias;
|
||||
|
||||
if (prevCapabilities != device.capabilities ||
|
||||
prevCanConnect != device.can_connect) {
|
||||
// need to rebuild the submenu
|
||||
item.menu.removeAll();
|
||||
this._buildDeviceSubMenu(item, device);
|
||||
}
|
||||
|
||||
// update connected property
|
||||
if (device.can_connect)
|
||||
item._connectedMenuitem.setToggleState(device.connected);
|
||||
},
|
||||
|
||||
_createDeviceItem: function(device) {
|
||||
if (!device.can_connect && device.capabilities == GnomeBluetoothApplet.Capabilities.NONE)
|
||||
return null;
|
||||
let item = new PopupMenu.PopupSubMenuMenuItem(device.alias);
|
||||
item._device = device;
|
||||
|
||||
// adopt the device object, and add a back link
|
||||
item._device = device;
|
||||
device._item = item;
|
||||
|
||||
this._buildDeviceSubMenu(item, device);
|
||||
|
||||
return item;
|
||||
},
|
||||
|
||||
_buildDeviceSubMenu: function(item, device) {
|
||||
if (device.can_connect) {
|
||||
item._connected = device.connected;
|
||||
let menuitem = new PopupMenu.PopupSwitchMenuItem(_("Connection"), device.connected);
|
||||
item._connectedMenuitem = new PopupMenu.PopupSwitchMenuItem(_("Connection"), device.connected);
|
||||
|
||||
menuitem.connect('toggled', Lang.bind(this, function() {
|
||||
item._connectedMenuitem.connect('toggled', Lang.bind(this, function() {
|
||||
if (item._connected > ConnectionState.CONNECTED) {
|
||||
// operation already in progress, revert
|
||||
menuitem.setToggleState(menuitem.state);
|
||||
@@ -221,7 +241,7 @@ Indicator.prototype = {
|
||||
}
|
||||
}));
|
||||
|
||||
item.menu.addMenuItem(menuitem);
|
||||
item.menu.addMenuItem(item._connectedMenuitem);
|
||||
}
|
||||
|
||||
if (device.capabilities & GnomeBluetoothApplet.Capabilities.OBEX_PUSH) {
|
||||
@@ -267,8 +287,6 @@ Indicator.prototype = {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return item;
|
||||
},
|
||||
|
||||
_updateFullMenu: function() {
|
||||
@@ -471,9 +489,15 @@ PinNotification.prototype = {
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
if (action == 'ok') {
|
||||
if (this._numeric)
|
||||
this._applet.agent_reply_passkey(this._devicePath, parseInt(this._entry.text));
|
||||
else
|
||||
if (this._numeric) {
|
||||
let num = parseInt(this._entry.text);
|
||||
if (isNaN(num)) {
|
||||
// user reply was empty, or was invalid
|
||||
// cancel the operation
|
||||
num = -1;
|
||||
}
|
||||
this._applet.agent_reply_passkey(this._devicePath, num);
|
||||
} else
|
||||
this._applet.agent_reply_pincode(this._devicePath, this._entry.text);
|
||||
} else {
|
||||
if (this._numeric)
|
||||
|
||||
@@ -13,9 +13,6 @@ const PopupMenu = imports.ui.popupMenu;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
function LayoutMenuItem() {
|
||||
this._init.apply(this, arguments);
|
||||
}
|
||||
@@ -74,7 +71,8 @@ XKBIndicator.prototype = {
|
||||
Util.spawn(['gkbd-keyboard-display', '-g', String(this._config.get_current_group() + 1)]);
|
||||
}));
|
||||
this.menu.addAction(_("Localization Settings"), function() {
|
||||
Util.spawn(['gnome-control-center', 'region']);
|
||||
let app = Shell.AppSystem.get_default().get_app('gnome-region-panel.desktop');
|
||||
app.activate(-1);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
2193
js/ui/status/network.js
Normal file
@@ -11,9 +11,6 @@ const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const BUS_NAME = 'org.gnome.PowerManager';
|
||||
const OBJECT_PATH = '/org/gnome/PowerManager';
|
||||
|
||||
@@ -83,7 +80,8 @@ Indicator.prototype = {
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
|
||||
this.menu.addAction(_("Power Settings"),function() {
|
||||
Util.spawnDesktop('gnome-power-panel');
|
||||
let app = Shell.AppSystem.get_default().get_app('gnome-power-panel.desktop');
|
||||
app.activate(-1);
|
||||
});
|
||||
|
||||
this._proxy.connect('Changed', Lang.bind(this, this._devicesChanged));
|
||||
@@ -114,15 +112,15 @@ Indicator.prototype = {
|
||||
let timestring;
|
||||
if (time > 60) {
|
||||
if (minutes == 0) {
|
||||
timestring = Gettext.ngettext("%d hour remaining", "%d hours remaining", hours).format(hours);
|
||||
timestring = ngettext("%d hour remaining", "%d hours remaining", hours).format(hours);
|
||||
} else {
|
||||
/* TRANSLATORS: this is a time string, as in "%d hours %d minutes remaining" */
|
||||
let template = _("%d %s %d %s remaining");
|
||||
|
||||
timestring = template.format (hours, Gettext.ngettext("hour", "hours", hours), minutes, Gettext.ngettext("minute", "minutes", minutes));
|
||||
timestring = template.format (hours, ngettext("hour", "hours", hours), minutes, ngettext("minute", "minutes", minutes));
|
||||
}
|
||||
} else
|
||||
timestring = Gettext.ngettext("%d minute remaining", "%d minutes remaining", minutes).format(minutes);
|
||||
timestring = ngettext("%d minute remaining", "%d minutes remaining", minutes).format(minutes);
|
||||
this._batteryItem.label.text = timestring;
|
||||
}
|
||||
this._primaryPercentage.text = Math.round(percentage) + '%';
|
||||
|
||||
@@ -13,10 +13,6 @@ const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const VOLUME_MAX = 65536.0; /* PA_VOLUME_NORM */
|
||||
const VOLUME_ADJUSTMENT_STEP = 0.05; /* Volume adjustment step in % */
|
||||
|
||||
const VOLUME_NOTIFY_ID = 1;
|
||||
@@ -37,6 +33,8 @@ Indicator.prototype = {
|
||||
this._control.connect('default-source-changed', Lang.bind(this, this._readInput));
|
||||
this._control.connect('stream-added', Lang.bind(this, this._maybeShowInput));
|
||||
this._control.connect('stream-removed', Lang.bind(this, this._maybeShowInput));
|
||||
this._volumeMax = this._control.get_vol_max_norm();
|
||||
this._volumeMaxAmplified = this._control.get_vol_max_amplified();
|
||||
|
||||
this._output = null;
|
||||
this._outputVolumeId = 0;
|
||||
@@ -63,7 +61,8 @@ Indicator.prototype = {
|
||||
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this.menu.addAction(_("Sound Settings"), function() {
|
||||
Util.spawnDesktop('gnome-sound-panel');
|
||||
let app = Shell.AppSystem.get_default().get_app('gnome-sound-panel.desktop');
|
||||
app.activate(-1);
|
||||
});
|
||||
|
||||
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
|
||||
@@ -72,9 +71,9 @@ Indicator.prototype = {
|
||||
|
||||
_getMaxVolume: function(property) {
|
||||
if (this[property].get_can_decibel())
|
||||
return (VOLUME_MAX * 1.5);
|
||||
return this._volumeMaxAmplified;
|
||||
else
|
||||
return VOLUME_MAX;
|
||||
return this._volumeMax;
|
||||
},
|
||||
|
||||
_onScrollEvent: function(actor, event) {
|
||||
|
||||
@@ -19,7 +19,8 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
|
||||
'a11y-keyboard': 'a11y',
|
||||
'kbd-scrolllock': 'keyboard',
|
||||
'kbd-numlock': 'keyboard',
|
||||
'kbd-capslock': 'keyboard'
|
||||
'kbd-capslock': 'keyboard',
|
||||
'ibus-ui-gtk': 'input-method'
|
||||
};
|
||||
|
||||
function StatusIconDispatcher() {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Gdm = imports.gi.Gdm;
|
||||
const DBus = imports.dbus;
|
||||
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 Tp = imports.gi.TelepathyGLib;
|
||||
const UPowerGlib = imports.gi.UPowerGlib;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const GnomeSession = imports.misc.gnomeSession;
|
||||
const Main = imports.ui.main;
|
||||
@@ -16,6 +16,21 @@ const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const BUS_NAME = 'org.gnome.ScreenSaver';
|
||||
const OBJECT_PATH = '/org/gnome/ScreenSaver';
|
||||
|
||||
const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown';
|
||||
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 ScreenSaverInterface = {
|
||||
name: BUS_NAME,
|
||||
methods: [ { name: 'Lock', inSignature: '' } ]
|
||||
};
|
||||
|
||||
let ScreenSaverProxy = DBus.makeProxyClass(ScreenSaverInterface);
|
||||
|
||||
// Adapted from gdm/gui/user-switch-applet/applet.c
|
||||
//
|
||||
// Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
|
||||
@@ -33,17 +48,20 @@ StatusMenuButton.prototype = {
|
||||
let box = new St.BoxLayout({ name: 'panelStatusMenu' });
|
||||
this.actor.set_child(box);
|
||||
|
||||
this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
|
||||
|
||||
this._gdm = Gdm.UserManager.ref_default();
|
||||
this._gdm.queue_load();
|
||||
|
||||
this._user = this._gdm.get_user(GLib.get_user_name());
|
||||
this._presence = new GnomeSession.Presence();
|
||||
this._presenceItems = {};
|
||||
this._session = new GnomeSession.SessionManager();
|
||||
|
||||
this._account_mgr = Tp.AccountManager.dup()
|
||||
|
||||
this._upClient = new UPowerGlib.Client();
|
||||
|
||||
this._screenSaverProxy = new ScreenSaverProxy(DBus.session, BUS_NAME, OBJECT_PATH);
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
||||
this._iconBox = new St.Bin();
|
||||
@@ -67,6 +85,15 @@ StatusMenuButton.prototype = {
|
||||
this._gdm.connect('notify::is-loaded', Lang.bind(this, this._updateSwitchUser));
|
||||
this._gdm.connect('user-added', Lang.bind(this, this._updateSwitchUser));
|
||||
this._gdm.connect('user-removed', Lang.bind(this, this._updateSwitchUser));
|
||||
this._lockdownSettings.connect('changed::' + DISABLE_USER_SWITCH_KEY,
|
||||
Lang.bind(this, this._updateSwitchUser));
|
||||
this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
|
||||
Lang.bind(this, this._updateLogout));
|
||||
this._lockdownSettings.connect('changed::' + DISABLE_LOCK_SCREEN_KEY,
|
||||
Lang.bind(this, this._updateLockScreen));
|
||||
this._updateSwitchUser();
|
||||
this._updateLogout();
|
||||
this._updateLockScreen();
|
||||
|
||||
this._upClient.connect('notify::can-suspend', Lang.bind(this, this._updateSuspendOrPowerOff));
|
||||
},
|
||||
@@ -83,11 +110,41 @@ StatusMenuButton.prototype = {
|
||||
this._name.set_text("");
|
||||
},
|
||||
|
||||
_updateSessionSeparator: function() {
|
||||
let showSeparator = this._loginScreenItem.actor.visible ||
|
||||
this._logoutItem.actor.visible ||
|
||||
this._lockScreenItem.actor.visible;
|
||||
if (showSeparator)
|
||||
this._sessionSeparator.actor.show();
|
||||
else
|
||||
this._sessionSeparator.actor.hide();
|
||||
},
|
||||
|
||||
_updateSwitchUser: function() {
|
||||
if (this._gdm.can_switch ())
|
||||
let allowSwitch = !this._lockdownSettings.get_boolean(DISABLE_USER_SWITCH_KEY);
|
||||
if (allowSwitch && this._gdm.can_switch ())
|
||||
this._loginScreenItem.actor.show();
|
||||
else
|
||||
this._loginScreenItem.actor.hide();
|
||||
this._updateSessionSeparator();
|
||||
},
|
||||
|
||||
_updateLogout: function() {
|
||||
let allowLogout = !this._lockdownSettings.get_boolean(DISABLE_LOG_OUT_KEY);
|
||||
if (allowLogout)
|
||||
this._logoutItem.actor.show();
|
||||
else
|
||||
this._logoutItem.actor.hide();
|
||||
this._updateSessionSeparator();
|
||||
},
|
||||
|
||||
_updateLockScreen: function() {
|
||||
let allowLockScreen = !this._lockdownSettings.get_boolean(DISABLE_LOCK_SCREEN_KEY);
|
||||
if (allowLockScreen)
|
||||
this._lockScreenItem.actor.show();
|
||||
else
|
||||
this._lockScreenItem.actor.hide();
|
||||
this._updateSessionSeparator();
|
||||
},
|
||||
|
||||
_updateSuspendOrPowerOff: function() {
|
||||
@@ -101,7 +158,7 @@ StatusMenuButton.prototype = {
|
||||
if (!this._haveSuspend) {
|
||||
this._suspendOrPowerOffItem.updateText(_("Power Off..."), null);
|
||||
} else {
|
||||
this._suspendOrPowerOffItem.updateText(_("Suspend"), ("Power Off..."));
|
||||
this._suspendOrPowerOffItem.updateText(_("Suspend"), _("Power Off..."));
|
||||
}
|
||||
},
|
||||
|
||||
@@ -149,6 +206,7 @@ StatusMenuButton.prototype = {
|
||||
item = new PopupMenu.PopupMenuItem(_("Lock Screen"));
|
||||
item.connect('activate', Lang.bind(this, this._onLockScreenActivate));
|
||||
this.menu.addMenuItem(item);
|
||||
this._lockScreenItem = item;
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_("Switch User"));
|
||||
item.connect('activate', Lang.bind(this, this._onLoginScreenActivate));
|
||||
@@ -158,9 +216,11 @@ StatusMenuButton.prototype = {
|
||||
item = new PopupMenu.PopupMenuItem(_("Log Out..."));
|
||||
item.connect('activate', Lang.bind(this, this._onQuitSessionActivate));
|
||||
this.menu.addMenuItem(item);
|
||||
this._logoutItem = item;
|
||||
|
||||
item = new PopupMenu.PopupSeparatorMenuItem();
|
||||
this.menu.addMenuItem(item);
|
||||
this._sessionSeparator = item;
|
||||
|
||||
item = new PopupMenu.PopupAlternatingMenuItem(_("Suspend"),
|
||||
_("Power Off..."));
|
||||
@@ -178,17 +238,19 @@ StatusMenuButton.prototype = {
|
||||
|
||||
_onMyAccountActivate: function() {
|
||||
Main.overview.hide();
|
||||
Util.spawnDesktop('gnome-user-accounts-panel');
|
||||
let app = Shell.AppSystem.get_default().get_app('gnome-user-accounts-panel.desktop');
|
||||
app.activate(-1);
|
||||
},
|
||||
|
||||
_onPreferencesActivate: function() {
|
||||
Main.overview.hide();
|
||||
Util.spawnDesktop('gnome-control-center');
|
||||
let app = Shell.AppSystem.get_default().get_app('gnome-control-center.desktop');
|
||||
app.activate(-1);
|
||||
},
|
||||
|
||||
_onLockScreenActivate: function() {
|
||||
Main.overview.hide();
|
||||
Util.spawn(['gnome-screensaver-command', '--lock']);
|
||||
this._screenSaverProxy.LockRemote();
|
||||
},
|
||||
|
||||
_onLoginScreenActivate: function() {
|
||||
@@ -199,7 +261,7 @@ StatusMenuButton.prototype = {
|
||||
|
||||
_onQuitSessionActivate: function() {
|
||||
Main.overview.hide();
|
||||
Util.spawn(['gnome-session-quit', '--logout']);
|
||||
this._session.LogoutRemote(0);
|
||||
},
|
||||
|
||||
_onSuspendOrPowerOffActivate: function() {
|
||||
@@ -207,9 +269,11 @@ StatusMenuButton.prototype = {
|
||||
|
||||
if (this._haveSuspend &&
|
||||
this._suspendOrPowerOffItem.state == PopupMenu.PopupAlternatingMenuItemState.DEFAULT) {
|
||||
this._upClient.suspend_sync(null);
|
||||
this._screenSaverProxy.LockRemote(Lang.bind(this, function() {
|
||||
this._upClient.suspend_sync(null);
|
||||
}));
|
||||
} else {
|
||||
Util.spawn(['gnome-session-quit', '--power-off']);
|
||||
this._session.ShutdownRemote();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ const Mainloop = imports.mainloop;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
const Tpl = imports.gi.TelepathyLogger;
|
||||
const Tp = imports.gi.TelepathyGLib;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const History = imports.misc.history;
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
|
||||
@@ -21,6 +21,9 @@ const SCROLLBACK_RECENT_TIME = 15 * 60; // 15 minutes
|
||||
const SCROLLBACK_RECENT_LENGTH = 20;
|
||||
const SCROLLBACK_IDLE_LENGTH = 5;
|
||||
|
||||
// See Source._displayPendingMessages
|
||||
const SCROLLBACK_HISTORY_LINES = 10;
|
||||
|
||||
const NotificationDirection = {
|
||||
SENT: 'chat-sent',
|
||||
RECEIVED: 'chat-received'
|
||||
@@ -35,6 +38,31 @@ let contactFeatures = [Tp.ContactFeature.ALIAS,
|
||||
// lets us see messages even if they belong to another app (eg,
|
||||
// Empathy).
|
||||
|
||||
function makeMessageFromTpMessage(tpMessage, direction) {
|
||||
let [text, flags] = tpMessage.to_text();
|
||||
return {
|
||||
messageType: tpMessage.get_message_type(),
|
||||
text: text,
|
||||
sender: tpMessage.sender.alias,
|
||||
timestamp: tpMessage.get_received_timestamp(),
|
||||
direction: direction
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function makeMessageFromTplEvent(event) {
|
||||
let sent = event.get_sender().get_entity_type() == Tpl.EntityType.SELF;
|
||||
let direction = sent ? NotificationDirection.SENT : NotificationDirection.RECEIVED;
|
||||
|
||||
return {
|
||||
messageType: event.get_message_type(),
|
||||
text: event.get_message(),
|
||||
sender: event.get_sender().get_alias(),
|
||||
timestamp: event.get_timestamp(),
|
||||
direction: direction
|
||||
};
|
||||
}
|
||||
|
||||
function Client() {
|
||||
this._init();
|
||||
};
|
||||
@@ -49,14 +77,9 @@ Client.prototype = {
|
||||
// The second argument, recover, means _observeChannels will be run
|
||||
// for any existing channel as well.
|
||||
let dbus = Tp.DBusDaemon.dup();
|
||||
this._observer = Tp.SimpleObserver.new(dbus, true, 'GnomeShell', true,
|
||||
Lang.bind(this, this._observeChannels));
|
||||
|
||||
// We only care about single-user text-based chats
|
||||
let props = {};
|
||||
props[Tp.PROP_CHANNEL_CHANNEL_TYPE] = Tp.IFACE_CHANNEL_TYPE_TEXT;
|
||||
props[Tp.PROP_CHANNEL_TARGET_HANDLE_TYPE] = Tp.HandleType.CONTACT;
|
||||
this._observer.add_observer_filter(props);
|
||||
this._observer = Shell.TpClient.new(dbus);
|
||||
this._observer.set_observe_channels_func(
|
||||
Lang.bind(this, this._observeChannels));
|
||||
|
||||
try {
|
||||
this._observer.register();
|
||||
@@ -67,7 +90,22 @@ Client.prototype = {
|
||||
|
||||
_observeChannels: function(observer, account, conn, channels,
|
||||
dispatchOp, requests, context) {
|
||||
let connPath = conn.get_object_path();
|
||||
// If the self_contact doesn't have the ALIAS, make sure
|
||||
// to fetch it before trying to grab the channels.
|
||||
let self_contact = conn.get_self_contact();
|
||||
if (self_contact.has_feature(Tp.ContactFeature.ALIAS)) {
|
||||
this._finishObserveChannels(account, conn, channels, context);
|
||||
} else {
|
||||
Shell.get_self_contact_features(conn,
|
||||
contactFeatures.length, contactFeatures,
|
||||
Lang.bind(this, function() {
|
||||
this._finishObserveChannels(account, conn, channels, context);
|
||||
}));
|
||||
context.delay();
|
||||
}
|
||||
},
|
||||
|
||||
_finishObserveChannels: function(account, conn, channels, context) {
|
||||
let len = channels.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
let channel = channels[i];
|
||||
@@ -90,7 +128,6 @@ Client.prototype = {
|
||||
}), null);
|
||||
}
|
||||
|
||||
// Allow dbus method to return
|
||||
context.accept();
|
||||
},
|
||||
|
||||
@@ -116,7 +153,7 @@ Source.prototype = {
|
||||
__proto__: MessageTray.Source.prototype,
|
||||
|
||||
_init: function(account, conn, channel, contact) {
|
||||
MessageTray.Source.prototype._init.call(this, channel.get_identifier());
|
||||
MessageTray.Source.prototype._init.call(this, contact.get_alias());
|
||||
|
||||
this.isChat = true;
|
||||
|
||||
@@ -127,8 +164,6 @@ Source.prototype = {
|
||||
this._channel = channel;
|
||||
this._closedId = this._channel.connect('invalidated', Lang.bind(this, this._channelClosed));
|
||||
|
||||
this._updateAlias();
|
||||
|
||||
this._notification = new Notification(this);
|
||||
this._notification.setUrgency(MessageTray.Urgency.HIGH);
|
||||
|
||||
@@ -143,11 +178,18 @@ Source.prototype = {
|
||||
this._notifyAvatarId = this._contact.connect('notify::avatar-file', Lang.bind(this, this._updateAvatarIcon));
|
||||
this._presenceChangedId = this._contact.connect('presence-changed', Lang.bind(this, this._presenceChanged));
|
||||
|
||||
this._displayPendingMessages();
|
||||
// Add ourselves as a source.
|
||||
Main.messageTray.add(this);
|
||||
this.pushNotification(this._notification);
|
||||
|
||||
this._getLogMessages();
|
||||
},
|
||||
|
||||
_updateAlias: function() {
|
||||
let oldAlias = this.title;
|
||||
this.title = this._contact.get_alias();
|
||||
this._notification.appendAliasChange(oldAlias, this.title);
|
||||
this.pushNotification(this._notification);
|
||||
},
|
||||
|
||||
createNotificationIcon: function() {
|
||||
@@ -183,13 +225,52 @@ Source.prototype = {
|
||||
req.ensure_channel_async('', null, null);
|
||||
},
|
||||
|
||||
_displayPendingMessages: function() {
|
||||
let msgs = this._channel.get_pending_messages();
|
||||
_getLogMessages: function() {
|
||||
let logManager = Tpl.LogManager.dup_singleton();
|
||||
let entity = Tpl.Entity.new_from_tp_contact(this._contact, Tpl.EntityType.CONTACT);
|
||||
Shell.get_contact_events(logManager,
|
||||
this._account, entity,
|
||||
SCROLLBACK_HISTORY_LINES,
|
||||
Lang.bind(this, this._displayPendingMessages));
|
||||
},
|
||||
|
||||
for (let i = 0; i < msgs.length; i++) {
|
||||
let msg = msgs[i];
|
||||
this._messageReceived(this._channel, msg);
|
||||
_displayPendingMessages: function(logManager, result) {
|
||||
let [success, events] = logManager.get_filtered_events_finish(result);
|
||||
|
||||
let logMessages = events.map(makeMessageFromTplEvent);
|
||||
|
||||
let pendingTpMessages = this._channel.get_pending_messages();
|
||||
let pendingMessages = pendingTpMessages.map(function (tpMessage) { return makeMessageFromTpMessage(tpMessage, NotificationDirection.RECEIVED); });
|
||||
|
||||
let showTimestamp = false;
|
||||
|
||||
for (let i = 0; i < logMessages.length; i++) {
|
||||
let logMessage = logMessages[i];
|
||||
let isPending = false;
|
||||
|
||||
// Skip any log messages that are also in pendingMessages
|
||||
for (let j = 0; j < pendingMessages.length; j++) {
|
||||
let pending = pendingMessages[j];
|
||||
if (logMessage.timestamp == pending.timestamp && logMessage.text == pending.text) {
|
||||
isPending = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isPending) {
|
||||
showTimestamp = true;
|
||||
this._notification.appendMessage(logMessage, true, ['chat-log-message']);
|
||||
}
|
||||
}
|
||||
|
||||
if (showTimestamp)
|
||||
this._notification.appendTimestamp();
|
||||
|
||||
for (let i = 0; i < pendingMessages.length; i++)
|
||||
this._notification.appendMessage(pendingMessages[i], true);
|
||||
|
||||
if (pendingMessages.length > 0)
|
||||
this.notify();
|
||||
},
|
||||
|
||||
_channelClosed: function() {
|
||||
@@ -205,25 +286,35 @@ Source.prototype = {
|
||||
},
|
||||
|
||||
_messageReceived: function(channel, message) {
|
||||
this._notification.appendMessage(message, NotificationDirection.RECEIVED);
|
||||
if (message.get_message_type() == Tp.ChannelTextMessageType.DELIVERY_REPORT)
|
||||
return;
|
||||
|
||||
message = makeMessageFromTpMessage(message, NotificationDirection.RECEIVED);
|
||||
this._notification.appendMessage(message);
|
||||
this.notify();
|
||||
},
|
||||
|
||||
// This is called for both messages we send from
|
||||
// our client and other clients as well.
|
||||
_messageSent: function(channel, message, flags, token) {
|
||||
this._notification.appendMessage(message, NotificationDirection.SENT);
|
||||
message = makeMessageFromTpMessage(message, NotificationDirection.SENT);
|
||||
this._notification.appendMessage(message);
|
||||
},
|
||||
|
||||
notify: function() {
|
||||
if (!Main.messageTray.contains(this))
|
||||
Main.messageTray.add(this);
|
||||
|
||||
MessageTray.Source.prototype.notify.call(this, this._notification);
|
||||
},
|
||||
|
||||
respond: function(text) {
|
||||
let msg = Tp.ClientMessage.new_text(Tp.ChannelTextMessageType.NORMAL, text);
|
||||
let type;
|
||||
if (text.slice(0, 4) == '/me ') {
|
||||
type = Tp.ChannelTextMessageType.ACTION;
|
||||
text = text.slice(4);
|
||||
} else {
|
||||
type = Tp.ChannelTextMessageType.NORMAL;
|
||||
}
|
||||
|
||||
let msg = Tp.ClientMessage.new_text(type, text);
|
||||
this._channel.send_message_async(msg, 0, null);
|
||||
},
|
||||
|
||||
@@ -279,19 +370,52 @@ Notification.prototype = {
|
||||
this._responseEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivated));
|
||||
this.setActionArea(this._responseEntry);
|
||||
|
||||
this._oldMaxScrollAdjustment = 0;
|
||||
this._createScrollArea();
|
||||
|
||||
this._scrollArea.vscroll.adjustment.connect('changed', Lang.bind(this, function(adjustment) {
|
||||
let currentValue = adjustment.value + adjustment.page_size;
|
||||
if (currentValue == this._oldMaxScrollAdjustment)
|
||||
this.scrollTo(St.Side.BOTTOM);
|
||||
this._oldMaxScrollAdjustment = adjustment.upper;
|
||||
}));
|
||||
|
||||
this._inputHistory = new History.HistoryManager({ entry: this._responseEntry.clutter_text });
|
||||
|
||||
this._history = [];
|
||||
this._timestampTimeoutId = 0;
|
||||
},
|
||||
|
||||
appendMessage: function(message, direction) {
|
||||
let [text, flags] = message.to_text();
|
||||
let timestamp = message.get_received_timestamp();
|
||||
/**
|
||||
* appendMessage:
|
||||
* @message: An object with the properties:
|
||||
* text: the body of the message,
|
||||
* messageType: a #Tp.ChannelTextMessageType,
|
||||
* sender: the name of the sender,
|
||||
* timestamp: the time the message was sent
|
||||
* direction: a #NotificationDirection
|
||||
*
|
||||
* @noTimestamp: Whether to add a timestamp. If %true, no timestamp
|
||||
* will be added, regardless of the difference since the
|
||||
* last timestamp
|
||||
* @styles: A list of CSS class names.
|
||||
*/
|
||||
appendMessage: function(message, noTimestamp, styles) {
|
||||
let messageBody = GLib.markup_escape_text(message.text, -1);
|
||||
styles = styles || [];
|
||||
styles.push(message.direction);
|
||||
|
||||
this.update(this.source.title, text, { customContent: true });
|
||||
this._append(text, direction, timestamp);
|
||||
if (message.messageType == Tp.ChannelTextMessageType.ACTION) {
|
||||
let senderAlias = GLib.markup_escape_text(message.sender, -1);
|
||||
messageBody = '<i>%s</i> %s'.format(senderAlias, messageBody);
|
||||
styles.push('chat-action');
|
||||
}
|
||||
|
||||
this.update(this.source.title, messageBody, { customContent: true, bannerMarkup: true });
|
||||
this._append(messageBody, styles, message.timestamp, noTimestamp);
|
||||
},
|
||||
|
||||
_append: function(text, style, timestamp) {
|
||||
_append: function(text, styles, timestamp, noTimestamp) {
|
||||
let currentTime = (Date.now() / 1000);
|
||||
if (!timestamp)
|
||||
timestamp = currentTime;
|
||||
@@ -303,20 +427,22 @@ Notification.prototype = {
|
||||
if (this._timestampTimeoutId)
|
||||
Mainloop.source_remove(this._timestampTimeoutId);
|
||||
|
||||
let body = this.addBody(text);
|
||||
body.add_style_class_name(style);
|
||||
this.scrollTo(St.Side.BOTTOM);
|
||||
let body = this.addBody(text, true);
|
||||
for (let i = 0; i < styles.length; i ++)
|
||||
body.add_style_class_name(styles[i]);
|
||||
|
||||
this._history.unshift({ actor: body, time: timestamp, realMessage: true });
|
||||
|
||||
if (timestamp < currentTime - SCROLLBACK_IMMEDIATE_TIME)
|
||||
this._appendTimestamp();
|
||||
else
|
||||
// Schedule a new timestamp in SCROLLBACK_IMMEDIATE_TIME
|
||||
// from the timestamp of the message.
|
||||
this._timestampTimeoutId = Mainloop.timeout_add_seconds(
|
||||
SCROLLBACK_IMMEDIATE_TIME - (currentTime - timestamp),
|
||||
Lang.bind(this, this._appendTimestamp));
|
||||
if (!noTimestamp) {
|
||||
if (timestamp < currentTime - SCROLLBACK_IMMEDIATE_TIME)
|
||||
this.appendTimestamp();
|
||||
else
|
||||
// Schedule a new timestamp in SCROLLBACK_IMMEDIATE_TIME
|
||||
// from the timestamp of the message.
|
||||
this._timestampTimeoutId = Mainloop.timeout_add_seconds(
|
||||
SCROLLBACK_IMMEDIATE_TIME - (currentTime - timestamp),
|
||||
Lang.bind(this, this.appendTimestamp));
|
||||
}
|
||||
|
||||
if (this._history.length > 1) {
|
||||
// Keep the scrollback from growing too long. If the most
|
||||
@@ -337,15 +463,41 @@ Notification.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_appendTimestamp: function() {
|
||||
_formatTimestamp: function(date) {
|
||||
let now = new Date();
|
||||
|
||||
var daysAgo = (now.getTime() - date.getTime()) / (24 * 60 * 60 * 1000);
|
||||
|
||||
let format;
|
||||
|
||||
// Show a week day and time if date is in the last week
|
||||
if (daysAgo < 1 || (daysAgo < 7 && now.getDay() != date.getDay())) {
|
||||
/* Translators: this is a time format string followed by a date.
|
||||
If applicable, replace %X with a strftime format valid for your
|
||||
locale, without seconds. */
|
||||
// xgettext:no-c-format
|
||||
format = _("Sent at %X on %A");
|
||||
|
||||
// FIXME: The next two are stolen from calendar.js with the comment to avoid
|
||||
// a string-freeze break. They should be replaced with better strings
|
||||
// with 'Sent at', appropriate context and appropriate translator comment.
|
||||
|
||||
} else if (date.getYear() == now.getYear()) {
|
||||
/* Translators: Shown on calendar heading when selected day occurs on current year */
|
||||
format = C_("calendar heading", "%A, %B %d");
|
||||
} else {
|
||||
/* Translators: Shown on calendar heading when selected day occurs on different year */
|
||||
format = C_("calendar heading", "%A, %B %d, %Y");
|
||||
}
|
||||
|
||||
return date.toLocaleFormat(format);
|
||||
},
|
||||
|
||||
appendTimestamp: function() {
|
||||
let lastMessageTime = this._history[0].time;
|
||||
let lastMessageDate = new Date(lastMessageTime * 1000);
|
||||
|
||||
/* Translators: this is a time format string followed by a date.
|
||||
If applicable, replace %X with a strftime format valid for your
|
||||
locale, without seconds. */
|
||||
// xgettext:no-c-format
|
||||
let timeLabel = this.addBody(lastMessageDate.toLocaleFormat(_("Sent at %X on %A")), false, { expand: true, x_fill: false, x_align: St.Align.END });
|
||||
let timeLabel = this.addBody(this._formatTimestamp(lastMessageDate), false, { expand: true, x_fill: false, x_align: St.Align.END });
|
||||
timeLabel.add_style_class_name('chat-meta-message');
|
||||
this._history.unshift({ actor: timeLabel, time: lastMessageTime, realMessage: false });
|
||||
|
||||
@@ -363,11 +515,26 @@ Notification.prototype = {
|
||||
this._history.unshift({ actor: label, time: (Date.now() / 1000), realMessage: false});
|
||||
},
|
||||
|
||||
appendAliasChange: function(oldAlias, newAlias) {
|
||||
oldAlias = GLib.markup_escape_text(oldAlias, -1);
|
||||
newAlias = GLib.markup_escape_text(newAlias, -1);
|
||||
|
||||
/* Translators: this is the other person changing their old IM name to their new
|
||||
IM name. */
|
||||
let message = '<i>' + _("%s is now known as %s").format(oldAlias, newAlias) + '</i>';
|
||||
let label = this.addBody(message, true);
|
||||
label.add_style_class_name('chat-meta-message');
|
||||
this._history.unshift({ actor: label, time: (Date.now() / 1000), realMessage: false });
|
||||
this.update(newAlias, null, { customContent: true });
|
||||
},
|
||||
|
||||
_onEntryActivated: function() {
|
||||
let text = this._responseEntry.get_text();
|
||||
if (text == '')
|
||||
return;
|
||||
|
||||
this._inputHistory.addItem(text);
|
||||
|
||||
// Telepathy sends out the Sent signal for us.
|
||||
// see Source._messageSent
|
||||
this._responseEntry.set_text('');
|
||||
|
||||
@@ -8,8 +8,6 @@ const Signals = imports.signals;
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Search = imports.ui.search;
|
||||
@@ -41,11 +39,14 @@ BaseTab.prototype = {
|
||||
this.visible = false;
|
||||
},
|
||||
|
||||
show: function() {
|
||||
show: function(animate) {
|
||||
this.visible = true;
|
||||
this.page.opacity = 0;
|
||||
this.page.show();
|
||||
|
||||
if (!animate)
|
||||
return;
|
||||
|
||||
this.page.opacity = 0;
|
||||
Tweener.addTween(this.page,
|
||||
{ opacity: 255,
|
||||
time: 0.1,
|
||||
@@ -77,14 +78,16 @@ BaseTab.prototype = {
|
||||
Signals.addSignalMethods(BaseTab.prototype);
|
||||
|
||||
|
||||
function ViewTab(label, pageActor, a11yIcon) {
|
||||
this._init(label, pageActor, a11yIcon);
|
||||
function ViewTab(id, label, pageActor, a11yIcon) {
|
||||
this._init(id, label, pageActor, a11yIcon);
|
||||
}
|
||||
|
||||
ViewTab.prototype = {
|
||||
__proto__: BaseTab.prototype,
|
||||
|
||||
_init: function(label, pageActor, a11yIcon) {
|
||||
_init: function(id, label, pageActor, a11yIcon) {
|
||||
this.id = id;
|
||||
|
||||
let titleActor = new St.Button({ label: label,
|
||||
style_class: 'view-tab-title' });
|
||||
titleActor.connect('clicked', Lang.bind(this, this._activate));
|
||||
@@ -147,10 +150,6 @@ SearchTab.prototype = {
|
||||
return true;
|
||||
}));
|
||||
|
||||
this._entry.connect('secondary-icon-clicked', Lang.bind(this,
|
||||
function() {
|
||||
this._reset();
|
||||
}));
|
||||
this._entry.connect('notify::mapped', Lang.bind(this, this._onMapped));
|
||||
|
||||
global.stage.connect('notify::key-focus', Lang.bind(this, this._updateCursorVisibility));
|
||||
@@ -161,7 +160,14 @@ SearchTab.prototype = {
|
||||
hide: function() {
|
||||
BaseTab.prototype.hide.call(this);
|
||||
|
||||
this._reset();
|
||||
// Leave the entry focused when it doesn't have any text;
|
||||
// when replacing a selected search term, Clutter emits
|
||||
// two 'text-changed' signals, one for deleting the previous
|
||||
// text and one for the new one - the second one is handled
|
||||
// incorrectly when we remove focus
|
||||
// (https://bugzilla.gnome.org/show_bug.cgi?id=636341) */
|
||||
if (this._text.text != '')
|
||||
this._reset();
|
||||
},
|
||||
|
||||
_reset: function () {
|
||||
@@ -221,7 +227,7 @@ SearchTab.prototype = {
|
||||
if (this._iconClickedId == 0) {
|
||||
this._iconClickedId = this._entry.connect('secondary-icon-clicked',
|
||||
Lang.bind(this, function() {
|
||||
this.reset();
|
||||
this._reset();
|
||||
}));
|
||||
}
|
||||
this._activate();
|
||||
@@ -383,14 +389,16 @@ ViewSelector.prototype = {
|
||||
}));
|
||||
},
|
||||
|
||||
addViewTab: function(title, pageActor, a11yIcon) {
|
||||
let viewTab = new ViewTab(title, pageActor, a11yIcon);
|
||||
addViewTab: function(id, title, pageActor, a11yIcon) {
|
||||
let viewTab = new ViewTab(id, title, pageActor, a11yIcon);
|
||||
this._tabs.push(viewTab);
|
||||
this._tabBox.add(viewTab.title);
|
||||
this._addTab(viewTab);
|
||||
},
|
||||
|
||||
_switchTab: function(tab) {
|
||||
let firstSwitch = this._activeTab == null;
|
||||
|
||||
if (this._activeTab && this._activeTab.visible) {
|
||||
if (this._activeTab == tab)
|
||||
return;
|
||||
@@ -406,11 +414,13 @@ ViewSelector.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
// Only fade when switching between tabs,
|
||||
// not when setting the initially selected one.
|
||||
if (!tab.visible)
|
||||
tab.show();
|
||||
tab.show(!firstSwitch);
|
||||
|
||||
// Pull a Meg Ryan:
|
||||
if (Main.overview && Main.overview.workspaces) {
|
||||
if (!firstSwitch && Main.overview.workspaces) {
|
||||
if (tab != this._tabs[0]) {
|
||||
Tweener.addTween(Main.overview.workspaces.actor,
|
||||
{ opacity: 0,
|
||||
@@ -433,6 +443,14 @@ ViewSelector.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
switchTab: function(id) {
|
||||
for (let i = 0; i < this._tabs.length; i++)
|
||||
if (this._tabs[i].id == id) {
|
||||
this._switchTab(this._tabs[i]);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_switchDefaultTab: function() {
|
||||
if (this._tabs.length > 0)
|
||||
this._switchTab(this._tabs[0]);
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
|
||||
@@ -93,6 +93,8 @@ WindowManager.prototype = {
|
||||
|
||||
this._dimmedWindows = [];
|
||||
|
||||
this._animationBlockCount = 0;
|
||||
|
||||
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) {
|
||||
@@ -121,11 +123,11 @@ WindowManager.prototype = {
|
||||
|
||||
Main.overview.connect('showing', Lang.bind(this, function() {
|
||||
for (let i = 0; i < this._dimmedWindows.length; i++)
|
||||
this._undimParentWindow(this._dimmedWindows[i], true);
|
||||
this._undimWindow(this._dimmedWindows[i], true);
|
||||
}));
|
||||
Main.overview.connect('hiding', Lang.bind(this, function() {
|
||||
for (let i = 0; i < this._dimmedWindows.length; i++)
|
||||
this._dimParentWindow(this._dimmedWindows[i], true);
|
||||
this._dimWindow(this._dimmedWindows[i], true);
|
||||
}));
|
||||
},
|
||||
|
||||
@@ -139,8 +141,16 @@ WindowManager.prototype = {
|
||||
this._shellwm.connect('keybinding::' + keybinding, handler);
|
||||
},
|
||||
|
||||
blockAnimations: function() {
|
||||
this._animationBlockCount++;
|
||||
},
|
||||
|
||||
unblockAnimations: function() {
|
||||
this._animationBlockCount = Math.max(0, this._animationBlockCount - 1);
|
||||
},
|
||||
|
||||
_shouldAnimate : function(actor) {
|
||||
if (Main.overview.visible)
|
||||
if (Main.overview.visible || this._animationsBlocked > 0)
|
||||
return false;
|
||||
if (actor && (actor.meta_window.get_window_type() != Meta.WindowType.NORMAL))
|
||||
return false;
|
||||
@@ -224,41 +234,39 @@ WindowManager.prototype = {
|
||||
_unmaximizeWindowDone : function(shellwm, actor) {
|
||||
},
|
||||
|
||||
_parentHasOtherAttachedDialog: function(parent, self) {
|
||||
_hasAttachedDialogs: function(window, ignoreWindow) {
|
||||
var count = 0;
|
||||
parent.foreach_transient(function(win) {
|
||||
if (win.get_window_type() == Meta.WindowType.MODAL_DIALOG && win != self)
|
||||
window.foreach_transient(function(win) {
|
||||
if (win != ignoreWindow && win.get_window_type() == Meta.WindowType.MODAL_DIALOG)
|
||||
count++;
|
||||
return false;
|
||||
});
|
||||
return count != 0;
|
||||
},
|
||||
|
||||
_markParentWindowAsDimmable: function(actor, animate) {
|
||||
if (Meta.prefs_get_attach_modal_dialogs()) {
|
||||
this._dimmedWindows.push(actor);
|
||||
if (this._shouldAnimate())
|
||||
this._dimParentWindow(actor, animate);
|
||||
_checkDimming: function(window, ignoreWindow) {
|
||||
let shouldDim = Meta.prefs_get_attach_modal_dialogs() && this._hasAttachedDialogs(window, ignoreWindow);
|
||||
|
||||
if (shouldDim && !window._dimmed) {
|
||||
window._dimmed = true;
|
||||
this._dimmedWindows.push(window);
|
||||
if (!Main.overview.visible)
|
||||
this._dimWindow(window, true);
|
||||
} else if (!shouldDim && window._dimmed) {
|
||||
window._dimmed = false;
|
||||
this._dimmedWindows = this._dimmedWindows.filter(function(win) {
|
||||
return win != window;
|
||||
});
|
||||
if (!Main.overview.visible)
|
||||
this._undimWindow(window, true);
|
||||
}
|
||||
},
|
||||
|
||||
_unmarkParentWindowAsDimmable: function(actor, animate) {
|
||||
if (!Main.overview.visible)
|
||||
this._undimParentWindow(actor, true);
|
||||
this._dimmedWindows = this._dimmedWindows.filter(function(win) {
|
||||
return win != actor;
|
||||
});
|
||||
},
|
||||
|
||||
_dimParentWindow: function(actor, animate) {
|
||||
let meta = actor.get_meta_window();
|
||||
let parent = meta.get_transient_for();
|
||||
if (!parent)
|
||||
_dimWindow: function(window, animate) {
|
||||
let actor = window.get_compositor_private();
|
||||
if (!actor)
|
||||
return;
|
||||
let parentActor = parent.get_compositor_private();
|
||||
if (!parentActor || this._parentHasOtherAttachedDialog(parent, meta))
|
||||
return;
|
||||
let texture = parentActor.get_texture();
|
||||
let texture = actor.get_texture();
|
||||
if (animate)
|
||||
Tweener.addTween(getWindowDimmer(texture),
|
||||
{ dimFraction: 1.0,
|
||||
@@ -269,15 +277,11 @@ WindowManager.prototype = {
|
||||
getWindowDimmer(texture).dimFraction = 1.0;
|
||||
},
|
||||
|
||||
_undimParentWindow: function(actor, animate) {
|
||||
let meta = actor.get_meta_window();
|
||||
let parent = meta.get_transient_for();
|
||||
if (!parent)
|
||||
_undimWindow: function(window, animate) {
|
||||
let actor = window.get_compositor_private();
|
||||
if (!actor)
|
||||
return;
|
||||
let parentActor = parent.get_compositor_private();
|
||||
if (!parentActor || this._parentHasOtherAttachedDialog(parent, meta))
|
||||
return;
|
||||
let texture = parentActor.get_texture();
|
||||
let texture = actor.get_texture();
|
||||
if (animate)
|
||||
Tweener.addTween(getWindowDimmer(texture),
|
||||
{ dimFraction: 0.0,
|
||||
@@ -294,17 +298,19 @@ WindowManager.prototype = {
|
||||
let type = actor.meta_window.get_window_type();
|
||||
if (type == actor._windowType)
|
||||
return;
|
||||
if (type == Meta.WindowType.MODAL_DIALOG)
|
||||
this._markParentWindowAsDimmable(actor, true);
|
||||
else if (actor._windowType == Meta.WindowType.MODAL_DIALOG)
|
||||
this._unmarkParentWindowAsDimmable(actor, true);
|
||||
if (type == Meta.WindowType.MODAL_DIALOG ||
|
||||
actor._windowType == Meta.WindowType.MODAL_DIALOG) {
|
||||
let parent = actor.get_meta_window().get_transient_for();
|
||||
if (parent)
|
||||
this._checkDimming(parent);
|
||||
}
|
||||
|
||||
actor._windowType = type;
|
||||
}));
|
||||
if (actor.meta_window.get_window_type() == Meta.WindowType.MODAL_DIALOG
|
||||
&& Meta.prefs_get_attach_modal_dialogs()
|
||||
&& actor.get_meta_window().get_transient_for()) {
|
||||
this._markParentWindowAsDimmable(actor, true);
|
||||
this._checkDimming(actor.get_meta_window().get_transient_for());
|
||||
if (this._shouldAnimate()) {
|
||||
actor.set_scale(1.0, 0.0);
|
||||
actor.show();
|
||||
@@ -364,14 +370,20 @@ WindowManager.prototype = {
|
||||
},
|
||||
|
||||
_destroyWindow : function(shellwm, actor) {
|
||||
let parent = actor.meta_window.get_transient_for();
|
||||
let window = actor.meta_window;
|
||||
let parent = window.get_transient_for();
|
||||
if (actor._notifyWindowTypeSignalId) {
|
||||
actor.meta_window.disconnect(actor._notifyWindowTypeSignalId);
|
||||
window.disconnect(actor._notifyWindowTypeSignalId);
|
||||
actor._notifyWindowTypeSignalId = 0;
|
||||
}
|
||||
while (actor.meta_window.get_window_type() == Meta.WindowType.MODAL_DIALOG
|
||||
if (window._dimmed) {
|
||||
this._dimmedWindows = this._dimmedWindows.filter(function(win) {
|
||||
return win != window;
|
||||
});
|
||||
}
|
||||
while (window.get_window_type() == Meta.WindowType.MODAL_DIALOG
|
||||
&& parent) {
|
||||
this._unmarkParentWindowAsDimmable(actor, true);
|
||||
this._checkDimming(parent, window);
|
||||
if (!Meta.prefs_get_attach_modal_dialogs()
|
||||
|| !this._shouldAnimate())
|
||||
break;
|
||||
|
||||
@@ -125,6 +125,7 @@ WindowClone.prototype = {
|
||||
dragActorMaxSize: WINDOW_DND_SIZE,
|
||||
dragActorOpacity: DRAGGING_WINDOW_OPACITY });
|
||||
this._draggable.connect('drag-begin', Lang.bind(this, this._onDragBegin));
|
||||
this._draggable.connect('drag-cancelled', Lang.bind(this, this._onDragCancelled));
|
||||
this._draggable.connect('drag-end', Lang.bind(this, this._onDragEnd));
|
||||
this.inDrag = false;
|
||||
|
||||
@@ -220,8 +221,15 @@ WindowClone.prototype = {
|
||||
|
||||
let [width, height] = this.actor.get_transformed_size();
|
||||
|
||||
this.actor.x = _clamp(this.actor.x, 0, global.screen_width - width);
|
||||
this.actor.y = _clamp(this.actor.y, Panel.PANEL_HEIGHT, global.screen_height - height);
|
||||
let monitorIndex = this.metaWindow.get_monitor();
|
||||
let availArea = global.get_monitors()[monitorIndex];
|
||||
if (monitorIndex == global.get_primary_monitor_index()) {
|
||||
availArea.y += Main.panel.actor.height;
|
||||
availArea.height -= Main.panel.actor.height;
|
||||
}
|
||||
|
||||
this.actor.x = _clamp(this.actor.x, availArea.x, availArea.x + availArea.width - width);
|
||||
this.actor.y = _clamp(this.actor.y, availArea.y, availArea.y + availArea.height - height);
|
||||
},
|
||||
|
||||
_zoomStart : function () {
|
||||
@@ -229,7 +237,7 @@ WindowClone.prototype = {
|
||||
this.emit('zoom-start');
|
||||
|
||||
if (!this._zoomLightbox)
|
||||
this._zoomLightbox = new Lightbox.Lightbox(global.stage,
|
||||
this._zoomLightbox = new Lightbox.Lightbox(Main.uiGroup,
|
||||
{ fadeTime: LIGHTBOX_FADE_TIME });
|
||||
this._zoomLightbox.show();
|
||||
|
||||
@@ -240,7 +248,7 @@ WindowClone.prototype = {
|
||||
this._zoomGlobalOrig.setPosition.apply(this._zoomGlobalOrig, this.actor.get_transformed_position());
|
||||
this._zoomGlobalOrig.setScale(width / this.actor.width, height / this.actor.height);
|
||||
|
||||
this.actor.reparent(global.stage);
|
||||
this.actor.reparent(Main.uiGroup);
|
||||
this._zoomLightbox.highlight(this.actor);
|
||||
|
||||
[this.actor.x, this.actor.y] = this._zoomGlobalOrig.getPosition();
|
||||
@@ -288,10 +296,19 @@ WindowClone.prototype = {
|
||||
},
|
||||
|
||||
_onDragBegin : function (draggable, time) {
|
||||
if (this._zooming)
|
||||
this._zoomEnd();
|
||||
|
||||
[this.dragOrigX, this.dragOrigY] = this.actor.get_position();
|
||||
this.dragOrigScale = this.actor.scale_x;
|
||||
this.inDrag = true;
|
||||
this.emit('drag-begin');
|
||||
},
|
||||
|
||||
_onDragCancelled : function (draggable, time) {
|
||||
this.emit('drag-cancelled');
|
||||
},
|
||||
|
||||
_onDragEnd : function (draggable, time, snapback) {
|
||||
this.inDrag = false;
|
||||
|
||||
@@ -327,6 +344,7 @@ WindowOverlay.prototype = {
|
||||
|
||||
this._windowClone = windowClone;
|
||||
this._parentActor = parentActor;
|
||||
this._hidden = false;
|
||||
|
||||
let title = new St.Label({ style_class: 'window-caption',
|
||||
text: metaWindow.title });
|
||||
@@ -372,23 +390,21 @@ WindowOverlay.prototype = {
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this._hidden = true;
|
||||
this.closeButton.hide();
|
||||
this.title.hide();
|
||||
},
|
||||
|
||||
show: function() {
|
||||
let [x, y, mask] = global.get_pointer();
|
||||
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE,
|
||||
x, y);
|
||||
if (actor == this._windowClone.actor) {
|
||||
this._hidden = false;
|
||||
if (this._windowClone.actor.has_pointer)
|
||||
this.closeButton.show();
|
||||
}
|
||||
this.title.show();
|
||||
},
|
||||
|
||||
fadeIn: function() {
|
||||
this.show();
|
||||
this.title.opacity = 0;
|
||||
this.title.show();
|
||||
this._parentActor.raise_top();
|
||||
Tweener.addTween(this.title,
|
||||
{ opacity: 255,
|
||||
@@ -480,6 +496,12 @@ WindowOverlay.prototype = {
|
||||
},
|
||||
|
||||
_onEnter: function() {
|
||||
// We might get enter events on the clone while the overlay is
|
||||
// hidden, e.g. during animations, we ignore these events,
|
||||
// as the close button will be shown as needed when the overlays
|
||||
// are shown again
|
||||
if (this._hidden)
|
||||
return;
|
||||
this._parentActor.raise_top();
|
||||
this.closeButton.show();
|
||||
this.emit('show-close-button');
|
||||
@@ -520,44 +542,45 @@ WindowOverlay.prototype = {
|
||||
Signals.addSignalMethods(WindowOverlay.prototype);
|
||||
|
||||
const WindowPositionFlags = {
|
||||
ZOOM: 1 << 0,
|
||||
INITIAL: 1 << 0,
|
||||
ANIMATE: 1 << 1
|
||||
};
|
||||
|
||||
/**
|
||||
* @metaWorkspace: a #Meta.Workspace
|
||||
* @metaWorkspace: a #Meta.Workspace, or null
|
||||
*/
|
||||
function Workspace(metaWorkspace) {
|
||||
this._init(metaWorkspace);
|
||||
function Workspace(metaWorkspace, monitorIndex) {
|
||||
this._init(metaWorkspace, monitorIndex);
|
||||
}
|
||||
|
||||
Workspace.prototype = {
|
||||
_init : function(metaWorkspace) {
|
||||
_init : function(metaWorkspace, monitorIndex) {
|
||||
// When dragging a window, we use this slot for reserve space.
|
||||
this._reservedSlot = null;
|
||||
this.metaWorkspace = metaWorkspace;
|
||||
this._x = 0;
|
||||
this._y = 0;
|
||||
this._width = 0;
|
||||
this._height = 0;
|
||||
|
||||
this.monitorIndex = monitorIndex;
|
||||
this._monitor = global.get_monitors()[this.monitorIndex];
|
||||
this._windowOverlaysGroup = new Clutter.Group();
|
||||
// Without this the drop area will be overlapped.
|
||||
this._windowOverlaysGroup.set_size(0, 0);
|
||||
|
||||
this.actor = new Clutter.Group();
|
||||
this.actor._delegate = this;
|
||||
this.actor.set_size(0, 0);
|
||||
|
||||
this._dropRect = new Clutter.Rectangle({ opacity: 0 });
|
||||
this._dropRect._delegate = this;
|
||||
|
||||
this.actor.add_actor(this._dropRect);
|
||||
this.actor.add_actor(this._windowOverlaysGroup);
|
||||
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
||||
// Items in _windowOverlaysGroup should not be scaled, so we don't
|
||||
// add them to this.actor, but to its parent whenever it changes
|
||||
this.actor.connect('parent-set', Lang.bind(this, this._onParentSet));
|
||||
|
||||
// Auto-sizing is unreliable in the presence of ClutterClone, so rather than
|
||||
// implicitly counting on the workspace actor to be sized to the size of the
|
||||
// included desktop actor clone, set the size explicitly to the screen size.
|
||||
// See http://bugzilla.openedhand.com/show_bug.cgi?id=1755
|
||||
this.actor.width = global.screen_width;
|
||||
this.actor.height = global.screen_height;
|
||||
this.scale = 1.0;
|
||||
|
||||
let windows = Main.getWindowActorsForWorkspace(this.metaWorkspace.index());
|
||||
let windows = global.get_window_actors().filter(this._isMyWindow, this);
|
||||
|
||||
// Create clones for windows that should be
|
||||
// visible in the Overview
|
||||
@@ -570,15 +593,37 @@ Workspace.prototype = {
|
||||
}
|
||||
|
||||
// Track window changes
|
||||
this._windowAddedId = this.metaWorkspace.connect('window-added',
|
||||
Lang.bind(this, this._windowAdded));
|
||||
this._windowRemovedId = this.metaWorkspace.connect('window-removed',
|
||||
Lang.bind(this, this._windowRemoved));
|
||||
if (this.metaWorkspace) {
|
||||
this._windowAddedId = this.metaWorkspace.connect('window-added',
|
||||
Lang.bind(this, this._windowAdded));
|
||||
this._windowRemovedId = this.metaWorkspace.connect('window-removed',
|
||||
Lang.bind(this, this._windowRemoved));
|
||||
}
|
||||
this._windowEnteredMonitorId = global.screen.connect('window-entered-monitor',
|
||||
Lang.bind(this, this._windowEnteredMonitor));
|
||||
this._windowLeftMonitorId = global.screen.connect('window-left-monitor',
|
||||
Lang.bind(this, this._windowLeftMonitor));
|
||||
this._repositionWindowsId = 0;
|
||||
|
||||
this.leavingOverview = false;
|
||||
},
|
||||
|
||||
setGeometry: function(x, y, width, height) {
|
||||
this._x = x;
|
||||
this._y = y;
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
|
||||
// This is sometimes called during allocation, so we do this later
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
|
||||
function () {
|
||||
this._dropRect.set_position(x, y);
|
||||
this._dropRect.set_size(width, height);
|
||||
return false;
|
||||
}));
|
||||
|
||||
},
|
||||
|
||||
_lookupIndex: function (metaWindow) {
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
if (this._windows[i].metaWindow == metaWindow) {
|
||||
@@ -588,17 +633,6 @@ Workspace.prototype = {
|
||||
return -1;
|
||||
},
|
||||
|
||||
_onParentSet: function(actor, old_parent) {
|
||||
let new_parent = this.actor.get_parent();
|
||||
if (new_parent == null)
|
||||
return;
|
||||
|
||||
if (old_parent)
|
||||
this._windowOverlaysGroup.reparent(new_parent);
|
||||
else
|
||||
new_parent.add_actor(this._windowOverlaysGroup);
|
||||
},
|
||||
|
||||
containsMetaWindow: function (metaWindow) {
|
||||
return this._lookupIndex(metaWindow) >= 0;
|
||||
},
|
||||
@@ -677,10 +711,20 @@ Workspace.prototype = {
|
||||
let xDelta, yDelta, distanceSquared;
|
||||
let actorWidth, actorHeight;
|
||||
|
||||
actorWidth = actor.width * actor.scale_x;
|
||||
actorHeight = actor.height * actor.scale_y;
|
||||
xDelta = actor.x + actorWidth / 2.0 - xCenter * global.screen_width;
|
||||
yDelta = actor.y + actorHeight / 2.0 - yCenter * global.screen_height;
|
||||
let x = actor.x;
|
||||
let y = actor.y;
|
||||
let scale = actor.scale_x;
|
||||
|
||||
if (actor._delegate.inDrag) {
|
||||
x = actor._delegate.dragOrigX;
|
||||
y = actor._delegate.dragOrigY;
|
||||
scale = actor._delegate.dragOrigScale;
|
||||
}
|
||||
|
||||
actorWidth = actor.width * scale;
|
||||
actorHeight = actor.height * scale;
|
||||
xDelta = x + actorWidth / 2.0 - xCenter * this._width - this._x;
|
||||
yDelta = y + actorHeight / 2.0 - yCenter * this._height - this._y;
|
||||
distanceSquared = xDelta * xDelta + yDelta * yDelta;
|
||||
|
||||
return distanceSquared;
|
||||
@@ -705,6 +749,12 @@ Workspace.prototype = {
|
||||
let delta = this._computeWindowMotion(cloneActor, slot);
|
||||
|
||||
motion += delta;
|
||||
|
||||
// Bail out early if we're already larger than the
|
||||
// previous best
|
||||
if (minimumMotionPermutation != null &&
|
||||
motion > minimumMotion)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (minimumMotionPermutation == null || motion < minimumMotion) {
|
||||
@@ -765,38 +815,35 @@ Workspace.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* _getSlotRelativeGeometry:
|
||||
* _getSlotGeometry:
|
||||
* @slot: A layout slot
|
||||
*
|
||||
* Returns: the workspace-relative [x, y, width, height]
|
||||
* Returns: the screen-relative [x, y, width, height]
|
||||
* of a given window layout slot.
|
||||
*/
|
||||
_getSlotRelativeGeometry: function(slot) {
|
||||
_getSlotGeometry: function(slot) {
|
||||
let [xCenter, yCenter, fraction] = slot;
|
||||
|
||||
let width = global.screen_width * fraction;
|
||||
let height = global.screen_height * fraction;
|
||||
let width = this._width * fraction;
|
||||
let height = this._height * fraction;
|
||||
|
||||
let x = xCenter * global.screen_width - width / 2;
|
||||
let y = yCenter * global.screen_height - height / 2;
|
||||
let x = this._x + xCenter * this._width - width / 2 ;
|
||||
let y = this._y + yCenter * this._height - height / 2;
|
||||
|
||||
return [x, y, width, height];
|
||||
},
|
||||
|
||||
/**
|
||||
* _computeWindowRelativeLayout:
|
||||
* _computeWindowLayout:
|
||||
* @metaWindow: A #MetaWindow
|
||||
* @slot: A layout slot
|
||||
*
|
||||
* Given a window and slot to fit it in, compute its
|
||||
* workspace-relative [x, y, scale] where scale applies
|
||||
* screen-relative [x, y, scale] where scale applies
|
||||
* to both X and Y directions.
|
||||
*/
|
||||
_computeWindowRelativeLayout: function(metaWindow, slot) {
|
||||
let [xCenter, yCenter, fraction] = slot;
|
||||
let [x, y, width, height] = this._getSlotRelativeGeometry(slot);
|
||||
|
||||
xCenter = xCenter * global.screen_width;
|
||||
_computeWindowLayout: function(metaWindow, slot) {
|
||||
let [x, y, width, height] = this._getSlotGeometry(slot);
|
||||
|
||||
let rect = metaWindow.get_outer_rect();
|
||||
let buttonOuterHeight, captionHeight;
|
||||
@@ -804,23 +851,19 @@ Workspace.prototype = {
|
||||
|
||||
if (this._windowOverlays[0]) {
|
||||
[buttonOuterHeight, captionHeight] = this._windowOverlays[0].chromeHeights();
|
||||
buttonOuterWidth = this._windowOverlays[0].chromeWidth() / this.scale;
|
||||
buttonOuterWidth = this._windowOverlays[0].chromeWidth();
|
||||
} else
|
||||
[buttonOuterHeight, captionHeight] = [0, 0];
|
||||
buttonOuterHeight /= this.scale;
|
||||
captionHeight /= this.scale;
|
||||
|
||||
let desiredWidth = global.screen_width * fraction;
|
||||
let desiredHeight = global.screen_height * fraction;
|
||||
let scale = Math.min((desiredWidth - buttonOuterWidth) / rect.width,
|
||||
(desiredHeight - buttonOuterHeight - captionHeight) / rect.height,
|
||||
1.0 / this.scale);
|
||||
let scale = Math.min((width - buttonOuterWidth) / rect.width,
|
||||
(height - buttonOuterHeight - captionHeight) / rect.height,
|
||||
1.0);
|
||||
|
||||
x = Math.floor(xCenter - 0.5 * scale * rect.width);
|
||||
x = Math.floor(x + (width - scale * rect.width) / 2);
|
||||
|
||||
// We want to center the window in case we have just one
|
||||
if (metaWindow.get_workspace().n_windows == 1)
|
||||
y = Math.floor(yCenter * global.screen_height - 0.5 * scale * rect.height);
|
||||
y = Math.floor(y + (height - scale * rect.height) / 2);
|
||||
else
|
||||
y = Math.floor(y + height - rect.height * scale - captionHeight);
|
||||
|
||||
@@ -846,7 +889,7 @@ Workspace.prototype = {
|
||||
/**
|
||||
* positionWindows:
|
||||
* @flags:
|
||||
* ZOOM - workspace is moving at the same time and we need to take that into account.
|
||||
* INITIAL - this is the initial positioning of the windows.
|
||||
* ANIMATE - Indicates that we need animate changing position.
|
||||
*/
|
||||
positionWindows : function(flags) {
|
||||
@@ -859,7 +902,7 @@ Workspace.prototype = {
|
||||
if (this._reservedSlot)
|
||||
clones.push(this._reservedSlot);
|
||||
|
||||
let workspaceZooming = flags & WindowPositionFlags.ZOOM;
|
||||
let initialPositioning = flags & WindowPositionFlags.INITIAL;
|
||||
let animate = flags & WindowPositionFlags.ANIMATE;
|
||||
|
||||
// Start the animations
|
||||
@@ -867,7 +910,7 @@ Workspace.prototype = {
|
||||
clones = this._orderWindowsByMotionAndStartup(clones, slots);
|
||||
|
||||
let currentWorkspace = global.screen.get_active_workspace();
|
||||
let isOnCurrentWorkspace = this.metaWorkspace == currentWorkspace;
|
||||
let isOnCurrentWorkspace = this.metaWorkspace == null || this.metaWorkspace == currentWorkspace;
|
||||
|
||||
for (let i = 0; i < clones.length; i++) {
|
||||
let slot = slots[i];
|
||||
@@ -881,7 +924,7 @@ Workspace.prototype = {
|
||||
if (clone.inDrag)
|
||||
continue;
|
||||
|
||||
let [x, y, scale] = this._computeWindowRelativeLayout(metaWindow, slot);
|
||||
let [x, y, scale] = this._computeWindowLayout(metaWindow, slot);
|
||||
|
||||
if (overlay)
|
||||
overlay.hide();
|
||||
@@ -890,7 +933,7 @@ Workspace.prototype = {
|
||||
/* Hidden windows should fade in and grow
|
||||
* therefore we need to resize them now so they
|
||||
* can be scaled up later */
|
||||
if (workspaceZooming) {
|
||||
if (initialPositioning) {
|
||||
clone.actor.opacity = 0;
|
||||
clone.actor.scale_x = 0;
|
||||
clone.actor.scale_y = 0;
|
||||
@@ -911,7 +954,6 @@ Workspace.prototype = {
|
||||
y: y,
|
||||
scale_x: scale,
|
||||
scale_y: scale,
|
||||
workspace_relative: workspaceZooming ? this : null,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this, function() {
|
||||
@@ -934,7 +976,7 @@ Workspace.prototype = {
|
||||
let clone = clones[i];
|
||||
let metaWindow = clone.metaWindow;
|
||||
if (i == 0) {
|
||||
clone.setStackAbove(null);
|
||||
clone.setStackAbove(this._dropRect);
|
||||
} else {
|
||||
let previousClone = clones[i - 1];
|
||||
clone.setStackAbove(previousClone.actor);
|
||||
@@ -954,10 +996,8 @@ Workspace.prototype = {
|
||||
// be after the workspace animation finishes.
|
||||
let [cloneX, cloneY] = clone.actor.get_position();
|
||||
let [cloneWidth, cloneHeight] = clone.actor.get_size();
|
||||
cloneX = this.x + this.scale * cloneX;
|
||||
cloneY = this.y + this.scale * cloneY;
|
||||
cloneWidth = this.scale * clone.actor.scale_x * cloneWidth;
|
||||
cloneHeight = this.scale * clone.actor.scale_y * cloneHeight;
|
||||
cloneWidth = clone.actor.scale_x * cloneWidth;
|
||||
cloneHeight = clone.actor.scale_y * cloneHeight;
|
||||
|
||||
if (overlay) {
|
||||
overlay.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight);
|
||||
@@ -973,7 +1013,8 @@ Workspace.prototype = {
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
let clone = this._windows[i];
|
||||
let overlay = this._windowOverlays[i];
|
||||
this._showWindowOverlay(clone, overlay, this.metaWorkspace == currentWorkspace);
|
||||
this._showWindowOverlay(clone, overlay,
|
||||
this.metaWorkspace == null || this.metaWorkspace == currentWorkspace);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -982,12 +1023,10 @@ Workspace.prototype = {
|
||||
return true;
|
||||
|
||||
let [x, y, mask] = global.get_pointer();
|
||||
let wsWidth = this.actor.width * this.scale;
|
||||
let wsHeight = this.actor.height * this.scale;
|
||||
|
||||
let pointerHasMoved = (this._cursorX != x && this._cursorY != y);
|
||||
let inWorkspace = (this.x < x && x < this.x + wsWidth &&
|
||||
this.y < y && y < this.y + wsHeight);
|
||||
let inWorkspace = (this._x < x && x < this._x + this._width &&
|
||||
this._y < y && y < this._y + this._height);
|
||||
|
||||
if (pointerHasMoved && inWorkspace) {
|
||||
// store current cursor position
|
||||
@@ -1012,7 +1051,7 @@ Workspace.prototype = {
|
||||
this._windowOverlaysGroup.hide();
|
||||
},
|
||||
|
||||
_windowRemoved : function(metaWorkspace, metaWin) {
|
||||
_doRemoveWindow : function(metaWin) {
|
||||
let win = metaWin.get_compositor_private();
|
||||
|
||||
// find the position of the window in our list
|
||||
@@ -1021,6 +1060,10 @@ Workspace.prototype = {
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
// Check if window still should be here
|
||||
if (win && this._isMyWindow(win))
|
||||
return;
|
||||
|
||||
let clone = this._windows[index];
|
||||
|
||||
this._windows.splice(index, 1);
|
||||
@@ -1064,7 +1107,7 @@ Workspace.prototype = {
|
||||
Lang.bind(this, this._delayedWindowRepositioning));
|
||||
},
|
||||
|
||||
_windowAdded : function(metaWorkspace, metaWin) {
|
||||
_doAddWindow : function(metaWin) {
|
||||
if (this.leavingOverview)
|
||||
return;
|
||||
|
||||
@@ -1075,31 +1118,65 @@ Workspace.prototype = {
|
||||
// the compositor finds out about them...
|
||||
Mainloop.idle_add(Lang.bind(this,
|
||||
function () {
|
||||
if (this.actor && metaWin.get_compositor_private())
|
||||
this._windowAdded(metaWorkspace, metaWin);
|
||||
if (this.actor &&
|
||||
metaWin.get_compositor_private() &&
|
||||
metaWin.get_workspace() == this.metaWorkspace)
|
||||
this._doAddWindow(metaWin);
|
||||
return false;
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._isOverviewWindow(win))
|
||||
// We might have the window in our list already if it was on all workspaces and
|
||||
// now was moved to this workspace
|
||||
if (this._lookupIndex (metaWin) != -1)
|
||||
return;
|
||||
|
||||
if (!this._isMyWindow(win) || !this._isOverviewWindow(win))
|
||||
return;
|
||||
|
||||
let clone = this._addWindowClone(win);
|
||||
|
||||
if (win._overviewHint) {
|
||||
let x = (win._overviewHint.x - this.actor.x) / this.scale;
|
||||
let y = (win._overviewHint.y - this.actor.y) / this.scale;
|
||||
let scale = win._overviewHint.scale / this.scale;
|
||||
let x = win._overviewHint.x - this.actor.x;
|
||||
let y = win._overviewHint.y - this.actor.y;
|
||||
let scale = win._overviewHint.scale;
|
||||
delete win._overviewHint;
|
||||
|
||||
clone.actor.set_position (x, y);
|
||||
clone.actor.set_scale (scale, scale);
|
||||
} else {
|
||||
// Position new windows at the top corner of the workspace rather
|
||||
// than where they were placed for real to avoid the window
|
||||
// being clipped to the workspaceView. Its not really more
|
||||
// natural for the window to suddenly appear in the overview
|
||||
// on some seemingly random location anyway.
|
||||
clone.actor.set_position (this._x, this._y);
|
||||
}
|
||||
|
||||
this.positionWindows(WindowPositionFlags.ANIMATE);
|
||||
},
|
||||
|
||||
_windowAdded : function(metaWorkspace, metaWin) {
|
||||
this._doAddWindow(metaWin);
|
||||
},
|
||||
|
||||
_windowRemoved : function(metaWorkspace, metaWin) {
|
||||
this._doRemoveWindow(metaWin);
|
||||
},
|
||||
|
||||
_windowEnteredMonitor : function(metaScreen, monitorIndex, metaWin) {
|
||||
if (monitorIndex == this.monitorIndex) {
|
||||
this._doAddWindow(metaWin);
|
||||
}
|
||||
},
|
||||
|
||||
_windowLeftMonitor : function(metaScreen, monitorIndex, metaWin) {
|
||||
if (monitorIndex == this.monitorIndex) {
|
||||
this._doRemoveWindow(metaWin);
|
||||
}
|
||||
},
|
||||
|
||||
// check for maximized windows on the workspace
|
||||
hasMaximizedWindows: function() {
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
@@ -1114,14 +1191,11 @@ Workspace.prototype = {
|
||||
|
||||
// Animate the full-screen to Overview transition.
|
||||
zoomToOverview : function() {
|
||||
this.actor.set_position(this.x, this.y);
|
||||
this.actor.set_scale(this.scale, this.scale);
|
||||
|
||||
// Position and scale the windows.
|
||||
if (Main.overview.animationInProgress)
|
||||
this.positionWindows(WindowPositionFlags.ANIMATE | WindowPositionFlags.ZOOM);
|
||||
this.positionWindows(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL);
|
||||
else
|
||||
this.positionWindows(WindowPositionFlags.ZOOM);
|
||||
this.positionWindows(WindowPositionFlags.INITIAL);
|
||||
},
|
||||
|
||||
// Animates the return from Overview mode
|
||||
@@ -1139,7 +1213,7 @@ Workspace.prototype = {
|
||||
this._overviewHiddenId = Main.overview.connect('hidden', Lang.bind(this,
|
||||
this._doneLeavingOverview));
|
||||
|
||||
if (this._metaWorkspace == currentWorkspace)
|
||||
if (this.metaWorkspace != null && this.metaWorkspace != currentWorkspace)
|
||||
return;
|
||||
|
||||
// Position and scale the windows.
|
||||
@@ -1154,7 +1228,6 @@ Workspace.prototype = {
|
||||
y: clone.origY,
|
||||
scale_x: 1.0,
|
||||
scale_y: 1.0,
|
||||
workspace_relative: this,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
opacity: 255,
|
||||
transition: 'easeOutQuad'
|
||||
@@ -1165,7 +1238,6 @@ Workspace.prototype = {
|
||||
{ scale_x: 0,
|
||||
scale_y: 0,
|
||||
opacity: 0,
|
||||
workspace_relative: this,
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
@@ -1185,8 +1257,12 @@ Workspace.prototype = {
|
||||
}
|
||||
Tweener.removeTweens(actor);
|
||||
|
||||
this.metaWorkspace.disconnect(this._windowAddedId);
|
||||
this.metaWorkspace.disconnect(this._windowRemovedId);
|
||||
if (this.metaWorkspace) {
|
||||
this.metaWorkspace.disconnect(this._windowAddedId);
|
||||
this.metaWorkspace.disconnect(this._windowRemovedId);
|
||||
}
|
||||
global.screen.disconnect(this._windowEnteredMonitorId);
|
||||
global.screen.disconnect(this._windowLeftMonitorId);
|
||||
|
||||
if (this._repositionWindowsId > 0)
|
||||
Mainloop.source_remove(this._repositionWindowsId);
|
||||
@@ -1205,9 +1281,10 @@ Workspace.prototype = {
|
||||
this.leavingOverview = false;
|
||||
},
|
||||
|
||||
// Tests if @win belongs to this workspaces
|
||||
// Tests if @win belongs to this workspaces and monitor
|
||||
_isMyWindow : function (win) {
|
||||
return Main.isWindowActorDisplayedOnWorkspace(win, this.metaWorkspace.index());
|
||||
return (this.metaWorkspace == null || Main.isWindowActorDisplayedOnWorkspace(win, this.metaWorkspace.index())) &&
|
||||
(!win.get_meta_window() || win.get_meta_window().get_monitor() == this.monitorIndex);
|
||||
},
|
||||
|
||||
// Tests if @win should be shown in the Overview
|
||||
@@ -1228,6 +1305,10 @@ Workspace.prototype = {
|
||||
Main.overview.beginWindowDrag();
|
||||
overlay.hide();
|
||||
}));
|
||||
clone.connect('drag-cancelled',
|
||||
Lang.bind(this, function(clone) {
|
||||
Main.overview.cancelledWindowDrag();
|
||||
}));
|
||||
clone.connect('drag-end',
|
||||
Lang.bind(this, function(clone) {
|
||||
Main.overview.endWindowDrag();
|
||||
@@ -1291,8 +1372,10 @@ Workspace.prototype = {
|
||||
},
|
||||
|
||||
_onCloneSelected : function (clone, time) {
|
||||
Main.activateWindow(clone.metaWindow, time,
|
||||
this.metaWorkspace.index());
|
||||
let wsIndex = undefined;
|
||||
if (this.metaWorkspace)
|
||||
wsIndex = this.metaWorkspace.index();
|
||||
Main.activateWindow(clone.metaWindow, time, wsIndex);
|
||||
},
|
||||
|
||||
// Draggable target interface
|
||||
@@ -1320,7 +1403,15 @@ Workspace.prototype = {
|
||||
};
|
||||
|
||||
let metaWindow = win.get_meta_window();
|
||||
metaWindow.change_workspace_by_index(this.metaWorkspace.index(),
|
||||
|
||||
// We need to move the window before changing the workspace, because
|
||||
// the move itself could cause a workspace change if the window enters
|
||||
// the primary monitor
|
||||
if (metaWindow.get_monitor() != this.monitorIndex)
|
||||
metaWindow.move_to_monitor(this.monitorIndex);
|
||||
|
||||
let index = this.metaWorkspace ? this.metaWorkspace.index() : global.screen.get_active_workspace_index();
|
||||
metaWindow.change_workspace_by_index(index,
|
||||
false, // don't create workspace
|
||||
time);
|
||||
return true;
|
||||
@@ -1335,56 +1426,3 @@ Workspace.prototype = {
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(Workspace.prototype);
|
||||
|
||||
// Create a SpecialPropertyModifier to let us move windows in a
|
||||
// straight line on the screen even though their containing workspace
|
||||
// is also moving.
|
||||
Tweener.registerSpecialPropertyModifier('workspace_relative', _workspaceRelativeModifier, _workspaceRelativeGet);
|
||||
|
||||
function _workspaceRelativeModifier(workspace) {
|
||||
let [startX, startY] = Main.overview.getPosition();
|
||||
let overviewPosX, overviewPosY, overviewScale;
|
||||
|
||||
if (!workspace)
|
||||
return [];
|
||||
|
||||
if (workspace.leavingOverview) {
|
||||
let [zoomedInX, zoomedInY] = Main.overview.getZoomedInPosition();
|
||||
overviewPosX = { begin: startX, end: zoomedInX };
|
||||
overviewPosY = { begin: startY, end: zoomedInY };
|
||||
overviewScale = { begin: Main.overview.getScale(),
|
||||
end: Main.overview.getZoomedInScale() };
|
||||
} else {
|
||||
overviewPosX = { begin: startX, end: 0 };
|
||||
overviewPosY = { begin: startY, end: 0 };
|
||||
overviewScale = { begin: Main.overview.getScale(), end: 1 };
|
||||
}
|
||||
|
||||
return [ { name: 'x',
|
||||
parameters: { workspacePos: workspace.x,
|
||||
overviewPos: overviewPosX,
|
||||
overviewScale: overviewScale } },
|
||||
{ name: 'y',
|
||||
parameters: { workspacePos: workspace.y,
|
||||
overviewPos: overviewPosY,
|
||||
overviewScale: overviewScale } }
|
||||
];
|
||||
}
|
||||
|
||||
function _workspaceRelativeGet(begin, end, time, params) {
|
||||
let curOverviewPos = (1 - time) * params.overviewPos.begin +
|
||||
time * params.overviewPos.end;
|
||||
let curOverviewScale = (1 - time) * params.overviewScale.begin +
|
||||
time * params.overviewScale.end;
|
||||
|
||||
// Calculate the screen position of the window.
|
||||
let screen = (1 - time) *
|
||||
((begin + params.workspacePos) * params.overviewScale.begin +
|
||||
params.overviewPos.begin) +
|
||||
time *
|
||||
((end + params.workspacePos) * params.overviewScale.end +
|
||||
params.overviewPos.end);
|
||||
|
||||
// Return the workspace coordinates.
|
||||
return (screen - curOverviewPos) / curOverviewScale - params.workspacePos;
|
||||
}
|
||||
|
||||
@@ -146,6 +146,7 @@ function WorkspaceThumbnail(metaWorkspace) {
|
||||
WorkspaceThumbnail.prototype = {
|
||||
_init : function(metaWorkspace) {
|
||||
this.metaWorkspace = metaWorkspace;
|
||||
this.monitorIndex = global.get_primary_monitor_index();
|
||||
|
||||
this.actor = new St.Group({ reactive: true,
|
||||
clip_to_allocation: true,
|
||||
@@ -169,7 +170,8 @@ WorkspaceThumbnail.prototype = {
|
||||
this._background = new Clutter.Clone({ source: global.background_actor });
|
||||
this._contents.add_actor(this._background);
|
||||
|
||||
this.setPorthole(0, 0, global.screen_width, global.screen_height);
|
||||
let monitor = global.get_primary_monitor();
|
||||
this.setPorthole(monitor.x, monitor.y, monitor.width, monitor.height);
|
||||
|
||||
let windows = global.get_window_actors().filter(this._isMyWindow, this);
|
||||
|
||||
@@ -186,6 +188,10 @@ WorkspaceThumbnail.prototype = {
|
||||
Lang.bind(this, this._windowAdded));
|
||||
this._windowRemovedId = this.metaWorkspace.connect('window-removed',
|
||||
Lang.bind(this, this._windowRemoved));
|
||||
this._windowEnteredMonitorId = global.screen.connect('window-entered-monitor',
|
||||
Lang.bind(this, this._windowEnteredMonitor));
|
||||
this._windowLeftMonitorId = global.screen.connect('window-left-monitor',
|
||||
Lang.bind(this, this._windowLeftMonitor));
|
||||
|
||||
this.state = ThumbnailState.NORMAL;
|
||||
this._slidePosition = 0; // Fully slid in
|
||||
@@ -193,6 +199,8 @@ WorkspaceThumbnail.prototype = {
|
||||
},
|
||||
|
||||
setPorthole: function(x, y, width, height) {
|
||||
this._portholeX = x;
|
||||
this._portholeY = y;
|
||||
this.actor.set_size(width, height);
|
||||
this._contents.set_position(-x, -y);
|
||||
},
|
||||
@@ -239,7 +247,7 @@ WorkspaceThumbnail.prototype = {
|
||||
return this._collapseFraction;
|
||||
},
|
||||
|
||||
_windowRemoved : function(metaWorkspace, metaWin) {
|
||||
_doRemoveWindow : function(metaWin) {
|
||||
let win = metaWin.get_compositor_private();
|
||||
|
||||
// find the position of the window in our list
|
||||
@@ -248,12 +256,16 @@ WorkspaceThumbnail.prototype = {
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
// Check if window still should be here
|
||||
if (win && this._isMyWindow(win))
|
||||
return;
|
||||
|
||||
let clone = this._windows[index];
|
||||
this._windows.splice(index, 1);
|
||||
clone.destroy();
|
||||
},
|
||||
|
||||
_windowAdded : function(metaWorkspace, metaWin) {
|
||||
_doAddWindow : function(metaWin) {
|
||||
if (this.leavingOverview)
|
||||
return;
|
||||
|
||||
@@ -264,19 +276,46 @@ WorkspaceThumbnail.prototype = {
|
||||
// the compositor finds out about them...
|
||||
Mainloop.idle_add(Lang.bind(this,
|
||||
function () {
|
||||
if (this.actor && metaWin.get_compositor_private())
|
||||
this._windowAdded(metaWorkspace, metaWin);
|
||||
if (this.actor &&
|
||||
metaWin.get_compositor_private() &&
|
||||
metaWin.get_workspace() == this.metaWorkspace)
|
||||
this._doAddWindow(metaWin);
|
||||
return false;
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._isOverviewWindow(win))
|
||||
// We might have the window in our list already if it was on all workspaces and
|
||||
// now was moved to this workspace
|
||||
if (this._lookupIndex (metaWin) != -1)
|
||||
return;
|
||||
|
||||
if (!this._isMyWindow(win) || !this._isOverviewWindow(win))
|
||||
return;
|
||||
|
||||
let clone = this._addWindowClone(win);
|
||||
},
|
||||
|
||||
_windowAdded : function(metaWorkspace, metaWin) {
|
||||
this._doAddWindow(metaWin);
|
||||
},
|
||||
|
||||
_windowRemoved : function(metaWorkspace, metaWin) {
|
||||
this._doRemoveWindow(metaWin);
|
||||
},
|
||||
|
||||
_windowEnteredMonitor : function(metaScreen, monitorIndex, metaWin) {
|
||||
if (monitorIndex == this.monitorIndex) {
|
||||
this._doAddWindow(metaWin);
|
||||
}
|
||||
},
|
||||
|
||||
_windowLeftMonitor : function(metaScreen, monitorIndex, metaWin) {
|
||||
if (monitorIndex == this.monitorIndex) {
|
||||
this._doRemoveWindow(metaWin);
|
||||
}
|
||||
},
|
||||
|
||||
destroy : function() {
|
||||
this.actor.destroy();
|
||||
},
|
||||
@@ -284,15 +323,17 @@ WorkspaceThumbnail.prototype = {
|
||||
_onDestroy: function(actor) {
|
||||
this.metaWorkspace.disconnect(this._windowAddedId);
|
||||
this.metaWorkspace.disconnect(this._windowRemovedId);
|
||||
global.screen.disconnect(this._windowEnteredMonitorId);
|
||||
global.screen.disconnect(this._windowLeftMonitorId);
|
||||
|
||||
this._windows = [];
|
||||
this.actor = null;
|
||||
},
|
||||
|
||||
// Tests if @win belongs to this workspaces
|
||||
// Tests if @win belongs to this workspace and monitor
|
||||
_isMyWindow : function (win) {
|
||||
return win.get_workspace() == this.metaWorkspace.index() ||
|
||||
(win.get_meta_window() && win.get_meta_window().is_on_all_workspaces());
|
||||
return Main.isWindowActorDisplayedOnWorkspace(win, this.metaWorkspace.index()) &&
|
||||
(!win.get_meta_window() || win.get_meta_window().get_monitor() == this.monitorIndex);
|
||||
},
|
||||
|
||||
// Tests if @win should be shown in the Overview
|
||||
@@ -340,6 +381,11 @@ WorkspaceThumbnail.prototype = {
|
||||
|
||||
// Draggable target interface
|
||||
handleDragOver : function(source, actor, x, y, time) {
|
||||
if (source == Main.xdndHandler) {
|
||||
this.metaWorkspace.activate(time);
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
}
|
||||
|
||||
if (this.state > ThumbnailState.NORMAL)
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
|
||||
@@ -361,6 +407,13 @@ WorkspaceThumbnail.prototype = {
|
||||
return false;
|
||||
|
||||
let metaWindow = win.get_meta_window();
|
||||
|
||||
// We need to move the window before changing the workspace, because
|
||||
// the move itself could cause a workspace change if the window enters
|
||||
// the primary monitor
|
||||
if (metaWindow.get_monitor() != this.monitorIndex)
|
||||
metaWindow.move_to_monitor(this.monitorIndex);
|
||||
|
||||
metaWindow.change_workspace_by_index(this.metaWorkspace.index(),
|
||||
false, // don't create workspace
|
||||
time);
|
||||
@@ -442,11 +495,12 @@ ThumbnailsBox.prototype = {
|
||||
|
||||
// The "porthole" is the portion of the screen that we show in the workspaces
|
||||
let panelHeight = Main.panel.actor.height;
|
||||
let monitor = global.get_primary_monitor();
|
||||
this._porthole = {
|
||||
x: 0,
|
||||
y: panelHeight,
|
||||
width: global.screen_width,
|
||||
height: global.screen_height - panelHeight
|
||||
x: monitor.x,
|
||||
y: monitor.y + panelHeight,
|
||||
width: monitor.width,
|
||||
height: monitor.height - panelHeight
|
||||
};
|
||||
|
||||
this.addThumbnails(0, global.screen.n_workspaces);
|
||||
|
||||
@@ -7,8 +7,6 @@ const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const Signals = imports.signals;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
const Main = imports.ui.main;
|
||||
@@ -25,14 +23,13 @@ const MAX_WORKSPACES = 16;
|
||||
const CONTROLS_POP_IN_TIME = 0.1;
|
||||
|
||||
|
||||
function WorkspacesView(width, height, x, y, workspaces) {
|
||||
this._init(width, height, x, y, workspaces);
|
||||
function WorkspacesView(workspaces) {
|
||||
this._init(workspaces);
|
||||
}
|
||||
|
||||
WorkspacesView.prototype = {
|
||||
_init: function(width, height, x, y, workspaces) {
|
||||
_init: function(workspaces) {
|
||||
this.actor = new St.Group({ style_class: 'workspaces-view' });
|
||||
this.actor.set_clip(x, y, width, height);
|
||||
|
||||
// The actor itself isn't a drop target, so we don't want to pick on its area
|
||||
this.actor.set_size(0, 0);
|
||||
@@ -43,19 +40,17 @@ WorkspacesView.prototype = {
|
||||
function() {
|
||||
let node = this.actor.get_theme_node();
|
||||
this._spacing = node.get_length('spacing');
|
||||
this._computeWorkspacePositions();
|
||||
this._updateWorkspaceActors(false);
|
||||
}));
|
||||
this.actor.connect('notify::mapped',
|
||||
Lang.bind(this, this._onMappedChanged));
|
||||
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
this._x = x;
|
||||
this._y = y;
|
||||
this._zoomScale = 1.0;
|
||||
this._width = 0;
|
||||
this._height = 0;
|
||||
this._x = 0;
|
||||
this._y = 0;
|
||||
this._workspaceRatioSpacing = 0;
|
||||
this._spacing = 0;
|
||||
this._activeWorkspaceX = 0; // x offset of active ws while dragging
|
||||
this._activeWorkspaceY = 0; // y offset of active ws while dragging
|
||||
this._lostWorkspaces = [];
|
||||
this._animating = false; // tweening
|
||||
this._scrolling = false; // swipe-scrolling
|
||||
@@ -71,6 +66,18 @@ WorkspacesView.prototype = {
|
||||
this._workspaces[w].actor.reparent(this.actor);
|
||||
this._workspaces[activeWorkspaceIndex].actor.raise_top();
|
||||
|
||||
this._extraWorkspaces = [];
|
||||
let monitors = global.get_monitors();
|
||||
let m = 0;
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (i == global.get_primary_monitor_index())
|
||||
continue;
|
||||
let ws = new Workspace.Workspace(null, i);
|
||||
this._extraWorkspaces[m++] = ws;
|
||||
ws.setGeometry(monitors[i].x, monitors[i].y, monitors[i].width, monitors[i].height);
|
||||
global.overlay_group.add_actor(ws.actor);
|
||||
}
|
||||
|
||||
// Position/scale the desktop windows and their children after the
|
||||
// workspaces have been created. This cannot be done first because
|
||||
// window movement depends on the Workspaces object being accessible
|
||||
@@ -80,6 +87,13 @@ WorkspacesView.prototype = {
|
||||
Lang.bind(this, function() {
|
||||
for (let w = 0; w < this._workspaces.length; w++)
|
||||
this._workspaces[w].zoomToOverview();
|
||||
for (let w = 0; w < this._extraWorkspaces.length; w++)
|
||||
this._extraWorkspaces[w].zoomToOverview();
|
||||
}));
|
||||
this._overviewShownId =
|
||||
Main.overview.connect('shown',
|
||||
Lang.bind(this, function() {
|
||||
this.actor.set_clip(this._x, this._y, this._width, this._height);
|
||||
}));
|
||||
|
||||
this._scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex,
|
||||
@@ -109,30 +123,18 @@ WorkspacesView.prototype = {
|
||||
this._swipeScrollEndId = 0;
|
||||
},
|
||||
|
||||
setZoomScale: function(zoomScale) {
|
||||
if (zoomScale == this._zoomScale)
|
||||
return;
|
||||
setGeometry: function(x, y, width, height, spacing) {
|
||||
if (this._x == x && this._y == y &&
|
||||
this._width == width && this._height == height)
|
||||
return;
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
this._x = x;
|
||||
this._y = y;
|
||||
this._workspaceRatioSpacing = spacing;
|
||||
|
||||
this._zoomScale = zoomScale;
|
||||
if (this._zoomOut) {
|
||||
// If we are already zoomed out, then we have to reposition.
|
||||
// Note that when shown initially zoomOut is false, so we
|
||||
// won't trigger this.
|
||||
|
||||
// setZoomScale can be invoked when the workspaces view is
|
||||
// reallocated. Since we just want to animate things to the
|
||||
// new position it seems OK to call updateWorkspaceActors
|
||||
// immediately - adding a tween doesn't immediately cause
|
||||
// a new allocation. But hide/show of the window overlays we
|
||||
// do around animation does, so we need to do it later.
|
||||
// This can be removed when we fix things to not hide/show
|
||||
// the window overlay.
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
|
||||
Lang.bind(this, function() {
|
||||
this._computeWorkspacePositions();
|
||||
this._updateWorkspaceActors(true);
|
||||
}));
|
||||
}
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
this._workspaces[i].setGeometry(x, y, width, height);
|
||||
},
|
||||
|
||||
_lookupWorkspaceForMetaWindow: function (metaWindow) {
|
||||
@@ -154,101 +156,41 @@ WorkspacesView.prototype = {
|
||||
|
||||
activeWorkspace.actor.raise_top();
|
||||
|
||||
this.actor.remove_clip(this._x, this._y, this._width, this._height);
|
||||
|
||||
for (let w = 0; w < this._workspaces.length; w++)
|
||||
this._workspaces[w].zoomFromOverview();
|
||||
for (let w = 0; w < this._extraWorkspaces.length; w++)
|
||||
this._extraWorkspaces[w].zoomFromOverview();
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.actor.destroy();
|
||||
},
|
||||
|
||||
getScale: function() {
|
||||
return this._workspaces[0].scale;
|
||||
},
|
||||
|
||||
syncStacking: function(stackIndices) {
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
this._workspaces[i].syncStacking(stackIndices);
|
||||
for (let i = 0; i < this._extraWorkspaces.length; i++)
|
||||
this._extraWorkspaces[i].syncStacking(stackIndices);
|
||||
},
|
||||
|
||||
// Get the grid position of the active workspace.
|
||||
getActiveWorkspacePosition: function() {
|
||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
||||
|
||||
return [activeWorkspace.x, activeWorkspace.y];
|
||||
},
|
||||
|
||||
zoomOut: function() {
|
||||
if (this._zoomOut)
|
||||
return;
|
||||
|
||||
this._zoomOut = true;
|
||||
this._computeWorkspacePositions();
|
||||
this._updateWorkspaceActors(true);
|
||||
},
|
||||
|
||||
zoomIn: function() {
|
||||
if (!this._zoomOut)
|
||||
return;
|
||||
|
||||
this._zoomOut = false;
|
||||
this._computeWorkspacePositions();
|
||||
this._updateWorkspaceActors(true);
|
||||
},
|
||||
|
||||
// Compute the position, scale and opacity of the workspaces, but don't
|
||||
// actually change the actors to match
|
||||
_computeWorkspacePositions: function() {
|
||||
let active = global.screen.get_active_workspace_index();
|
||||
let zoomScale = this._zoomOut ? this._zoomScale : 1;
|
||||
let scale = zoomScale * this._width / global.screen_width;
|
||||
|
||||
let _width = this._workspaces[0].actor.width * scale;
|
||||
let _height = this._workspaces[0].actor.height * scale;
|
||||
|
||||
this._activeWorkspaceX = (this._width - _width) / 2;
|
||||
this._activeWorkspaceY = (this._height - _height) / 2;
|
||||
|
||||
for (let w = 0; w < this._workspaces.length; w++) {
|
||||
let workspace = this._workspaces[w];
|
||||
|
||||
workspace.opacity = (this._inDrag && w != active) ? 200 : 255;
|
||||
|
||||
workspace.scale = scale;
|
||||
workspace.x = this._x + this._activeWorkspaceX;
|
||||
|
||||
// We adjust the center because the zoomScale is to leave space for
|
||||
// the expanded workspace control so we want to zoom to either the
|
||||
// left part of the area or the right part of the area
|
||||
let offset = 0.5 * (1 - this._zoomScale) * this._width;
|
||||
let rtl = (St.Widget.get_default_direction () == St.TextDirection.RTL);
|
||||
if (this._zoomOut)
|
||||
workspace.x += rtl ? offset : - offset;
|
||||
|
||||
// We divide by zoomScale so that adjacent workspaces are always offscreen
|
||||
// except when we are switching between workspaces
|
||||
workspace.y = this._y + this._activeWorkspaceY
|
||||
+ (w - active) * (_height + this._spacing) / zoomScale;
|
||||
}
|
||||
updateWindowPositions: function() {
|
||||
for (let w = 0; w < this._workspaces.length; w++)
|
||||
this._workspaces[w].positionWindows(Workspace.WindowPositionFlags.ANIMATE);
|
||||
},
|
||||
|
||||
_scrollToActive: function(showAnimation) {
|
||||
let active = global.screen.get_active_workspace_index();
|
||||
|
||||
this._computeWorkspacePositions();
|
||||
this._updateWorkspaceActors(showAnimation);
|
||||
this._updateScrollAdjustment(active, showAnimation);
|
||||
},
|
||||
|
||||
// Update workspace actors parameters to the values calculated in
|
||||
// _computeWorkspacePositions()
|
||||
// Update workspace actors parameters
|
||||
// @showAnimation: iff %true, transition between states
|
||||
_updateWorkspaceActors: function(showAnimation) {
|
||||
let active = global.screen.get_active_workspace_index();
|
||||
let targetWorkspaceNewY = this._y + this._activeWorkspaceY;
|
||||
let targetWorkspaceCurrentY = this._workspaces[active].y;
|
||||
let dy = targetWorkspaceNewY - targetWorkspaceCurrentY;
|
||||
|
||||
this._animating = showAnimation;
|
||||
|
||||
@@ -257,14 +199,10 @@ WorkspacesView.prototype = {
|
||||
|
||||
Tweener.removeTweens(workspace.actor);
|
||||
|
||||
workspace.y += dy;
|
||||
let y = (w - active) * (this._height + this._spacing + this._workspaceRatioSpacing);
|
||||
|
||||
if (showAnimation) {
|
||||
let params = { x: workspace.x,
|
||||
y: workspace.y,
|
||||
scale_x: workspace.scale,
|
||||
scale_y: workspace.scale,
|
||||
opacity: workspace.opacity,
|
||||
let params = { y: y,
|
||||
time: WORKSPACE_SWITCH_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
};
|
||||
@@ -281,9 +219,7 @@ WorkspacesView.prototype = {
|
||||
}
|
||||
Tweener.addTween(workspace.actor, params);
|
||||
} else {
|
||||
workspace.actor.set_scale(workspace.scale, workspace.scale);
|
||||
workspace.actor.set_position(workspace.x, workspace.y);
|
||||
workspace.actor.opacity = workspace.opacity;
|
||||
workspace.actor.set_position(0, y);
|
||||
if (w == 0)
|
||||
this._updateVisibility();
|
||||
}
|
||||
@@ -294,7 +230,6 @@ WorkspacesView.prototype = {
|
||||
|
||||
Tweener.removeTweens(workspace.actor);
|
||||
|
||||
workspace.y += dy;
|
||||
workspace.actor.show();
|
||||
workspace.hideWindowsOverlays();
|
||||
|
||||
@@ -338,7 +273,6 @@ WorkspacesView.prototype = {
|
||||
this._lostWorkspaces[l].destroy();
|
||||
this._lostWorkspaces = [];
|
||||
|
||||
this._computeWorkspacePositions();
|
||||
this._updateWorkspaceActors(false);
|
||||
},
|
||||
|
||||
@@ -380,7 +314,6 @@ WorkspacesView.prototype = {
|
||||
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++)
|
||||
this.actor.add_actor(this._workspaces[w].actor);
|
||||
|
||||
this._computeWorkspacePositions();
|
||||
this._updateWorkspaceActors(false);
|
||||
} else {
|
||||
this._lostWorkspaces = lostWorkspaces;
|
||||
@@ -397,10 +330,16 @@ WorkspacesView.prototype = {
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
for (let i = 0; i < this._extraWorkspaces.length; i++)
|
||||
this._extraWorkspaces[i].destroy();
|
||||
this._scrollAdjustment.run_dispose();
|
||||
Main.overview.disconnect(this._overviewShowingId);
|
||||
Main.overview.disconnect(this._overviewShownId);
|
||||
global.window_manager.disconnect(this._switchWorkspaceNotifyId);
|
||||
|
||||
if (this._inDrag)
|
||||
this._dragEnd();
|
||||
|
||||
if (this._timeoutId) {
|
||||
Mainloop.source_remove(this._timeoutId);
|
||||
this._timeoutId = 0;
|
||||
@@ -443,6 +382,7 @@ WorkspacesView.prototype = {
|
||||
return;
|
||||
|
||||
this._inDrag = true;
|
||||
this._firstDragMotion = true;
|
||||
|
||||
this._dragMonitor = {
|
||||
dragMotion: Lang.bind(this, this._onDragMotion)
|
||||
@@ -454,6 +394,14 @@ WorkspacesView.prototype = {
|
||||
if (Main.overview.animationInProgress)
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
|
||||
if (this._firstDragMotion) {
|
||||
this._firstDragMotion = false;
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
this._workspaces[i].setReservedSlot(dragEvent.dragActor._delegate);
|
||||
for (let i = 0; i < this._extraWorkspaces.length; i++)
|
||||
this._extraWorkspaces[i].setReservedSlot(dragEvent.dragActor._delegate);
|
||||
}
|
||||
|
||||
let primary = global.get_primary_monitor();
|
||||
|
||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||
@@ -467,7 +415,6 @@ WorkspacesView.prototype = {
|
||||
let switchTop = (dragEvent.y <= topEdge && topWorkspace);
|
||||
if (switchTop && this._dragOverLastY != topEdge) {
|
||||
topWorkspace.metaWorkspace.activate(global.get_current_time());
|
||||
topWorkspace.setReservedSlot(dragEvent.dragActor._delegate);
|
||||
this._dragOverLastY = topEdge;
|
||||
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
@@ -476,7 +423,6 @@ WorkspacesView.prototype = {
|
||||
let switchBottom = (dragEvent.y >= bottomEdge && bottomWorkspace);
|
||||
if (switchBottom && this._dragOverLastY != bottomEdge) {
|
||||
bottomWorkspace.metaWorkspace.activate(global.get_current_time());
|
||||
bottomWorkspace.setReservedSlot(dragEvent.dragActor._delegate);
|
||||
this._dragOverLastY = bottomEdge;
|
||||
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
@@ -488,20 +434,14 @@ WorkspacesView.prototype = {
|
||||
if (topWorkspace) {
|
||||
if (topWorkspace.actor.contains(dragEvent.targetActor)) {
|
||||
hoverWorkspace = topWorkspace;
|
||||
topWorkspace.opacity = topWorkspace.actor.opacity = 255;
|
||||
result = topWorkspace.handleDragOver(dragEvent.source, dragEvent.dragActor);
|
||||
} else {
|
||||
topWorkspace.opacity = topWorkspace.actor.opacity = 200;
|
||||
}
|
||||
}
|
||||
|
||||
if (bottomWorkspace) {
|
||||
if (bottomWorkspace.actor.contains(dragEvent.targetActor)) {
|
||||
hoverWorkspace = bottomWorkspace;
|
||||
bottomWorkspace.opacity = bottomWorkspace.actor.opacity = 255;
|
||||
result = bottomWorkspace.handleDragOver(dragEvent.source, dragEvent.dragActor);
|
||||
} else {
|
||||
bottomWorkspace.opacity = bottomWorkspace.actor.opacity = 200;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,7 +451,6 @@ WorkspacesView.prototype = {
|
||||
this._timeoutId = Mainloop.timeout_add_seconds(1,
|
||||
Lang.bind(this, function() {
|
||||
hoverWorkspace.metaWorkspace.activate(global.get_current_time());
|
||||
hoverWorkspace.setReservedSlot(dragEvent.dragActor._delegate);
|
||||
return false;
|
||||
}));
|
||||
} else {
|
||||
@@ -534,6 +473,8 @@ WorkspacesView.prototype = {
|
||||
|
||||
for (let i = 0; i < this._workspaces.length; i++)
|
||||
this._workspaces[i].setReservedSlot(null);
|
||||
for (let i = 0; i < this._extraWorkspaces.length; i++)
|
||||
this._extraWorkspaces[i].setReservedSlot(null);
|
||||
},
|
||||
|
||||
_swipeScrollBegin: function() {
|
||||
@@ -557,12 +498,6 @@ WorkspacesView.prototype = {
|
||||
Main.overview.hide();
|
||||
}
|
||||
|
||||
if (result == Overview.SwipeScrollResult.SWIPE)
|
||||
// The active workspace has changed; while swipe-scrolling
|
||||
// has already taken care of the positioning, the cached
|
||||
// positions need to be updated
|
||||
this._computeWorkspacePositions();
|
||||
|
||||
// Make sure title captions etc are shown as necessary
|
||||
this._updateVisibility();
|
||||
},
|
||||
@@ -590,7 +525,7 @@ WorkspacesView.prototype = {
|
||||
return;
|
||||
|
||||
let currentY = firstWorkspaceY;
|
||||
let newY = this._y - adj.value / (adj.upper - 1) * workspacesHeight;
|
||||
let newY = - adj.value / (adj.upper - 1) * workspacesHeight;
|
||||
|
||||
let dy = newY - currentY;
|
||||
|
||||
@@ -618,6 +553,7 @@ WorkspacesDisplay.prototype = {
|
||||
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.set_clip_to_allocation(true);
|
||||
|
||||
let controls = new St.Bin({ style_class: 'workspace-controls',
|
||||
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT,
|
||||
@@ -633,6 +569,8 @@ WorkspacesDisplay.prototype = {
|
||||
controls.connect('scroll-event',
|
||||
Lang.bind(this, this._onScrollEvent));
|
||||
|
||||
this._monitorIndex = global.get_primary_monitor_index();
|
||||
this._monitor = global.get_monitors()[this._monitorIndex];
|
||||
|
||||
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
|
||||
controls.add_actor(this._thumbnailsBox.actor);
|
||||
@@ -640,65 +578,53 @@ WorkspacesDisplay.prototype = {
|
||||
this.workspacesView = null;
|
||||
|
||||
this._inDrag = false;
|
||||
this._cancelledDrag = false;
|
||||
|
||||
this._alwaysZoomOut = false;
|
||||
this._zoomOut = false;
|
||||
this._zoomFraction = 0;
|
||||
|
||||
this._updateAlwaysZoom();
|
||||
|
||||
global.screen.connect('monitors-changed', Lang.bind(this, this._updateAlwaysZoom));
|
||||
Main.xdndHandler.connect('drag-begin', Lang.bind(this, function(){
|
||||
this._alwaysZoomOut = true;
|
||||
}));
|
||||
|
||||
Main.xdndHandler.connect('drag-end', Lang.bind(this, function(){
|
||||
this._alwaysZoomOut = false;
|
||||
this._updateAlwaysZoom();
|
||||
}));
|
||||
|
||||
this._nWorkspacesNotifyId = 0;
|
||||
this._switchWorkspaceNotifyId = 0;
|
||||
|
||||
this._itemDragBeginId = 0;
|
||||
this._itemDragCancelledId = 0;
|
||||
this._itemDragEndId = 0;
|
||||
this._windowDragBeginId = 0;
|
||||
this._windowDragCancelledId = 0;
|
||||
this._windowDragEndId = 0;
|
||||
},
|
||||
|
||||
show: function() {
|
||||
this._zoomOut = this._alwaysZoomOut;
|
||||
this._zoomFraction = this._alwaysZoomOut ? 1 : 0;
|
||||
this._updateZoom();
|
||||
|
||||
this._controls.show();
|
||||
this._thumbnailsBox.show();
|
||||
|
||||
this._workspaces = [];
|
||||
for (let i = 0; i < global.screen.n_workspaces; i++) {
|
||||
let metaWorkspace = global.screen.get_workspace_by_index(i);
|
||||
this._workspaces[i] = new Workspace.Workspace(metaWorkspace);
|
||||
this._workspaces[i] = new Workspace.Workspace(metaWorkspace, this._monitorIndex);
|
||||
}
|
||||
|
||||
let rtl = (St.Widget.get_default_direction () == St.TextDirection.RTL);
|
||||
|
||||
let totalAllocation = this.actor.allocation;
|
||||
let totalWidth = totalAllocation.x2 - totalAllocation.x1;
|
||||
let totalHeight = totalAllocation.y2 - totalAllocation.y1;
|
||||
|
||||
let controlsVisible = this._controls.get_theme_node().get_length('visible-width');
|
||||
|
||||
totalWidth -= controlsVisible;
|
||||
|
||||
// Workspaces expect to have the same ratio as the screen, so take
|
||||
// this into account when fitting the workspace into the available space
|
||||
let width, height;
|
||||
let totalRatio = totalWidth / totalHeight;
|
||||
let wsRatio = global.screen_width / global.screen_height;
|
||||
if (wsRatio > totalRatio) {
|
||||
width = totalWidth;
|
||||
height = Math.floor(totalWidth / wsRatio);
|
||||
} else {
|
||||
width = Math.floor(totalHeight * wsRatio);
|
||||
height = totalHeight;
|
||||
}
|
||||
|
||||
// Position workspaces in the available space
|
||||
let [x, y] = this.actor.get_transformed_position();
|
||||
x = Math.floor(x + Math.abs(totalWidth - width) / 2);
|
||||
y = Math.floor(y + Math.abs(totalHeight - height) / 2);
|
||||
|
||||
if (rtl)
|
||||
x += controlsVisible;
|
||||
|
||||
let newView = new WorkspacesView(width, height, x, y, this._workspaces);
|
||||
this._updateZoomScale();
|
||||
|
||||
if (this.workspacesView)
|
||||
this.workspacesView.destroy();
|
||||
this.workspacesView = newView;
|
||||
this.workspacesView = new WorkspacesView(this._workspaces);
|
||||
this._updateWorkspacesGeometry();
|
||||
|
||||
this._nWorkspacesNotifyId =
|
||||
global.screen.connect('notify::n-workspaces',
|
||||
@@ -711,20 +637,23 @@ WorkspacesDisplay.prototype = {
|
||||
if (this._itemDragBeginId == 0)
|
||||
this._itemDragBeginId = Main.overview.connect('item-drag-begin',
|
||||
Lang.bind(this, this._dragBegin));
|
||||
if (this._itemDragCancelledId == 0)
|
||||
this._itemDragCancelledId = Main.overview.connect('item-drag-cancelled',
|
||||
Lang.bind(this, this._dragCancelled));
|
||||
if (this._itemDragEndId == 0)
|
||||
this._itemDragEndId = Main.overview.connect('item-drag-end',
|
||||
Lang.bind(this, this._dragEnd));
|
||||
if (this._windowDragBeginId == 0)
|
||||
this._windowDragBeginId = Main.overview.connect('window-drag-begin',
|
||||
Lang.bind(this, this._dragBegin));
|
||||
if (this._windowDragCancelledId == 0)
|
||||
this._windowDragCancelledId = Main.overview.connect('window-drag-cancelled',
|
||||
Lang.bind(this, this._dragCancelled));
|
||||
if (this._windowDragEndId == 0)
|
||||
this._windowDragEndId = Main.overview.connect('window-drag-end',
|
||||
Lang.bind(this, this._dragEnd));
|
||||
|
||||
this._onRestacked();
|
||||
this._zoomOut = false;
|
||||
this._zoomFraction = 0;
|
||||
this._updateZoom();
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
@@ -743,7 +672,11 @@ WorkspacesDisplay.prototype = {
|
||||
Main.overview.disconnect(this._itemDragBeginId);
|
||||
this._itemDragBeginId = 0;
|
||||
}
|
||||
if (this._itemEndBeginId > 0) {
|
||||
if (this._itemDragCancelledId > 0) {
|
||||
Main.overview.disconnect(this._itemDragCancelledId);
|
||||
this._itemDragCancelledId = 0;
|
||||
}
|
||||
if (this._itemDragEndId > 0) {
|
||||
Main.overview.disconnect(this._itemDragEndId);
|
||||
this._itemDragEndId = 0;
|
||||
}
|
||||
@@ -751,6 +684,10 @@ WorkspacesDisplay.prototype = {
|
||||
Main.overview.disconnect(this._windowDragBeginId);
|
||||
this._windowDragBeginId = 0;
|
||||
}
|
||||
if (this._windowDragCancelledId > 0) {
|
||||
Main.overview.disconnect(this._windowDragCancelledId);
|
||||
this._windowDragCancelledId = 0;
|
||||
}
|
||||
if (this._windowDragEndId > 0) {
|
||||
Main.overview.disconnect(this._windowDragEndId);
|
||||
this._windowDragEndId = 0;
|
||||
@@ -774,6 +711,23 @@ WorkspacesDisplay.prototype = {
|
||||
return this._zoomFraction;
|
||||
},
|
||||
|
||||
_updateAlwaysZoom: function() {
|
||||
this._alwaysZoomOut = false;
|
||||
|
||||
let monitors = global.get_monitors();
|
||||
let primary = global.get_primary_monitor();
|
||||
|
||||
/* Look for any monitor to the right of the primary, if there is
|
||||
* one, we always keep zoom out, otherwise its hard to reach
|
||||
* the thumbnail area without passing into the next monitor. */
|
||||
for (let i = 0; i < monitors.length; i++) {
|
||||
if (monitors[i].x >= primary.x + primary.width) {
|
||||
this._alwaysZoomOut = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_getPreferredWidth: function (actor, forHeight, alloc) {
|
||||
// pass through the call in case the child needs it, but report 0x0
|
||||
this._controls.get_preferred_width(forHeight);
|
||||
@@ -809,22 +763,41 @@ WorkspacesDisplay.prototype = {
|
||||
childBox.y2 = box.y2- box.y1;
|
||||
this._controls.allocate(childBox, flags);
|
||||
|
||||
this._updateZoomScale();
|
||||
this._updateWorkspacesGeometry();
|
||||
},
|
||||
|
||||
_updateZoomScale: function() {
|
||||
_updateWorkspacesGeometry: function() {
|
||||
if (!this.workspacesView)
|
||||
return;
|
||||
|
||||
let totalAllocation = this.actor.allocation;
|
||||
let totalWidth = totalAllocation.x2 - totalAllocation.x1;
|
||||
let totalHeight = totalAllocation.y2 - totalAllocation.y1;
|
||||
let fullWidth = this.actor.allocation.x2 - this.actor.allocation.x1;
|
||||
let fullHeight = this.actor.allocation.y2 - this.actor.allocation.y1;
|
||||
|
||||
let [controlsMin, controlsNatural] = this._controls.get_preferred_width(totalHeight);
|
||||
let width = fullWidth;
|
||||
let height = fullHeight;
|
||||
|
||||
let [controlsMin, controlsNatural] = this._controls.get_preferred_width(height);
|
||||
let controlsVisible = this._controls.get_theme_node().get_length('visible-width');
|
||||
|
||||
let zoomScale = (totalWidth - controlsNatural) / (totalWidth - controlsVisible);
|
||||
this.workspacesView.setZoomScale(zoomScale);
|
||||
let [x, y] = this.actor.get_transformed_position();
|
||||
|
||||
let rtl = (St.Widget.get_default_direction () == St.TextDirection.RTL);
|
||||
|
||||
if (this._zoomOut) {
|
||||
width -= controlsNatural;
|
||||
if (rtl)
|
||||
x += controlsNatural;
|
||||
} else {
|
||||
width -= controlsVisible;
|
||||
if (rtl)
|
||||
x += controlsVisible;
|
||||
}
|
||||
|
||||
height = (fullHeight / fullWidth) * width;
|
||||
let difference = fullHeight - height;
|
||||
y += difference / 2;
|
||||
|
||||
this.workspacesView.setGeometry(x, y, width, height, difference);
|
||||
},
|
||||
|
||||
_onRestacked: function() {
|
||||
@@ -853,7 +826,7 @@ WorkspacesDisplay.prototype = {
|
||||
// Assume workspaces are only added at the end
|
||||
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
|
||||
let metaWorkspace = global.screen.get_workspace_by_index(w);
|
||||
this._workspaces[w] = new Workspace.Workspace(metaWorkspace);
|
||||
this._workspaces[w] = new Workspace.Workspace(metaWorkspace, this._monitorIndex);
|
||||
}
|
||||
|
||||
this._thumbnailsBox.addThumbnails(oldNumWorkspaces, newNumWorkspaces - oldNumWorkspaces);
|
||||
@@ -890,9 +863,10 @@ WorkspacesDisplay.prototype = {
|
||||
if (Main.overview.animationInProgress)
|
||||
return;
|
||||
|
||||
let shouldZoom = this._controls.hover || this._inDrag;
|
||||
let shouldZoom = this._alwaysZoomOut || this._controls.hover || (this._inDrag && !this._cancelledDrag);
|
||||
if (shouldZoom != this._zoomOut) {
|
||||
this._zoomOut = shouldZoom;
|
||||
this._updateWorkspacesGeometry();
|
||||
|
||||
if (!this.workspacesView)
|
||||
return;
|
||||
@@ -902,10 +876,7 @@ WorkspacesDisplay.prototype = {
|
||||
time: WORKSPACE_SWITCH_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
|
||||
if (shouldZoom)
|
||||
this.workspacesView.zoomOut();
|
||||
else
|
||||
this.workspacesView.zoomIn();
|
||||
this.workspacesView.updateWindowPositions();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -915,6 +886,12 @@ WorkspacesDisplay.prototype = {
|
||||
|
||||
_dragBegin: function() {
|
||||
this._inDrag = true;
|
||||
this._cancelledDrag = false;
|
||||
this._updateZoom();
|
||||
},
|
||||
|
||||
_dragCancelled: function() {
|
||||
this._cancelledDrag = true;
|
||||
this._updateZoom();
|
||||
},
|
||||
|
||||
|
||||
10
po/LINGUAS
@@ -1,13 +1,19 @@
|
||||
af
|
||||
an
|
||||
ar
|
||||
bg
|
||||
bn
|
||||
bn_IN
|
||||
ca
|
||||
cs
|
||||
da
|
||||
de
|
||||
el
|
||||
en_GB
|
||||
eo
|
||||
es
|
||||
et
|
||||
eu
|
||||
fa
|
||||
fi
|
||||
fr
|
||||
@@ -15,6 +21,7 @@ ga
|
||||
gl
|
||||
gu
|
||||
he
|
||||
hi
|
||||
hu
|
||||
id
|
||||
it
|
||||
@@ -22,6 +29,8 @@ ja
|
||||
ko
|
||||
kn
|
||||
lt
|
||||
lv
|
||||
mr
|
||||
nb
|
||||
nl
|
||||
nn
|
||||
@@ -31,6 +40,7 @@ pt
|
||||
pt_BR
|
||||
ro
|
||||
ru
|
||||
sk
|
||||
sl
|
||||
sr
|
||||
sr@latin
|
||||
|
||||
@@ -13,6 +13,7 @@ js/ui/messageTray.js
|
||||
js/ui/overview.js
|
||||
js/ui/panel.js
|
||||
js/ui/placeDisplay.js
|
||||
js/ui/polkitAuthenticationAgent.js
|
||||
js/ui/popupMenu.js
|
||||
js/ui/runDialog.js
|
||||
js/ui/searchDisplay.js
|
||||
@@ -20,6 +21,7 @@ js/ui/statusMenu.js
|
||||
js/ui/status/accessibility.js
|
||||
js/ui/status/bluetooth.js
|
||||
js/ui/status/keyboard.js
|
||||
js/ui/status/network.js
|
||||
js/ui/status/power.js
|
||||
js/ui/status/volume.js
|
||||
js/ui/telepathyClient.js
|
||||
@@ -29,8 +31,10 @@ js/ui/workspacesView.js
|
||||
src/gvc/gvc-mixer-control.c
|
||||
src/gdmuser/gdm-user.c
|
||||
src/main.c
|
||||
src/shell-app.c
|
||||
src/shell-app-system.c
|
||||
src/shell-global.c
|
||||
src/shell-mobile-providers.c
|
||||
src/shell-polkit-authentication-agent.c
|
||||
src/shell-util.c
|
||||
|
||||
|
||||
471
po/bg.po
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-03-05 23:07+0200\n"
|
||||
"PO-Revision-Date: 2011-03-05 23:07+0200\n"
|
||||
"POT-Creation-Date: 2011-03-27 08:03+0300\n"
|
||||
"PO-Revision-Date: 2011-03-27 08:03+0300\n"
|
||||
"Last-Translator: Ivaylo Valkov <ivaylo@e-valkov.org>\n"
|
||||
"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
|
||||
"Language: bg\n"
|
||||
@@ -174,47 +174,43 @@ msgstr "Дали да се събира статистика за използв
|
||||
msgid "disabled OpenSearch providers"
|
||||
msgstr "изключени доставчици на OpenSearch"
|
||||
|
||||
#: ../js/misc/util.js:86
|
||||
#: ../js/misc/util.js:71
|
||||
msgid "Command not found"
|
||||
msgstr "Командата не беше открита"
|
||||
|
||||
#. Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
#. something nicer
|
||||
#: ../js/misc/util.js:113
|
||||
#: ../js/misc/util.js:98
|
||||
msgid "Could not parse command:"
|
||||
msgstr "Неуспех при анализиране на командата:"
|
||||
|
||||
#: ../js/misc/util.js:135
|
||||
msgid "No such application"
|
||||
msgstr "Няма такава програма"
|
||||
|
||||
#: ../js/misc/util.js:148
|
||||
#: ../js/misc/util.js:106
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "Неуспешно изпълнение на „%s“:"
|
||||
|
||||
#. Translators: Filter to display all applications
|
||||
#: ../js/ui/appDisplay.js:195
|
||||
#: ../js/ui/appDisplay.js:230
|
||||
msgid "All"
|
||||
msgstr "Всички"
|
||||
|
||||
#: ../js/ui/appDisplay.js:285
|
||||
#: ../js/ui/appDisplay.js:328
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "ПРОГРАМИ"
|
||||
|
||||
#: ../js/ui/appDisplay.js:311
|
||||
#: ../js/ui/appDisplay.js:354
|
||||
msgid "SETTINGS"
|
||||
msgstr "НАСТРОЙКИ"
|
||||
|
||||
#: ../js/ui/appDisplay.js:565
|
||||
#: ../js/ui/appDisplay.js:625
|
||||
msgid "New Window"
|
||||
msgstr "Нов прозорец"
|
||||
|
||||
#: ../js/ui/appDisplay.js:568
|
||||
#: ../js/ui/appDisplay.js:628
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "Премахване от „Любими“"
|
||||
|
||||
#: ../js/ui/appDisplay.js:569
|
||||
#: ../js/ui/appDisplay.js:629
|
||||
msgid "Add to Favorites"
|
||||
msgstr "Добавяне в „Любими“"
|
||||
|
||||
@@ -244,7 +240,6 @@ msgstr "%H:%M"
|
||||
|
||||
#. Transators: Shown in calendar event list, if 12h format
|
||||
#: ../js/ui/calendar.js:78
|
||||
#, fuzzy
|
||||
msgctxt "event list time"
|
||||
msgid "%l:%M %p"
|
||||
msgstr "%l:%M %p"
|
||||
@@ -349,14 +344,12 @@ msgstr "Няма нищо запланувано"
|
||||
|
||||
#. Translators: Shown on calendar heading when selected day occurs on current year
|
||||
#: ../js/ui/calendar.js:720
|
||||
#, fuzzy
|
||||
msgctxt "calendar heading"
|
||||
msgid "%A, %B %d"
|
||||
msgstr "%A, %B %d"
|
||||
|
||||
#. Translators: Shown on calendar heading when selected day occurs on different year
|
||||
#: ../js/ui/calendar.js:723
|
||||
#, fuzzy
|
||||
msgctxt "calendar heading"
|
||||
msgid "%A, %B %d, %Y"
|
||||
msgstr "%A, %B, %d, %Y"
|
||||
@@ -377,7 +370,7 @@ msgstr "Тази седмица"
|
||||
msgid "Next week"
|
||||
msgstr "Следващата седмица"
|
||||
|
||||
#: ../js/ui/dash.js:174
|
||||
#: ../js/ui/dash.js:174 ../js/ui/messageTray.js:1000
|
||||
msgid "Remove"
|
||||
msgstr "Премахване"
|
||||
|
||||
@@ -385,55 +378,54 @@ msgstr "Премахване"
|
||||
msgid "Date and Time Settings"
|
||||
msgstr "Настройки на датата и времето"
|
||||
|
||||
#: ../js/ui/dateMenu.js:110
|
||||
#: ../js/ui/dateMenu.js:111
|
||||
msgid "Open Calendar"
|
||||
msgstr "Отваряне на календара"
|
||||
|
||||
#. Translators: This is the time format with date used
|
||||
#. in 24-hour mode.
|
||||
#: ../js/ui/dateMenu.js:162
|
||||
#: ../js/ui/dateMenu.js:164
|
||||
msgid "%a %b %e, %R:%S"
|
||||
msgstr "%a, %e %b, %R:%S"
|
||||
|
||||
#: ../js/ui/dateMenu.js:163
|
||||
#: ../js/ui/dateMenu.js:165
|
||||
msgid "%a %b %e, %R"
|
||||
msgstr "%a, %e %b, %R"
|
||||
|
||||
#. Translators: This is the time format without date used
|
||||
#. in 24-hour mode.
|
||||
#: ../js/ui/dateMenu.js:167
|
||||
#: ../js/ui/dateMenu.js:169
|
||||
msgid "%a %R:%S"
|
||||
msgstr "%a, %R:%S"
|
||||
|
||||
#: ../js/ui/dateMenu.js:168
|
||||
#: ../js/ui/dateMenu.js:170
|
||||
msgid "%a %R"
|
||||
msgstr "%a, %R"
|
||||
|
||||
#. Translators: This is a time format with date used
|
||||
#. for AM/PM.
|
||||
#: ../js/ui/dateMenu.js:175
|
||||
#: ../js/ui/dateMenu.js:177
|
||||
msgid "%a %b %e, %l:%M:%S %p"
|
||||
msgstr "%a, %e %b, %l:%M:%S %p"
|
||||
|
||||
#: ../js/ui/dateMenu.js:176
|
||||
#: ../js/ui/dateMenu.js:178
|
||||
msgid "%a %b %e, %l:%M %p"
|
||||
msgstr "%a, %e %b, %l:%M %p"
|
||||
|
||||
#. Translators: This is a time format without date used
|
||||
#. for AM/PM.
|
||||
#: ../js/ui/dateMenu.js:180
|
||||
#: ../js/ui/dateMenu.js:182
|
||||
msgid "%a %l:%M:%S %p"
|
||||
msgstr "%a %l:%M:%S %p"
|
||||
|
||||
#: ../js/ui/dateMenu.js:181
|
||||
#: ../js/ui/dateMenu.js:183
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a, %H:%M"
|
||||
|
||||
#. 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").
|
||||
#.
|
||||
#: ../js/ui/dateMenu.js:207
|
||||
#, fuzzy
|
||||
#: ../js/ui/dateMenu.js:194
|
||||
msgid "%A %B %e, %Y"
|
||||
msgstr "%A %B %e, %Y"
|
||||
|
||||
@@ -446,7 +438,7 @@ msgstr "СКОРО ОТВАРЯНИ"
|
||||
msgid "Log Out %s"
|
||||
msgstr "Изход на „%s“"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:64 ../js/ui/endSessionDialog.js:69
|
||||
#: ../js/ui/endSessionDialog.js:64 ../js/ui/endSessionDialog.js:70
|
||||
msgid "Log Out"
|
||||
msgstr "Изход"
|
||||
|
||||
@@ -469,49 +461,47 @@ msgstr "Ще излезете от системата автоматично с
|
||||
msgid "Logging out of the system."
|
||||
msgstr "Излизане от системата."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:74 ../js/ui/endSessionDialog.js:78
|
||||
msgid "Shut Down"
|
||||
msgstr "Изключване на компютъра"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:75
|
||||
msgid "Click Shut Down to quit these applications and shut down the system."
|
||||
msgstr ""
|
||||
"Натиснете „Изключване на системата“, за да спрете тези програми и да "
|
||||
"изключите системата."
|
||||
#: ../js/ui/endSessionDialog.js:75 ../js/ui/endSessionDialog.js:82
|
||||
msgid "Power Off"
|
||||
msgstr "Изключване"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:76
|
||||
#, c-format
|
||||
msgid "The system will shut down automatically in %d seconds."
|
||||
msgstr "Системата ще се изключи автоматично след %d секунди."
|
||||
msgid "Click Power Off to quit these applications and power off the system."
|
||||
msgstr ""
|
||||
"Натиснете „Изключване“, за да спрете тези програми и да излезете от "
|
||||
"системата."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:77
|
||||
msgid "Shutting down the system."
|
||||
#, c-format
|
||||
msgid "The system will power off automatically in %d seconds."
|
||||
msgstr "Системата ще се изключи автоматично след %d секунди."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:78
|
||||
msgid "Powering off the system."
|
||||
msgstr "Изключване на системата."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:84 ../js/ui/endSessionDialog.js:88
|
||||
#: ../js/ui/endSessionDialog.js:80 ../js/ui/endSessionDialog.js:88
|
||||
#: ../js/ui/endSessionDialog.js:93
|
||||
msgid "Restart"
|
||||
msgstr "Рестартиране"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:85
|
||||
#: ../js/ui/endSessionDialog.js:89
|
||||
msgid "Click Restart to quit these applications and restart the system."
|
||||
msgstr ""
|
||||
"Натиснете „Рестартиране“, за да спрете тези програми и да рестартирате "
|
||||
"системата."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:86
|
||||
#: ../js/ui/endSessionDialog.js:90
|
||||
#, c-format
|
||||
msgid "The system will restart automatically in %d seconds."
|
||||
msgstr "Системата ще се рестартира автоматично след %d секунди."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:87
|
||||
#: ../js/ui/endSessionDialog.js:91
|
||||
msgid "Restarting the system."
|
||||
msgstr "Рестартиране на системата."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:395
|
||||
msgid "Confirm"
|
||||
msgstr "Потвърждаване"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:400 ../js/ui/status/bluetooth.js:470
|
||||
#: ../js/ui/endSessionDialog.js:415 ../js/ui/polkitAuthenticationAgent.js:172
|
||||
#: ../js/ui/status/bluetooth.js:466
|
||||
msgid "Cancel"
|
||||
msgstr "Отказване"
|
||||
|
||||
@@ -525,7 +515,7 @@ msgstr "Включено"
|
||||
|
||||
#. translators:
|
||||
#. * The device has been disabled
|
||||
#: ../js/ui/lookingGlass.js:627 ../src/gvc/gvc-mixer-control.c:1087
|
||||
#: ../js/ui/lookingGlass.js:627 ../src/gvc/gvc-mixer-control.c:1091
|
||||
msgid "Disabled"
|
||||
msgstr "Изключено"
|
||||
|
||||
@@ -545,34 +535,48 @@ msgstr "Преглед на изходния код"
|
||||
msgid "Web Page"
|
||||
msgstr "Домашна страница"
|
||||
|
||||
#: ../js/ui/messageTray.js:1907
|
||||
#: ../js/ui/messageTray.js:993
|
||||
msgid "Open"
|
||||
msgstr "Отваряне"
|
||||
|
||||
#: ../js/ui/messageTray.js:2151
|
||||
msgid "System Information"
|
||||
msgstr "Информация за системата"
|
||||
|
||||
#: ../js/ui/overview.js:88
|
||||
#: ../js/ui/overview.js:91
|
||||
msgid "Undo"
|
||||
msgstr "Отмяна"
|
||||
|
||||
#: ../js/ui/overview.js:183
|
||||
#: ../js/ui/overview.js:186
|
||||
msgid "Windows"
|
||||
msgstr "Прозорци"
|
||||
|
||||
#: ../js/ui/overview.js:186
|
||||
#: ../js/ui/overview.js:189
|
||||
msgid "Applications"
|
||||
msgstr "Програми"
|
||||
|
||||
#. Translators: this is the name of the dock/favorites area on
|
||||
#. the left of the overview
|
||||
#: ../js/ui/overview.js:205
|
||||
msgid "Dash"
|
||||
msgstr "Най-ползвани"
|
||||
|
||||
#. TODO - _quit() doesn't really work on apps in state STARTING yet
|
||||
#: ../js/ui/panel.js:531
|
||||
#: ../js/ui/panel.js:515
|
||||
#, c-format
|
||||
msgid "Quit %s"
|
||||
msgstr "Спиране на програмата „%s“"
|
||||
|
||||
#. Button on the left side of the panel.
|
||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
||||
#: ../js/ui/panel.js:892
|
||||
#: ../js/ui/panel.js:878
|
||||
msgid "Activities"
|
||||
msgstr "Дейности"
|
||||
|
||||
#: ../js/ui/panel.js:979
|
||||
msgid "Top Bar"
|
||||
msgstr "Горна лента"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:122
|
||||
#, c-format
|
||||
msgid "Failed to unmount '%s'"
|
||||
@@ -586,65 +590,85 @@ msgstr "Повторен опит"
|
||||
msgid "Connect to..."
|
||||
msgstr "Свързване към…"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:409
|
||||
#: ../js/ui/placeDisplay.js:380
|
||||
msgid "PLACES & DEVICES"
|
||||
msgstr "МЕСТА И УСТРОЙСТВА"
|
||||
|
||||
#: ../js/ui/polkitAuthenticationAgent.js:74
|
||||
msgid "Authentication Required"
|
||||
msgstr "Необходимо е удостоверяване"
|
||||
|
||||
#: ../js/ui/polkitAuthenticationAgent.js:108
|
||||
msgid "Administrator"
|
||||
msgstr "Администратор"
|
||||
|
||||
#: ../js/ui/polkitAuthenticationAgent.js:176
|
||||
msgid "Authenticate"
|
||||
msgstr "Удостоверяване"
|
||||
|
||||
#: ../js/ui/polkitAuthenticationAgent.js:260
|
||||
msgid "Sorry, that didn't work. Please try again."
|
||||
msgstr "Действието не беше успешно. Опитайте отново."
|
||||
|
||||
#: ../js/ui/polkitAuthenticationAgent.js:272
|
||||
msgid "Password:"
|
||||
msgstr "Парола:"
|
||||
|
||||
#. Translators: this MUST be either "toggle-switch-us"
|
||||
#. (for toggle switches containing the English words
|
||||
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
|
||||
#. switches containing "◯" and "|"). Other values will
|
||||
#. simply result in invisible toggle switches.
|
||||
#: ../js/ui/popupMenu.js:612
|
||||
#: ../js/ui/popupMenu.js:679
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-intl"
|
||||
|
||||
#: ../js/ui/runDialog.js:201
|
||||
#: ../js/ui/runDialog.js:205
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Въведете команда:"
|
||||
|
||||
#: ../js/ui/searchDisplay.js:283
|
||||
#: ../js/ui/searchDisplay.js:310
|
||||
msgid "Searching..."
|
||||
msgstr "Търсене…"
|
||||
|
||||
#: ../js/ui/searchDisplay.js:297
|
||||
#: ../js/ui/searchDisplay.js:324
|
||||
msgid "No matching results."
|
||||
msgstr "Няма съвпадения."
|
||||
|
||||
#: ../js/ui/statusMenu.js:102 ../js/ui/statusMenu.js:166
|
||||
#: ../js/ui/statusMenu.js:161 ../js/ui/statusMenu.js:163
|
||||
#: ../js/ui/statusMenu.js:228
|
||||
msgid "Power Off..."
|
||||
msgstr "Изключване..."
|
||||
|
||||
#: ../js/ui/statusMenu.js:104 ../js/ui/statusMenu.js:165
|
||||
#: ../js/ui/statusMenu.js:163 ../js/ui/statusMenu.js:227
|
||||
msgid "Suspend"
|
||||
msgstr "Приспиване"
|
||||
|
||||
#: ../js/ui/statusMenu.js:125
|
||||
#: ../js/ui/statusMenu.js:184
|
||||
msgid "Available"
|
||||
msgstr "На линия"
|
||||
|
||||
#: ../js/ui/statusMenu.js:130
|
||||
#, fuzzy
|
||||
#: ../js/ui/statusMenu.js:189
|
||||
msgid "Busy"
|
||||
msgstr "Правя нещо друго"
|
||||
|
||||
#: ../js/ui/statusMenu.js:138
|
||||
#: ../js/ui/statusMenu.js:197
|
||||
msgid "My Account"
|
||||
msgstr "Моята регистрация"
|
||||
|
||||
#: ../js/ui/statusMenu.js:142
|
||||
#: ../js/ui/statusMenu.js:201
|
||||
msgid "System Settings"
|
||||
msgstr "Настройки на системата"
|
||||
|
||||
#: ../js/ui/statusMenu.js:149
|
||||
#: ../js/ui/statusMenu.js:208
|
||||
msgid "Lock Screen"
|
||||
msgstr "Заключване на екрана"
|
||||
|
||||
#: ../js/ui/statusMenu.js:153
|
||||
#: ../js/ui/statusMenu.js:213
|
||||
msgid "Switch User"
|
||||
msgstr "Смяна на потребител"
|
||||
|
||||
#: ../js/ui/statusMenu.js:158
|
||||
#: ../js/ui/statusMenu.js:218
|
||||
msgid "Log Out..."
|
||||
msgstr "Изход…"
|
||||
|
||||
@@ -652,14 +676,12 @@ msgstr "Изход…"
|
||||
msgid "Zoom"
|
||||
msgstr "Увеличаване"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:69
|
||||
msgid "Screen Reader"
|
||||
msgstr "Четец на екрана"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:73
|
||||
msgid "Screen Keyboard"
|
||||
msgstr "Екранна клавиатура"
|
||||
|
||||
#. let screenReader = this._buildItem(_("Screen Reader"), APPLICATIONS_SCHEMA,
|
||||
#. 'screen-reader-enabled');
|
||||
#. this.menu.addMenuItem(screenReader);
|
||||
#. let screenKeyboard = this._buildItem(_("Screen Keyboard"), APPLICATIONS_SCHEMA,
|
||||
#. 'screen-keyboard-enabled');
|
||||
#. this.menu.addMenuItem(screenKeyboard);
|
||||
#: ../js/ui/status/accessibility.js:77
|
||||
msgid "Visual Alerts"
|
||||
msgstr "Визуална помощ"
|
||||
@@ -684,17 +706,17 @@ msgstr "Клавиши за мишка"
|
||||
msgid "Universal Access Settings"
|
||||
msgstr "Настройки на универсалния достъп"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:145
|
||||
#: ../js/ui/status/accessibility.js:146
|
||||
msgid "High Contrast"
|
||||
msgstr "Висок контраст"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:182
|
||||
#: ../js/ui/status/accessibility.js:183
|
||||
msgid "Large Text"
|
||||
msgstr "Едър текст"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:241
|
||||
#: ../js/ui/status/bluetooth.js:337 ../js/ui/status/bluetooth.js:371
|
||||
#: ../js/ui/status/bluetooth.js:411 ../js/ui/status/bluetooth.js:444
|
||||
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:237
|
||||
#: ../js/ui/status/bluetooth.js:333 ../js/ui/status/bluetooth.js:367
|
||||
#: ../js/ui/status/bluetooth.js:407 ../js/ui/status/bluetooth.js:440
|
||||
msgid "Bluetooth"
|
||||
msgstr "Bluetooth"
|
||||
|
||||
@@ -714,94 +736,94 @@ msgstr "Добавяне на ново устройство..."
|
||||
msgid "Bluetooth Settings"
|
||||
msgstr "Настройки на Bluetooth"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:192
|
||||
#: ../js/ui/status/bluetooth.js:188
|
||||
msgid "Connection"
|
||||
msgstr "Свързване"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:228
|
||||
#: ../js/ui/status/bluetooth.js:224
|
||||
msgid "Send Files..."
|
||||
msgstr "Изпращане на файлове..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:233
|
||||
#: ../js/ui/status/bluetooth.js:229
|
||||
msgid "Browse Files..."
|
||||
msgstr "Разглеждане на файлове..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:242
|
||||
#: ../js/ui/status/bluetooth.js:238
|
||||
msgid "Error browsing device"
|
||||
msgstr "Грешка при разглеждане на устройството"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:243
|
||||
#: ../js/ui/status/bluetooth.js:239
|
||||
#, c-format
|
||||
msgid "The requested device cannot be browsed, error is '%s'"
|
||||
msgstr "Заявеното устройство не може да бъде разгледано. Грешката е „%s“"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:251
|
||||
#: ../js/ui/status/bluetooth.js:247
|
||||
msgid "Keyboard Settings"
|
||||
msgstr "Настройка на клавиатурата"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:256
|
||||
#: ../js/ui/status/bluetooth.js:252
|
||||
msgid "Mouse Settings"
|
||||
msgstr "Настройки на мишката"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:263 ../js/ui/status/volume.js:65
|
||||
#: ../js/ui/status/bluetooth.js:259 ../js/ui/status/volume.js:66
|
||||
msgid "Sound Settings"
|
||||
msgstr "Настройки на звука"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:372
|
||||
#: ../js/ui/status/bluetooth.js:368
|
||||
#, c-format
|
||||
msgid "Authorization request from %s"
|
||||
msgstr "Заявка за упълномощаване от „%s“"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:378
|
||||
#: ../js/ui/status/bluetooth.js:374
|
||||
#, c-format
|
||||
msgid "Device %s wants access to the service '%s'"
|
||||
msgstr "Устройството %s иска достъп до услугата „%s“"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:380
|
||||
#: ../js/ui/status/bluetooth.js:376
|
||||
msgid "Always grant access"
|
||||
msgstr "Винаги позволяване на достъп"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:381
|
||||
#: ../js/ui/status/bluetooth.js:377
|
||||
msgid "Grant this time only"
|
||||
msgstr "Позволяване само този път"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:382
|
||||
#: ../js/ui/status/bluetooth.js:378
|
||||
msgid "Reject"
|
||||
msgstr "Отхвърляне"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:412
|
||||
#: ../js/ui/status/bluetooth.js:408
|
||||
#, c-format
|
||||
msgid "Pairing confirmation for %s"
|
||||
msgstr "Потвърждение за сдвояване с „%s“"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:418 ../js/ui/status/bluetooth.js:452
|
||||
#: ../js/ui/status/bluetooth.js:414 ../js/ui/status/bluetooth.js:448
|
||||
#, c-format
|
||||
msgid "Device %s wants to pair with this computer"
|
||||
msgstr "Устройството %s иска да се сдвои с този компютър"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:419
|
||||
#: ../js/ui/status/bluetooth.js:415
|
||||
#, c-format
|
||||
msgid "Please confirm whether the PIN '%s' matches the one on the device."
|
||||
msgstr "Потвърдете дали кодът „%s“ съвпада с този на устройството."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:421
|
||||
#: ../js/ui/status/bluetooth.js:417
|
||||
msgid "Matches"
|
||||
msgstr "Съвпадения"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:422
|
||||
#: ../js/ui/status/bluetooth.js:418
|
||||
msgid "Does not match"
|
||||
msgstr "Няма съвпадения"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:445
|
||||
#: ../js/ui/status/bluetooth.js:441
|
||||
#, c-format
|
||||
msgid "Pairing request for %s"
|
||||
msgstr "Запитване за свързване с „%s“"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:453
|
||||
#: ../js/ui/status/bluetooth.js:449
|
||||
msgid "Please enter the PIN mentioned on the device."
|
||||
msgstr "Въведете кода на устройството %s."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:469
|
||||
#: ../js/ui/status/bluetooth.js:465
|
||||
msgid "OK"
|
||||
msgstr "Добре"
|
||||
|
||||
@@ -813,17 +835,153 @@ msgstr "Показване клавиатурната подредба…"
|
||||
msgid "Localization Settings"
|
||||
msgstr "Настройка на локализацията"
|
||||
|
||||
#: ../js/ui/status/network.js:104 ../js/ui/status/network.js:1454
|
||||
msgid "<unknown>"
|
||||
msgstr "<неизвестно>"
|
||||
|
||||
#. Translators: this indicates that wireless or wwan is disabled by hardware killswitch
|
||||
#: ../js/ui/status/network.js:311
|
||||
msgid "disabled"
|
||||
msgstr "изключено"
|
||||
|
||||
#: ../js/ui/status/network.js:494
|
||||
msgid "connecting..."
|
||||
msgstr "свързване…"
|
||||
|
||||
#. Translators: this is for network connections that require some kind of key or password
|
||||
#: ../js/ui/status/network.js:497
|
||||
msgid "authentication required"
|
||||
msgstr "изисква се удостоверяване"
|
||||
|
||||
#. Translators: this is for devices that require some kind of firmware or kernel
|
||||
#. module, which is missing
|
||||
#: ../js/ui/status/network.js:507
|
||||
msgid "firmware missing"
|
||||
msgstr "липсва фърмуер"
|
||||
|
||||
#. Translators: this is for wired network devices that are physically disconnected
|
||||
#: ../js/ui/status/network.js:514
|
||||
msgid "cable unplugged"
|
||||
msgstr "кабелът е изваден"
|
||||
|
||||
#. Translators: this is for a network device that cannot be activated (for example it
|
||||
#. is disabled by rfkill, or it has no coverage
|
||||
#: ../js/ui/status/network.js:519
|
||||
msgid "unavailable"
|
||||
msgstr "недостъпно"
|
||||
|
||||
#: ../js/ui/status/network.js:521
|
||||
msgid "connection failed"
|
||||
msgstr "връзката е неуспешна"
|
||||
|
||||
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
|
||||
#. and we cannot access its settings (including the name)
|
||||
#: ../js/ui/status/network.js:602 ../js/ui/status/network.js:1402
|
||||
msgid "Connected (private)"
|
||||
msgstr "Връзката е осъществена (няма налични данни)"
|
||||
|
||||
#: ../js/ui/status/network.js:683
|
||||
msgid "Auto Ethernet"
|
||||
msgstr "Автоматична мрежа по Ethernet"
|
||||
|
||||
#: ../js/ui/status/network.js:758
|
||||
msgid "Auto broadband"
|
||||
msgstr "Автоматична широколентова мрежа"
|
||||
|
||||
#: ../js/ui/status/network.js:761
|
||||
msgid "Auto dial-up"
|
||||
msgstr "Автоматична мрежа през модем"
|
||||
|
||||
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
|
||||
#: ../js/ui/status/network.js:904 ../js/ui/status/network.js:1414
|
||||
#, c-format
|
||||
msgid "Auto %s"
|
||||
msgstr "Автоматична мрежа към „%s“"
|
||||
|
||||
#: ../js/ui/status/network.js:906
|
||||
msgid "Auto bluetooth"
|
||||
msgstr "Автоматична мрежа по Bluetooth"
|
||||
|
||||
#: ../js/ui/status/network.js:1416
|
||||
msgid "Auto wireless"
|
||||
msgstr "Автоматична безжична мрежа"
|
||||
|
||||
#: ../js/ui/status/network.js:1474
|
||||
msgid "More..."
|
||||
msgstr "Повече…"
|
||||
|
||||
#: ../js/ui/status/network.js:1497
|
||||
msgid "Enable networking"
|
||||
msgstr "Включване на мрежата"
|
||||
|
||||
#: ../js/ui/status/network.js:1509
|
||||
msgid "Wired"
|
||||
msgstr "Жична"
|
||||
|
||||
#: ../js/ui/status/network.js:1520
|
||||
msgid "Wireless"
|
||||
msgstr "Безжична"
|
||||
|
||||
#: ../js/ui/status/network.js:1530
|
||||
msgid "Mobile broadband"
|
||||
msgstr "Мобилна широколентова"
|
||||
|
||||
#: ../js/ui/status/network.js:1540
|
||||
msgid "VPN Connections"
|
||||
msgstr "Връзки към ВЧМ"
|
||||
|
||||
#: ../js/ui/status/network.js:1549
|
||||
msgid "Network Settings"
|
||||
msgstr "Настройки на мрежата"
|
||||
|
||||
#: ../js/ui/status/network.js:1844
|
||||
#, c-format
|
||||
msgid "You're now connected to mobile broadband connection '%s'"
|
||||
msgstr "Връзката в момента е към мобилната широколентова мрежа „%s“"
|
||||
|
||||
#: ../js/ui/status/network.js:1848
|
||||
#, c-format
|
||||
msgid "You're now connected to wireless network '%s'"
|
||||
msgstr "Връзката в момента е към безжичната мрежа „%s“"
|
||||
|
||||
#: ../js/ui/status/network.js:1852
|
||||
#, c-format
|
||||
msgid "You're now connected to wired network '%s'"
|
||||
msgstr "Връзката в момента е към жичната мрежа „%s“"
|
||||
|
||||
#: ../js/ui/status/network.js:1856
|
||||
#, c-format
|
||||
msgid "You're now connected to VPN network '%s'"
|
||||
msgstr "Връзката в момента е към ВЧМ „%s“"
|
||||
|
||||
#: ../js/ui/status/network.js:1861
|
||||
#, c-format
|
||||
msgid "You're now connected to '%s'"
|
||||
msgstr "Връзката в момента е към „%s“"
|
||||
|
||||
#: ../js/ui/status/network.js:1869
|
||||
msgid "Connection established"
|
||||
msgstr "Връзката е осъществена"
|
||||
|
||||
#: ../js/ui/status/network.js:1991
|
||||
msgid "Networking is disabled"
|
||||
msgstr "Мрежата е изключена"
|
||||
|
||||
#: ../js/ui/status/network.js:2116
|
||||
msgid "Network Manager"
|
||||
msgstr "Управление на мрежата"
|
||||
|
||||
#: ../js/ui/status/power.js:85
|
||||
msgid "Power Settings"
|
||||
msgstr "Настройка на захранването"
|
||||
|
||||
#. 0 is reported when UPower does not have enough data
|
||||
#. to estimate battery life
|
||||
#: ../js/ui/status/power.js:110
|
||||
#: ../js/ui/status/power.js:111
|
||||
msgid "Estimating..."
|
||||
msgstr "Приблизително времето…"
|
||||
|
||||
#: ../js/ui/status/power.js:117
|
||||
#: ../js/ui/status/power.js:118
|
||||
#, c-format
|
||||
msgid "%d hour remaining"
|
||||
msgid_plural "%d hours remaining"
|
||||
@@ -831,110 +989,110 @@ msgstr[0] "Остава %d час"
|
||||
msgstr[1] "Остават %d часа"
|
||||
|
||||
#. TRANSLATORS: this is a time string, as in "%d hours %d minutes remaining"
|
||||
#: ../js/ui/status/power.js:120
|
||||
#: ../js/ui/status/power.js:121
|
||||
#, c-format
|
||||
msgid "%d %s %d %s remaining"
|
||||
msgstr "Остават %d %s и %d %s"
|
||||
|
||||
#: ../js/ui/status/power.js:122
|
||||
#: ../js/ui/status/power.js:123
|
||||
msgid "hour"
|
||||
msgid_plural "hours"
|
||||
msgstr[0] "час"
|
||||
msgstr[1] "часа"
|
||||
|
||||
#: ../js/ui/status/power.js:122
|
||||
#: ../js/ui/status/power.js:123
|
||||
msgid "minute"
|
||||
msgid_plural "minutes"
|
||||
msgstr[0] "минута"
|
||||
msgstr[1] "минути"
|
||||
|
||||
#: ../js/ui/status/power.js:125
|
||||
#: ../js/ui/status/power.js:126
|
||||
#, c-format
|
||||
msgid "%d minute remaining"
|
||||
msgid_plural "%d minutes remaining"
|
||||
msgstr[0] "остават %d минути"
|
||||
msgstr[1] "остават %d минути"
|
||||
|
||||
#: ../js/ui/status/power.js:227
|
||||
#: ../js/ui/status/power.js:228
|
||||
msgid "AC adapter"
|
||||
msgstr "Адаптер за ел. мрежа"
|
||||
|
||||
#: ../js/ui/status/power.js:229
|
||||
#: ../js/ui/status/power.js:230
|
||||
msgid "Laptop battery"
|
||||
msgstr "Батерия на преносим компютър"
|
||||
|
||||
#: ../js/ui/status/power.js:231
|
||||
#: ../js/ui/status/power.js:232
|
||||
msgid "UPS"
|
||||
msgstr "Непрекъсваемо токозахранване"
|
||||
|
||||
#: ../js/ui/status/power.js:233
|
||||
#: ../js/ui/status/power.js:234
|
||||
msgid "Monitor"
|
||||
msgstr "Монитор"
|
||||
|
||||
#: ../js/ui/status/power.js:235
|
||||
#: ../js/ui/status/power.js:236
|
||||
msgid "Mouse"
|
||||
msgstr "Мишка"
|
||||
|
||||
#: ../js/ui/status/power.js:237
|
||||
#: ../js/ui/status/power.js:238
|
||||
msgid "Keyboard"
|
||||
msgstr "Клавиатура"
|
||||
|
||||
#: ../js/ui/status/power.js:239
|
||||
#: ../js/ui/status/power.js:240
|
||||
msgid "PDA"
|
||||
msgstr "Цифров помощник"
|
||||
|
||||
#: ../js/ui/status/power.js:241
|
||||
#: ../js/ui/status/power.js:242
|
||||
msgid "Cell phone"
|
||||
msgstr "Мобилен телефон"
|
||||
|
||||
#: ../js/ui/status/power.js:243
|
||||
#: ../js/ui/status/power.js:244
|
||||
msgid "Media player"
|
||||
msgstr "Музикално устройство"
|
||||
|
||||
#: ../js/ui/status/power.js:245
|
||||
#: ../js/ui/status/power.js:246
|
||||
msgid "Tablet"
|
||||
msgstr "Таблет"
|
||||
|
||||
#: ../js/ui/status/power.js:247
|
||||
#: ../js/ui/status/power.js:248
|
||||
msgid "Computer"
|
||||
msgstr "Компютър"
|
||||
|
||||
#: ../js/ui/status/power.js:249 ../src/shell-app-system.c:1013
|
||||
#: ../js/ui/status/power.js:250 ../src/shell-app-system.c:1088
|
||||
msgid "Unknown"
|
||||
msgstr "Неизвестно"
|
||||
|
||||
#: ../js/ui/status/volume.js:44
|
||||
#: ../js/ui/status/volume.js:45
|
||||
msgid "Volume"
|
||||
msgstr "Сила на звука"
|
||||
|
||||
#: ../js/ui/status/volume.js:57
|
||||
#: ../js/ui/status/volume.js:58
|
||||
msgid "Microphone"
|
||||
msgstr "Микрофон"
|
||||
|
||||
#: ../js/ui/telepathyClient.js:239
|
||||
#: ../js/ui/telepathyClient.js:331
|
||||
#, c-format
|
||||
msgid "%s is online."
|
||||
msgstr "%s е на линия."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:244
|
||||
#: ../js/ui/telepathyClient.js:336
|
||||
#, c-format
|
||||
msgid "%s is offline."
|
||||
msgstr "%s не е на линия."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:247
|
||||
#: ../js/ui/telepathyClient.js:339
|
||||
#, c-format
|
||||
msgid "%s is away."
|
||||
msgstr "%s отсъства."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:250
|
||||
#, fuzzy, c-format
|
||||
#: ../js/ui/telepathyClient.js:342
|
||||
#, c-format
|
||||
msgid "%s is busy."
|
||||
msgstr "%s прави нещо друго."
|
||||
|
||||
#. Translators: this is a time format string followed by a date.
|
||||
#. If applicable, replace %X with a strftime format valid for your
|
||||
#. locale, without seconds.
|
||||
#: ../js/ui/telepathyClient.js:348
|
||||
#: ../js/ui/telepathyClient.js:473
|
||||
#, no-c-format
|
||||
msgid "Sent at %X on %A"
|
||||
msgstr "Изпратено на %2$A в %1$X"
|
||||
@@ -943,10 +1101,14 @@ msgstr "Изпратено на %2$A в %1$X"
|
||||
#. in the search entry when no search is
|
||||
#. active; it should not exceed ~30
|
||||
#. characters.
|
||||
#: ../js/ui/viewSelector.js:103
|
||||
#: ../js/ui/viewSelector.js:122
|
||||
msgid "Type to search..."
|
||||
msgstr "Търсене на написаното…"
|
||||
|
||||
#: ../js/ui/viewSelector.js:142 ../src/shell-util.c:250
|
||||
msgid "Search"
|
||||
msgstr "Търсене"
|
||||
|
||||
#: ../js/ui/windowAttentionHandler.js:42
|
||||
#, c-format
|
||||
msgid "%s has finished starting"
|
||||
@@ -959,7 +1121,7 @@ msgstr "Програмата „%s“ е готова за употреба"
|
||||
|
||||
#. translators:
|
||||
#. * The number of sound outputs on a particular device
|
||||
#: ../src/gvc/gvc-mixer-control.c:1094
|
||||
#: ../src/gvc/gvc-mixer-control.c:1098
|
||||
#, c-format
|
||||
msgid "%u Output"
|
||||
msgid_plural "%u Outputs"
|
||||
@@ -968,49 +1130,66 @@ msgstr[1] "%u изхода"
|
||||
|
||||
#. translators:
|
||||
#. * The number of sound inputs on a particular device
|
||||
#: ../src/gvc/gvc-mixer-control.c:1104
|
||||
#: ../src/gvc/gvc-mixer-control.c:1108
|
||||
#, c-format
|
||||
msgid "%u Input"
|
||||
msgid_plural "%u Inputs"
|
||||
msgstr[0] "%u вход"
|
||||
msgstr[1] "%u входа"
|
||||
|
||||
#: ../src/gvc/gvc-mixer-control.c:1402
|
||||
#: ../src/gvc/gvc-mixer-control.c:1406
|
||||
msgid "System Sounds"
|
||||
msgstr "Системни звуци"
|
||||
|
||||
#: ../src/shell-global.c:1298
|
||||
#: ../src/main.c:446
|
||||
msgid "Print version"
|
||||
msgstr "Показване на версията"
|
||||
|
||||
#: ../src/shell-app.c:454
|
||||
#, c-format
|
||||
msgid "Failed to launch '%s'"
|
||||
msgstr "Неуспех при стартиране на „%s“"
|
||||
|
||||
#: ../src/shell-global.c:1395
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Преди по-малко от минута"
|
||||
|
||||
#: ../src/shell-global.c:1302
|
||||
#: ../src/shell-global.c:1399
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "преди %d минута"
|
||||
msgstr[1] "преди %d минути"
|
||||
|
||||
#: ../src/shell-global.c:1307
|
||||
#: ../src/shell-global.c:1404
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "преди %d час"
|
||||
msgstr[1] "преди %d часа"
|
||||
|
||||
#: ../src/shell-global.c:1312
|
||||
#: ../src/shell-global.c:1409
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "преди %d ден"
|
||||
msgstr[1] "преди %d дни"
|
||||
|
||||
#: ../src/shell-global.c:1317
|
||||
#: ../src/shell-global.c:1414
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "преди %d седмица"
|
||||
msgstr[1] "преди %d седмици"
|
||||
|
||||
#: ../src/shell-mobile-providers.c:80
|
||||
msgid "United Kingdom"
|
||||
msgstr "Великобритания"
|
||||
|
||||
#: ../src/shell-mobile-providers.c:526
|
||||
msgid "Default"
|
||||
msgstr "Стандартно"
|
||||
|
||||
#: ../src/shell-polkit-authentication-agent.c:334
|
||||
msgid "Authentication dialog was dismissed by the user"
|
||||
msgstr "Прозорецът за упълномощаване беше затворен от потребителя"
|
||||
@@ -1025,10 +1204,6 @@ msgstr "Домашна папка"
|
||||
msgid "File System"
|
||||
msgstr "Файлова система"
|
||||
|
||||
#: ../src/shell-util.c:250
|
||||
msgid "Search"
|
||||
msgstr "Търсене"
|
||||
|
||||
#. Translators: the first string is the name of a gvfs
|
||||
#. * method, and the second string is a path. For
|
||||
#. * example, "Trash: some-directory". It means that the
|
||||
|
||||
1189
po/bn_IN.po
Normal file
501
po/ca.po
@@ -8,8 +8,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: HEAD\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-03-06 18:36+0100\n"
|
||||
"PO-Revision-Date: 2011-03-06 18:36+0100\n"
|
||||
"POT-Creation-Date: 2011-03-29 00:29+0200\n"
|
||||
"PO-Revision-Date: 2011-04-03 23:19+0200\n"
|
||||
"Last-Translator: Gil Forcada <gilforcada@guifi.net>\n"
|
||||
"Language-Team: Catalan <tradgnome@softcatala.org>\n"
|
||||
"Language: ca\n"
|
||||
@@ -62,7 +62,7 @@ msgstr "Historial de les ordres utilitzades en el diàleg de l'Alt+F2"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:7
|
||||
msgid "History for the looking glass dialog"
|
||||
msgstr "Historial del diàleg de l'Alt+F2"
|
||||
msgstr "Historial del depurador del GNOME Shell"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:8
|
||||
msgid "If true, display date in the clock, in addition to time."
|
||||
@@ -71,7 +71,7 @@ msgstr ""
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:9
|
||||
msgid "If true, display seconds in time."
|
||||
msgstr "Si és «true» (cert) es mostren el segons."
|
||||
msgstr "Si és «true» (cert) es mostren els segons."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:10
|
||||
msgid "If true, display the ISO week date in the calendar."
|
||||
@@ -106,7 +106,7 @@ msgstr ""
|
||||
"s'estableix a un valor nul, s'utilitzarà el conducte predeterminat que ara "
|
||||
"mateix és «videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! "
|
||||
"webmmux» que enregistra amb el format WEBM amb el còdec VP8. El %T és una "
|
||||
"variable per a estimar el nombre de fils d'execució paral·lels òptims del "
|
||||
"variable per estimar el nombre de fils d'execució paral·lels òptims del "
|
||||
"sistema."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:14
|
||||
@@ -161,7 +161,7 @@ msgstr ""
|
||||
"El GNOME Shell normalment fa un seguiment de les aplicacions actives per tal "
|
||||
"de mostrar les més utilitzades (per exemple en els llançadors). Tot i que "
|
||||
"les dades es mantindran en privat, podeu inhabilitar-ho per motius de "
|
||||
"privacitat. Tingueu en compte que si ho inhabiliteu no es suprimiran les "
|
||||
"privadesa. Tingueu en compte que si ho inhabiliteu no es suprimiran les "
|
||||
"dades ja recollides."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:22
|
||||
@@ -176,47 +176,43 @@ msgstr "Si s'han de recollir estadístiques d'ús de les aplicacions"
|
||||
msgid "disabled OpenSearch providers"
|
||||
msgstr "inhabilita els proveïdors d'OpenSearch"
|
||||
|
||||
#: ../js/misc/util.js:86
|
||||
#: ../js/misc/util.js:71
|
||||
msgid "Command not found"
|
||||
msgstr "No s'ha trobat l'ordre"
|
||||
|
||||
#. Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
#. something nicer
|
||||
#: ../js/misc/util.js:113
|
||||
#: ../js/misc/util.js:98
|
||||
msgid "Could not parse command:"
|
||||
msgstr "No s'ha pogut analitzar l'ordre:"
|
||||
|
||||
#: ../js/misc/util.js:135
|
||||
msgid "No such application"
|
||||
msgstr "No hi ha cap aplicació"
|
||||
|
||||
#: ../js/misc/util.js:148
|
||||
#: ../js/misc/util.js:106
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "No s'ha pogut executar «%s»:"
|
||||
|
||||
#. Translators: Filter to display all applications
|
||||
#: ../js/ui/appDisplay.js:195
|
||||
#: ../js/ui/appDisplay.js:230
|
||||
msgid "All"
|
||||
msgstr "Totes"
|
||||
|
||||
#: ../js/ui/appDisplay.js:285
|
||||
#: ../js/ui/appDisplay.js:328
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APLICACIONS"
|
||||
|
||||
#: ../js/ui/appDisplay.js:311
|
||||
#: ../js/ui/appDisplay.js:354
|
||||
msgid "SETTINGS"
|
||||
msgstr "CONFIGURACIÓ"
|
||||
|
||||
#: ../js/ui/appDisplay.js:565
|
||||
#: ../js/ui/appDisplay.js:625
|
||||
msgid "New Window"
|
||||
msgstr "Finestra nova"
|
||||
|
||||
#: ../js/ui/appDisplay.js:568
|
||||
#: ../js/ui/appDisplay.js:628
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "Suprimeix dels preferits"
|
||||
|
||||
#: ../js/ui/appDisplay.js:569
|
||||
#: ../js/ui/appDisplay.js:629
|
||||
msgid "Add to Favorites"
|
||||
msgstr "Afegeix als preferits"
|
||||
|
||||
@@ -376,7 +372,7 @@ msgstr "Aquesta setmana"
|
||||
msgid "Next week"
|
||||
msgstr "La setmana que ve"
|
||||
|
||||
#: ../js/ui/dash.js:174
|
||||
#: ../js/ui/dash.js:174 ../js/ui/messageTray.js:1000
|
||||
msgid "Remove"
|
||||
msgstr "Suprimeix"
|
||||
|
||||
@@ -384,54 +380,54 @@ msgstr "Suprimeix"
|
||||
msgid "Date and Time Settings"
|
||||
msgstr "Configuració de la data i l'hora"
|
||||
|
||||
#: ../js/ui/dateMenu.js:110
|
||||
#: ../js/ui/dateMenu.js:111
|
||||
msgid "Open Calendar"
|
||||
msgstr "Obre el calendari"
|
||||
|
||||
#. Translators: This is the time format with date used
|
||||
#. in 24-hour mode.
|
||||
#: ../js/ui/dateMenu.js:162
|
||||
#: ../js/ui/dateMenu.js:164
|
||||
msgid "%a %b %e, %R:%S"
|
||||
msgstr "%a %d de %b, %R:%S"
|
||||
|
||||
#: ../js/ui/dateMenu.js:163
|
||||
#: ../js/ui/dateMenu.js:165
|
||||
msgid "%a %b %e, %R"
|
||||
msgstr "%a %d de %b, %R"
|
||||
|
||||
#. Translators: This is the time format without date used
|
||||
#. in 24-hour mode.
|
||||
#: ../js/ui/dateMenu.js:167
|
||||
#: ../js/ui/dateMenu.js:169
|
||||
msgid "%a %R:%S"
|
||||
msgstr "%a %R:%S"
|
||||
|
||||
#: ../js/ui/dateMenu.js:168
|
||||
#: ../js/ui/dateMenu.js:170
|
||||
msgid "%a %R"
|
||||
msgstr "%a %R"
|
||||
|
||||
#. Translators: This is a time format with date used
|
||||
#. for AM/PM.
|
||||
#: ../js/ui/dateMenu.js:175
|
||||
#: ../js/ui/dateMenu.js:177
|
||||
msgid "%a %b %e, %l:%M:%S %p"
|
||||
msgstr "%a %d de %b, %l:%M:%S %p"
|
||||
|
||||
#: ../js/ui/dateMenu.js:176
|
||||
#: ../js/ui/dateMenu.js:178
|
||||
msgid "%a %b %e, %l:%M %p"
|
||||
msgstr "%a %d de %b, %l:%M %p"
|
||||
|
||||
#. Translators: This is a time format without date used
|
||||
#. for AM/PM.
|
||||
#: ../js/ui/dateMenu.js:180
|
||||
#: ../js/ui/dateMenu.js:182
|
||||
msgid "%a %l:%M:%S %p"
|
||||
msgstr "%a %l:%M:%S %p"
|
||||
|
||||
#: ../js/ui/dateMenu.js:181
|
||||
#: ../js/ui/dateMenu.js:183
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %l:%M %p"
|
||||
|
||||
#. 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").
|
||||
#.
|
||||
#: ../js/ui/dateMenu.js:207
|
||||
#: ../js/ui/dateMenu.js:194
|
||||
msgid "%A %B %e, %Y"
|
||||
msgstr "%A %d de %B, %Y"
|
||||
|
||||
@@ -444,7 +440,7 @@ msgstr "DOCUMENTS RECENTS"
|
||||
msgid "Log Out %s"
|
||||
msgstr "Surt %s"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:64 ../js/ui/endSessionDialog.js:69
|
||||
#: ../js/ui/endSessionDialog.js:64 ../js/ui/endSessionDialog.js:70
|
||||
msgid "Log Out"
|
||||
msgstr "Surt"
|
||||
|
||||
@@ -466,46 +462,44 @@ msgstr "Sortireu automàticament d'aquí %d segons."
|
||||
msgid "Logging out of the system."
|
||||
msgstr "S'està sortint de la sessió."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:74 ../js/ui/endSessionDialog.js:78
|
||||
msgid "Shut Down"
|
||||
msgstr "Atura"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:75
|
||||
msgid "Click Shut Down to quit these applications and shut down the system."
|
||||
msgstr "Feu clic a «Atura» per tancar les aplicacions i apagar l'ordinador."
|
||||
#: ../js/ui/endSessionDialog.js:75 ../js/ui/endSessionDialog.js:82
|
||||
msgid "Power Off"
|
||||
msgstr "Apaga"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:76
|
||||
#, c-format
|
||||
msgid "The system will shut down automatically in %d seconds."
|
||||
msgstr "S'apagarà l'ordinador automàticament d'aquí %d segons."
|
||||
msgid "Click Power Off to quit these applications and power off the system."
|
||||
msgstr "Feu clic a «Apaga» per tancar les aplicacions i apagar l'ordinador."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:77
|
||||
msgid "Shutting down the system."
|
||||
#, c-format
|
||||
msgid "The system will power off automatically in %d seconds."
|
||||
msgstr "S'apagarà l'ordinador automàticament d'aquí %d segons."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:78
|
||||
msgid "Powering off the system."
|
||||
msgstr "S'està apagant l'ordinador."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:84 ../js/ui/endSessionDialog.js:88
|
||||
#: ../js/ui/endSessionDialog.js:80 ../js/ui/endSessionDialog.js:88
|
||||
#: ../js/ui/endSessionDialog.js:93
|
||||
msgid "Restart"
|
||||
msgstr "Reinicia"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:85
|
||||
#: ../js/ui/endSessionDialog.js:89
|
||||
msgid "Click Restart to quit these applications and restart the system."
|
||||
msgstr ""
|
||||
"Feu clic a «Reinicia» per tancar les aplicacions i reiniciar l'ordinador."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:86
|
||||
#: ../js/ui/endSessionDialog.js:90
|
||||
#, c-format
|
||||
msgid "The system will restart automatically in %d seconds."
|
||||
msgstr "Es reiniciarà l'ordinador automàticament d'aquí %d segons."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:87
|
||||
#: ../js/ui/endSessionDialog.js:91
|
||||
msgid "Restarting the system."
|
||||
msgstr "S'està reiniciant l'ordinador."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:395
|
||||
msgid "Confirm"
|
||||
msgstr "D'acord"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:400 ../js/ui/status/bluetooth.js:470
|
||||
#: ../js/ui/endSessionDialog.js:415 ../js/ui/polkitAuthenticationAgent.js:172
|
||||
#: ../js/ui/status/bluetooth.js:466
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel·la"
|
||||
|
||||
@@ -519,7 +513,7 @@ msgstr "Habilitat"
|
||||
|
||||
#. translators:
|
||||
#. * The device has been disabled
|
||||
#: ../js/ui/lookingGlass.js:627 ../src/gvc/gvc-mixer-control.c:1087
|
||||
#: ../js/ui/lookingGlass.js:627 ../src/gvc/gvc-mixer-control.c:1091
|
||||
msgid "Disabled"
|
||||
msgstr "Inhabilitat"
|
||||
|
||||
@@ -539,34 +533,48 @@ msgstr "Visualitza el font"
|
||||
msgid "Web Page"
|
||||
msgstr "Pàgina web"
|
||||
|
||||
#: ../js/ui/messageTray.js:1907
|
||||
#: ../js/ui/messageTray.js:993
|
||||
msgid "Open"
|
||||
msgstr "Obre"
|
||||
|
||||
#: ../js/ui/messageTray.js:2151
|
||||
msgid "System Information"
|
||||
msgstr "Informació de l'ordinador"
|
||||
|
||||
#: ../js/ui/overview.js:88
|
||||
#: ../js/ui/overview.js:91
|
||||
msgid "Undo"
|
||||
msgstr "Desfés"
|
||||
|
||||
#: ../js/ui/overview.js:183
|
||||
#: ../js/ui/overview.js:186
|
||||
msgid "Windows"
|
||||
msgstr "Finestres"
|
||||
|
||||
#: ../js/ui/overview.js:186
|
||||
#: ../js/ui/overview.js:189
|
||||
msgid "Applications"
|
||||
msgstr "Aplicacions"
|
||||
|
||||
#. Translators: this is the name of the dock/favorites area on
|
||||
#. the left of the overview
|
||||
#: ../js/ui/overview.js:205
|
||||
msgid "Dash"
|
||||
msgstr "Quadre d'aplicacions"
|
||||
|
||||
#. TODO - _quit() doesn't really work on apps in state STARTING yet
|
||||
#: ../js/ui/panel.js:531
|
||||
#: ../js/ui/panel.js:515
|
||||
#, c-format
|
||||
msgid "Quit %s"
|
||||
msgstr "Tanca %s"
|
||||
|
||||
#. Button on the left side of the panel.
|
||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
||||
#: ../js/ui/panel.js:892
|
||||
#: ../js/ui/panel.js:893
|
||||
msgid "Activities"
|
||||
msgstr "Activitats"
|
||||
|
||||
#: ../js/ui/panel.js:994
|
||||
msgid "Top Bar"
|
||||
msgstr "Barra superior"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:122
|
||||
#, c-format
|
||||
msgid "Failed to unmount '%s'"
|
||||
@@ -580,64 +588,89 @@ msgstr "Torna-ho a intentar"
|
||||
msgid "Connect to..."
|
||||
msgstr "Connecta a..."
|
||||
|
||||
#: ../js/ui/placeDisplay.js:409
|
||||
#: ../js/ui/placeDisplay.js:380
|
||||
msgid "PLACES & DEVICES"
|
||||
msgstr "LLOCS I DISPOSITIUS"
|
||||
|
||||
#: ../js/ui/polkitAuthenticationAgent.js:74
|
||||
msgid "Authentication Required"
|
||||
msgstr "Cal autenticació"
|
||||
|
||||
#: ../js/ui/polkitAuthenticationAgent.js:108
|
||||
msgid "Administrator"
|
||||
msgstr "Administrador"
|
||||
|
||||
#: ../js/ui/polkitAuthenticationAgent.js:176
|
||||
msgid "Authenticate"
|
||||
msgstr "Autentica"
|
||||
|
||||
#. Translators: "that didn't work" refers to the fact that the
|
||||
#. * requested authentication was not gained; this can happen
|
||||
#. * because of an authentication error (like invalid password),
|
||||
#. * for instance.
|
||||
#: ../js/ui/polkitAuthenticationAgent.js:264
|
||||
msgid "Sorry, that didn't work. Please try again."
|
||||
msgstr "No ha funcionat. Torneu-ho a provar."
|
||||
|
||||
#: ../js/ui/polkitAuthenticationAgent.js:276
|
||||
msgid "Password:"
|
||||
msgstr "Contrasenya:"
|
||||
|
||||
#. Translators: this MUST be either "toggle-switch-us"
|
||||
#. (for toggle switches containing the English words
|
||||
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
|
||||
#. switches containing "◯" and "|"). Other values will
|
||||
#. simply result in invisible toggle switches.
|
||||
#: ../js/ui/popupMenu.js:612
|
||||
#: ../js/ui/popupMenu.js:679
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-intl"
|
||||
|
||||
#: ../js/ui/runDialog.js:201
|
||||
#: ../js/ui/runDialog.js:205
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Introduïu una ordre:"
|
||||
|
||||
#: ../js/ui/searchDisplay.js:283
|
||||
#: ../js/ui/searchDisplay.js:310
|
||||
msgid "Searching..."
|
||||
msgstr "S'està cercant..."
|
||||
|
||||
#: ../js/ui/searchDisplay.js:297
|
||||
#: ../js/ui/searchDisplay.js:324
|
||||
msgid "No matching results."
|
||||
msgstr "No s'ha trobat cap coincidència."
|
||||
|
||||
#: ../js/ui/statusMenu.js:102 ../js/ui/statusMenu.js:166
|
||||
#: ../js/ui/statusMenu.js:161 ../js/ui/statusMenu.js:163
|
||||
#: ../js/ui/statusMenu.js:228
|
||||
msgid "Power Off..."
|
||||
msgstr "Apaga..."
|
||||
|
||||
#: ../js/ui/statusMenu.js:104 ../js/ui/statusMenu.js:165
|
||||
#: ../js/ui/statusMenu.js:163 ../js/ui/statusMenu.js:227
|
||||
msgid "Suspend"
|
||||
msgstr "Atura temporalment"
|
||||
|
||||
#: ../js/ui/statusMenu.js:125
|
||||
#: ../js/ui/statusMenu.js:184
|
||||
msgid "Available"
|
||||
msgstr "Disponible"
|
||||
|
||||
#: ../js/ui/statusMenu.js:130
|
||||
#: ../js/ui/statusMenu.js:189
|
||||
msgid "Busy"
|
||||
msgstr "Ocupat"
|
||||
|
||||
#: ../js/ui/statusMenu.js:138
|
||||
#: ../js/ui/statusMenu.js:197
|
||||
msgid "My Account"
|
||||
msgstr "El meu compte"
|
||||
|
||||
#: ../js/ui/statusMenu.js:142
|
||||
#: ../js/ui/statusMenu.js:201
|
||||
msgid "System Settings"
|
||||
msgstr "Paràmetres de l'ordinador"
|
||||
|
||||
#: ../js/ui/statusMenu.js:149
|
||||
#: ../js/ui/statusMenu.js:208
|
||||
msgid "Lock Screen"
|
||||
msgstr "Bloca la pantalla"
|
||||
|
||||
#: ../js/ui/statusMenu.js:153
|
||||
#: ../js/ui/statusMenu.js:213
|
||||
msgid "Switch User"
|
||||
msgstr "Canvia d'usuari"
|
||||
|
||||
#: ../js/ui/statusMenu.js:158
|
||||
#: ../js/ui/statusMenu.js:218
|
||||
msgid "Log Out..."
|
||||
msgstr "Surt..."
|
||||
|
||||
@@ -645,14 +678,12 @@ msgstr "Surt..."
|
||||
msgid "Zoom"
|
||||
msgstr "Amplia"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:69
|
||||
msgid "Screen Reader"
|
||||
msgstr "Lector de pantalla"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:73
|
||||
msgid "Screen Keyboard"
|
||||
msgstr "Teclat en pantalla"
|
||||
|
||||
#. let screenReader = this._buildItem(_("Screen Reader"), APPLICATIONS_SCHEMA,
|
||||
#. 'screen-reader-enabled');
|
||||
#. this.menu.addMenuItem(screenReader);
|
||||
#. let screenKeyboard = this._buildItem(_("Screen Keyboard"), APPLICATIONS_SCHEMA,
|
||||
#. 'screen-keyboard-enabled');
|
||||
#. this.menu.addMenuItem(screenKeyboard);
|
||||
#: ../js/ui/status/accessibility.js:77
|
||||
msgid "Visual Alerts"
|
||||
msgstr "Avisos visuals"
|
||||
@@ -677,17 +708,17 @@ msgstr "Tecles del ratolí"
|
||||
msgid "Universal Access Settings"
|
||||
msgstr "Paràmetres d'accés universal"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:145
|
||||
#: ../js/ui/status/accessibility.js:146
|
||||
msgid "High Contrast"
|
||||
msgstr "Alt contrast"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:182
|
||||
#: ../js/ui/status/accessibility.js:183
|
||||
msgid "Large Text"
|
||||
msgstr "Text gran"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:241
|
||||
#: ../js/ui/status/bluetooth.js:337 ../js/ui/status/bluetooth.js:371
|
||||
#: ../js/ui/status/bluetooth.js:411 ../js/ui/status/bluetooth.js:444
|
||||
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:237
|
||||
#: ../js/ui/status/bluetooth.js:333 ../js/ui/status/bluetooth.js:367
|
||||
#: ../js/ui/status/bluetooth.js:407 ../js/ui/status/bluetooth.js:440
|
||||
msgid "Bluetooth"
|
||||
msgstr "Bluetooth"
|
||||
|
||||
@@ -707,94 +738,94 @@ msgstr "Establiu un dispositiu nou..."
|
||||
msgid "Bluetooth Settings"
|
||||
msgstr "Paràmetres del Bluetooth"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:192
|
||||
#: ../js/ui/status/bluetooth.js:188
|
||||
msgid "Connection"
|
||||
msgstr "Connexió"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:228
|
||||
#: ../js/ui/status/bluetooth.js:224
|
||||
msgid "Send Files..."
|
||||
msgstr "Envia fitxers..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:233
|
||||
#: ../js/ui/status/bluetooth.js:229
|
||||
msgid "Browse Files..."
|
||||
msgstr "Navega pels fitxers..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:242
|
||||
#: ../js/ui/status/bluetooth.js:238
|
||||
msgid "Error browsing device"
|
||||
msgstr "S'ha produït un error en navegar pel dispositiu"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:243
|
||||
#: ../js/ui/status/bluetooth.js:239
|
||||
#, c-format
|
||||
msgid "The requested device cannot be browsed, error is '%s'"
|
||||
msgstr "No es pot navegar pel dispositiu degut a l'error «%s»"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:251
|
||||
#: ../js/ui/status/bluetooth.js:247
|
||||
msgid "Keyboard Settings"
|
||||
msgstr "Paràmetres del teclat"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:256
|
||||
#: ../js/ui/status/bluetooth.js:252
|
||||
msgid "Mouse Settings"
|
||||
msgstr "Paràmetres del ratolí"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:263 ../js/ui/status/volume.js:65
|
||||
#: ../js/ui/status/bluetooth.js:259 ../js/ui/status/volume.js:66
|
||||
msgid "Sound Settings"
|
||||
msgstr "Paràmetres de so"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:372
|
||||
#: ../js/ui/status/bluetooth.js:368
|
||||
#, c-format
|
||||
msgid "Authorization request from %s"
|
||||
msgstr "Hi ha una petició d'autorització des de %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:378
|
||||
#: ../js/ui/status/bluetooth.js:374
|
||||
#, c-format
|
||||
msgid "Device %s wants access to the service '%s'"
|
||||
msgstr "El dispositiu %s vol accedir al servei «%s»"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:380
|
||||
#: ../js/ui/status/bluetooth.js:376
|
||||
msgid "Always grant access"
|
||||
msgstr "Permet l'accés sempre"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:381
|
||||
#: ../js/ui/status/bluetooth.js:377
|
||||
msgid "Grant this time only"
|
||||
msgstr "Permete-ho només ara"
|
||||
msgstr "Permet-ho només ara"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:382
|
||||
#: ../js/ui/status/bluetooth.js:378
|
||||
msgid "Reject"
|
||||
msgstr "Rebutja"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:412
|
||||
#: ../js/ui/status/bluetooth.js:408
|
||||
#, c-format
|
||||
msgid "Pairing confirmation for %s"
|
||||
msgstr "Confirmació d'aparellament per %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:418 ../js/ui/status/bluetooth.js:452
|
||||
#: ../js/ui/status/bluetooth.js:414 ../js/ui/status/bluetooth.js:448
|
||||
#, c-format
|
||||
msgid "Device %s wants to pair with this computer"
|
||||
msgstr "El dispositiu %s vol aparellar-se amb aquest ordinador"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:419
|
||||
#: ../js/ui/status/bluetooth.js:415
|
||||
#, c-format
|
||||
msgid "Please confirm whether the PIN '%s' matches the one on the device."
|
||||
msgstr "Confirmeu que el PIN «%s» coincideix amb el que hi ha al dispositiu."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:421
|
||||
#: ../js/ui/status/bluetooth.js:417
|
||||
msgid "Matches"
|
||||
msgstr "Coincideix"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:422
|
||||
#: ../js/ui/status/bluetooth.js:418
|
||||
msgid "Does not match"
|
||||
msgstr "No coincideix"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:445
|
||||
#: ../js/ui/status/bluetooth.js:441
|
||||
#, c-format
|
||||
msgid "Pairing request for %s"
|
||||
msgstr "Teniu una sol·licitud d'aparellament amb %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:453
|
||||
#: ../js/ui/status/bluetooth.js:449
|
||||
msgid "Please enter the PIN mentioned on the device."
|
||||
msgstr "Introduïu el PIN que es mostra al dispositiu."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:469
|
||||
#: ../js/ui/status/bluetooth.js:465
|
||||
msgid "OK"
|
||||
msgstr "D'acord"
|
||||
|
||||
@@ -806,17 +837,153 @@ msgstr "Mostra la disposició del teclat..."
|
||||
msgid "Localization Settings"
|
||||
msgstr "Paràmetres de localització"
|
||||
|
||||
#: ../js/ui/status/network.js:104 ../js/ui/status/network.js:1454
|
||||
msgid "<unknown>"
|
||||
msgstr "<desconegut>"
|
||||
|
||||
#. Translators: this indicates that wireless or wwan is disabled by hardware killswitch
|
||||
#: ../js/ui/status/network.js:311
|
||||
msgid "disabled"
|
||||
msgstr "inhabilitada"
|
||||
|
||||
#: ../js/ui/status/network.js:494
|
||||
msgid "connecting..."
|
||||
msgstr "s'està connectant..."
|
||||
|
||||
#. Translators: this is for network connections that require some kind of key or password
|
||||
#: ../js/ui/status/network.js:497
|
||||
msgid "authentication required"
|
||||
msgstr "cal autenticació"
|
||||
|
||||
#. Translators: this is for devices that require some kind of firmware or kernel
|
||||
#. module, which is missing
|
||||
#: ../js/ui/status/network.js:507
|
||||
msgid "firmware missing"
|
||||
msgstr "manca el microprogramari"
|
||||
|
||||
#. Translators: this is for wired network devices that are physically disconnected
|
||||
#: ../js/ui/status/network.js:514
|
||||
msgid "cable unplugged"
|
||||
msgstr "s'ha desconnectat el cable"
|
||||
|
||||
#. Translators: this is for a network device that cannot be activated (for example it
|
||||
#. is disabled by rfkill, or it has no coverage
|
||||
#: ../js/ui/status/network.js:519
|
||||
msgid "unavailable"
|
||||
msgstr "no disponible"
|
||||
|
||||
#: ../js/ui/status/network.js:521
|
||||
msgid "connection failed"
|
||||
msgstr "ha fallat la connexió"
|
||||
|
||||
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
|
||||
#. and we cannot access its settings (including the name)
|
||||
#: ../js/ui/status/network.js:602 ../js/ui/status/network.js:1402
|
||||
msgid "Connected (private)"
|
||||
msgstr "Connectat (privat)"
|
||||
|
||||
#: ../js/ui/status/network.js:683
|
||||
msgid "Auto Ethernet"
|
||||
msgstr "Ethernet automàtic"
|
||||
|
||||
#: ../js/ui/status/network.js:758
|
||||
msgid "Auto broadband"
|
||||
msgstr "Banda ampla automàtica"
|
||||
|
||||
#: ../js/ui/status/network.js:761
|
||||
msgid "Auto dial-up"
|
||||
msgstr "Marcatge directe automàtic"
|
||||
|
||||
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
|
||||
#: ../js/ui/status/network.js:904 ../js/ui/status/network.js:1414
|
||||
#, c-format
|
||||
msgid "Auto %s"
|
||||
msgstr "%s automàtic"
|
||||
|
||||
#: ../js/ui/status/network.js:906
|
||||
msgid "Auto bluetooth"
|
||||
msgstr "Bluetooth automàtic"
|
||||
|
||||
#: ../js/ui/status/network.js:1416
|
||||
msgid "Auto wireless"
|
||||
msgstr "Sense fil automàtic"
|
||||
|
||||
#: ../js/ui/status/network.js:1474
|
||||
msgid "More..."
|
||||
msgstr "Més..."
|
||||
|
||||
#: ../js/ui/status/network.js:1497
|
||||
msgid "Enable networking"
|
||||
msgstr "Habilita la xarxa"
|
||||
|
||||
#: ../js/ui/status/network.js:1509
|
||||
msgid "Wired"
|
||||
msgstr "Amb fil"
|
||||
|
||||
#: ../js/ui/status/network.js:1520
|
||||
msgid "Wireless"
|
||||
msgstr "Sense fil"
|
||||
|
||||
#: ../js/ui/status/network.js:1530
|
||||
msgid "Mobile broadband"
|
||||
msgstr "Ampla de banda mòbil"
|
||||
|
||||
#: ../js/ui/status/network.js:1540
|
||||
msgid "VPN Connections"
|
||||
msgstr "Connexions VPN"
|
||||
|
||||
#: ../js/ui/status/network.js:1549
|
||||
msgid "Network Settings"
|
||||
msgstr "Paràmetres de xarxa"
|
||||
|
||||
#: ../js/ui/status/network.js:1844
|
||||
#, c-format
|
||||
msgid "You're now connected to mobile broadband connection '%s'"
|
||||
msgstr "Us acabeu de connectar amb la connexió de banda ampla mòbil «%s»"
|
||||
|
||||
#: ../js/ui/status/network.js:1848
|
||||
#, c-format
|
||||
msgid "You're now connected to wireless network '%s'"
|
||||
msgstr "Us acabeu de connectar a la xarxa sense fil «%s»"
|
||||
|
||||
#: ../js/ui/status/network.js:1852
|
||||
#, c-format
|
||||
msgid "You're now connected to wired network '%s'"
|
||||
msgstr "Us acabeu de connectar a la xarxa amb fil «%s»"
|
||||
|
||||
#: ../js/ui/status/network.js:1856
|
||||
#, c-format
|
||||
msgid "You're now connected to VPN network '%s'"
|
||||
msgstr "Us acabeu de connectar a la xarxa VPN «%s»"
|
||||
|
||||
#: ../js/ui/status/network.js:1861
|
||||
#, c-format
|
||||
msgid "You're now connected to '%s'"
|
||||
msgstr "Us acabeu de connectar a «%s»"
|
||||
|
||||
#: ../js/ui/status/network.js:1869
|
||||
msgid "Connection established"
|
||||
msgstr "S'ha establert la connexió"
|
||||
|
||||
#: ../js/ui/status/network.js:1991
|
||||
msgid "Networking is disabled"
|
||||
msgstr "S'ha inhabilitat la xarxa"
|
||||
|
||||
#: ../js/ui/status/network.js:2116
|
||||
msgid "Network Manager"
|
||||
msgstr "Gestor de connexions de xarxa"
|
||||
|
||||
#: ../js/ui/status/power.js:85
|
||||
msgid "Power Settings"
|
||||
msgstr "Paràmetres d'energia"
|
||||
|
||||
#. 0 is reported when UPower does not have enough data
|
||||
#. to estimate battery life
|
||||
#: ../js/ui/status/power.js:110
|
||||
#: ../js/ui/status/power.js:111
|
||||
msgid "Estimating..."
|
||||
msgstr "S'està estimant la durada..."
|
||||
|
||||
#: ../js/ui/status/power.js:117
|
||||
#: ../js/ui/status/power.js:118
|
||||
#, c-format
|
||||
msgid "%d hour remaining"
|
||||
msgid_plural "%d hours remaining"
|
||||
@@ -824,102 +991,102 @@ msgstr[0] "Queda %d hora"
|
||||
msgstr[1] "Queden %d hores"
|
||||
|
||||
#. TRANSLATORS: this is a time string, as in "%d hours %d minutes remaining"
|
||||
#: ../js/ui/status/power.js:120
|
||||
#: ../js/ui/status/power.js:121
|
||||
#, c-format
|
||||
msgid "%d %s %d %s remaining"
|
||||
msgstr "Queden %d %s %d %s"
|
||||
|
||||
#: ../js/ui/status/power.js:122
|
||||
#: ../js/ui/status/power.js:123
|
||||
msgid "hour"
|
||||
msgid_plural "hours"
|
||||
msgstr[0] "hora"
|
||||
msgstr[1] "hores"
|
||||
|
||||
#: ../js/ui/status/power.js:122
|
||||
#: ../js/ui/status/power.js:123
|
||||
msgid "minute"
|
||||
msgid_plural "minutes"
|
||||
msgstr[0] "minut"
|
||||
msgstr[1] "minuts"
|
||||
|
||||
#: ../js/ui/status/power.js:125
|
||||
#: ../js/ui/status/power.js:126
|
||||
#, c-format
|
||||
msgid "%d minute remaining"
|
||||
msgid_plural "%d minutes remaining"
|
||||
msgstr[0] "Queda %d minut"
|
||||
msgstr[1] "Queden %d minuts"
|
||||
|
||||
#: ../js/ui/status/power.js:227
|
||||
#: ../js/ui/status/power.js:228
|
||||
msgid "AC adapter"
|
||||
msgstr "Adaptador de corrent"
|
||||
|
||||
#: ../js/ui/status/power.js:229
|
||||
#: ../js/ui/status/power.js:230
|
||||
msgid "Laptop battery"
|
||||
msgstr "Bateria del portàtil"
|
||||
|
||||
#: ../js/ui/status/power.js:231
|
||||
#: ../js/ui/status/power.js:232
|
||||
msgid "UPS"
|
||||
msgstr "SAI"
|
||||
|
||||
#: ../js/ui/status/power.js:233
|
||||
#: ../js/ui/status/power.js:234
|
||||
msgid "Monitor"
|
||||
msgstr "Pantalla"
|
||||
|
||||
#: ../js/ui/status/power.js:235
|
||||
#: ../js/ui/status/power.js:236
|
||||
msgid "Mouse"
|
||||
msgstr "Ratolí"
|
||||
|
||||
#: ../js/ui/status/power.js:237
|
||||
#: ../js/ui/status/power.js:238
|
||||
msgid "Keyboard"
|
||||
msgstr "Teclat"
|
||||
|
||||
#: ../js/ui/status/power.js:239
|
||||
#: ../js/ui/status/power.js:240
|
||||
msgid "PDA"
|
||||
msgstr "PDA"
|
||||
|
||||
#: ../js/ui/status/power.js:241
|
||||
#: ../js/ui/status/power.js:242
|
||||
msgid "Cell phone"
|
||||
msgstr "Telèfon mòbil"
|
||||
|
||||
#: ../js/ui/status/power.js:243
|
||||
#: ../js/ui/status/power.js:244
|
||||
msgid "Media player"
|
||||
msgstr "Reproductor multimèdia"
|
||||
|
||||
#: ../js/ui/status/power.js:245
|
||||
#: ../js/ui/status/power.js:246
|
||||
msgid "Tablet"
|
||||
msgstr "Tauleta"
|
||||
|
||||
#: ../js/ui/status/power.js:247
|
||||
#: ../js/ui/status/power.js:248
|
||||
msgid "Computer"
|
||||
msgstr "Ordinador"
|
||||
|
||||
#: ../js/ui/status/power.js:249 ../src/shell-app-system.c:1013
|
||||
#: ../js/ui/status/power.js:250 ../src/shell-app-system.c:1088
|
||||
msgid "Unknown"
|
||||
msgstr "Desconegut"
|
||||
|
||||
#: ../js/ui/status/volume.js:44
|
||||
#: ../js/ui/status/volume.js:45
|
||||
msgid "Volume"
|
||||
msgstr "Volum"
|
||||
|
||||
#: ../js/ui/status/volume.js:57
|
||||
#: ../js/ui/status/volume.js:58
|
||||
msgid "Microphone"
|
||||
msgstr "Micròfon"
|
||||
|
||||
#: ../js/ui/telepathyClient.js:239
|
||||
#: ../js/ui/telepathyClient.js:331
|
||||
#, c-format
|
||||
msgid "%s is online."
|
||||
msgstr "%s és en línia."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:244
|
||||
#: ../js/ui/telepathyClient.js:336
|
||||
#, c-format
|
||||
msgid "%s is offline."
|
||||
msgstr "%s no hi és."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:247
|
||||
#: ../js/ui/telepathyClient.js:339
|
||||
#, c-format
|
||||
msgid "%s is away."
|
||||
msgstr "%s és lluny."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:250
|
||||
#: ../js/ui/telepathyClient.js:342
|
||||
#, c-format
|
||||
msgid "%s is busy."
|
||||
msgstr "%s està ocupat."
|
||||
@@ -927,7 +1094,7 @@ msgstr "%s està ocupat."
|
||||
#. Translators: this is a time format string followed by a date.
|
||||
#. If applicable, replace %X with a strftime format valid for your
|
||||
#. locale, without seconds.
|
||||
#: ../js/ui/telepathyClient.js:348
|
||||
#: ../js/ui/telepathyClient.js:473
|
||||
#, no-c-format
|
||||
msgid "Sent at %X on %A"
|
||||
msgstr "Enviat a les %X del %A"
|
||||
@@ -936,10 +1103,14 @@ msgstr "Enviat a les %X del %A"
|
||||
#. in the search entry when no search is
|
||||
#. active; it should not exceed ~30
|
||||
#. characters.
|
||||
#: ../js/ui/viewSelector.js:103
|
||||
#: ../js/ui/viewSelector.js:122
|
||||
msgid "Type to search..."
|
||||
msgstr "Teclegeu per cercar..."
|
||||
|
||||
#: ../js/ui/viewSelector.js:142 ../src/shell-util.c:250
|
||||
msgid "Search"
|
||||
msgstr "Cerca"
|
||||
|
||||
#: ../js/ui/windowAttentionHandler.js:42
|
||||
#, c-format
|
||||
msgid "%s has finished starting"
|
||||
@@ -952,7 +1123,7 @@ msgstr "«%s» ja està apunt"
|
||||
|
||||
#. translators:
|
||||
#. * The number of sound outputs on a particular device
|
||||
#: ../src/gvc/gvc-mixer-control.c:1094
|
||||
#: ../src/gvc/gvc-mixer-control.c:1098
|
||||
#, c-format
|
||||
msgid "%u Output"
|
||||
msgid_plural "%u Outputs"
|
||||
@@ -961,49 +1132,66 @@ msgstr[1] "%u sortides"
|
||||
|
||||
#. translators:
|
||||
#. * The number of sound inputs on a particular device
|
||||
#: ../src/gvc/gvc-mixer-control.c:1104
|
||||
#: ../src/gvc/gvc-mixer-control.c:1108
|
||||
#, c-format
|
||||
msgid "%u Input"
|
||||
msgid_plural "%u Inputs"
|
||||
msgstr[0] "%u entrada"
|
||||
msgstr[1] "%u entrades"
|
||||
|
||||
#: ../src/gvc/gvc-mixer-control.c:1402
|
||||
#: ../src/gvc/gvc-mixer-control.c:1406
|
||||
msgid "System Sounds"
|
||||
msgstr "Sons del sistema"
|
||||
|
||||
#: ../src/shell-global.c:1298
|
||||
#: ../src/main.c:446
|
||||
msgid "Print version"
|
||||
msgstr "Mostra la versió"
|
||||
|
||||
#: ../src/shell-app.c:454
|
||||
#, c-format
|
||||
msgid "Failed to launch '%s'"
|
||||
msgstr "No s'ha pogut iniciar «%s»"
|
||||
|
||||
#: ../src/shell-global.c:1395
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Fa menys d'un minut"
|
||||
|
||||
#: ../src/shell-global.c:1302
|
||||
#: ../src/shell-global.c:1399
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "Fa %d minut"
|
||||
msgstr[1] "Fa %d minuts"
|
||||
|
||||
#: ../src/shell-global.c:1307
|
||||
#: ../src/shell-global.c:1404
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "Fa %d hora"
|
||||
msgstr[1] "Fa %d hores"
|
||||
|
||||
#: ../src/shell-global.c:1312
|
||||
#: ../src/shell-global.c:1409
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "Fa %d dia"
|
||||
msgstr[1] "Fa %d dies"
|
||||
|
||||
#: ../src/shell-global.c:1317
|
||||
#: ../src/shell-global.c:1414
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "Fa %d setmana"
|
||||
msgstr[1] "Fa %d setmanes"
|
||||
|
||||
#: ../src/shell-mobile-providers.c:80
|
||||
msgid "United Kingdom"
|
||||
msgstr "Regne Unit"
|
||||
|
||||
#: ../src/shell-mobile-providers.c:526
|
||||
msgid "Default"
|
||||
msgstr "Predeterminat"
|
||||
|
||||
#: ../src/shell-polkit-authentication-agent.c:334
|
||||
msgid "Authentication dialog was dismissed by the user"
|
||||
msgstr "L'usuari ha descartat el diàleg d'autenticació"
|
||||
@@ -1018,10 +1206,6 @@ msgstr "Carpeta d'inici"
|
||||
msgid "File System"
|
||||
msgstr "Sistema de fitxers"
|
||||
|
||||
#: ../src/shell-util.c:250
|
||||
msgid "Search"
|
||||
msgstr "Cerca"
|
||||
|
||||
#. Translators: the first string is the name of a gvfs
|
||||
#. * method, and the second string is a path. For
|
||||
#. * example, "Trash: some-directory". It means that the
|
||||
@@ -1032,6 +1216,33 @@ msgstr "Cerca"
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "Shut Down"
|
||||
#~ msgstr "Atura"
|
||||
|
||||
#~ msgid "Click Shut Down to quit these applications and shut down the system."
|
||||
#~ msgstr "Feu clic a «Atura» per tancar les aplicacions i apagar l'ordinador."
|
||||
|
||||
#~ msgid "The system will shut down automatically in %d seconds."
|
||||
#~ msgstr "S'apagarà l'ordinador automàticament d'aquí %d segons."
|
||||
|
||||
#~ msgid "Shutting down the system."
|
||||
#~ msgstr "S'està apagant l'ordinador."
|
||||
|
||||
#~ msgid "Confirm"
|
||||
#~ msgstr "D'acord"
|
||||
|
||||
#~ msgid "Panel"
|
||||
#~ msgstr "Quadre"
|
||||
|
||||
#~ msgid "No such application"
|
||||
#~ msgstr "No hi ha cap aplicació"
|
||||
|
||||
#~ msgid "Screen Reader"
|
||||
#~ msgstr "Lector de pantalla"
|
||||
|
||||
#~ msgid "Screen Keyboard"
|
||||
#~ msgstr "Teclat en pantalla"
|
||||
|
||||
#~ msgid "PREFERENCES"
|
||||
#~ msgstr "PREFERÈNCIES"
|
||||
|
||||
|
||||
1314
po/en_GB.po
550
po/et.po
@@ -12,21 +12,21 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell MASTER\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&component=general\n"
|
||||
"POT-Creation-Date: 2011-02-04 22:28+0000\n"
|
||||
"PO-Revision-Date: 2011-02-06 08:43+0200\n"
|
||||
"Last-Translator: Ivar Smolin <okul@linux.ee>\n"
|
||||
"shell&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2011-03-30 17:13+0000\n"
|
||||
"PO-Revision-Date: 2011-03-30 23:56+0300\n"
|
||||
"Last-Translator: Mattias Põldaru <mahfiaz@gmail.com>\n"
|
||||
"Language-Team: Estonian <gnome-et@linux.ee>\n"
|
||||
"Language: et\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: et\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Poedit-Language: Estonian\n"
|
||||
"X-Poedit-Country: Estonia\n"
|
||||
|
||||
msgid "GNOME Shell"
|
||||
msgstr "GNOME kest"
|
||||
msgstr "GNOME Shell"
|
||||
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Aknahaldur ja rakenduste käivitaja"
|
||||
@@ -58,6 +58,10 @@ msgstr ""
|
||||
msgid "History for command (Alt-F2) dialog"
|
||||
msgstr "Käsudialoogi (Alt-F2) ajalugu"
|
||||
|
||||
# suurendusklaasidialoog? miks ka mitte :)
|
||||
msgid "History for the looking glass dialog"
|
||||
msgstr "Otsingudialoogi ajalugu"
|
||||
|
||||
msgid "If true, display date in the clock, in addition to time."
|
||||
msgstr "Kui määratud, siis kuvatakse kellaaja kõrval ka kuupäeva."
|
||||
|
||||
@@ -83,6 +87,16 @@ msgid ""
|
||||
"records to WEBM using the VP8 codec. %T is used as a placeholder for a guess "
|
||||
"at the optimal thread count on the system."
|
||||
msgstr ""
|
||||
"Määrab GStreameri toru, mida kasutatakse lindistuste kodeerimiseks. See peab "
|
||||
"vastama gst-launch'i süntaksile. Torul peaks olema vaba plokk (pad), kuhu "
|
||||
"lindistatav video salvestatakse. Tavaliselt on vaba plokk olemas; selle "
|
||||
"ploki väljund kirjutatakse väljundfaili. Toru võib hoolitseda ka enda "
|
||||
"väljundi eest - seda võib kasutada väljundi saatmiseks icecast serverisse "
|
||||
"shout2send või sarnase tehnoloogia abil. Kui see on määramata või väärtus on "
|
||||
"tühi, kasutatakse vaikimisi toru. See on praegu 'videorate ! vp8enc "
|
||||
"quality=10 speed=2 threads=%T ! queue ! webmmux' ning lindistab WEBM "
|
||||
"vormingusse VP8 koodekiga. %T asendatakse süsteemi oletatava optimaalseima "
|
||||
"lõimede (thread) arvuga."
|
||||
|
||||
msgid "Show date in clock"
|
||||
msgstr "Kell näitab kuupäeva"
|
||||
@@ -96,7 +110,7 @@ msgstr "Kellaaega näidatakse sekunditega"
|
||||
msgid ""
|
||||
"The applications corresponding to these identifiers will be displayed in the "
|
||||
"favorites area."
|
||||
msgstr ""
|
||||
msgstr "Nendele tunnustele vastavaid rakendusi kuvatakse lemmikutes."
|
||||
|
||||
msgid ""
|
||||
"The filename for recorded screencasts will be a unique filename based on the "
|
||||
@@ -112,9 +126,10 @@ msgid ""
|
||||
"The framerate of the resulting screencast recordered by GNOME Shell's "
|
||||
"screencast recorder in frames-per-second."
|
||||
msgstr ""
|
||||
"GNOME Shelli lindistatava ekraanivideo kaadrisagedus (kaadrit sekundis)."
|
||||
|
||||
msgid "The gstreamer pipeline used to encode the screencast"
|
||||
msgstr ""
|
||||
msgstr "GStreameri toru, mida ekraanivideo kodeerimiseks kasutatakse"
|
||||
|
||||
msgid ""
|
||||
"The shell normally monitors active applications in order to present the most "
|
||||
@@ -122,125 +137,19 @@ msgid ""
|
||||
"want to disable this for privacy reasons. Please note that doing so won't "
|
||||
"remove already saved data."
|
||||
msgstr ""
|
||||
"Shell tavaliselt seirab aktiivseid rakendusi, et näidata enamkasutatavaid "
|
||||
"(näiteks käivitajaid). Kuigi neid andmeid hoitakse privaatselt, võid "
|
||||
"privaatsuse suurendamiseks selle keelata. Selle keelamine siiski ei eemalda "
|
||||
"juba salvestatud andmeid."
|
||||
|
||||
msgid "Uuids of extensions to disable"
|
||||
msgstr "Keelatavate laienduste UUID-d"
|
||||
|
||||
msgid "Whether to collect stats about applications usage"
|
||||
msgstr ""
|
||||
msgstr "Kas rakenduste kasutuse kohta kogutakse andmeid"
|
||||
|
||||
msgid "disabled OpenSearch providers"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clip the crosshairs at the center"
|
||||
msgstr "Niitristi keskel on auk"
|
||||
|
||||
msgid "Color of the crosshairs"
|
||||
msgstr "Niitristi värvus"
|
||||
|
||||
msgid ""
|
||||
"Determines the length of the vertical and horizontal lines that make up the "
|
||||
"crosshairs."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Determines the position of the magnified mouse image within the magnified "
|
||||
"view and how it reacts to system mouse movement. The values are - none: no "
|
||||
"mouse tracking; - centered: the mouse image is displayed at the center of "
|
||||
"the zoom region (which also represents the point under the system mouse) and "
|
||||
"the magnified contents are scrolled as the system mouse moves; - "
|
||||
"proportional: the position of the magnified mouse in the zoom region is "
|
||||
"proportionally the same as the position of the system mouse on screen; - "
|
||||
"push: when the magnified mouse intersects a boundary of the zoom region, the "
|
||||
"contents are scrolled into view."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Determines the transparency of the crosshairs, from fully opaque to fully "
|
||||
"transparent."
|
||||
msgstr ""
|
||||
"Määrab niitristi läbipaistvuse, alates täiesti läbipaistmatust kuni täiesti "
|
||||
"läbipaistvani."
|
||||
|
||||
msgid ""
|
||||
"Determines whether the crosshairs intersect the magnified mouse sprite, or "
|
||||
"are clipped such that the ends of the horizontal and vertical lines surround "
|
||||
"the mouse image."
|
||||
msgstr ""
|
||||
"Määrab, kas niitrist kattub suurendatud hiire pildiga või on keskelt ära "
|
||||
"lõigatud nii, et jooned ümbritsevad hiirekursori pilti."
|
||||
|
||||
msgid "Enable lens mode"
|
||||
msgstr "Läätsede režiimi lubamine"
|
||||
|
||||
msgid ""
|
||||
"Enables/disables display of crosshairs centered on the magnified mouse "
|
||||
"sprite."
|
||||
msgstr "Lubab/keelab niitristi kuvamise suurendatud hiirekursori kohal."
|
||||
|
||||
msgid ""
|
||||
"For centered mouse tracking, when the system pointer is at or near the edge "
|
||||
"of the screen, the magnified contents continue to scroll such that the "
|
||||
"screen edge moves into the magnified view."
|
||||
msgstr ""
|
||||
|
||||
msgid "Length of the crosshairs"
|
||||
msgstr "Niitristi pikkus"
|
||||
|
||||
msgid "Magnification factor"
|
||||
msgstr "Suurendustegur"
|
||||
|
||||
msgid "Mouse Tracking Mode"
|
||||
msgstr "Hiire jälitamise režiim"
|
||||
|
||||
msgid "Opacity of the crosshairs"
|
||||
msgstr "Niitristi läbipaistvus"
|
||||
|
||||
msgid "Screen position"
|
||||
msgstr "Ekraani asukoht"
|
||||
|
||||
msgid "Scroll magnified contents beyond the edges of the desktop"
|
||||
msgstr "Suurendusklaas võib liikuda töölauapiiridest väljapoole"
|
||||
|
||||
msgid "Show or hide crosshairs"
|
||||
msgstr "Niitristi kuvamine või peitmine"
|
||||
|
||||
msgid "Show or hide the magnifier"
|
||||
msgstr "Suurendusklaasi kuvamine või peitmine"
|
||||
|
||||
msgid "Show or hide the magnifier and all of its zoom regions."
|
||||
msgstr ""
|
||||
"Suurendusklaasi ja selle kõigi suurenduspiirkondade kuvamine või peitmine."
|
||||
|
||||
msgid ""
|
||||
"The color of the the vertical and horizontal lines that make up the "
|
||||
"crosshairs."
|
||||
msgstr "Niitristi püst- ja rõhtjoone värvus."
|
||||
|
||||
msgid ""
|
||||
"The magnified view either fills the entire screen, or occupies the top-half, "
|
||||
"bottom-half, left-half, or right-half of the screen."
|
||||
msgstr ""
|
||||
"Suurendatud vaade täidab kas kogu ekraani või täidab ülemise, alumise, "
|
||||
"vasaku või parema ekraanipoole."
|
||||
|
||||
msgid ""
|
||||
"The power of the magnification. A value of 1.0 means no magnification. A "
|
||||
"value of 2.0 doubles the size."
|
||||
msgstr "Suurendustegur. 1,0 tähendab originaalsuurust. 2,0 muudab kaks korda."
|
||||
|
||||
msgid "Thickness of the crosshairs"
|
||||
msgstr "Niitristi paksus"
|
||||
|
||||
msgid ""
|
||||
"Whether the magnified view should be centered over the location of the "
|
||||
"system mouse and move with it."
|
||||
msgstr ""
|
||||
"Kas suurendatud vaate keskkoht peaks asetsema süsteemi hiire kohal ning "
|
||||
"liikuma sellega kaasa."
|
||||
|
||||
msgid "Width of the vertical and horizontal lines that make up the crosshairs."
|
||||
msgstr "Niitristi moodustavate püst- ja rõhtjoone laius"
|
||||
msgstr "keelatud OpenSearch pakkujad"
|
||||
|
||||
msgid "Command not found"
|
||||
msgstr "Käsku ei leitud"
|
||||
@@ -250,9 +159,6 @@ msgstr "Käsku ei leitud"
|
||||
msgid "Could not parse command:"
|
||||
msgstr "Käsku pole võimalik analüüsida:"
|
||||
|
||||
msgid "No such application"
|
||||
msgstr "Sellist rakendust ei ole"
|
||||
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "'%s' käivitamine nurjus:"
|
||||
@@ -264,8 +170,8 @@ msgstr "Kõik"
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "Rakendused"
|
||||
|
||||
msgid "PREFERENCES"
|
||||
msgstr "Eelistused"
|
||||
msgid "SETTINGS"
|
||||
msgstr "Seaded"
|
||||
|
||||
msgid "New Window"
|
||||
msgstr "Uus aken"
|
||||
@@ -382,7 +288,7 @@ msgstr "L"
|
||||
|
||||
#. Translators: Text to show if there are no events
|
||||
msgid "Nothing Scheduled"
|
||||
msgstr ""
|
||||
msgstr "Ühtegi sündmust pole plaanitud"
|
||||
|
||||
#. Translators: Shown on calendar heading when selected day occurs on current year
|
||||
msgctxt "calendar heading"
|
||||
@@ -465,6 +371,8 @@ msgstr "Logi välja"
|
||||
|
||||
msgid "Click Log Out to quit these applications and log out of the system."
|
||||
msgstr ""
|
||||
"Nende rakenduste sulgemiseks ja süsteemist väljalogimiseks klõpsa nupule "
|
||||
"Logi välja."
|
||||
|
||||
#, c-format
|
||||
msgid "%s will be logged out automatically in %d seconds."
|
||||
@@ -477,17 +385,19 @@ msgstr "Sind logitakse %d sekundi pärast automaatselt välja."
|
||||
msgid "Logging out of the system."
|
||||
msgstr "Süsteemist väljalogimine"
|
||||
|
||||
msgid "Shut Down"
|
||||
msgid "Power Off"
|
||||
msgstr "Lülita välja"
|
||||
|
||||
msgid "Click Shut Down to quit these applications and shut down the system."
|
||||
msgid "Click Power Off to quit these applications and power off the system."
|
||||
msgstr ""
|
||||
"Nende rakenduste sulgemiseks ja süsteemi väljalülitamiseks klõpsa nupule "
|
||||
"Lülita välja."
|
||||
|
||||
#, c-format
|
||||
msgid "The system will shut down automatically in %d seconds."
|
||||
msgid "The system will power off automatically in %d seconds."
|
||||
msgstr "%d sekundi pärast lülitub süsteem automaatselt välja."
|
||||
|
||||
msgid "Shutting down the system."
|
||||
msgid "Powering off the system."
|
||||
msgstr "Süsteemi väljalülitamine."
|
||||
|
||||
msgid "Restart"
|
||||
@@ -505,9 +415,6 @@ msgstr "Süsteem taaskäivitatakse automaatselt %d sekundi pärast."
|
||||
msgid "Restarting the system."
|
||||
msgstr "Süsteemi taaskäivitamine."
|
||||
|
||||
msgid "Confirm"
|
||||
msgstr "Kinnita"
|
||||
|
||||
msgid "Cancel"
|
||||
msgstr "Katkesta"
|
||||
|
||||
@@ -534,6 +441,9 @@ msgstr "Kuva lähtekoodi"
|
||||
msgid "Web Page"
|
||||
msgstr "Veebileht"
|
||||
|
||||
msgid "Open"
|
||||
msgstr "Ava"
|
||||
|
||||
msgid "System Information"
|
||||
msgstr "Süsteemi andmed"
|
||||
|
||||
@@ -546,6 +456,11 @@ msgstr "Aknad"
|
||||
msgid "Applications"
|
||||
msgstr "Rakendused"
|
||||
|
||||
#. Translators: this is the name of the dock/favorites area on
|
||||
#. the left of the overview
|
||||
msgid "Dash"
|
||||
msgstr "Dokk"
|
||||
|
||||
#. TODO - _quit() doesn't really work on apps in state STARTING yet
|
||||
#, c-format
|
||||
msgid "Quit %s"
|
||||
@@ -556,6 +471,9 @@ msgstr "Lõpeta %s"
|
||||
msgid "Activities"
|
||||
msgstr "Tegevused"
|
||||
|
||||
msgid "Top Bar"
|
||||
msgstr "Ülemine riba"
|
||||
|
||||
#, c-format
|
||||
msgid "Failed to unmount '%s'"
|
||||
msgstr "'%s' lahtihaakimine nurjus"
|
||||
@@ -569,6 +487,25 @@ msgstr "Ühendumine..."
|
||||
msgid "PLACES & DEVICES"
|
||||
msgstr "Asukohad ja seadmed"
|
||||
|
||||
msgid "Authentication Required"
|
||||
msgstr "Vajalik on autentimine"
|
||||
|
||||
msgid "Administrator"
|
||||
msgstr "Administraator"
|
||||
|
||||
msgid "Authenticate"
|
||||
msgstr "Autendi"
|
||||
|
||||
#. Translators: "that didn't work" refers to the fact that the
|
||||
#. * requested authentication was not gained; this can happen
|
||||
#. * because of an authentication error (like invalid password),
|
||||
#. * for instance.
|
||||
msgid "Sorry, that didn't work. Please try again."
|
||||
msgstr "Kahjuks see ei sobinud. Palun proovi uuesti."
|
||||
|
||||
msgid "Password:"
|
||||
msgstr "Parool:"
|
||||
|
||||
#. Translators: this MUST be either "toggle-switch-us"
|
||||
#. (for toggle switches containing the English words
|
||||
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
|
||||
@@ -580,6 +517,18 @@ msgstr "toggle-switch-intl"
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Palun sisesta käsk:"
|
||||
|
||||
msgid "Searching..."
|
||||
msgstr "Otsimine..."
|
||||
|
||||
msgid "No matching results."
|
||||
msgstr "Tulemused puuduvad."
|
||||
|
||||
msgid "Power Off..."
|
||||
msgstr "Lülita välja..."
|
||||
|
||||
msgid "Suspend"
|
||||
msgstr "Uinak"
|
||||
|
||||
msgid "Available"
|
||||
msgstr "Saadaval"
|
||||
|
||||
@@ -601,24 +550,15 @@ msgstr "Vaheta kasutajat"
|
||||
msgid "Log Out..."
|
||||
msgstr "Logi välja..."
|
||||
|
||||
#. This is temporarily removed, see
|
||||
#. http://bugzilla.gnome.org/show_bug.cgi?id=636680
|
||||
#. for details.
|
||||
#. item = new PopupMenu.PopupMenuItem(_("Suspend..."));
|
||||
#. item.connect('activate', Lang.bind(this, this._onShutDownActivate));
|
||||
#. this.menu.addMenuItem(item);
|
||||
msgid "Shut Down..."
|
||||
msgstr "Lülita välja..."
|
||||
|
||||
msgid "Zoom"
|
||||
msgstr ""
|
||||
|
||||
msgid "Screen Reader"
|
||||
msgstr "Ekraanilugeja"
|
||||
|
||||
msgid "Screen Keyboard"
|
||||
msgstr "Ekraaniklaviatuur"
|
||||
msgstr "Suurendus"
|
||||
|
||||
#. let screenReader = this._buildItem(_("Screen Reader"), APPLICATIONS_SCHEMA,
|
||||
#. 'screen-reader-enabled');
|
||||
#. this.menu.addMenuItem(screenReader);
|
||||
#. let screenKeyboard = this._buildItem(_("Screen Keyboard"), APPLICATIONS_SCHEMA,
|
||||
#. 'screen-keyboard-enabled');
|
||||
#. this.menu.addMenuItem(screenKeyboard);
|
||||
msgid "Visual Alerts"
|
||||
msgstr "Visuaalsed märguanded"
|
||||
|
||||
@@ -638,10 +578,10 @@ msgid "Universal Access Settings"
|
||||
msgstr "Universaalse ligipääsu sätted"
|
||||
|
||||
msgid "High Contrast"
|
||||
msgstr ""
|
||||
msgstr "Kõrgkontrastne"
|
||||
|
||||
msgid "Large Text"
|
||||
msgstr ""
|
||||
msgstr "Suur tekst"
|
||||
|
||||
msgid "Bluetooth"
|
||||
msgstr "Bluetooth"
|
||||
@@ -653,7 +593,7 @@ msgid "Send Files to Device..."
|
||||
msgstr "Failide saatmine seadmesse..."
|
||||
|
||||
msgid "Setup a New Device..."
|
||||
msgstr ""
|
||||
msgstr "Uue seadme häälestamine..."
|
||||
|
||||
msgid "Bluetooth Settings"
|
||||
msgstr "Bluetoothi sätted"
|
||||
@@ -672,7 +612,7 @@ msgstr "Viga seadme sirvimisel"
|
||||
|
||||
#, c-format
|
||||
msgid "The requested device cannot be browsed, error is '%s'"
|
||||
msgstr ""
|
||||
msgstr "Küsitud seadet pole võimalik sirvida, viga on '%s'"
|
||||
|
||||
msgid "Keyboard Settings"
|
||||
msgstr "Klaviatuurisätted"
|
||||
@@ -683,9 +623,6 @@ msgstr "Hiiresätted"
|
||||
msgid "Sound Settings"
|
||||
msgstr "Helisätted"
|
||||
|
||||
msgid "Bluetooth Agent"
|
||||
msgstr "Bluetoothi agent"
|
||||
|
||||
#, c-format
|
||||
msgid "Authorization request from %s"
|
||||
msgstr "Autoriseerimise päring seadmelt %s"
|
||||
@@ -731,12 +668,126 @@ msgstr "Palun sisesta seadme poolt öeldav PIN-kood."
|
||||
msgid "OK"
|
||||
msgstr "Olgu"
|
||||
|
||||
msgid "Show Keyboard Layout..."
|
||||
msgstr "Klaviatuuripaigutuse kuvamine..."
|
||||
|
||||
msgid "Localization Settings"
|
||||
msgstr "Lokaliseerimissätted"
|
||||
|
||||
msgid "<unknown>"
|
||||
msgstr "<tundmatu>"
|
||||
|
||||
#. Translators: this indicates that wireless or wwan is disabled by hardware killswitch
|
||||
msgid "disabled"
|
||||
msgstr "keelatud"
|
||||
|
||||
msgid "connecting..."
|
||||
msgstr "ühendumine..."
|
||||
|
||||
#. Translators: this is for network connections that require some kind of key or password
|
||||
msgid "authentication required"
|
||||
msgstr "vajalik on autentimine"
|
||||
|
||||
#. Translators: this is for devices that require some kind of firmware or kernel
|
||||
#. module, which is missing
|
||||
msgid "firmware missing"
|
||||
msgstr "püsivara puudub"
|
||||
|
||||
#. Translators: this is for wired network devices that are physically disconnected
|
||||
msgid "cable unplugged"
|
||||
msgstr "juhe eemaldatud"
|
||||
|
||||
#. Translators: this is for a network device that cannot be activated (for example it
|
||||
#. is disabled by rfkill, or it has no coverage
|
||||
msgid "unavailable"
|
||||
msgstr "pole saadaval"
|
||||
|
||||
msgid "connection failed"
|
||||
msgstr "ühendumine nurjus"
|
||||
|
||||
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
|
||||
#. and we cannot access its settings (including the name)
|
||||
msgid "Connected (private)"
|
||||
msgstr "Ühendatud (privaatne)"
|
||||
|
||||
msgid "Auto Ethernet"
|
||||
msgstr "Automaatne ethernet"
|
||||
|
||||
msgid "Auto broadband"
|
||||
msgstr "Automaatne lairibaühendus"
|
||||
|
||||
msgid "Auto dial-up"
|
||||
msgstr "Automaatne sissehelistamine"
|
||||
|
||||
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
|
||||
#, c-format
|
||||
msgid "Auto %s"
|
||||
msgstr "Automaatne %s"
|
||||
|
||||
msgid "Auto bluetooth"
|
||||
msgstr "Automaatne bluetooth"
|
||||
|
||||
msgid "Auto wireless"
|
||||
msgstr "Automaatne juhtmeta ühendus"
|
||||
|
||||
msgid "More..."
|
||||
msgstr "Veel..."
|
||||
|
||||
msgid "Enable networking"
|
||||
msgstr "Luba võrguühendused"
|
||||
|
||||
msgid "Wired"
|
||||
msgstr "Juhtmega"
|
||||
|
||||
msgid "Wireless"
|
||||
msgstr "Juhtmeta"
|
||||
|
||||
msgid "Mobile broadband"
|
||||
msgstr "Mobiiliühendus"
|
||||
|
||||
msgid "VPN Connections"
|
||||
msgstr "VPN-ühendused"
|
||||
|
||||
msgid "Network Settings"
|
||||
msgstr "Võrgusätted"
|
||||
|
||||
#, c-format
|
||||
msgid "You're now connected to mobile broadband connection '%s'"
|
||||
msgstr "Loodi mobiiliühendus '%s'"
|
||||
|
||||
#, c-format
|
||||
msgid "You're now connected to wireless network '%s'"
|
||||
msgstr "Loodi ühendus juhtmeta võrguga '%s'"
|
||||
|
||||
#, c-format
|
||||
msgid "You're now connected to wired network '%s'"
|
||||
msgstr "Loodi ühendus juhtmega võrguga '%s'"
|
||||
|
||||
#, c-format
|
||||
msgid "You're now connected to VPN network '%s'"
|
||||
msgstr "Loodi ühendus VPN-võrguga '%s'"
|
||||
|
||||
#, c-format
|
||||
msgid "You're now connected to '%s'"
|
||||
msgstr "Loodi võrguühendus '%s' kaudu"
|
||||
|
||||
msgid "Connection established"
|
||||
msgstr "Ühendus loodud"
|
||||
|
||||
msgid "Networking is disabled"
|
||||
msgstr "Võrguühendused on keelatud"
|
||||
|
||||
msgid "Network Manager"
|
||||
msgstr "Võrguhaldur"
|
||||
|
||||
msgid "Power Settings"
|
||||
msgstr "Toitesätted..."
|
||||
|
||||
#. 0 is reported when UPower does not have enough data
|
||||
#. to estimate battery life
|
||||
msgid "Estimating..."
|
||||
msgstr "Andmete kogumine..."
|
||||
|
||||
#, c-format
|
||||
msgid "%d hour remaining"
|
||||
msgid_plural "%d hours remaining"
|
||||
@@ -829,8 +880,15 @@ msgstr "%s on hõivatud."
|
||||
msgid "Sent at %X on %A"
|
||||
msgstr "Saadetud: %a, kell %X"
|
||||
|
||||
msgid "Search your computer"
|
||||
msgstr ""
|
||||
#. Translators: this is the text displayed
|
||||
#. in the search entry when no search is
|
||||
#. active; it should not exceed ~30
|
||||
#. characters.
|
||||
msgid "Type to search..."
|
||||
msgstr "Otsing..."
|
||||
|
||||
msgid "Search"
|
||||
msgstr "Otsing"
|
||||
|
||||
#, c-format
|
||||
msgid "%s has finished starting"
|
||||
@@ -840,32 +898,32 @@ msgstr "%s läks käima"
|
||||
msgid "'%s' is ready"
|
||||
msgstr "'%s' on valmis"
|
||||
|
||||
msgid ""
|
||||
"Can't add a new workspace because maximum workspaces limit has been reached."
|
||||
msgstr "Pole võimalik uut tööala lisada, kuna tööalade piir on saavutatud."
|
||||
|
||||
msgid "Can't remove the first workspace."
|
||||
msgstr "Esimest tööala pole võimalik eemaldada."
|
||||
|
||||
#. translators:
|
||||
#. * The number of sound outputs on a particular device
|
||||
#, c-format
|
||||
msgid "%u Output"
|
||||
msgid_plural "%u Outputs"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "%u väljund"
|
||||
msgstr[1] "%u väljundit"
|
||||
|
||||
#. translators:
|
||||
#. * The number of sound inputs on a particular device
|
||||
#, c-format
|
||||
msgid "%u Input"
|
||||
msgid_plural "%u Inputs"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "%u sisend"
|
||||
msgstr[1] "%u sisendit"
|
||||
|
||||
msgid "System Sounds"
|
||||
msgstr "Süsteemi helid"
|
||||
|
||||
msgid "Print version"
|
||||
msgstr "Printimise versioon"
|
||||
|
||||
#, c-format
|
||||
msgid "Failed to launch '%s'"
|
||||
msgstr "'%s' käivitamine nurjus"
|
||||
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Vähem kui minuti eest"
|
||||
|
||||
@@ -893,6 +951,15 @@ msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d nädal tagasi"
|
||||
msgstr[1] "%d nädalat tagasi"
|
||||
|
||||
msgid "United Kingdom"
|
||||
msgstr "Suurbritannia"
|
||||
|
||||
msgid "Default"
|
||||
msgstr "Vaikimisi"
|
||||
|
||||
msgid "Authentication dialog was dismissed by the user"
|
||||
msgstr "Kasutaja katkestas autentimisdialoogi"
|
||||
|
||||
msgid "Home Folder"
|
||||
msgstr "Kodukaust"
|
||||
|
||||
@@ -901,9 +968,6 @@ msgstr "Kodukaust"
|
||||
msgid "File System"
|
||||
msgstr "Failisüsteem"
|
||||
|
||||
msgid "Search"
|
||||
msgstr "Otsing"
|
||||
|
||||
#. Translators: the first string is the name of a gvfs
|
||||
#. * method, and the second string is a path. For
|
||||
#. * example, "Trash: some-directory". It means that the
|
||||
@@ -913,8 +977,140 @@ msgstr "Otsing"
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "Suspend..."
|
||||
#~ msgstr "Peata..."
|
||||
#~ msgid "Shut Down"
|
||||
#~ msgstr "Lülita välja"
|
||||
|
||||
#~ msgid "Click Shut Down to quit these applications and shut down the system."
|
||||
#~ msgstr ""
|
||||
#~ "Nende rakenduste sulgemiseks ja süsteemi väljalülitamiseks klõpsa nupule "
|
||||
#~ "Logi välja."
|
||||
|
||||
#~ msgid "The system will shut down automatically in %d seconds."
|
||||
#~ msgstr "%d sekundi pärast lülitub süsteem automaatselt välja."
|
||||
|
||||
#~ msgid "Shutting down the system."
|
||||
#~ msgstr "Süsteemi väljalülitamine."
|
||||
|
||||
#~ msgid "Confirm"
|
||||
#~ msgstr "Kinnita"
|
||||
|
||||
#~ msgid "Panel"
|
||||
#~ msgstr "Paneel"
|
||||
|
||||
#~ msgid "No such application"
|
||||
#~ msgstr "Sellist rakendust ei ole"
|
||||
|
||||
#~ msgid "Screen Reader"
|
||||
#~ msgstr "Ekraanilugeja"
|
||||
|
||||
#~ msgid "Screen Keyboard"
|
||||
#~ msgstr "Ekraaniklaviatuur"
|
||||
|
||||
#~ msgid "Clip the crosshairs at the center"
|
||||
#~ msgstr "Niitristi keskel on auk"
|
||||
|
||||
#~ msgid "Color of the crosshairs"
|
||||
#~ msgstr "Niitristi värvus"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Determines the transparency of the crosshairs, from fully opaque to fully "
|
||||
#~ "transparent."
|
||||
#~ msgstr ""
|
||||
#~ "Määrab niitristi läbipaistvuse, alates täiesti läbipaistmatust kuni "
|
||||
#~ "täiesti läbipaistvani."
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Determines whether the crosshairs intersect the magnified mouse sprite, "
|
||||
#~ "or are clipped such that the ends of the horizontal and vertical lines "
|
||||
#~ "surround the mouse image."
|
||||
#~ msgstr ""
|
||||
#~ "Määrab, kas niitrist kattub suurendatud hiire pildiga või on keskelt ära "
|
||||
#~ "lõigatud nii, et jooned ümbritsevad hiirekursori pilti."
|
||||
|
||||
#~ msgid "Enable lens mode"
|
||||
#~ msgstr "Läätsede režiimi lubamine"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Enables/disables display of crosshairs centered on the magnified mouse "
|
||||
#~ "sprite."
|
||||
#~ msgstr "Lubab/keelab niitristi kuvamise suurendatud hiirekursori kohal."
|
||||
|
||||
#~ msgid "Length of the crosshairs"
|
||||
#~ msgstr "Niitristi pikkus"
|
||||
|
||||
#~ msgid "Magnification factor"
|
||||
#~ msgstr "Suurendustegur"
|
||||
|
||||
#~ msgid "Mouse Tracking Mode"
|
||||
#~ msgstr "Hiire jälitamise režiim"
|
||||
|
||||
#~ msgid "Opacity of the crosshairs"
|
||||
#~ msgstr "Niitristi läbipaistvus"
|
||||
|
||||
#~ msgid "Screen position"
|
||||
#~ msgstr "Ekraani asukoht"
|
||||
|
||||
#~ msgid "Scroll magnified contents beyond the edges of the desktop"
|
||||
#~ msgstr "Suurendusklaas võib liikuda töölauapiiridest väljapoole"
|
||||
|
||||
#~ msgid "Show or hide crosshairs"
|
||||
#~ msgstr "Niitristi kuvamine või peitmine"
|
||||
|
||||
#~ msgid "Show or hide the magnifier"
|
||||
#~ msgstr "Suurendusklaasi kuvamine või peitmine"
|
||||
|
||||
#~ msgid "Show or hide the magnifier and all of its zoom regions."
|
||||
#~ msgstr ""
|
||||
#~ "Suurendusklaasi ja selle kõigi suurenduspiirkondade kuvamine või peitmine."
|
||||
|
||||
#~ msgid ""
|
||||
#~ "The color of the the vertical and horizontal lines that make up the "
|
||||
#~ "crosshairs."
|
||||
#~ msgstr "Niitristi püst- ja rõhtjoone värvus."
|
||||
|
||||
#~ msgid ""
|
||||
#~ "The magnified view either fills the entire screen, or occupies the top-"
|
||||
#~ "half, bottom-half, left-half, or right-half of the screen."
|
||||
#~ msgstr ""
|
||||
#~ "Suurendatud vaade täidab kas kogu ekraani või täidab ülemise, alumise, "
|
||||
#~ "vasaku või parema ekraanipoole."
|
||||
|
||||
#~ msgid ""
|
||||
#~ "The power of the magnification. A value of 1.0 means no magnification. A "
|
||||
#~ "value of 2.0 doubles the size."
|
||||
#~ msgstr ""
|
||||
#~ "Suurendustegur. 1,0 tähendab originaalsuurust. 2,0 muudab kaks korda."
|
||||
|
||||
#~ msgid "Thickness of the crosshairs"
|
||||
#~ msgstr "Niitristi paksus"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Whether the magnified view should be centered over the location of the "
|
||||
#~ "system mouse and move with it."
|
||||
#~ msgstr ""
|
||||
#~ "Kas suurendatud vaate keskkoht peaks asetsema süsteemi hiire kohal ning "
|
||||
#~ "liikuma sellega kaasa."
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Width of the vertical and horizontal lines that make up the crosshairs."
|
||||
#~ msgstr "Niitristi moodustavate püst- ja rõhtjoone laius"
|
||||
|
||||
#~ msgid "PREFERENCES"
|
||||
#~ msgstr "Eelistused"
|
||||
|
||||
#~ msgid "Shut Down..."
|
||||
#~ msgstr "Lülita välja..."
|
||||
|
||||
#~ msgid "Bluetooth Agent"
|
||||
#~ msgstr "Bluetoothi agent"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Can't add a new workspace because maximum workspaces limit has been "
|
||||
#~ "reached."
|
||||
#~ msgstr "Pole võimalik uut tööala lisada, kuna tööalade piir on saavutatud."
|
||||
|
||||
#~ msgid "Can't remove the first workspace."
|
||||
#~ msgstr "Esimest tööala pole võimalik eemaldada."
|
||||
|
||||
#~ msgid "Clock"
|
||||
#~ msgstr "Kell"
|
||||
@@ -958,11 +1154,5 @@ msgstr "%1$s: %2$s"
|
||||
#~ msgid "Find"
|
||||
#~ msgstr "Otsi"
|
||||
|
||||
#~ msgid "Searching..."
|
||||
#~ msgstr "Otsimine..."
|
||||
|
||||
#~ msgid "No matching results."
|
||||
#~ msgstr "Tulemused puuduvad."
|
||||
|
||||
#~ msgid "Invisible"
|
||||
#~ msgstr "Nähtamatu"
|
||||
|
||||