Compare commits
306 Commits
wip/cogl-d
...
3.11.1
Author | SHA1 | Date | |
---|---|---|---|
cf7cf45003 | |||
633dd0d9de | |||
b929320d4c | |||
7296bedd8e | |||
e9fbbf4000 | |||
dd44219aa5 | |||
8cc1fe007d | |||
c0b45c9fc4 | |||
41315f45a9 | |||
04d28a0eea | |||
1e9cd3f785 | |||
f462dd6a4c | |||
34e75fc595 | |||
dac513e046 | |||
2c538d247b | |||
f3b7f61e54 | |||
d47ecf19f5 | |||
da19b344b5 | |||
eb66407926 | |||
61c5b8e7d2 | |||
4b09d57ec2 | |||
a16f699dfc | |||
b908a3d70a | |||
d519c7263e | |||
5dedc5d8ba | |||
3ca1784ff4 | |||
b54d512f3f | |||
9d8fb19f55 | |||
1ac4ab7edc | |||
c9b73ac731 | |||
e0b87f1e14 | |||
394743efc8 | |||
27a86a4756 | |||
8ee0ef2cde | |||
43f4682ec4 | |||
5f081b8f8d | |||
5023542882 | |||
88d0731d80 | |||
06cb8c52d7 | |||
4d1358b7ed | |||
0cfa7c1c56 | |||
76928390a3 | |||
af1f9cd76d | |||
2f39f3d146 | |||
f72f39bc26 | |||
2659ba6bb4 | |||
0b8c0c202e | |||
37c8132632 | |||
02f2f694e4 | |||
d175a588f7 | |||
4bb41f2f66 | |||
088c46c7be | |||
4228c40b3d | |||
d581d29198 | |||
5a7e854f9e | |||
6e13823ccc | |||
5c5f2fdf8f | |||
96aa33f4ef | |||
25fd23e703 | |||
99cf4e5787 | |||
66a4cb5875 | |||
da14e2c349 | |||
4cda61a16a | |||
002afda503 | |||
cb7a2e8c6a | |||
d21ae1dad1 | |||
4548859509 | |||
09c6e6427a | |||
8c34398a15 | |||
a65b705080 | |||
7e28c71074 | |||
726f4a6715 | |||
a444b43548 | |||
473bb139d1 | |||
d084770cea | |||
619389ed20 | |||
ad043e009e | |||
89b9d079b1 | |||
58a8845047 | |||
3e6c8e68b4 | |||
40cd92f701 | |||
e216addf7c | |||
9291594330 | |||
f6010864ea | |||
13e6a6def5 | |||
575b373cd5 | |||
0892065649 | |||
766ef367fb | |||
0c7d9958f5 | |||
425b8f6073 | |||
63593e45a6 | |||
a6ee9806de | |||
a6579f4ceb | |||
639622a4fe | |||
e28ec2f5ab | |||
873753c735 | |||
ff14951be4 | |||
b47b445558 | |||
6e9a2fea89 | |||
64d2679b3c | |||
3c3d4dfccb | |||
0ccffed517 | |||
20c18c1fc0 | |||
a21c0097c2 | |||
404d9ef2af | |||
503fa1cbce | |||
63f7991d0f | |||
ae301c1f39 | |||
8e911fb719 | |||
a0d84e44c5 | |||
81fb7ebb31 | |||
3751211590 | |||
6b4cba09be | |||
6a7d184b7b | |||
bde5cfc8bb | |||
777c7a952b | |||
c79bdd9029 | |||
6a154efe65 | |||
627f3ef36b | |||
3d28836f2c | |||
c28bd04958 | |||
a6fb3acb42 | |||
8a8b3bf96e | |||
f7624e5f05 | |||
55edfd2e4a | |||
91878dd52c | |||
c132358ec9 | |||
e426f8ac47 | |||
740dca8afc | |||
6ae06d319c | |||
30bc2b2f9c | |||
7dc8e9d657 | |||
1ab2fa5bf0 | |||
779a1077bf | |||
815bf7a53a | |||
91a382dfb5 | |||
2d8d4cd57d | |||
0c5fe2b3bf | |||
56c487347f | |||
0a572fce1b | |||
e898e29910 | |||
843f076225 | |||
fdb732c8c2 | |||
33896a4e8f | |||
51e016a0d6 | |||
8737b06559 | |||
15ab285174 | |||
3a4782cc64 | |||
0256a6d47b | |||
8b0e846e0e | |||
41acb5d3cc | |||
a2f9b8ea9b | |||
6237a1c505 | |||
7c08db0b0f | |||
df1270ac49 | |||
46edc053d4 | |||
908046c31a | |||
8380c79875 | |||
8a4879a96a | |||
cdf1a77f08 | |||
3f9857ccbd | |||
1d65a31420 | |||
dafdf0838a | |||
f9cf135f68 | |||
a1878e54c9 | |||
95e5d899a9 | |||
ee8321df67 | |||
4918213e68 | |||
ed7f349fc6 | |||
2888f22a24 | |||
fcb217f681 | |||
9ffa9fe1a8 | |||
905020c507 | |||
02f5500641 | |||
465af55d6e | |||
80a3bb85aa | |||
ea26bd3003 | |||
508a511d2a | |||
2d80cb71db | |||
e31693bbee | |||
fb561f10a7 | |||
0c57d53e03 | |||
3b1b9f589b | |||
ac8d39acf4 | |||
664e795217 | |||
82bf323f63 | |||
547ac85113 | |||
46e0e4430d | |||
609a31ea46 | |||
3e99eb10d1 | |||
b9d935af0c | |||
31d3e82aa8 | |||
dfdc17197b | |||
62b965b4b7 | |||
ba221abea5 | |||
aa026c7134 | |||
496cfff97a | |||
ccaa7f5f3e | |||
f492d21c70 | |||
1983541f8c | |||
e4cb3672b9 | |||
a06a78a9c1 | |||
2ba91ad837 | |||
66eb3ea723 | |||
d30e992b20 | |||
c6a342563f | |||
fd584eda05 | |||
4301506590 | |||
88f7c3a970 | |||
f21a9f0cc2 | |||
2233c2e618 | |||
6264419bd4 | |||
b62effb8fa | |||
c8a07dd612 | |||
02c99e4b25 | |||
1242a16265 | |||
a89fd17b8e | |||
3d5e7bd6f1 | |||
cefcb89487 | |||
005272bde9 | |||
491e60e4f2 | |||
e5f72fd302 | |||
5f21b100b8 | |||
1a4c7629c5 | |||
d21734ee47 | |||
e140e2c367 | |||
7ced1f5b54 | |||
54b028ee3e | |||
703336e1ea | |||
9e936252ae | |||
fc71a0f081 | |||
86c72fa15d | |||
6ba5af1e9e | |||
33a4f59cfb | |||
39134f0d9b | |||
30e7440851 | |||
be1a7bac7c | |||
fb52a93a28 | |||
efdf1ff755 | |||
2c00dad211 | |||
c23786c73e | |||
7f1b07b76f | |||
2f35ad6e65 | |||
159c7d34c7 | |||
fe8e990ed7 | |||
1fb9b18cb6 | |||
5c2586127b | |||
661b266b45 | |||
98af044196 | |||
8006c336f5 | |||
bdf07d2ce8 | |||
efcf858e60 | |||
93d9c16672 | |||
7aaf261f5a | |||
5eb4450012 | |||
49c8cdd8f6 | |||
c860b96a86 | |||
69403bda80 | |||
f5456b66ff | |||
28b4c413cb | |||
5b97250bb1 | |||
5d26c29eaa | |||
613944eccd | |||
8d0e8fc021 | |||
41ee70d414 | |||
3691e8ddd7 | |||
be54e94045 | |||
366ca72342 | |||
fc4e392ac1 | |||
507be35d3a | |||
5c0d62cd0e | |||
7b7c4568b2 | |||
f38091d96b | |||
7c78e1fbf5 | |||
72f0a48fac | |||
193f872ebe | |||
c3f96cf0e8 | |||
df09109d81 | |||
662cb9e2a3 | |||
daa54a3798 | |||
f035a1a0e0 | |||
2688bf3333 | |||
4095a58eb9 | |||
c1b1ebe97e | |||
a47b97d443 | |||
df5d5583eb | |||
79e764d5ec | |||
2fcb04e5b2 | |||
da1e264687 | |||
03975287d2 | |||
50a61b38f7 | |||
1fe072471e | |||
93e840295e | |||
6ab7d640f0 | |||
255cb8edb1 | |||
367fb32493 | |||
ef6d1fd6ce | |||
3e8ab0645b | |||
135727c9f7 | |||
c58448817b | |||
8ae0f1a9dc | |||
ba9c1d98f6 | |||
4db6e70f97 | |||
9d1f789937 | |||
11c2933e23 | |||
fbd4951ea7 |
5
.gitignore
vendored
@ -19,6 +19,8 @@ configure
|
||||
data/50-gnome-shell-*.xml
|
||||
data/gnome-shell.desktop
|
||||
data/gnome-shell.desktop.in
|
||||
data/gnome-shell-wayland.desktop
|
||||
data/gnome-shell-wayland.desktop.in
|
||||
data/gnome-shell-extension-prefs.desktop
|
||||
data/gnome-shell-extension-prefs.desktop.in
|
||||
data/gschemas.compiled
|
||||
@ -71,13 +73,14 @@ src/calendar-server/evolution-calendar.desktop.in
|
||||
src/calendar-server/org.gnome.Shell.CalendarServer.service
|
||||
src/gnome-shell
|
||||
src/gnome-shell-calendar-server
|
||||
src/gnome-shell-extension-tool
|
||||
src/gnome-shell-extension-prefs
|
||||
src/gnome-shell-extension-tool
|
||||
src/gnome-shell-hotplug-sniffer
|
||||
src/gnome-shell-jhbuild
|
||||
src/gnome-shell-perf-helper
|
||||
src/gnome-shell-perf-tool
|
||||
src/gnome-shell-real
|
||||
src/gnome-shell-wayland
|
||||
src/hotplug-sniffer/org.gnome.Shell.HotplugSniffer.service
|
||||
src/run-js-test
|
||||
src/test-recorder
|
||||
|
143
NEWS
@ -1,3 +1,146 @@
|
||||
3.11.1
|
||||
======
|
||||
* power: Use UPower directly instead of gnome-settings-daemon [Bastien; #710273]
|
||||
* Implement support for new GTK+ notification API [Jasper, Giovanni, Florian;
|
||||
#710137, #710596]
|
||||
* gdm: Don't allow user-list to fill up the entire screen [Florian; #710555]
|
||||
* Don't autostart remote search providers at login [Giovanni; #708830]
|
||||
* Fix spacing in end-session dialog [Sebastien; #710543]
|
||||
* Prepare for js24 [Tim; #711052]
|
||||
* Misc bug fixes and cleanups [Jasper, Florian, Adel, Tim, Sebastien; #710347,
|
||||
#710144, #710541, #691409, #710745, #688331, #704912]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Adel Gadllah, Sebastien Lafargue, Tim Lunn,
|
||||
Florian Müllner, Bastien Nocera, Jasper St. Pierre, Rico Tzschichholz
|
||||
|
||||
Translations:
|
||||
Stas Solovey [ru], Yosef Or Boczko [he], Rafael Ferreira [pt_BR]
|
||||
|
||||
3.10.1
|
||||
======
|
||||
* Make sure lock screen is drawn once before switching user [Giovanni; #708051]
|
||||
* Fix signal strength indicators in network selector [Jasper; #708442]
|
||||
* Scroll search results when focusing provider icons [Jasper; #708868]
|
||||
* Add separate hover/active states to page indicators [Carlos; #708852]
|
||||
* Tweak appearance of user name and avatar [Yash; #702309]
|
||||
* Hide "Turn On" in network menu when disabled by hardware [Giovanni; #709635]
|
||||
* Cancel open keyring prompts when the screen is locked [Florian; #708910]
|
||||
* Differentiate "Not Connected" and "Off" in network menu [Giovanni; #709043]
|
||||
* Make network settings items point to the right device [Giovanni; #709246]
|
||||
* Remove animation of window preview titles [Sebastien; #709392]
|
||||
* Add 'Notifications' switch to tray menu [Florian; #707073]
|
||||
* Make dropdown arrows consistent [Carlos; #709564]
|
||||
* power: Use icon from primary device for status [Jasper; #709925]
|
||||
* Fix XDND drags to overview [Adel; #708887]
|
||||
* Fix workspace switcher disappearing with too many workspaces [Jasper; #694881]
|
||||
* Handle search results with 'special:' prefix specially [Giovanni; #707055]
|
||||
* gdm: Support pre-authenticated logins from oVirt [Vinzenz; #702162]
|
||||
* Use ARROW role for labels representing arrows [Alejandro; #710120]
|
||||
* Make selected view in app picker persistent [Florian; #710042]
|
||||
* Make network selector navigable by keyboard [Alejandro; #710144]
|
||||
* Misc bug fixes [Florian, Adel, Jasper, Aleksander, Giovanni, Dan, Michael,
|
||||
Tim; #709034, #709263, #698486, #709286, #709248, #709543, #696564, #703265,
|
||||
#709638, #709866, #709998, #710019, #710104, #710115]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Michael Catanzaro, Vinzenz Feenstra, Adel Gadllah,
|
||||
Yash Girdhar, Sebastien Lafargue, Tim Lunn, Aleksander Morgado,
|
||||
Florian Müllner, Alejandro Piñeiro, Carlos Soriano, Jasper St. Pierre,
|
||||
Dieter Verfaillie, Dan Winship
|
||||
|
||||
Translations:
|
||||
Inaki Larranaga Murgoitio [eu], Christian Kirbach [de], Muhammet Kara [tr],
|
||||
Aurimas Černius [lt], Ryan Lortie [eo], Rūdolfs Mazurs [lv],
|
||||
Dušan Kazik [sk], Fran Diéguez [gl], Enrico Nicoletto [pt_BR],
|
||||
Kjartan Maraas [nb], Victor Ibragimov [tg], Matej Urbančič [sl],
|
||||
A S Alam [pa], Nilamdyuti Goswami [as], Daniel Mustieles [es],
|
||||
Cheng-Chia Tseng [zh_HK, zh_TW], Mattias Põldaru [et], Kenneth Nielsen [da],
|
||||
Milo Casagrande [it], Marek Černocký [cs], Ihar Hrachyshka [be],
|
||||
Мирослав Николић [sr, sr@latin], Arash Mousavi [fa], Yuri Myasoedov [ru],
|
||||
Gil Forcada [ca], Carles Ferrando [ca@valencia], Andika Triwidada [id],
|
||||
Timo Jyrinki [fi], Piotr Drąg [pl], Rafael Ferreira [pt_BR],
|
||||
Gabor Kelemen [hu], Yosef Or Boczko [he], Daniel Korostil [uk],
|
||||
Wouter Bolsterlee [nl], António Lima [pt]
|
||||
|
||||
3.10.0.1
|
||||
=========
|
||||
* Fix login screen [Ray; #708691]
|
||||
|
||||
Contributors:
|
||||
Ray Strode, Giovanni Campagna, Jasper St. Pierree
|
||||
|
||||
Translations:
|
||||
Kjartan Maraas [nb], Marek Černocký [cs], A S Alam [pa], Daniel Mustieles [es],
|
||||
Ihar Hrachyshka [be], Chao-Hsiung Liao [zh_HK], Nilamdyuti Goswami [as],
|
||||
Yuri Myasoedov [ru], Baurzhan Muftakhidinov [kk]
|
||||
|
||||
3.10.0
|
||||
======
|
||||
* Fix fade effect in ScrollViews [Carlos; #708256]
|
||||
* network: Resync when activating connection changes [Jasper; #708322]
|
||||
* Close run dialog when the screen locks [Florian; #708218]
|
||||
* Fix entry growing out of password dialogs [Florian; #708324, #703833]
|
||||
* Vertically center labels in submenu items [Jasper; #708330]
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=708387 [Mike; #708387]
|
||||
* Fix bluetooth icon not being added to status menu [Jasper; #708541]
|
||||
* Fix GNOME 2 keyring dialogs appearing on lock screen [Florian; #708187]
|
||||
* Fix passwords being cleared twice when authentication fails [Florian; #708186]
|
||||
* Fix message tray appearing in a11y popup on login screen [Florian; #708380]
|
||||
* Increase width of aggregate menu popup [Adel; #708472]
|
||||
|
||||
Contributors:
|
||||
Adel Gadllah, Mike Gorse, Ryan Lortie, Florian Müllner, Frédéric Péters,
|
||||
Carlos Soriano, Jasper St. Pierre, Rico Tzschichholz
|
||||
|
||||
Translations:
|
||||
Daniel Șerbănescu [ro], Ryan Lortie [eo], Ihar Hrachyshka [be],
|
||||
A S Alam [pa], Jiro Matsuzawa [ja], Chao-Hsiung Liao [zh_HK, zh_TW],
|
||||
Piotr Drąg [pl], Kristjan SCHMIDT [eo], Daniel Korostil [uk],
|
||||
Rūdolfs Mazurs [lv], Reinout van Schouwen [nl], Yosef Or Boczko [he],
|
||||
Fran Diéguez [gl], António Lima [pt], Andika Triwidada [id],
|
||||
Alexandre Franke [fr], Rafael Ferreira [pt_BR], Milo Casagrande [it],
|
||||
Kenneth Nielsen [da], Matej Urbančič [sl]
|
||||
|
||||
3.9.92
|
||||
======
|
||||
* Don't show page indicators if there's only one page [Florian; #707363]
|
||||
* Make :active style of app and non-app results consistent [Jakub; #704714]
|
||||
* Fade app pages when scrolled [Florian; #707409]
|
||||
* Don't block scrolling on page indicators [Carlos; #707609]
|
||||
* Tweak visual appearance of folder views [Florian; #707662]
|
||||
* Don't put minimized apps at the end of the app switcher [Florian; #707663]
|
||||
* Merge the wayland branch [Giovanni, Neil; #707467]
|
||||
* Make search entry behave better in RTL locales [Matthias, Florian; #705779]
|
||||
* Allow to change app pages with pageUp/pageDown keys [Carlos; #707979]
|
||||
* Set approriate a11y states on expandable menu items [Alejandro; #708038]
|
||||
* Improve page indicator animation [Carlos; #707565]
|
||||
* Misc bug fixes and cleanups [Florian, Olivier, Jasper, Giovanni, Magdalen,
|
||||
Adel, Carlos, Rico, Joanmarie; #707308, #707430, #707508, #707557, #707600,
|
||||
#707614, #707666, #707814, #707806, #707801, #707889, #707892, #707935,
|
||||
#707842, #707940, #707996, #708007, #708009, #708020, #707580, #708080]
|
||||
|
||||
Contributors:
|
||||
Magdalen Berns, Olivier Blin, Giovanni Campagna, Matthias Clasen,
|
||||
Joanmarie Diggs, Adel Gadllah, Florian Müllner, Alejandro Piñeiro,
|
||||
Neil Roberts, Carlos Soriano, Jasper St. Pierre, Jakub Steiner,
|
||||
Rico Tzschichholz
|
||||
|
||||
Translations:
|
||||
Rafael Ferreira [pt_BR], Fran Diéguez [gl], Daniel Mustieles [es],
|
||||
Aurimas Černius [lt], Luca Ferretti [it], Piotr Drąg [pl],
|
||||
Chao-Hsiung Liao [zh_HK, zh_TW], Timo Jyrinki [fi], Daniel Korostil [uk],
|
||||
Dušan Kazik [sk], Adam Matoušek [cs], Marek Černocký [cs],
|
||||
Jiro Matsuzawa [ja], Yuri Myasoedov [ru], Tobias Endrigkeit [de],
|
||||
Kjartan Maraas [nb], Victor Ibragimov [tg], Мирослав Николић [sr, sr@latin],
|
||||
A S Alam [pa], Khaled Hosny [ar], Andika Triwidada [id],
|
||||
Nilamdyuti Goswami [as], Ihar Hrachyshka [be], Rūdolfs Mazurs [lv],
|
||||
Mattias Põldaru [et], Gabor Kelemen [hu], Bruce Cowan [en_GB],
|
||||
Matej Urbančič [sl], Enrico Nicoletto [pt_BR], Benjamin Steinwender [de],
|
||||
Changwoo Ryu [ko], Kris Thomsen [da], Alexandre Franke [fr],
|
||||
Evgeny Bobkin [ru], Baurzhan Muftakhidinov [kk], Peter Mráz [sk],
|
||||
Inaki Larranaga Murgoitio [eu], Yosef Or Boczko [he]
|
||||
|
||||
3.9.91
|
||||
======
|
||||
* Improve submenu styling [Jakub; #706037]
|
||||
|
@ -1,5 +1,5 @@
|
||||
AC_PREREQ(2.63)
|
||||
AC_INIT([gnome-shell],[3.9.91],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||
AC_INIT([gnome-shell],[3.11.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])
|
||||
@ -16,6 +16,7 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
|
||||
# Initialize libtool
|
||||
LT_PREREQ([2.2.6])
|
||||
@ -59,8 +60,8 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
|
||||
|
||||
CLUTTER_MIN_VERSION=1.13.4
|
||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
|
||||
GJS_MIN_VERSION=1.35.4
|
||||
MUTTER_MIN_VERSION=3.9.91
|
||||
GJS_MIN_VERSION=1.38.1
|
||||
MUTTER_MIN_VERSION=3.11.1
|
||||
GTK_MIN_VERSION=3.7.9
|
||||
GIO_MIN_VERSION=2.37.0
|
||||
LIBECAL_MIN_VERSION=3.5.3
|
||||
|
@ -1,8 +1,9 @@
|
||||
wandadir = $(pkgdatadir)
|
||||
dist_wanda_DATA = wanda.png
|
||||
|
||||
desktopdir=$(datadir)/applications
|
||||
desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
|
||||
if HAVE_MUTTER_WAYLAND
|
||||
desktop_DATA += gnome-shell-wayland.desktop
|
||||
endif HAVE_MUTTER_WAYLAND
|
||||
|
||||
|
||||
# We substitute in bindir so it works as an autostart
|
||||
# file when built in a non-system prefix
|
||||
@ -41,8 +42,10 @@ dist_theme_DATA = \
|
||||
theme/message-tray-background.png \
|
||||
theme/more-results.svg \
|
||||
theme/noise-texture.png \
|
||||
theme/page-indicator-active.svg \
|
||||
theme/page-indicator-active.svg \
|
||||
theme/page-indicator-inactive.svg \
|
||||
theme/page-indicator-checked.svg \
|
||||
theme/page-indicator-hover.svg \
|
||||
theme/panel-button-border.svg \
|
||||
theme/panel-button-highlight-narrow.svg \
|
||||
theme/panel-button-highlight-wide.svg \
|
||||
@ -83,6 +86,7 @@ convert_DATA = gnome-shell-overrides.convert
|
||||
|
||||
EXTRA_DIST = \
|
||||
gnome-shell.desktop.in.in \
|
||||
gnome-shell-wayland.desktop.in.in \
|
||||
gnome-shell-extension-prefs.desktop.in.in \
|
||||
$(introspection_DATA) \
|
||||
$(menu_DATA) \
|
||||
@ -92,6 +96,7 @@ EXTRA_DIST = \
|
||||
|
||||
CLEANFILES = \
|
||||
gnome-shell.desktop.in \
|
||||
gnome-shell-wayland.desktop.in \
|
||||
gnome-shell-extension-prefs.in \
|
||||
$(desktop_DATA) \
|
||||
$(keys_DATA) \
|
||||
|
15
data/gnome-shell-wayland.desktop.in.in
Normal file
@ -0,0 +1,15 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
_Name=GNOME Shell (wayland compositor)
|
||||
_Comment=Window management and application launching
|
||||
Exec=@bindir@/mutter-launch -- gnome-shell-wayland --wayland
|
||||
X-GNOME-Bugzilla-Bugzilla=GNOME
|
||||
X-GNOME-Bugzilla-Product=gnome-shell
|
||||
X-GNOME-Bugzilla-Component=general
|
||||
X-GNOME-Bugzilla-Version=@VERSION@
|
||||
Categories=GNOME;GTK;Core;
|
||||
OnlyShowIn=GNOME;
|
||||
NoDisplay=true
|
||||
X-GNOME-Autostart-Phase=DisplayServer
|
||||
X-GNOME-Autostart-Notify=true
|
||||
X-GNOME-AutoRestart=false
|
@ -37,6 +37,13 @@
|
||||
application view, rather than being displayed inline in the main view.
|
||||
</_description>
|
||||
</key>
|
||||
<key name="app-picker-view" type="u">
|
||||
<default>0</default>
|
||||
<summary>App Picker View</summary>
|
||||
<description>
|
||||
Index of the currently selected view in the application picker.
|
||||
</description>
|
||||
</key>
|
||||
<key name="command-history" type="as">
|
||||
<default>[]</default>
|
||||
<_summary>History for command (Alt-F2) dialog</_summary>
|
||||
@ -216,10 +223,10 @@
|
||||
|
||||
<key name="focus-change-on-pointer-rest" type="b">
|
||||
<default>true</default>
|
||||
<summary>Delay focus changes in mouse mode until the pointer stops moving</summary>
|
||||
<description>
|
||||
<_summary>Delay focus changes in mouse mode until the pointer stops moving</_summary>
|
||||
<_description>
|
||||
This key overrides the key in org.gnome.mutter when running GNOME Shell.
|
||||
</description>
|
||||
</_description>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
||||
|
@ -157,7 +157,7 @@ StScrollBar StButton#vhandle:active {
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.popup-submenu-menu-item-triangle {
|
||||
.unicode-arrow {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
@ -306,16 +306,13 @@ StScrollBar StButton#vhandle:active {
|
||||
font-size: 12pt;
|
||||
border-bottom: 1px solid #666;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.nm-dialog-item:checked {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.nm-dialog-item-box {
|
||||
spacing: 20px;
|
||||
}
|
||||
|
||||
.nm-dialog-item:selected {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.nm-dialog-icons {
|
||||
spacing: .5em;
|
||||
}
|
||||
@ -642,7 +639,7 @@ StScrollBar StButton#vhandle:active {
|
||||
}
|
||||
|
||||
.aggregate-menu {
|
||||
width: 340px;
|
||||
width: 360px;
|
||||
}
|
||||
|
||||
.aggregate-menu .popup-menu-icon {
|
||||
@ -693,7 +690,9 @@ StScrollBar StButton#vhandle:active {
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
.workspace-thumbnails-background {
|
||||
.workspace-thumbnails {
|
||||
spacing: 11px;
|
||||
visible-width: 32px; /* Amount visible before hovering */
|
||||
border: 1px solid rgba(128, 128, 128, 0.4);
|
||||
border-right: 0px;
|
||||
border-radius: 9px 0px 0px 9px;
|
||||
@ -701,18 +700,13 @@ StScrollBar StButton#vhandle:active {
|
||||
padding: 11px 7px 11px 11px;
|
||||
}
|
||||
|
||||
.workspace-thumbnails-background:rtl {
|
||||
.workspace-thumbnails:rtl {
|
||||
border-right: 1px;
|
||||
border-left: 0px;
|
||||
border-radius: 0px 9px 9px 0px;
|
||||
padding: 11px 11px 11px 7px;
|
||||
}
|
||||
|
||||
.workspace-thumbnails {
|
||||
spacing: 11px;
|
||||
visible-width: 32px; /* Amount visible before hovering */
|
||||
}
|
||||
|
||||
.workspace-thumbnail-indicator {
|
||||
border: 4px solid rgba(255,255,255,0.7);
|
||||
border-radius: 4px;
|
||||
@ -918,7 +912,6 @@ StScrollBar StButton#vhandle:active {
|
||||
}
|
||||
|
||||
.app-display {
|
||||
padding: 8px;
|
||||
spacing: 20px;
|
||||
}
|
||||
|
||||
@ -942,7 +935,7 @@ StScrollBar StButton#vhandle:active {
|
||||
}
|
||||
|
||||
.page-indicator {
|
||||
padding: 15px 30px;
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.page-indicator .page-indicator-icon {
|
||||
@ -951,11 +944,19 @@ StScrollBar StButton#vhandle:active {
|
||||
background-image: url(page-indicator-inactive.svg);
|
||||
}
|
||||
|
||||
.page-indicator:hover .page-indicator-icon,
|
||||
.page-indicator:checked .page-indicator-icon {
|
||||
.page-indicator:hover .page-indicator-icon {
|
||||
background-image: url(page-indicator-hover.svg);
|
||||
}
|
||||
|
||||
.page-indicator:active .page-indicator-icon {
|
||||
background-image: url(page-indicator-active.svg);
|
||||
}
|
||||
|
||||
.page-indicator:checked .page-indicator-icon,
|
||||
.page-indicator:checked:active .page-indicator-icon {
|
||||
background-image: url(page-indicator-checked.svg);
|
||||
}
|
||||
|
||||
.no-frequent-applications-label {
|
||||
font-size: 18pt;
|
||||
color: #999999;
|
||||
@ -1966,6 +1967,11 @@ StScrollBar StButton#vhandle:active {
|
||||
padding-left: 50px;
|
||||
}
|
||||
|
||||
.end-session-dialog-session-list,
|
||||
.end-session-dialog-app-list {
|
||||
spacing: 1em;
|
||||
}
|
||||
|
||||
.end-session-dialog-list-header {
|
||||
font-weight: bold;
|
||||
}
|
||||
@ -2269,7 +2275,7 @@ StScrollBar StButton#vhandle:active {
|
||||
|
||||
.framed-user-icon {
|
||||
border: 2px solid #8b8b8b;
|
||||
border-radius: 5px;
|
||||
border-radius: 3px;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
@ -2313,7 +2319,7 @@ StScrollBar StButton#vhandle:active {
|
||||
}
|
||||
|
||||
.login-dialog-user-list-item {
|
||||
border-radius: 10px;
|
||||
border-radius: 5px;
|
||||
padding: .2em;
|
||||
}
|
||||
|
||||
@ -2326,19 +2332,20 @@ StScrollBar StButton#vhandle:active {
|
||||
}
|
||||
|
||||
.login-dialog-user-list-item .login-dialog-user-list-item-name {
|
||||
font-size: 20pt;
|
||||
padding-left: 9px;
|
||||
font-size: 20px;
|
||||
padding-left: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.login-dialog-user-list:expanded .login-dialog-user-list-item {
|
||||
color: #666666;
|
||||
color: #bfbfbf;
|
||||
}
|
||||
|
||||
.login-dialog-user-list-item,
|
||||
.login-dialog-user-list-item:hover .login-dialog-user-list-item-name,
|
||||
.login-dialog-user-list:expanded .login-dialog-user-list-item:focus .login-dialog-user-list-item-name,
|
||||
.login-dialog-user-list:expanded .login-dialog-user-list-item:logged-in {
|
||||
color: white;
|
||||
color: #bfbfbf;
|
||||
text-shadow: black 0px 2px 2px;
|
||||
}
|
||||
|
||||
@ -2370,7 +2377,7 @@ StScrollBar StButton#vhandle:active {
|
||||
|
||||
.login-dialog-user-list-item-icon {
|
||||
border: 2px solid #8b8b8b;
|
||||
border-radius: 8px;
|
||||
border-radius: 3px;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
@ -2382,6 +2389,10 @@ StScrollBar StButton#vhandle:active {
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
.login-dialog-user-selection-box {
|
||||
padding: 100px 0;
|
||||
}
|
||||
|
||||
.login-dialog-user-selection-box .login-dialog-not-listed-label {
|
||||
padding-left: 2px;
|
||||
}
|
||||
@ -2487,10 +2498,11 @@ StScrollBar StButton#vhandle:active {
|
||||
}
|
||||
|
||||
.user-widget-label {
|
||||
font-size: 16pt;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
padding-left: 15px;
|
||||
padding-left: 18px;
|
||||
color:white;
|
||||
text-shadow: black 0px 4px 3px 0px;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
id="svg4703"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="page-indicator-active.svg">
|
||||
sodipodi:docname="page-indicator-pushed.svg">
|
||||
<defs
|
||||
id="defs4705" />
|
||||
<sodipodi:namedview
|
||||
@ -24,18 +24,22 @@
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="22.197802"
|
||||
inkscape:cx="2.1522887"
|
||||
inkscape:cy="16.782904"
|
||||
inkscape:zoom="31.392433"
|
||||
inkscape:cx="1.0245308"
|
||||
inkscape:cy="13.3715"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1021"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1374"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1" />
|
||||
inkscape:window-maximized="1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid6140" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata4708">
|
||||
<rdf:RDF>
|
||||
@ -44,7 +48,7 @@
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
@ -54,14 +58,14 @@
|
||||
inkscape:groupmode="layer"
|
||||
transform="translate(0,2)">
|
||||
<path
|
||||
transform="matrix(0.72823872,0,0,0.8336417,-1512.2872,-525.55618)"
|
||||
d="m 2099.9808,638.83099 c 0,5.29998 -4.9184,9.59645 -10.9854,9.59645 -6.0671,0 -10.9854,-4.29647 -10.9854,-9.59645 0,-5.29997 4.9183,-9.59645 10.9854,-9.59645 6.067,0 10.9854,4.29648 10.9854,9.59645 z"
|
||||
transform="matrix(0.54617904,0,0,0.62523128,-1131.9904,-392.39214)"
|
||||
d="m 2099.9808,638.83099 a 10.985409,9.5964489 0 1 1 -21.9708,0 10.985409,9.5964489 0 1 1 21.9708,0 z"
|
||||
sodipodi:ry="9.5964489"
|
||||
sodipodi:rx="10.985409"
|
||||
sodipodi:cy="638.83099"
|
||||
sodipodi:cx="2088.9954"
|
||||
id="path4711"
|
||||
style="fill:#fdffff;fill-opacity:0.94117647;stroke:none"
|
||||
style="fill:#fdffff;fill-opacity:1;stroke:none"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
67
data/theme/page-indicator-checked.svg
Normal file
@ -0,0 +1,67 @@
|
||||
<?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="18"
|
||||
height="18"
|
||||
id="svg4703"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="page-indicator-active.svg">
|
||||
<defs
|
||||
id="defs4705" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="22.197802"
|
||||
inkscape:cx="2.1522887"
|
||||
inkscape:cy="16.782904"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1021"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata4708">
|
||||
<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,2)">
|
||||
<path
|
||||
transform="matrix(0.72823872,0,0,0.8336417,-1512.2872,-525.55618)"
|
||||
d="m 2099.9808,638.83099 c 0,5.29998 -4.9184,9.59645 -10.9854,9.59645 -6.0671,0 -10.9854,-4.29647 -10.9854,-9.59645 0,-5.29997 4.9183,-9.59645 10.9854,-9.59645 6.067,0 10.9854,4.29648 10.9854,9.59645 z"
|
||||
sodipodi:ry="9.5964489"
|
||||
sodipodi:rx="10.985409"
|
||||
sodipodi:cy="638.83099"
|
||||
sodipodi:cx="2088.9954"
|
||||
id="path4711"
|
||||
style="fill:#fdffff;fill-opacity:0.94117647;stroke:none"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
67
data/theme/page-indicator-hover.svg
Normal file
@ -0,0 +1,67 @@
|
||||
<?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="18"
|
||||
height="18"
|
||||
id="svg5266"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="page-indicator-inactive.svg">
|
||||
<defs
|
||||
id="defs5268" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.313709"
|
||||
inkscape:cx="-2.307566"
|
||||
inkscape:cy="17.859535"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1374"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5271">
|
||||
<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,2)">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;fill-opacity:0;stroke:#ffffff;stroke-width:2.93356276000000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path5274"
|
||||
sodipodi:cx="2088.9954"
|
||||
sodipodi:cy="638.83099"
|
||||
sodipodi:rx="10.985409"
|
||||
sodipodi:ry="9.5964489"
|
||||
d="m 2099.9808,638.83099 c 0,5.29998 -4.9184,9.59645 -10.9854,9.59645 -6.0671,0 -10.9854,-4.29647 -10.9854,-9.59645 0,-5.29997 4.9183,-9.59645 10.9854,-9.59645 6.067,0 10.9854,4.29648 10.9854,9.59645 z"
|
||||
transform="matrix(0.63720887,0,0,0.72943648,-1322.1264,-458.98661)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
@ -25,14 +25,14 @@
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.313709"
|
||||
inkscape:cx="13.381365"
|
||||
inkscape:cx="-2.307566"
|
||||
inkscape:cy="17.859535"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1021"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1374"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1" />
|
||||
@ -55,7 +55,7 @@
|
||||
transform="translate(0,2)">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#ffffff;fill-opacity:0;stroke:#ffffff;stroke-width:2.93356276;stroke-miterlimit:4;stroke-opacity:0.39215686;stroke-dasharray:none"
|
||||
style="fill:none;fill-opacity:0;stroke:#ffffff;stroke-width:2.93356276000000005;stroke-miterlimit:4;stroke-opacity:0.39215686000000000;stroke-dasharray:none"
|
||||
id="path5274"
|
||||
sodipodi:cx="2088.9954"
|
||||
sodipodi:cy="638.83099"
|
||||
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
BIN
data/wanda.png
Before Width: | Height: | Size: 13 KiB |
@ -21,6 +21,7 @@ nobase_dist_js_DATA = \
|
||||
gdm/batch.js \
|
||||
gdm/fingerprint.js \
|
||||
gdm/loginDialog.js \
|
||||
gdm/oVirt.js \
|
||||
gdm/realmd.js \
|
||||
gdm/util.js \
|
||||
extensionPrefs/main.js \
|
||||
@ -89,7 +90,6 @@ nobase_dist_js_DATA = \
|
||||
ui/screenShield.js \
|
||||
ui/scripting.js \
|
||||
ui/search.js \
|
||||
ui/searchDisplay.js \
|
||||
ui/shellDBus.js \
|
||||
ui/status/accessibility.js \
|
||||
ui/status/brightness.js \
|
||||
@ -106,7 +106,6 @@ nobase_dist_js_DATA = \
|
||||
ui/unlockDialog.js \
|
||||
ui/userWidget.js \
|
||||
ui/viewSelector.js \
|
||||
ui/wanda.js \
|
||||
ui/windowAttentionHandler.js \
|
||||
ui/windowManager.js \
|
||||
ui/workspace.js \
|
||||
|
@ -13,13 +13,15 @@ const _ = Gettext.gettext;
|
||||
const Config = imports.misc.config;
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
|
||||
const GnomeShellIface = <interface name="org.gnome.Shell.Extensions">
|
||||
<signal name="ExtensionStatusChanged">
|
||||
<arg type="s" name="uuid"/>
|
||||
<arg type="i" name="state"/>
|
||||
<arg type="s" name="error"/>
|
||||
</signal>
|
||||
</interface>;
|
||||
const GnomeShellIface = '<node> \
|
||||
<interface name="org.gnome.Shell.Extensions"> \
|
||||
<signal name="ExtensionStatusChanged"> \
|
||||
<arg type="s" name="uuid"/> \
|
||||
<arg type="i" name="state"/> \
|
||||
<arg type="s" name="error"/> \
|
||||
</signal> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
|
||||
|
||||
|
@ -59,6 +59,7 @@ const AuthPrompt = new Lang.Class({
|
||||
this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete));
|
||||
this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
|
||||
this._userVerifier.connect('smartcard-status-changed', Lang.bind(this, this._onSmartcardStatusChanged));
|
||||
this._userVerifier.connect('ovirt-user-authenticated', Lang.bind(this, this._onOVirtUserAuthenticated));
|
||||
this.smartcardDetected = this._userVerifier.smartcardDetected;
|
||||
|
||||
this.connect('next', Lang.bind(this, function() {
|
||||
@ -219,6 +220,11 @@ const AuthPrompt = new Lang.Class({
|
||||
this.emit('prompted');
|
||||
},
|
||||
|
||||
_onOVirtUserAuthenticated: function() {
|
||||
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
|
||||
this.reset();
|
||||
},
|
||||
|
||||
_onSmartcardStatusChanged: function() {
|
||||
this.smartcardDetected = this._userVerifier.smartcardDetected;
|
||||
|
||||
@ -244,6 +250,7 @@ const AuthPrompt = new Lang.Class({
|
||||
},
|
||||
|
||||
_onVerificationFailed: function() {
|
||||
this._queryingService = null;
|
||||
this.clear();
|
||||
|
||||
this.updateSensitivity(true);
|
||||
@ -443,10 +450,11 @@ const AuthPrompt = new Lang.Class({
|
||||
// The user is constant at the unlock screen, so it will immediately
|
||||
// respond to the request with the username
|
||||
beginRequestType = BeginRequestType.PROVIDE_USERNAME;
|
||||
} else if (this.smartcardDetected &&
|
||||
this._userVerifier.serviceIsForeground(GdmUtil.SMARTCARD_SERVICE_NAME)) {
|
||||
} else if (this._userVerifier.serviceIsForeground(GdmUtil.OVIRT_SERVICE_NAME) ||
|
||||
(this.smartcardDetected &&
|
||||
this._userVerifier.serviceIsForeground(GdmUtil.SMARTCARD_SERVICE_NAME))) {
|
||||
// We don't need to know the username if the user preempted the login screen
|
||||
// with a smartcard.
|
||||
// with a smartcard or with preauthenticated oVirt credentials
|
||||
beginRequestType = BeginRequestType.DONT_PROVIDE_USERNAME;
|
||||
} else {
|
||||
// In all other cases, we should get the username up front.
|
||||
|
@ -5,11 +5,13 @@ const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const FprintManagerIface = <interface name='net.reactivated.Fprint.Manager'>
|
||||
<method name='GetDefaultDevice'>
|
||||
<arg type='o' direction='out' />
|
||||
</method>
|
||||
</interface>;
|
||||
const FprintManagerIface = '<node> \
|
||||
<interface name="net.reactivated.Fprint.Manager"> \
|
||||
<method name="GetDefaultDevice"> \
|
||||
<arg type="o" direction="out" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const FprintManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(FprintManagerIface);
|
||||
|
||||
|
@ -619,7 +619,7 @@ const LoginDialog = new Lang.Class({
|
||||
|
||||
// Translators: this message is shown below the username entry field
|
||||
// to clue the user in on how to login to the local network realm
|
||||
this._authPrompt.setMessage(_("(e.g., user or %s)").format(hint), AuthPrompt.MessageType.HINT);
|
||||
this._authPrompt.setMessage(_("(e.g., user or %s)").format(hint), GdmUtil.MessageType.HINT);
|
||||
},
|
||||
|
||||
_askForUsernameAndBeginVerification: function() {
|
||||
|
64
js/gdm/oVirt.js
Normal file
@ -0,0 +1,64 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const OVirtCredentialsIface = '<node> \
|
||||
<interface name="org.ovirt.vdsm.Credentials"> \
|
||||
<signal name="UserAuthenticated"> \
|
||||
<arg type="s" name="token"/> \
|
||||
</signal> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const OVirtCredentialsInfo = Gio.DBusInterfaceInfo.new_for_xml(OVirtCredentialsIface);
|
||||
|
||||
let _oVirtCredentialsManager = null;
|
||||
|
||||
function OVirtCredentials() {
|
||||
var self = new Gio.DBusProxy({ g_connection: Gio.DBus.system,
|
||||
g_interface_name: OVirtCredentialsInfo.name,
|
||||
g_interface_info: OVirtCredentialsInfo,
|
||||
g_name: 'org.ovirt.vdsm.Credentials',
|
||||
g_object_path: '/org/ovirt/vdsm/Credentials',
|
||||
g_flags: (Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
|
||||
self.init(null);
|
||||
return self;
|
||||
}
|
||||
|
||||
const OVirtCredentialsManager = new Lang.Class({
|
||||
Name: 'OVirtCredentialsManager',
|
||||
_init: function() {
|
||||
this._token = null;
|
||||
|
||||
this._credentials = new OVirtCredentials();
|
||||
this._credentials.connectSignal('UserAuthenticated',
|
||||
Lang.bind(this, this._onUserAuthenticated));
|
||||
},
|
||||
|
||||
_onUserAuthenticated: function(proxy, sender, [token]) {
|
||||
this._token = token;
|
||||
this.emit('user-authenticated', token);
|
||||
},
|
||||
|
||||
hasToken: function() {
|
||||
return this._token != null;
|
||||
},
|
||||
|
||||
getToken: function() {
|
||||
return this._token;
|
||||
},
|
||||
|
||||
resetToken: function() {
|
||||
this._token = null;
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(OVirtCredentialsManager.prototype);
|
||||
|
||||
function getOVirtCredentialsManager() {
|
||||
if (!_oVirtCredentialsManager)
|
||||
_oVirtCredentialsManager = new OVirtCredentialsManager();
|
||||
|
||||
return _oVirtCredentialsManager;
|
||||
}
|
@ -5,52 +5,58 @@ const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const ProviderIface = <interface name='org.freedesktop.realmd.Provider'>
|
||||
<property name="Name" type="s" access="read"/>
|
||||
<property name="Version" type="s" access="read"/>
|
||||
<property name="Realms" type="ao" access="read"/>
|
||||
<method name="Discover">
|
||||
<arg name="string" type="s" direction="in"/>
|
||||
<arg name="options" type="a{sv}" direction="in"/>
|
||||
<arg name="relevance" type="i" direction="out"/>
|
||||
<arg name="realm" type="ao" direction="out"/>
|
||||
</method>
|
||||
</interface>;
|
||||
const ProviderIface = '<node> \
|
||||
<interface name="org.freedesktop.realmd.Provider"> \
|
||||
<property name="Name" type="s" access="read"/> \
|
||||
<property name="Version" type="s" access="read"/> \
|
||||
<property name="Realms" type="ao" access="read"/> \
|
||||
<method name="Discover"> \
|
||||
<arg name="string" type="s" direction="in"/> \
|
||||
<arg name="options" type="a{sv}" direction="in"/> \
|
||||
<arg name="relevance" type="i" direction="out"/> \
|
||||
<arg name="realm" type="ao" direction="out"/> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
const Provider = Gio.DBusProxy.makeProxyWrapper(ProviderIface);
|
||||
|
||||
const ServiceIface = <interface name="org.freedesktop.realmd.Service">
|
||||
<method name="Cancel">
|
||||
<arg name="operation" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="Release" />
|
||||
<method name="SetLocale">
|
||||
<arg name="locale" type="s" direction="in"/>
|
||||
</method>
|
||||
<signal name="Diagnostics">
|
||||
<arg name="data" type="s"/>
|
||||
<arg name="operation" type="s"/>
|
||||
</signal>
|
||||
</interface>;
|
||||
const ServiceIface = '<node> \
|
||||
<interface name="org.freedesktop.realmd.Service"> \
|
||||
<method name="Cancel"> \
|
||||
<arg name="operation" type="s" direction="in"/> \
|
||||
</method> \
|
||||
<method name="Release" /> \
|
||||
<method name="SetLocale"> \
|
||||
<arg name="locale" type="s" direction="in"/> \
|
||||
</method> \
|
||||
<signal name="Diagnostics"> \
|
||||
<arg name="data" type="s"/> \
|
||||
<arg name="operation" type="s"/> \
|
||||
</signal> \
|
||||
</interface> \
|
||||
</node>';
|
||||
const Service = Gio.DBusProxy.makeProxyWrapper(ServiceIface);
|
||||
|
||||
const RealmIface = <interface name="org.freedesktop.realmd.Realm">
|
||||
<property name="Name" type="s" access="read"/>
|
||||
<property name="Configured" type="s" access="read"/>
|
||||
<property name="Details" type="a(ss)" access="read"/>
|
||||
<property name="LoginFormats" type="as" access="read"/>
|
||||
<property name="LoginPolicy" type="s" access="read"/>
|
||||
<property name="PermittedLogins" type="as" access="read"/>
|
||||
<property name="SupportedInterfaces" type="as" access="read"/>
|
||||
<method name="ChangeLoginPolicy">
|
||||
<arg name="login_policy" type="s" direction="in"/>
|
||||
<arg name="permitted_add" type="as" direction="in"/>
|
||||
<arg name="permitted_remove" type="as" direction="in"/>
|
||||
<arg name="options" type="a{sv}" direction="in"/>
|
||||
</method>
|
||||
<method name="Deconfigure">
|
||||
<arg name="options" type="a{sv}" direction="in"/>
|
||||
</method>
|
||||
</interface>;
|
||||
const RealmIface = '<node> \
|
||||
<interface name="org.freedesktop.realmd.Realm"> \
|
||||
<property name="Name" type="s" access="read"/> \
|
||||
<property name="Configured" type="s" access="read"/> \
|
||||
<property name="Details" type="a(ss)" access="read"/> \
|
||||
<property name="LoginFormats" type="as" access="read"/> \
|
||||
<property name="LoginPolicy" type="s" access="read"/> \
|
||||
<property name="PermittedLogins" type="as" access="read"/> \
|
||||
<property name="SupportedInterfaces" type="as" access="read"/> \
|
||||
<method name="ChangeLoginPolicy"> \
|
||||
<arg name="login_policy" type="s" direction="in"/> \
|
||||
<arg name="permitted_add" type="as" direction="in"/> \
|
||||
<arg name="permitted_remove" type="as" direction="in"/> \
|
||||
<arg name="options" type="a{sv}" direction="in"/> \
|
||||
</method> \
|
||||
<method name="Deconfigure"> \
|
||||
<arg name="options" type="a{sv}" direction="in"/> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
|
||||
|
||||
const Manager = new Lang.Class({
|
||||
|
@ -10,6 +10,7 @@ const St = imports.gi.St;
|
||||
|
||||
const Batch = imports.gdm.batch;
|
||||
const Fprint = imports.gdm.fingerprint;
|
||||
const OVirt = imports.gdm.oVirt;
|
||||
const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
@ -19,6 +20,7 @@ const Tweener = imports.ui.tweener;
|
||||
const PASSWORD_SERVICE_NAME = 'gdm-password';
|
||||
const FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
|
||||
const SMARTCARD_SERVICE_NAME = 'gdm-smartcard';
|
||||
const OVIRT_SERVICE_NAME = 'gdm-ovirtcred';
|
||||
const FADE_ANIMATION_TIME = 0.16;
|
||||
const CLONE_FADE_ANIMATION_TIME = 0.25;
|
||||
|
||||
@ -151,6 +153,14 @@ const ShellUserVerifier = new Lang.Class({
|
||||
this.reauthenticating = false;
|
||||
|
||||
this._failCounter = 0;
|
||||
|
||||
this._oVirtCredentialsManager = OVirt.getOVirtCredentialsManager();
|
||||
|
||||
if (this._oVirtCredentialsManager.hasToken())
|
||||
this._oVirtUserAuthenticated(this._oVirtCredentialsManager.getToken());
|
||||
|
||||
this._oVirtCredentialsManager.connect('user-authenticated',
|
||||
Lang.bind(this, this._oVirtUserAuthenticated));
|
||||
},
|
||||
|
||||
begin: function(userName, hold) {
|
||||
@ -277,6 +287,11 @@ const ShellUserVerifier = new Lang.Class({
|
||||
}));
|
||||
},
|
||||
|
||||
_oVirtUserAuthenticated: function(token) {
|
||||
this._preemptingService = OVIRT_SERVICE_NAME;
|
||||
this.emit('ovirt-user-authenticated');
|
||||
},
|
||||
|
||||
_checkForSmartcard: function() {
|
||||
let smartcardDetected;
|
||||
|
||||
@ -455,6 +470,12 @@ const ShellUserVerifier = new Lang.Class({
|
||||
if (!this.serviceIsForeground(serviceName))
|
||||
return;
|
||||
|
||||
if (serviceName == OVIRT_SERVICE_NAME) {
|
||||
// The only question asked by this service is "Token?"
|
||||
this.answerQuery(serviceName, this._oVirtCredentialsManager.getToken());
|
||||
return;
|
||||
}
|
||||
|
||||
this.emit('ask-question', serviceName, secretQuestion, '\u25cf');
|
||||
},
|
||||
|
||||
@ -515,6 +536,16 @@ const ShellUserVerifier = new Lang.Class({
|
||||
},
|
||||
|
||||
_onConversationStopped: function(client, serviceName) {
|
||||
// If the login failed with the preauthenticated oVirt credentials
|
||||
// then discard the credentials and revert to default authentication
|
||||
// mechanism.
|
||||
if (this.serviceIsForeground(OVIRT_SERVICE_NAME)) {
|
||||
this._oVirtCredentialsManager.resetToken();
|
||||
this._preemptingService = null;
|
||||
this._verificationFailed(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// if the password service fails, then cancel everything.
|
||||
// But if, e.g., fingerprint fails, still give
|
||||
// password authentication a chance to succeed
|
||||
|
@ -4,15 +4,17 @@ const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const PresenceIface = <interface name="org.gnome.SessionManager.Presence">
|
||||
<method name="SetStatus">
|
||||
<arg type="u" direction="in"/>
|
||||
</method>
|
||||
<property name="status" type="u" access="readwrite"/>
|
||||
<signal name="StatusChanged">
|
||||
<arg type="u" direction="out"/>
|
||||
</signal>
|
||||
</interface>;
|
||||
const PresenceIface = '<node> \
|
||||
<interface name="org.gnome.SessionManager.Presence"> \
|
||||
<method name="SetStatus"> \
|
||||
<arg type="u" direction="in"/> \
|
||||
</method> \
|
||||
<property name="status" type="u" access="readwrite"/> \
|
||||
<signal name="StatusChanged"> \
|
||||
<arg type="u" direction="out"/> \
|
||||
</signal> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const PresenceStatus = {
|
||||
AVAILABLE: 0,
|
||||
@ -30,14 +32,16 @@ function Presence(initCallback, cancellable) {
|
||||
// Note inhibitors are immutable objects, so they don't
|
||||
// change at runtime (changes always come in the form
|
||||
// of new inhibitors)
|
||||
const InhibitorIface = <interface name="org.gnome.SessionManager.Inhibitor">
|
||||
<method name="GetAppId">
|
||||
<arg type="s" direction="out" />
|
||||
</method>
|
||||
<method name="GetReason">
|
||||
<arg type="s" direction="out" />
|
||||
</method>
|
||||
</interface>;
|
||||
const InhibitorIface = '<node> \
|
||||
<interface name="org.gnome.SessionManager.Inhibitor"> \
|
||||
<method name="GetAppId"> \
|
||||
<arg type="s" direction="out" /> \
|
||||
</method> \
|
||||
<method name="GetReason"> \
|
||||
<arg type="s" direction="out" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
var InhibitorProxy = Gio.DBusProxy.makeProxyWrapper(InhibitorIface);
|
||||
function Inhibitor(objectPath, initCallback, cancellable) {
|
||||
@ -45,27 +49,29 @@ function Inhibitor(objectPath, initCallback, cancellable) {
|
||||
}
|
||||
|
||||
// Not the full interface, only the methods we use
|
||||
const SessionManagerIface = <interface name="org.gnome.SessionManager">
|
||||
<method name="Logout">
|
||||
<arg type="u" direction="in" />
|
||||
</method>
|
||||
<method name="Shutdown" />
|
||||
<method name="Reboot" />
|
||||
<method name="CanShutdown">
|
||||
<arg type="b" direction="out" />
|
||||
</method>
|
||||
<method name="IsInhibited">
|
||||
<arg type="u" direction="in" />
|
||||
<arg type="b" direction="out" />
|
||||
</method>
|
||||
<property name="SessionIsActive" type="b" access="read"/>
|
||||
<signal name="InhibitorAdded">
|
||||
<arg type="o" direction="out"/>
|
||||
</signal>
|
||||
<signal name="InhibitorRemoved">
|
||||
<arg type="o" direction="out"/>
|
||||
</signal>
|
||||
</interface>;
|
||||
const SessionManagerIface = '<node> \
|
||||
<interface name="org.gnome.SessionManager"> \
|
||||
<method name="Logout"> \
|
||||
<arg type="u" direction="in" /> \
|
||||
</method> \
|
||||
<method name="Shutdown" /> \
|
||||
<method name="Reboot" /> \
|
||||
<method name="CanShutdown"> \
|
||||
<arg type="b" direction="out" /> \
|
||||
</method> \
|
||||
<method name="IsInhibited"> \
|
||||
<arg type="u" direction="in" /> \
|
||||
<arg type="b" direction="out" /> \
|
||||
</method> \
|
||||
<property name="SessionIsActive" type="b" access="read"/> \
|
||||
<signal name="InhibitorAdded"> \
|
||||
<arg type="o" direction="out"/> \
|
||||
</signal> \
|
||||
<signal name="InhibitorRemoved"> \
|
||||
<arg type="o" direction="out"/> \
|
||||
</signal> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface);
|
||||
function SessionManager(initCallback, cancellable) {
|
||||
|
@ -7,58 +7,66 @@ const Mainloop = imports.mainloop;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const SystemdLoginManagerIface = <interface name='org.freedesktop.login1.Manager'>
|
||||
<method name='Suspend'>
|
||||
<arg type='b' direction='in'/>
|
||||
</method>
|
||||
<method name='CanSuspend'>
|
||||
<arg type='s' direction='out'/>
|
||||
</method>
|
||||
<method name='Inhibit'>
|
||||
<arg type='s' direction='in'/>
|
||||
<arg type='s' direction='in'/>
|
||||
<arg type='s' direction='in'/>
|
||||
<arg type='s' direction='in'/>
|
||||
<arg type='h' direction='out'/>
|
||||
</method>
|
||||
<method name='GetSession'>
|
||||
<arg type='s' direction='in'/>
|
||||
<arg type='o' direction='out'/>
|
||||
</method>
|
||||
<method name='ListSessions'>
|
||||
<arg name='sessions' type='a(susso)' direction='out'/>
|
||||
</method>
|
||||
<signal name='PrepareForSleep'>
|
||||
<arg type='b' direction='out'/>
|
||||
</signal>
|
||||
</interface>;
|
||||
const SystemdLoginManagerIface = '<node> \
|
||||
<interface name="org.freedesktop.login1.Manager"> \
|
||||
<method name="Suspend"> \
|
||||
<arg type="b" direction="in"/> \
|
||||
</method> \
|
||||
<method name="CanSuspend"> \
|
||||
<arg type="s" direction="out"/> \
|
||||
</method> \
|
||||
<method name="Inhibit"> \
|
||||
<arg type="s" direction="in"/> \
|
||||
<arg type="s" direction="in"/> \
|
||||
<arg type="s" direction="in"/> \
|
||||
<arg type="s" direction="in"/> \
|
||||
<arg type="h" direction="out"/> \
|
||||
</method> \
|
||||
<method name="GetSession"> \
|
||||
<arg type="s" direction="in"/> \
|
||||
<arg type="o" direction="out"/> \
|
||||
</method> \
|
||||
<method name="ListSessions"> \
|
||||
<arg name="sessions" type="a(susso)" direction="out"/> \
|
||||
</method> \
|
||||
<signal name="PrepareForSleep"> \
|
||||
<arg type="b" direction="out"/> \
|
||||
</signal> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session'>
|
||||
<signal name='Lock' />
|
||||
<signal name='Unlock' />
|
||||
</interface>;
|
||||
const SystemdLoginSessionIface = '<node> \
|
||||
<interface name="org.freedesktop.login1.Session"> \
|
||||
<signal name="Lock" /> \
|
||||
<signal name="Unlock" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface);
|
||||
const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface);
|
||||
|
||||
const ConsoleKitManagerIface = <interface name='org.freedesktop.ConsoleKit.Manager'>
|
||||
<method name='CanRestart'>
|
||||
<arg type='b' direction='out'/>
|
||||
</method>
|
||||
<method name='CanStop'>
|
||||
<arg type='b' direction='out'/>
|
||||
</method>
|
||||
<method name='Restart' />
|
||||
<method name='Stop' />
|
||||
<method name='GetCurrentSession'>
|
||||
<arg type='o' direction='out' />
|
||||
</method>
|
||||
</interface>;
|
||||
const ConsoleKitManagerIface = '<node> \
|
||||
<interface name="org.freedesktop.ConsoleKit.Manager"> \
|
||||
<method name="CanRestart"> \
|
||||
<arg type="b" direction="out"/> \
|
||||
</method> \
|
||||
<method name="CanStop"> \
|
||||
<arg type="b" direction="out"/> \
|
||||
</method> \
|
||||
<method name="Restart" /> \
|
||||
<method name="Stop" /> \
|
||||
<method name="GetCurrentSession"> \
|
||||
<arg type="o" direction="out" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const ConsoleKitSessionIface = <interface name='org.freedesktop.ConsoleKit.Session'>
|
||||
<signal name='Lock' />
|
||||
<signal name='Unlock' />
|
||||
</interface>;
|
||||
const ConsoleKitSessionIface = '<node> \
|
||||
<interface name="org.freedesktop.ConsoleKit.Session"> \
|
||||
<signal name="Lock" /> \
|
||||
<signal name="Unlock" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const ConsoleKitSession = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
|
||||
const ConsoleKitManager = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface);
|
||||
@ -72,8 +80,10 @@ function versionCompare(required, reference) {
|
||||
reference = reference.split('.');
|
||||
|
||||
for (let i = 0; i < required.length; i++) {
|
||||
if (required[i] != reference[i])
|
||||
return required[i] < reference[i];
|
||||
let requiredInt = parseInt(required[i]);
|
||||
let referenceInt = parseInt(reference[i]);
|
||||
if (requiredInt != referenceInt)
|
||||
return requiredInt < referenceInt;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -92,37 +92,41 @@ function _findProviderForSid(sid) {
|
||||
// The following are not the complete interfaces, just the methods we need
|
||||
// (or may need in the future)
|
||||
|
||||
const ModemGsmNetworkInterface = <interface name="org.freedesktop.ModemManager.Modem.Gsm.Network">
|
||||
<method name="GetRegistrationInfo">
|
||||
<arg type="(uss)" direction="out" />
|
||||
</method>
|
||||
<method name="GetSignalQuality">
|
||||
<arg type="u" direction="out" />
|
||||
</method>
|
||||
<property name="AccessTechnology" type="u" access="read" />
|
||||
<signal name="SignalQuality">
|
||||
<arg type="u" direction="out" />
|
||||
</signal>
|
||||
<signal name="RegistrationInfo">
|
||||
<arg type="u" direction="out" />
|
||||
<arg type="s" direction="out" />
|
||||
<arg type="s" direction="out" />
|
||||
</signal>
|
||||
</interface>;
|
||||
const ModemGsmNetworkInterface = '<node> \
|
||||
<interface name="org.freedesktop.ModemManager.Modem.Gsm.Network"> \
|
||||
<method name="GetRegistrationInfo"> \
|
||||
<arg type="(uss)" direction="out" /> \
|
||||
</method> \
|
||||
<method name="GetSignalQuality"> \
|
||||
<arg type="u" direction="out" /> \
|
||||
</method> \
|
||||
<property name="AccessTechnology" type="u" access="read" /> \
|
||||
<signal name="SignalQuality"> \
|
||||
<arg type="u" direction="out" /> \
|
||||
</signal> \
|
||||
<signal name="RegistrationInfo"> \
|
||||
<arg type="u" direction="out" /> \
|
||||
<arg type="s" direction="out" /> \
|
||||
<arg type="s" direction="out" /> \
|
||||
</signal> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInterface);
|
||||
|
||||
const ModemCdmaInterface = <interface name="org.freedesktop.ModemManager.Modem.Cdma">
|
||||
<method name="GetSignalQuality">
|
||||
<arg type="u" direction="out" />
|
||||
</method>
|
||||
<method name="GetServingSystem">
|
||||
<arg type="(usu)" direction="out" />
|
||||
</method>
|
||||
<signal name="SignalQuality">
|
||||
<arg type="u" direction="out" />
|
||||
</signal>
|
||||
</interface>;
|
||||
const ModemCdmaInterface = '<node> \
|
||||
<interface name="org.freedesktop.ModemManager.Modem.Cdma"> \
|
||||
<method name="GetSignalQuality"> \
|
||||
<arg type="u" direction="out" /> \
|
||||
</method> \
|
||||
<method name="GetServingSystem"> \
|
||||
<arg type="(usu)" direction="out" /> \
|
||||
</method> \
|
||||
<signal name="SignalQuality"> \
|
||||
<arg type="u" direction="out" /> \
|
||||
</signal> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
|
||||
|
||||
@ -218,20 +222,26 @@ Signals.addSignalMethods(ModemCdma.prototype);
|
||||
// Support for the new ModemManager1 interface (MM >= 0.7)
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const BroadbandModemInterface = <interface name="org.freedesktop.ModemManager1.Modem">
|
||||
<property name="SignalQuality" type="(ub)" access="read" />
|
||||
</interface>;
|
||||
const BroadbandModemInterface = '<node> \
|
||||
<interface name="org.freedesktop.ModemManager1.Modem"> \
|
||||
<property name="SignalQuality" type="(ub)" access="read" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface);
|
||||
|
||||
const BroadbandModem3gppInterface = <interface name="org.freedesktop.ModemManager1.Modem.Modem3gpp">
|
||||
<property name="OperatorCode" type="s" access="read" />
|
||||
<property name="OperatorName" type="s" access="read" />
|
||||
</interface>;
|
||||
const BroadbandModem3gppInterface = '<node> \
|
||||
<interface name="org.freedesktop.ModemManager1.Modem.Modem3gpp"> \
|
||||
<property name="OperatorCode" type="s" access="read" /> \
|
||||
<property name="OperatorName" type="s" access="read" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
const BroadbandModem3gppProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModem3gppInterface);
|
||||
|
||||
const BroadbandModemCdmaInterface = <interface name="org.freedesktop.ModemManager1.Modem.ModemCdma">
|
||||
<property name="Sid" type="u" access="read" />
|
||||
</interface>;
|
||||
const BroadbandModemCdmaInterface = '<node> \
|
||||
<interface name="org.freedesktop.ModemManager1.Modem.ModemCdma"> \
|
||||
<property name="Sid" type="u" access="read" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
const BroadbandModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemCdmaInterface);
|
||||
|
||||
const BroadbandModem = new Lang.Class({
|
||||
|
@ -8,19 +8,21 @@ const Signals = imports.signals;
|
||||
|
||||
// Specified in the D-Bus specification here:
|
||||
// http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
|
||||
const ObjectManagerIface = <interface name="org.freedesktop.DBus.ObjectManager">
|
||||
<method name="GetManagedObjects">
|
||||
<arg name="objects" type="a{oa{sa{sv}}}" direction="out"/>
|
||||
</method>
|
||||
<signal name="InterfacesAdded">
|
||||
<arg name="objectPath" type="o"/>
|
||||
<arg name="interfaces" type="a{sa{sv}}" />
|
||||
</signal>
|
||||
<signal name="InterfacesRemoved">
|
||||
<arg name="objectPath" type="o"/>
|
||||
<arg name="interfaces" type="as" />
|
||||
</signal>
|
||||
</interface>;
|
||||
const ObjectManagerIface = '<node> \
|
||||
<interface name="org.freedesktop.DBus.ObjectManager"> \
|
||||
<method name="GetManagedObjects"> \
|
||||
<arg name="objects" type="a{oa{sa{sv}}}" direction="out"/> \
|
||||
</method> \
|
||||
<signal name="InterfacesAdded"> \
|
||||
<arg name="objectPath" type="o"/> \
|
||||
<arg name="interfaces" type="a{sa{sv}}" /> \
|
||||
</signal> \
|
||||
<signal name="InterfacesRemoved"> \
|
||||
<arg name="objectPath" type="o"/> \
|
||||
<arg name="interfaces" type="as" /> \
|
||||
</signal> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface);
|
||||
|
||||
|
@ -7,12 +7,14 @@ const Signals = imports.signals;
|
||||
|
||||
const ObjectManager = imports.misc.objectManager;
|
||||
|
||||
const SmartcardTokenIface = <interface name="org.gnome.SettingsDaemon.Smartcard.Token">
|
||||
<property name="Name" type="s" access="read"/>
|
||||
<property name="Driver" type="o" access="read"/>
|
||||
<property name="IsInserted" type="b" access="read"/>
|
||||
<property name="UsedToLogin" type="b" access="read"/>
|
||||
</interface>;
|
||||
const SmartcardTokenIface = '<node> \
|
||||
<interface name="org.gnome.SettingsDaemon.Smartcard.Token"> \
|
||||
<property name="Name" type="s" access="read"/> \
|
||||
<property name="Driver" type="o" access="read"/> \
|
||||
<property name="IsInserted" type="b" access="read"/> \
|
||||
<property name="UsedToLogin" type="b" access="read"/> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
let _smartcardManager = null;
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
@ -78,6 +80,22 @@ function spawnCommandLine(command_line) {
|
||||
}
|
||||
}
|
||||
|
||||
// spawnApp:
|
||||
// @argv: an argv array
|
||||
//
|
||||
// Runs @argv as if it was an application, handling startup notification
|
||||
function spawnApp(argv) {
|
||||
try {
|
||||
let app = Gio.AppInfo.create_from_commandline(argv.join(' '), null,
|
||||
Gio.AppInfoCreateFlags.SUPPORTS_STARTUP_NOTIFICATION);
|
||||
|
||||
let context = global.create_app_launch_context();
|
||||
app.launch([], context);
|
||||
} catch(err) {
|
||||
_handleSpawnError(argv[0], err);
|
||||
}
|
||||
}
|
||||
|
||||
// trySpawn:
|
||||
// @argv: an argv array
|
||||
//
|
||||
@ -189,28 +207,57 @@ function insertSorted(array, val, cmp) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
function makeCloseButton() {
|
||||
let closeButton = new St.Button({ style_class: 'notification-close'});
|
||||
const CloseButton = new Lang.Class({
|
||||
Name: 'CloseButton',
|
||||
Extends: St.Button,
|
||||
|
||||
// This is a bit tricky. St.Bin has its own x-align/y-align properties
|
||||
// that compete with Clutter's properties. This should be fixed for
|
||||
// Clutter 2.0. Since St.Bin doesn't define its own setters, the
|
||||
// setters are a workaround to get Clutter's version.
|
||||
closeButton.set_x_align(Clutter.ActorAlign.END);
|
||||
closeButton.set_y_align(Clutter.ActorAlign.START);
|
||||
_init: function(boxpointer) {
|
||||
this.parent({ style_class: 'notification-close'});
|
||||
|
||||
// XXX Clutter 2.0 workaround: ClutterBinLayout needs expand
|
||||
// to respect the alignments.
|
||||
closeButton.set_x_expand(true);
|
||||
closeButton.set_y_expand(true);
|
||||
// This is a bit tricky. St.Bin has its own x-align/y-align properties
|
||||
// that compete with Clutter's properties. This should be fixed for
|
||||
// Clutter 2.0. Since St.Bin doesn't define its own setters, the
|
||||
// setters are a workaround to get Clutter's version.
|
||||
this.set_x_align(Clutter.ActorAlign.END);
|
||||
this.set_y_align(Clutter.ActorAlign.START);
|
||||
|
||||
closeButton.connect('style-changed', function() {
|
||||
let themeNode = closeButton.get_theme_node();
|
||||
closeButton.translation_x = themeNode.get_length('-shell-close-overlap-x');
|
||||
closeButton.translation_y = themeNode.get_length('-shell-close-overlap-y');
|
||||
});
|
||||
// XXX Clutter 2.0 workaround: ClutterBinLayout needs expand
|
||||
// to respect the alignments.
|
||||
this.set_x_expand(true);
|
||||
this.set_y_expand(true);
|
||||
|
||||
return closeButton;
|
||||
this._boxPointer = boxpointer;
|
||||
if (boxpointer)
|
||||
this._boxPointer.connect('arrow-side-changed', Lang.bind(this, this._sync));
|
||||
},
|
||||
|
||||
_computeBoxPointerOffset: function() {
|
||||
if (!this._boxPointer || !this._boxPointer.actor.get_stage())
|
||||
return 0;
|
||||
|
||||
let side = this._boxPointer.arrowSide;
|
||||
if (side == St.Side.TOP)
|
||||
return this._boxPointer.getArrowHeight();
|
||||
else
|
||||
return 0;
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
let themeNode = this.get_theme_node();
|
||||
|
||||
let offY = this._computeBoxPointerOffset();
|
||||
this.translation_x = themeNode.get_length('-shell-close-overlap-x')
|
||||
this.translation_y = themeNode.get_length('-shell-close-overlap-y') + offY;
|
||||
},
|
||||
|
||||
vfunc_style_changed: function() {
|
||||
this._sync();
|
||||
this.parent();
|
||||
},
|
||||
});
|
||||
|
||||
function makeCloseButton(boxpointer) {
|
||||
return new CloseButton(boxpointer);
|
||||
}
|
||||
|
||||
function ensureActorVisibleInScrollView(scrollView, actor) {
|
||||
|
@ -106,6 +106,8 @@ const AppSwitcherPopup = new Lang.Class({
|
||||
|
||||
this._switcherList = new AppSwitcher(apps, this);
|
||||
this._items = this._switcherList.icons;
|
||||
if (this._items.length == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
},
|
||||
@ -375,6 +377,9 @@ const WindowSwitcherPopup = new Lang.Class({
|
||||
this._switcherList = new WindowList(windows, mode);
|
||||
this._items = this._switcherList.icons;
|
||||
|
||||
if (this._items.length == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
|
@ -39,12 +39,9 @@ const FOLDER_SUBICON_FRACTION = .4;
|
||||
|
||||
const MIN_FREQUENT_APPS_COUNT = 3;
|
||||
|
||||
const INDICATORS_ANIMATION_TIME = 0.5;
|
||||
// 100% means indicators wait for be animated until the previous one
|
||||
// is animated completely. 0% means all animators are animated
|
||||
// at once without delay
|
||||
const INDICATORS_ANIMATION_DELAY_PERCENTAGE = 50;
|
||||
|
||||
const INDICATORS_BASE_TIME = 0.25;
|
||||
const INDICATORS_ANIMATION_DELAY = 0.125;
|
||||
const INDICATORS_ANIMATION_MAX_TIME = 0.75;
|
||||
// Fraction of page height the finger or mouse must reach
|
||||
// to change page
|
||||
const PAGE_SWITCH_TRESHOLD = 0.2;
|
||||
@ -230,24 +227,23 @@ const PageIndicators = new Lang.Class({
|
||||
if (children.length == 0)
|
||||
return;
|
||||
|
||||
let timePerChild = INDICATORS_ANIMATION_TIME / this._nPages;
|
||||
let delay = INDICATORS_ANIMATION_DELAY_PERCENTAGE / 100 * timePerChild;
|
||||
|
||||
let [stageX, ] = children[0].get_transformed_position();
|
||||
let offset;
|
||||
let monitor = Main.layoutManager.primaryMonitor;
|
||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
||||
offset = monitor.x - stageX - children[0].width;
|
||||
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
|
||||
offset = -children[0].width;
|
||||
else
|
||||
offset = monitor.x + monitor.width - stageX;
|
||||
offset = children[0].width;
|
||||
|
||||
let delay = INDICATORS_ANIMATION_DELAY;
|
||||
let totalAnimationTime = INDICATORS_BASE_TIME + INDICATORS_ANIMATION_DELAY * this._nPages;
|
||||
if (totalAnimationTime > INDICATORS_ANIMATION_MAX_TIME)
|
||||
delay -= (totalAnimationTime - INDICATORS_ANIMATION_MAX_TIME) / this._nPages;
|
||||
|
||||
for (let i = 0; i < this._nPages; i++) {
|
||||
children[i].translation_x = offset;
|
||||
Tweener.addTween(children[i],
|
||||
{ translation_x: 0,
|
||||
time: timePerChild,
|
||||
delay: delay * i,
|
||||
transition: 'easeOutQuad'
|
||||
time: INDICATORS_BASE_TIME + delay * i,
|
||||
transition: 'easeInOutQuad'
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -337,6 +333,19 @@ const AllView = new Lang.Class({
|
||||
function() {
|
||||
this._displayingPopup = false;
|
||||
}));
|
||||
|
||||
this.actor.connect('notify::mapped', Lang.bind(this,
|
||||
function() {
|
||||
if (this.actor.mapped) {
|
||||
this._keyPressEventId =
|
||||
global.stage.connect('key-press-event',
|
||||
Lang.bind(this, this._onKeyPressEvent));
|
||||
} else {
|
||||
if (this._keyPressEventId)
|
||||
global.stage.disconnect(this._keyPressEventId);
|
||||
this._keyPressEventId = 0;
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
getCurrentPageY: function() {
|
||||
@ -344,6 +353,8 @@ const AllView = new Lang.Class({
|
||||
},
|
||||
|
||||
goToPage: function(pageNumber) {
|
||||
if(pageNumber < 0 || pageNumber > this._grid.nPages() - 1)
|
||||
return;
|
||||
if (this._currentPage == pageNumber && this._displayingPopup && this._currentPopup)
|
||||
return;
|
||||
if (this._displayingPopup && this._currentPopup)
|
||||
@ -405,16 +416,13 @@ const AllView = new Lang.Class({
|
||||
_onScroll: function(actor, event) {
|
||||
if (this._displayingPopup)
|
||||
return true;
|
||||
|
||||
let direction = event.get_scroll_direction();
|
||||
if (direction == Clutter.ScrollDirection.UP) {
|
||||
if (this._currentPage > 0)
|
||||
this.goToPage(this._currentPage - 1);
|
||||
} else {
|
||||
if (direction == Clutter.ScrollDirection.DOWN) {
|
||||
if (this._currentPage < (this._grid.nPages() - 1))
|
||||
this.goToPage(this._currentPage + 1);
|
||||
}
|
||||
}
|
||||
if (direction == Clutter.ScrollDirection.UP)
|
||||
this.goToPage(this._currentPage - 1);
|
||||
else if (direction == Clutter.ScrollDirection.DOWN)
|
||||
this.goToPage(this._currentPage + 1);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
@ -434,9 +442,9 @@ const AllView = new Lang.Class({
|
||||
return;
|
||||
let diffCurrentPage = this._diffToPage(this._currentPage);
|
||||
if (diffCurrentPage > this._scrollView.height * PAGE_SWITCH_TRESHOLD) {
|
||||
if (action.get_velocity(0)[2] > 0 && this._currentPage > 0)
|
||||
if (action.get_velocity(0)[2] > 0)
|
||||
this.goToPage(this._currentPage - 1);
|
||||
else if (this._currentPage < this._grid.nPages() - 1)
|
||||
else
|
||||
this.goToPage(this._currentPage + 1);
|
||||
} else {
|
||||
this.goToPage(this._currentPage);
|
||||
@ -444,6 +452,21 @@ const AllView = new Lang.Class({
|
||||
this._panning = false;
|
||||
},
|
||||
|
||||
_onKeyPressEvent: function(actor, event) {
|
||||
if (this._displayingPopup)
|
||||
return true;
|
||||
|
||||
if (event.get_key_symbol() == Clutter.Page_Up) {
|
||||
this.goToPage(this._currentPage - 1);
|
||||
return true;
|
||||
} else if (event.get_key_symbol() == Clutter.Page_Down) {
|
||||
this.goToPage(this._currentPage + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
_getItemId: function(item) {
|
||||
if (item instanceof Shell.App)
|
||||
return item.get_id();
|
||||
@ -721,10 +744,15 @@ const AppDisplay = new Lang.Class({
|
||||
this._views[i].control.connect('clicked', Lang.bind(this,
|
||||
function(actor) {
|
||||
this._showView(viewIndex);
|
||||
global.settings.set_uint('app-picker-view', viewIndex);
|
||||
}));
|
||||
}
|
||||
let initialView = Math.min(global.settings.get_uint('app-picker-view'),
|
||||
this._views.length - 1);
|
||||
let frequentUseful = this._views[Views.FREQUENT].view.hasUsefulData();
|
||||
this._showView(frequentUseful ? Views.FREQUENT : Views.ALL);
|
||||
if (initialView == Views.FREQUENT && !frequentUseful)
|
||||
initialView = Views.ALL;
|
||||
this._showView(initialView);
|
||||
this._updateFrequentVisibility();
|
||||
|
||||
// We need a dummy actor to catch the keyboard focus if the
|
||||
@ -854,6 +882,10 @@ const AppSearchProvider = new Lang.Class({
|
||||
callback(metas);
|
||||
},
|
||||
|
||||
filterResults: function(results, maxNumber) {
|
||||
return results.slice(0, maxNumber);
|
||||
},
|
||||
|
||||
getInitialResultSet: function(terms) {
|
||||
this.searchSystem.setResults(this, this._appSys.initial_search(terms));
|
||||
},
|
||||
@ -1157,7 +1189,7 @@ const AppFolderPopup = new Lang.Class({
|
||||
this.actor.add_actor(this._boxPointer.actor);
|
||||
this._boxPointer.bin.set_child(this._view.actor);
|
||||
|
||||
this.closeButton = Util.makeCloseButton();
|
||||
this.closeButton = Util.makeCloseButton(this._boxPointer);
|
||||
this.closeButton.connect('clicked', Lang.bind(this, this.popdown));
|
||||
this.actor.add_actor(this.closeButton);
|
||||
|
||||
|
@ -315,13 +315,12 @@ const Background = new Lang.Class({
|
||||
|
||||
this._brightness = 1.0;
|
||||
this._vignetteSharpness = 0.2;
|
||||
this._saturation = 1.0;
|
||||
this._cancellable = new Gio.Cancellable();
|
||||
this.isLoaded = false;
|
||||
|
||||
this._settings.connect('changed', Lang.bind(this, function() {
|
||||
this.emit('changed');
|
||||
}));
|
||||
this._settingsChangedSignalId = this._settings.connect('changed', Lang.bind(this, function() {
|
||||
this.emit('changed');
|
||||
}));
|
||||
|
||||
this._load();
|
||||
},
|
||||
@ -362,6 +361,10 @@ const Background = new Lang.Class({
|
||||
|
||||
this.actor.disconnect(this._destroySignalId);
|
||||
this._destroySignalId = 0;
|
||||
|
||||
if (this._settingsChangedSignalId != 0)
|
||||
this._settings.disconnect(this._settingsChangedSignalId);
|
||||
this._settingsChangedSignalId = 0;
|
||||
},
|
||||
|
||||
_setLoaded: function() {
|
||||
@ -412,7 +415,6 @@ const Background = new Lang.Class({
|
||||
},
|
||||
|
||||
_addImage: function(content, index, filename) {
|
||||
content.saturation = this._saturation;
|
||||
content.brightness = this._brightness;
|
||||
content.vignette_sharpness = this._vignetteSharpness;
|
||||
|
||||
@ -428,7 +430,6 @@ const Background = new Lang.Class({
|
||||
},
|
||||
|
||||
_updateImage: function(content, index, filename) {
|
||||
content.saturation = this._saturation;
|
||||
content.brightness = this._brightness;
|
||||
content.vignette_sharpness = this._vignetteSharpness;
|
||||
|
||||
@ -586,24 +587,6 @@ const Background = new Lang.Class({
|
||||
this._loadFile(filename);
|
||||
},
|
||||
|
||||
get saturation() {
|
||||
return this._saturation;
|
||||
},
|
||||
|
||||
set saturation(saturation) {
|
||||
this._saturation = saturation;
|
||||
|
||||
if (this._pattern && this._pattern.content)
|
||||
this._pattern.content.saturation = saturation;
|
||||
|
||||
let keys = Object.keys(this._images);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
let image = this._images[keys[i]];
|
||||
if (image && image.content)
|
||||
image.content.saturation = saturation;
|
||||
}
|
||||
},
|
||||
|
||||
get brightness() {
|
||||
return this._brightness;
|
||||
},
|
||||
@ -747,7 +730,6 @@ const BackgroundManager = new Lang.Class({
|
||||
let newBackground = this._createBackground(monitorIndex);
|
||||
newBackground.vignetteSharpness = background.vignetteSharpness;
|
||||
newBackground.brightness = background.brightness;
|
||||
newBackground.saturation = background.saturation;
|
||||
newBackground.visible = background.visible;
|
||||
|
||||
newBackground.loadedSignalId = newBackground.connect('loaded',
|
||||
|
@ -3,8 +3,9 @@
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
@ -61,6 +62,10 @@ const BoxPointer = new Lang.Class({
|
||||
this._muteInput();
|
||||
},
|
||||
|
||||
get arrowSide() {
|
||||
return this._arrowSide;
|
||||
},
|
||||
|
||||
_muteInput: function() {
|
||||
if (this._capturedEventId == 0)
|
||||
this._capturedEventId = this.actor.connect('captured-event',
|
||||
@ -180,7 +185,9 @@ const BoxPointer = new Lang.Class({
|
||||
},
|
||||
|
||||
_getPreferredHeight: function(actor, forWidth, alloc) {
|
||||
let [minSize, naturalSize] = this.bin.get_preferred_height(forWidth);
|
||||
let themeNode = this.actor.get_theme_node();
|
||||
let borderWidth = themeNode.get_length('-arrow-border-width');
|
||||
let [minSize, naturalSize] = this.bin.get_preferred_height(forWidth - 2 * borderWidth);
|
||||
alloc.min_size = minSize;
|
||||
alloc.natural_size = naturalSize;
|
||||
this._adjustAllocationForArrow(false, alloc);
|
||||
@ -612,6 +619,8 @@ const BoxPointer = new Lang.Class({
|
||||
this._container.queue_relayout();
|
||||
return false;
|
||||
}));
|
||||
|
||||
this.emit('arrow-side-changed');
|
||||
}
|
||||
},
|
||||
|
||||
@ -644,6 +653,8 @@ const BoxPointer = new Lang.Class({
|
||||
updateArrowSide: function(side) {
|
||||
this._arrowSide = side;
|
||||
this._border.queue_repaint();
|
||||
|
||||
this.emit('arrow-side-changed');
|
||||
},
|
||||
|
||||
getPadding: function(side) {
|
||||
@ -654,3 +665,4 @@ const BoxPointer = new Lang.Class({
|
||||
return this.actor.get_theme_node().get_length('-arrow-rise');
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(BoxPointer.prototype);
|
||||
|
@ -190,16 +190,18 @@ const EmptyEventSource = new Lang.Class({
|
||||
});
|
||||
Signals.addSignalMethods(EmptyEventSource.prototype);
|
||||
|
||||
const CalendarServerIface = <interface name="org.gnome.Shell.CalendarServer">
|
||||
<method name="GetEvents">
|
||||
<arg type="x" direction="in" />
|
||||
<arg type="x" direction="in" />
|
||||
<arg type="b" direction="in" />
|
||||
<arg type="a(sssbxxa{sv})" direction="out" />
|
||||
</method>
|
||||
<property name="HasCalendars" type="b" access="read" />
|
||||
<signal name="Changed" />
|
||||
</interface>;
|
||||
const CalendarServerIface = '<node> \
|
||||
<interface name="org.gnome.Shell.CalendarServer"> \
|
||||
<method name="GetEvents"> \
|
||||
<arg type="x" direction="in" /> \
|
||||
<arg type="x" direction="in" /> \
|
||||
<arg type="b" direction="in" /> \
|
||||
<arg type="a(sssbxxa{sv})" direction="out" /> \
|
||||
</method> \
|
||||
<property name="HasCalendars" type="b" access="read" /> \
|
||||
<signal name="Changed" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);
|
||||
|
||||
|
@ -75,12 +75,14 @@ function startAppForMount(app, mount) {
|
||||
|
||||
/******************************************/
|
||||
|
||||
const HotplugSnifferIface = <interface name="org.gnome.Shell.HotplugSniffer">
|
||||
<method name="SniffURI">
|
||||
<arg type="s" direction="in" />
|
||||
<arg type="as" direction="out" />
|
||||
</method>
|
||||
</interface>;
|
||||
const HotplugSnifferIface = '<node> \
|
||||
<interface name="org.gnome.Shell.HotplugSniffer"> \
|
||||
<method name="SniffURI"> \
|
||||
<arg type="s" direction="in" /> \
|
||||
<arg type="as" direction="out" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
|
||||
function HotplugSniffer() {
|
||||
|
@ -13,8 +13,6 @@ const ModalDialog = imports.ui.modalDialog;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
const CheckBox = imports.ui.checkBox;
|
||||
|
||||
let prompter = null;
|
||||
|
||||
const KeyringDialog = new Lang.Class({
|
||||
Name: 'KeyringDialog',
|
||||
Extends: ModalDialog.ModalDialog,
|
||||
@ -80,23 +78,26 @@ const KeyringDialog = new Lang.Class({
|
||||
},
|
||||
|
||||
_buildControlTable: function() {
|
||||
let table = new St.Table({ style_class: 'keyring-dialog-control-table' });
|
||||
let layout = new Clutter.TableLayout();
|
||||
let table = new St.Widget({ style_class: 'keyring-dialog-control-table',
|
||||
layout_manager: layout });
|
||||
layout.hookup_style(table);
|
||||
let row = 0;
|
||||
|
||||
if (this.prompt.password_visible) {
|
||||
let label = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
|
||||
let label = new St.Label({ style_class: 'prompt-dialog-password-label' });
|
||||
label.set_text(_("Password:"));
|
||||
table.add(label, { row: row, col: 0,
|
||||
x_expand: false, x_fill: true,
|
||||
x_align: St.Align.START,
|
||||
y_fill: false, y_align: St.Align.MIDDLE });
|
||||
label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
layout.pack(label, 0, row);
|
||||
layout.child_set(label, { x_expand: false, y_fill: false,
|
||||
x_align: Clutter.TableAlignment.START });
|
||||
this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
|
||||
text: '',
|
||||
can_focus: true});
|
||||
can_focus: true });
|
||||
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
|
||||
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
|
||||
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onPasswordActivate));
|
||||
table.add(this._passwordEntry, { row: row, col: 1, x_expand: true, x_fill: true, x_align: St.Align.START });
|
||||
layout.pack(this._passwordEntry, 1, row);
|
||||
row++;
|
||||
} else {
|
||||
this._passwordEntry = null;
|
||||
@ -105,17 +106,16 @@ const KeyringDialog = new Lang.Class({
|
||||
if (this.prompt.confirm_visible) {
|
||||
var label = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
|
||||
label.set_text(_("Type again:"));
|
||||
table.add(label, { row: row, col: 0,
|
||||
x_expand: false, x_fill: true,
|
||||
x_align: St.Align.START,
|
||||
y_fill: false, y_align: St.Align.MIDDLE });
|
||||
layout.pack(label, 0, row);
|
||||
layout.child_set(label, { x_expand: false, y_fill: false,
|
||||
x_align: Clutter.TableAlignment.START });
|
||||
this._confirmEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
|
||||
text: '',
|
||||
can_focus: true});
|
||||
can_focus: true });
|
||||
this._confirmEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
|
||||
ShellEntry.addContextMenu(this._confirmEntry, { isPassword: true });
|
||||
this._confirmEntry.clutter_text.connect('activate', Lang.bind(this, this._onConfirmActivate));
|
||||
table.add(this._confirmEntry, { row: row, col: 1, x_expand: true, x_fill: true, x_align: St.Align.START });
|
||||
layout.pack(this._confirmEntry, 1, row);
|
||||
row++;
|
||||
} else {
|
||||
this._confirmEntry = null;
|
||||
@ -128,14 +128,14 @@ const KeyringDialog = new Lang.Class({
|
||||
let choice = new CheckBox.CheckBox();
|
||||
this.prompt.bind_property('choice-label', choice.getLabelActor(), 'text', GObject.BindingFlags.SYNC_CREATE);
|
||||
this.prompt.bind_property('choice-chosen', choice.actor, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
|
||||
table.add(choice.actor, { row: row, col: 1, x_expand: false, x_fill: true, x_align: St.Align.START });
|
||||
layout.pack(choice.actor, 1, row);
|
||||
row++;
|
||||
}
|
||||
|
||||
let warning = new St.Label({ style_class: 'prompt-dialog-error-label' });
|
||||
warning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
warning.clutter_text.line_wrap = true;
|
||||
table.add(warning, { row: row, col: 1, x_expand: false, x_fill: false, x_align: St.Align.START });
|
||||
layout.pack(warning, 1, row);
|
||||
this.prompt.bind_property('warning-visible', warning, 'visible', GObject.BindingFlags.SYNC_CREATE);
|
||||
this.prompt.bind_property('warning', warning, 'text', GObject.BindingFlags.SYNC_CREATE);
|
||||
|
||||
@ -221,27 +221,56 @@ const KeyringDialog = new Lang.Class({
|
||||
},
|
||||
});
|
||||
|
||||
const KeyringDummyDialog = new Lang.Class({
|
||||
Name: 'KeyringDummyDialog',
|
||||
|
||||
_init: function() {
|
||||
this.prompt = new Shell.KeyringPrompt();
|
||||
this.prompt.connect('show-password',
|
||||
Lang.bind(this, this._cancelPrompt));
|
||||
this.prompt.connect('show-confirm', Lang.bind(this,
|
||||
this._cancelPrompt));
|
||||
},
|
||||
|
||||
_cancelPrompt: function() {
|
||||
this.prompt.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
const KeyringPrompter = new Lang.Class({
|
||||
Name: 'KeyringPrompter',
|
||||
|
||||
_init: function() {
|
||||
this._prompter = new Gcr.SystemPrompter();
|
||||
this._prompter.connect('new-prompt', function(prompter) {
|
||||
let dialog = new KeyringDialog();
|
||||
return dialog.prompt;
|
||||
});
|
||||
this._prompter.connect('new-prompt', Lang.bind(this,
|
||||
function() {
|
||||
let dialog = this._enabled ? new KeyringDialog()
|
||||
: new KeyringDummyDialog();
|
||||
this._currentPrompt = dialog.prompt;
|
||||
return this._currentPrompt;
|
||||
}));
|
||||
this._dbusId = null;
|
||||
this._registered = false;
|
||||
this._enabled = false;
|
||||
this._currentPrompt = null;
|
||||
},
|
||||
|
||||
enable: function() {
|
||||
this._prompter.register(Gio.DBus.session);
|
||||
this._dbusId = Gio.DBus.session.own_name('org.gnome.keyring.SystemPrompter',
|
||||
Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT, null, null);
|
||||
if (!this._registered) {
|
||||
this._prompter.register(Gio.DBus.session);
|
||||
this._dbusId = Gio.DBus.session.own_name('org.gnome.keyring.SystemPrompter',
|
||||
Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT, null, null);
|
||||
this._registered = true;
|
||||
}
|
||||
this._enabled = true;
|
||||
},
|
||||
|
||||
disable: function() {
|
||||
this._prompter.unregister(false);
|
||||
Gio.DBus.session.unown_name(this._dbusId);
|
||||
this._enabled = false;
|
||||
|
||||
if (this._prompter.prompting)
|
||||
this._currentPrompt.cancel();
|
||||
this._currentPrompt = null;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -72,13 +72,18 @@ const NetworkSecretDialog = new Lang.Class({
|
||||
expand: true });
|
||||
}
|
||||
|
||||
let secretTable = new St.Table({ style_class: 'network-dialog-secret-table' });
|
||||
let layout = new Clutter.TableLayout();
|
||||
let secretTable = new St.Widget({ style_class: 'network-dialog-secret-table',
|
||||
layout_manager: layout });
|
||||
layout.hookup_style(secretTable);
|
||||
|
||||
let initialFocusSet = false;
|
||||
let pos = 0;
|
||||
for (let i = 0; i < this._content.secrets.length; i++) {
|
||||
let secret = this._content.secrets[i];
|
||||
let label = new St.Label({ style_class: 'prompt-dialog-password-label',
|
||||
text: secret.label });
|
||||
label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
|
||||
let reactive = secret.key != null;
|
||||
|
||||
@ -111,11 +116,10 @@ const NetworkSecretDialog = new Lang.Class({
|
||||
} else
|
||||
secret.valid = true;
|
||||
|
||||
secretTable.add(label, { row: pos, col: 0,
|
||||
x_expand: false, x_fill: true,
|
||||
x_align: St.Align.START,
|
||||
y_fill: false, y_align: St.Align.MIDDLE });
|
||||
secretTable.add(secret.entry, { row: pos, col: 1, x_expand: true, x_fill: true, y_align: St.Align.END });
|
||||
layout.pack(label, 0, pos);
|
||||
layout.child_set(label, { x_expand: false, y_fill: false,
|
||||
x_align: Clutter.TableAlignment.START });
|
||||
layout.pack(secret.entry, 1, pos);
|
||||
pos++;
|
||||
|
||||
if (secret.password)
|
||||
|
@ -13,7 +13,6 @@ const Tp = imports.gi.TelepathyGLib;
|
||||
const History = imports.misc.history;
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
const NotificationDaemon = imports.ui.notificationDaemon;
|
||||
const Params = imports.misc.params;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
@ -416,7 +415,7 @@ const TelepathyClient = new Lang.Class({
|
||||
_ensureAppSource: function() {
|
||||
if (this._appSource == null) {
|
||||
this._appSource = new MessageTray.Source(_("Chat"), 'empathy');
|
||||
this._appSource.policy = new NotificationDaemon.NotificationApplicationPolicy('empathy');
|
||||
this._appSource.policy = new MessageTray.NotificationApplicationPolicy('empathy');
|
||||
|
||||
Main.messageTray.add(this._appSource);
|
||||
this._appSource.connect('destroy', Lang.bind(this, function () {
|
||||
@ -447,6 +446,7 @@ const ChatSource = new Lang.Class({
|
||||
this._closedId = this._channel.connect('invalidated', Lang.bind(this, this._channelClosed));
|
||||
|
||||
this._notification = new ChatNotification(this);
|
||||
this._notification.connect('clicked', Lang.bind(this, this.open));
|
||||
this._notification.setUrgency(MessageTray.Urgency.HIGH);
|
||||
this._notifyTimeoutId = 0;
|
||||
|
||||
@ -488,7 +488,7 @@ const ChatSource = new Lang.Class({
|
||||
},
|
||||
|
||||
_createPolicy: function() {
|
||||
return new NotificationDaemon.NotificationApplicationPolicy('empathy');
|
||||
return new MessageTray.NotificationApplicationPolicy('empathy');
|
||||
},
|
||||
|
||||
_updateAlias: function() {
|
||||
@ -545,20 +545,19 @@ const ChatSource = new Lang.Class({
|
||||
this._notification.update(this._notification.title, null, { customContent: true });
|
||||
},
|
||||
|
||||
open: function(notification) {
|
||||
if (this._client.is_handling_channel(this._channel)) {
|
||||
// We are handling the channel, try to pass it to Empathy
|
||||
this._client.delegate_channels_async([this._channel],
|
||||
global.get_current_time(),
|
||||
'org.freedesktop.Telepathy.Client.Empathy.Chat', null);
|
||||
}
|
||||
else {
|
||||
// We are not the handler, just ask to present the channel
|
||||
let dbus = Tp.DBusDaemon.dup();
|
||||
let cd = Tp.ChannelDispatcher.new(dbus);
|
||||
open: function() {
|
||||
if (this._client.is_handling_channel(this._channel)) {
|
||||
// We are handling the channel, try to pass it to Empathy
|
||||
this._client.delegate_channels_async([this._channel],
|
||||
global.get_current_time(),
|
||||
'org.freedesktop.Telepathy.Client.Empathy.Chat', null);
|
||||
} else {
|
||||
// We are not the handler, just ask to present the channel
|
||||
let dbus = Tp.DBusDaemon.dup();
|
||||
let cd = Tp.ChannelDispatcher.new(dbus);
|
||||
|
||||
cd.present_channel_async(this._channel, global.get_current_time(), null);
|
||||
}
|
||||
cd.present_channel_async(this._channel, global.get_current_time(), null);
|
||||
}
|
||||
},
|
||||
|
||||
_getLogMessages: function() {
|
||||
@ -1061,7 +1060,7 @@ const ApproverSource = new Lang.Class({
|
||||
},
|
||||
|
||||
_createPolicy: function() {
|
||||
return new NotificationDaemon.NotificationApplicationPolicy('empathy');
|
||||
return new MessageTray.NotificationApplicationPolicy('empathy');
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
@ -1096,22 +1095,16 @@ const RoomInviteNotification = new Lang.Class({
|
||||
* for example. */
|
||||
this.addBody(_("%s is inviting you to join %s").format(inviter.get_alias(), channel.get_identifier()));
|
||||
|
||||
this.addButton('decline', _("Decline"));
|
||||
this.addButton('accept', _("Accept"));
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
switch (action) {
|
||||
case 'decline':
|
||||
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE,
|
||||
'', function(src, result) {
|
||||
src.leave_channels_finish(result)});
|
||||
break;
|
||||
case 'accept':
|
||||
dispatchOp.handle_with_time_async('', global.get_current_time(),
|
||||
function(src, result) {
|
||||
src.handle_with_time_finish(result)});
|
||||
break;
|
||||
}
|
||||
this.addAction(_("Decline"), Lang.bind(this, function() {
|
||||
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) {
|
||||
src.leave_channels_finish(result);
|
||||
});
|
||||
this.destroy();
|
||||
}));
|
||||
this.addAction(_("Accept"), Lang.bind(this, function() {
|
||||
dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) {
|
||||
src.handle_with_time_finish(result);
|
||||
});
|
||||
this.destroy();
|
||||
}));
|
||||
}
|
||||
@ -1137,23 +1130,17 @@ const AudioVideoNotification = new Lang.Class({
|
||||
|
||||
this.setUrgency(MessageTray.Urgency.CRITICAL);
|
||||
|
||||
this.addButton('reject', _("Decline"));
|
||||
this.addAction(_("Decline"), Lang.bind(this, function() {
|
||||
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) {
|
||||
src.leave_channels_finish(result);
|
||||
});
|
||||
this.destroy();
|
||||
}));
|
||||
/* translators: this is a button label (verb), not a noun */
|
||||
this.addButton('answer', _("Answer"));
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
switch (action) {
|
||||
case 'reject':
|
||||
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE,
|
||||
'', function(src, result) {
|
||||
src.leave_channels_finish(result)});
|
||||
break;
|
||||
case 'answer':
|
||||
dispatchOp.handle_with_time_async('', global.get_current_time(),
|
||||
function(src, result) {
|
||||
src.handle_with_time_finish(result)});
|
||||
break;
|
||||
}
|
||||
this.addAction(_("Answer"), Lang.bind(this, function() {
|
||||
dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) {
|
||||
src.handle_with_time_finish(result);
|
||||
});
|
||||
this.destroy();
|
||||
}));
|
||||
}
|
||||
@ -1177,22 +1164,16 @@ const FileTransferNotification = new Lang.Class({
|
||||
{ customContent: true });
|
||||
this.setResident(true);
|
||||
|
||||
this.addButton('decline', _("Decline"));
|
||||
this.addButton('accept', _("Accept"));
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
switch (action) {
|
||||
case 'decline':
|
||||
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE,
|
||||
'', function(src, result) {
|
||||
src.leave_channels_finish(result)});
|
||||
break;
|
||||
case 'accept':
|
||||
dispatchOp.handle_with_time_async('', global.get_current_time(),
|
||||
function(src, result) {
|
||||
src.handle_with_time_finish(result)});
|
||||
break;
|
||||
}
|
||||
this.addAction(_("Decline"), Lang.bind(this, function() {
|
||||
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) {
|
||||
src.leave_channels_finish(result);
|
||||
});
|
||||
this.destroy();
|
||||
}));
|
||||
this.addAction(_("Accept"), Lang.bind(this, function() {
|
||||
dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) {
|
||||
src.handle_with_time_finish(result);
|
||||
});
|
||||
this.destroy();
|
||||
}));
|
||||
}
|
||||
@ -1240,27 +1221,20 @@ const SubscriptionRequestNotification = new Lang.Class({
|
||||
|
||||
this.addActor(layout);
|
||||
|
||||
this.addButton('decline', _("Decline"));
|
||||
this.addButton('accept', _("Accept"));
|
||||
this.addAction(_("Decline"), Lang.bind(this, function() {
|
||||
contact.remove_async(function(src, result) {
|
||||
src.remove_finish(result);
|
||||
});
|
||||
}));
|
||||
this.addAction(_("Accept"), Lang.bind(this, function() {
|
||||
// Authorize the contact and request to see his status as well
|
||||
contact.authorize_publication_async(function(src, result) {
|
||||
src.authorize_publication_finish(result);
|
||||
});
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
switch (action) {
|
||||
case 'decline':
|
||||
contact.remove_async(function(src, result) {
|
||||
src.remove_finish(result)});
|
||||
break;
|
||||
case 'accept':
|
||||
// Authorize the contact and request to see his status as well
|
||||
contact.authorize_publication_async(function(src, result) {
|
||||
src.authorize_publication_finish(result)});
|
||||
|
||||
contact.request_subscription_async('', function(src, result) {
|
||||
src.request_subscription_finish(result)});
|
||||
break;
|
||||
}
|
||||
|
||||
// rely on _subscriptionStatesChangedCb to destroy the
|
||||
// notification
|
||||
contact.request_subscription_async('', function(src, result) {
|
||||
src.request_subscription_finish(result);
|
||||
});
|
||||
}));
|
||||
|
||||
this._changedId = contact.connect('subscription-states-changed',
|
||||
@ -1359,18 +1333,11 @@ const AccountNotification = new Lang.Class({
|
||||
|
||||
this._account = account;
|
||||
|
||||
this.addButton('view', _("View account"));
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
switch (action) {
|
||||
case 'view':
|
||||
let cmd = 'empathy-accounts --select-account=' +
|
||||
account.get_path_suffix();
|
||||
let app_info = Gio.app_info_create_from_commandline(cmd, null, 0);
|
||||
app_info.launch([], global.create_app_launch_context());
|
||||
break;
|
||||
}
|
||||
this.destroy();
|
||||
this.addAction(_("View account"), Lang.bind(this, function() {
|
||||
let cmd = 'empathy-accounts --select-account=' +
|
||||
account.get_path_suffix();
|
||||
let app_info = Gio.app_info_create_from_commandline(cmd, null, 0);
|
||||
app_info.launch([], global.create_app_launch_context());
|
||||
}));
|
||||
|
||||
this._enabledId = account.connect('notify::enabled',
|
||||
|
60
js/ui/dnd.js
@ -5,6 +5,7 @@ const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const St = imports.gi.St;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const Tweener = imports.ui.tweener;
|
||||
@ -27,9 +28,9 @@ const DragMotionResult = {
|
||||
};
|
||||
|
||||
const DRAG_CURSOR_MAP = {
|
||||
0: Shell.Cursor.DND_UNSUPPORTED_TARGET,
|
||||
1: Shell.Cursor.DND_COPY,
|
||||
2: Shell.Cursor.DND_MOVE
|
||||
0: Meta.Cursor.DND_UNSUPPORTED_TARGET,
|
||||
1: Meta.Cursor.DND_COPY,
|
||||
2: Meta.Cursor.DND_MOVE
|
||||
};
|
||||
|
||||
const DragDropResult = {
|
||||
@ -85,11 +86,6 @@ const _Draggable = new Lang.Class({
|
||||
this.actor.connect('destroy', Lang.bind(this, function() {
|
||||
this._actorDestroyed = true;
|
||||
|
||||
// If the drag actor is destroyed and we were going to fix
|
||||
// up its hover state, fix up the parent hover state instead
|
||||
if (this.actor == this._firstLeaveActor)
|
||||
this._firstLeaveActor = this._dragOrigParent;
|
||||
|
||||
if (this._dragInProgress && this._dragCancellable)
|
||||
this._cancelDrag(global.get_current_time());
|
||||
this.disconnectAll();
|
||||
@ -105,12 +101,6 @@ const _Draggable = new Lang.Class({
|
||||
this._animationInProgress = false; // The drag is over and the item is in the process of animating to its original position (snapping back or reverting).
|
||||
this._dragCancellable = true;
|
||||
|
||||
// During the drag, we eat enter/leave events so that actors don't prelight.
|
||||
// But we remember the actors that we first left/last entered so we can
|
||||
// fix up the hover state after the drag ends.
|
||||
this._firstLeaveActor = null;
|
||||
this._lastEnterActor = null;
|
||||
|
||||
this._eventsGrabbed = false;
|
||||
},
|
||||
|
||||
@ -196,11 +186,6 @@ const _Draggable = new Lang.Class({
|
||||
this._cancelDrag(event.get_time());
|
||||
return true;
|
||||
}
|
||||
} else if (event.type() == Clutter.EventType.LEAVE) {
|
||||
if (this._firstLeaveActor == null)
|
||||
this._firstLeaveActor = event.get_source();
|
||||
} else if (event.type() == Clutter.EventType.ENTER) {
|
||||
this._lastEnterActor = event.get_source();
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -244,7 +229,7 @@ const _Draggable = new Lang.Class({
|
||||
if (this._onEventId)
|
||||
this._ungrabActor();
|
||||
this._grabEvents();
|
||||
global.set_cursor(Shell.Cursor.DND_IN_DRAG);
|
||||
global.screen.set_cursor(Meta.Cursor.DND_IN_DRAG);
|
||||
|
||||
this._dragX = this._dragStartX = stageX;
|
||||
this._dragY = this._dragStartY = stageY;
|
||||
@ -374,7 +359,7 @@ const _Draggable = new Lang.Class({
|
||||
if (motionFunc) {
|
||||
let result = motionFunc(dragEvent);
|
||||
if (result != DragMotionResult.CONTINUE) {
|
||||
global.set_cursor(DRAG_CURSOR_MAP[result]);
|
||||
global.screen.set_cursor(DRAG_CURSOR_MAP[result]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -392,13 +377,13 @@ const _Draggable = new Lang.Class({
|
||||
targY,
|
||||
0);
|
||||
if (result != DragMotionResult.CONTINUE) {
|
||||
global.set_cursor(DRAG_CURSOR_MAP[result]);
|
||||
global.screen.set_cursor(DRAG_CURSOR_MAP[result]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
target = target.get_parent();
|
||||
}
|
||||
global.set_cursor(Shell.Cursor.DND_IN_DRAG);
|
||||
global.screen.set_cursor(Meta.Cursor.DND_IN_DRAG);
|
||||
return false;
|
||||
},
|
||||
|
||||
@ -470,7 +455,7 @@ const _Draggable = new Lang.Class({
|
||||
}
|
||||
|
||||
this._dragInProgress = false;
|
||||
global.unset_cursor();
|
||||
global.screen.set_cursor(Meta.Cursor.DEFAULT);
|
||||
this.emit('drag-end', event.get_time(), true);
|
||||
this._dragComplete();
|
||||
return true;
|
||||
@ -522,7 +507,7 @@ const _Draggable = new Lang.Class({
|
||||
let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
|
||||
|
||||
if (this._actorDestroyed) {
|
||||
global.unset_cursor();
|
||||
global.screen.set_cursor(Meta.Cursor.DEFAULT);
|
||||
if (!this._buttonDown)
|
||||
this._dragComplete();
|
||||
this.emit('drag-end', eventTime, false);
|
||||
@ -576,7 +561,7 @@ const _Draggable = new Lang.Class({
|
||||
} else {
|
||||
dragActor.destroy();
|
||||
}
|
||||
global.unset_cursor();
|
||||
global.screen.set_cursor(Meta.Cursor.DEFAULT);
|
||||
this.emit('drag-end', eventTime, false);
|
||||
|
||||
this._animationInProgress = false;
|
||||
@ -584,33 +569,12 @@ const _Draggable = new Lang.Class({
|
||||
this._dragComplete();
|
||||
},
|
||||
|
||||
// Actor is an actor we have entered or left during the drag; call
|
||||
// st_widget_sync_hover on all StWidget ancestors
|
||||
_syncHover: function(actor) {
|
||||
while (actor) {
|
||||
let parent = actor.get_parent();
|
||||
if (actor instanceof St.Widget)
|
||||
actor.sync_hover();
|
||||
|
||||
actor = parent;
|
||||
}
|
||||
},
|
||||
|
||||
_dragComplete: function() {
|
||||
if (!this._actorDestroyed)
|
||||
Shell.util_set_hidden_from_pick(this._dragActor, false);
|
||||
|
||||
this._ungrabEvents();
|
||||
|
||||
if (this._firstLeaveActor) {
|
||||
this._syncHover(this._firstLeaveActor);
|
||||
this._firstLeaveActor = null;
|
||||
}
|
||||
|
||||
if (this._lastEnterActor) {
|
||||
this._syncHover(this._lastEnterActor);
|
||||
this._lastEnterActor = null;
|
||||
}
|
||||
global.sync_pointer();
|
||||
|
||||
if (this._updateHoverId) {
|
||||
GLib.source_remove(this._updateHoverId);
|
||||
|
@ -43,20 +43,22 @@ const _DIALOG_ICON_SIZE = 32;
|
||||
|
||||
const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
|
||||
|
||||
const EndSessionDialogIface = <interface name="org.gnome.SessionManager.EndSessionDialog">
|
||||
<method name="Open">
|
||||
<arg type="u" direction="in" />
|
||||
<arg type="u" direction="in" />
|
||||
<arg type="u" direction="in" />
|
||||
<arg type="ao" direction="in" />
|
||||
</method>
|
||||
<method name="Close" />
|
||||
<signal name="ConfirmedLogout" />
|
||||
<signal name="ConfirmedReboot" />
|
||||
<signal name="ConfirmedShutdown" />
|
||||
<signal name="Canceled" />
|
||||
<signal name="Closed" />
|
||||
</interface>;
|
||||
const EndSessionDialogIface = '<node> \
|
||||
<interface name="org.gnome.SessionManager.EndSessionDialog"> \
|
||||
<method name="Open"> \
|
||||
<arg type="u" direction="in" /> \
|
||||
<arg type="u" direction="in" /> \
|
||||
<arg type="u" direction="in" /> \
|
||||
<arg type="ao" direction="in" /> \
|
||||
</method> \
|
||||
<method name="Close" /> \
|
||||
<signal name="ConfirmedLogout" /> \
|
||||
<signal name="ConfirmedReboot" /> \
|
||||
<signal name="ConfirmedShutdown" /> \
|
||||
<signal name="Canceled" /> \
|
||||
<signal name="Closed" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const logoutDialogContent = {
|
||||
subjectWithUser: C_("title", "Log Out %s"),
|
||||
@ -131,13 +133,15 @@ const DialogContent = {
|
||||
|
||||
const MAX_USERS_IN_SESSION_DIALOG = 5;
|
||||
|
||||
const LogindSessionIface = <interface name='org.freedesktop.login1.Session'>
|
||||
<property name="Id" type="s" access="read"/>
|
||||
<property name="Remote" type="b" access="read"/>
|
||||
<property name="Class" type="s" access="read"/>
|
||||
<property name="Type" type="s" access="read"/>
|
||||
<property name="State" type="s" access="read"/>
|
||||
</interface>;
|
||||
const LogindSessionIface = '<node> \
|
||||
<interface name="org.freedesktop.login1.Session"> \
|
||||
<property name="Id" type="s" access="read"/> \
|
||||
<property name="Remote" type="b" access="read"/> \
|
||||
<property name="Class" type="s" access="read"/> \
|
||||
<property name="Type" type="s" access="read"/> \
|
||||
<property name="State" type="s" access="read"/> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const LogindSession = Gio.DBusProxy.makeProxyWrapper(LogindSessionIface);
|
||||
|
||||
@ -269,13 +273,15 @@ const EndSessionDialog = new Lang.Class({
|
||||
|
||||
this._applicationHeader = new St.Label({ style_class: 'end-session-dialog-list-header',
|
||||
text: _("Some applications are busy or have unsaved work.") });
|
||||
this._applicationList = new St.BoxLayout({ vertical: true });
|
||||
this._applicationList = new St.BoxLayout({ style_class: 'end-session-dialog-app-list',
|
||||
vertical: true });
|
||||
this._inhibitorSection.add_actor(this._applicationHeader);
|
||||
this._inhibitorSection.add_actor(this._applicationList);
|
||||
|
||||
this._sessionHeader = new St.Label({ style_class: 'end-session-dialog-list-header',
|
||||
text: _("Other users are logged in.") });
|
||||
this._sessionList = new St.BoxLayout({ vertical: true });
|
||||
this._sessionList = new St.BoxLayout({ style_class: 'end-session-dialog-session-list',
|
||||
vertical: true });
|
||||
this._inhibitorSection.add_actor(this._sessionHeader);
|
||||
this._inhibitorSection.add_actor(this._sessionList);
|
||||
|
||||
|
@ -76,7 +76,11 @@ function disableExtension(uuid) {
|
||||
theme.unload_stylesheet(extension.stylesheet.get_path());
|
||||
}
|
||||
|
||||
extension.stateObj.disable();
|
||||
try {
|
||||
extension.stateObj.disable();
|
||||
} catch(e) {
|
||||
logExtensionError(uuid, e);
|
||||
}
|
||||
|
||||
for (let i = 0; i < order.length; i++) {
|
||||
let uuid = order[i];
|
||||
@ -89,8 +93,10 @@ function disableExtension(uuid) {
|
||||
|
||||
extensionOrder.splice(orderIdx, 1);
|
||||
|
||||
extension.state = ExtensionState.DISABLED;
|
||||
_signals.emit('extension-state-changed', extension);
|
||||
if ( extension.state != ExtensionState.ERROR ) {
|
||||
extension.state = ExtensionState.DISABLED;
|
||||
_signals.emit('extension-state-changed', extension);
|
||||
}
|
||||
}
|
||||
|
||||
function enableExtension(uuid) {
|
||||
@ -117,10 +123,15 @@ function enableExtension(uuid) {
|
||||
}
|
||||
}
|
||||
|
||||
extension.stateObj.enable();
|
||||
|
||||
extension.state = ExtensionState.ENABLED;
|
||||
_signals.emit('extension-state-changed', extension);
|
||||
try {
|
||||
extension.stateObj.enable();
|
||||
extension.state = ExtensionState.ENABLED;
|
||||
_signals.emit('extension-state-changed', extension);
|
||||
return;
|
||||
} catch(e) {
|
||||
logExtensionError(uuid, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function logExtensionError(uuid, error) {
|
||||
@ -150,7 +161,8 @@ function loadExtension(extension) {
|
||||
} else {
|
||||
let enabled = enabledExtensions.indexOf(extension.uuid) != -1;
|
||||
if (enabled) {
|
||||
initExtension(extension.uuid);
|
||||
if (!initExtension(extension.uuid))
|
||||
return;
|
||||
if (extension.state == ExtensionState.DISABLED)
|
||||
enableExtension(extension.uuid);
|
||||
} else {
|
||||
@ -205,7 +217,12 @@ function initExtension(uuid) {
|
||||
extensionModule = extension.imports.extension;
|
||||
|
||||
if (extensionModule.init) {
|
||||
extensionState = extensionModule.init(extension);
|
||||
try {
|
||||
extensionState = extensionModule.init(extension);
|
||||
} catch(e) {
|
||||
logExtensionError(uuid, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!extensionState)
|
||||
@ -214,6 +231,7 @@ function initExtension(uuid) {
|
||||
|
||||
extension.state = ExtensionState.DISABLED;
|
||||
_signals.emit('extension-loaded', uuid);
|
||||
return true;
|
||||
}
|
||||
|
||||
function getEnabledExtensions() {
|
||||
@ -235,11 +253,7 @@ function onEnabledExtensionsChanged() {
|
||||
newEnabledExtensions.filter(function(uuid) {
|
||||
return enabledExtensions.indexOf(uuid) == -1;
|
||||
}).forEach(function(uuid) {
|
||||
try {
|
||||
enableExtension(uuid);
|
||||
} catch(e) {
|
||||
logExtensionError(uuid, e);
|
||||
}
|
||||
});
|
||||
|
||||
// Find and disable all the newly disabled extensions: UUIDs found in the
|
||||
@ -247,11 +261,7 @@ function onEnabledExtensionsChanged() {
|
||||
enabledExtensions.filter(function(item) {
|
||||
return newEnabledExtensions.indexOf(item) == -1;
|
||||
}).forEach(function(uuid) {
|
||||
try {
|
||||
disableExtension(uuid);
|
||||
} catch(e) {
|
||||
logExtensionError(uuid, e);
|
||||
}
|
||||
});
|
||||
|
||||
enabledExtensions = newEnabledExtensions;
|
||||
@ -263,11 +273,7 @@ function _loadExtensions() {
|
||||
|
||||
let finder = new ExtensionUtils.ExtensionFinder();
|
||||
finder.connect('extension-found', function(signals, extension) {
|
||||
try {
|
||||
loadExtension(extension);
|
||||
} catch(e) {
|
||||
logExtensionError(extension.uuid, e);
|
||||
}
|
||||
loadExtension(extension);
|
||||
});
|
||||
finder.scanExtensions();
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ const FocusCaretTracker = new Lang.Class({
|
||||
|
||||
_init: function() {
|
||||
Atspi.init();
|
||||
Atspi.set_timeout(250, 250);
|
||||
this._atspiListener = Atspi.EventListener.new(Lang.bind(this, this._onChanged));
|
||||
},
|
||||
|
||||
|
@ -23,27 +23,29 @@ const KEYBOARD_TYPE = 'keyboard-type';
|
||||
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
|
||||
const SHOW_KEYBOARD = 'screen-keyboard-enabled';
|
||||
|
||||
const CaribouKeyboardIface = <interface name='org.gnome.Caribou.Keyboard'>
|
||||
<method name='Show'>
|
||||
<arg type='u' direction='in' />
|
||||
</method>
|
||||
<method name='Hide'>
|
||||
<arg type='u' direction='in' />
|
||||
</method>
|
||||
<method name='SetCursorLocation'>
|
||||
<arg type='i' direction='in' />
|
||||
<arg type='i' direction='in' />
|
||||
<arg type='i' direction='in' />
|
||||
<arg type='i' direction='in' />
|
||||
</method>
|
||||
<method name='SetEntryLocation'>
|
||||
<arg type='i' direction='in' />
|
||||
<arg type='i' direction='in' />
|
||||
<arg type='i' direction='in' />
|
||||
<arg type='i' direction='in' />
|
||||
</method>
|
||||
<property name='Name' access='read' type='s' />
|
||||
</interface>;
|
||||
const CaribouKeyboardIface = '<node> \
|
||||
<interface name="org.gnome.Caribou.Keyboard"> \
|
||||
<method name="Show"> \
|
||||
<arg type="u" direction="in" /> \
|
||||
</method> \
|
||||
<method name="Hide"> \
|
||||
<arg type="u" direction="in" /> \
|
||||
</method> \
|
||||
<method name="SetCursorLocation"> \
|
||||
<arg type="i" direction="in" /> \
|
||||
<arg type="i" direction="in" /> \
|
||||
<arg type="i" direction="in" /> \
|
||||
<arg type="i" direction="in" /> \
|
||||
</method> \
|
||||
<method name="SetEntryLocation"> \
|
||||
<arg type="i" direction="in" /> \
|
||||
<arg type="i" direction="in" /> \
|
||||
<arg type="i" direction="in" /> \
|
||||
<arg type="i" direction="in" /> \
|
||||
</method> \
|
||||
<property name="Name" access="read" type="s" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const Key = new Lang.Class({
|
||||
Name: 'Key',
|
||||
|
@ -251,7 +251,7 @@ const LayoutManager = new Lang.Class({
|
||||
|
||||
this._inOverview = true;
|
||||
this._updateVisibility();
|
||||
this._queueUpdateRegions();
|
||||
this._updateRegions();
|
||||
},
|
||||
|
||||
hideOverview: function() {
|
||||
@ -362,7 +362,7 @@ const LayoutManager = new Lang.Class({
|
||||
BackgroundMenu.addBackgroundMenu(bgManager.background.actor);
|
||||
}));
|
||||
|
||||
this._bgManagers.push(bgManager);
|
||||
this._bgManagers[monitorIndex] = bgManager;
|
||||
|
||||
return bgManager.background;
|
||||
},
|
||||
|
@ -629,55 +629,6 @@ const Inspector = new Lang.Class({
|
||||
|
||||
Signals.addSignalMethods(Inspector.prototype);
|
||||
|
||||
const Memory = new Lang.Class({
|
||||
Name: 'Memory',
|
||||
|
||||
_init: function() {
|
||||
this.actor = new St.BoxLayout({ vertical: true });
|
||||
this._glibc_uordblks = new St.Label();
|
||||
this.actor.add(this._glibc_uordblks);
|
||||
|
||||
this._js_bytes = new St.Label();
|
||||
this.actor.add(this._js_bytes);
|
||||
|
||||
this._gjs_boxed = new St.Label();
|
||||
this.actor.add(this._gjs_boxed);
|
||||
|
||||
this._gjs_gobject = new St.Label();
|
||||
this.actor.add(this._gjs_gobject);
|
||||
|
||||
this._gjs_function = new St.Label();
|
||||
this.actor.add(this._gjs_function);
|
||||
|
||||
this._gjs_closure = new St.Label();
|
||||
this.actor.add(this._gjs_closure);
|
||||
|
||||
this._last_gc_seconds_ago = new St.Label();
|
||||
this.actor.add(this._last_gc_seconds_ago);
|
||||
|
||||
this._gcbutton = new St.Button({ label: 'Full GC',
|
||||
style_class: 'lg-obj-inspector-button' });
|
||||
this._gcbutton.connect('clicked', Lang.bind(this, function () { System.gc(); this._renderText(); }));
|
||||
this.actor.add(this._gcbutton, { x_align: St.Align.START,
|
||||
x_fill: false });
|
||||
|
||||
this.actor.connect('notify::mapped', Lang.bind(this, this._renderText));
|
||||
},
|
||||
|
||||
_renderText: function() {
|
||||
if (!this.actor.mapped)
|
||||
return;
|
||||
let memInfo = global.get_memory_info();
|
||||
this._glibc_uordblks.text = 'glibc_uordblks: ' + memInfo.glibc_uordblks;
|
||||
this._js_bytes.text = 'js bytes: ' + memInfo.js_bytes;
|
||||
this._gjs_boxed.text = 'gjs_boxed: ' + memInfo.gjs_boxed;
|
||||
this._gjs_gobject.text = 'gjs_gobject: ' + memInfo.gjs_gobject;
|
||||
this._gjs_function.text = 'gjs_function: ' + memInfo.gjs_function;
|
||||
this._gjs_closure.text = 'gjs_closure: ' + memInfo.gjs_closure;
|
||||
this._last_gc_seconds_ago.text = 'last_gc_seconds_ago: ' + memInfo.last_gc_seconds_ago;
|
||||
}
|
||||
});
|
||||
|
||||
const Extensions = new Lang.Class({
|
||||
Name: 'Extensions',
|
||||
|
||||
@ -880,6 +831,19 @@ const LookingGlass = new Lang.Class({
|
||||
return true;
|
||||
}));
|
||||
|
||||
let gcIcon = new St.Icon({ icon_name: 'gnome-fs-trash-full',
|
||||
icon_size: 24 });
|
||||
toolbar.add_actor(gcIcon);
|
||||
gcIcon.reactive = true;
|
||||
gcIcon.connect('button-press-event', Lang.bind(this, function () {
|
||||
gcIcon.icon_name = 'gnome-fs-trash-empty';
|
||||
System.gc();
|
||||
this._timeoutId = Mainloop.timeout_add(500, Lang.bind(this, function () {
|
||||
gcIcon.icon_name = 'gnome-fs-trash-full';
|
||||
Mainloop.source_remove(this._timeoutId);
|
||||
}));
|
||||
}));
|
||||
|
||||
let notebook = new Notebook();
|
||||
this._notebook = notebook;
|
||||
this.actor.add(notebook.actor, { expand: true });
|
||||
@ -907,9 +871,6 @@ const LookingGlass = new Lang.Class({
|
||||
this._windowList = new WindowList(this);
|
||||
notebook.appendPage('Windows', this._windowList.actor);
|
||||
|
||||
this._memory = new Memory();
|
||||
notebook.appendPage('Memory', this._memory.actor);
|
||||
|
||||
this._extensions = new Extensions(this);
|
||||
notebook.appendPage('Extensions', this._extensions.actor);
|
||||
|
||||
@ -1072,15 +1033,15 @@ const LookingGlass = new Lang.Class({
|
||||
let myWidth = primary.width * 0.7;
|
||||
let availableHeight = primary.height - Main.layoutManager.keyboardBox.height;
|
||||
let myHeight = Math.min(primary.height * 0.7, availableHeight * 0.9);
|
||||
this.actor.x = (primary.width - myWidth) / 2;
|
||||
this._hiddenY = Main.layoutManager.panelBox.height - myHeight - 4; // -4 to hide the top corners
|
||||
this.actor.x = primary.x + (primary.width - myWidth) / 2;
|
||||
this._hiddenY = primary.y + Main.layoutManager.panelBox.height - myHeight - 4; // -4 to hide the top corners
|
||||
this._targetY = this._hiddenY + myHeight;
|
||||
this.actor.y = this._hiddenY;
|
||||
this.actor.width = myWidth;
|
||||
this.actor.height = myHeight;
|
||||
this._objInspector.actor.set_size(Math.floor(myWidth * 0.8), Math.floor(myHeight * 0.8));
|
||||
this._objInspector.actor.set_position(primary.x + this.actor.x + Math.floor(myWidth * 0.1),
|
||||
primary.y + this._targetY + Math.floor(myHeight * 0.1));
|
||||
this._objInspector.actor.set_position(this.actor.x + Math.floor(myWidth * 0.1),
|
||||
this._targetY + Math.floor(myHeight * 0.1));
|
||||
},
|
||||
|
||||
insertObject: function(obj) {
|
||||
|
@ -57,6 +57,20 @@ const Magnifier = new Lang.Class({
|
||||
// Magnifier is a manager of ZoomRegions.
|
||||
this._zoomRegions = [];
|
||||
|
||||
// Export to dbus.
|
||||
magDBusService = new MagnifierDBus.ShellMagnifier();
|
||||
|
||||
let showAtLaunch = this._settingsInit();
|
||||
this.setActive(showAtLaunch);
|
||||
},
|
||||
|
||||
_initialize: function() {
|
||||
if (this._initialized)
|
||||
return;
|
||||
this._initialized = true;
|
||||
|
||||
this._settingsInitLate();
|
||||
|
||||
// Create small clutter tree for the magnified mouse.
|
||||
let cursorTracker = Meta.CursorTracker.get_for_screen(global.screen);
|
||||
this._mouseSprite = new Clutter.Texture();
|
||||
@ -72,15 +86,11 @@ const Magnifier = new Lang.Class({
|
||||
|
||||
let aZoomRegion = new ZoomRegion(this, this._cursorRoot);
|
||||
this._zoomRegions.push(aZoomRegion);
|
||||
let showAtLaunch = this._settingsInit(aZoomRegion);
|
||||
this._settingsInitRegion(aZoomRegion);
|
||||
aZoomRegion.scrollContentsTo(this.xMouse, this.yMouse);
|
||||
|
||||
cursorTracker.connect('cursor-changed', Lang.bind(this, this._updateMouseSprite));
|
||||
this._cursorTracker = cursorTracker;
|
||||
|
||||
// Export to dbus.
|
||||
magDBusService = new MagnifierDBus.ShellMagnifier();
|
||||
this.setActive(showAtLaunch);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -88,7 +98,7 @@ const Magnifier = new Lang.Class({
|
||||
* Show the system mouse pointer.
|
||||
*/
|
||||
showSystemCursor: function() {
|
||||
global.stage.show_cursor();
|
||||
this._cursorTracker.set_pointer_visible(true);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -96,7 +106,7 @@ const Magnifier = new Lang.Class({
|
||||
* Hide the system mouse pointer.
|
||||
*/
|
||||
hideSystemCursor: function() {
|
||||
global.stage.hide_cursor();
|
||||
this._cursorTracker.set_pointer_visible(false);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -105,6 +115,12 @@ const Magnifier = new Lang.Class({
|
||||
* @activate: Boolean to activate or de-activate the magnifier.
|
||||
*/
|
||||
setActive: function(activate) {
|
||||
if (activate == this.isActive())
|
||||
return;
|
||||
|
||||
if (activate)
|
||||
this._initialize();
|
||||
|
||||
this._zoomRegions.forEach (function(zoomRegion, index, array) {
|
||||
zoomRegion.setActive(activate);
|
||||
});
|
||||
@ -117,7 +133,7 @@ const Magnifier = new Lang.Class({
|
||||
// Make sure system mouse pointer is shown when all zoom regions are
|
||||
// invisible.
|
||||
if (!activate)
|
||||
global.stage.show_cursor();
|
||||
this._cursorTracker.set_pointer_visible(true);
|
||||
|
||||
// Notify interested parties of this change
|
||||
this.emit('active-changed', activate);
|
||||
@ -432,64 +448,68 @@ const Magnifier = new Lang.Class({
|
||||
this._mouseSprite.set_anchor_point(xHot, yHot);
|
||||
},
|
||||
|
||||
_settingsInit: function(zoomRegion) {
|
||||
_settingsInitRegion: function(zoomRegion) {
|
||||
// Mag factor is accurate to two decimal places.
|
||||
let aPref = parseFloat(this._settings.get_double(MAG_FACTOR_KEY).toFixed(2));
|
||||
if (aPref != 0.0)
|
||||
zoomRegion.setMagFactor(aPref, aPref);
|
||||
|
||||
aPref = this._settings.get_enum(SCREEN_POSITION_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setScreenPosition(aPref);
|
||||
|
||||
zoomRegion.setLensMode(this._settings.get_boolean(LENS_MODE_KEY));
|
||||
zoomRegion.setClampScrollingAtEdges(!this._settings.get_boolean(CLAMP_MODE_KEY));
|
||||
|
||||
aPref = this._settings.get_enum(MOUSE_TRACKING_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setMouseTrackingMode(aPref);
|
||||
|
||||
aPref = this._settings.get_enum(FOCUS_TRACKING_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setFocusTrackingMode(aPref);
|
||||
|
||||
aPref = this._settings.get_enum(CARET_TRACKING_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setCaretTrackingMode(aPref);
|
||||
|
||||
aPref = this._settings.get_boolean(INVERT_LIGHTNESS_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setInvertLightness(aPref);
|
||||
|
||||
aPref = this._settings.get_double(COLOR_SATURATION_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setColorSaturation(aPref);
|
||||
|
||||
let bc = {};
|
||||
bc.r = this._settings.get_double(BRIGHT_RED_KEY);
|
||||
bc.g = this._settings.get_double(BRIGHT_GREEN_KEY);
|
||||
bc.b = this._settings.get_double(BRIGHT_BLUE_KEY);
|
||||
zoomRegion.setBrightness(bc);
|
||||
|
||||
bc.r = this._settings.get_double(CONTRAST_RED_KEY);
|
||||
bc.g = this._settings.get_double(CONTRAST_GREEN_KEY);
|
||||
bc.b = this._settings.get_double(CONTRAST_BLUE_KEY);
|
||||
zoomRegion.setContrast(bc);
|
||||
},
|
||||
|
||||
_settingsInit: function() {
|
||||
this._appSettings = new Gio.Settings({ schema: APPLICATIONS_SCHEMA });
|
||||
this._settings = new Gio.Settings({ schema: MAGNIFIER_SCHEMA });
|
||||
|
||||
if (zoomRegion) {
|
||||
// Mag factor is accurate to two decimal places.
|
||||
let aPref = parseFloat(this._settings.get_double(MAG_FACTOR_KEY).toFixed(2));
|
||||
if (aPref != 0.0)
|
||||
zoomRegion.setMagFactor(aPref, aPref);
|
||||
this._appSettings.connect('changed::' + SHOW_KEY, Lang.bind(this, function() {
|
||||
let active = this._appSettings.get_boolean(SHOW_KEY);
|
||||
this.setActive(active);
|
||||
}));
|
||||
|
||||
aPref = this._settings.get_enum(SCREEN_POSITION_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setScreenPosition(aPref);
|
||||
|
||||
zoomRegion.setLensMode(this._settings.get_boolean(LENS_MODE_KEY));
|
||||
zoomRegion.setClampScrollingAtEdges(!this._settings.get_boolean(CLAMP_MODE_KEY));
|
||||
|
||||
aPref = this._settings.get_enum(MOUSE_TRACKING_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setMouseTrackingMode(aPref);
|
||||
|
||||
aPref = this._settings.get_enum(FOCUS_TRACKING_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setFocusTrackingMode(aPref);
|
||||
|
||||
aPref = this._settings.get_enum(CARET_TRACKING_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setCaretTrackingMode(aPref);
|
||||
|
||||
aPref = this._settings.get_boolean(INVERT_LIGHTNESS_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setInvertLightness(aPref);
|
||||
|
||||
aPref = this._settings.get_double(COLOR_SATURATION_KEY);
|
||||
if (aPref)
|
||||
zoomRegion.setColorSaturation(aPref);
|
||||
|
||||
let bc = {};
|
||||
bc.r = this._settings.get_double(BRIGHT_RED_KEY);
|
||||
bc.g = this._settings.get_double(BRIGHT_GREEN_KEY);
|
||||
bc.b = this._settings.get_double(BRIGHT_BLUE_KEY);
|
||||
zoomRegion.setBrightness(bc);
|
||||
|
||||
bc.r = this._settings.get_double(CONTRAST_RED_KEY);
|
||||
bc.g = this._settings.get_double(CONTRAST_GREEN_KEY);
|
||||
bc.b = this._settings.get_double(CONTRAST_BLUE_KEY);
|
||||
zoomRegion.setContrast(bc);
|
||||
}
|
||||
return this._appSettings.get_boolean(SHOW_KEY);
|
||||
},
|
||||
|
||||
_settingsInitLate: function() {
|
||||
let showCrosshairs = this._settings.get_boolean(SHOW_CROSS_HAIRS_KEY);
|
||||
this.addCrosshairs();
|
||||
this.setCrosshairsVisible(showCrosshairs);
|
||||
|
||||
this._appSettings.connect('changed::' + SHOW_KEY,
|
||||
Lang.bind(this, function() {
|
||||
this.setActive(this._appSettings.get_boolean(SHOW_KEY));
|
||||
}));
|
||||
|
||||
this._settings.connect('changed::' + SCREEN_POSITION_KEY,
|
||||
Lang.bind(this, this._updateScreenPosition));
|
||||
this._settings.connect('changed::' + MAG_FACTOR_KEY,
|
||||
@ -553,8 +573,6 @@ const Magnifier = new Lang.Class({
|
||||
Lang.bind(this, function() {
|
||||
this.setCrosshairsClip(this._settings.get_boolean(CROSS_HAIRS_CLIP_KEY));
|
||||
}));
|
||||
|
||||
return this._appSettings.get_boolean(SHOW_KEY);
|
||||
},
|
||||
|
||||
_updateScreenPosition: function() {
|
||||
@ -732,14 +750,17 @@ const ZoomRegion = new Lang.Class({
|
||||
* @activate: Boolean to show/hide the ZoomRegion.
|
||||
*/
|
||||
setActive: function(activate) {
|
||||
if (activate && !this.isActive()) {
|
||||
if (activate == this.isActive())
|
||||
return;
|
||||
|
||||
if (activate) {
|
||||
this._createActors();
|
||||
if (this._isMouseOverRegion())
|
||||
this._magnifier.hideSystemCursor();
|
||||
this._updateMagViewGeometry();
|
||||
this._updateCloneGeometry();
|
||||
this._updateMousePosition();
|
||||
} else if (!activate && this.isActive()) {
|
||||
} else {
|
||||
this._destroyActors();
|
||||
}
|
||||
},
|
||||
|
@ -9,85 +9,89 @@ const ZOOM_SERVICE_PATH = '/org/gnome/Magnifier/ZoomRegion';
|
||||
|
||||
// Subset of gnome-mag's Magnifier dbus interface -- to be expanded. See:
|
||||
// http://git.gnome.org/browse/gnome-mag/tree/xml/...Magnifier.xml
|
||||
const MagnifierIface = <interface name="org.gnome.Magnifier">
|
||||
<method name="setActive">
|
||||
<arg type="b" direction="in" />
|
||||
</method>
|
||||
<method name="isActive">
|
||||
<arg type="b" direction="out" />
|
||||
</method>
|
||||
<method name="showCursor" />
|
||||
<method name="hideCursor" />
|
||||
<method name="createZoomRegion">
|
||||
<arg type="d" direction="in" />
|
||||
<arg type="d" direction="in" />
|
||||
<arg type="ai" direction="in" />
|
||||
<arg type="ai" direction="in" />
|
||||
<arg type="o" direction="out" />
|
||||
</method>
|
||||
<method name="addZoomRegion">
|
||||
<arg type="o" direction="in" />
|
||||
<arg type="b" direction="out" />
|
||||
</method>
|
||||
<method name="getZoomRegions">
|
||||
<arg type="ao" direction="out" />
|
||||
</method>
|
||||
<method name="clearAllZoomRegions" />
|
||||
<method name="fullScreenCapable">
|
||||
<arg type="b" direction="out" />
|
||||
</method>
|
||||
<method name="setCrosswireSize">
|
||||
<arg type="i" direction="in" />
|
||||
</method>
|
||||
<method name="getCrosswireSize">
|
||||
<arg type="i" direction="out" />
|
||||
</method>
|
||||
<method name="setCrosswireLength">
|
||||
<arg type="i" direction="in" />
|
||||
</method>
|
||||
<method name="getCrosswireLength">
|
||||
<arg type="i" direction="out" />
|
||||
</method>
|
||||
<method name="setCrosswireClip">
|
||||
<arg type="b" direction="in" />
|
||||
</method>
|
||||
<method name="getCrosswireClip">
|
||||
<arg type="b" direction="out" />
|
||||
</method>
|
||||
<method name="setCrosswireColor">
|
||||
<arg type="u" direction="in" />
|
||||
</method>
|
||||
<method name="getCrosswireColor">
|
||||
<arg type="u" direction="out" />
|
||||
</method>
|
||||
</interface>;
|
||||
const MagnifierIface = '<node> \
|
||||
<interface name="org.gnome.Magnifier"> \
|
||||
<method name="setActive"> \
|
||||
<arg type="b" direction="in" /> \
|
||||
</method> \
|
||||
<method name="isActive"> \
|
||||
<arg type="b" direction="out" /> \
|
||||
</method> \
|
||||
<method name="showCursor" /> \
|
||||
<method name="hideCursor" /> \
|
||||
<method name="createZoomRegion"> \
|
||||
<arg type="d" direction="in" /> \
|
||||
<arg type="d" direction="in" /> \
|
||||
<arg type="ai" direction="in" /> \
|
||||
<arg type="ai" direction="in" /> \
|
||||
<arg type="o" direction="out" /> \
|
||||
</method> \
|
||||
<method name="addZoomRegion"> \
|
||||
<arg type="o" direction="in" /> \
|
||||
<arg type="b" direction="out" /> \
|
||||
</method> \
|
||||
<method name="getZoomRegions"> \
|
||||
<arg type="ao" direction="out" /> \
|
||||
</method> \
|
||||
<method name="clearAllZoomRegions" /> \
|
||||
<method name="fullScreenCapable"> \
|
||||
<arg type="b" direction="out" /> \
|
||||
</method> \
|
||||
<method name="setCrosswireSize"> \
|
||||
<arg type="i" direction="in" /> \
|
||||
</method> \
|
||||
<method name="getCrosswireSize"> \
|
||||
<arg type="i" direction="out" /> \
|
||||
</method> \
|
||||
<method name="setCrosswireLength"> \
|
||||
<arg type="i" direction="in" /> \
|
||||
</method> \
|
||||
<method name="getCrosswireLength"> \
|
||||
<arg type="i" direction="out" /> \
|
||||
</method> \
|
||||
<method name="setCrosswireClip"> \
|
||||
<arg type="b" direction="in" /> \
|
||||
</method> \
|
||||
<method name="getCrosswireClip"> \
|
||||
<arg type="b" direction="out" /> \
|
||||
</method> \
|
||||
<method name="setCrosswireColor"> \
|
||||
<arg type="u" direction="in" /> \
|
||||
</method> \
|
||||
<method name="getCrosswireColor"> \
|
||||
<arg type="u" direction="out" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
// Subset of gnome-mag's ZoomRegion dbus interface -- to be expanded. See:
|
||||
// http://git.gnome.org/browse/gnome-mag/tree/xml/...ZoomRegion.xml
|
||||
const ZoomRegionIface = <interface name="org.gnome.Magnifier.ZoomRegion">
|
||||
<method name="setMagFactor">
|
||||
<arg type="d" direction="in" />
|
||||
<arg type="d" direction="in" />
|
||||
</method>
|
||||
<method name="getMagFactor">
|
||||
<arg type="d" direction="out" />
|
||||
<arg type="d" direction="out" />
|
||||
</method>
|
||||
<method name="setRoi">
|
||||
<arg type="ai" direction="in" />
|
||||
</method>
|
||||
<method name="getRoi">
|
||||
<arg type="ai" direction="out" />
|
||||
</method>
|
||||
<method name="shiftContentsTo">
|
||||
<arg type="i" direction="in" />
|
||||
<arg type="i" direction="in" />
|
||||
<arg type="b" direction="out" />
|
||||
</method>
|
||||
<method name="moveResize">
|
||||
<arg type="ai" direction="in" />
|
||||
</method>
|
||||
</interface>;
|
||||
const ZoomRegionIface = '<node> \
|
||||
<interface name="org.gnome.Magnifier.ZoomRegion"> \
|
||||
<method name="setMagFactor"> \
|
||||
<arg type="d" direction="in" /> \
|
||||
<arg type="d" direction="in" /> \
|
||||
</method> \
|
||||
<method name="getMagFactor"> \
|
||||
<arg type="d" direction="out" /> \
|
||||
<arg type="d" direction="out" /> \
|
||||
</method> \
|
||||
<method name="setRoi"> \
|
||||
<arg type="ai" direction="in" /> \
|
||||
</method> \
|
||||
<method name="getRoi"> \
|
||||
<arg type="ai" direction="out" /> \
|
||||
</method> \
|
||||
<method name="shiftContentsTo"> \
|
||||
<arg type="i" direction="in" /> \
|
||||
<arg type="i" direction="in" /> \
|
||||
<arg type="b" direction="out" /> \
|
||||
</method> \
|
||||
<method name="moveResize"> \
|
||||
<arg type="ai" direction="in" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
// For making unique ZoomRegion DBus proxy object paths of the form:
|
||||
// '/org/gnome/Magnifier/ZoomRegion/zoomer0',
|
||||
|
@ -90,8 +90,12 @@ function _sessionUpdated() {
|
||||
Shell.KeyBindingMode.OVERVIEW,
|
||||
sessionMode.hasRunDialog ? openRunDialog : null);
|
||||
|
||||
if (!sessionMode.hasRunDialog && lookingGlass)
|
||||
lookingGlass.close();
|
||||
if (!sessionMode.hasRunDialog) {
|
||||
if (runDialog)
|
||||
runDialog.close();
|
||||
if (lookingGlass)
|
||||
lookingGlass.close();
|
||||
}
|
||||
}
|
||||
|
||||
function start() {
|
||||
|
@ -215,10 +215,10 @@ const URLHighlighter = new Lang.Class({
|
||||
|
||||
let urlId = this._findUrlAtPos(event);
|
||||
if (urlId != -1 && !this._cursorChanged) {
|
||||
global.set_cursor(Shell.Cursor.POINTING_HAND);
|
||||
global.screen.set_cursor(Meta.Cursor.POINTING_HAND);
|
||||
this._cursorChanged = true;
|
||||
} else if (urlId == -1) {
|
||||
global.unset_cursor();
|
||||
global.screen.set_cursor(Meta.Cursor.DEFAULT);
|
||||
this._cursorChanged = false;
|
||||
}
|
||||
return false;
|
||||
@ -229,7 +229,7 @@ const URLHighlighter = new Lang.Class({
|
||||
|
||||
if (this._cursorChanged) {
|
||||
this._cursorChanged = false;
|
||||
global.unset_cursor();
|
||||
global.screen.set_cursor(Meta.Cursor.DEFAULT);
|
||||
}
|
||||
}));
|
||||
},
|
||||
@ -280,10 +280,6 @@ const URLHighlighter = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
function strHasSuffix(string, suffix) {
|
||||
return string.substr(-suffix.length) == suffix;
|
||||
}
|
||||
|
||||
// NotificationPolicy:
|
||||
// An object that holds all bits of configurable policy related to a notification
|
||||
// source, such as whether to play sound or honour the critical bit.
|
||||
@ -310,6 +306,126 @@ const NotificationPolicy = new Lang.Class({
|
||||
});
|
||||
Signals.addSignalMethods(NotificationPolicy.prototype);
|
||||
|
||||
const NotificationGenericPolicy = new Lang.Class({
|
||||
Name: 'NotificationGenericPolicy',
|
||||
Extends: NotificationPolicy,
|
||||
|
||||
_init: function() {
|
||||
// Don't chain to parent, it would try setting
|
||||
// our properties to the defaults
|
||||
|
||||
this.id = 'generic';
|
||||
|
||||
this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' });
|
||||
this._masterSettings.connect('changed', Lang.bind(this, this._changed));
|
||||
},
|
||||
|
||||
store: function() { },
|
||||
|
||||
destroy: function() {
|
||||
this._masterSettings.run_dispose();
|
||||
},
|
||||
|
||||
_changed: function(settings, key) {
|
||||
this.emit('policy-changed', key);
|
||||
},
|
||||
|
||||
get enable() {
|
||||
return true;
|
||||
},
|
||||
|
||||
get enableSound() {
|
||||
return true;
|
||||
},
|
||||
|
||||
get showBanners() {
|
||||
return this._masterSettings.get_boolean('show-banners');
|
||||
},
|
||||
|
||||
get forceExpanded() {
|
||||
return false;
|
||||
},
|
||||
|
||||
get showInLockScreen() {
|
||||
return this._masterSettings.get_boolean('show-in-lock-screen');
|
||||
},
|
||||
|
||||
get detailsInLockScreen() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
const NotificationApplicationPolicy = new Lang.Class({
|
||||
Name: 'NotificationApplicationPolicy',
|
||||
Extends: NotificationPolicy,
|
||||
|
||||
_init: function(id) {
|
||||
// Don't chain to parent, it would try setting
|
||||
// our properties to the defaults
|
||||
|
||||
this.id = id;
|
||||
this._canonicalId = this._canonicalizeId(id);
|
||||
|
||||
this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' });
|
||||
this._settings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications.application',
|
||||
path: '/org/gnome/desktop/notifications/application/' + this._canonicalId + '/' });
|
||||
|
||||
this._masterSettings.connect('changed', Lang.bind(this, this._changed));
|
||||
this._settings.connect('changed', Lang.bind(this, this._changed));
|
||||
},
|
||||
|
||||
store: function() {
|
||||
this._settings.set_string('application-id', this.id + '.desktop');
|
||||
|
||||
let apps = this._masterSettings.get_strv('application-children');
|
||||
if (apps.indexOf(this._canonicalId) < 0) {
|
||||
apps.push(this._canonicalId);
|
||||
this._masterSettings.set_strv('application-children', apps);
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this._masterSettings.run_dispose();
|
||||
this._settings.run_dispose();
|
||||
},
|
||||
|
||||
_changed: function(settings, key) {
|
||||
this.emit('policy-changed', key);
|
||||
},
|
||||
|
||||
_canonicalizeId: function(id) {
|
||||
// Keys are restricted to lowercase alphanumeric characters and dash,
|
||||
// and two dashes cannot be in succession
|
||||
return id.toLowerCase().replace(/[^a-z0-9\-]/g, '-').replace(/--+/g, '-');
|
||||
},
|
||||
|
||||
get enable() {
|
||||
return this._settings.get_boolean('enable');
|
||||
},
|
||||
|
||||
get enableSound() {
|
||||
return this._settings.get_boolean('enable-sound-alerts');
|
||||
},
|
||||
|
||||
get showBanners() {
|
||||
return this._masterSettings.get_boolean('show-banners') &&
|
||||
this._settings.get_boolean('show-banners');
|
||||
},
|
||||
|
||||
get forceExpanded() {
|
||||
return this._settings.get_boolean('force-expanded');
|
||||
},
|
||||
|
||||
get showInLockScreen() {
|
||||
return this._masterSettings.get_boolean('show-in-lock-screen') &&
|
||||
this._settings.get_boolean('show-in-lock-screen');
|
||||
},
|
||||
|
||||
get detailsInLockScreen() {
|
||||
return this._settings.get_boolean('details-in-lock-screen');
|
||||
}
|
||||
});
|
||||
|
||||
// Notification:
|
||||
// @source: the notification's Source
|
||||
// @title: the title
|
||||
@ -383,7 +499,6 @@ const Notification = new Lang.Class({
|
||||
this.focused = false;
|
||||
this.acknowledged = false;
|
||||
this._destroyed = false;
|
||||
this._useActionIcons = false;
|
||||
this._customContent = false;
|
||||
this.bannerBodyText = null;
|
||||
this.bannerBodyMarkup = false;
|
||||
@ -438,7 +553,12 @@ const Notification = new Lang.Class({
|
||||
this._bannerLabel = this._bannerUrlHighlighter.actor;
|
||||
this._bannerBox.add_actor(this._bannerLabel);
|
||||
|
||||
this.update(title, banner, params);
|
||||
// If called with only one argument we assume the caller
|
||||
// will call .update() later on. This is the case of
|
||||
// NotificationDaemon, which wants to use the same code
|
||||
// for new and updated notifications
|
||||
if (arguments.length != 1)
|
||||
this.update(title, banner, params);
|
||||
},
|
||||
|
||||
// update:
|
||||
@ -711,19 +831,8 @@ const Notification = new Lang.Class({
|
||||
}
|
||||
},
|
||||
|
||||
// addButton:
|
||||
// @id: the action ID
|
||||
// @label: the label for the action's button
|
||||
//
|
||||
// Adds a button with the given @label to the notification. All
|
||||
// action buttons will appear in a single row at the bottom of
|
||||
// the notification.
|
||||
//
|
||||
// If the button is clicked, the notification will emit the
|
||||
// %action-invoked signal with @id as a parameter
|
||||
addButton: function(id, label) {
|
||||
addButton: function(button, callback) {
|
||||
if (!this._buttonBox) {
|
||||
|
||||
let box = new St.BoxLayout({ style_class: 'notification-actions' });
|
||||
this.setActionArea(box, { x_expand: false,
|
||||
y_expand: false,
|
||||
@ -731,49 +840,40 @@ const Notification = new Lang.Class({
|
||||
y_fill: false,
|
||||
x_align: St.Align.END });
|
||||
this._buttonBox = box;
|
||||
global.focus_manager.add_group(this._buttonBox);
|
||||
}
|
||||
|
||||
let button = new St.Button({ can_focus: true });
|
||||
button._actionId = id;
|
||||
|
||||
let iconName = strHasSuffix(id, '-symbolic') ? id : id + '-symbolic';
|
||||
if (this._useActionIcons && Gtk.IconTheme.get_default().has_icon(iconName)) {
|
||||
button.add_style_class_name('notification-icon-button');
|
||||
button.child = new St.Icon({ icon_name: iconName });
|
||||
} else {
|
||||
button.add_style_class_name('notification-button');
|
||||
button.label = label;
|
||||
}
|
||||
|
||||
if (this._buttonBox.get_n_children() > 0)
|
||||
global.focus_manager.remove_group(this._buttonBox);
|
||||
|
||||
this._buttonBox.add(button);
|
||||
global.focus_manager.add_group(this._buttonBox);
|
||||
button.connect('clicked', Lang.bind(this, this._onActionInvoked, id));
|
||||
button.connect('clicked', Lang.bind(this, function() {
|
||||
callback();
|
||||
|
||||
if (!this.resident) {
|
||||
// We don't hide a resident notification when the user invokes one of its actions,
|
||||
// because it is common for such notifications to update themselves with new
|
||||
// information based on the action. We'd like to display the updated information
|
||||
// in place, rather than pop-up a new notification.
|
||||
this.emit('done-displaying');
|
||||
this.destroy();
|
||||
}
|
||||
}));
|
||||
|
||||
this.updated();
|
||||
return button;
|
||||
},
|
||||
|
||||
// setButtonSensitive:
|
||||
// @id: the action ID
|
||||
// @sensitive: whether the button should be sensitive
|
||||
// addAction:
|
||||
// @label: the label for the action's button
|
||||
// @callback: the callback for the action
|
||||
//
|
||||
// If the notification contains a button with action ID @id,
|
||||
// its sensitivity will be set to @sensitive. Insensitive
|
||||
// buttons cannot be clicked.
|
||||
setButtonSensitive: function(id, sensitive) {
|
||||
if (!this._buttonBox)
|
||||
return;
|
||||
// Adds a button with the given @label to the notification. All
|
||||
// action buttons will appear in a single row at the bottom of
|
||||
// the notification.
|
||||
addAction: function(label, callback) {
|
||||
let button = new St.Button({ style_class: 'notification-button',
|
||||
label: label,
|
||||
can_focus: true });
|
||||
|
||||
let button = this._buttonBox.get_children().filter(function(b) {
|
||||
return b._actionId == id;
|
||||
})[0];
|
||||
|
||||
if (!button || button.reactive == sensitive)
|
||||
return;
|
||||
|
||||
button.reactive = sensitive;
|
||||
return this.addButton(button, callback);
|
||||
},
|
||||
|
||||
setUrgency: function(urgency) {
|
||||
@ -792,10 +892,6 @@ const Notification = new Lang.Class({
|
||||
this.forFeedback = forFeedback;
|
||||
},
|
||||
|
||||
setUseActionIcons: function(useIcons) {
|
||||
this._useActionIcons = useIcons;
|
||||
},
|
||||
|
||||
_styleChanged: function() {
|
||||
this._spacing = this._table.get_theme_node().get_length('spacing-columns');
|
||||
},
|
||||
@ -1020,18 +1116,6 @@ const Notification = new Lang.Class({
|
||||
this.actor.add_style_class_name('notification-unexpanded');
|
||||
},
|
||||
|
||||
_onActionInvoked: function(actor, mouseButtonClicked, id) {
|
||||
this.emit('action-invoked', id);
|
||||
if (!this.resident) {
|
||||
// We don't hide a resident notification when the user invokes one of its actions,
|
||||
// because it is common for such notifications to update themselves with new
|
||||
// information based on the action. We'd like to display the updated information
|
||||
// in place, rather than pop-up a new notification.
|
||||
this.emit('done-displaying');
|
||||
this.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
_onClicked: function() {
|
||||
this.emit('clicked');
|
||||
// We hide all types of notifications once the user clicks on them because the common
|
||||
@ -1206,6 +1290,10 @@ const Source = new Lang.Class({
|
||||
return this.count > 1;
|
||||
},
|
||||
|
||||
get isClearable() {
|
||||
return !this.trayIcon && !this.isChat && !this.resident;
|
||||
},
|
||||
|
||||
countUpdated: function() {
|
||||
this.emit('count-updated');
|
||||
},
|
||||
@ -1277,25 +1365,25 @@ const Source = new Lang.Class({
|
||||
return this._mainIcon.actor;
|
||||
},
|
||||
|
||||
_onNotificationDestroy: function(notification) {
|
||||
let index = this.notifications.indexOf(notification);
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
this.notifications.splice(index, 1);
|
||||
if (this.notifications.length == 0)
|
||||
this._lastNotificationRemoved();
|
||||
|
||||
this.countUpdated();
|
||||
},
|
||||
|
||||
pushNotification: function(notification) {
|
||||
if (this.notifications.indexOf(notification) < 0) {
|
||||
this.notifications.push(notification);
|
||||
this.emit('notification-added', notification);
|
||||
}
|
||||
if (this.notifications.indexOf(notification) >= 0)
|
||||
return;
|
||||
|
||||
notification.connect('clicked', Lang.bind(this, this.open));
|
||||
notification.connect('destroy', Lang.bind(this,
|
||||
function () {
|
||||
let index = this.notifications.indexOf(notification);
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
this.notifications.splice(index, 1);
|
||||
if (this.notifications.length == 0)
|
||||
this._lastNotificationRemoved();
|
||||
|
||||
this.countUpdated();
|
||||
}));
|
||||
notification.connect('destroy', Lang.bind(this, this._onNotificationDestroy));
|
||||
this.notifications.push(notification);
|
||||
this.emit('notification-added', notification);
|
||||
|
||||
this.countUpdated();
|
||||
},
|
||||
@ -1507,26 +1595,42 @@ const MessageTrayMenu = new Lang.Class({
|
||||
|
||||
this._tray = tray;
|
||||
|
||||
this._presence = new GnomeSession.Presence(Lang.bind(this, function(proxy, error) {
|
||||
if (error) {
|
||||
logError(error, 'Error while reading gnome-session presence');
|
||||
return;
|
||||
}
|
||||
|
||||
this._onStatusChanged(proxy.status);
|
||||
}));
|
||||
this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
|
||||
this._onStatusChanged(status);
|
||||
}));
|
||||
|
||||
this._accountManager = Tp.AccountManager.dup();
|
||||
this._accountManager.connect('most-available-presence-changed',
|
||||
Lang.bind(this, this._onIMPresenceChanged));
|
||||
this._accountManager.prepare_async(null, Lang.bind(this, this._onIMPresenceChanged));
|
||||
|
||||
this.actor.hide();
|
||||
Main.layoutManager.addChrome(this.actor);
|
||||
|
||||
this._busyItem = new PopupMenu.PopupSwitchMenuItem(_("Notifications"));
|
||||
this._busyItem.connect('toggled', Lang.bind(this, this._updatePresence));
|
||||
this.addMenuItem(this._busyItem);
|
||||
|
||||
let separator = new PopupMenu.PopupSeparatorMenuItem();
|
||||
this.addMenuItem(separator);
|
||||
|
||||
this._clearItem = this.addAction(_("Clear Messages"), function() {
|
||||
let toDestroy = [];
|
||||
let sources = tray.getSources();
|
||||
for (let i = 0; i < sources.length; i++) {
|
||||
// We exclude trayIcons, chat and resident sources
|
||||
if (sources[i].trayIcon ||
|
||||
sources[i].isChat ||
|
||||
sources[i].resident)
|
||||
continue;
|
||||
toDestroy.push(sources[i]);
|
||||
}
|
||||
let toDestroy = tray.getSources().filter(function(source) {
|
||||
return source.isClearable;
|
||||
})
|
||||
|
||||
for (let i = 0; i < toDestroy.length; i++) {
|
||||
toDestroy[i].destroy();
|
||||
}
|
||||
toDestroy.forEach(function(source) {
|
||||
source.destroy();
|
||||
});
|
||||
|
||||
toDestroy = null;
|
||||
tray.close();
|
||||
});
|
||||
|
||||
@ -1541,9 +1645,43 @@ const MessageTrayMenu = new Lang.Class({
|
||||
settingsItem.connect('activate', function() { tray.close(); });
|
||||
},
|
||||
|
||||
_onStatusChanged: function(status) {
|
||||
this._sessionStatus = status;
|
||||
this._busyItem.setToggleState(status != GnomeSession.PresenceStatus.BUSY);
|
||||
},
|
||||
|
||||
_onIMPresenceChanged: function(am, type) {
|
||||
if (type == Tp.ConnectionPresenceType.AVAILABLE &&
|
||||
this._sessionStatus == GnomeSession.PresenceStatus.BUSY)
|
||||
this._presence.SetStatusRemote(GnomeSession.PresenceStatus.AVAILABLE);
|
||||
},
|
||||
|
||||
_updateClearSensitivity: function() {
|
||||
this._clearItem.setSensitive(this._tray.clearableCount > 0);
|
||||
},
|
||||
|
||||
_updatePresence: function(item, state) {
|
||||
let status = state ? GnomeSession.PresenceStatus.AVAILABLE
|
||||
: GnomeSession.PresenceStatus.BUSY;
|
||||
this._presence.SetStatusRemote(status);
|
||||
|
||||
let [type, s ,msg] = this._accountManager.get_most_available_presence();
|
||||
let newType = 0;
|
||||
let newStatus;
|
||||
if (status == GnomeSession.PresenceStatus.BUSY &&
|
||||
type == Tp.ConnectionPresenceType.AVAILABLE) {
|
||||
newType = Tp.ConnectionPresenceType.BUSY;
|
||||
newStatus = 'busy';
|
||||
} else if (status == GnomeSession.PresenceStatus.AVAILABLE &&
|
||||
type == Tp.ConnectionPresenceType.BUSY) {
|
||||
newType = Tp.ConnectionPresenceType.AVAILABLE;
|
||||
newStatus = 'available';
|
||||
}
|
||||
|
||||
if (newType > 0)
|
||||
this._accountManager.set_all_requested_presences(newType,
|
||||
newStatus, msg);
|
||||
}
|
||||
});
|
||||
|
||||
const MessageTrayMenuButton = new Lang.Class({
|
||||
@ -1805,8 +1943,9 @@ const MessageTray = new Lang.Class({
|
||||
},
|
||||
|
||||
_sessionUpdated: function() {
|
||||
if ((Main.sessionMode.isLocked || Main.sessionMode.isGreeter) && this._inCtrlAltTab) {
|
||||
Main.ctrlAltTabManager.removeGroup(this._summary);
|
||||
if (Main.sessionMode.isLocked || Main.sessionMode.isGreeter) {
|
||||
if (this._inCtrlAltTab)
|
||||
Main.ctrlAltTabManager.removeGroup(this._summary);
|
||||
this._inCtrlAltTab = false;
|
||||
} else if (!this._inCtrlAltTab) {
|
||||
Main.ctrlAltTabManager.addGroup(this._summary, _("Message Tray"), 'user-available-symbolic',
|
||||
@ -1925,7 +2064,7 @@ const MessageTray = new Lang.Class({
|
||||
this._summary.insert_child_at_index(summaryItem.actor, this._chatSummaryItemsCount);
|
||||
}
|
||||
|
||||
if (!source.trayIcon && !source.isChat && !source.resident)
|
||||
if (source.isClearable)
|
||||
this.clearableCount++;
|
||||
|
||||
this._sources.set(source, obj);
|
||||
@ -1969,7 +2108,7 @@ const MessageTray = new Lang.Class({
|
||||
if (source.isChat)
|
||||
this._chatSummaryItemsCount--;
|
||||
|
||||
if (!source.trayIcon && !source.isChat && !source.resident)
|
||||
if (source.isClearable)
|
||||
this.clearableCount--;
|
||||
|
||||
source.disconnect(obj.notifyId);
|
||||
@ -2034,7 +2173,10 @@ const MessageTray = new Lang.Class({
|
||||
},
|
||||
|
||||
toggleAndNavigate: function() {
|
||||
if (this.toggle())
|
||||
if (!this.toggle())
|
||||
return;
|
||||
|
||||
if (this._traySummoned)
|
||||
this._summary.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||
},
|
||||
|
||||
|
@ -4,6 +4,7 @@ const Clutter = imports.gi.Clutter;
|
||||
const GdkPixbuf = imports.gi.GdkPixbuf;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Mainloop = imports.mainloop;
|
||||
@ -15,54 +16,56 @@ const MessageTray = imports.ui.messageTray;
|
||||
const Params = imports.misc.params;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
let nextNotificationId = 1;
|
||||
|
||||
// Should really be defined in Gio.js
|
||||
const BusIface = <interface name="org.freedesktop.DBus">
|
||||
<method name="GetConnectionUnixProcessID">
|
||||
<arg type="s" direction="in" />
|
||||
<arg type="u" direction="out" />
|
||||
</method>
|
||||
</interface>;
|
||||
const BusIface = '<node> \
|
||||
<interface name="org.freedesktop.DBus"> \
|
||||
<method name="GetConnectionUnixProcessID"> \
|
||||
<arg type="s" direction="in" /> \
|
||||
<arg type="u" direction="out" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
var BusProxy = Gio.DBusProxy.makeProxyWrapper(BusIface);
|
||||
function Bus() {
|
||||
return new BusProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
|
||||
}
|
||||
|
||||
const NotificationDaemonIface = <interface name="org.freedesktop.Notifications">
|
||||
<method name="Notify">
|
||||
<arg type="s" direction="in"/>
|
||||
<arg type="u" direction="in"/>
|
||||
<arg type="s" direction="in"/>
|
||||
<arg type="s" direction="in"/>
|
||||
<arg type="s" direction="in"/>
|
||||
<arg type="as" direction="in"/>
|
||||
<arg type="a{sv}" direction="in"/>
|
||||
<arg type="i" direction="in"/>
|
||||
<arg type="u" direction="out"/>
|
||||
</method>
|
||||
<method name="CloseNotification">
|
||||
<arg type="u" direction="in"/>
|
||||
</method>
|
||||
<method name="GetCapabilities">
|
||||
<arg type="as" direction="out"/>
|
||||
</method>
|
||||
<method name="GetServerInformation">
|
||||
<arg type="s" direction="out"/>
|
||||
<arg type="s" direction="out"/>
|
||||
<arg type="s" direction="out"/>
|
||||
<arg type="s" direction="out"/>
|
||||
</method>
|
||||
<signal name="NotificationClosed">
|
||||
<arg type="u"/>
|
||||
<arg type="u"/>
|
||||
</signal>
|
||||
<signal name="ActionInvoked">
|
||||
<arg type="u"/>
|
||||
<arg type="s"/>
|
||||
</signal>
|
||||
</interface>;
|
||||
const FdoNotificationsIface = '<node> \
|
||||
<interface name="org.freedesktop.Notifications"> \
|
||||
<method name="Notify"> \
|
||||
<arg type="s" direction="in"/> \
|
||||
<arg type="u" direction="in"/> \
|
||||
<arg type="s" direction="in"/> \
|
||||
<arg type="s" direction="in"/> \
|
||||
<arg type="s" direction="in"/> \
|
||||
<arg type="as" direction="in"/> \
|
||||
<arg type="a{sv}" direction="in"/> \
|
||||
<arg type="i" direction="in"/> \
|
||||
<arg type="u" direction="out"/> \
|
||||
</method> \
|
||||
<method name="CloseNotification"> \
|
||||
<arg type="u" direction="in"/> \
|
||||
</method> \
|
||||
<method name="GetCapabilities"> \
|
||||
<arg type="as" direction="out"/> \
|
||||
</method> \
|
||||
<method name="GetServerInformation"> \
|
||||
<arg type="s" direction="out"/> \
|
||||
<arg type="s" direction="out"/> \
|
||||
<arg type="s" direction="out"/> \
|
||||
<arg type="s" direction="out"/> \
|
||||
</method> \
|
||||
<signal name="NotificationClosed"> \
|
||||
<arg type="u"/> \
|
||||
<arg type="u"/> \
|
||||
</signal> \
|
||||
<signal name="ActionInvoked"> \
|
||||
<arg type="u"/> \
|
||||
<arg type="s"/> \
|
||||
</signal> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const NotificationClosedReason = {
|
||||
EXPIRED: 1,
|
||||
@ -103,131 +106,11 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
|
||||
'ibus-ui-gtk': 'keyboard'
|
||||
};
|
||||
|
||||
const NotificationGenericPolicy = new Lang.Class({
|
||||
Name: 'NotificationGenericPolicy',
|
||||
Extends: MessageTray.NotificationPolicy,
|
||||
const FdoNotificationDaemon = new Lang.Class({
|
||||
Name: 'FdoNotificationDaemon',
|
||||
|
||||
_init: function() {
|
||||
// Don't chain to parent, it would try setting
|
||||
// our properties to the defaults
|
||||
|
||||
this.id = 'generic';
|
||||
|
||||
this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' });
|
||||
this._masterSettings.connect('changed', Lang.bind(this, this._changed));
|
||||
},
|
||||
|
||||
store: function() { },
|
||||
|
||||
destroy: function() {
|
||||
this._masterSettings.run_dispose();
|
||||
},
|
||||
|
||||
_changed: function(settings, key) {
|
||||
this.emit('policy-changed', key);
|
||||
},
|
||||
|
||||
get enable() {
|
||||
return true;
|
||||
},
|
||||
|
||||
get enableSound() {
|
||||
return true;
|
||||
},
|
||||
|
||||
get showBanners() {
|
||||
return this._masterSettings.get_boolean('show-banners');
|
||||
},
|
||||
|
||||
get forceExpanded() {
|
||||
return false;
|
||||
},
|
||||
|
||||
get showInLockScreen() {
|
||||
return this._masterSettings.get_boolean('show-in-lock-screen');
|
||||
},
|
||||
|
||||
get detailsInLockScreen() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
const NotificationApplicationPolicy = new Lang.Class({
|
||||
Name: 'NotificationApplicationPolicy',
|
||||
Extends: MessageTray.NotificationPolicy,
|
||||
|
||||
_init: function(id) {
|
||||
// Don't chain to parent, it would try setting
|
||||
// our properties to the defaults
|
||||
|
||||
this.id = id;
|
||||
this._canonicalId = this._canonicalizeId(id)
|
||||
|
||||
this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' });
|
||||
this._settings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications.application',
|
||||
path: '/org/gnome/desktop/notifications/application/' + this._canonicalId + '/' });
|
||||
|
||||
this._masterSettings.connect('changed', Lang.bind(this, this._changed));
|
||||
this._settings.connect('changed', Lang.bind(this, this._changed));
|
||||
},
|
||||
|
||||
store: function() {
|
||||
this._settings.set_string('application-id', this.id + '.desktop');
|
||||
|
||||
let apps = this._masterSettings.get_strv('application-children');
|
||||
if (apps.indexOf(this._canonicalId) < 0) {
|
||||
apps.push(this._canonicalId);
|
||||
this._masterSettings.set_strv('application-children', apps);
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this._masterSettings.run_dispose();
|
||||
this._settings.run_dispose();
|
||||
},
|
||||
|
||||
_changed: function(settings, key) {
|
||||
this.emit('policy-changed', key);
|
||||
},
|
||||
|
||||
_canonicalizeId: function(id) {
|
||||
// Keys are restricted to lowercase alphanumeric characters and dash,
|
||||
// and two dashes cannot be in succession
|
||||
return id.toLowerCase().replace(/[^a-z0-9\-]/g, '-').replace(/--+/g, '-');
|
||||
},
|
||||
|
||||
get enable() {
|
||||
return this._settings.get_boolean('enable');
|
||||
},
|
||||
|
||||
get enableSound() {
|
||||
return this._settings.get_boolean('enable-sound-alerts');
|
||||
},
|
||||
|
||||
get showBanners() {
|
||||
return this._masterSettings.get_boolean('show-banners') &&
|
||||
this._settings.get_boolean('show-banners');
|
||||
},
|
||||
|
||||
get forceExpanded() {
|
||||
return this._settings.get_boolean('force-expanded');
|
||||
},
|
||||
|
||||
get showInLockScreen() {
|
||||
return this._masterSettings.get_boolean('show-in-lock-screen') &&
|
||||
this._settings.get_boolean('show-in-lock-screen');
|
||||
},
|
||||
|
||||
get detailsInLockScreen() {
|
||||
return this._settings.get_boolean('details-in-lock-screen');
|
||||
}
|
||||
});
|
||||
|
||||
const NotificationDaemon = new Lang.Class({
|
||||
Name: 'NotificationDaemon',
|
||||
|
||||
_init: function() {
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(NotificationDaemonIface, this);
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(FdoNotificationsIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
|
||||
|
||||
this._sources = [];
|
||||
@ -235,6 +118,8 @@ const NotificationDaemon = new Lang.Class({
|
||||
this._notifications = {};
|
||||
this._busProxy = new Bus();
|
||||
|
||||
this._nextNotificationId = 1;
|
||||
|
||||
this._trayManager = new Shell.TrayManager();
|
||||
this._trayIconAddedId = this._trayManager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
|
||||
this._trayIconRemovedId = this._trayManager.connect('tray-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
|
||||
@ -333,7 +218,7 @@ const NotificationDaemon = new Lang.Class({
|
||||
}
|
||||
}
|
||||
|
||||
let source = new Source(title, pid, sender, trayIcon, ndata ? ndata.hints['desktop-entry'] : null);
|
||||
let source = new FdoNotificationDaemonSource(title, pid, sender, trayIcon, ndata ? ndata.hints['desktop-entry'] : null);
|
||||
source.setTransient(isForTransientNotification);
|
||||
|
||||
if (!isForTransientNotification) {
|
||||
@ -372,7 +257,7 @@ const NotificationDaemon = new Lang.Class({
|
||||
hints['category'] == 'presence.offline')) {
|
||||
// Ignore replacesId since we already sent back a
|
||||
// NotificationClosed for that id.
|
||||
id = nextNotificationId++;
|
||||
id = this._nextNotificationId++;
|
||||
Mainloop.idle_add(Lang.bind(this,
|
||||
function () {
|
||||
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
|
||||
@ -396,12 +281,13 @@ const NotificationDaemon = new Lang.Class({
|
||||
if (!hints['image-path'] && hints['image_path'])
|
||||
hints['image-path'] = hints['image_path']; // version 1.1 of the spec
|
||||
|
||||
if (!hints['image-data'])
|
||||
if (!hints['image-data']) {
|
||||
if (hints['image_data'])
|
||||
hints['image-data'] = hints['image_data']; // version 1.1 of the spec
|
||||
else if (hints['icon_data'] && !hints['image-path'])
|
||||
// early versions of the spec; 'icon_data' should only be used if 'image-path' is not available
|
||||
hints['image-data'] = hints['icon_data'];
|
||||
}
|
||||
|
||||
let ndata = { appName: appName,
|
||||
icon: icon,
|
||||
@ -415,7 +301,7 @@ const NotificationDaemon = new Lang.Class({
|
||||
ndata.notification = this._notifications[replacesId].notification;
|
||||
} else {
|
||||
replacesId = 0;
|
||||
ndata.id = id = nextNotificationId++;
|
||||
ndata.id = id = this._nextNotificationId++;
|
||||
}
|
||||
this._notifications[id] = ndata;
|
||||
|
||||
@ -470,6 +356,19 @@ const NotificationDaemon = new Lang.Class({
|
||||
return invocation.return_value(GLib.Variant.new('(u)', [id]));
|
||||
},
|
||||
|
||||
_makeButton: function(id, label, useActionIcons) {
|
||||
let button = new St.Button({ can_focus: true });
|
||||
let iconName = id.endsWith('-symbolic') ? id : id + '-symbolic';
|
||||
if (useActionIcons && Gtk.IconTheme.get_default().has_icon(iconName)) {
|
||||
button.add_style_class_name('notification-icon-button');
|
||||
button.child = new St.Icon({ icon_name: iconName });
|
||||
} else {
|
||||
button.add_style_class_name('notification-button');
|
||||
button.label = label;
|
||||
}
|
||||
return button;
|
||||
},
|
||||
|
||||
_notifyForSource: function(source, ndata) {
|
||||
let [id, icon, summary, body, actions, hints, notification] =
|
||||
[ndata.id, ndata.icon, ndata.summary, ndata.body,
|
||||
@ -495,10 +394,6 @@ const NotificationDaemon = new Lang.Class({
|
||||
}
|
||||
this._emitNotificationClosed(ndata.id, notificationClosedReason);
|
||||
}));
|
||||
notification.connect('action-invoked', Lang.bind(this,
|
||||
function(n, actionId) {
|
||||
this._emitActionInvoked(ndata.id, actionId);
|
||||
}));
|
||||
}
|
||||
|
||||
// Mark music notifications so they can be shown in the screen shield
|
||||
@ -532,18 +427,33 @@ const NotificationDaemon = new Lang.Class({
|
||||
soundName: hints['sound-name'] });
|
||||
notification.setImage(image);
|
||||
|
||||
let hasDefaultAction = false;
|
||||
|
||||
if (actions.length) {
|
||||
notification.setUseActionIcons(hints['action-icons'] == true);
|
||||
let useActionIcons = (hints['action-icons'] == true);
|
||||
|
||||
for (let i = 0; i < actions.length - 1; i += 2) {
|
||||
if (actions[i] == 'default')
|
||||
notification.connect('clicked', Lang.bind(this,
|
||||
function() {
|
||||
this._emitActionInvoked(ndata.id, "default");
|
||||
}));
|
||||
else
|
||||
notification.addButton(actions[i], actions[i + 1]);
|
||||
let [actionId, label] = [actions[i], actions[i+1]];
|
||||
if (actionId == 'default') {
|
||||
hasDefaultAction = true;
|
||||
} else {
|
||||
notification.addButton(this._makeButton(actionId, label, useActionIcons), Lang.bind(this, function() {
|
||||
this._emitActionInvoked(ndata.id, actionId);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasDefaultAction) {
|
||||
notification.connect('clicked', Lang.bind(this, function() {
|
||||
this._emitActionInvoked(ndata.id, 'default');
|
||||
}));
|
||||
} else {
|
||||
notification.connect('clicked', Lang.bind(this, function() {
|
||||
source.open();
|
||||
}));
|
||||
}
|
||||
|
||||
switch (hints.urgency) {
|
||||
case Urgency.LOW:
|
||||
notification.setUrgency(MessageTray.Urgency.LOW);
|
||||
@ -636,8 +546,8 @@ const NotificationDaemon = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
const Source = new Lang.Class({
|
||||
Name: 'NotificationDaemonSource',
|
||||
const FdoNotificationDaemonSource = new Lang.Class({
|
||||
Name: 'FdoNotificationDaemonSource',
|
||||
Extends: MessageTray.Source,
|
||||
|
||||
_init: function(title, pid, sender, trayIcon, appId) {
|
||||
@ -674,9 +584,9 @@ const Source = new Lang.Class({
|
||||
_createPolicy: function() {
|
||||
if (this.app) {
|
||||
let id = this.app.get_id().replace(/\.desktop$/,'');
|
||||
return new NotificationApplicationPolicy(id);
|
||||
return new MessageTray.NotificationApplicationPolicy(id);
|
||||
} else {
|
||||
return new NotificationGenericPolicy();
|
||||
return new MessageTray.NotificationGenericPolicy();
|
||||
}
|
||||
},
|
||||
|
||||
@ -752,22 +662,6 @@ const Source = new Lang.Class({
|
||||
return null;
|
||||
},
|
||||
|
||||
_setApp: function(appId) {
|
||||
if (this.app)
|
||||
return;
|
||||
|
||||
this.app = this._getApp(appId);
|
||||
if (!this.app)
|
||||
return;
|
||||
|
||||
// Only override the icon if we were previously using
|
||||
// notification-based icons (ie, not a trayicon) or if it was unset before
|
||||
if (!this.trayIcon) {
|
||||
this.useNotificationIcon = false;
|
||||
this.iconUpdated();
|
||||
}
|
||||
},
|
||||
|
||||
setTitle: function(title) {
|
||||
// Do nothing if .app is set, we don't want to override the
|
||||
// app name with whatever is provided through libnotify (usually
|
||||
@ -778,9 +672,9 @@ const Source = new Lang.Class({
|
||||
this.parent(title);
|
||||
},
|
||||
|
||||
open: function(notification) {
|
||||
this.destroyNonResidentNotifications();
|
||||
open: function() {
|
||||
this.openApp();
|
||||
this.destroyNonResidentNotifications();
|
||||
},
|
||||
|
||||
_lastNotificationRemoved: function() {
|
||||
@ -792,11 +686,8 @@ const Source = new Lang.Class({
|
||||
if (this.app == null)
|
||||
return;
|
||||
|
||||
let windows = this.app.get_windows();
|
||||
if (windows.length > 0) {
|
||||
let mostRecentWindow = windows[0];
|
||||
Main.activateWindow(mostRecentWindow);
|
||||
}
|
||||
this.app.activate();
|
||||
Main.overview.hide();
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
@ -823,3 +714,276 @@ const Source = new Lang.Class({
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const GtkNotificationDaemonNotification = new Lang.Class({
|
||||
Name: 'GtkNotificationDaemonNotification',
|
||||
Extends: MessageTray.Notification,
|
||||
|
||||
_init: function(source, notification) {
|
||||
this.parent(source);
|
||||
this._serialized = GLib.Variant.new('a{sv}', notification);
|
||||
|
||||
let { "title": title,
|
||||
"body": body,
|
||||
"icon": gicon,
|
||||
"urgent": urgent,
|
||||
"buttons": buttons,
|
||||
"default-action": defaultAction,
|
||||
"default-action-target": defaultActionTarget } = notification;
|
||||
|
||||
this.setUrgency(urgent.unpack() ? MessageTray.Urgency.CRITICAL
|
||||
: MessageTray.Urgency.NORMAL);
|
||||
|
||||
if (buttons) {
|
||||
buttons.deep_unpack().forEach(Lang.bind(this, function(button) {
|
||||
this.addAction(button.label.unpack(),
|
||||
Lang.bind(this, this._onButtonClicked, button));
|
||||
}));
|
||||
}
|
||||
|
||||
this._defaultAction = defaultAction ? defaultAction.unpack() : null;
|
||||
this._defaultActionTarget = defaultActionTarget;
|
||||
|
||||
this.update(title.unpack(), body ? body.unpack() : null,
|
||||
{ gicon: gicon ? Gio.icon_deserialize(gicon) : null });
|
||||
},
|
||||
|
||||
_activateAction: function(namespacedActionId, target) {
|
||||
if (namespacedActionId) {
|
||||
if (namespacedActionId.startsWith('app.')) {
|
||||
let actionId = namespacedActionId.slice('app.'.length);
|
||||
this.source.activateAction(actionId, target);
|
||||
}
|
||||
} else {
|
||||
this.source.open();
|
||||
}
|
||||
},
|
||||
|
||||
_onButtonClicked: function(button) {
|
||||
let { 'action': action, 'target': actionTarget } = button;
|
||||
this._activateAction(action.unpack(), actionTarget);
|
||||
},
|
||||
|
||||
_onClicked: function() {
|
||||
this._activateAction(this._defaultAction, this._defaultActionTarget);
|
||||
this.parent();
|
||||
},
|
||||
|
||||
serialize: function() {
|
||||
return this._serialized;
|
||||
},
|
||||
});
|
||||
|
||||
const FdoApplicationIface = '<node> \
|
||||
<interface name="org.freedesktop.Application"> \
|
||||
<method name="ActivateAction"> \
|
||||
<arg type="s" direction="in" /> \
|
||||
<arg type="av" direction="in" /> \
|
||||
<arg type="a{sv}" direction="in" /> \
|
||||
</method> \
|
||||
<method name="Activate"> \
|
||||
<arg type="a{sv}" direction="in" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
const FdoApplicationProxy = Gio.DBusProxy.makeProxyWrapper(FdoApplicationIface);
|
||||
|
||||
function objectPathFromAppId(appId) {
|
||||
return '/' + appId.replace(/\./g, '/');
|
||||
}
|
||||
|
||||
function getPlatformData() {
|
||||
let startupId = GLib.Variant.new('s', '_TIME' + global.get_current_time());
|
||||
return { "desktop-startup-id": startupId };
|
||||
}
|
||||
|
||||
function InvalidAppError() {}
|
||||
|
||||
const GtkNotificationDaemonAppSource = new Lang.Class({
|
||||
Name: 'GtkNotificationDaemonAppSource',
|
||||
Extends: MessageTray.Source,
|
||||
|
||||
_init: function(appId) {
|
||||
this._appId = appId;
|
||||
this._objectPath = objectPathFromAppId(appId);
|
||||
|
||||
this._app = Shell.AppSystem.get_default().lookup_app(appId + '.desktop');
|
||||
if (!this._app)
|
||||
throw new InvalidAppError();
|
||||
|
||||
this._notifications = {};
|
||||
|
||||
this.parent(this._app.get_name());
|
||||
},
|
||||
|
||||
createIcon: function(size) {
|
||||
return this._app.create_icon_texture(size);
|
||||
},
|
||||
|
||||
_createPolicy: function() {
|
||||
return new MessageTray.NotificationApplicationPolicy(this._appId);
|
||||
},
|
||||
|
||||
_createApp: function() {
|
||||
return new FdoApplicationProxy(Gio.DBus.session, this._appId, this._objectPath);
|
||||
},
|
||||
|
||||
activateAction: function(actionId, target) {
|
||||
let app = this._createApp();
|
||||
app.ActivateActionRemote(actionId, target ? [target] : [], getPlatformData());
|
||||
},
|
||||
|
||||
open: function() {
|
||||
let app = this._createApp();
|
||||
app.ActivateRemote(getPlatformData());
|
||||
},
|
||||
|
||||
addNotification: function(notificationId, notificationParams, showBanner) {
|
||||
if (this._notifications[notificationId])
|
||||
this._notifications[notificationId].destroy();
|
||||
|
||||
let notification = new GtkNotificationDaemonNotification(this, notificationParams);
|
||||
notification.connect('destroy', Lang.bind(this, function() {
|
||||
delete this._notifications[notificationId];
|
||||
}));
|
||||
this._notifications[notificationId] = notification;
|
||||
|
||||
if (showBanner)
|
||||
this.notify(notification);
|
||||
else
|
||||
this.pushNotification(notification);
|
||||
},
|
||||
|
||||
removeNotification: function(notificationId) {
|
||||
if (this._notifications[notificationId])
|
||||
this._notifications[notificationId].destroy(MessageTray.NotificationDestroyedReason.SOURCE_CLOSED);
|
||||
},
|
||||
|
||||
serialize: function() {
|
||||
let notifications = [];
|
||||
for (let notificationId in this._notifications) {
|
||||
let notification = this._notifications[notificationId];
|
||||
notifications.push([notificationId, notification.serialize()]);
|
||||
}
|
||||
return [this._appId, notifications];
|
||||
},
|
||||
});
|
||||
|
||||
const GtkNotificationsIface = '<node> \
|
||||
<interface name="org.gtk.Notifications"> \
|
||||
<method name="AddNotification"> \
|
||||
<arg type="s" direction="in" /> \
|
||||
<arg type="s" direction="in" /> \
|
||||
<arg type="a{sv}" direction="in" /> \
|
||||
</method> \
|
||||
<method name="RemoveNotification"> \
|
||||
<arg type="s" direction="in" /> \
|
||||
<arg type="s" direction="in" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const GtkNotificationDaemon = new Lang.Class({
|
||||
Name: 'GtkNotificationDaemon',
|
||||
|
||||
_init: function() {
|
||||
this._sources = {};
|
||||
|
||||
this._loadNotifications();
|
||||
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GtkNotificationsIface, this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/org/gtk/Notifications');
|
||||
|
||||
Gio.DBus.session.own_name('org.gtk.Notifications', Gio.BusNameOwnerFlags.REPLACE, null, null);
|
||||
},
|
||||
|
||||
_ensureAppSource: function(appId) {
|
||||
if (this._sources[appId])
|
||||
return this._sources[appId];
|
||||
|
||||
let source = new GtkNotificationDaemonAppSource(appId);
|
||||
|
||||
source.connect('destroy', Lang.bind(this, function() {
|
||||
delete this._sources[appId];
|
||||
this._saveNotifications();
|
||||
}));
|
||||
source.connect('count-updated', Lang.bind(this, this._saveNotifications));
|
||||
Main.messageTray.add(source);
|
||||
this._sources[appId] = source;
|
||||
return source;
|
||||
},
|
||||
|
||||
_loadNotifications: function() {
|
||||
this._isLoading = true;
|
||||
|
||||
let value = global.get_persistent_state('a(sa(sv))', 'notifications');
|
||||
if (value) {
|
||||
let sources = value.deep_unpack();
|
||||
sources.forEach(Lang.bind(this, function([appId, notifications]) {
|
||||
if (notifications.length == 0)
|
||||
return;
|
||||
|
||||
let source;
|
||||
try {
|
||||
source = this._ensureAppSource(appId);
|
||||
} catch(e if e instanceof InvalidAppError) {
|
||||
return;
|
||||
}
|
||||
|
||||
notifications.forEach(function([notificationId, notification]) {
|
||||
source.addNotification(notificationId, notification.deep_unpack(), false);
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
this._isLoading = false;
|
||||
},
|
||||
|
||||
_saveNotifications: function() {
|
||||
if (this._isLoading)
|
||||
return;
|
||||
|
||||
let sources = [];
|
||||
for (let appId in this._sources) {
|
||||
let source = this._sources[appId];
|
||||
sources.push(source.serialize());
|
||||
}
|
||||
|
||||
global.set_persistent_state('notifications', new GLib.Variant('a(sa(sv))', sources));
|
||||
},
|
||||
|
||||
AddNotificationAsync: function(params, invocation) {
|
||||
let [appId, notificationId, notification] = params;
|
||||
|
||||
let source;
|
||||
try {
|
||||
source = this._ensureAppSource(appId);
|
||||
} catch(e if e instanceof InvalidAppError) {
|
||||
invocation.return_dbus_error('org.gtk.Notifications.InvalidApp', 'The app by ID "%s" could not be found'.format(appId));
|
||||
return;
|
||||
}
|
||||
|
||||
source.addNotification(notificationId, notification, true);
|
||||
|
||||
invocation.return_value(null);
|
||||
},
|
||||
|
||||
RemoveNotificationAsync: function(params, invocation) {
|
||||
let [appId, notificationId] = params;
|
||||
let source = this._sources[appId];
|
||||
if (source)
|
||||
source.removeNotification(notificationId);
|
||||
|
||||
invocation.return_value(null);
|
||||
},
|
||||
});
|
||||
|
||||
const NotificationDaemon = new Lang.Class({
|
||||
Name: 'NotificationDaemon',
|
||||
|
||||
_init: function() {
|
||||
this._fdoNotificationDaemon = new FdoNotificationDaemon();
|
||||
this._gtkNotificationDaemon = new GtkNotificationDaemon();
|
||||
},
|
||||
});
|
||||
|
@ -78,10 +78,8 @@ const ShellInfo = new Lang.Class({
|
||||
}
|
||||
|
||||
this._undoCallback = undoCallback;
|
||||
if (undoCallback) {
|
||||
notification.addButton('system-undo', _("Undo"));
|
||||
notification.connect('action-invoked', Lang.bind(this, this._onUndoClicked));
|
||||
}
|
||||
if (undoCallback)
|
||||
notification.addAction(_("Undo"), Lang.bind(this, this._onUndoClicked));
|
||||
|
||||
this._source.notify(notification);
|
||||
}
|
||||
@ -148,7 +146,7 @@ const Overview = new Lang.Class({
|
||||
// Dash elements, or mouseover handlers in the workspaces.
|
||||
this._coverPane = new Clutter.Actor({ opacity: 0,
|
||||
reactive: true });
|
||||
this._stack.add_actor(this._coverPane);
|
||||
Main.layoutManager.overviewGroup.add_child(this._coverPane);
|
||||
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
|
||||
|
||||
this._stack.add_actor(this._overview);
|
||||
|
@ -55,18 +55,21 @@ const SlideLayout = new Lang.Class({
|
||||
vfunc_allocate: function(container, box, flags) {
|
||||
let child = container.get_first_child();
|
||||
|
||||
let [, , natWidth, natHeight] = child.get_preferred_size();
|
||||
let availWidth = Math.round(box.x2 - box.x1);
|
||||
let availHeight = Math.round(box.y2 - box.y1);
|
||||
let [, natWidth] = child.get_preferred_width(availHeight);
|
||||
|
||||
// Align the actor inside the clipped box, as the actor's alignment
|
||||
// flags only determine what to do if the allocated box is bigger
|
||||
// than the actor's box.
|
||||
let realDirection = getRtlSlideDirection(this._direction, child);
|
||||
let translationX = (realDirection == SlideDirection.LEFT) ?
|
||||
(availWidth - natWidth) : (natWidth - availWidth);
|
||||
let alignX = (realDirection == SlideDirection.LEFT) ? (availWidth - natWidth) : 0;
|
||||
|
||||
let actorBox = new Clutter.ActorBox({ x1: translationX,
|
||||
y1: 0,
|
||||
x2: child.x_expand ? availWidth : natWidth,
|
||||
y2: child.y_expand ? availHeight : natHeight });
|
||||
let actorBox = new Clutter.ActorBox();
|
||||
actorBox.x1 = alignX;
|
||||
actorBox.x2 = actorBox.x1 + child.x_expand ? availWidth : natWidth;
|
||||
actorBox.y1 = 0;
|
||||
actorBox.y2 = actorBox.y1 + availHeight;
|
||||
|
||||
child.allocate(actorBox, flags);
|
||||
},
|
||||
@ -236,11 +239,6 @@ const ThumbnailsSlider = new Lang.Class({
|
||||
|
||||
this._thumbnailsBox = thumbnailsBox;
|
||||
|
||||
// SlideLayout reads the actor's expand flags to decide
|
||||
// whether to allocate the natural size to its child, or the whole
|
||||
// available allocation
|
||||
this._thumbnailsBox.actor.y_expand = true;
|
||||
|
||||
this.actor.request_mode = Clutter.RequestMode.WIDTH_FOR_HEIGHT;
|
||||
this.actor.reactive = true;
|
||||
this.actor.track_hover = true;
|
||||
@ -324,7 +322,6 @@ const DashSlider = new Lang.Class({
|
||||
// whether to allocate the natural size to its child, or the whole
|
||||
// available allocation
|
||||
this._dash.actor.x_expand = true;
|
||||
this._dash.actor.y_expand = true;
|
||||
|
||||
this.actor.x_align = Clutter.ActorAlign.START;
|
||||
this.actor.y_expand = true;
|
||||
@ -504,6 +501,17 @@ const MessagesIndicator = new Lang.Class({
|
||||
}
|
||||
});
|
||||
|
||||
const ControlsLayout = new Lang.Class({
|
||||
Name: 'ControlsLayout',
|
||||
Extends: Clutter.BinLayout,
|
||||
Signals: { 'allocation-changed': { flags: GObject.SignalFlags.RUN_LAST } },
|
||||
|
||||
vfunc_allocate: function(container, box, flags) {
|
||||
this.parent(container, box, flags);
|
||||
this.emit('allocation-changed');
|
||||
}
|
||||
});
|
||||
|
||||
const ControlsManager = new Lang.Class({
|
||||
Name: 'ControlsManager',
|
||||
|
||||
@ -524,7 +532,8 @@ const ControlsManager = new Lang.Class({
|
||||
this._indicator = new MessagesIndicator(this.viewSelector);
|
||||
this.indicatorActor = this._indicator.actor;
|
||||
|
||||
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(),
|
||||
let layout = new ControlsLayout();
|
||||
this.actor = new St.Widget({ layout_manager: layout,
|
||||
reactive: true,
|
||||
x_expand: true, y_expand: true,
|
||||
clip_to_allocation: true });
|
||||
@ -539,7 +548,7 @@ const ControlsManager = new Lang.Class({
|
||||
expand: true });
|
||||
this._group.add_actor(this._thumbnailsSlider.actor);
|
||||
|
||||
this._group.connect('notify::allocation', Lang.bind(this, this._updateWorkspacesGeometry));
|
||||
layout.connect('allocation-changed', Lang.bind(this, this._updateWorkspacesGeometry));
|
||||
|
||||
Main.overview.connect('showing', Lang.bind(this, this._updateSpacerVisibility));
|
||||
Main.overview.connect('item-drag-begin', Lang.bind(this,
|
||||
|
@ -213,9 +213,7 @@ const AppMenuButton = new Lang.Class({
|
||||
this._label = new TextShadower();
|
||||
this._label.actor.y_align = Clutter.ActorAlign.CENTER;
|
||||
this._hbox.add_actor(this._label.actor);
|
||||
this._arrow = new St.Label({ text: '\u25BE',
|
||||
y_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
this._arrow = PopupMenu.unicodeArrow(St.Side.BOTTOM);
|
||||
this._hbox.add_actor(this._arrow);
|
||||
|
||||
this._iconBottomClip = 0;
|
||||
@ -611,6 +609,7 @@ const ActivitiesButton = new Lang.Class({
|
||||
|
||||
_onButtonRelease: function() {
|
||||
Main.overview.toggle();
|
||||
this.menu.close();
|
||||
},
|
||||
|
||||
_onKeyRelease: function(actor, event) {
|
||||
@ -804,7 +803,7 @@ const AggregateMenu = new Lang.Class({
|
||||
Extends: PanelMenu.Button,
|
||||
|
||||
_init: function() {
|
||||
this.parent(0.0, _("Settings Menu"), false);
|
||||
this.parent(0.0, _("Settings"), false);
|
||||
this.menu.actor.add_style_class_name('aggregate-menu');
|
||||
|
||||
this._indicators = new St.BoxLayout({ style_class: 'panel-status-indicators-box' });
|
||||
@ -832,9 +831,7 @@ const AggregateMenu = new Lang.Class({
|
||||
this._indicators.add_child(this._rfkill.indicators);
|
||||
this._indicators.add_child(this._volume.indicators);
|
||||
this._indicators.add_child(this._power.indicators);
|
||||
this._indicators.add_child(new St.Label({ text: '\u25BE',
|
||||
y_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER }));
|
||||
this._indicators.add_child(PopupMenu.unicodeArrow(St.Side.BOTTOM));
|
||||
|
||||
this.menu.addMenuItem(this._volume.menu);
|
||||
this.menu.addMenuItem(this._brightness.menu);
|
||||
|
@ -42,6 +42,33 @@ function isPopupMenuItemVisible(child) {
|
||||
return child.visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* @side Side to which the arrow points.
|
||||
*/
|
||||
function unicodeArrow(side) {
|
||||
let arrowChar;
|
||||
switch (side) {
|
||||
case St.Side.TOP:
|
||||
arrowChar = '\u25B4';
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
arrowChar = '\u25B8';
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
arrowChar = '\u25BE';
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
arrowChar = '\u25C2';
|
||||
break;
|
||||
}
|
||||
|
||||
return new St.Label({ text: arrowChar,
|
||||
style_class: 'unicode-arrow',
|
||||
accessible_role: Atk.Role.ARROW,
|
||||
y_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
}
|
||||
|
||||
const PopupBaseMenuItem = new Lang.Class({
|
||||
Name: 'PopupBaseMenuItem',
|
||||
|
||||
@ -948,18 +975,21 @@ const PopupSubMenuMenuItem = new Lang.Class({
|
||||
this.actor.add_child(this.icon);
|
||||
}
|
||||
|
||||
this.label = new St.Label({ text: text });
|
||||
this.label = new St.Label({ text: text,
|
||||
y_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
this.actor.add_child(this.label);
|
||||
this.actor.label_actor = this.label;
|
||||
|
||||
let expander = new St.Bin({ style_class: 'popup-menu-item-expander' });
|
||||
this.actor.add(expander, { expand: true });
|
||||
|
||||
this.status = new St.Label({ style_class: 'popup-status-menu-item' });
|
||||
this.status = new St.Label({ style_class: 'popup-status-menu-item',
|
||||
y_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER });
|
||||
this.actor.add_child(this.status);
|
||||
|
||||
this._triangle = new St.Label({ text: '\u25B8',
|
||||
style_class: 'popup-submenu-menu-item-triangle' });
|
||||
this._triangle = unicodeArrow(St.Side.RIGHT);
|
||||
this._triangle.pivot_point = new Clutter.Point({ x: 0.5, y: 0.6 });
|
||||
|
||||
this._triangleBin = new St.Widget({ y_expand: true,
|
||||
@ -969,6 +999,7 @@ const PopupSubMenuMenuItem = new Lang.Class({
|
||||
this._triangleBin.set_scale(-1.0, 1.0);
|
||||
|
||||
this.actor.add_child(this._triangleBin);
|
||||
this.actor.add_accessible_state (Atk.StateType.EXPANDABLE);
|
||||
|
||||
this.menu = new PopupSubMenu(this.actor, this._triangle);
|
||||
this.menu.connect('open-state-changed', Lang.bind(this, this._subMenuOpenStateChanged));
|
||||
@ -990,9 +1021,11 @@ const PopupSubMenuMenuItem = new Lang.Class({
|
||||
if (open) {
|
||||
this.actor.add_style_pseudo_class('open');
|
||||
this._getTopMenu()._setOpenedSubMenu(this.menu);
|
||||
this.actor.add_accessible_state (Atk.StateType.EXPANDED);
|
||||
} else {
|
||||
this.actor.remove_style_pseudo_class('open');
|
||||
this._getTopMenu()._setOpenedSubMenu(null);
|
||||
this.actor.remove_accessible_state (Atk.StateType.EXPANDED);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -11,52 +11,56 @@ const Search = imports.ui.search;
|
||||
|
||||
const KEY_FILE_GROUP = 'Shell Search Provider';
|
||||
|
||||
const SearchProviderIface = <interface name="org.gnome.Shell.SearchProvider">
|
||||
<method name="GetInitialResultSet">
|
||||
<arg type="as" direction="in" />
|
||||
<arg type="as" direction="out" />
|
||||
</method>
|
||||
<method name="GetSubsearchResultSet">
|
||||
<arg type="as" direction="in" />
|
||||
<arg type="as" direction="in" />
|
||||
<arg type="as" direction="out" />
|
||||
</method>
|
||||
<method name="GetResultMetas">
|
||||
<arg type="as" direction="in" />
|
||||
<arg type="aa{sv}" direction="out" />
|
||||
</method>
|
||||
<method name="ActivateResult">
|
||||
<arg type="s" direction="in" />
|
||||
</method>
|
||||
</interface>;
|
||||
const SearchProviderIface = '<node> \
|
||||
<interface name="org.gnome.Shell.SearchProvider"> \
|
||||
<method name="GetInitialResultSet"> \
|
||||
<arg type="as" direction="in" /> \
|
||||
<arg type="as" direction="out" /> \
|
||||
</method> \
|
||||
<method name="GetSubsearchResultSet"> \
|
||||
<arg type="as" direction="in" /> \
|
||||
<arg type="as" direction="in" /> \
|
||||
<arg type="as" direction="out" /> \
|
||||
</method> \
|
||||
<method name="GetResultMetas"> \
|
||||
<arg type="as" direction="in" /> \
|
||||
<arg type="aa{sv}" direction="out" /> \
|
||||
</method> \
|
||||
<method name="ActivateResult"> \
|
||||
<arg type="s" direction="in" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const SearchProvider2Iface = <interface name="org.gnome.Shell.SearchProvider2">
|
||||
<method name="GetInitialResultSet">
|
||||
<arg type="as" direction="in" />
|
||||
<arg type="as" direction="out" />
|
||||
</method>
|
||||
<method name="GetSubsearchResultSet">
|
||||
<arg type="as" direction="in" />
|
||||
<arg type="as" direction="in" />
|
||||
<arg type="as" direction="out" />
|
||||
</method>
|
||||
<method name="GetResultMetas">
|
||||
<arg type="as" direction="in" />
|
||||
<arg type="aa{sv}" direction="out" />
|
||||
</method>
|
||||
<method name="ActivateResult">
|
||||
<arg type="s" direction="in" />
|
||||
<arg type="as" direction="in" />
|
||||
<arg type="u" direction="in" />
|
||||
</method>
|
||||
<method name="LaunchSearch">
|
||||
<arg type="as" direction="in" />
|
||||
<arg type="u" direction="in" />
|
||||
</method>
|
||||
</interface>;
|
||||
const SearchProvider2Iface = '<node> \
|
||||
<interface name="org.gnome.Shell.SearchProvider2"> \
|
||||
<method name="GetInitialResultSet"> \
|
||||
<arg type="as" direction="in" /> \
|
||||
<arg type="as" direction="out" /> \
|
||||
</method> \
|
||||
<method name="GetSubsearchResultSet"> \
|
||||
<arg type="as" direction="in" /> \
|
||||
<arg type="as" direction="in" /> \
|
||||
<arg type="as" direction="out" /> \
|
||||
</method> \
|
||||
<method name="GetResultMetas"> \
|
||||
<arg type="as" direction="in" /> \
|
||||
<arg type="aa{sv}" direction="out" /> \
|
||||
</method> \
|
||||
<method name="ActivateResult"> \
|
||||
<arg type="s" direction="in" /> \
|
||||
<arg type="as" direction="in" /> \
|
||||
<arg type="u" direction="in" /> \
|
||||
</method> \
|
||||
<method name="LaunchSearch"> \
|
||||
<arg type="as" direction="in" /> \
|
||||
<arg type="u" direction="in" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface);
|
||||
var SearchProvider2Proxy = Gio.DBusProxy.makeProxyWrapper(SearchProvider2Iface);
|
||||
var SearchProviderProxyInfo = Gio.DBusInterfaceInfo.new_for_xml(SearchProviderIface);
|
||||
var SearchProvider2ProxyInfo = Gio.DBusInterfaceInfo.new_for_xml(SearchProvider2Iface);
|
||||
|
||||
function loadRemoteSearchProviders(addProviderCallback) {
|
||||
let objectPaths = {};
|
||||
@ -172,12 +176,18 @@ function loadRemoteSearchProviders(addProviderCallback) {
|
||||
const RemoteSearchProvider = new Lang.Class({
|
||||
Name: 'RemoteSearchProvider',
|
||||
|
||||
_init: function(appInfo, dbusName, dbusPath, proxyType) {
|
||||
if (!proxyType)
|
||||
proxyType = SearchProviderProxy;
|
||||
_init: function(appInfo, dbusName, dbusPath, proxyInfo) {
|
||||
if (!proxyInfo)
|
||||
proxyInfo = SearchProviderProxyInfo;
|
||||
|
||||
this.proxy = new proxyType(Gio.DBus.session,
|
||||
dbusName, dbusPath, Lang.bind(this, this._onProxyConstructed));
|
||||
this.proxy = new Gio.DBusProxy({ g_bus_type: Gio.BusType.SESSION,
|
||||
g_name: dbusName,
|
||||
g_object_path: dbusPath,
|
||||
g_interface_info: proxyInfo,
|
||||
g_interface_name: proxyInfo.name,
|
||||
g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START_AT_CONSTRUCTION |
|
||||
Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
|
||||
this.proxy.init_async(GLib.PRIORITY_DEFAULT, null, null);
|
||||
|
||||
this.appInfo = appInfo;
|
||||
this.id = appInfo.get_id();
|
||||
@ -186,10 +196,6 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
this._cancellable = new Gio.Cancellable();
|
||||
},
|
||||
|
||||
_onProxyConstructed: function(proxy) {
|
||||
// Do nothing
|
||||
},
|
||||
|
||||
createIcon: function(size, meta) {
|
||||
let gicon;
|
||||
if (meta['icon']) {
|
||||
@ -207,40 +213,45 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
icon_size: size });
|
||||
},
|
||||
|
||||
filterResults: function(results, maxNumber) {
|
||||
if (results.length <= maxNumber)
|
||||
return results;
|
||||
|
||||
let regularResults = results.filter(function(r) { return !r.startsWith('special:'); });
|
||||
let specialResults = results.filter(function(r) { return r.startsWith('special:'); });
|
||||
|
||||
return regularResults.slice(0, maxNumber).concat(specialResults.slice(0, maxNumber));
|
||||
},
|
||||
|
||||
_getResultsFinished: function(results, error) {
|
||||
if (error)
|
||||
return;
|
||||
this.searchSystem.setResults(this, results[0]);
|
||||
if (error) {
|
||||
if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
log('Received error from DBus search provider %s: %s'.format(this.id, String(error)));
|
||||
} else {
|
||||
this.searchSystem.setResults(this, results[0]);
|
||||
}
|
||||
},
|
||||
|
||||
getInitialResultSet: function(terms) {
|
||||
this._cancellable.cancel();
|
||||
this._cancellable.reset();
|
||||
try {
|
||||
this.proxy.GetInitialResultSetRemote(terms,
|
||||
Lang.bind(this, this._getResultsFinished),
|
||||
this._cancellable);
|
||||
} catch(e) {
|
||||
log('Error calling GetInitialResultSet for provider %s: %s'.format(this.id, e.toString()));
|
||||
this.searchSystem.setResults(this, []);
|
||||
}
|
||||
this.proxy.GetInitialResultSetRemote(terms,
|
||||
Lang.bind(this, this._getResultsFinished),
|
||||
this._cancellable);
|
||||
},
|
||||
|
||||
getSubsearchResultSet: function(previousResults, newTerms) {
|
||||
this._cancellable.cancel();
|
||||
this._cancellable.reset();
|
||||
try {
|
||||
this.proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
|
||||
Lang.bind(this, this._getResultsFinished),
|
||||
this._cancellable);
|
||||
} catch(e) {
|
||||
log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.id, e.toString()));
|
||||
this.searchSystem.setResults(this, []);
|
||||
}
|
||||
this.proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
|
||||
Lang.bind(this, this._getResultsFinished),
|
||||
this._cancellable);
|
||||
},
|
||||
|
||||
_getResultMetasFinished: function(results, error, callback) {
|
||||
if (error) {
|
||||
if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
log('Received error from DBus search provider %s during GetResultMetas: %s'.format(this.id, String(error)));
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
@ -265,14 +276,9 @@ const RemoteSearchProvider = new Lang.Class({
|
||||
getResultMetas: function(ids, callback) {
|
||||
this._cancellable.cancel();
|
||||
this._cancellable.reset();
|
||||
try {
|
||||
this.proxy.GetResultMetasRemote(ids,
|
||||
Lang.bind(this, this._getResultMetasFinished, callback),
|
||||
this._cancellable);
|
||||
} catch(e) {
|
||||
log('Error calling GetResultMetas for provider %s: %s'.format(this.id, e.toString()));
|
||||
callback([]);
|
||||
}
|
||||
this.proxy.GetResultMetasRemote(ids,
|
||||
Lang.bind(this, this._getResultMetasFinished, callback),
|
||||
this._cancellable);
|
||||
},
|
||||
|
||||
activateResult: function(id) {
|
||||
@ -292,7 +298,7 @@ const RemoteSearchProvider2 = new Lang.Class({
|
||||
Extends: RemoteSearchProvider,
|
||||
|
||||
_init: function(appInfo, dbusName, dbusPath) {
|
||||
this.parent(appInfo, dbusName, dbusPath, SearchProvider2Proxy);
|
||||
this.parent(appInfo, dbusName, dbusPath, SearchProvider2ProxyInfo);
|
||||
|
||||
this.canLaunchSearch = true;
|
||||
},
|
||||
|
@ -19,6 +19,7 @@ const Background = imports.ui.background;
|
||||
const GnomeSession = imports.misc.gnomeSession;
|
||||
const Hash = imports.misc.hash;
|
||||
const Layout = imports.ui.layout;
|
||||
const OVirt = imports.gdm.oVirt;
|
||||
const LoginManager = imports.misc.loginManager;
|
||||
const Lightbox = imports.ui.lightbox;
|
||||
const Main = imports.ui.main;
|
||||
@ -545,6 +546,13 @@ const ScreenShield = new Lang.Class({
|
||||
this._liftShield(true, 0);
|
||||
}));
|
||||
|
||||
this._oVirtCredentialsManager = OVirt.getOVirtCredentialsManager();
|
||||
this._oVirtCredentialsManager.connect('user-authenticated',
|
||||
Lang.bind(this, function() {
|
||||
if (this._isLocked)
|
||||
this._liftShield(true, 0);
|
||||
}));
|
||||
|
||||
this._inhibitor = null;
|
||||
this._aboutToSuspend = false;
|
||||
this._loginManager = LoginManager.getLoginManager();
|
||||
@ -584,6 +592,7 @@ const ScreenShield = new Lang.Class({
|
||||
this._shortLightbox.connect('shown', Lang.bind(this, this._onShortLightboxShown));
|
||||
|
||||
this.idleMonitor = Meta.IdleMonitor.get_core();
|
||||
this._cursorTracker = Meta.CursorTracker.get_for_screen(global.screen);
|
||||
},
|
||||
|
||||
_createBackground: function(monitorIndex) {
|
||||
@ -953,7 +962,7 @@ const ScreenShield = new Lang.Class({
|
||||
this._hideLockScreenComplete();
|
||||
}
|
||||
|
||||
global.stage.show_cursor();
|
||||
this._cursorTracker.set_pointer_visible(true);
|
||||
},
|
||||
|
||||
_ensureUnlockDialog: function(onPrimary, allowCancel) {
|
||||
@ -1086,15 +1095,15 @@ const ScreenShield = new Lang.Class({
|
||||
|
||||
this._checkArrowAnimation();
|
||||
|
||||
let motionId = global.stage.connect('captured-event', function(stage, event) {
|
||||
let motionId = global.stage.connect('captured-event', Lang.bind(this, function(stage, event) {
|
||||
if (event.type() == Clutter.EventType.MOTION) {
|
||||
global.stage.show_cursor();
|
||||
this._cursorTracker.set_pointer_visible(true);
|
||||
global.stage.disconnect(motionId);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
global.stage.hide_cursor();
|
||||
}));
|
||||
this._cursorTracker.set_pointer_visible(false);
|
||||
|
||||
this._lockScreenState = MessageTray.State.SHOWN;
|
||||
this._lockScreenGroup.fixed_position_set = false;
|
||||
|
@ -9,27 +9,29 @@ const Signals = imports.signals;
|
||||
const Hash = imports.misc.hash;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const ScreencastIface = <interface name="org.gnome.Shell.Screencast">
|
||||
<method name="Screencast">
|
||||
<arg type="s" direction="in" name="file_template"/>
|
||||
<arg type="a{sv}" direction="in" name="options"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
<arg type="s" direction="out" name="filename_used"/>
|
||||
</method>
|
||||
<method name="ScreencastArea">
|
||||
<arg type="i" direction="in" name="x"/>
|
||||
<arg type="i" direction="in" name="y"/>
|
||||
<arg type="i" direction="in" name="width"/>
|
||||
<arg type="i" direction="in" name="height"/>
|
||||
<arg type="s" direction="in" name="file_template"/>
|
||||
<arg type="a{sv}" direction="in" name="options"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
<arg type="s" direction="out" name="filename_used"/>
|
||||
</method>
|
||||
<method name="StopScreencast">
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
</method>
|
||||
</interface>;
|
||||
const ScreencastIface = '<node> \
|
||||
<interface name="org.gnome.Shell.Screencast"> \
|
||||
<method name="Screencast"> \
|
||||
<arg type="s" direction="in" name="file_template"/> \
|
||||
<arg type="a{sv}" direction="in" name="options"/> \
|
||||
<arg type="b" direction="out" name="success"/> \
|
||||
<arg type="s" direction="out" name="filename_used"/> \
|
||||
</method> \
|
||||
<method name="ScreencastArea"> \
|
||||
<arg type="i" direction="in" name="x"/> \
|
||||
<arg type="i" direction="in" name="y"/> \
|
||||
<arg type="i" direction="in" name="width"/> \
|
||||
<arg type="i" direction="in" name="height"/> \
|
||||
<arg type="s" direction="in" name="file_template"/> \
|
||||
<arg type="a{sv}" direction="in" name="options"/> \
|
||||
<arg type="b" direction="out" name="success"/> \
|
||||
<arg type="s" direction="out" name="filename_used"/> \
|
||||
</method> \
|
||||
<method name="StopScreencast"> \
|
||||
<arg type="b" direction="out" name="success"/> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const ScreencastService = new Lang.Class({
|
||||
Name: 'ScreencastService',
|
||||
|
@ -6,6 +6,7 @@ const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
@ -14,45 +15,47 @@ const Lightbox = imports.ui.lightbox;
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const ScreenshotIface = <interface name="org.gnome.Shell.Screenshot">
|
||||
<method name="ScreenshotArea">
|
||||
<arg type="i" direction="in" name="x"/>
|
||||
<arg type="i" direction="in" name="y"/>
|
||||
<arg type="i" direction="in" name="width"/>
|
||||
<arg type="i" direction="in" name="height"/>
|
||||
<arg type="b" direction="in" name="flash"/>
|
||||
<arg type="s" direction="in" name="filename"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
<arg type="s" direction="out" name="filename_used"/>
|
||||
</method>
|
||||
<method name="ScreenshotWindow">
|
||||
<arg type="b" direction="in" name="include_frame"/>
|
||||
<arg type="b" direction="in" name="include_cursor"/>
|
||||
<arg type="b" direction="in" name="flash"/>
|
||||
<arg type="s" direction="in" name="filename"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
<arg type="s" direction="out" name="filename_used"/>
|
||||
</method>
|
||||
<method name="Screenshot">
|
||||
<arg type="b" direction="in" name="include_cursor"/>
|
||||
<arg type="b" direction="in" name="flash"/>
|
||||
<arg type="s" direction="in" name="filename"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
<arg type="s" direction="out" name="filename_used"/>
|
||||
</method>
|
||||
<method name="SelectArea">
|
||||
<arg type="i" direction="out" name="x"/>
|
||||
<arg type="i" direction="out" name="y"/>
|
||||
<arg type="i" direction="out" name="width"/>
|
||||
<arg type="i" direction="out" name="height"/>
|
||||
</method>
|
||||
<method name="FlashArea">
|
||||
<arg type="i" direction="in" name="x"/>
|
||||
<arg type="i" direction="in" name="y"/>
|
||||
<arg type="i" direction="in" name="width"/>
|
||||
<arg type="i" direction="in" name="height"/>
|
||||
</method>
|
||||
</interface>;
|
||||
const ScreenshotIface = '<node> \
|
||||
<interface name="org.gnome.Shell.Screenshot"> \
|
||||
<method name="ScreenshotArea"> \
|
||||
<arg type="i" direction="in" name="x"/> \
|
||||
<arg type="i" direction="in" name="y"/> \
|
||||
<arg type="i" direction="in" name="width"/> \
|
||||
<arg type="i" direction="in" name="height"/> \
|
||||
<arg type="b" direction="in" name="flash"/> \
|
||||
<arg type="s" direction="in" name="filename"/> \
|
||||
<arg type="b" direction="out" name="success"/> \
|
||||
<arg type="s" direction="out" name="filename_used"/> \
|
||||
</method> \
|
||||
<method name="ScreenshotWindow"> \
|
||||
<arg type="b" direction="in" name="include_frame"/> \
|
||||
<arg type="b" direction="in" name="include_cursor"/> \
|
||||
<arg type="b" direction="in" name="flash"/> \
|
||||
<arg type="s" direction="in" name="filename"/> \
|
||||
<arg type="b" direction="out" name="success"/> \
|
||||
<arg type="s" direction="out" name="filename_used"/> \
|
||||
</method> \
|
||||
<method name="Screenshot"> \
|
||||
<arg type="b" direction="in" name="include_cursor"/> \
|
||||
<arg type="b" direction="in" name="flash"/> \
|
||||
<arg type="s" direction="in" name="filename"/> \
|
||||
<arg type="b" direction="out" name="success"/> \
|
||||
<arg type="s" direction="out" name="filename_used"/> \
|
||||
</method> \
|
||||
<method name="SelectArea"> \
|
||||
<arg type="i" direction="out" name="x"/> \
|
||||
<arg type="i" direction="out" name="y"/> \
|
||||
<arg type="i" direction="out" name="width"/> \
|
||||
<arg type="i" direction="out" name="height"/> \
|
||||
</method> \
|
||||
<method name="FlashArea"> \
|
||||
<arg type="i" direction="in" name="x"/> \
|
||||
<arg type="i" direction="in" name="y"/> \
|
||||
<arg type="i" direction="in" name="width"/> \
|
||||
<arg type="i" direction="in" name="height"/> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const ScreenshotService = new Lang.Class({
|
||||
Name: 'ScreenshotService',
|
||||
@ -167,7 +170,7 @@ const SelectArea = new Lang.Class({
|
||||
if (!Main.pushModal(this._group) || this._group.visible)
|
||||
return;
|
||||
|
||||
global.set_cursor(Shell.Cursor.CROSSHAIR);
|
||||
global.screen.set_cursor(Meta.Cursor.CROSSHAIR);
|
||||
this._group.visible = true;
|
||||
},
|
||||
|
||||
@ -238,7 +241,7 @@ const SelectArea = new Lang.Class({
|
||||
function() {
|
||||
Main.popModal(this._group);
|
||||
this._group.destroy();
|
||||
global.unset_cursor();
|
||||
global.screen.set_cursor(Meta.Cursor.DEFAULT);
|
||||
|
||||
this.emit('finished', geometry);
|
||||
})
|
||||
|
@ -69,16 +69,18 @@ function waitLeisure() {
|
||||
};
|
||||
}
|
||||
|
||||
const PerfHelperIface = <interface name="org.gnome.Shell.PerfHelper">
|
||||
<method name="CreateWindow">
|
||||
<arg type="i" direction="in" />
|
||||
<arg type="i" direction="in" />
|
||||
<arg type="b" direction="in" />
|
||||
<arg type="b" direction="in" />
|
||||
</method>
|
||||
<method name="WaitWindows" />
|
||||
<method name="DestroyWindows" />
|
||||
</interface>;
|
||||
const PerfHelperIface = '<node> \
|
||||
<interface name="org.gnome.Shell.PerfHelper"> \
|
||||
<method name="CreateWindow"> \
|
||||
<arg type="i" direction="in" /> \
|
||||
<arg type="i" direction="in" /> \
|
||||
<arg type="b" direction="in" /> \
|
||||
<arg type="b" direction="in" /> \
|
||||
</method> \
|
||||
<method name="WaitWindows" /> \
|
||||
<method name="DestroyWindows" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
var PerfHelperProxy = Gio.DBusProxy.makeProxyWrapper(PerfHelperIface);
|
||||
function PerfHelper() {
|
||||
|
579
js/ui/search.js
@ -1,10 +1,26 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
const Atk = imports.gi.Atk;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
const IconGrid = imports.ui.iconGrid;
|
||||
const Main = imports.ui.main;
|
||||
const Overview = imports.ui.overview;
|
||||
const Separator = imports.ui.separator;
|
||||
const Search = imports.ui.search;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
|
||||
|
||||
const MAX_LIST_SEARCH_RESULTS_ROWS = 3;
|
||||
const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
|
||||
|
||||
const SearchSystem = new Lang.Class({
|
||||
Name: 'SearchSystem',
|
||||
|
||||
@ -82,24 +98,563 @@ const SearchSystem = new Lang.Class({
|
||||
if (isSubSearch) {
|
||||
for (let i = 0; i < this._providers.length; i++) {
|
||||
let [provider, previousResults] = previousResultsArr[i];
|
||||
try {
|
||||
results.push([provider, []]);
|
||||
provider.getSubsearchResultSet(previousResults, terms);
|
||||
} catch (error) {
|
||||
log('A ' + error.name + ' has occured in ' + provider.id + ': ' + error.message);
|
||||
}
|
||||
results.push([provider, []]);
|
||||
provider.getSubsearchResultSet(previousResults, terms);
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < this._providers.length; i++) {
|
||||
let provider = this._providers[i];
|
||||
try {
|
||||
results.push([provider, []]);
|
||||
provider.getInitialResultSet(terms);
|
||||
} catch (error) {
|
||||
log('A ' + error.name + ' has occured in ' + provider.id + ': ' + error.message);
|
||||
}
|
||||
results.push([provider, []]);
|
||||
provider.getInitialResultSet(terms);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(SearchSystem.prototype);
|
||||
|
||||
const MaxWidthBin = new Lang.Class({
|
||||
Name: 'MaxWidthBin',
|
||||
Extends: St.Bin,
|
||||
|
||||
vfunc_allocate: function(box, flags) {
|
||||
let themeNode = this.get_theme_node();
|
||||
let maxWidth = themeNode.get_max_width();
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let adjustedBox = box;
|
||||
|
||||
if (availWidth > maxWidth) {
|
||||
let excessWidth = availWidth - maxWidth;
|
||||
adjustedBox.x1 += Math.floor(excessWidth / 2);
|
||||
adjustedBox.x2 -= Math.floor(excessWidth / 2);
|
||||
}
|
||||
|
||||
this.parent(adjustedBox, flags);
|
||||
}
|
||||
});
|
||||
|
||||
const SearchResult = new Lang.Class({
|
||||
Name: 'SearchResult',
|
||||
|
||||
_init: function(provider, metaInfo, terms) {
|
||||
this.provider = provider;
|
||||
this.metaInfo = metaInfo;
|
||||
this.terms = terms;
|
||||
|
||||
this.actor = new St.Button({ reactive: true,
|
||||
can_focus: true,
|
||||
track_hover: true,
|
||||
x_align: St.Align.START,
|
||||
y_fill: true });
|
||||
|
||||
this.actor._delegate = this;
|
||||
this.actor.connect('clicked', Lang.bind(this, this.activate));
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
this.provider.activateResult(this.metaInfo.id, this.terms);
|
||||
Main.overview.toggle();
|
||||
},
|
||||
|
||||
setSelected: function(selected) {
|
||||
if (selected)
|
||||
this.actor.add_style_pseudo_class('selected');
|
||||
else
|
||||
this.actor.remove_style_pseudo_class('selected');
|
||||
}
|
||||
});
|
||||
|
||||
const ListSearchResult = new Lang.Class({
|
||||
Name: 'ListSearchResult',
|
||||
Extends: SearchResult,
|
||||
|
||||
ICON_SIZE: 64,
|
||||
|
||||
_init: function(provider, metaInfo, terms) {
|
||||
this.parent(provider, metaInfo, terms);
|
||||
|
||||
this.actor.style_class = 'list-search-result';
|
||||
this.actor.x_fill = true;
|
||||
|
||||
let content = new St.BoxLayout({ style_class: 'list-search-result-content',
|
||||
vertical: false });
|
||||
this.actor.set_child(content);
|
||||
|
||||
// An icon for, or thumbnail of, content
|
||||
let icon = this.metaInfo['createIcon'](this.ICON_SIZE);
|
||||
if (icon) {
|
||||
content.add(icon);
|
||||
}
|
||||
|
||||
let details = new St.BoxLayout({ vertical: true });
|
||||
content.add(details, { x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.MIDDLE });
|
||||
|
||||
let title = new St.Label({ style_class: 'list-search-result-title',
|
||||
text: this.metaInfo['name'] })
|
||||
details.add(title, { x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
this.actor.label_actor = title;
|
||||
|
||||
if (this.metaInfo['description']) {
|
||||
let description = new St.Label({ style_class: 'list-search-result-description' });
|
||||
description.clutter_text.set_markup(this.metaInfo['description']);
|
||||
details.add(description, { x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.END });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const GridSearchResult = new Lang.Class({
|
||||
Name: 'GridSearchResult',
|
||||
Extends: SearchResult,
|
||||
|
||||
_init: function(provider, metaInfo, terms) {
|
||||
this.parent(provider, metaInfo, terms);
|
||||
|
||||
this.actor.style_class = 'grid-search-result';
|
||||
|
||||
let content = provider.createResultObject(metaInfo, terms);
|
||||
let dragSource = null;
|
||||
|
||||
if (content == null) {
|
||||
let actor = new St.Bin();
|
||||
let icon = new IconGrid.BaseIcon(this.metaInfo['name'],
|
||||
{ createIcon: this.metaInfo['createIcon'] });
|
||||
actor.set_child(icon.actor);
|
||||
actor.label_actor = icon.label;
|
||||
dragSource = icon.icon;
|
||||
content = { actor: actor, icon: icon };
|
||||
} else {
|
||||
if (content._delegate && content._delegate.getDragActorSource)
|
||||
dragSource = content._delegate.getDragActorSource();
|
||||
}
|
||||
|
||||
this.actor.set_child(content.actor);
|
||||
this.actor.label_actor = content.actor.label_actor;
|
||||
this.icon = content.icon;
|
||||
|
||||
let draggable = DND.makeDraggable(this.actor);
|
||||
draggable.connect('drag-begin',
|
||||
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);
|
||||
}));
|
||||
|
||||
if (!dragSource)
|
||||
// not exactly right, but alignment problems are hard to notice
|
||||
dragSource = content;
|
||||
this._dragActorSource = dragSource;
|
||||
},
|
||||
|
||||
getDragActorSource: function() {
|
||||
return this._dragActorSource;
|
||||
},
|
||||
|
||||
getDragActor: function() {
|
||||
return this.metaInfo['createIcon'](Main.overview.dashIconSize);
|
||||
},
|
||||
|
||||
shellWorkspaceLaunch: function(params) {
|
||||
if (this.provider.dragActivateResult)
|
||||
this.provider.dragActivateResult(this.metaInfo.id, params);
|
||||
else
|
||||
this.provider.activateResult(this.metaInfo.id, this.terms);
|
||||
}
|
||||
});
|
||||
|
||||
const SearchResultsBase = new Lang.Class({
|
||||
Name: 'SearchResultsBase',
|
||||
|
||||
_init: function(provider) {
|
||||
this.provider = provider;
|
||||
|
||||
this._terms = [];
|
||||
|
||||
this.actor = new St.BoxLayout({ style_class: 'search-section',
|
||||
vertical: true });
|
||||
|
||||
this._resultDisplayBin = new St.Bin({ x_fill: true,
|
||||
y_fill: true });
|
||||
this.actor.add(this._resultDisplayBin, { expand: true });
|
||||
|
||||
let separator = new Separator.HorizontalSeparator({ style_class: 'search-section-separator' });
|
||||
this.actor.add(separator.actor);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.actor.destroy();
|
||||
this._terms = [];
|
||||
},
|
||||
|
||||
_clearResultDisplay: function() {
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
this._clearResultDisplay();
|
||||
this.actor.hide();
|
||||
},
|
||||
|
||||
_keyFocusIn: function(actor) {
|
||||
this.emit('key-focus-in', actor);
|
||||
},
|
||||
|
||||
_setMoreIconVisible: function(visible) {
|
||||
},
|
||||
|
||||
updateSearch: function(providerResults, terms, callback) {
|
||||
this._terms = terms;
|
||||
|
||||
if (providerResults.length == 0) {
|
||||
this._clearResultDisplay();
|
||||
this.actor.hide();
|
||||
callback();
|
||||
} else {
|
||||
let maxResults = this._getMaxDisplayedResults();
|
||||
let results = this.provider.filterResults(providerResults, maxResults);
|
||||
let hasMoreResults = results.length < providerResults.length;
|
||||
|
||||
this.provider.getResultMetas(results, Lang.bind(this, function(metas) {
|
||||
this.clear();
|
||||
|
||||
// To avoid CSS transitions causing flickering when
|
||||
// the first search result stays the same, we hide the
|
||||
// content while filling in the results.
|
||||
this.actor.hide();
|
||||
this._clearResultDisplay();
|
||||
this._renderResults(metas);
|
||||
this._setMoreIconVisible(hasMoreResults && this.provider.canLaunchSearch);
|
||||
this.actor.show();
|
||||
callback();
|
||||
}));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const ListSearchResults = new Lang.Class({
|
||||
Name: 'ListSearchResults',
|
||||
Extends: SearchResultsBase,
|
||||
|
||||
_init: function(provider) {
|
||||
this.parent(provider);
|
||||
|
||||
this._container = new St.BoxLayout({ style_class: 'search-section-content' });
|
||||
this.providerIcon = new ProviderIcon(provider);
|
||||
this.providerIcon.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
|
||||
this.providerIcon.connect('clicked', Lang.bind(this,
|
||||
function() {
|
||||
provider.launchSearch(this._terms);
|
||||
Main.overview.toggle();
|
||||
}));
|
||||
|
||||
this._container.add(this.providerIcon, { x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
|
||||
this._content = new St.BoxLayout({ style_class: 'list-search-results',
|
||||
vertical: true });
|
||||
this._container.add(this._content, { expand: true });
|
||||
|
||||
this._resultDisplayBin.set_child(this._container);
|
||||
},
|
||||
|
||||
_setMoreIconVisible: function(visible) {
|
||||
this.providerIcon.moreIcon.visible = true;
|
||||
},
|
||||
|
||||
_getMaxDisplayedResults: function() {
|
||||
return MAX_LIST_SEARCH_RESULTS_ROWS;
|
||||
},
|
||||
|
||||
_renderResults: function(metas) {
|
||||
for (let i = 0; i < metas.length; i++) {
|
||||
let display = new ListSearchResult(this.provider, metas[i], this._terms);
|
||||
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
|
||||
this._content.add_actor(display.actor);
|
||||
}
|
||||
},
|
||||
|
||||
_clearResultDisplay: function () {
|
||||
this._content.destroy_all_children();
|
||||
},
|
||||
|
||||
getFirstResult: function() {
|
||||
if (this._content.get_n_children() > 0)
|
||||
return this._content.get_child_at_index(0)._delegate;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(ListSearchResults.prototype);
|
||||
|
||||
const GridSearchResults = new Lang.Class({
|
||||
Name: 'GridSearchResults',
|
||||
Extends: SearchResultsBase,
|
||||
|
||||
_init: function(provider) {
|
||||
this.parent(provider);
|
||||
|
||||
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
|
||||
xAlign: St.Align.START });
|
||||
this._bin = new St.Bin({ x_align: St.Align.MIDDLE });
|
||||
this._bin.set_child(this._grid.actor);
|
||||
|
||||
this._resultDisplayBin.set_child(this._bin);
|
||||
},
|
||||
|
||||
_getMaxDisplayedResults: function() {
|
||||
return this._grid.columnsForWidth(this._bin.width) * this._grid.getRowLimit();
|
||||
},
|
||||
|
||||
_renderResults: function(metas) {
|
||||
for (let i = 0; i < metas.length; i++) {
|
||||
let display = new GridSearchResult(this.provider, metas[i], this._terms);
|
||||
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
|
||||
this._grid.addItem(display);
|
||||
}
|
||||
},
|
||||
|
||||
_clearResultDisplay: function () {
|
||||
this._grid.removeAll();
|
||||
},
|
||||
|
||||
getFirstResult: function() {
|
||||
if (this._grid.visibleItemsCount() > 0)
|
||||
return this._grid.getItemAtIndex(0)._delegate;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(GridSearchResults.prototype);
|
||||
|
||||
const SearchResults = new Lang.Class({
|
||||
Name: 'SearchResults',
|
||||
|
||||
_init: function(searchSystem) {
|
||||
this._searchSystem = searchSystem;
|
||||
this._searchSystem.connect('search-updated', Lang.bind(this, this._updateResults));
|
||||
|
||||
this.actor = new St.BoxLayout({ name: 'searchResults',
|
||||
vertical: true });
|
||||
|
||||
this._content = new St.BoxLayout({ name: 'searchResultsContent',
|
||||
vertical: true });
|
||||
this._contentBin = new MaxWidthBin({ name: 'searchResultsBin',
|
||||
x_fill: true,
|
||||
y_fill: true,
|
||||
child: this._content });
|
||||
|
||||
let scrollChild = new St.BoxLayout();
|
||||
scrollChild.add(this._contentBin, { expand: true });
|
||||
|
||||
this._scrollView = new St.ScrollView({ x_fill: true,
|
||||
y_fill: false,
|
||||
overlay_scrollbars: true,
|
||||
style_class: 'search-display vfade' });
|
||||
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
this._scrollView.add_actor(scrollChild);
|
||||
let action = new Clutter.PanAction({ interpolate: true });
|
||||
action.connect('pan', Lang.bind(this, this._onPan));
|
||||
this._scrollView.add_action(action);
|
||||
|
||||
this.actor.add(this._scrollView, { x_fill: true,
|
||||
y_fill: true,
|
||||
expand: true,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
|
||||
this._statusText = new St.Label({ style_class: 'search-statustext' });
|
||||
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.MIDDLE });
|
||||
this._content.add(this._statusBin, { expand: true });
|
||||
this._statusBin.add_actor(this._statusText);
|
||||
this._providers = this._searchSystem.getProviders();
|
||||
this._providerDisplays = {};
|
||||
for (let i = 0; i < this._providers.length; i++) {
|
||||
this.createProviderDisplay(this._providers[i]);
|
||||
}
|
||||
|
||||
this._highlightDefault = false;
|
||||
this._defaultResult = null;
|
||||
},
|
||||
|
||||
_onPan: function(action) {
|
||||
let [dist, dx, dy] = action.get_motion_delta(0);
|
||||
let adjustment = this._scrollView.vscroll.adjustment;
|
||||
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
|
||||
return false;
|
||||
},
|
||||
|
||||
_keyFocusIn: function(provider, actor) {
|
||||
Util.ensureActorVisibleInScrollView(this._scrollView, actor);
|
||||
},
|
||||
|
||||
createProviderDisplay: function(provider) {
|
||||
let providerDisplay = null;
|
||||
|
||||
if (provider.appInfo) {
|
||||
providerDisplay = new ListSearchResults(provider);
|
||||
} else {
|
||||
providerDisplay = new GridSearchResults(provider);
|
||||
}
|
||||
|
||||
providerDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
|
||||
this._providerDisplays[provider.id] = providerDisplay;
|
||||
this._content.add(providerDisplay.actor);
|
||||
},
|
||||
|
||||
destroyProviderDisplay: function(provider) {
|
||||
this._providerDisplays[provider.id].destroy();
|
||||
delete this._providerDisplays[provider.id];
|
||||
},
|
||||
|
||||
_clearDisplay: function() {
|
||||
for (let i = 0; i < this._providers.length; i++) {
|
||||
let provider = this._providers[i];
|
||||
let providerDisplay = this._providerDisplays[provider.id];
|
||||
providerDisplay.clear();
|
||||
}
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
this._searchSystem.reset();
|
||||
this._statusBin.hide();
|
||||
this._clearDisplay();
|
||||
this._defaultResult = null;
|
||||
},
|
||||
|
||||
startingSearch: function() {
|
||||
this.reset();
|
||||
this._statusText.set_text(_("Searching…"));
|
||||
this._statusBin.show();
|
||||
},
|
||||
|
||||
_maybeSetInitialSelection: function() {
|
||||
let newDefaultResult = null;
|
||||
|
||||
for (let i = 0; i < this._providers.length; i++) {
|
||||
let provider = this._providers[i];
|
||||
let display = this._providerDisplays[provider.id];
|
||||
|
||||
if (!display.actor.visible)
|
||||
continue;
|
||||
|
||||
let firstResult = display.getFirstResult();
|
||||
if (firstResult) {
|
||||
newDefaultResult = firstResult;
|
||||
break; // select this one!
|
||||
}
|
||||
}
|
||||
|
||||
if (newDefaultResult != this._defaultResult) {
|
||||
if (this._defaultResult)
|
||||
this._defaultResult.setSelected(false);
|
||||
if (newDefaultResult)
|
||||
newDefaultResult.setSelected(this._highlightDefault);
|
||||
|
||||
this._defaultResult = newDefaultResult;
|
||||
}
|
||||
},
|
||||
|
||||
_updateStatusText: function () {
|
||||
let haveResults = false;
|
||||
|
||||
for (let i = 0; i < this._providers.length; i++) {
|
||||
let provider = this._providers[i];
|
||||
let display = this._providerDisplays[provider.id];
|
||||
if (display.getFirstResult()) {
|
||||
haveResults = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!haveResults) {
|
||||
this._statusText.set_text(_("No results."));
|
||||
this._statusBin.show();
|
||||
} else {
|
||||
this._statusBin.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_updateResults: function(searchSystem, results) {
|
||||
let terms = searchSystem.getTerms();
|
||||
let [provider, providerResults] = results;
|
||||
let display = this._providerDisplays[provider.id];
|
||||
|
||||
display.updateSearch(providerResults, terms, Lang.bind(this, function() {
|
||||
this._maybeSetInitialSelection();
|
||||
this._updateStatusText();
|
||||
}));
|
||||
},
|
||||
|
||||
activateDefault: function() {
|
||||
if (this._defaultResult)
|
||||
this._defaultResult.activate();
|
||||
},
|
||||
|
||||
highlightDefault: function(highlight) {
|
||||
this._highlightDefault = highlight;
|
||||
if (this._defaultResult)
|
||||
this._defaultResult.setSelected(highlight);
|
||||
},
|
||||
|
||||
navigateFocus: function(direction) {
|
||||
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
|
||||
if (direction == Gtk.DirectionType.TAB_BACKWARD ||
|
||||
direction == (rtl ? Gtk.DirectionType.RIGHT
|
||||
: Gtk.DirectionType.LEFT) ||
|
||||
direction == Gtk.DirectionType.UP) {
|
||||
this.actor.navigate_focus(null, direction, false);
|
||||
return;
|
||||
}
|
||||
|
||||
let from = this._defaultResult ? this._defaultResult.actor : null;
|
||||
this.actor.navigate_focus(from, direction, false);
|
||||
}
|
||||
});
|
||||
|
||||
const ProviderIcon = new Lang.Class({
|
||||
Name: 'ProviderIcon',
|
||||
Extends: St.Button,
|
||||
|
||||
PROVIDER_ICON_SIZE: 48,
|
||||
|
||||
_init: function(provider) {
|
||||
this.provider = provider;
|
||||
this.parent({ style_class: 'search-provider-icon',
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
accessible_name: provider.appInfo.get_name(),
|
||||
track_hover: true });
|
||||
|
||||
this._content = new St.Widget({ layout_manager: new Clutter.BinLayout() });
|
||||
this.set_child(this._content);
|
||||
|
||||
let rtl = (this.get_text_direction() == Clutter.TextDirection.RTL);
|
||||
|
||||
this.moreIcon = new St.Widget({ style_class: 'search-provider-icon-more',
|
||||
visible: false,
|
||||
x_align: rtl ? Clutter.ActorAlign.START : Clutter.ActorAlign.END,
|
||||
y_align: Clutter.ActorAlign.END,
|
||||
x_expand: true,
|
||||
y_expand: true });
|
||||
|
||||
let icon = new St.Icon({ icon_size: this.PROVIDER_ICON_SIZE,
|
||||
gicon: provider.appInfo.get_icon() });
|
||||
this._content.add_actor(icon);
|
||||
this._content.add_actor(this.moreIcon);
|
||||
}
|
||||
});
|
||||
|
@ -1,566 +0,0 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
const Atk = imports.gi.Atk;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
const IconGrid = imports.ui.iconGrid;
|
||||
const Main = imports.ui.main;
|
||||
const Overview = imports.ui.overview;
|
||||
const Separator = imports.ui.separator;
|
||||
const Search = imports.ui.search;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const MAX_LIST_SEARCH_RESULTS_ROWS = 3;
|
||||
const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
|
||||
|
||||
const MaxWidthBin = new Lang.Class({
|
||||
Name: 'MaxWidthBin',
|
||||
Extends: St.Bin,
|
||||
|
||||
vfunc_allocate: function(box, flags) {
|
||||
let themeNode = this.get_theme_node();
|
||||
let maxWidth = themeNode.get_max_width();
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let adjustedBox = box;
|
||||
|
||||
if (availWidth > maxWidth) {
|
||||
let excessWidth = availWidth - maxWidth;
|
||||
adjustedBox.x1 += Math.floor(excessWidth / 2);
|
||||
adjustedBox.x2 -= Math.floor(excessWidth / 2);
|
||||
}
|
||||
|
||||
this.parent(adjustedBox, flags);
|
||||
}
|
||||
});
|
||||
|
||||
const SearchResult = new Lang.Class({
|
||||
Name: 'SearchResult',
|
||||
|
||||
_init: function(provider, metaInfo, terms) {
|
||||
this.provider = provider;
|
||||
this.metaInfo = metaInfo;
|
||||
this.terms = terms;
|
||||
|
||||
this.actor = new St.Button({ reactive: true,
|
||||
can_focus: true,
|
||||
track_hover: true,
|
||||
x_align: St.Align.START,
|
||||
y_fill: true });
|
||||
|
||||
this.actor._delegate = this;
|
||||
this.actor.connect('clicked', Lang.bind(this, this.activate));
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
this.provider.activateResult(this.metaInfo.id, this.terms);
|
||||
Main.overview.toggle();
|
||||
},
|
||||
|
||||
setSelected: function(selected) {
|
||||
if (selected)
|
||||
this.actor.add_style_pseudo_class('selected');
|
||||
else
|
||||
this.actor.remove_style_pseudo_class('selected');
|
||||
}
|
||||
});
|
||||
|
||||
const ListSearchResult = new Lang.Class({
|
||||
Name: 'ListSearchResult',
|
||||
Extends: SearchResult,
|
||||
|
||||
ICON_SIZE: 64,
|
||||
|
||||
_init: function(provider, metaInfo, terms) {
|
||||
this.parent(provider, metaInfo, terms);
|
||||
|
||||
this.actor.style_class = 'list-search-result';
|
||||
this.actor.x_fill = true;
|
||||
|
||||
let content = new St.BoxLayout({ style_class: 'list-search-result-content',
|
||||
vertical: false });
|
||||
this.actor.set_child(content);
|
||||
|
||||
// An icon for, or thumbnail of, content
|
||||
let icon = this.metaInfo['createIcon'](this.ICON_SIZE);
|
||||
if (icon) {
|
||||
content.add(icon);
|
||||
}
|
||||
|
||||
let details = new St.BoxLayout({ vertical: true });
|
||||
content.add(details, { x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.MIDDLE });
|
||||
|
||||
let title = new St.Label({ style_class: 'list-search-result-title',
|
||||
text: this.metaInfo['name'] })
|
||||
details.add(title, { x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
this.actor.label_actor = title;
|
||||
|
||||
if (this.metaInfo['description']) {
|
||||
let description = new St.Label({ style_class: 'list-search-result-description' });
|
||||
description.clutter_text.set_markup(this.metaInfo['description']);
|
||||
details.add(description, { x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.END });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const GridSearchResult = new Lang.Class({
|
||||
Name: 'GridSearchResult',
|
||||
Extends: SearchResult,
|
||||
|
||||
_init: function(provider, metaInfo, terms) {
|
||||
this.parent(provider, metaInfo, terms);
|
||||
|
||||
this.actor.style_class = 'grid-search-result';
|
||||
|
||||
let content = provider.createResultObject(metaInfo, terms);
|
||||
let dragSource = null;
|
||||
|
||||
if (content == null) {
|
||||
let actor = new St.Bin();
|
||||
let icon = new IconGrid.BaseIcon(this.metaInfo['name'],
|
||||
{ createIcon: this.metaInfo['createIcon'] });
|
||||
actor.set_child(icon.actor);
|
||||
actor.label_actor = icon.label;
|
||||
dragSource = icon.icon;
|
||||
content = { actor: actor, icon: icon };
|
||||
} else {
|
||||
if (content._delegate && content._delegate.getDragActorSource)
|
||||
dragSource = content._delegate.getDragActorSource();
|
||||
}
|
||||
|
||||
this.actor.set_child(content.actor);
|
||||
this.actor.label_actor = content.actor.label_actor;
|
||||
this.icon = content.icon;
|
||||
|
||||
let draggable = DND.makeDraggable(this.actor);
|
||||
draggable.connect('drag-begin',
|
||||
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);
|
||||
}));
|
||||
|
||||
if (!dragSource)
|
||||
// not exactly right, but alignment problems are hard to notice
|
||||
dragSource = content;
|
||||
this._dragActorSource = dragSource;
|
||||
},
|
||||
|
||||
getDragActorSource: function() {
|
||||
return this._dragActorSource;
|
||||
},
|
||||
|
||||
getDragActor: function() {
|
||||
return this.metaInfo['createIcon'](Main.overview.dashIconSize);
|
||||
},
|
||||
|
||||
shellWorkspaceLaunch: function(params) {
|
||||
if (this.provider.dragActivateResult)
|
||||
this.provider.dragActivateResult(this.metaInfo.id, params);
|
||||
else
|
||||
this.provider.activateResult(this.metaInfo.id, this.terms);
|
||||
}
|
||||
});
|
||||
|
||||
const SearchResultsBase = new Lang.Class({
|
||||
Name: 'SearchResultsBase',
|
||||
|
||||
_init: function(provider) {
|
||||
this.provider = provider;
|
||||
|
||||
this._terms = [];
|
||||
|
||||
this.actor = new St.BoxLayout({ style_class: 'search-section',
|
||||
vertical: true });
|
||||
|
||||
this._resultDisplayBin = new St.Bin({ x_fill: true,
|
||||
y_fill: true });
|
||||
this.actor.add(this._resultDisplayBin, { expand: true });
|
||||
|
||||
let separator = new Separator.HorizontalSeparator({ style_class: 'search-section-separator' });
|
||||
this.actor.add(separator.actor);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.actor.destroy();
|
||||
this._terms = [];
|
||||
},
|
||||
|
||||
_clearResultDisplay: function() {
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
this._clearResultDisplay();
|
||||
this.actor.hide();
|
||||
},
|
||||
|
||||
_keyFocusIn: function(icon) {
|
||||
this.emit('key-focus-in', icon);
|
||||
},
|
||||
|
||||
_setMoreIconVisible: function(visible) {
|
||||
},
|
||||
|
||||
updateSearch: function(providerResults, terms, callback) {
|
||||
this._terms = terms;
|
||||
|
||||
if (providerResults.length == 0) {
|
||||
this._clearResultDisplay();
|
||||
this.actor.hide();
|
||||
callback();
|
||||
} else {
|
||||
let maxResults = this._getMaxDisplayedResults();
|
||||
let results = providerResults.slice(0, maxResults);
|
||||
let hasMoreResults = results.length < providerResults.length;
|
||||
|
||||
this.provider.getResultMetas(results, Lang.bind(this, function(metas) {
|
||||
this.clear();
|
||||
|
||||
// To avoid CSS transitions causing flickering when
|
||||
// the first search result stays the same, we hide the
|
||||
// content while filling in the results.
|
||||
this.actor.hide();
|
||||
this._clearResultDisplay();
|
||||
this._renderResults(metas);
|
||||
this._setMoreIconVisible(hasMoreResults && this.provider.canLaunchSearch);
|
||||
this.actor.show();
|
||||
callback();
|
||||
}));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const ListSearchResults = new Lang.Class({
|
||||
Name: 'ListSearchResults',
|
||||
Extends: SearchResultsBase,
|
||||
|
||||
_init: function(provider) {
|
||||
this.parent(provider);
|
||||
|
||||
this._container = new St.BoxLayout({ style_class: 'search-section-content' });
|
||||
this.providerIcon = new ProviderIcon(provider);
|
||||
this.providerIcon.connect('clicked', Lang.bind(this,
|
||||
function() {
|
||||
provider.launchSearch(this._terms);
|
||||
Main.overview.toggle();
|
||||
}));
|
||||
|
||||
this._container.add(this.providerIcon, { x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
|
||||
this._content = new St.BoxLayout({ style_class: 'list-search-results',
|
||||
vertical: true });
|
||||
this._container.add(this._content, { expand: true });
|
||||
|
||||
this._resultDisplayBin.set_child(this._container);
|
||||
},
|
||||
|
||||
_setMoreIconVisible: function(visible) {
|
||||
this.providerIcon.moreIcon.visible = true;
|
||||
},
|
||||
|
||||
_getMaxDisplayedResults: function() {
|
||||
return MAX_LIST_SEARCH_RESULTS_ROWS;
|
||||
},
|
||||
|
||||
_renderResults: function(metas) {
|
||||
for (let i = 0; i < metas.length; i++) {
|
||||
let display = new ListSearchResult(this.provider, metas[i], this._terms);
|
||||
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
|
||||
this._content.add_actor(display.actor);
|
||||
}
|
||||
},
|
||||
|
||||
_clearResultDisplay: function () {
|
||||
this._content.destroy_all_children();
|
||||
},
|
||||
|
||||
getFirstResult: function() {
|
||||
if (this._content.get_n_children() > 0)
|
||||
return this._content.get_child_at_index(0)._delegate;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(ListSearchResults.prototype);
|
||||
|
||||
const GridSearchResults = new Lang.Class({
|
||||
Name: 'GridSearchResults',
|
||||
Extends: SearchResultsBase,
|
||||
|
||||
_init: function(provider) {
|
||||
this.parent(provider);
|
||||
|
||||
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
|
||||
xAlign: St.Align.START });
|
||||
this._bin = new St.Bin({ x_align: St.Align.MIDDLE });
|
||||
this._bin.set_child(this._grid.actor);
|
||||
|
||||
this._resultDisplayBin.set_child(this._bin);
|
||||
},
|
||||
|
||||
_getMaxDisplayedResults: function() {
|
||||
return this._grid.columnsForWidth(this._bin.width) * this._grid.getRowLimit();
|
||||
},
|
||||
|
||||
_renderResults: function(metas) {
|
||||
for (let i = 0; i < metas.length; i++) {
|
||||
let display = new GridSearchResult(this.provider, metas[i], this._terms);
|
||||
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
|
||||
this._grid.addItem(display);
|
||||
}
|
||||
},
|
||||
|
||||
_clearResultDisplay: function () {
|
||||
this._grid.removeAll();
|
||||
},
|
||||
|
||||
getFirstResult: function() {
|
||||
if (this._grid.visibleItemsCount() > 0)
|
||||
return this._grid.getItemAtIndex(0)._delegate;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(GridSearchResults.prototype);
|
||||
|
||||
const SearchResults = new Lang.Class({
|
||||
Name: 'SearchResults',
|
||||
|
||||
_init: function(searchSystem) {
|
||||
this._searchSystem = searchSystem;
|
||||
this._searchSystem.connect('search-updated', Lang.bind(this, this._updateResults));
|
||||
|
||||
this.actor = new St.BoxLayout({ name: 'searchResults',
|
||||
vertical: true });
|
||||
|
||||
this._content = new St.BoxLayout({ name: 'searchResultsContent',
|
||||
vertical: true });
|
||||
this._contentBin = new MaxWidthBin({ name: 'searchResultsBin',
|
||||
x_fill: true,
|
||||
y_fill: true,
|
||||
child: this._content });
|
||||
|
||||
let scrollChild = new St.BoxLayout();
|
||||
scrollChild.add(this._contentBin, { expand: true });
|
||||
|
||||
this._scrollView = new St.ScrollView({ x_fill: true,
|
||||
y_fill: false,
|
||||
overlay_scrollbars: true,
|
||||
style_class: 'search-display vfade' });
|
||||
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
this._scrollView.add_actor(scrollChild);
|
||||
let action = new Clutter.PanAction({ interpolate: true });
|
||||
action.connect('pan', Lang.bind(this, this._onPan));
|
||||
this._scrollView.add_action(action);
|
||||
|
||||
this.actor.add(this._scrollView, { x_fill: true,
|
||||
y_fill: true,
|
||||
expand: true,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
|
||||
this._statusText = new St.Label({ style_class: 'search-statustext' });
|
||||
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.MIDDLE });
|
||||
this._content.add(this._statusBin, { expand: true });
|
||||
this._statusBin.add_actor(this._statusText);
|
||||
this._providers = this._searchSystem.getProviders();
|
||||
this._providerDisplays = {};
|
||||
for (let i = 0; i < this._providers.length; i++) {
|
||||
this.createProviderDisplay(this._providers[i]);
|
||||
}
|
||||
|
||||
this._highlightDefault = false;
|
||||
this._defaultResult = null;
|
||||
},
|
||||
|
||||
_onPan: function(action) {
|
||||
let [dist, dx, dy] = action.get_motion_delta(0);
|
||||
let adjustment = this._scrollView.vscroll.adjustment;
|
||||
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
|
||||
return false;
|
||||
},
|
||||
|
||||
_keyFocusIn: function(provider, icon) {
|
||||
Util.ensureActorVisibleInScrollView(this._scrollView, icon);
|
||||
},
|
||||
|
||||
createProviderDisplay: function(provider) {
|
||||
let providerDisplay = null;
|
||||
|
||||
if (provider.appInfo) {
|
||||
providerDisplay = new ListSearchResults(provider);
|
||||
} else {
|
||||
providerDisplay = new GridSearchResults(provider);
|
||||
}
|
||||
|
||||
providerDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
|
||||
this._providerDisplays[provider.id] = providerDisplay;
|
||||
this._content.add(providerDisplay.actor);
|
||||
},
|
||||
|
||||
destroyProviderDisplay: function(provider) {
|
||||
this._providerDisplays[provider.id].destroy();
|
||||
delete this._providerDisplays[provider.id];
|
||||
},
|
||||
|
||||
_clearDisplay: function() {
|
||||
for (let i = 0; i < this._providers.length; i++) {
|
||||
let provider = this._providers[i];
|
||||
let providerDisplay = this._providerDisplays[provider.id];
|
||||
providerDisplay.clear();
|
||||
}
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
this._searchSystem.reset();
|
||||
this._statusBin.hide();
|
||||
this._clearDisplay();
|
||||
this._defaultResult = null;
|
||||
},
|
||||
|
||||
startingSearch: function() {
|
||||
this.reset();
|
||||
this._statusText.set_text(_("Searching…"));
|
||||
this._statusBin.show();
|
||||
},
|
||||
|
||||
_maybeSetInitialSelection: function() {
|
||||
let newDefaultResult = null;
|
||||
|
||||
for (let i = 0; i < this._providers.length; i++) {
|
||||
let provider = this._providers[i];
|
||||
let display = this._providerDisplays[provider.id];
|
||||
|
||||
if (!display.actor.visible)
|
||||
continue;
|
||||
|
||||
let firstResult = display.getFirstResult();
|
||||
if (firstResult) {
|
||||
newDefaultResult = firstResult;
|
||||
break; // select this one!
|
||||
}
|
||||
}
|
||||
|
||||
if (newDefaultResult != this._defaultResult) {
|
||||
if (this._defaultResult)
|
||||
this._defaultResult.setSelected(false);
|
||||
if (newDefaultResult)
|
||||
newDefaultResult.setSelected(this._highlightDefault);
|
||||
|
||||
this._defaultResult = newDefaultResult;
|
||||
}
|
||||
},
|
||||
|
||||
_updateStatusText: function () {
|
||||
let haveResults = false;
|
||||
|
||||
for (let i = 0; i < this._providers.length; i++) {
|
||||
let provider = this._providers[i];
|
||||
let display = this._providerDisplays[provider.id];
|
||||
if (display.getFirstResult()) {
|
||||
haveResults = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!haveResults) {
|
||||
this._statusText.set_text(_("No results."));
|
||||
this._statusBin.show();
|
||||
} else {
|
||||
this._statusBin.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_updateResults: function(searchSystem, results) {
|
||||
let terms = searchSystem.getTerms();
|
||||
let [provider, providerResults] = results;
|
||||
let display = this._providerDisplays[provider.id];
|
||||
|
||||
display.updateSearch(providerResults, terms, Lang.bind(this, function() {
|
||||
this._maybeSetInitialSelection();
|
||||
this._updateStatusText();
|
||||
}));
|
||||
},
|
||||
|
||||
activateDefault: function() {
|
||||
if (this._defaultResult)
|
||||
this._defaultResult.activate();
|
||||
},
|
||||
|
||||
highlightDefault: function(highlight) {
|
||||
this._highlightDefault = highlight;
|
||||
if (this._defaultResult)
|
||||
this._defaultResult.setSelected(highlight);
|
||||
},
|
||||
|
||||
navigateFocus: function(direction) {
|
||||
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
|
||||
if (direction == Gtk.DirectionType.TAB_BACKWARD ||
|
||||
direction == (rtl ? Gtk.DirectionType.RIGHT
|
||||
: Gtk.DirectionType.LEFT) ||
|
||||
direction == Gtk.DirectionType.UP) {
|
||||
this.actor.navigate_focus(null, direction, false);
|
||||
return;
|
||||
}
|
||||
|
||||
let from = this._defaultResult ? this._defaultResult.actor : null;
|
||||
this.actor.navigate_focus(from, direction, false);
|
||||
}
|
||||
});
|
||||
|
||||
const ProviderIcon = new Lang.Class({
|
||||
Name: 'ProviderIcon',
|
||||
Extends: St.Button,
|
||||
|
||||
PROVIDER_ICON_SIZE: 48,
|
||||
|
||||
_init: function(provider) {
|
||||
this.provider = provider;
|
||||
this.parent({ style_class: 'search-provider-icon',
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
accessible_name: provider.appInfo.get_name(),
|
||||
track_hover: true });
|
||||
|
||||
this._content = new St.Widget({ layout_manager: new Clutter.BinLayout() });
|
||||
this.set_child(this._content);
|
||||
|
||||
let rtl = (this.get_text_direction() == Clutter.TextDirection.RTL);
|
||||
|
||||
this.moreIcon = new St.Widget({ style_class: 'search-provider-icon-more',
|
||||
visible: false,
|
||||
x_align: rtl ? Clutter.ActorAlign.START : Clutter.ActorAlign.END,
|
||||
y_align: Clutter.ActorAlign.END,
|
||||
x_expand: true,
|
||||
y_expand: true });
|
||||
|
||||
let icon = new St.Icon({ icon_size: this.PROVIDER_ICON_SIZE,
|
||||
gicon: provider.appInfo.get_icon() });
|
||||
this._content.add_actor(icon);
|
||||
this._content.add_actor(this.moreIcon);
|
||||
}
|
||||
});
|
@ -15,59 +15,63 @@ const Main = imports.ui.main;
|
||||
const Screenshot = imports.ui.screenshot;
|
||||
const ViewSelector = imports.ui.viewSelector;
|
||||
|
||||
const GnomeShellIface = <interface name="org.gnome.Shell">
|
||||
<method name="Eval">
|
||||
<arg type="s" direction="in" name="script" />
|
||||
<arg type="b" direction="out" name="success" />
|
||||
<arg type="s" direction="out" name="result" />
|
||||
</method>
|
||||
<method name="FocusSearch"/>
|
||||
<method name="ShowOSD">
|
||||
<arg type="a{sv}" direction="in" name="params"/>
|
||||
</method>
|
||||
<method name="FocusApp">
|
||||
<arg type="s" direction="in" name="id"/>
|
||||
</method>
|
||||
<method name="ShowApplications" />
|
||||
<method name="GrabAccelerator">
|
||||
<arg type="s" direction="in" name="accelerator"/>
|
||||
<arg type="u" direction="in" name="flags"/>
|
||||
<arg type="u" direction="out" name="action"/>
|
||||
</method>
|
||||
<method name="GrabAccelerators">
|
||||
<arg type="a(su)" direction="in" name="accelerators"/>
|
||||
<arg type="au" direction="out" name="actions"/>
|
||||
</method>
|
||||
<method name="UngrabAccelerator">
|
||||
<arg type="u" direction="in" name="action"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
</method>
|
||||
<signal name="AcceleratorActivated">
|
||||
<arg name="action" type="u" />
|
||||
<arg name="deviceid" type="u" />
|
||||
<arg name="timestamp" type="u" />
|
||||
</signal>
|
||||
<property name="Mode" type="s" access="read" />
|
||||
<property name="OverviewActive" type="b" access="readwrite" />
|
||||
<property name="ShellVersion" type="s" access="read" />
|
||||
</interface>;
|
||||
const GnomeShellIface = '<node> \
|
||||
<interface name="org.gnome.Shell"> \
|
||||
<method name="Eval"> \
|
||||
<arg type="s" direction="in" name="script" /> \
|
||||
<arg type="b" direction="out" name="success" /> \
|
||||
<arg type="s" direction="out" name="result" /> \
|
||||
</method> \
|
||||
<method name="FocusSearch"/> \
|
||||
<method name="ShowOSD"> \
|
||||
<arg type="a{sv}" direction="in" name="params"/> \
|
||||
</method> \
|
||||
<method name="FocusApp"> \
|
||||
<arg type="s" direction="in" name="id"/> \
|
||||
</method> \
|
||||
<method name="ShowApplications" /> \
|
||||
<method name="GrabAccelerator"> \
|
||||
<arg type="s" direction="in" name="accelerator"/> \
|
||||
<arg type="u" direction="in" name="flags"/> \
|
||||
<arg type="u" direction="out" name="action"/> \
|
||||
</method> \
|
||||
<method name="GrabAccelerators"> \
|
||||
<arg type="a(su)" direction="in" name="accelerators"/> \
|
||||
<arg type="au" direction="out" name="actions"/> \
|
||||
</method> \
|
||||
<method name="UngrabAccelerator"> \
|
||||
<arg type="u" direction="in" name="action"/> \
|
||||
<arg type="b" direction="out" name="success"/> \
|
||||
</method> \
|
||||
<signal name="AcceleratorActivated"> \
|
||||
<arg name="action" type="u" /> \
|
||||
<arg name="deviceid" type="u" /> \
|
||||
<arg name="timestamp" type="u" /> \
|
||||
</signal> \
|
||||
<property name="Mode" type="s" access="read" /> \
|
||||
<property name="OverviewActive" type="b" access="readwrite" /> \
|
||||
<property name="ShellVersion" type="s" access="read" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const ScreenSaverIface = <interface name="org.gnome.ScreenSaver">
|
||||
<method name="Lock">
|
||||
</method>
|
||||
<method name="GetActive">
|
||||
<arg name="active" direction="out" type="b" />
|
||||
</method>
|
||||
<method name="SetActive">
|
||||
<arg name="value" direction="in" type="b" />
|
||||
</method>
|
||||
<method name="GetActiveTime">
|
||||
<arg name="value" direction="out" type="u" />
|
||||
</method>
|
||||
<signal name="ActiveChanged">
|
||||
<arg name="new_value" type="b" />
|
||||
</signal>
|
||||
</interface>;
|
||||
const ScreenSaverIface = '<node> \
|
||||
<interface name="org.gnome.ScreenSaver"> \
|
||||
<method name="Lock"> \
|
||||
</method> \
|
||||
<method name="GetActive"> \
|
||||
<arg name="active" direction="out" type="b" /> \
|
||||
</method> \
|
||||
<method name="SetActive"> \
|
||||
<arg name="value" direction="in" type="b" /> \
|
||||
</method> \
|
||||
<method name="GetActiveTime"> \
|
||||
<arg name="value" direction="out" type="u" /> \
|
||||
</method> \
|
||||
<signal name="ActiveChanged"> \
|
||||
<arg name="new_value" type="b" /> \
|
||||
</signal> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const GnomeShell = new Lang.Class({
|
||||
Name: 'GnomeShellDBus',
|
||||
@ -246,41 +250,43 @@ const GnomeShell = new Lang.Class({
|
||||
ShellVersion: Config.PACKAGE_VERSION
|
||||
});
|
||||
|
||||
const GnomeShellExtensionsIface = <interface name="org.gnome.Shell.Extensions">
|
||||
<method name="ListExtensions">
|
||||
<arg type="a{sa{sv}}" direction="out" name="extensions" />
|
||||
</method>
|
||||
<method name="GetExtensionInfo">
|
||||
<arg type="s" direction="in" name="extension" />
|
||||
<arg type="a{sv}" direction="out" name="info" />
|
||||
</method>
|
||||
<method name="GetExtensionErrors">
|
||||
<arg type="s" direction="in" name="extension" />
|
||||
<arg type="as" direction="out" name="errors" />
|
||||
</method>
|
||||
<signal name="ExtensionStatusChanged">
|
||||
<arg type="s" name="uuid"/>
|
||||
<arg type="i" name="state"/>
|
||||
<arg type="s" name="error"/>
|
||||
</signal>
|
||||
<method name="InstallRemoteExtension">
|
||||
<arg type="s" direction="in" name="uuid"/>
|
||||
<arg type="s" direction="out" name="result"/>
|
||||
</method>
|
||||
<method name="UninstallExtension">
|
||||
<arg type="s" direction="in" name="uuid"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
</method>
|
||||
<method name="LaunchExtensionPrefs">
|
||||
<arg type="s" direction="in" name="uuid"/>
|
||||
</method>
|
||||
<method name="ReloadExtension">
|
||||
<arg type="s" direction="in" name="uuid"/>
|
||||
</method>
|
||||
<method name="CheckForUpdates">
|
||||
</method>
|
||||
<property name="ShellVersion" type="s" access="read" />
|
||||
</interface>;
|
||||
const GnomeShellExtensionsIface = '<node> \
|
||||
<interface name="org.gnome.Shell.Extensions"> \
|
||||
<method name="ListExtensions"> \
|
||||
<arg type="a{sa{sv}}" direction="out" name="extensions" /> \
|
||||
</method> \
|
||||
<method name="GetExtensionInfo"> \
|
||||
<arg type="s" direction="in" name="extension" /> \
|
||||
<arg type="a{sv}" direction="out" name="info" /> \
|
||||
</method> \
|
||||
<method name="GetExtensionErrors"> \
|
||||
<arg type="s" direction="in" name="extension" /> \
|
||||
<arg type="as" direction="out" name="errors" /> \
|
||||
</method> \
|
||||
<signal name="ExtensionStatusChanged"> \
|
||||
<arg type="s" name="uuid"/> \
|
||||
<arg type="i" name="state"/> \
|
||||
<arg type="s" name="error"/> \
|
||||
</signal> \
|
||||
<method name="InstallRemoteExtension"> \
|
||||
<arg type="s" direction="in" name="uuid"/> \
|
||||
<arg type="s" direction="out" name="result"/> \
|
||||
</method> \
|
||||
<method name="UninstallExtension"> \
|
||||
<arg type="s" direction="in" name="uuid"/> \
|
||||
<arg type="b" direction="out" name="success"/> \
|
||||
</method> \
|
||||
<method name="LaunchExtensionPrefs"> \
|
||||
<arg type="s" direction="in" name="uuid"/> \
|
||||
</method> \
|
||||
<method name="ReloadExtension"> \
|
||||
<arg type="s" direction="in" name="uuid"/> \
|
||||
</method> \
|
||||
<method name="CheckForUpdates"> \
|
||||
</method> \
|
||||
<property name="ShellVersion" type="s" access="read" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const GnomeShellExtensions = new Lang.Class({
|
||||
Name: 'GnomeShellExtensionsDBus',
|
||||
|
@ -521,36 +521,38 @@ const ShellProcessesDialog = new Lang.Class({
|
||||
});
|
||||
Signals.addSignalMethods(ShellProcessesDialog.prototype);
|
||||
|
||||
const GnomeShellMountOpIface = <interface name="org.Gtk.MountOperationHandler">
|
||||
<method name="AskPassword">
|
||||
<arg type="s" direction="in" name="object_id"/>
|
||||
<arg type="s" direction="in" name="message"/>
|
||||
<arg type="s" direction="in" name="icon_name"/>
|
||||
<arg type="s" direction="in" name="default_user"/>
|
||||
<arg type="s" direction="in" name="default_domain"/>
|
||||
<arg type="u" direction="in" name="flags"/>
|
||||
<arg type="u" direction="out" name="response"/>
|
||||
<arg type="a{sv}" direction="out" name="response_details"/>
|
||||
</method>
|
||||
<method name="AskQuestion">
|
||||
<arg type="s" direction="in" name="object_id"/>
|
||||
<arg type="s" direction="in" name="message"/>
|
||||
<arg type="s" direction="in" name="icon_name"/>
|
||||
<arg type="as" direction="in" name="choices"/>
|
||||
<arg type="u" direction="out" name="response"/>
|
||||
<arg type="a{sv}" direction="out" name="response_details"/>
|
||||
</method>
|
||||
<method name="ShowProcesses">
|
||||
<arg type="s" direction="in" name="object_id"/>
|
||||
<arg type="s" direction="in" name="message"/>
|
||||
<arg type="s" direction="in" name="icon_name"/>
|
||||
<arg type="ai" direction="in" name="application_pids"/>
|
||||
<arg type="as" direction="in" name="choices"/>
|
||||
<arg type="u" direction="out" name="response"/>
|
||||
<arg type="a{sv}" direction="out" name="response_details"/>
|
||||
</method>
|
||||
<method name="Close"/>
|
||||
</interface>;
|
||||
const GnomeShellMountOpIface = '<node> \
|
||||
<interface name="org.Gtk.MountOperationHandler"> \
|
||||
<method name="AskPassword"> \
|
||||
<arg type="s" direction="in" name="object_id"/> \
|
||||
<arg type="s" direction="in" name="message"/> \
|
||||
<arg type="s" direction="in" name="icon_name"/> \
|
||||
<arg type="s" direction="in" name="default_user"/> \
|
||||
<arg type="s" direction="in" name="default_domain"/> \
|
||||
<arg type="u" direction="in" name="flags"/> \
|
||||
<arg type="u" direction="out" name="response"/> \
|
||||
<arg type="a{sv}" direction="out" name="response_details"/> \
|
||||
</method> \
|
||||
<method name="AskQuestion"> \
|
||||
<arg type="s" direction="in" name="object_id"/> \
|
||||
<arg type="s" direction="in" name="message"/> \
|
||||
<arg type="s" direction="in" name="icon_name"/> \
|
||||
<arg type="as" direction="in" name="choices"/> \
|
||||
<arg type="u" direction="out" name="response"/> \
|
||||
<arg type="a{sv}" direction="out" name="response_details"/> \
|
||||
</method> \
|
||||
<method name="ShowProcesses"> \
|
||||
<arg type="s" direction="in" name="object_id"/> \
|
||||
<arg type="s" direction="in" name="message"/> \
|
||||
<arg type="s" direction="in" name="icon_name"/> \
|
||||
<arg type="ai" direction="in" name="application_pids"/> \
|
||||
<arg type="as" direction="in" name="choices"/> \
|
||||
<arg type="u" direction="out" name="response"/> \
|
||||
<arg type="a{sv}" direction="out" name="response_details"/> \
|
||||
</method> \
|
||||
<method name="Close"/> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const ShellMountOperationType = {
|
||||
NONE: 0,
|
||||
|
@ -43,9 +43,7 @@ const ATIndicator = new Lang.Class({
|
||||
this._hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
|
||||
this._hbox.add_child(new St.Icon({ style_class: 'system-status-icon',
|
||||
icon_name: 'preferences-desktop-accessibility-symbolic' }));
|
||||
this._hbox.add_child(new St.Label({ text: '\u25BE',
|
||||
y_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER }));
|
||||
this._hbox.add_child(PopupMenu.unicodeArrow(St.Side.BOTTOM));
|
||||
|
||||
this.actor.add_child(this._hbox);
|
||||
|
||||
|
@ -9,7 +9,6 @@ const St = imports.gi.St;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
const NotificationDaemon = imports.ui.notificationDaemon;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
@ -31,6 +30,7 @@ const Indicator = new Lang.Class({
|
||||
this._applet.killswitch_state = GnomeBluetooth.KillswitchState.SOFT_BLOCKED;
|
||||
}));
|
||||
this._item.menu.addSettingsAction(_("Bluetooth Settings"), 'gnome-bluetooth-panel.desktop');
|
||||
this.menu.addMenuItem(this._item);
|
||||
|
||||
this._applet = new GnomeBluetoothApplet.Applet();
|
||||
this._applet.connect('devices-changed', Lang.bind(this, this._sync));
|
||||
@ -54,13 +54,13 @@ const Indicator = new Lang.Class({
|
||||
this._item.actor.visible = on;
|
||||
|
||||
if (on)
|
||||
this._item.status.text = ngettext("%d Connected Device", "%d Connected Devices").format(nDevices);
|
||||
this._item.status.text = ngettext("%d Connected Device", "%d Connected Devices", nDevices).format(nDevices);
|
||||
},
|
||||
|
||||
_ensureSource: function() {
|
||||
if (!this._source) {
|
||||
this._source = new MessageTray.Source(_("Bluetooth"), 'bluetooth-active');
|
||||
this._source.policy = new NotificationDaemon.NotificationApplicationPolicy('gnome-bluetooth-panel');
|
||||
this._source.policy = new MessageTray.NotificationApplicationPolicy('gnome-bluetooth-panel');
|
||||
Main.messageTray.add(this._source);
|
||||
}
|
||||
},
|
||||
@ -105,8 +105,8 @@ const AuthNotification = new Lang.Class({
|
||||
this._devicePath = device_path;
|
||||
this.addBody(_("Device %s wants to pair with this computer").format(long_name));
|
||||
|
||||
this.addButton('allow', _("Allow"));
|
||||
this.addButton('deny', _("Deny"));
|
||||
this.addAction('allow', _("Allow"));
|
||||
this.addAction('deny', _("Deny"));
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
if (action == 'allow')
|
||||
@ -133,9 +133,9 @@ const AuthServiceNotification = new Lang.Class({
|
||||
this._devicePath = device_path;
|
||||
this.addBody(_("Device %s wants access to the service '%s'").format(long_name, uuid));
|
||||
|
||||
this.addButton('always-grant', _("Always grant access"));
|
||||
this.addButton('grant', _("Grant this time only"));
|
||||
this.addButton('reject', _("Reject"));
|
||||
this.addAction('always-grant', _("Always grant access"));
|
||||
this.addAction('grant', _("Grant this time only"));
|
||||
this.addAction('reject', _("Reject"));
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
switch (action) {
|
||||
@ -172,8 +172,8 @@ const ConfirmNotification = new Lang.Class({
|
||||
this.addBody(_("Please confirm whether the Passkey '%06d' matches the one on the device.").format(pin));
|
||||
|
||||
/* Translators: this is the verb, not the noun */
|
||||
this.addButton('matches', _("Matches"));
|
||||
this.addButton('does-not-match', _("Does not match"));
|
||||
this.addAction('matches', _("Matches"));
|
||||
this.addAction('does-not-match', _("Does not match"));
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
if (action == 'matches')
|
||||
@ -207,47 +207,48 @@ const PinNotification = new Lang.Class({
|
||||
let key = event.get_key_symbol();
|
||||
if (key == Clutter.KEY_Return) {
|
||||
if (this._canActivateOkButton())
|
||||
this.emit('action-invoked', 'ok');
|
||||
this._ok();
|
||||
return true;
|
||||
} else if (key == Clutter.KEY_Escape) {
|
||||
this.emit('action-invoked', 'cancel');
|
||||
this._cancel();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
this.addActor(this._entry);
|
||||
|
||||
this.addButton('ok', _("OK"));
|
||||
this.addButton('cancel', _("Cancel"));
|
||||
let okButton = this.addAction(_("OK"), Lang.bind(this, this._ok));
|
||||
this.addAction(_("Cancel"), Lang.bind(this, this._cancel));
|
||||
|
||||
this.setButtonSensitive('ok', this._canActivateOkButton());
|
||||
this._entry.clutter_text.connect('text-changed', Lang.bind(this,
|
||||
function() {
|
||||
this.setButtonSensitive('ok', this._canActivateOkButton());
|
||||
}));
|
||||
|
||||
this.connect('action-invoked', Lang.bind(this, function(self, action) {
|
||||
if (action == 'ok') {
|
||||
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)
|
||||
this._applet.agent_reply_passkey(this._devicePath, -1);
|
||||
else
|
||||
this._applet.agent_reply_pincode(this._devicePath, null);
|
||||
}
|
||||
this.destroy();
|
||||
okButton.reactive = this._canActivateOkButton();
|
||||
this._entry.clutter_text.connect('text-changed', Lang.bind(this, function() {
|
||||
okButton.reactive = this._canActivateOkButton();
|
||||
}));
|
||||
},
|
||||
|
||||
_ok: function() {
|
||||
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);
|
||||
}
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
_cancel: function() {
|
||||
if (this._numeric)
|
||||
this._applet.agent_reply_passkey(this._devicePath, -1);
|
||||
else
|
||||
this._applet.agent_reply_pincode(this._devicePath, null);
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
_canActivateOkButton: function() {
|
||||
// PINs have a fixed length of 6
|
||||
if (this._numeric)
|
||||
|
@ -11,9 +11,11 @@ const Slider = imports.ui.slider;
|
||||
const BUS_NAME = 'org.gnome.SettingsDaemon.Power';
|
||||
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
|
||||
|
||||
const BrightnessInterface = <interface name="org.gnome.SettingsDaemon.Power.Screen">
|
||||
<property name='Brightness' type='i' access='readwrite'/>
|
||||
</interface>;
|
||||
const BrightnessInterface = '<node> \
|
||||
<interface name="org.gnome.SettingsDaemon.Power.Screen"> \
|
||||
<property name="Brightness" type="i" access="readwrite"/> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const BrightnessProxy = Gio.DBusProxy.makeProxyWrapper(BrightnessInterface);
|
||||
|
||||
|
@ -41,11 +41,13 @@ const MAX_INPUT_SOURCE_ACTIVATION_TIME = 4000; // ms
|
||||
const BUS_NAME = 'org.gnome.SettingsDaemon.Keyboard';
|
||||
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Keyboard';
|
||||
|
||||
const KeyboardManagerInterface = <interface name="org.gnome.SettingsDaemon.Keyboard">
|
||||
<method name="SetInputSource">
|
||||
<arg type="u" direction="in" />
|
||||
</method>
|
||||
</interface>;
|
||||
const KeyboardManagerInterface = '<node> \
|
||||
<interface name="org.gnome.SettingsDaemon.Keyboard"> \
|
||||
<method name="SetInputSource"> \
|
||||
<arg type="u" direction="in" /> \
|
||||
</method> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const KeyboardManagerProxy = Gio.DBusProxy.makeProxyWrapper(KeyboardManagerInterface);
|
||||
|
||||
@ -339,9 +341,7 @@ const InputSourceIndicator = new Lang.Class({
|
||||
|
||||
this._hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
|
||||
this._hbox.add_child(this._container);
|
||||
this._hbox.add_child(new St.Label({ text: '\u25BE',
|
||||
y_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER }));
|
||||
this._hbox.add_child(PopupMenu.unicodeArrow(St.Side.BOTTOM));
|
||||
|
||||
this.actor.add_child(this._hbox);
|
||||
this.actor.add_style_class_name('panel-status-button');
|
||||
|
@ -16,7 +16,6 @@ const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
const NotificationDaemon = imports.ui.notificationDaemon;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const ModemManager = imports.misc.modemManager;
|
||||
const Util = imports.misc.util;
|
||||
@ -73,6 +72,27 @@ function ssidToLabel(ssid) {
|
||||
return label;
|
||||
}
|
||||
|
||||
function ensureActiveConnectionProps(active, settings) {
|
||||
if (!active._connection) {
|
||||
active._connection = settings.get_connection_by_path(active.connection);
|
||||
|
||||
// This list is guaranteed to have only one device in it.
|
||||
let device = active.get_devices()[0]._delegate;
|
||||
active._primaryDevice = device;
|
||||
}
|
||||
}
|
||||
|
||||
function createSettingsAction(label, device) {
|
||||
let item = new PopupMenu.PopupMenuItem(label);
|
||||
|
||||
item.connect('activate', function() {
|
||||
Util.spawnApp(['gnome-control-center', 'network', 'show-device',
|
||||
device.get_path()]);
|
||||
});
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
const NMConnectionItem = new Lang.Class({
|
||||
Name: 'NMConnectionItem',
|
||||
|
||||
@ -170,8 +190,7 @@ const NMConnectionSection = new Lang.Class({
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.statusItem.destroy();
|
||||
this.section.destroy();
|
||||
this.item.destroy();
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
@ -268,12 +287,12 @@ const NMConnectionDevice = new Lang.Class({
|
||||
Extends: NMConnectionSection,
|
||||
Abstract: true,
|
||||
|
||||
_init: function(client, device) {
|
||||
_init: function(client, device, settings) {
|
||||
this.parent(client);
|
||||
this._device = device;
|
||||
this._settings = settings;
|
||||
|
||||
this._autoConnectItem = this.item.menu.addAction(_("Connect"), Lang.bind(this, this._autoConnect));
|
||||
this.item.menu.addSettingsAction(_("Network Settings"), 'gnome-network-panel.desktop');
|
||||
|
||||
this._stateChangedId = this._device.connect('state-changed', Lang.bind(this, this._deviceStateChanged));
|
||||
this._activeConnectionChangedId = this._device.connect('notify::active-connection', Lang.bind(this, this._activeConnectionChanged));
|
||||
@ -301,6 +320,7 @@ const NMConnectionDevice = new Lang.Class({
|
||||
this._activeConnection = this._device.active_connection;
|
||||
|
||||
if (this._activeConnection) {
|
||||
ensureActiveConnectionProps(this._activeConnection, this._settings);
|
||||
let item = this._connectionItems.get(this._activeConnection._connection.get_uuid());
|
||||
item.setActiveConnection(this._activeConnection);
|
||||
}
|
||||
@ -356,8 +376,9 @@ const NMConnectionDevice = new Lang.Class({
|
||||
|
||||
switch(this._device.state) {
|
||||
case NetworkManager.DeviceState.DISCONNECTED:
|
||||
return _("Off");
|
||||
case NetworkManager.DeviceState.ACTIVATED:
|
||||
return '';
|
||||
return this.parent();
|
||||
case NetworkManager.DeviceState.UNMANAGED:
|
||||
/* Translators: this is for network devices that are physically present but are not
|
||||
under NetworkManager's control (and thus cannot be used in the menu) */
|
||||
@ -399,8 +420,11 @@ const NMDeviceModem = new Lang.Class({
|
||||
Extends: NMConnectionDevice,
|
||||
category: NMConnectionCategory.WWAN,
|
||||
|
||||
_init: function(client, device) {
|
||||
this.parent(client, device);
|
||||
_init: function(client, device, settings) {
|
||||
this.parent(client, device, settings);
|
||||
|
||||
this.item.menu.addMenuItem(createSettingsAction(_("Mobile Broadband Settings"), device));
|
||||
|
||||
this._mobileDevice = null;
|
||||
|
||||
let capabilities = device.current_capabilities;
|
||||
@ -414,16 +438,7 @@ const NMDeviceModem = new Lang.Class({
|
||||
this._mobileDevice = new ModemManager.ModemGsm(device.udi);
|
||||
|
||||
if (this._mobileDevice) {
|
||||
this._operatorNameId = this._mobileDevice.connect('notify::operator-name', Lang.bind(this, function() {
|
||||
if (this._operatorItem) {
|
||||
let name = this._mobileDevice.operator_name;
|
||||
if (name) {
|
||||
this._operatorItem.label.text = name;
|
||||
this._operatorItem.actor.show();
|
||||
} else
|
||||
this._operatorItem.actor.hide();
|
||||
}
|
||||
}));
|
||||
this._operatorNameId = this._mobileDevice.connect('notify::operator-name', Lang.bind(this, this._sync));
|
||||
this._signalQualityId = this._mobileDevice.connect('notify::signal-quality', Lang.bind(this, function() {
|
||||
this.emit('icon-changed');
|
||||
}));
|
||||
@ -448,6 +463,20 @@ const NMDeviceModem = new Lang.Class({
|
||||
this.parent();
|
||||
},
|
||||
|
||||
_getStatus: function() {
|
||||
if (!this._client.wwan_hardware_enabled)
|
||||
return _("Hardware Disabled");
|
||||
else if (!this._client.wwan_enabled)
|
||||
/* Translators: this is for a network device that cannot be activated
|
||||
because it's disabled by rfkill (airplane mode) */
|
||||
return _("Disabled");
|
||||
else if (this._device.state == NetworkManager.DeviceState.ACTIVATED &&
|
||||
this._mobileDevice && this._mobileDevice.operator_name)
|
||||
return this._mobileDevice.operator_name;
|
||||
else
|
||||
return this.parent();
|
||||
},
|
||||
|
||||
_getMenuIcon: function() {
|
||||
if (this._device.active_connection)
|
||||
return this.getIndicatorIcon();
|
||||
@ -477,6 +506,12 @@ const NMDeviceBluetooth = new Lang.Class({
|
||||
Extends: NMConnectionDevice,
|
||||
category: NMConnectionCategory.WWAN,
|
||||
|
||||
_init: function(client, device, settings) {
|
||||
this.parent(client, device, settings);
|
||||
|
||||
this.item.menu.addMenuItem(createSettingsAction(_("Mobile Broadband Settings"), device));
|
||||
},
|
||||
|
||||
_autoConnect: function() {
|
||||
// FIXME: DUN devices are configured like modems, so
|
||||
// We need to spawn the mobile wizard
|
||||
@ -514,31 +549,30 @@ const NMWirelessDialogItem = new Lang.Class({
|
||||
this._network = network;
|
||||
this._ap = network.accessPoints[0];
|
||||
|
||||
this.actor = new St.Button({ style_class: 'nm-dialog-item',
|
||||
can_focus: true,
|
||||
x_fill: true });
|
||||
this.actor = new St.BoxLayout({ style_class: 'nm-dialog-item',
|
||||
can_focus: true,
|
||||
reactive: true });
|
||||
this.actor.connect('key-focus-in', Lang.bind(this, function() {
|
||||
this.emit('selected');
|
||||
}));
|
||||
this.actor.connect('clicked', Lang.bind(this, function() {
|
||||
let action = new Clutter.ClickAction();
|
||||
action.connect('clicked', Lang.bind(this, function() {
|
||||
this.actor.grab_key_focus();
|
||||
}));
|
||||
|
||||
this._content = new St.BoxLayout({ style_class: 'nm-dialog-item-box' });
|
||||
this.actor.set_child(this._content);
|
||||
this.actor.add_action(action);
|
||||
|
||||
let title = ssidToLabel(this._ap.get_ssid());
|
||||
this._label = new St.Label({ text: title });
|
||||
|
||||
this.actor.label_actor = this._label;
|
||||
this._content.add(this._label, { x_align: St.Align.START });
|
||||
this.actor.add(this._label, { x_align: St.Align.START });
|
||||
|
||||
this._selectedIcon = new St.Icon({ style_class: 'nm-dialog-icon',
|
||||
icon_name: 'object-select-symbolic' });
|
||||
this._content.add(this._selectedIcon);
|
||||
this.actor.add(this._selectedIcon);
|
||||
|
||||
this._icons = new St.BoxLayout({ style_class: 'nm-dialog-icons' });
|
||||
this._content.add(this._icons, { expand: true, x_fill: false, x_align: St.Align.END });
|
||||
this.actor.add(this._icons, { expand: true, x_fill: false, x_align: St.Align.END });
|
||||
|
||||
this._secureIcon = new St.Icon({ style_class: 'nm-dialog-icon' });
|
||||
if (this._ap._secType != NMAccessPointSecurity.NONE)
|
||||
@ -547,18 +581,24 @@ const NMWirelessDialogItem = new Lang.Class({
|
||||
|
||||
this._signalIcon = new St.Icon({ style_class: 'nm-dialog-icon' });
|
||||
this._icons.add_actor(this._signalIcon);
|
||||
|
||||
this._sync();
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
this._signalIcon.icon_name = this._getSignalIcon();
|
||||
},
|
||||
|
||||
updateBestAP: function(ap) {
|
||||
this._ap = ap;
|
||||
this._signalIcon.icon_name = this._getIcon();
|
||||
this._sync();
|
||||
},
|
||||
|
||||
setActive: function(isActive) {
|
||||
this._selectedIcon.opacity = isActive ? 255 : 0;
|
||||
},
|
||||
|
||||
_getIcon: function() {
|
||||
_getSignalIcon: function() {
|
||||
if (this._ap.mode == NM80211Mode.ADHOC)
|
||||
return 'network-workgroup-symbolic';
|
||||
else
|
||||
@ -915,13 +955,13 @@ const NMWirelessDialog = new Lang.Class({
|
||||
|
||||
_selectNetwork: function(network) {
|
||||
if (this._selectedNetwork)
|
||||
this._selectedNetwork.item.actor.checked = false;
|
||||
this._selectedNetwork.item.actor.remove_style_pseudo_class('selected');
|
||||
|
||||
this._selectedNetwork = network;
|
||||
this._updateSensitivity();
|
||||
|
||||
if (this._selectedNetwork)
|
||||
this._selectedNetwork.item.actor.checked = true;
|
||||
this._selectedNetwork.item.actor.add_style_pseudo_class('selected');
|
||||
},
|
||||
|
||||
_createNetworkItem: function(network) {
|
||||
@ -952,9 +992,10 @@ const NMDeviceWireless = new Lang.Class({
|
||||
this._toggleItem.connect('activate', Lang.bind(this, this._toggleWifi));
|
||||
this.item.menu.addMenuItem(this._toggleItem);
|
||||
|
||||
this.item.menu.addSettingsAction(_("Network Settings"), 'gnome-network-panel.desktop');
|
||||
this.item.menu.addMenuItem(createSettingsAction(_("Wi-Fi Settings"), device));
|
||||
|
||||
this._wirelessEnabledChangedId = this._device.connect('notify::wireless-enabled', Lang.bind(this, this._sync));
|
||||
this._wirelessEnabledChangedId = this._client.connect('notify::wireless-enabled', Lang.bind(this, this._sync));
|
||||
this._wirelessHwEnabledChangedId = this._client.connect('notify::wireless-hardware-enabled', Lang.bind(this, this._sync));
|
||||
this._activeApChangedId = this._device.connect('notify::active-access-point', Lang.bind(this, this._activeApChanged));
|
||||
this._stateChangedId = this._device.connect('state-changed', Lang.bind(this, this._deviceStateChanged));
|
||||
|
||||
@ -974,6 +1015,14 @@ const NMDeviceWireless = new Lang.Class({
|
||||
this._activeAccessPoint.disconnect(this._strengthChangedId);
|
||||
this._strengthChangedId = 0;
|
||||
}
|
||||
if (this._wirelessEnabledChangedId) {
|
||||
this._client.disconnect(this._wirelessEnabledChangedId);
|
||||
this._wirelessEnabledChangedId = 0;
|
||||
}
|
||||
if (this._wirelessHwEnabledChangedId) {
|
||||
this._client.disconnect(this._wirelessHwEnabledChangedId);
|
||||
this._wirelessHwEnabledChangedId = 0;
|
||||
}
|
||||
|
||||
this.item.destroy();
|
||||
},
|
||||
@ -1032,6 +1081,7 @@ const NMDeviceWireless = new Lang.Class({
|
||||
|
||||
_sync: function() {
|
||||
this._toggleItem.label.text = this._client.wireless_enabled ? _("Turn Off") : _("Turn On");
|
||||
this._toggleItem.actor.visible = this._client.wireless_hardware_enabled;
|
||||
|
||||
this.item.status.text = this._getStatus();
|
||||
this.item.icon.icon_name = this._getMenuIcon();
|
||||
@ -1045,10 +1095,17 @@ const NMDeviceWireless = new Lang.Class({
|
||||
|
||||
_getStatus: function() {
|
||||
let ap = this._device.active_access_point;
|
||||
if (!ap)
|
||||
return _("Off"); // XXX -- interpret actual status
|
||||
|
||||
return ssidToLabel(ap.get_ssid());
|
||||
if (ap)
|
||||
return ssidToLabel(ap.get_ssid());
|
||||
else if (!this._client.wireless_hardware_enabled)
|
||||
return _("Hardware Disabled");
|
||||
else if (!this._client.wireless_enabled)
|
||||
return _("Off");
|
||||
else if (this._device.state == NetworkManager.DeviceState.DISCONNECTED)
|
||||
return _("Not Connected");
|
||||
else
|
||||
return '';
|
||||
},
|
||||
|
||||
_getMenuIcon: function() {
|
||||
@ -1059,7 +1116,8 @@ const NMDeviceWireless = new Lang.Class({
|
||||
},
|
||||
|
||||
getIndicatorIcon: function() {
|
||||
if (this._device.active_connection.state == NetworkManager.ActiveConnectionState.ACTIVATING)
|
||||
if (this._device.state >= NetworkManager.DeviceState.PREPARE &&
|
||||
this._device.state < NetworkManager.DeviceState.ACTIVATED)
|
||||
return 'network-wireless-acquiring-symbolic';
|
||||
|
||||
let ap = this._device.active_access_point;
|
||||
@ -1117,6 +1175,7 @@ const NMVPNConnectionItem = new Lang.Class({
|
||||
this.emit('activation-failed', reason);
|
||||
}
|
||||
|
||||
this.emit('icon-changed');
|
||||
this.parent();
|
||||
},
|
||||
|
||||
@ -1287,6 +1346,7 @@ const NMApplet = new Lang.Class({
|
||||
this._client.connect('notify::networking-enabled', Lang.bind(this, this._syncNMState));
|
||||
this._client.connect('notify::state', Lang.bind(this, this._syncNMState));
|
||||
this._client.connect('notify::primary-connection', Lang.bind(this, this._syncMainConnection));
|
||||
this._client.connect('notify::activating-connection', Lang.bind(this, this._syncMainConnection));
|
||||
this._client.connect('notify::active-connections', Lang.bind(this, this._syncVPNConnections));
|
||||
this._client.connect('device-added', Lang.bind(this, this._deviceAdded));
|
||||
this._client.connect('device-removed', Lang.bind(this, this._deviceRemoved));
|
||||
@ -1305,7 +1365,7 @@ const NMApplet = new Lang.Class({
|
||||
if (!this._source) {
|
||||
this._source = new MessageTray.Source(_("Network Manager"),
|
||||
'network-transmit-receive');
|
||||
this._source.policy = new NotificationDaemon.NotificationApplicationPolicy('gnome-network-panel');
|
||||
this._source.policy = new MessageTray.NotificationApplicationPolicy('gnome-network-panel');
|
||||
|
||||
this._source.connect('destroy', Lang.bind(this, function() {
|
||||
this._source = null;
|
||||
@ -1417,28 +1477,18 @@ const NMApplet = new Lang.Class({
|
||||
devices.splice(pos, 1);
|
||||
},
|
||||
|
||||
_ensureActiveConnectionProps: function(a) {
|
||||
if (!a._connection) {
|
||||
a._connection = this._settings.get_connection_by_path(a.connection);
|
||||
|
||||
// This list is guaranteed to have only one device in it.
|
||||
let device = a.get_devices()[0]._delegate;
|
||||
a._primaryDevice = device;
|
||||
}
|
||||
},
|
||||
|
||||
_getMainConnection: function() {
|
||||
let connection;
|
||||
|
||||
connection = this._client.get_primary_connection();
|
||||
if (connection) {
|
||||
this._ensureActiveConnectionProps(connection);
|
||||
ensureActiveConnectionProps(connection, this._settings);
|
||||
return connection;
|
||||
}
|
||||
|
||||
connection = this._client.get_activating_connection();
|
||||
if (connection) {
|
||||
this._ensureActiveConnectionProps(connection);
|
||||
ensureActiveConnectionProps(connection, this._settings);
|
||||
return connection;
|
||||
}
|
||||
|
||||
@ -1474,7 +1524,7 @@ const NMApplet = new Lang.Class({
|
||||
return (a instanceof NMClient.VPNConnection);
|
||||
});
|
||||
vpnConnections.forEach(Lang.bind(this, function(a) {
|
||||
this._ensureActiveConnectionProps(a);
|
||||
ensureActiveConnectionProps(a, this._settings);
|
||||
}));
|
||||
this._vpnSection.setActiveConnections(vpnConnections);
|
||||
|
||||
@ -1577,6 +1627,7 @@ const NMApplet = new Lang.Class({
|
||||
_updateIcon: function() {
|
||||
if (!this._client.networking_enabled || !this._mainConnection) {
|
||||
this._primaryIndicator.icon_name = 'network-offline-symbolic';
|
||||
this._primaryIndicator.visible = true;
|
||||
} else {
|
||||
let dev = this._mainConnection._primaryDevice;
|
||||
this._primaryIndicator.visible = (dev != null);
|
||||
|
@ -8,20 +8,22 @@ const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const BUS_NAME = 'org.gnome.SettingsDaemon.Power';
|
||||
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
|
||||
const BUS_NAME = 'org.freedesktop.UPower';
|
||||
const OBJECT_PATH = '/org/freedesktop/UPower/devices/DisplayDevice';
|
||||
|
||||
const PowerManagerInterface = <interface name="org.gnome.SettingsDaemon.Power">
|
||||
<method name="GetDevices">
|
||||
<arg type="a(susdut)" direction="out" />
|
||||
</method>
|
||||
<method name="GetPrimaryDevice">
|
||||
<arg type="(susdut)" direction="out" />
|
||||
</method>
|
||||
<property name="Icon" type="s" access="read" />
|
||||
</interface>;
|
||||
const DisplayDeviceInterface = '<node> \
|
||||
<interface name="org.freedesktop.UPower.Device"> \
|
||||
<property name="Type" type="u" access="read"/> \
|
||||
<property name="State" type="u" access="read"/> \
|
||||
<property name="Percentage" type="d" access="read"/> \
|
||||
<property name="TimeToEmpty" type="x" access="read"/> \
|
||||
<property name="TimeToFull" type="x" access="read"/> \
|
||||
<property name="IsPresent" type="b" access="read"/> \
|
||||
<property name="IconName" type="s" access="read"/> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(PowerManagerInterface);
|
||||
const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(DisplayDeviceInterface);
|
||||
|
||||
const Indicator = new Lang.Class({
|
||||
Name: 'PowerIndicator',
|
||||
@ -32,7 +34,7 @@ const Indicator = new Lang.Class({
|
||||
|
||||
this._indicator = this._addIndicator();
|
||||
|
||||
this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
|
||||
this._proxy = new PowerManagerProxy(Gio.DBus.system, BUS_NAME, OBJECT_PATH,
|
||||
Lang.bind(this, function(proxy, error) {
|
||||
if (error) {
|
||||
log(error.message);
|
||||
@ -43,7 +45,7 @@ const Indicator = new Lang.Class({
|
||||
this._sync();
|
||||
}));
|
||||
|
||||
this._item = new PopupMenu.PopupSubMenuMenuItem(_("Battery"), true);
|
||||
this._item = new PopupMenu.PopupSubMenuMenuItem("", true);
|
||||
this._item.menu.addSettingsAction(_("Power Settings"), 'gnome-power-panel.desktop');
|
||||
this.menu.addMenuItem(this._item);
|
||||
|
||||
@ -56,11 +58,18 @@ const Indicator = new Lang.Class({
|
||||
this.menu.setSensitive(sensitive);
|
||||
},
|
||||
|
||||
_statusForDevice: function(device) {
|
||||
let [device_id, device_type, icon, percentage, state, seconds] = device;
|
||||
_getStatus: function() {
|
||||
let seconds = 0;
|
||||
|
||||
if (state == UPower.DeviceState.FULLY_CHARGED)
|
||||
if (this._proxy.State == UPower.DeviceState.FULLY_CHARGED)
|
||||
return _("Fully Charged");
|
||||
else if (this._proxy.State == UPower.DeviceState.CHARGING)
|
||||
seconds = this._proxy.TimeToFull;
|
||||
else if (this._proxy.State == UPower.DeviceState.DISCHARGING)
|
||||
seconds = this._proxy.TimeToEmpty;
|
||||
// state is one of PENDING_CHARGING, PENDING_DISCHARGING
|
||||
else
|
||||
return _("Estimating…");
|
||||
|
||||
let time = Math.round(seconds / 60);
|
||||
if (time == 0) {
|
||||
@ -72,52 +81,43 @@ const Indicator = new Lang.Class({
|
||||
let minutes = time % 60;
|
||||
let hours = Math.floor(time / 60);
|
||||
|
||||
if (state == UPower.DeviceState.DISCHARGING) {
|
||||
if (this._proxy.State == UPower.DeviceState.DISCHARGING) {
|
||||
// Translators: this is <hours>:<minutes> Remaining (<percentage>)
|
||||
return _("%d\u2236%02d Remaining (%d%%)").format(hours, minutes, percentage);
|
||||
return _("%d\u2236%02d Remaining (%d%%)").format(hours, minutes, this._proxy.Percentage);
|
||||
}
|
||||
|
||||
if (state == UPower.DeviceState.CHARGING) {
|
||||
if (this._proxy.State == UPower.DeviceState.CHARGING) {
|
||||
// Translators: this is <hours>:<minutes> Until Full (<percentage>)
|
||||
return _("%d\u2236%02d Until Full (%d%%)").format(hours, minutes, percentage);
|
||||
return _("%d\u2236%02d Until Full (%d%%)").format(hours, minutes, this._proxy.Percentage);
|
||||
}
|
||||
|
||||
// state is one of PENDING_CHARGING, PENDING_DISCHARGING
|
||||
return _("Estimating…");
|
||||
},
|
||||
|
||||
_syncStatusLabel: function() {
|
||||
this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(result, error) {
|
||||
if (error) {
|
||||
this._item.actor.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
let [device] = result;
|
||||
let [device_id, device_type] = device;
|
||||
if (device_type == UPower.DeviceKind.BATTERY) {
|
||||
this._item.status.text = this._statusForDevice(device);
|
||||
this._item.actor.show();
|
||||
} else {
|
||||
this._item.actor.hide();
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
_syncIcon: function() {
|
||||
let icon = this._proxy.Icon;
|
||||
if (icon) {
|
||||
let gicon = Gio.icon_new_for_string(icon);
|
||||
this._indicator.gicon = gicon;
|
||||
this._item.icon.gicon = gicon;
|
||||
} else {
|
||||
// If there's no battery, then we use the power icon.
|
||||
this._indicator.icon_name = 'system-shutdown-symbolic';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
this._syncIcon();
|
||||
this._syncStatusLabel();
|
||||
}
|
||||
// Do we have batteries or a UPS?
|
||||
let visible = this._proxy.IsPresent;
|
||||
if (visible) {
|
||||
this._item.actor.show();
|
||||
} else {
|
||||
// If there's no battery, then we use the power icon.
|
||||
this._item.actor.hide();
|
||||
this._indicator.icon_name = 'system-shutdown-symbolic';
|
||||
return;
|
||||
}
|
||||
|
||||
// The icons
|
||||
let icon = this._proxy.IconName;
|
||||
this._indicator.icon_name = icon;
|
||||
this._item.icon.icon_name = icon;
|
||||
|
||||
// The status label
|
||||
this._item.status.text = this._getStatus();
|
||||
|
||||
// The sub-menu heading
|
||||
if (this._proxy.Type == UPower.DeviceKind.UPS)
|
||||
this._item.label.text = _("UPS");
|
||||
else
|
||||
this._item.label.text = _("Battery");
|
||||
},
|
||||
});
|
||||
|
@ -9,9 +9,11 @@ const PopupMenu = imports.ui.popupMenu;
|
||||
const BUS_NAME = 'org.gnome.SettingsDaemon.Rfkill';
|
||||
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Rfkill';
|
||||
|
||||
const RfkillManagerInterface = <interface name="org.gnome.SettingsDaemon.Rfkill">
|
||||
<property name="AirplaneMode" type="b" access="readwrite" />
|
||||
</interface>;
|
||||
const RfkillManagerInterface = '<node> \
|
||||
<interface name="org.gnome.SettingsDaemon.Rfkill"> \
|
||||
<property name="AirplaneMode" type="b" access="readwrite" /> \
|
||||
</interface> \
|
||||
</node>';
|
||||
|
||||
const RfkillManagerProxy = Gio.DBusProxy.makeProxyWrapper(RfkillManagerInterface);
|
||||
|
||||
|
@ -372,7 +372,11 @@ const Indicator = new Lang.Class({
|
||||
Main.overview.hide();
|
||||
if (Main.screenShield)
|
||||
Main.screenShield.lock(false);
|
||||
Gdm.goto_login_session_sync(null);
|
||||
|
||||
Clutter.threads_add_repaint_func_full(Clutter.RepaintFlags.POST_PAINT, function() {
|
||||
Gdm.goto_login_session_sync(null);
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
_onQuitSessionActivate: function() {
|
||||
|
@ -16,10 +16,8 @@ const OverviewControls = imports.ui.overviewControls;
|
||||
const Params = imports.misc.params;
|
||||
const RemoteSearch = imports.ui.remoteSearch;
|
||||
const Search = imports.ui.search;
|
||||
const SearchDisplay = imports.ui.searchDisplay;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Wanda = imports.ui.wanda;
|
||||
const WorkspacesView = imports.ui.workspacesView;
|
||||
|
||||
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
|
||||
@ -103,7 +101,7 @@ const ViewSelector = new Lang.Class({
|
||||
this._appsPage = this._addPage(this.appDisplay.actor,
|
||||
_("Applications"), 'view-grid-symbolic');
|
||||
|
||||
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
|
||||
this._searchResults = new Search.SearchResults(this._searchSystem);
|
||||
this._searchPage = this._addPage(this._searchResults.actor,
|
||||
_("Search"), 'edit-find-symbolic',
|
||||
{ a11yFocus: this._entry });
|
||||
@ -114,8 +112,6 @@ const ViewSelector = new Lang.Class({
|
||||
this._searchSettings.connect('changed::sort-order', Lang.bind(this, this._reloadRemoteProviders));
|
||||
|
||||
// Default search providers
|
||||
// Wanda comes obviously first
|
||||
this.addSearchProvider(new Wanda.WandaSearchProvider());
|
||||
this.addSearchProvider(new AppDisplay.AppSearchProvider());
|
||||
|
||||
// Load remote search providers provided by applications
|
||||
|
156
js/ui/wanda.js
@ -1,156 +0,0 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const GdkPixbuf = imports.gi.GdkPixbuf;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const IconGrid = imports.ui.iconGrid;
|
||||
const Layout = imports.ui.layout;
|
||||
const Main = imports.ui.main;
|
||||
const Panel = imports.ui.panel;
|
||||
|
||||
const FISH_NAME = 'wanda';
|
||||
const FISH_FILENAME = 'wanda.png';
|
||||
const FISH_SPEED = 300;
|
||||
const FISH_COMMAND = 'fortune';
|
||||
// The size of an individual frame in the animation
|
||||
const FISH_HEIGHT = 22;
|
||||
const FISH_WIDTH = 36;
|
||||
|
||||
const FISH_GROUP = 'Fish Animation';
|
||||
|
||||
const MAGIC_FISH_KEY = 'free the fish';
|
||||
|
||||
const WandaIcon = new Lang.Class({
|
||||
Name: 'WandaIcon',
|
||||
Extends: IconGrid.BaseIcon,
|
||||
|
||||
_init : function(fish, label, params) {
|
||||
this.parent(label, params);
|
||||
|
||||
this._fish = fish;
|
||||
this._imageFile = GLib.build_filenamev([global.datadir, fish + '.png']);
|
||||
|
||||
this._imgHeight = FISH_HEIGHT;
|
||||
this._imgWidth = FISH_WIDTH;
|
||||
},
|
||||
|
||||
createIcon: function(iconSize) {
|
||||
this._animations = new Panel.Animation(this._imageFile, this._imgWidth, this._imgHeight, FISH_SPEED);
|
||||
this._animations.play();
|
||||
return this._animations.actor;
|
||||
},
|
||||
|
||||
_createIconTexture: function(size) {
|
||||
if (size == this.iconSize)
|
||||
return;
|
||||
|
||||
this.parent(size);
|
||||
}
|
||||
});
|
||||
|
||||
const WandaIconBin = new Lang.Class({
|
||||
Name: 'WandaIconBin',
|
||||
|
||||
_init: function(fish, label, params) {
|
||||
this.actor = new St.Bin({ reactive: true,
|
||||
track_hover: true });
|
||||
this.icon = new WandaIcon(fish, label, params);
|
||||
|
||||
this.actor.child = this.icon.actor;
|
||||
this.actor.label_actor = this.icon.label;
|
||||
},
|
||||
});
|
||||
|
||||
const FortuneDialog = new Lang.Class({
|
||||
Name: 'FortuneDialog',
|
||||
|
||||
_init: function(name, command) {
|
||||
let text;
|
||||
|
||||
try {
|
||||
let [res, stdout, stderr, status] = GLib.spawn_command_line_sync(command);
|
||||
text = String.fromCharCode.apply(null, stdout);
|
||||
} catch(e) {
|
||||
text = _("Sorry, no wisdom for you today:\n%s").format(e.message);
|
||||
}
|
||||
|
||||
this._title = new St.Label({ style_class: 'prompt-dialog-headline',
|
||||
text: _("%s the Oracle says").format(name) });
|
||||
this._label = new St.Label({ style_class: 'prompt-dialog-description',
|
||||
text: text });
|
||||
this._label.clutter_text.line_wrap = true;
|
||||
|
||||
this._box = new St.BoxLayout({ vertical: true,
|
||||
style_class: 'prompt-dialog' // this is just to force a reasonable width
|
||||
});
|
||||
this._box.add(this._title, { align: St.Align.MIDDLE });
|
||||
this._box.add(this._label, { expand: true });
|
||||
|
||||
this._button = new St.Button({ button_mask: St.ButtonMask.ONE,
|
||||
style_class: 'modal-dialog',
|
||||
reactive: true });
|
||||
this._button.connect('clicked', Lang.bind(this, this.destroy));
|
||||
this._button.child = this._box;
|
||||
|
||||
this._bin = new St.Bin({ x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.MIDDLE });
|
||||
this._bin.add_constraint(new Layout.MonitorConstraint({ primary: true }));
|
||||
this._bin.add_actor(this._button);
|
||||
|
||||
Main.layoutManager.addChrome(this._bin);
|
||||
|
||||
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 10, Lang.bind(this, this.destroy));
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this._bin.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
function capitalize(str) {
|
||||
return str[0].toUpperCase() + str.substring(1, str.length);
|
||||
}
|
||||
|
||||
const WandaSearchProvider = new Lang.Class({
|
||||
Name: 'WandaSearchProvider',
|
||||
|
||||
_init: function() {
|
||||
this.id = 'wanda';
|
||||
},
|
||||
|
||||
getResultMetas: function(fish, callback) {
|
||||
callback([{ 'id': fish[0], // there may be many fish in the sea, but
|
||||
// only one which speaks the truth!
|
||||
'name': capitalize(fish[0]),
|
||||
'createIcon': function(iconSize) {
|
||||
return new St.Icon({ gicon: Gio.icon_new_for_string('face-smile'),
|
||||
icon_size: iconSize });
|
||||
}
|
||||
}]);
|
||||
},
|
||||
|
||||
getInitialResultSet: function(terms) {
|
||||
if (terms.join(' ') == MAGIC_FISH_KEY) {
|
||||
this.searchSystem.setResults(this, [ FISH_NAME ]);
|
||||
} else {
|
||||
this.searchSystem.setResults(this, []);
|
||||
}
|
||||
},
|
||||
|
||||
getSubsearchResultSet: function(previousResults, terms) {
|
||||
this.getInitialResultSet(terms);
|
||||
},
|
||||
|
||||
activateResult: function(fish) {
|
||||
if (this._dialog)
|
||||
this._dialog.destroy();
|
||||
this._dialog = new FortuneDialog(capitalize(fish), FISH_COMMAND);
|
||||
},
|
||||
|
||||
createResultObject: function (resultMeta, terms) {
|
||||
return new WandaIconBin(resultMeta.id, resultMeta.name);
|
||||
}
|
||||
});
|
@ -39,6 +39,9 @@ const WindowAttentionHandler = new Lang.Class({
|
||||
let [title, banner] = this._getTitleAndBanner(app, window);
|
||||
|
||||
let notification = new MessageTray.Notification(source, title, banner);
|
||||
notification.connect('clicked', function() {
|
||||
source.open();
|
||||
});
|
||||
notification.setForFeedback(true);
|
||||
|
||||
source.notify(notification);
|
||||
@ -79,7 +82,7 @@ const Source = new Lang.Class({
|
||||
return this._app.create_icon_texture(size);
|
||||
},
|
||||
|
||||
open : function(notification) {
|
||||
open: function() {
|
||||
Main.activateWindow(this._window);
|
||||
this.destroy();
|
||||
}
|
||||
|
@ -20,8 +20,6 @@ const FOCUS_ANIMATION_TIME = 0.15;
|
||||
|
||||
const WINDOW_DND_SIZE = 256;
|
||||
|
||||
const SCROLL_SCALE_AMOUNT = 100 / 5;
|
||||
|
||||
const WINDOW_CLONE_MAXIMUM_SCALE = 0.7;
|
||||
|
||||
const LIGHTBOX_FADE_TIME = 0.1;
|
||||
@ -345,19 +343,6 @@ const WindowOverlay = new Lang.Class({
|
||||
this._animateVisible();
|
||||
},
|
||||
|
||||
fadeIn: function() {
|
||||
if (!this._hidden)
|
||||
return;
|
||||
|
||||
this.show();
|
||||
this.title.opacity = 0;
|
||||
this._parentActor.raise_top();
|
||||
Tweener.addTween(this.title,
|
||||
{ opacity: 255,
|
||||
time: CLOSE_BUTTON_FADE_TIME,
|
||||
transition: 'easeOutQuad' });
|
||||
},
|
||||
|
||||
chromeHeights: function () {
|
||||
return [Math.max(this.borderSize, this.closeButton.height - this.closeButton._overlap),
|
||||
this.title.height + this.title._spacing];
|
||||
@ -374,7 +359,6 @@ const WindowOverlay = new Lang.Class({
|
||||
let border = this.border;
|
||||
|
||||
Tweener.removeTweens(button);
|
||||
Tweener.removeTweens(title);
|
||||
Tweener.removeTweens(border);
|
||||
|
||||
let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
|
||||
@ -1144,7 +1128,7 @@ const Workspace = new Lang.Class({
|
||||
clone.actor.set_scale(scale, scale);
|
||||
clone.actor.set_opacity(255);
|
||||
clone.overlay.relayout(false);
|
||||
this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace);
|
||||
this._showWindowOverlay(clone, overlay);
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1174,23 +1158,19 @@ const Workspace = new Lang.Class({
|
||||
time: Overview.ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this, function() {
|
||||
this._showWindowOverlay(clone, overlay, true);
|
||||
this._showWindowOverlay(clone, overlay);
|
||||
})
|
||||
});
|
||||
|
||||
clone.overlay.relayout(true);
|
||||
},
|
||||
|
||||
_showWindowOverlay: function(clone, overlay, fade) {
|
||||
_showWindowOverlay: function(clone, overlay) {
|
||||
if (clone.inDrag)
|
||||
return;
|
||||
|
||||
if (overlay) {
|
||||
if (fade)
|
||||
overlay.fadeIn();
|
||||
else
|
||||
if (overlay && overlay._hidden)
|
||||
overlay.show();
|
||||
}
|
||||
},
|
||||
|
||||
_delayedWindowRepositioning: function() {
|
||||
@ -1641,9 +1621,7 @@ const Workspace = new Lang.Class({
|
||||
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);
|
||||
metaWindow.change_workspace_by_index(index, false);
|
||||
return true;
|
||||
} else if (source.shellWorkspaceLaunch) {
|
||||
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1,
|
||||
|
@ -507,9 +507,7 @@ const WorkspaceThumbnail = new Lang.Class({
|
||||
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);
|
||||
metaWindow.change_workspace_by_index(this.metaWorkspace.index(), false);
|
||||
return true;
|
||||
} else if (source.shellWorkspaceLaunch) {
|
||||
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1,
|
||||
@ -536,20 +534,6 @@ const ThumbnailsBox = new Lang.Class({
|
||||
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||
this.actor._delegate = this;
|
||||
|
||||
// When we animate the scale, we don't animate the requested size of the thumbnails, rather
|
||||
// we ask for our final size and then animate within that size. This slightly simplifies the
|
||||
// interaction with the main workspace windows (instead of constantly reallocating them
|
||||
// to a new size, they get a new size once, then use the standard window animation code
|
||||
// allocate the windows to their new positions), however it causes problems for drawing
|
||||
// the background and border wrapped around the thumbnail as we animate - we can't just pack
|
||||
// the container into a box and set style properties on the box since that box would wrap
|
||||
// around the final size not the animating size. So instead we fake the background with
|
||||
// an actor underneath the content and adjust the allocation of our children to leave space
|
||||
// for the border and padding of the background actor.
|
||||
this._background = new St.Bin({ style_class: 'workspace-thumbnails-background' });
|
||||
|
||||
this.actor.add_actor(this._background);
|
||||
|
||||
let indicator = new St.Bin({ style_class: 'workspace-thumbnail-indicator' });
|
||||
|
||||
// We don't want the indicator to affect drag-and-drop
|
||||
@ -753,14 +737,12 @@ const ThumbnailsBox = new Lang.Class({
|
||||
|
||||
// ... move them down one.
|
||||
windows.forEach(function(win) {
|
||||
win.meta_window.change_workspace_by_index(win.get_workspace() + 1,
|
||||
true, time);
|
||||
win.meta_window.change_workspace_by_index(win.get_workspace() + 1, true);
|
||||
});
|
||||
|
||||
if (isWindow)
|
||||
// ... and bam, a workspace, good as new.
|
||||
source.metaWindow.change_workspace_by_index(newWorkspaceIndex,
|
||||
true, time);
|
||||
source.metaWindow.change_workspace_by_index(newWorkspaceIndex, true);
|
||||
else if (source.shellWorkspaceLaunch) {
|
||||
source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex,
|
||||
timestamp: time });
|
||||
@ -1042,9 +1024,6 @@ const ThumbnailsBox = new Lang.Class({
|
||||
},
|
||||
|
||||
_getPreferredHeight: function(actor, forWidth, alloc) {
|
||||
// See comment about this._background in _init()
|
||||
let themeNode = this._background.get_theme_node();
|
||||
|
||||
// Note that for getPreferredWidth/Height we cheat a bit and skip propagating
|
||||
// the size request to our children because we know how big they are and know
|
||||
// that the actors aren't depending on the virtual functions being called.
|
||||
@ -1052,24 +1031,21 @@ const ThumbnailsBox = new Lang.Class({
|
||||
if (this._thumbnails.length == 0)
|
||||
return;
|
||||
|
||||
let spacing = this.actor.get_theme_node().get_length('spacing');
|
||||
let themeNode = this.actor.get_theme_node();
|
||||
|
||||
let spacing = themeNode.get_length('spacing');
|
||||
let nWorkspaces = global.screen.n_workspaces;
|
||||
let totalSpacing = (nWorkspaces - 1) * spacing;
|
||||
|
||||
[alloc.min_size, alloc.natural_size] =
|
||||
themeNode.adjust_preferred_height(totalSpacing,
|
||||
totalSpacing + nWorkspaces * this._porthole.height * MAX_THUMBNAIL_SCALE);
|
||||
alloc.min_size = totalSpacing;
|
||||
alloc.natural_size = totalSpacing + nWorkspaces * this._porthole.height * MAX_THUMBNAIL_SCALE;
|
||||
},
|
||||
|
||||
_getPreferredWidth: function(actor, forHeight, alloc) {
|
||||
// See comment about this._background in _init()
|
||||
let themeNode = this._background.get_theme_node();
|
||||
|
||||
if (this._thumbnails.length == 0)
|
||||
return;
|
||||
|
||||
// We don't animate our preferred width, which is always reported according
|
||||
// to the actual number of current workspaces, we just animate within that
|
||||
let themeNode = this.actor.get_theme_node();
|
||||
|
||||
let spacing = this.actor.get_theme_node().get_length('spacing');
|
||||
let nWorkspaces = global.screen.n_workspaces;
|
||||
@ -1081,28 +1057,26 @@ const ThumbnailsBox = new Lang.Class({
|
||||
scale = Math.min(scale, MAX_THUMBNAIL_SCALE);
|
||||
|
||||
let width = Math.round(this._porthole.width * scale);
|
||||
[alloc.min_size, alloc.natural_size] =
|
||||
themeNode.adjust_preferred_width(width, width);
|
||||
alloc.min_size = width;
|
||||
alloc.natural_size = width;
|
||||
},
|
||||
|
||||
_allocate: function(actor, box, flags) {
|
||||
let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL);
|
||||
|
||||
// See comment about this._background in _init()
|
||||
let themeNode = this._background.get_theme_node();
|
||||
let contentBox = themeNode.get_content_box(box);
|
||||
|
||||
if (this._thumbnails.length == 0) // not visible
|
||||
return;
|
||||
|
||||
let themeNode = this.actor.get_theme_node();
|
||||
|
||||
let portholeWidth = this._porthole.width;
|
||||
let portholeHeight = this._porthole.height;
|
||||
let spacing = this.actor.get_theme_node().get_length('spacing');
|
||||
let spacing = themeNode.get_length('spacing');
|
||||
|
||||
// Compute the scale we'll need once everything is updated
|
||||
let nWorkspaces = global.screen.n_workspaces;
|
||||
let totalSpacing = (nWorkspaces - 1) * spacing;
|
||||
let avail = (contentBox.y2 - contentBox.y1) - totalSpacing;
|
||||
let avail = (box.y2 - box.y1) - totalSpacing;
|
||||
|
||||
let newScale = (avail / nWorkspaces) / portholeHeight;
|
||||
newScale = Math.min(newScale, MAX_THUMBNAIL_SCALE);
|
||||
@ -1131,21 +1105,6 @@ const ThumbnailsBox = new Lang.Class({
|
||||
else
|
||||
slideOffset = thumbnailWidth + themeNode.get_padding(St.Side.RIGHT);
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
|
||||
// The background is horizontally restricted to correspond to the current thumbnail size
|
||||
// but otherwise covers the entire allocation
|
||||
if (rtl) {
|
||||
childBox.x1 = box.x1;
|
||||
childBox.x2 = box.x2 - ((contentBox.x2 - contentBox.x1) - thumbnailWidth);
|
||||
} else {
|
||||
childBox.x1 = box.x1 + ((contentBox.x2 - contentBox.x1) - thumbnailWidth);
|
||||
childBox.x2 = box.x2;
|
||||
}
|
||||
childBox.y1 = box.y1;
|
||||
childBox.y2 = box.y2;
|
||||
this._background.allocate(childBox, flags);
|
||||
|
||||
let indicatorY1 = this._indicatorY;
|
||||
let indicatorY2;
|
||||
// when not animating, the workspace position overrides this._indicatorY
|
||||
@ -1157,7 +1116,7 @@ const ThumbnailsBox = new Lang.Class({
|
||||
let indicatorLeftFullBorder = indicatorThemeNode.get_padding(St.Side.LEFT) + indicatorThemeNode.get_border_width(St.Side.LEFT);
|
||||
let indicatorRightFullBorder = indicatorThemeNode.get_padding(St.Side.RIGHT) + indicatorThemeNode.get_border_width(St.Side.RIGHT);
|
||||
|
||||
let y = contentBox.y1;
|
||||
let y = box.y1;
|
||||
|
||||
if (this._dropPlaceholderPos == -1) {
|
||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
|
||||
@ -1165,6 +1124,8 @@ const ThumbnailsBox = new Lang.Class({
|
||||
}));
|
||||
}
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
|
||||
for (let i = 0; i < this._thumbnails.length; i++) {
|
||||
let thumbnail = this._thumbnails[i];
|
||||
|
||||
@ -1173,10 +1134,10 @@ const ThumbnailsBox = new Lang.Class({
|
||||
|
||||
let x1, x2;
|
||||
if (rtl) {
|
||||
x1 = contentBox.x1 + slideOffset * thumbnail.slidePosition;
|
||||
x1 = box.x1 + slideOffset * thumbnail.slidePosition;
|
||||
x2 = x1 + thumbnailWidth;
|
||||
} else {
|
||||
x1 = contentBox.x2 - thumbnailWidth + slideOffset * thumbnail.slidePosition;
|
||||
x1 = box.x2 - thumbnailWidth + slideOffset * thumbnail.slidePosition;
|
||||
x2 = x1 + thumbnailWidth;
|
||||
}
|
||||
|
||||
@ -1223,11 +1184,11 @@ const ThumbnailsBox = new Lang.Class({
|
||||
}
|
||||
|
||||
if (rtl) {
|
||||
childBox.x1 = contentBox.x1;
|
||||
childBox.x2 = contentBox.x1 + thumbnailWidth;
|
||||
childBox.x1 = box.x1;
|
||||
childBox.x2 = box.x1 + thumbnailWidth;
|
||||
} else {
|
||||
childBox.x1 = contentBox.x2 - thumbnailWidth;
|
||||
childBox.x2 = contentBox.x2;
|
||||
childBox.x1 = box.x2 - thumbnailWidth;
|
||||
childBox.x2 = box.x2;
|
||||
}
|
||||
childBox.x1 -= indicatorLeftFullBorder;
|
||||
childBox.x2 += indicatorRightFullBorder;
|
||||
|
@ -62,7 +62,6 @@ const WorkspacesView = new Lang.Class({
|
||||
this._animating = false; // tweening
|
||||
this._scrolling = false; // swipe-scrolling
|
||||
this._animatingScroll = false; // programatically updating the adjustment
|
||||
this._zoomOut = false; // zoom to a larger area
|
||||
this._inDrag = false; // dragging a window
|
||||
|
||||
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
|
||||
@ -168,14 +167,6 @@ const WorkspacesView = new Lang.Class({
|
||||
this._workspaces[i].setActualGeometry(geom);
|
||||
},
|
||||
|
||||
_lookupWorkspaceForMetaWindow: function (metaWindow) {
|
||||
for (let i = 0; i < this._workspaces.length; i++) {
|
||||
if (this._workspaces[i].containsMetaWindow(metaWindow))
|
||||
return this._workspaces[i];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
getActiveWorkspace: function() {
|
||||
let active = global.screen.get_active_workspace_index();
|
||||
return this._workspaces[active];
|
||||
@ -433,10 +424,6 @@ const WorkspacesView = new Lang.Class({
|
||||
this._workspaces[i].actor.y += dy;
|
||||
}
|
||||
},
|
||||
|
||||
_getWorkspaceIndexToRemove: function() {
|
||||
return global.screen.get_active_workspace_index();
|
||||
}
|
||||
});
|
||||
Signals.addSignalMethods(WorkspacesView.prototype);
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const Main = imports.ui.main;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const DND = imports.ui.dnd;
|
||||
@ -20,7 +21,8 @@ const XdndHandler = new Lang.Class({
|
||||
Main.uiGroup.add_actor(this._dummy);
|
||||
this._dummy.hide();
|
||||
|
||||
global.init_xdnd();
|
||||
if (!Meta.is_wayland_compositor())
|
||||
global.init_xdnd();
|
||||
|
||||
global.connect('xdnd-enter', Lang.bind(this, this._onEnter));
|
||||
global.connect('xdnd-position-changed', Lang.bind(this, this._onPositionChanged));
|
||||
|
@ -4,6 +4,7 @@
|
||||
data/50-gnome-shell-system.xml.in
|
||||
data/gnome-shell.desktop.in.in
|
||||
data/gnome-shell-extension-prefs.desktop.in.in
|
||||
data/gnome-shell-wayland.desktop.in.in
|
||||
data/org.gnome.shell.gschema.xml.in.in
|
||||
js/extensionPrefs/main.js
|
||||
js/gdm/authPrompt.js
|
||||
@ -37,7 +38,7 @@ js/ui/panel.js
|
||||
js/ui/popupMenu.js
|
||||
js/ui/runDialog.js
|
||||
js/ui/screenShield.js
|
||||
js/ui/searchDisplay.js
|
||||
js/ui/search.js
|
||||
js/ui/shellEntry.js
|
||||
js/ui/shellMountOperation.js
|
||||
js/ui/status/accessibility.js
|
||||
@ -51,7 +52,6 @@ js/ui/status/system.js
|
||||
js/ui/status/volume.js
|
||||
js/ui/unlockDialog.js
|
||||
js/ui/viewSelector.js
|
||||
js/ui/wanda.js
|
||||
js/ui/windowAttentionHandler.js
|
||||
js/ui/windowManager.js
|
||||
src/calendar-server/evolution-calendar.desktop.in.in
|
||||
|
1828
po/ca@valencia.po
175
po/de.po
@ -18,18 +18,17 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2013-09-07 19:18+0000\n"
|
||||
"PO-Revision-Date: 2013-09-08 00:01+0200\n"
|
||||
"Last-Translator: Tobias Endrigkeit <tobiasendrigkeit@outlook.com>\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-09-25 15:24+0200\n"
|
||||
"PO-Revision-Date: 2013-09-25 15:25+0100\n"
|
||||
"Last-Translator: Christian Kirbach <christian.kirbach@gmail.com>\n"
|
||||
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
|
||||
"Language: de_DE\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Gtranslator 2.91.6\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
|
||||
#: ../data/50-gnome-shell-system.xml.in.h:1
|
||||
msgid "System"
|
||||
@ -60,6 +59,7 @@ msgid "GNOME Shell"
|
||||
msgstr "GNOME-Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
#: ../data/gnome-shell-wayland.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Fenster verwalten und Anwendungen starten"
|
||||
|
||||
@ -72,6 +72,10 @@ msgstr "Einstellungen für Erweiterungen der GNOME-Shell"
|
||||
msgid "Configure GNOME Shell Extensions"
|
||||
msgstr "Erweiterungen der GNOME-Shell einrichten"
|
||||
|
||||
#: ../data/gnome-shell-wayland.desktop.in.in.h:1
|
||||
msgid "GNOME Shell (wayland compositor)"
|
||||
msgstr "GNOME-Shell (Wayland Composition)"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:1
|
||||
msgid "Enable internal tools useful for developers and testers from Alt-F2"
|
||||
msgstr "Interne Werkzeuge für Entwickler und Tester mit Alt+F2 aktivieren"
|
||||
@ -277,6 +281,11 @@ msgstr "Arbeitsflächen dynamisch verwalten"
|
||||
msgid "Workspaces only on primary monitor"
|
||||
msgstr "Arbeitsflächen nur auf dem primären Bildschirm"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:38
|
||||
msgid "Delay focus changes in mouse mode until the pointer stops moving"
|
||||
msgstr ""
|
||||
"Fokuswechsel im Mausmodus verzögern, bis sich der Zeiger nicht mehr bewegt."
|
||||
|
||||
#: ../js/extensionPrefs/main.js:125
|
||||
#, c-format
|
||||
msgid "There was an error loading the preferences dialog for %s:"
|
||||
@ -290,10 +299,10 @@ msgstr "Erweiterung"
|
||||
msgid "Select an extension to configure using the combobox above."
|
||||
msgstr "Wählen Sie oben eine Erweiterung aus, die Sie konfigurieren wollen."
|
||||
|
||||
#: ../js/gdm/authPrompt.js:145 ../js/ui/components/networkAgent.js:132
|
||||
#: ../js/gdm/authPrompt.js:145 ../js/ui/components/networkAgent.js:136
|
||||
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:351
|
||||
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
|
||||
#: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:686
|
||||
#: ../js/ui/status/bluetooth.js:222 ../js/ui/status/network.js:686
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
@ -332,8 +341,8 @@ msgstr "(z.B. Benutzer oder %s)"
|
||||
#. TTLS and PEAP are actually much more complicated, but this complication
|
||||
#. is not visible here since we only care about phase2 authentication
|
||||
#. (and don't even care of which one)
|
||||
#: ../js/gdm/loginDialog.js:627 ../js/ui/components/networkAgent.js:255
|
||||
#: ../js/ui/components/networkAgent.js:273
|
||||
#: ../js/gdm/loginDialog.js:627 ../js/ui/components/networkAgent.js:259
|
||||
#: ../js/ui/components/networkAgent.js:277
|
||||
msgid "Username: "
|
||||
msgstr "Benutzername:"
|
||||
|
||||
@ -354,42 +363,42 @@ msgstr "Legitimationsfehler"
|
||||
msgid "(or swipe finger)"
|
||||
msgstr "(oder benutzen Sie den Fingerabdruckleser)"
|
||||
|
||||
#: ../js/misc/util.js:97
|
||||
#: ../js/misc/util.js:98
|
||||
msgid "Command not found"
|
||||
msgstr "Befehl nicht gefunden"
|
||||
|
||||
#. Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
#. something nicer
|
||||
#: ../js/misc/util.js:130
|
||||
#: ../js/misc/util.js:131
|
||||
msgid "Could not parse command:"
|
||||
msgstr "Befehl konnte nicht verarbeitet werden:"
|
||||
|
||||
#: ../js/misc/util.js:138
|
||||
#: ../js/misc/util.js:139
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "Ausführung von »%s« ist gescheitert:"
|
||||
|
||||
#: ../js/ui/appDisplay.js:573
|
||||
#: ../js/ui/appDisplay.js:596
|
||||
msgid "Frequently used applications will appear here"
|
||||
msgstr "Häufig genutzte Anwendungen werden hier erscheinen"
|
||||
|
||||
#: ../js/ui/appDisplay.js:689
|
||||
#: ../js/ui/appDisplay.js:712
|
||||
msgid "Frequent"
|
||||
msgstr "Häufig"
|
||||
|
||||
#: ../js/ui/appDisplay.js:696
|
||||
#: ../js/ui/appDisplay.js:719
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: ../js/ui/appDisplay.js:1491
|
||||
#: ../js/ui/appDisplay.js:1514
|
||||
msgid "New Window"
|
||||
msgstr "Neues Fenster"
|
||||
|
||||
#: ../js/ui/appDisplay.js:1494 ../js/ui/dash.js:284
|
||||
#: ../js/ui/appDisplay.js:1517 ../js/ui/dash.js:284
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "Aus Favoriten entfernen"
|
||||
|
||||
#: ../js/ui/appDisplay.js:1495
|
||||
#: ../js/ui/appDisplay.js:1518
|
||||
msgid "Add to Favorites"
|
||||
msgstr "Zu Favoriten hinzufügen"
|
||||
|
||||
@ -403,7 +412,8 @@ msgstr "%s wurde zu Ihren Favoriten hinzugefügt"
|
||||
msgid "%s has been removed from your favorites."
|
||||
msgstr "%s wurde aus Ihren Favoriten entfernt"
|
||||
|
||||
#: ../js/ui/backgroundMenu.js:19 ../js/ui/status/system.js:325
|
||||
#: ../js/ui/backgroundMenu.js:19 ../js/ui/panel.js:808
|
||||
#: ../js/ui/status/system.js:325
|
||||
msgid "Settings"
|
||||
msgstr "Einstellungen"
|
||||
|
||||
@ -592,50 +602,50 @@ msgstr "Öffnen mit %s"
|
||||
msgid "Eject"
|
||||
msgstr "Auswerfen"
|
||||
|
||||
#: ../js/ui/components/keyring.js:88 ../js/ui/components/polkitAgent.js:280
|
||||
#: ../js/ui/components/keyring.js:91 ../js/ui/components/polkitAgent.js:280
|
||||
msgid "Password:"
|
||||
msgstr "Passwort:"
|
||||
|
||||
#: ../js/ui/components/keyring.js:107
|
||||
#: ../js/ui/components/keyring.js:110
|
||||
msgid "Type again:"
|
||||
msgstr "Erneut eingeben:"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:127 ../js/ui/status/network.js:112
|
||||
#: ../js/ui/components/networkAgent.js:131 ../js/ui/status/network.js:112
|
||||
#: ../js/ui/status/network.js:275 ../js/ui/status/network.js:689
|
||||
msgid "Connect"
|
||||
msgstr "Verbinden"
|
||||
|
||||
#. Cisco LEAP
|
||||
#: ../js/ui/components/networkAgent.js:218
|
||||
#: ../js/ui/components/networkAgent.js:230
|
||||
#: ../js/ui/components/networkAgent.js:257
|
||||
#: ../js/ui/components/networkAgent.js:277
|
||||
#: ../js/ui/components/networkAgent.js:287
|
||||
#: ../js/ui/components/networkAgent.js:222
|
||||
#: ../js/ui/components/networkAgent.js:234
|
||||
#: ../js/ui/components/networkAgent.js:261
|
||||
#: ../js/ui/components/networkAgent.js:281
|
||||
#: ../js/ui/components/networkAgent.js:291
|
||||
msgid "Password: "
|
||||
msgstr "Passwort:"
|
||||
|
||||
#. static WEP
|
||||
#: ../js/ui/components/networkAgent.js:223
|
||||
#: ../js/ui/components/networkAgent.js:227
|
||||
msgid "Key: "
|
||||
msgstr "Schlüssel:"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:261
|
||||
#: ../js/ui/components/networkAgent.js:265
|
||||
msgid "Identity: "
|
||||
msgstr "Identität:"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:263
|
||||
#: ../js/ui/components/networkAgent.js:267
|
||||
msgid "Private key password: "
|
||||
msgstr "Passwort für geheimen Schlüssel:"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:275
|
||||
#: ../js/ui/components/networkAgent.js:279
|
||||
msgid "Service: "
|
||||
msgstr "Dienst:"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:304
|
||||
#: ../js/ui/components/networkAgent.js:308
|
||||
msgid "Authentication required by wireless network"
|
||||
msgstr "Legitimierung für Funknetzwerk wird benötigt"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:305
|
||||
#: ../js/ui/components/networkAgent.js:309
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Passwords or encryption keys are required to access the wireless network "
|
||||
@ -644,35 +654,35 @@ msgstr ""
|
||||
"Passwörter oder Schlüssel sind erforderlich, um auf das Funknetzwerk »%s« "
|
||||
"zuzugreifen."
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:309
|
||||
#: ../js/ui/components/networkAgent.js:313
|
||||
msgid "Wired 802.1X authentication"
|
||||
msgstr "Kabelgebundene 802.1X-Legitimierung"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:311
|
||||
#: ../js/ui/components/networkAgent.js:315
|
||||
msgid "Network name: "
|
||||
msgstr "Netzwerkname:"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:316
|
||||
#: ../js/ui/components/networkAgent.js:320
|
||||
msgid "DSL authentication"
|
||||
msgstr "DSL-Legitimierung"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:323
|
||||
#: ../js/ui/components/networkAgent.js:327
|
||||
msgid "PIN code required"
|
||||
msgstr "PIN-Code ist erforderlich"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:324
|
||||
#: ../js/ui/components/networkAgent.js:328
|
||||
msgid "PIN code is needed for the mobile broadband device"
|
||||
msgstr "Für das mobile Breitbandgerät wird ein PIN-Code benötigt."
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:325
|
||||
#: ../js/ui/components/networkAgent.js:329
|
||||
msgid "PIN: "
|
||||
msgstr "PIN: "
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:331
|
||||
#: ../js/ui/components/networkAgent.js:335
|
||||
msgid "Mobile broadband network password"
|
||||
msgstr "Passwort der mobilen Breitbandverbindung"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:332
|
||||
#: ../js/ui/components/networkAgent.js:336
|
||||
#, c-format
|
||||
msgid "A password is required to connect to '%s'."
|
||||
msgstr "Es wird ein Passwort benötigt, um sich mit »%s« zu verbinden."
|
||||
@ -940,7 +950,7 @@ msgstr "Konto anzeigen"
|
||||
msgid "Unknown reason"
|
||||
msgstr "Unbekannter Grund"
|
||||
|
||||
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:96
|
||||
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:100
|
||||
msgid "Windows"
|
||||
msgstr "Fenster"
|
||||
|
||||
@ -1088,7 +1098,7 @@ msgstr "Installieren"
|
||||
msgid "Download and install '%s' from extensions.gnome.org?"
|
||||
msgstr "»%s« von extensions.gnome.org herunterladen und installieren?"
|
||||
|
||||
#: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:334
|
||||
#: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:333
|
||||
msgid "Keyboard"
|
||||
msgstr "Tastatur"
|
||||
|
||||
@ -1164,11 +1174,11 @@ msgstr "Benachrichtigungsfeldmenü"
|
||||
msgid "No Messages"
|
||||
msgstr "Keine Nachrichten"
|
||||
|
||||
#: ../js/ui/messageTray.js:1812
|
||||
#: ../js/ui/messageTray.js:1813
|
||||
msgid "Message Tray"
|
||||
msgstr "Benachrichtigungsfeld"
|
||||
|
||||
#: ../js/ui/messageTray.js:2787
|
||||
#: ../js/ui/messageTray.js:2788
|
||||
msgid "System Information"
|
||||
msgstr "Systeminformationen"
|
||||
|
||||
@ -1200,21 +1210,17 @@ msgstr "Übersicht"
|
||||
msgid "Type to search…"
|
||||
msgstr "Suchbegriff eingeben …"
|
||||
|
||||
#: ../js/ui/panel.js:516
|
||||
#: ../js/ui/panel.js:518
|
||||
msgid "Quit"
|
||||
msgstr "Beenden"
|
||||
|
||||
#. Translators: If there is no suitable word for "Activities"
|
||||
#. in your language, you can use the word for "Overview".
|
||||
#: ../js/ui/panel.js:568
|
||||
#: ../js/ui/panel.js:570
|
||||
msgid "Activities"
|
||||
msgstr "Aktivitäten"
|
||||
|
||||
#: ../js/ui/panel.js:805
|
||||
msgid "Settings Menu"
|
||||
msgstr "Einstellungsmenü"
|
||||
|
||||
#: ../js/ui/panel.js:901
|
||||
#: ../js/ui/panel.js:904
|
||||
msgid "Top Bar"
|
||||
msgstr "Oberes Panel"
|
||||
|
||||
@ -1223,7 +1229,7 @@ msgstr "Oberes Panel"
|
||||
#. "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:226
|
||||
#: ../js/ui/popupMenu.js:233
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-intl"
|
||||
|
||||
@ -1255,7 +1261,7 @@ msgstr[1] "%d neue Benachrichtigungen"
|
||||
msgid "Lock"
|
||||
msgstr "Sperren"
|
||||
|
||||
#: ../js/ui/screenShield.js:703
|
||||
#: ../js/ui/screenShield.js:704
|
||||
msgid "GNOME needs to lock the screen"
|
||||
msgstr "GNOME muss den Bildschirm sperren"
|
||||
|
||||
@ -1266,11 +1272,11 @@ msgstr "GNOME muss den Bildschirm sperren"
|
||||
#.
|
||||
#. XXX: another option is to kick the user into the gdm login
|
||||
#. screen, where we're not affected by grabs
|
||||
#: ../js/ui/screenShield.js:830 ../js/ui/screenShield.js:1296
|
||||
#: ../js/ui/screenShield.js:831 ../js/ui/screenShield.js:1297
|
||||
msgid "Unable to lock"
|
||||
msgstr "Sperrung fehlgeschlagen"
|
||||
|
||||
#: ../js/ui/screenShield.js:831 ../js/ui/screenShield.js:1297
|
||||
#: ../js/ui/screenShield.js:832 ../js/ui/screenShield.js:1298
|
||||
msgid "Lock was blocked by an application"
|
||||
msgstr "Sperrung wurde von einer Anwendung blockiert"
|
||||
|
||||
@ -1352,9 +1358,9 @@ msgstr "Große Schrift"
|
||||
|
||||
#. The Bluetooth menu only appears when Bluetooth is in use,
|
||||
#. so just statically build it with a "Turn Off" menu item.
|
||||
#: ../js/ui/status/bluetooth.js:28 ../js/ui/status/bluetooth.js:62
|
||||
#: ../js/ui/status/bluetooth.js:99 ../js/ui/status/bluetooth.js:127
|
||||
#: ../js/ui/status/bluetooth.js:163 ../js/ui/status/bluetooth.js:194
|
||||
#: ../js/ui/status/bluetooth.js:28 ../js/ui/status/bluetooth.js:63
|
||||
#: ../js/ui/status/bluetooth.js:100 ../js/ui/status/bluetooth.js:128
|
||||
#: ../js/ui/status/bluetooth.js:164 ../js/ui/status/bluetooth.js:195
|
||||
msgid "Bluetooth"
|
||||
msgstr "Bluetooth"
|
||||
|
||||
@ -1367,56 +1373,56 @@ msgstr "Ausschalten"
|
||||
msgid "Bluetooth Settings"
|
||||
msgstr "Bluetooth-Einstellungen"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:57
|
||||
#: ../js/ui/status/bluetooth.js:58
|
||||
#, c-format
|
||||
msgid "%d Connected Device"
|
||||
msgid_plural "%d Connected Devices"
|
||||
msgstr[0] "%d Verbundes Gerät"
|
||||
msgstr[1] "%d Verbundene Geräte"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:100 ../js/ui/status/bluetooth.js:128
|
||||
#: ../js/ui/status/bluetooth.js:101 ../js/ui/status/bluetooth.js:129
|
||||
#, c-format
|
||||
msgid "Authorization request from %s"
|
||||
msgstr "Legitimierungsanfrage von %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:106 ../js/ui/status/bluetooth.js:171
|
||||
#: ../js/ui/status/bluetooth.js:202
|
||||
#: ../js/ui/status/bluetooth.js:107 ../js/ui/status/bluetooth.js:172
|
||||
#: ../js/ui/status/bluetooth.js:203
|
||||
#, c-format
|
||||
msgid "Device %s wants to pair with this computer"
|
||||
msgstr "Gerät »%s« möchte mit diesem Rechner gekoppelt werden"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:108
|
||||
#: ../js/ui/status/bluetooth.js:109
|
||||
msgid "Allow"
|
||||
msgstr "Erlauben"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:109
|
||||
#: ../js/ui/status/bluetooth.js:110
|
||||
msgid "Deny"
|
||||
msgstr "Verweigern"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:134
|
||||
#: ../js/ui/status/bluetooth.js:135
|
||||
#, c-format
|
||||
msgid "Device %s wants access to the service '%s'"
|
||||
msgstr "Gerät »%s« bittet um Zugriff auf den Dienst »%s«"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:136
|
||||
#: ../js/ui/status/bluetooth.js:137
|
||||
msgid "Always grant access"
|
||||
msgstr "Immer Zugriff gewähren"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:137
|
||||
#: ../js/ui/status/bluetooth.js:138
|
||||
msgid "Grant this time only"
|
||||
msgstr "Nur dieses Mal gewähren"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:138
|
||||
#: ../js/ui/status/bluetooth.js:139
|
||||
msgid "Reject"
|
||||
msgstr "Abweisen"
|
||||
|
||||
#. Translators: argument is the device short name
|
||||
#: ../js/ui/status/bluetooth.js:165
|
||||
#: ../js/ui/status/bluetooth.js:166
|
||||
#, c-format
|
||||
msgid "Pairing confirmation for %s"
|
||||
msgstr "Koppelungsbestätigung für %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:172
|
||||
#: ../js/ui/status/bluetooth.js:173
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Please confirm whether the Passkey '%06d' matches the one on the device."
|
||||
@ -1424,24 +1430,24 @@ msgstr ""
|
||||
"Bitte bestätigen Sie, ob die PIN »%06d« mit der des Gerätes übereinstimmt."
|
||||
|
||||
#. Translators: this is the verb, not the noun
|
||||
#: ../js/ui/status/bluetooth.js:175
|
||||
#: ../js/ui/status/bluetooth.js:176
|
||||
msgid "Matches"
|
||||
msgstr "Stimmt überein"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:176
|
||||
#: ../js/ui/status/bluetooth.js:177
|
||||
msgid "Does not match"
|
||||
msgstr "Stimmt nicht überein"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:195
|
||||
#: ../js/ui/status/bluetooth.js:196
|
||||
#, c-format
|
||||
msgid "Pairing request for %s"
|
||||
msgstr "Koppelungsanfrage für %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:203
|
||||
#: ../js/ui/status/bluetooth.js:204
|
||||
msgid "Please enter the PIN mentioned on the device."
|
||||
msgstr "Bitte geben Sie die auf dem Gerät angezeigte PIN ein."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:220
|
||||
#: ../js/ui/status/bluetooth.js:221
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
@ -1449,7 +1455,7 @@ msgstr "OK"
|
||||
msgid "Brightness"
|
||||
msgstr "Helligkeit"
|
||||
|
||||
#: ../js/ui/status/keyboard.js:404
|
||||
#: ../js/ui/status/keyboard.js:403
|
||||
msgid "Show Keyboard Layout"
|
||||
msgstr "Tastaturbelegung zeigen"
|
||||
|
||||
@ -1525,15 +1531,15 @@ msgstr "Einschalten"
|
||||
msgid "VPN"
|
||||
msgstr "VPN"
|
||||
|
||||
#: ../js/ui/status/network.js:1306
|
||||
#: ../js/ui/status/network.js:1307
|
||||
msgid "Network Manager"
|
||||
msgstr "Netzwerk-Verwaltung"
|
||||
|
||||
#: ../js/ui/status/network.js:1345
|
||||
#: ../js/ui/status/network.js:1346
|
||||
msgid "Connection failed"
|
||||
msgstr "Verbindung gescheitert"
|
||||
|
||||
#: ../js/ui/status/network.js:1346
|
||||
#: ../js/ui/status/network.js:1347
|
||||
msgid "Activation of network connection failed"
|
||||
msgstr "Aktivierung der Netzwerkverbindung ist gescheitert"
|
||||
|
||||
@ -1619,11 +1625,11 @@ msgstr "Als anderer Benutzer anmelden"
|
||||
msgid "Unlock Window"
|
||||
msgstr "Fenster entsperren"
|
||||
|
||||
#: ../js/ui/viewSelector.js:100
|
||||
#: ../js/ui/viewSelector.js:104
|
||||
msgid "Applications"
|
||||
msgstr "Anwendungen"
|
||||
|
||||
#: ../js/ui/viewSelector.js:104
|
||||
#: ../js/ui/viewSelector.js:108
|
||||
msgid "Search"
|
||||
msgstr "Suchen"
|
||||
|
||||
@ -1729,6 +1735,9 @@ msgstr "Das Passwort darf nicht leer sein"
|
||||
msgid "Authentication dialog was dismissed by the user"
|
||||
msgstr "Der Dialog zur Legitimierung wurde vom Benutzer geschlossen"
|
||||
|
||||
#~ msgid "Settings Menu"
|
||||
#~ msgstr "Einstellungsmenü"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Internally used to store the last IM presence explicitly set by the user. "
|
||||
#~ "The value here is from the TpConnectionPresenceType enumeration."
|
||||
|
1578
po/en_GB.po
167
po/ja.po
@ -13,8 +13,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2013-09-06 21:55+0000\n"
|
||||
"PO-Revision-Date: 2013-09-07 22:28+0900\n"
|
||||
"POT-Creation-Date: 2013-09-23 13:35+0000\n"
|
||||
"PO-Revision-Date: 2013-09-23 23:30+0900\n"
|
||||
"Last-Translator: Jiro Matsuzawa <jmatsuzawa@gnome.org>\n"
|
||||
"Language-Team: Japanese <gnome-translation@gnome.gr.jp>\n"
|
||||
"Language: ja\n"
|
||||
@ -52,6 +52,7 @@ msgid "GNOME Shell"
|
||||
msgstr "GNOME Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
#: ../data/gnome-shell-wayland.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "ウィンドウ管理とアプリケーションの起動"
|
||||
|
||||
@ -64,6 +65,10 @@ msgstr "GNOME Shell 拡張機能設定"
|
||||
msgid "Configure GNOME Shell Extensions"
|
||||
msgstr "GNOME Shell 拡張機能の設定を行います"
|
||||
|
||||
#: ../data/gnome-shell-wayland.desktop.in.in.h:1
|
||||
msgid "GNOME Shell (wayland compositor)"
|
||||
msgstr "GNOME Shell (Wayland コンポジター)"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:1
|
||||
msgid "Enable internal tools useful for developers and testers from Alt-F2"
|
||||
msgstr "Alt-F2 から開発・テスト用の内部ツールを利用可能にする"
|
||||
@ -212,6 +217,10 @@ msgstr "ワークスペースを動的に管理する"
|
||||
msgid "Workspaces only on primary monitor"
|
||||
msgstr "プライマリモニターのみワークスペースを切り替える"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:38
|
||||
msgid "Delay focus changes in mouse mode until the pointer stops moving"
|
||||
msgstr "マウスモードにおけるフォーカス遷移をポインターが停止するまで遅延させる"
|
||||
|
||||
#: ../js/extensionPrefs/main.js:125
|
||||
#, c-format
|
||||
msgid "There was an error loading the preferences dialog for %s:"
|
||||
@ -225,10 +234,10 @@ msgstr "拡張機能"
|
||||
msgid "Select an extension to configure using the combobox above."
|
||||
msgstr "設定する拡張機能を上部のコンボボックスから選択してください。"
|
||||
|
||||
#: ../js/gdm/authPrompt.js:145 ../js/ui/components/networkAgent.js:132
|
||||
#: ../js/gdm/authPrompt.js:145 ../js/ui/components/networkAgent.js:136
|
||||
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:351
|
||||
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
|
||||
#: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:686
|
||||
#: ../js/ui/status/bluetooth.js:222 ../js/ui/status/network.js:686
|
||||
msgid "Cancel"
|
||||
msgstr "キャンセル"
|
||||
|
||||
@ -267,8 +276,8 @@ msgstr "(たとえば、user あるいは %s)"
|
||||
#. TTLS and PEAP are actually much more complicated, but this complication
|
||||
#. is not visible here since we only care about phase2 authentication
|
||||
#. (and don't even care of which one)
|
||||
#: ../js/gdm/loginDialog.js:627 ../js/ui/components/networkAgent.js:255
|
||||
#: ../js/ui/components/networkAgent.js:273
|
||||
#: ../js/gdm/loginDialog.js:627 ../js/ui/components/networkAgent.js:259
|
||||
#: ../js/ui/components/networkAgent.js:277
|
||||
msgid "Username: "
|
||||
msgstr "ユーザー名: "
|
||||
|
||||
@ -289,42 +298,42 @@ msgstr "認証エラー"
|
||||
msgid "(or swipe finger)"
|
||||
msgstr "(あるいは指でスワイプする)"
|
||||
|
||||
#: ../js/misc/util.js:97
|
||||
#: ../js/misc/util.js:98
|
||||
msgid "Command not found"
|
||||
msgstr "コマンドが見つかりません"
|
||||
|
||||
#. Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
#. something nicer
|
||||
#: ../js/misc/util.js:130
|
||||
#: ../js/misc/util.js:131
|
||||
msgid "Could not parse command:"
|
||||
msgstr "次のコマンドは解析できません:"
|
||||
|
||||
#: ../js/misc/util.js:138
|
||||
#: ../js/misc/util.js:139
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "'%s'の実行に失敗しました:"
|
||||
|
||||
#: ../js/ui/appDisplay.js:573
|
||||
#: ../js/ui/appDisplay.js:596
|
||||
msgid "Frequently used applications will appear here"
|
||||
msgstr "よく使うアプリケーションがここに表示されます"
|
||||
|
||||
#: ../js/ui/appDisplay.js:689
|
||||
#: ../js/ui/appDisplay.js:712
|
||||
msgid "Frequent"
|
||||
msgstr "常用"
|
||||
|
||||
#: ../js/ui/appDisplay.js:696
|
||||
#: ../js/ui/appDisplay.js:719
|
||||
msgid "All"
|
||||
msgstr "すべて"
|
||||
|
||||
#: ../js/ui/appDisplay.js:1491
|
||||
#: ../js/ui/appDisplay.js:1514
|
||||
msgid "New Window"
|
||||
msgstr "新しいウィンドウで開く"
|
||||
|
||||
#: ../js/ui/appDisplay.js:1494 ../js/ui/dash.js:284
|
||||
#: ../js/ui/appDisplay.js:1517 ../js/ui/dash.js:284
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "お気に入りから削除"
|
||||
|
||||
#: ../js/ui/appDisplay.js:1495
|
||||
#: ../js/ui/appDisplay.js:1518
|
||||
msgid "Add to Favorites"
|
||||
msgstr "お気に入りに追加"
|
||||
|
||||
@ -338,7 +347,8 @@ msgstr "%s をお気に入りに追加しました。"
|
||||
msgid "%s has been removed from your favorites."
|
||||
msgstr "%s をお気に入りから削除しました。"
|
||||
|
||||
#: ../js/ui/backgroundMenu.js:19 ../js/ui/status/system.js:325
|
||||
#: ../js/ui/backgroundMenu.js:19 ../js/ui/panel.js:807
|
||||
#: ../js/ui/status/system.js:325
|
||||
msgid "Settings"
|
||||
msgstr "設定"
|
||||
|
||||
@ -524,83 +534,83 @@ msgstr "%s で開く"
|
||||
msgid "Eject"
|
||||
msgstr "取り出し"
|
||||
|
||||
#: ../js/ui/components/keyring.js:88 ../js/ui/components/polkitAgent.js:280
|
||||
#: ../js/ui/components/keyring.js:91 ../js/ui/components/polkitAgent.js:280
|
||||
msgid "Password:"
|
||||
msgstr "パスワード:"
|
||||
|
||||
#: ../js/ui/components/keyring.js:107
|
||||
#: ../js/ui/components/keyring.js:110
|
||||
msgid "Type again:"
|
||||
msgstr "再入力:"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:127 ../js/ui/status/network.js:112
|
||||
#: ../js/ui/components/networkAgent.js:131 ../js/ui/status/network.js:112
|
||||
#: ../js/ui/status/network.js:275 ../js/ui/status/network.js:689
|
||||
msgid "Connect"
|
||||
msgstr "接続"
|
||||
|
||||
#. Cisco LEAP
|
||||
#: ../js/ui/components/networkAgent.js:218
|
||||
#: ../js/ui/components/networkAgent.js:230
|
||||
#: ../js/ui/components/networkAgent.js:257
|
||||
#: ../js/ui/components/networkAgent.js:277
|
||||
#: ../js/ui/components/networkAgent.js:287
|
||||
#: ../js/ui/components/networkAgent.js:222
|
||||
#: ../js/ui/components/networkAgent.js:234
|
||||
#: ../js/ui/components/networkAgent.js:261
|
||||
#: ../js/ui/components/networkAgent.js:281
|
||||
#: ../js/ui/components/networkAgent.js:291
|
||||
msgid "Password: "
|
||||
msgstr "パスワード: "
|
||||
|
||||
#. static WEP
|
||||
#: ../js/ui/components/networkAgent.js:223
|
||||
#: ../js/ui/components/networkAgent.js:227
|
||||
msgid "Key: "
|
||||
msgstr "キー: "
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:261
|
||||
#: ../js/ui/components/networkAgent.js:265
|
||||
msgid "Identity: "
|
||||
msgstr "識別子: "
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:263
|
||||
#: ../js/ui/components/networkAgent.js:267
|
||||
msgid "Private key password: "
|
||||
msgstr "プライベートキーパスワード: "
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:275
|
||||
#: ../js/ui/components/networkAgent.js:279
|
||||
msgid "Service: "
|
||||
msgstr "サービス: "
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:304
|
||||
#: ../js/ui/components/networkAgent.js:308
|
||||
msgid "Authentication required by wireless network"
|
||||
msgstr "無線ネットワークでは認証が要求されます"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:305
|
||||
#: ../js/ui/components/networkAgent.js:309
|
||||
#, c-format
|
||||
msgid "Passwords or encryption keys are required to access the wireless network '%s'."
|
||||
msgstr "無線ネットワーク '%s' にアクセスするにはパスワードか、または暗号化キーが必要です。"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:309
|
||||
#: ../js/ui/components/networkAgent.js:313
|
||||
msgid "Wired 802.1X authentication"
|
||||
msgstr "有線 802.1X の認証"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:311
|
||||
#: ../js/ui/components/networkAgent.js:315
|
||||
msgid "Network name: "
|
||||
msgstr "ネットワーク名: "
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:316
|
||||
#: ../js/ui/components/networkAgent.js:320
|
||||
msgid "DSL authentication"
|
||||
msgstr "DSL 認証"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:323
|
||||
#: ../js/ui/components/networkAgent.js:327
|
||||
msgid "PIN code required"
|
||||
msgstr "PIN コードが必要です"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:324
|
||||
#: ../js/ui/components/networkAgent.js:328
|
||||
msgid "PIN code is needed for the mobile broadband device"
|
||||
msgstr "モバイルブロードバンドデバイスには PIN コードが必要です"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:325
|
||||
#: ../js/ui/components/networkAgent.js:329
|
||||
msgid "PIN: "
|
||||
msgstr "PIN 番号: "
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:331
|
||||
#: ../js/ui/components/networkAgent.js:335
|
||||
msgid "Mobile broadband network password"
|
||||
msgstr "モバイルブロードバンドネットワークのパスワード"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:332
|
||||
#: ../js/ui/components/networkAgent.js:336
|
||||
#, c-format
|
||||
msgid "A password is required to connect to '%s'."
|
||||
msgstr "'%s' への接続にパスワードが必要です。"
|
||||
@ -856,7 +866,7 @@ msgstr "アカウントを表示"
|
||||
msgid "Unknown reason"
|
||||
msgstr "原因不明"
|
||||
|
||||
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:96
|
||||
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:100
|
||||
msgid "Windows"
|
||||
msgstr "ウィンドウ"
|
||||
|
||||
@ -994,7 +1004,7 @@ msgstr "インストール"
|
||||
msgid "Download and install '%s' from extensions.gnome.org?"
|
||||
msgstr "extensions.gnome.org から '%s' をダウンロードしてインストールしますか?"
|
||||
|
||||
#: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:334
|
||||
#: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:333
|
||||
msgid "Keyboard"
|
||||
msgstr "キーボード"
|
||||
|
||||
@ -1070,11 +1080,11 @@ msgstr "トレイメニュー"
|
||||
msgid "No Messages"
|
||||
msgstr "メッセージなし"
|
||||
|
||||
#: ../js/ui/messageTray.js:1812
|
||||
#: ../js/ui/messageTray.js:1813
|
||||
msgid "Message Tray"
|
||||
msgstr "メッセージトレイ"
|
||||
|
||||
#: ../js/ui/messageTray.js:2787
|
||||
#: ../js/ui/messageTray.js:2788
|
||||
msgid "System Information"
|
||||
msgstr "システム情報"
|
||||
|
||||
@ -1105,21 +1115,17 @@ msgstr "アクティビティ画面"
|
||||
msgid "Type to search…"
|
||||
msgstr "検索ワードを入力…"
|
||||
|
||||
#: ../js/ui/panel.js:516
|
||||
#: ../js/ui/panel.js:518
|
||||
msgid "Quit"
|
||||
msgstr "終了"
|
||||
|
||||
#. Translators: If there is no suitable word for "Activities"
|
||||
#. in your language, you can use the word for "Overview".
|
||||
#: ../js/ui/panel.js:568
|
||||
#: ../js/ui/panel.js:570
|
||||
msgid "Activities"
|
||||
msgstr "アクティビティ"
|
||||
|
||||
#: ../js/ui/panel.js:805
|
||||
msgid "Settings Menu"
|
||||
msgstr "設定メニュー"
|
||||
|
||||
#: ../js/ui/panel.js:901
|
||||
#: ../js/ui/panel.js:903
|
||||
msgid "Top Bar"
|
||||
msgstr "トップバー"
|
||||
|
||||
@ -1128,7 +1134,7 @@ msgstr "トップバー"
|
||||
#. "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:226
|
||||
#: ../js/ui/popupMenu.js:233
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-us"
|
||||
|
||||
@ -1156,7 +1162,7 @@ msgstr[0] "%d 件の新しい通知"
|
||||
msgid "Lock"
|
||||
msgstr "ロック"
|
||||
|
||||
#: ../js/ui/screenShield.js:703
|
||||
#: ../js/ui/screenShield.js:704
|
||||
msgid "GNOME needs to lock the screen"
|
||||
msgstr "画面をロックする必要があります"
|
||||
|
||||
@ -1167,11 +1173,11 @@ msgstr "画面をロックする必要があります"
|
||||
#.
|
||||
#. XXX: another option is to kick the user into the gdm login
|
||||
#. screen, where we're not affected by grabs
|
||||
#: ../js/ui/screenShield.js:830 ../js/ui/screenShield.js:1296
|
||||
#: ../js/ui/screenShield.js:831 ../js/ui/screenShield.js:1297
|
||||
msgid "Unable to lock"
|
||||
msgstr "ロックできません"
|
||||
|
||||
#: ../js/ui/screenShield.js:831 ../js/ui/screenShield.js:1297
|
||||
#: ../js/ui/screenShield.js:832 ../js/ui/screenShield.js:1298
|
||||
msgid "Lock was blocked by an application"
|
||||
msgstr "アプリケーションによってロックがブロックされました"
|
||||
|
||||
@ -1253,9 +1259,9 @@ msgstr "大きな文字"
|
||||
|
||||
#. The Bluetooth menu only appears when Bluetooth is in use,
|
||||
#. so just statically build it with a "Turn Off" menu item.
|
||||
#: ../js/ui/status/bluetooth.js:28 ../js/ui/status/bluetooth.js:62
|
||||
#: ../js/ui/status/bluetooth.js:99 ../js/ui/status/bluetooth.js:127
|
||||
#: ../js/ui/status/bluetooth.js:163 ../js/ui/status/bluetooth.js:194
|
||||
#: ../js/ui/status/bluetooth.js:28 ../js/ui/status/bluetooth.js:63
|
||||
#: ../js/ui/status/bluetooth.js:100 ../js/ui/status/bluetooth.js:128
|
||||
#: ../js/ui/status/bluetooth.js:164 ../js/ui/status/bluetooth.js:195
|
||||
msgid "Bluetooth"
|
||||
msgstr "Bluetooth"
|
||||
|
||||
@ -1268,78 +1274,78 @@ msgstr "オフにする"
|
||||
msgid "Bluetooth Settings"
|
||||
msgstr "Bluetooth の設定"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:57
|
||||
#: ../js/ui/status/bluetooth.js:58
|
||||
#, c-format
|
||||
msgid "%d Connected Device"
|
||||
msgid_plural "%d Connected Devices"
|
||||
msgstr[0] "接続デバイス: %d台"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:100 ../js/ui/status/bluetooth.js:128
|
||||
#: ../js/ui/status/bluetooth.js:101 ../js/ui/status/bluetooth.js:129
|
||||
#, c-format
|
||||
msgid "Authorization request from %s"
|
||||
msgstr "%s からアクセス許可の要求"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:106 ../js/ui/status/bluetooth.js:171
|
||||
#: ../js/ui/status/bluetooth.js:202
|
||||
#: ../js/ui/status/bluetooth.js:107 ../js/ui/status/bluetooth.js:172
|
||||
#: ../js/ui/status/bluetooth.js:203
|
||||
#, c-format
|
||||
msgid "Device %s wants to pair with this computer"
|
||||
msgstr "デバイス %s がこのコンピューターとのペアリングを要求しています"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:108
|
||||
#: ../js/ui/status/bluetooth.js:109
|
||||
msgid "Allow"
|
||||
msgstr "許可"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:109
|
||||
#: ../js/ui/status/bluetooth.js:110
|
||||
msgid "Deny"
|
||||
msgstr "拒否"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:134
|
||||
#: ../js/ui/status/bluetooth.js:135
|
||||
#, c-format
|
||||
msgid "Device %s wants access to the service '%s'"
|
||||
msgstr "デバイス '%s' が サービス '%s' へのアクセスを要求しています"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:136
|
||||
#: ../js/ui/status/bluetooth.js:137
|
||||
msgid "Always grant access"
|
||||
msgstr "許可"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:137
|
||||
#: ../js/ui/status/bluetooth.js:138
|
||||
msgid "Grant this time only"
|
||||
msgstr "今回のみ許可"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:138
|
||||
#: ../js/ui/status/bluetooth.js:139
|
||||
msgid "Reject"
|
||||
msgstr "拒否"
|
||||
|
||||
#. Translators: argument is the device short name
|
||||
#: ../js/ui/status/bluetooth.js:165
|
||||
#: ../js/ui/status/bluetooth.js:166
|
||||
#, c-format
|
||||
msgid "Pairing confirmation for %s"
|
||||
msgstr "%s からペアリングの確認"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:172
|
||||
#: ../js/ui/status/bluetooth.js:173
|
||||
#, c-format
|
||||
msgid "Please confirm whether the Passkey '%06d' matches the one on the device."
|
||||
msgstr "'%06d' がデバイスのパスキーと一致しているか確認してください。"
|
||||
|
||||
#. Translators: this is the verb, not the noun
|
||||
#: ../js/ui/status/bluetooth.js:175
|
||||
#: ../js/ui/status/bluetooth.js:176
|
||||
msgid "Matches"
|
||||
msgstr "一致"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:176
|
||||
#: ../js/ui/status/bluetooth.js:177
|
||||
msgid "Does not match"
|
||||
msgstr "不一致"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:195
|
||||
#: ../js/ui/status/bluetooth.js:196
|
||||
#, c-format
|
||||
msgid "Pairing request for %s"
|
||||
msgstr "%s からペアリングの要求"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:203
|
||||
#: ../js/ui/status/bluetooth.js:204
|
||||
msgid "Please enter the PIN mentioned on the device."
|
||||
msgstr "デバイスの PIN コードを入力してください。"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:220
|
||||
#: ../js/ui/status/bluetooth.js:221
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
@ -1347,7 +1353,7 @@ msgstr "OK"
|
||||
msgid "Brightness"
|
||||
msgstr "明るさ"
|
||||
|
||||
#: ../js/ui/status/keyboard.js:404
|
||||
#: ../js/ui/status/keyboard.js:403
|
||||
msgid "Show Keyboard Layout"
|
||||
msgstr "キーボードレイアウトの表示"
|
||||
|
||||
@ -1423,15 +1429,15 @@ msgstr "オンにする"
|
||||
msgid "VPN"
|
||||
msgstr "VPN"
|
||||
|
||||
#: ../js/ui/status/network.js:1306
|
||||
#: ../js/ui/status/network.js:1307
|
||||
msgid "Network Manager"
|
||||
msgstr "ネットワークマネージャー"
|
||||
|
||||
#: ../js/ui/status/network.js:1345
|
||||
#: ../js/ui/status/network.js:1346
|
||||
msgid "Connection failed"
|
||||
msgstr "接続失敗"
|
||||
|
||||
#: ../js/ui/status/network.js:1346
|
||||
#: ../js/ui/status/network.js:1347
|
||||
msgid "Activation of network connection failed"
|
||||
msgstr "ネットワーク接続を有効にできません"
|
||||
|
||||
@ -1517,11 +1523,11 @@ msgstr "他のユーザーでログイン"
|
||||
msgid "Unlock Window"
|
||||
msgstr "ロック解除"
|
||||
|
||||
#: ../js/ui/viewSelector.js:100
|
||||
#: ../js/ui/viewSelector.js:104
|
||||
msgid "Applications"
|
||||
msgstr "アプリケーション"
|
||||
|
||||
#: ../js/ui/viewSelector.js:104
|
||||
#: ../js/ui/viewSelector.js:108
|
||||
msgid "Search"
|
||||
msgstr "検索"
|
||||
|
||||
@ -1622,6 +1628,9 @@ msgstr "パスワードを空白にすることはできません。"
|
||||
msgid "Authentication dialog was dismissed by the user"
|
||||
msgstr "認証ダイアログはユーザーに拒否されました"
|
||||
|
||||
#~ msgid "Settings Menu"
|
||||
#~ msgstr "設定メニュー"
|
||||
|
||||
#~ msgid "Internally used to store the last IM presence explicitly set by the user. The value here is from the TpConnectionPresenceType enumeration."
|
||||
#~ msgstr "ユーザーにより明示的に設定された最新の IM プレゼンスを保存するのに内部的に使用されます。ここは TpConnectionPresenceType 列挙型の値になります。"
|
||||
|
||||
|
239
po/kk.po
@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2013-08-30 14:46+0000\n"
|
||||
"PO-Revision-Date: 2013-08-31 19:43+0600\n"
|
||||
"POT-Creation-Date: 2013-09-23 13:35+0000\n"
|
||||
"PO-Revision-Date: 2013-09-24 06:33+0600\n"
|
||||
"Last-Translator: Baurzhan Muftakhidinov <baurthefirst@gmail.com>\n"
|
||||
"Language-Team: Kazakh <kk_KZ@googlegroups.com>\n"
|
||||
"Language: kk\n"
|
||||
@ -48,6 +48,7 @@ msgid "GNOME Shell"
|
||||
msgstr "GNOME Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
#: ../data/gnome-shell-wayland.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Терезелерді басқару мен қолданбаларды жөнелту"
|
||||
|
||||
@ -60,6 +61,10 @@ msgstr "GNOME Shell кеңейту баптаулары"
|
||||
msgid "Configure GNOME Shell Extensions"
|
||||
msgstr "GNOME Shell кеңейтулерін баптау"
|
||||
|
||||
#: ../data/gnome-shell-wayland.desktop.in.in.h:1
|
||||
msgid "GNOME Shell (wayland compositor)"
|
||||
msgstr "GNOME Shell (wayland үйлестіргіші)"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:1
|
||||
msgid "Enable internal tools useful for developers and testers from Alt-F2"
|
||||
msgstr ""
|
||||
@ -85,6 +90,10 @@ msgid ""
|
||||
"list. You can also manipulate this list with the EnableExtension and "
|
||||
"DisableExtension DBus methods on org.gnome.Shell."
|
||||
msgstr ""
|
||||
"GNOME Shell кеңейтулерінде uuid қасиеті бар; бұл кілт жүктелетін кеңейтулер "
|
||||
"тізімін сақтайды. Жүйеге кірген кезде жүктелем дейтін кеңейту осы тізімде "
|
||||
"болуы тиіс. Бұл тізімді org.gnome.Shell ішіндегі EnableExtension және "
|
||||
"DisableExtension DBus тәсілдерімен де өзгертуге болады."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:5
|
||||
msgid "List of desktop file IDs for favorite applications"
|
||||
@ -95,6 +104,8 @@ msgid ""
|
||||
"The applications corresponding to these identifiers will be displayed in the "
|
||||
"favorites area."
|
||||
msgstr ""
|
||||
"Осы анықтағыштарға сәйкес келетін қолданбалар таңдамалылар аймағында "
|
||||
"көрсетілетін болады."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:7
|
||||
msgid "List of categories that should be displayed as folders"
|
||||
@ -105,6 +116,8 @@ msgid ""
|
||||
"Each category name in this list will be represented as folder in the "
|
||||
"application view, rather than being displayed inline in the main view."
|
||||
msgstr ""
|
||||
"Бұл тізімдегі әрбір санат аты басты көріністе қатарынан көрсетілудің орнына "
|
||||
"қолданбалар көрінісінде бума ретінде көрсетіледі."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:9
|
||||
msgid "History for command (Alt-F2) dialog"
|
||||
@ -123,6 +136,8 @@ msgid ""
|
||||
"This key overrides the automatic hiding of the 'Log out' menuitem in single-"
|
||||
"user, single-session situations."
|
||||
msgstr ""
|
||||
"Бұл кілт бір пайдаланушы, бір сессия бар кезінде 'Жүйеден шығу' "
|
||||
"мүмкіндігінің автоматты түрде жасыруын алмастырады."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:13
|
||||
msgid ""
|
||||
@ -138,6 +153,10 @@ msgid ""
|
||||
"'Remember Password' checkbox will be present. This key sets the default "
|
||||
"state of the checkbox."
|
||||
msgstr ""
|
||||
"Қоршам шифрленген құрылғы немесе қашықтағы файлдық жүйе тіркелген кезде "
|
||||
"парольді сұрайды. Егер парольді болашақтағы қолданулар үшін сақтау керек "
|
||||
"болса, 'Парольді еске сақтау' жалаушасые орнатыңыз. Бұл кілт жалаушаның "
|
||||
"бастапқы күйін орнатады."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
|
||||
msgid "Show the week date in the calendar"
|
||||
@ -207,10 +226,13 @@ msgid ""
|
||||
"are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-"
|
||||
"only' (shows only the application icon) or 'both'."
|
||||
msgstr ""
|
||||
"Терезелер ауыстырғышта қалай көрсетілетінін сипаттайды. Мүмкін мәндері "
|
||||
"'thumbnail-only' (терезенің кіші көрінісі көрсетіледі), 'app-icon-only' (тек "
|
||||
"қолданба таңбашасы көрсетіледі) немесе 'both' (екеуі де)."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31
|
||||
msgid "Attach modal dialog to the parent window"
|
||||
msgstr ""
|
||||
msgstr "Модальды сұхбатты аталық терезесіне жалғау"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:32
|
||||
msgid ""
|
||||
@ -234,6 +256,8 @@ msgstr ""
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:35
|
||||
msgid "Enable edge tiling when dropping windows on screen edges"
|
||||
msgstr ""
|
||||
"Терезелерді экран шеттеріне апарған кезде олардың өлшемдерін өзгертуді іске "
|
||||
"қосу"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:36
|
||||
msgid "Workspaces are managed dynamically"
|
||||
@ -243,6 +267,10 @@ msgstr "Жұмыс орындары динамикалы түрде басқар
|
||||
msgid "Workspaces only on primary monitor"
|
||||
msgstr "Жұмыс орындар тек біріншілік мониторда"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:38
|
||||
msgid "Delay focus changes in mouse mode until the pointer stops moving"
|
||||
msgstr "Тышқан режиміндегі фокусты ауыстыру курсор тоқтағанша дейін кідірту"
|
||||
|
||||
#: ../js/extensionPrefs/main.js:125
|
||||
#, c-format
|
||||
msgid "There was an error loading the preferences dialog for %s:"
|
||||
@ -256,10 +284,10 @@ msgstr "Кеңейту"
|
||||
msgid "Select an extension to configure using the combobox above."
|
||||
msgstr "Жоғарыдағы ашылмалы тізімнен баптау үшін кеңейтуді таңдаңыз."
|
||||
|
||||
#: ../js/gdm/authPrompt.js:145 ../js/ui/components/networkAgent.js:132
|
||||
#: ../js/gdm/authPrompt.js:145 ../js/ui/components/networkAgent.js:136
|
||||
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:351
|
||||
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
|
||||
#: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:679
|
||||
#: ../js/ui/status/bluetooth.js:222 ../js/ui/status/network.js:686
|
||||
msgid "Cancel"
|
||||
msgstr "Бас тарту"
|
||||
|
||||
@ -298,8 +326,8 @@ msgstr "(мыс., пайдаланушы не %s)"
|
||||
#. TTLS and PEAP are actually much more complicated, but this complication
|
||||
#. is not visible here since we only care about phase2 authentication
|
||||
#. (and don't even care of which one)
|
||||
#: ../js/gdm/loginDialog.js:627 ../js/ui/components/networkAgent.js:255
|
||||
#: ../js/ui/components/networkAgent.js:273
|
||||
#: ../js/gdm/loginDialog.js:627 ../js/ui/components/networkAgent.js:259
|
||||
#: ../js/ui/components/networkAgent.js:277
|
||||
msgid "Username: "
|
||||
msgstr "Пайдаланушы аты:"
|
||||
|
||||
@ -320,38 +348,42 @@ msgstr "Аутентификация қатесі"
|
||||
msgid "(or swipe finger)"
|
||||
msgstr "(немесе саусағыңызды өткізіңіз)"
|
||||
|
||||
#: ../js/misc/util.js:97
|
||||
#: ../js/misc/util.js:98
|
||||
msgid "Command not found"
|
||||
msgstr "Команда табылмады"
|
||||
|
||||
#. Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
#. something nicer
|
||||
#: ../js/misc/util.js:130
|
||||
#: ../js/misc/util.js:131
|
||||
msgid "Could not parse command:"
|
||||
msgstr "Команданы талдау мүмкін емес:"
|
||||
|
||||
#: ../js/misc/util.js:138
|
||||
#: ../js/misc/util.js:139
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "'%s' жөнелту сәтсіз:"
|
||||
|
||||
#: ../js/ui/appDisplay.js:386
|
||||
#: ../js/ui/appDisplay.js:596
|
||||
msgid "Frequently used applications will appear here"
|
||||
msgstr "Жиі қолданылатын қолданбалар осында көрінеді"
|
||||
|
||||
#: ../js/ui/appDisplay.js:712
|
||||
msgid "Frequent"
|
||||
msgstr "Жиі"
|
||||
|
||||
#: ../js/ui/appDisplay.js:393
|
||||
#: ../js/ui/appDisplay.js:719
|
||||
msgid "All"
|
||||
msgstr "Барлық"
|
||||
|
||||
#: ../js/ui/appDisplay.js:991
|
||||
#: ../js/ui/appDisplay.js:1514
|
||||
msgid "New Window"
|
||||
msgstr "Жаңа терезе"
|
||||
|
||||
#: ../js/ui/appDisplay.js:994 ../js/ui/dash.js:284
|
||||
#: ../js/ui/appDisplay.js:1517 ../js/ui/dash.js:284
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "Таңдамалылардан өшіру"
|
||||
|
||||
#: ../js/ui/appDisplay.js:995
|
||||
#: ../js/ui/appDisplay.js:1518
|
||||
msgid "Add to Favorites"
|
||||
msgstr "Таңдамалыларға қосу"
|
||||
|
||||
@ -365,7 +397,8 @@ msgstr "%s таңдамалыларыңызға қосылды."
|
||||
msgid "%s has been removed from your favorites."
|
||||
msgstr "%s таңдамалыларыңыздан өшірілді."
|
||||
|
||||
#: ../js/ui/backgroundMenu.js:19 ../js/ui/status/system.js:325
|
||||
#: ../js/ui/backgroundMenu.js:19 ../js/ui/panel.js:807
|
||||
#: ../js/ui/status/system.js:325
|
||||
msgid "Settings"
|
||||
msgstr "Баптаулар"
|
||||
|
||||
@ -520,7 +553,7 @@ msgstr "Бүгін"
|
||||
|
||||
#: ../js/ui/calendar.js:789
|
||||
msgid "Tomorrow"
|
||||
msgstr "Ертен"
|
||||
msgstr "Ертең"
|
||||
|
||||
#: ../js/ui/calendar.js:800
|
||||
msgid "This week"
|
||||
@ -551,85 +584,85 @@ msgstr "%s көмегімен ашу"
|
||||
msgid "Eject"
|
||||
msgstr "Шығару"
|
||||
|
||||
#: ../js/ui/components/keyring.js:88 ../js/ui/components/polkitAgent.js:280
|
||||
#: ../js/ui/components/keyring.js:91 ../js/ui/components/polkitAgent.js:280
|
||||
msgid "Password:"
|
||||
msgstr "Пароль:"
|
||||
|
||||
#: ../js/ui/components/keyring.js:107
|
||||
#: ../js/ui/components/keyring.js:110
|
||||
msgid "Type again:"
|
||||
msgstr "Қайтадан енгізіңіз:"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:127 ../js/ui/status/network.js:112
|
||||
#: ../js/ui/status/network.js:268 ../js/ui/status/network.js:682
|
||||
#: ../js/ui/components/networkAgent.js:131 ../js/ui/status/network.js:112
|
||||
#: ../js/ui/status/network.js:275 ../js/ui/status/network.js:689
|
||||
msgid "Connect"
|
||||
msgstr "Байланысу"
|
||||
|
||||
#. Cisco LEAP
|
||||
#: ../js/ui/components/networkAgent.js:218
|
||||
#: ../js/ui/components/networkAgent.js:230
|
||||
#: ../js/ui/components/networkAgent.js:257
|
||||
#: ../js/ui/components/networkAgent.js:277
|
||||
#: ../js/ui/components/networkAgent.js:287
|
||||
#: ../js/ui/components/networkAgent.js:222
|
||||
#: ../js/ui/components/networkAgent.js:234
|
||||
#: ../js/ui/components/networkAgent.js:261
|
||||
#: ../js/ui/components/networkAgent.js:281
|
||||
#: ../js/ui/components/networkAgent.js:291
|
||||
msgid "Password: "
|
||||
msgstr "Пароль:"
|
||||
|
||||
#. static WEP
|
||||
#: ../js/ui/components/networkAgent.js:223
|
||||
#: ../js/ui/components/networkAgent.js:227
|
||||
msgid "Key: "
|
||||
msgstr "Кілт:"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:261
|
||||
#: ../js/ui/components/networkAgent.js:265
|
||||
msgid "Identity: "
|
||||
msgstr ""
|
||||
msgstr "Анықтағыш:"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:263
|
||||
#: ../js/ui/components/networkAgent.js:267
|
||||
msgid "Private key password: "
|
||||
msgstr "Жеке кілт паролі:"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:275
|
||||
#: ../js/ui/components/networkAgent.js:279
|
||||
msgid "Service: "
|
||||
msgstr "Қызмет:"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:304
|
||||
#: ../js/ui/components/networkAgent.js:308
|
||||
msgid "Authentication required by wireless network"
|
||||
msgstr "Сымсыз желісі аутентификацияны талап етеді"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:305
|
||||
#: ../js/ui/components/networkAgent.js:309
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Passwords or encryption keys are required to access the wireless network "
|
||||
"'%s'."
|
||||
msgstr "'%s' сымсыз желісіне қатынау үшін парольдер не шифрлеу кілттері керек."
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:309
|
||||
#: ../js/ui/components/networkAgent.js:313
|
||||
msgid "Wired 802.1X authentication"
|
||||
msgstr "Сымды 802.1X аутентификациясы"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:311
|
||||
#: ../js/ui/components/networkAgent.js:315
|
||||
msgid "Network name: "
|
||||
msgstr "Желі аты:"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:316
|
||||
#: ../js/ui/components/networkAgent.js:320
|
||||
msgid "DSL authentication"
|
||||
msgstr "DSL аутентификациясы"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:323
|
||||
#: ../js/ui/components/networkAgent.js:327
|
||||
msgid "PIN code required"
|
||||
msgstr "PIN коды керек"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:324
|
||||
#: ../js/ui/components/networkAgent.js:328
|
||||
msgid "PIN code is needed for the mobile broadband device"
|
||||
msgstr "Сымсыз кеңжолақты құрылғы үшін PIN коды керек"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:325
|
||||
#: ../js/ui/components/networkAgent.js:329
|
||||
msgid "PIN: "
|
||||
msgstr "PIN: "
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:331
|
||||
#: ../js/ui/components/networkAgent.js:335
|
||||
msgid "Mobile broadband network password"
|
||||
msgstr "Сымсыз кеңжолақты желісінің паролі"
|
||||
|
||||
#: ../js/ui/components/networkAgent.js:332
|
||||
#: ../js/ui/components/networkAgent.js:336
|
||||
#, c-format
|
||||
msgid "A password is required to connect to '%s'."
|
||||
msgstr "'%s' үшін байланысты орнату үшін пароль керек."
|
||||
@ -893,7 +926,7 @@ msgstr "Тіркелгіні қарап шығу"
|
||||
msgid "Unknown reason"
|
||||
msgstr "Себебі белгісіз"
|
||||
|
||||
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:96
|
||||
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:100
|
||||
msgid "Windows"
|
||||
msgstr "Терезелер"
|
||||
|
||||
@ -903,7 +936,7 @@ msgstr "Қолданбаларды көрсету"
|
||||
|
||||
#. Translators: this is the name of the dock/favorites area on
|
||||
#. the left of the overview
|
||||
#: ../js/ui/dash.js:439
|
||||
#: ../js/ui/dash.js:442
|
||||
msgid "Dash"
|
||||
msgstr "Dash"
|
||||
|
||||
@ -987,15 +1020,12 @@ msgid_plural "The system will restart automatically in %d seconds."
|
||||
msgstr[0] "Жүйе %d секундтан кейін автоматты түрде қайта қосылады."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:112
|
||||
#| msgid "Install Updates & Restart"
|
||||
msgctxt "title"
|
||||
msgid "Restart & Install Updates"
|
||||
msgstr "Қайта қосу және жаңартуларды орнату"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:114
|
||||
#, c-format
|
||||
#| msgid "The system will restart automatically in %d second."
|
||||
#| msgid_plural "The system will restart automatically in %d seconds."
|
||||
msgid "The system will automatically restart and install updates in %d second."
|
||||
msgid_plural ""
|
||||
"The system will automatically restart and install updates in %d seconds."
|
||||
@ -1037,7 +1067,7 @@ msgstr "Орнату"
|
||||
msgid "Download and install '%s' from extensions.gnome.org?"
|
||||
msgstr "extensions.gnome.org адресінен '%s' жүктеп алып, орнату керек пе?"
|
||||
|
||||
#: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:334
|
||||
#: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:333
|
||||
msgid "Keyboard"
|
||||
msgstr "Пернетақта"
|
||||
|
||||
@ -1113,11 +1143,11 @@ msgstr "Трей мәзірі"
|
||||
msgid "No Messages"
|
||||
msgstr "Хабарламалар жоқ"
|
||||
|
||||
#: ../js/ui/messageTray.js:1812
|
||||
#: ../js/ui/messageTray.js:1813
|
||||
msgid "Message Tray"
|
||||
msgstr "Жүйелік трей"
|
||||
|
||||
#: ../js/ui/messageTray.js:2786
|
||||
#: ../js/ui/messageTray.js:2788
|
||||
msgid "System Information"
|
||||
msgstr "Жүйелік ақпарат"
|
||||
|
||||
@ -1148,21 +1178,17 @@ msgstr "Шолу"
|
||||
msgid "Type to search…"
|
||||
msgstr "Іздеу үшін теріңіз..."
|
||||
|
||||
#: ../js/ui/panel.js:516
|
||||
#: ../js/ui/panel.js:518
|
||||
msgid "Quit"
|
||||
msgstr "Шығу"
|
||||
|
||||
#. Translators: If there is no suitable word for "Activities"
|
||||
#. in your language, you can use the word for "Overview".
|
||||
#: ../js/ui/panel.js:568
|
||||
#: ../js/ui/panel.js:570
|
||||
msgid "Activities"
|
||||
msgstr "Көрініс"
|
||||
|
||||
#: ../js/ui/panel.js:805
|
||||
msgid "Settings Menu"
|
||||
msgstr "Баптаулар мәзірі"
|
||||
|
||||
#: ../js/ui/panel.js:892
|
||||
#: ../js/ui/panel.js:903
|
||||
msgid "Top Bar"
|
||||
msgstr "Үстідегі панель"
|
||||
|
||||
@ -1171,7 +1197,7 @@ msgstr "Үстідегі панель"
|
||||
#. "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:226
|
||||
#: ../js/ui/popupMenu.js:233
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-intl"
|
||||
|
||||
@ -1199,7 +1225,7 @@ msgstr[0] "%d жаңа ескерту"
|
||||
msgid "Lock"
|
||||
msgstr "Блоктау"
|
||||
|
||||
#: ../js/ui/screenShield.js:703
|
||||
#: ../js/ui/screenShield.js:704
|
||||
msgid "GNOME needs to lock the screen"
|
||||
msgstr "GNOME экранды блоктау керек"
|
||||
|
||||
@ -1210,19 +1236,19 @@ msgstr "GNOME экранды блоктау керек"
|
||||
#.
|
||||
#. XXX: another option is to kick the user into the gdm login
|
||||
#. screen, where we're not affected by grabs
|
||||
#: ../js/ui/screenShield.js:830 ../js/ui/screenShield.js:1296
|
||||
#: ../js/ui/screenShield.js:831 ../js/ui/screenShield.js:1297
|
||||
msgid "Unable to lock"
|
||||
msgstr "Блоктау мүмкін емес"
|
||||
|
||||
#: ../js/ui/screenShield.js:831 ../js/ui/screenShield.js:1297
|
||||
#: ../js/ui/screenShield.js:832 ../js/ui/screenShield.js:1298
|
||||
msgid "Lock was blocked by an application"
|
||||
msgstr "Блоктауды басқа қолданба болдырмады"
|
||||
|
||||
#: ../js/ui/searchDisplay.js:445
|
||||
#: ../js/ui/searchDisplay.js:447
|
||||
msgid "Searching…"
|
||||
msgstr "Іздеу..."
|
||||
|
||||
#: ../js/ui/searchDisplay.js:489
|
||||
#: ../js/ui/searchDisplay.js:491
|
||||
msgid "No results."
|
||||
msgstr "Нәтижелер жоқ."
|
||||
|
||||
@ -1296,14 +1322,14 @@ msgstr "Үлкен мәтін"
|
||||
|
||||
#. The Bluetooth menu only appears when Bluetooth is in use,
|
||||
#. so just statically build it with a "Turn Off" menu item.
|
||||
#: ../js/ui/status/bluetooth.js:28 ../js/ui/status/bluetooth.js:62
|
||||
#: ../js/ui/status/bluetooth.js:99 ../js/ui/status/bluetooth.js:127
|
||||
#: ../js/ui/status/bluetooth.js:163 ../js/ui/status/bluetooth.js:194
|
||||
#: ../js/ui/status/bluetooth.js:28 ../js/ui/status/bluetooth.js:63
|
||||
#: ../js/ui/status/bluetooth.js:100 ../js/ui/status/bluetooth.js:128
|
||||
#: ../js/ui/status/bluetooth.js:164 ../js/ui/status/bluetooth.js:195
|
||||
msgid "Bluetooth"
|
||||
msgstr "Bluetooth"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:30 ../js/ui/status/network.js:112
|
||||
#: ../js/ui/status/network.js:1027 ../js/ui/status/rfkill.js:46
|
||||
#: ../js/ui/status/network.js:1034 ../js/ui/status/rfkill.js:46
|
||||
msgid "Turn Off"
|
||||
msgstr "Сөндіру"
|
||||
|
||||
@ -1311,79 +1337,79 @@ msgstr "Сөндіру"
|
||||
msgid "Bluetooth Settings"
|
||||
msgstr "Bluetooth баптаулары"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:57
|
||||
#: ../js/ui/status/bluetooth.js:58
|
||||
#, c-format
|
||||
msgid "%d Connected Device"
|
||||
msgid_plural "%d Connected Devices"
|
||||
msgstr[0] "%d байланысқан құрылғы"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:100 ../js/ui/status/bluetooth.js:128
|
||||
#: ../js/ui/status/bluetooth.js:101 ../js/ui/status/bluetooth.js:129
|
||||
#, c-format
|
||||
msgid "Authorization request from %s"
|
||||
msgstr "%s жіберген авторизация сұранымы"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:106 ../js/ui/status/bluetooth.js:171
|
||||
#: ../js/ui/status/bluetooth.js:202
|
||||
#: ../js/ui/status/bluetooth.js:107 ../js/ui/status/bluetooth.js:172
|
||||
#: ../js/ui/status/bluetooth.js:203
|
||||
#, c-format
|
||||
msgid "Device %s wants to pair with this computer"
|
||||
msgstr "%s құрылғысы бұл компьютермен пар болғысы кеп тұр"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:108
|
||||
#: ../js/ui/status/bluetooth.js:109
|
||||
msgid "Allow"
|
||||
msgstr "Рұқсат ету"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:109
|
||||
#: ../js/ui/status/bluetooth.js:110
|
||||
msgid "Deny"
|
||||
msgstr "Тайдыру"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:134
|
||||
#: ../js/ui/status/bluetooth.js:135
|
||||
#, c-format
|
||||
msgid "Device %s wants access to the service '%s'"
|
||||
msgstr "%s құрылғысы '%s' қызметін қатынағысы кеп тұр"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:136
|
||||
#: ../js/ui/status/bluetooth.js:137
|
||||
msgid "Always grant access"
|
||||
msgstr "Әрқашан рұқсат ету"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:137
|
||||
#: ../js/ui/status/bluetooth.js:138
|
||||
msgid "Grant this time only"
|
||||
msgstr "Тек осы ретке рұқсат ету"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:138
|
||||
#: ../js/ui/status/bluetooth.js:139
|
||||
msgid "Reject"
|
||||
msgstr "Болдырмау"
|
||||
|
||||
#. Translators: argument is the device short name
|
||||
#: ../js/ui/status/bluetooth.js:165
|
||||
#: ../js/ui/status/bluetooth.js:166
|
||||
#, c-format
|
||||
msgid "Pairing confirmation for %s"
|
||||
msgstr "%s жіберген парлау растауы"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:172
|
||||
#: ../js/ui/status/bluetooth.js:173
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Please confirm whether the Passkey '%06d' matches the one on the device."
|
||||
msgstr "'%06d' кілт коды құрылғыдағы кодымен сәйкес келетінін растаңыз."
|
||||
|
||||
#. Translators: this is the verb, not the noun
|
||||
#: ../js/ui/status/bluetooth.js:175
|
||||
#: ../js/ui/status/bluetooth.js:176
|
||||
msgid "Matches"
|
||||
msgstr "Сәйкес"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:176
|
||||
#: ../js/ui/status/bluetooth.js:177
|
||||
msgid "Does not match"
|
||||
msgstr "Сәйкес емес"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:195
|
||||
#: ../js/ui/status/bluetooth.js:196
|
||||
#, c-format
|
||||
msgid "Pairing request for %s"
|
||||
msgstr "%s үшін парлау сұранымы"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:203
|
||||
#: ../js/ui/status/bluetooth.js:204
|
||||
msgid "Please enter the PIN mentioned on the device."
|
||||
msgstr "Құрылғыда көрсетілген PIN кодын енгізіңіз."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:220
|
||||
#: ../js/ui/status/bluetooth.js:221
|
||||
msgid "OK"
|
||||
msgstr "ОК"
|
||||
|
||||
@ -1391,7 +1417,7 @@ msgstr "ОК"
|
||||
msgid "Brightness"
|
||||
msgstr "Жарықтылығы"
|
||||
|
||||
#: ../js/ui/status/keyboard.js:404
|
||||
#: ../js/ui/status/keyboard.js:403
|
||||
msgid "Show Keyboard Layout"
|
||||
msgstr "Пернетақта жаймасын көрсету"
|
||||
|
||||
@ -1399,83 +1425,83 @@ msgstr "Пернетақта жаймасын көрсету"
|
||||
msgid "<unknown>"
|
||||
msgstr "<белгісіз>"
|
||||
|
||||
#: ../js/ui/status/network.js:196 ../js/ui/status/network.js:1042
|
||||
#: ../js/ui/status/network.js:203 ../js/ui/status/network.js:1049
|
||||
msgid "Off"
|
||||
msgstr "Сөнд."
|
||||
|
||||
#: ../js/ui/status/network.js:269 ../js/ui/status/network.js:948
|
||||
#: ../js/ui/status/network.js:276 ../js/ui/status/network.js:955
|
||||
#: ../js/ui/status/rfkill.js:49
|
||||
msgid "Network Settings"
|
||||
msgstr "Желі баптаулары"
|
||||
|
||||
#. Translators: this is for network devices that are physically present but are not
|
||||
#. under NetworkManager's control (and thus cannot be used in the menu)
|
||||
#: ../js/ui/status/network.js:357
|
||||
#: ../js/ui/status/network.js:364
|
||||
msgid "unmanaged"
|
||||
msgstr "басқарылмайтын"
|
||||
|
||||
#: ../js/ui/status/network.js:359
|
||||
#: ../js/ui/status/network.js:366
|
||||
msgid "disconnecting..."
|
||||
msgstr "байланысты үзу..."
|
||||
|
||||
#: ../js/ui/status/network.js:365 ../js/ui/status/network.js:1093
|
||||
#: ../js/ui/status/network.js:372 ../js/ui/status/network.js:1100
|
||||
msgid "connecting..."
|
||||
msgstr "байланысты орнату..."
|
||||
|
||||
#. Translators: this is for network connections that require some kind of key or password
|
||||
#: ../js/ui/status/network.js:368 ../js/ui/status/network.js:1096
|
||||
#: ../js/ui/status/network.js:375 ../js/ui/status/network.js:1103
|
||||
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:376
|
||||
#: ../js/ui/status/network.js:383
|
||||
msgid "firmware missing"
|
||||
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:380
|
||||
#: ../js/ui/status/network.js:387
|
||||
msgid "unavailable"
|
||||
msgstr "қолжетерсіз"
|
||||
|
||||
#: ../js/ui/status/network.js:382 ../js/ui/status/network.js:1098
|
||||
#: ../js/ui/status/network.js:389 ../js/ui/status/network.js:1105
|
||||
msgid "connection failed"
|
||||
msgstr "байланысты орнату сәтсіз"
|
||||
|
||||
#: ../js/ui/status/network.js:647
|
||||
#: ../js/ui/status/network.js:654
|
||||
msgid "Wi-Fi Networks"
|
||||
msgstr "Wi-Fi желілері"
|
||||
|
||||
#: ../js/ui/status/network.js:649
|
||||
#: ../js/ui/status/network.js:656
|
||||
msgid "Select a network"
|
||||
msgstr "Желіні таңдаңыз"
|
||||
|
||||
#: ../js/ui/status/network.js:673
|
||||
#: ../js/ui/status/network.js:680
|
||||
msgid "No Networks"
|
||||
msgstr "Желілер жоқ"
|
||||
|
||||
#: ../js/ui/status/network.js:942
|
||||
#: ../js/ui/status/network.js:949
|
||||
msgid "Select Network"
|
||||
msgstr "Желіні таңдаңыз"
|
||||
|
||||
#: ../js/ui/status/network.js:1027
|
||||
#: ../js/ui/status/network.js:1034
|
||||
msgid "Turn On"
|
||||
msgstr "Іске қосу"
|
||||
|
||||
#: ../js/ui/status/network.js:1160
|
||||
#: ../js/ui/status/network.js:1167
|
||||
msgid "VPN"
|
||||
msgstr "VPN"
|
||||
|
||||
#: ../js/ui/status/network.js:1299
|
||||
#: ../js/ui/status/network.js:1307
|
||||
msgid "Network Manager"
|
||||
msgstr "Желілер басқарушысы"
|
||||
|
||||
#: ../js/ui/status/network.js:1338
|
||||
#: ../js/ui/status/network.js:1346
|
||||
msgid "Connection failed"
|
||||
msgstr "Байланыс орнату сәтсіз"
|
||||
|
||||
#: ../js/ui/status/network.js:1339
|
||||
#: ../js/ui/status/network.js:1347
|
||||
msgid "Activation of network connection failed"
|
||||
msgstr "Желілік байланысты белсендіру сәтсіз"
|
||||
|
||||
@ -1561,11 +1587,11 @@ msgstr "Басқа пайдаланушы ретінде жүйеге кіру"
|
||||
msgid "Unlock Window"
|
||||
msgstr "Блоктауды алу терезесі"
|
||||
|
||||
#: ../js/ui/viewSelector.js:100
|
||||
#: ../js/ui/viewSelector.js:104
|
||||
msgid "Applications"
|
||||
msgstr "Қолданбалар"
|
||||
|
||||
#: ../js/ui/viewSelector.js:104
|
||||
#: ../js/ui/viewSelector.js:108
|
||||
msgid "Search"
|
||||
msgstr "Іздеу"
|
||||
|
||||
@ -1581,7 +1607,7 @@ msgstr ""
|
||||
#: ../js/ui/wanda.js:81
|
||||
#, c-format
|
||||
msgid "%s the Oracle says"
|
||||
msgstr ""
|
||||
msgstr "Болжаушы айтады: %s"
|
||||
|
||||
#: ../js/ui/windowAttentionHandler.js:19
|
||||
#, c-format
|
||||
@ -1665,3 +1691,6 @@ msgstr "Пароль бос болуы мүмкін емес"
|
||||
#: ../src/shell-polkit-authentication-agent.c:343
|
||||
msgid "Authentication dialog was dismissed by the user"
|
||||
msgstr "Аутентификация терезесін пайдаланушы тайдырды"
|
||||
|
||||
#~ msgid "Settings Menu"
|
||||
#~ msgstr "Баптаулар мәзірі"
|
||||
|