Compare commits

..

4 Commits

Author SHA1 Message Date
11bf65e2b4 status/keyboard: Disregard the backwards flag for the popup switcher
This seems to cause more harm than good. It puzzles users looking at
the shortcuts list in g-c-c and it prevents otherwise valid shortcuts
like Shift+Hangul from working.

https://bugzilla.gnome.org/show_bug.cgi?id=695823
2013-04-05 18:12:48 +02:00
a8b7e559aa status/keyboard: Allow switching input source in the message tray
We still can't show a popup switcher in the message tray but we can at
least degrade gracefully and advance to the next input source.

https://bugzilla.gnome.org/show_bug.cgi?id=697009
2013-04-05 18:12:48 +02:00
b733e30a4a status/keyboard: Switch input source on special modifiers accelerator
This simply mimics the X server's layout switching behavior by
advancing to the next input source and wrapping around.

https://bugzilla.gnome.org/show_bug.cgi?id=697008
2013-04-05 18:12:48 +02:00
b607958134 status/keyboard: Synchronize input source switching with key events
Currently we simply set the gsettings key when activating an input
source. This obviously introduces a time window, between the event that
activates the switch and when the switch is complete, under which key
events are being delivered to applications and interpreted according
to the previous input source.

The patches in bug 696996 introduce a DBus API in g-s-d that allows us
to know when an input source if effectively active. Using that and
freezing keyboard events in the X server until we hear back from g-s-d
we can ensure that events won't be misinterpreted after an input
source switch.

https://bugzilla.gnome.org/show_bug.cgi?id=697007
2013-04-05 18:12:47 +02:00
382 changed files with 89310 additions and 115311 deletions

14
.gitignore vendored
View File

@ -19,19 +19,13 @@ configure
data/50-gnome-shell-*.xml data/50-gnome-shell-*.xml
data/gnome-shell.desktop data/gnome-shell.desktop
data/gnome-shell.desktop.in 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
data/gnome-shell-extension-prefs.desktop.in data/gnome-shell-extension-prefs.desktop.in
data/gnome-shell-theme.gresource
data/gschemas.compiled data/gschemas.compiled
data/perf-background.xml
data/org.gnome.shell.gschema.xml data/org.gnome.shell.gschema.xml
data/org.gnome.shell.gschema.valid data/org.gnome.shell.gschema.valid
data/org.gnome.shell.evolution.calendar.gschema.xml data/org.gnome.shell.evolution.calendar.gschema.xml
data/org.gnome.shell.evolution.calendar.gschema.valid data/org.gnome.shell.evolution.calendar.gschema.valid
data/org.gnome.Shell.PortalHelper.desktop
data/org.gnome.Shell.PortalHelper.service
docs/reference/*/*.args docs/reference/*/*.args
docs/reference/*/*.bak docs/reference/*/*.bak
docs/reference/*/*.hierarchy docs/reference/*/*.hierarchy
@ -47,8 +41,6 @@ docs/reference/*/xml/
docs/reference/shell/doc-gen-* docs/reference/shell/doc-gen-*
gtk-doc.make gtk-doc.make
js/misc/config.js js/misc/config.js
js/js-resources.c
js/js-resources.h
intltool-extract.in intltool-extract.in
intltool-merge.in intltool-merge.in
intltool-update.in intltool-update.in
@ -79,14 +71,14 @@ src/calendar-server/evolution-calendar.desktop.in
src/calendar-server/org.gnome.Shell.CalendarServer.service src/calendar-server/org.gnome.Shell.CalendarServer.service
src/gnome-shell src/gnome-shell
src/gnome-shell-calendar-server src/gnome-shell-calendar-server
src/gnome-shell-extension-prefs
src/gnome-shell-extension-tool src/gnome-shell-extension-tool
src/gnome-shell-extension-prefs
src/gnome-shell-hotplug-sniffer src/gnome-shell-hotplug-sniffer
src/gnome-shell-jhbuild
src/gnome-shell-perf-helper src/gnome-shell-perf-helper
src/gnome-shell-perf-tool src/gnome-shell-perf-tool
src/gnome-shell-portal-helper src/gnome-shell-real
src/hotplug-sniffer/org.gnome.Shell.HotplugSniffer.service src/hotplug-sniffer/org.gnome.Shell.HotplugSniffer.service
src/org-gtk-application.[ch]
src/run-js-test src/run-js-test
src/test-recorder src/test-recorder
src/test-recorder.ogg src/test-recorder.ogg

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "src/gvc"] [submodule "src/gvc"]
path = src/gvc path = src/gvc
url = git://git.gnome.org/libgnome-volume-control url = git://git.gnome.org/libgnome-volume-control
[submodule "data/theme/gnome-shell-sass"]
path = data/theme/gnome-shell-sass
url = https://git.gnome.org/browse/gnome-shell-sass

41
COPYING
View File

@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
Version 2, June 1991 Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
Preamble Preamble
The licenses for most software are designed to take away your The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public freedom to share and change it. By contrast, the GNU General Public
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to the GNU Library General Public License instead.) You can apply it to
your programs, too. your programs, too.
When we speak of free software, we are referring to freedom, not When we speak of free software, we are referring to freedom, not
@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and The precise terms and conditions for copying, distribution and
modification follow. modification follow.
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains 0. This License applies to any program or other work which contains
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on does not normally print such an announcement, your work based on
the Program is not required to print an announcement.) the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program, identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in and can be reasonably considered independent and separate works in
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not distribution of the source code, even though third parties are not
compelled to copy the source along with the object code. compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program 4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is otherwise to copy, modify, sublicense or distribute the Program is
@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License. be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in 8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License original copyright holder who places the Program under this License
@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally. of promoting the sharing and reuse of software generally.
NO WARRANTY NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it possible use to the public, the best way to achieve this is to make it
@ -303,16 +303,17 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program; if not, write to the Free Software
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail. Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this If the program is interactive, make it output a short notice like this
when it starts in an interactive mode: when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details. under certain conditions; type `show c' for details.
@ -335,5 +336,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General library. If this is what you want to do, use the GNU Library General
Public License instead of this License. Public License instead of this License.

View File

@ -138,8 +138,8 @@ GObjects, although this feature isn't used very often in the Shell itself.
_init: function(icon, label) { _init: function(icon, label) {
this.parent({ reactive: false }); this.parent({ reactive: false });
this.actor.add_child(icon); this.addActor(icon);
this.actor.add_child(label); this.addActor(label);
}, },
open: function() { open: function() {

View File

@ -1,11 +1,7 @@
# Point to our macro directory and pick up user flags from the environment # Point to our macro directory and pick up user flags from the environment
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
SUBDIRS = data js src tests po docs SUBDIRS = data js src browser-plugin tests po docs
if BUILD_BROWSER_PLUGIN
SUBDIRS += browser-plugin
endif
if ENABLE_MAN if ENABLE_MAN
SUBDIRS += man SUBDIRS += man

969
NEWS
View File

@ -1,972 +1,3 @@
3.15.4
======
* Add mode parameter to AcceleratorActivated signal [Florian; #711682]
* Fix PID based window/app association [Sebastian; #736527]
* Fix current day highlight on day change [Sebastian; #742492]
* Switch to vp9 for screencast recordings [Adel; #742744]
* Disable IBus input sources on password entries [Takao; #730628]
* Make slider scrolling smoother [Adel; #742648]
* Allow move-up shortcut to move window above top workspace [Florian; #665764]
* Misc. bug fixes [Adel, Rui; #742748, #742824, #741114]
Contributors:
Cosimo Cecchi, Takao Fujiwara, Adel Gadllah, Sebastian Keller, Rui Matos,
Florian Müllner, Jasper St. Pierre
Translations:
Andika Triwidada [id], Matej Urbančič [sl], Saibal Ray [bn_IN],
Inaki Larranaga Murgoitio [eu], Stas Solovey [ru], Kjartan Maraas [nb],
Balázs Úr [hu], Marek Černocký [cs], Rafael Ferreira [pt_BR],
Bernd Homuth [de], Daniel Mustieles [es], Fabio Tomat [fur]
3.15.3
======
* Add support for high-contrast themes [Florian; #740447]
* Fix banner message on login screen without user list [Ray; #703972]
* Fix flicker when activating windows on another workspace [Florian; #741680]
* Misc. bug fixes [Giovanni, Florian; #735308, #740237]
Contributors:
Giovanni Campagna, Florian Müllner, Jasper St. Pierre, Ray Strode
Translations:
Balázs Úr [hu], Josef Andersson [sv], Muhammet Kara [tr],
Baurzhan Muftakhidinov [kk], Inaki Larranaga Murgoitio [eu]
3.15.2
======
* Fix visual glitch of window preview outline in overview [Chris; #699044]
* Change user facing name of "Captive Portal" to "Network Login" [Elad; #737198]
* Port to Python 3 [Slavek; #732478]
* Hide Airplane mode indicator when g-s-d says so [Cosimo; #736292]
* Allow translators to change non-work days [Lavi; #664645]
* Delay invocation of caribou daemon until really needed [Daiki; #739712]
* Don't lock screen after crash if locking is disabled [Adel; #704884]
* Improve layout of extension installation dialog [William; #739888]
* Fix workspace changes from app picker [Yuki; #737534]
* Preload all ibus input sources in user configuration [Takao; #695428]
* Properly remove network connections from list [Ryan; #740227]
* Support CSS margin property [Carlos; #728437]
* Improve handling of BUSY application state [Phillip; #736492]
* Fix erroneous week numbers in calendar [Florian; #736722]
* Misc. bugfixes and cleanups [Darcy, Yuki, Alexander, Eskild, Bastien, Cosimo, Colin,
Ray; #738725, #739497, #739241, #672500, #739822, #740074, #704163, #740141]
Contributors:
Yuki, Lavi .A, Elad Alfassa, Cosimo Cecchi, Takao Fujiwara, Adel Gadllah,
Eskild Hustvedt, Chris Johns, William Jon McCann, Slavek Kabrda, Ryan Lortie,
Florian Müllner, Bastien Nocera, Christian Persch, Carlos Soriano,
Jasper St. Pierre, Ray Strode, Alexander Tsoy, Daiki Ueno, Colin Walters,
Phillip Wood
Translations:
Jorge Perez Perez [an], Daniel Martinez [an], Daniel Mustieles [es],
Trần Ngọc Quân [vi], Changwoo Ryu [ko], Kjartan Maraas [nb],
Yosef Or Boczko [he], Marek Černocký [cs]
3.15.1
======
* Use GResources for theme loading [Cosimo; #736936]
* Reset the OSK to primary on monitor changes [Rui; #738536]
* Use LC_TIME locale for format string translations [Florian; #738640]
* Summarize queued up notifications [Devyani; #702460]
* Improve handling of multi-day events [Andreas; #727302]
* Support EXTERNAL scroll policy type [Florian; #739379]
* Misc. bugfixes [Owen, Rui; #738652, #739252]
Contributors:
Andreas Brauchli, Cosimo Cecchi, Devyani Kota, Rui Matos, Florian Müllner,
Jasper St. Pierre, Owen W. Taylor
Translations:
Bahodir Mansurov [uz@cyrillic]
3.14.1
======
* Fix pulse animation for scrolled app folders [Florian; #736885]
* Fix updating background on file changes [Owen; #710756]
* Obtain keyboard variant from IBus [Jinkyu; #735066]
* Implement Ctrl-u / Ctrl-k keybindings in entries [Florian; #737346]
* Pass VPN hints to auth dialog [Dan; #737592]
* Only allow one screenshot request at a time [Adel; #737456]
* Respect disable-save-to-disc lockdown setting [Florian; #737846]
* Respect scaling-factor for profile pictures [Darcy; #735419]
* Focus login screen after lifting the lock screen shield [Ray; #708105]
* Speed up pulse animation for few items [Carlos S.; #737017]
* Fix gap between workspace switcher and screen edge [Florian; #728899]
* Disable unredirection during recordings [Adel; #738226]
* Ensure there's always at least one input source [Rui; #738303]
* Restrict width of dash icons' context menus [Adel; #738054]
* Misc. bug fixes [Jasper, Florian, Carlos G., Owen; #736999, #737382, #737001,
#738314, #738256, #738147]
Contributors:
Darcy Beurle, Cosimo Cecchi, Adel Gadllah, Carlos Garnacho, Rui Matos,
Florian Müllner, Carlos Soriano, Jasper St. Pierre, Ray Strode, Patrick Ward,
Dan Williams, Owen W. Taylor, Jinkyu Yi
Translations:
Мирослав Николић po/sr, sr@latin.po, Fran Diéguez [gl], Marek Černocký [cs],
Saibal Ray [bn_IN], Rajesh Ranjan [hi], Friedel Wolff [af],
Zhou Fang [zh_CN], Krishnababu Krothapalli [te], Kjartan Maraas [nb],
Rūdolfs Mazurs [lv], Sweta Kothari [gu], Christian Kirbach [de],
Cheng-Chia Tseng [zh_TW], Pedro Albuquerque [pt], Daniel Mustieles [es],
Luca Ferretti [it], Baurzhan Muftakhidinov [kk], Arash Mousavi [fa],
Milo Casagrande [it]
3.14.0
======
* Fix exposure of the accessible tree [Alejandro; #736821]
* Hide empty app folders in app picker [Florian; #736910]
Contributors:
Florian Müllner, Alejandro Piñeiro
Translations:
Yuri Myasoedov [ru], Pawan Chitrakar [ne], Manoj Kumar Giri [or],
Daniel Mustieles [es], GNOME Translation Robot [de], Rajesh Ranjan [hi],
Shankar Prasad [kn], Kenneth Nielsen [da], Daniel Korostil [uk],
Changwoo Ryu [ko], A S Alam [pa], Tom Tryfonidis [el], Petr Kovar [cs]
3.13.92
=======
* Fix submenu arrow animations [Hashem; #728927]
* Always initialize clutter accessibility [Alejandro; #735908]
* Adapt to mutter background changes [Owen; #735638]
* Improve handling of outOfDate extensions in prefs [Florian; #736185]
* Port offline updates to PackageKit's DBus interface [Kalev; #736337]
* location: Translate accuracy levels for geoclue [Zeeshan; #736479]
* Implement input source switching [Rui; #736435]
* Fix crash when dragging window from workspace switcher [Carlos G.; #735972]
* Clean out list of default favorites [Elad; #735682]
* Add settings link to location submenu [Florian; #736542]
* Fix keynav of message tray menu button [Florian; #707799]
* Misc. bug fixes [Carlos G., Florian, Rui; #736110, #736329, #736343,
#735927, #735976]
Contributors:
Elad Alfassa, Zeeshan Ali (Khattak), Michael Catanzaro, Adel Gadllah,
Carlos Garnacho, Kalev Lember, Rui Matos, Florian Müllner, Hashem Nasarat,
Alejandro Piñeiro, Carlos Soriano, Jasper St. Pierre, Owen W. Taylor
Translations:
Piotr Drąg [pl], Changwoo Ryu [ko], Yuri Myasoedov [ru], Zhou Fang [ja],
Peter Mráz [sk], Ville-Pekka Vainio [fi], Sweta Kothari [gu],
Marek Černocký [cs], A S Alam [pa], Christian Kirbach [de],
Alexandre Franke [fr], Aurimas Černius [lt], Khaled Hosny [ar],
Enrico Nicoletto [pt_BR], Andika Triwidada [id], Shantha kumar [ta],
Matej Urbančič [sl], Pawan Chitrakar [ne], Yosef Or Boczko [he],
Balázs Úr [hu], Dušan Kazik [sk], Gil Forcada [ca],
Carles Ferrando [ca@valencia], Nilamdyuti Goswami [as], Ivaylo Valkov [bg],
Sandeep Sheshrao Shedmake [mr], Umarzuki Bin Mochlis Moktar [ms],
Muhammet Kara [tr], Jiro Matsuzawa [ja], Kris Thomsen [da],
Mattias Eriksson [sv]
3.13.91
=======
* Fix keynav into session menu on login screen [Florian; #735614]
* Add gesture to summon message tray [Carlos G.; #735625]
* Accept scrolls/swipes either way on the screen shield [Jasper; #734874]
* Animate opening the app picker and improve app folder animations
[Carlos S.; #734726]
* Animate app icons on launching a new window [Carlos S., Florian; #734726]
* Show the on-screen keyboard when touch input is being used [David; #702015]
* Misc. bug fixes [Bastien, Owen, Florian, Carlos G.; #735190, #735385,
#735608, #735681]
Contributors:
Carlos Garnacho, David King, Kalev Lember, Florian Müllner, Bastien Nocera,
Carlos Soriano, Jasper St. Pierre, Owen W. Taylor
Translations:
Fran Diéguez [gl], Sweta Kothari [gu], Manoj Kumar Giri [or],
Alain Lojewski [fr], Praveen Illa [te], Arash Mousavi [fa],
Andika Triwidada [id]
3.13.90
=======
* Make use of GLSL optional [Adel; #733623]
* Update on-screen-keyboard position on monitor changes [Cosimo; #733790]
* Improve window manager animations [Giovanni; #732857]
* Handle touch events [Carlos G.; #733633]
* Try to not show "New Window" action for single-window apps
[Giovanni; #722554]
* Fix overview exceeding screen size with many apps installed
[Carlos S.; #723496]
* Add Software to default favorites [Mathieu; #734406]
* Improve app picker <-> desktop transition [Carlos S.; #732901]
* Remove <shift>-magic for switcher popups [Christophe; #732296]
* Add a special background to use for performance testing [Owen; #734610]
* Add support for default disabled search providers [Giovanni; #734110]
* Fix portals that don't redirect properly [Giovanni; #733848]
* Fix history trimming in chat notifications [Giovanni; #733899]
* Try to use default calendar application [Florian; #722333]
* Only show location menu when geolocation is in use [Zeeshan; #731122]
* Misc. bug fixes and cleanups [Giovanni, Carlos G., Zeeshan, Carlos S.,
Cosimo; #711682, #733840, #734483, #734680, #733813, #735062]
Contributors:
Zeeshan Ali (Khattak), Mathieu Bridon, Giovanni Campagna, Cosimo Cecchi,
Piotr Drąg, Christophe Fergeau, Adel Gadllah, Carlos Garnacho,
Florian Müllner, Carlos Soriano, Jasper St. Pierre, Olav Vitters,
Owen W. Taylor
Translations:
Aurimas Černius [lt], MarMav [el], Inaki Larranaga Murgoitio [eu],
Reinout van Schouwen [nl], ngoswami [as], Fabio Tomat [fur],
Chao-Hsiung Liao [zh_HK, zh_TW]
3.13.4
======
* Handle portal login requests [Giovanni; #704416]
* Scale fonts on wayland on hiDPI devices [Adel; #732537]
* Fix default ibus candidate index labels [Rui; #702944]
* Add gestures for various system actions [Carlos G.]
* Add performance test script for the perf.gnome.org [Owen; #732350]
* Use new restart framework to improve restart visuals [Owen; #733026]
* Improve keynav in app folder popups [Carlos S.; #731477]
* Fix truncation of app search results [Carlos S.; #732416]
* Automatically update renamed desktop files in favorites [Kalev; #729429]
* Misc. bug fixes and cleanups [Giovanni, Yosef, Owen, Bastien, Javier;
#729823, #726401, #732301, #732348, #732349, #733498, #733540]
Contributors:
Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Javier Hernández,
Kalev Lember, Rui Matos, Florian Müllner, Bastien Nocera, Yosef Or Boczko,
Carlos Soriano, Jasper St. Pierre, Owen W. Taylor
Translations:
Yuri Myasoedov [ru], Daniel Mustieles [es], Fran Diéguez [gl],
Cheng-Chia Tseng [zh_TW], A S Alam [pa], Benjamin Steinwender [de],
Enrico Nicoletto [pt_BR], MarMav [el], Yosef Or Boczko [he],
Kjartan Maraas [nb]
3.13.3
======
* Don't allow closing windows with attached modals [Florian; #729886]
* Fix self-restarting on OpenBSD [Antoine; #727763]
* Improve behavior of window buttons with compositor menus [Florian; #731058]
* Work around atspi-related performance regression [Alejandro; #730118]
* Misc bug fixes and cleanups [Florian, Lan, Jasper, Christophe, Debarshi,
Zeeshan; #728271, #726460, #703833, #731118, #731220, #695487, #730527,
#728170, #731619, #731738, #731882, #731923]
Contributors:
Zeeshan Ali (Khattak), Christophe Fergeau, Adel Gadllah, Antoine Jacoutot,
Ting-Wei Lan, Florian Müllner, Alejandro Piñeiro, Debarshi Ray,
Carlos Soriano, Jasper St. Pierre, Wim Taymans, Rico Tzschichholz
Translations:
Philip Withnall [en_GB], Milo Casagrande [it], Aurimas Černius [lt],
Enrico Nicoletto [pt_BR], Kjartan Maraas [nb], Balázs Meskó [hu],
Muhammet Kara [tr], Daniel Mustieles [es], Yosef Or Boczko [he],
Matej Urbančič [sl], Mattias Eriksson [sv]
3.13.2
======
* Make airplane mode menu insensitive in lock screen [Giovanni; #729224]
* Don't always extend struts to the screen edge [Florian; #683819]
* Fix keynav for alternatives in AltSwitcher [Florian; #727259]
* Implement window menus in the shell [Jasper; #726352]
* Support resource:/// URLs in GNOME_SHELL_JS envvar [Owen; #730409]
* Fix switcher popups with keybindings containing Escape [Rui; #730739]
* Update extension-prefs UI to follow GNOME 3 patterns [Florian; #730829]
* Add support for fallback app menu in window decorations [Florian; #730752]
* Fix keynav escaping open app folders [Florian; #726760]
* Misc. bug fixes [Kalev, Florian, Owen; #729429, #728449, #730408, #730753,
#730653]
Contributors:
Giovanni Campagna, Piotr Drąg, Kalev Lember, Rui Matos, Florian Müllner,
Vadim Rutkovsky, Carlos Soriano, Jasper St. Pierre, Owen W. Taylor
Translations:
Ihar Hrachyshka [be], Giovanni Campagna [it], Carles Ferrando [ca@valencia],
Daniel Mustieles [es], Aurimas Černius [lt], Enrico Nicoletto [pt_BR],
Yosef Or Boczko [he], Marek Černocký [cs], Muhammet Kara [tr],
Georges Neto [pt_BR], Andika Triwidada [id]
3.13.1
======
* Ensure the currently focused app icon is viewable [Rui; #726759]
* Improve language in location menu [Zeeshan; #726498]
* Improve HiDpi support [Cosimo; #726907]
* Set accessible role for window previews [Alejandro; #726670]
* Fix bad antialiasing on panel menu buttons [Carlos; #727336]
* Don't hide location menu [Zeeshan; #727398]
* Fix IM candidate window obscuring current text [Rui; #727579]
* Don't always extend struts to the screen edge [Florian; #663690]
* Add shortcuts for switching to the last workspace [Elad; #659288]
* Show OSD window on all monitors [Adel; #722684]
* Improve consistency of labels in network menu [Paul; #727163]
* Fix zombie search providers showing up [Jasper; #728597]
* Remove ConsoleKit support [Florian; #686626]
* Fix region screenshots with open shell menus [Florian; #709126]
* Support <shift>insert in text entries [Florian; #648318]
* Improve app picker scrolling on touch [Jasper; #729064]
* Don't make date button clickable when on current date [Carlos; #726724]
* Tweak heuristic for hiding workspace switcher [Florian; #662457]
* Add option to show in Software to app context menu [Matthias; #643043]
* Misc. bug fixes and cleanups [Bastien, Florian, Giovanni, Adel, Vadim,
Carlos; #727983, #727948, #728512, #728681, #728897, #727384, #728820,
#715042, #728449, #728343]
Contributors:
Elad Alfassa, Zeeshan Ali (Khattak), Giovanni Campagna, Cosimo Cecchi,
Matthias Clasen, Piotr Drąg, Adel Gadllah, Paul Lange, Rui Matos,
Simon McVittie, Florian Müllner, Bastien Nocera, Alejandro Piñeiro,
Vadim Rutkovsky, Carlos Soriano, Jasper St. Pierre
Translations:
Khaled Hosny [ar], Piotr Drąg [pl], Yosef Or Boczko [he],
Antonio Fernandes C. Neto [pt_BR], Marek Černocký [cs], maria thukididu [el],
Andika Triwidada [id], Daniel Mustieles [es], Changwoo Ryu [ko],
Benjamin Steinwender [de], Sphinx Jiang [zh_CN],
Inaki Larranaga Murgoitio [eu], Marcus Lundblad [sv], Aurimas Černius [lt],
Stas Solovey [ru], Alexandre Franke [fr], Matej Urbančič [sl],
Fran Diéguez [gl], Pau Iranzo [ca], Luca Ferretti [it], Milo Casagrande [it],
Tiago S [pt], Victor Ibragimov [tg], Dirgita [id], Khoem Sokhem [km],
Rūdolfs Mazurs [lv], Balázs Úr [hu], Ask H. Larsen [da], Ikuya Awashiro [ja],
Wouter Bolsterlee [nl], Daniel Korostil [uk], Daniel Șerbănescu [ro],
Enrico Nicoletto [pt_BR]
3.12.0
======
* gdm: Reset greeter when coming back to login screen [Jasper; #726989]
Contributors:
Jasper St. Pierre
Translations:
Daniel Martinez [an], Yuri Myasoedov [ru], Inaki Larranaga Murgoitio [eu],
Abderrahim Kitouni [ar], Praveen Illa [te], Matej Urbančič [sl],
Chao-Hsiung Liao [zh_HK, zh_TW], Frédéric Péters [fr],
Мирослав Николић [sr, sr@latin], Ask H. Larsen [da], Kenneth Nielsen [da],
Jiro Matsuzawa [ja], Dušan Kazik [sk]
3.11.92
=======
* calendar: Grab key focus after changing day [Volker; #725606]
* gdm: Don't load user list if disabled [Florian; #725905]
* Don't show network-offline in the top bar [Jasper; #725340]
* Improve radial shade effect of modal dialogs [Giovanni; #725830]
* Fix broken suspend-on-idle functionality [Giovanni; #712706]
* Close wifi selection dialog when device disappears [Giovanni; #723935]
* Don't close chats when pressing Escape [Giovanni; #724178]
* Improve smartcard support in login/lock screen [Ray; #726262, #726263]
* Wake up screen when resuming from suspend [Giovanni; #726378]
* Make bluetooth and location items insensitive when locked [Florian; #726319]
* Don't show bluetooth icon when there is no adapter [Giovanni; #725057]
* Make sure to keep the OSK on top of modal dialogs [Rui; #719451]
* Misc. bug fixes and cleanups [Giovanni, Ray, Adel, Daniel, Jasper, Florian;
#725832, #725958, #722149, #724977, #724798, #725020, #723976, #726119,
#726238, #585500, #704844, #726323, #726322, #726120, #726414]
Contributors:
Giovanni Campagna, Daniel Drake, Adel Gadllah, Rui Matos, Florian Müllner,
Volker Sobek, Jasper St. Pierre, Ray Strode
Translations:
Fabio Tomat [fur], Rafael Ferreira [pt_BR], Fran Diéguez [gl],
Marek Černocký [cs], Baurzhan Muftakhidinov [kk], Andika Triwidada [id],
A S Alam [pa], Rūdolfs Mazurs [lv], Wylmer Wang [zh_CN],
Aurimas Černius [lt], Cheng-Chia Tseng [zh_TW], Stas Solovey [ru],
Tiagosdot [pt], Benjamin Steinwender [de], Frédéric Peters [fr],
Daniel Korostil [uk], Yaron Shahrabani [he], Ville-Pekka Vainio [fi],
maria thukididu [el], Victor Ibragimov [tg], Kjartan Maraas [nb],
Gábor Kelemen [hu], Ask H. Larsen [da]
3.11.91
=======
* Don't use network profile name in menu [Giovanni; #725586]
* calendar: Make date label clickable to return to current date [Vit; #641366]
* Misc. bug fixes [Florian, Zeeshan, Adel, Jasper, Dan, Volker; #724813,
#724686, #725082, #724870, #724779, #725533]
Contributors:
Zeeshan Ali (Khattak), Giovanni Campagna, Piotr Drąg, Adel Gadllah,
Florian Müllner, Volker Sobek, Vit Stanislav, Jasper St. Pierre, Dan Williams
Translations:
Victor Ibragimov [tg], Aurimas Černius [lt], Dimitris Spingos [el],
Andika Triwidada [id], Rafael Ferreira [pt_BR], Daniel Mustieles [es],
Baurzhan Muftakhidinov [kk], Marek Černocký [cs], Ihar Hrachyshka [be],
eternalhui [zh_CN], Yosef Or Boczko [he], Fran Diéguez [gl],
Khaled Hosny [ar], Ville-Pekka Vainio [fi], Piotr Drąg [pl],
Kjartan Maraas [nb], Changwoo Ryu [ko]
3.11.90
=======
* Stop showing two bluetooth entries [Giovanni; #709353]
* Improve styling of login/lock screen [Reda; #723833]
* Fix magnifier crosshairs [Magdalen; #723709]
* Make NetworkManager support optional [Michael; #669495]
* Make middle-click open a new instance [Florian; #695010]
* Scale the UI on high resolution displays [Cosimo, Adel; #705410, #724607]
* Remove notification counter on screen shield [Carlos; #709275]
* Improve app picker transition [Carlos; #722331]
* Add geolocation indicator to status menu [Zeeshan; #723684]
* Improve timestamps in chat notifications [Carlos; #708031, #715158]
* Improve network menus [Giovanni; #723570]
* Add "VPN Setting" item to VPN submenu [Giovanni; #709167]
* Improve appearance of disclosure arrows [Carlos; #720206]
* Add GSetting key to disable version validation of extensions [Adel; #724683]
* Delay auto-removing empty workspaces [Florian; #709064]
* Offer offline updates in the shutdown dialog [Kalev; #722898]
* Animate tile previews [Florian; #665758]
* Misc. bug fixes and cleanups [Giovanni, Ryan, Debarshi, Florian; #709128,
#722342, #723661, #724184, #724256, #724293, #724305, #722554, #724282,
#724690, #722928]
Contributors:
Zeeshan Ali (Khattak), Magdalen Berns, Michael Biebl, Giovanni Campagna,
Cosimo Cecchi, Adel Gadllah, Reda Lazri, Kalev Lember, Ryan Lortie,
Florian Müllner, Debarshi Ray, Carlos Soriano, Jasper St. Pierre,
Colin Walters
Translations:
Victor Ibragimov [tg], Daniel Mustieles [es], Khaled Hosny [ar],
Enrico Nicoletto [pt_BR], Yosef Or Boczko [he], Fran Diéguez [gl],
Marek Černocký [cs], Baurzhan Muftakhidinov [kk], Jorge Pérez Pérez [an],
Kjartan Maraas [nb], David Lüder [de], Daniel Korostil [uk], ngoswami [as],
Rafael Ferreira [pt_BR]
3.11.5
======
* Fix extension preference tool [Florian; #722334]
* Fix keyboard activation of legacy tray icons [Giovanni; #721267]
* Add radial background shade for modal dialogs [Giovanni; #669798]
* Show attached modal windows in the overview [Giovanni; #650843]
* Add support for desktop actions [Giovanni; #669603]
* Indicate in system status when location service is used [Zeeshan; #709372]
* Add support for extended app folder schema [Jasper; #723179]
* Show status icon for wired network connections [Jasper; #708966]
* Indicate airplane mode in network selection dialog [Giovanni; #709128]
* Misc bug fixes and cleanups [Florian, Sebastian, Giovanni, Tim, Matt, Jasper;
#722417, #722494, #722547, #722593, #722434, #722787, #722690, #722840,
#722660, #722812, #723197, #722927, #723306, #723308, #723523, #709685,
#723570]
Contributors:
Zeeshan Ali (Khattak), Magdalen Berns, Giovanni Campagna, William Jon McCann,
Sebastian Keller, Tim Lunn, Florian Müllner, Carlos Soriano,
Jasper St. Pierre, Rico Tzschichholz, Matt Watson
Translations:
Marek Černocký [cs], Mattias Põldaru [et], Tong Hui [zh_CN],
Victor Ibragimov [tg], Enrico Nicoletto [pt_BR], Daniel Mustieles [es],
Fran Diéguez [gl], Kjartan Maraas [nb], Nilamdyuti Goswami [as],
Aurimas Černius [lt], Stas Solovey [ru], Yosef Or Boczko [he],
Jorge Pérez Pérez [an], Dimitris Spingos [el], Baurzhan Muftakhidinov [kk],
Chao-Hsiung Liao [zh_HK, zh_TW], Shankar Prasad [kn], Yaron Shahrabani [he],
Andika Triwidada [id]
3.11.4
======
* Fix removal of workspacaes that are not at the end [Giovanni; #721417]
* Allow session mode to be specified in the environment [Ray; #720894]
* Special-case launching of terminals [Debarshi; #695010]
* Always show arrow if app switcher is scrollable [Jonh; #711467]
* Implement new app folders system [Jasper; #722117]
* Remove arrow from background menu [Tarun; #699608]
* Misc bug fixes and cleanups [Giovanni, Andika, Florian, Ray; #721039,
#721439, #721507, #721629, #721868, #722210]
Contributors:
Giovanni Campagna, Piotr Drąg, Tarun Kumar Joshi, Florian Müllner,
Debarshi Ray, Jasper St. Pierre, Ray Strode, Andika Triwidada, Jonh Wendell
Translations:
Dušan Kazik [sk], Tong Hui [zh_CN], Benjamin Steinwender [de],
Matej Urbančič [sl], Jorge Pérez Pérez [an], Kjartan Maraas [nb],
Milo Casagrande [it], Rafael Ferreira [pt_BR], Marek Černocký [cs],
Daniel Mustieles [es], Adorilson Bezerra [pt_BR], Christian Kirbach [de],
Aurimas Černius [lt], Andika Triwidada [id], Baurzhan Muftakhidinov [kk],
Victor Ibragimov [tg], Yosef Or Boczko [he], Dimitris Spingos [el],
Fran Diéguez [gl]
3.11.3
======
* Fix fade effect of desktop icons [Florian; #707671]
* Fix issues with background management code [Jasper; #709313]
* Use new Glib facilities for application search [Jasper; #711631]
* Add focus indication to session menu button [Sebastien; #710539]
* Fix hover tracking for StEntries [Jasper; #706749]
* Fix reentrancy issue in message tray [Jasper; #711694]
* Tone down zoom animation on login/unlock [Jasper; #712362]
* Allow specifying monitor for OSD [Carlos; #712664]
* Fix resetting prompt on user switch [Ray; #710456]
* Stop using gnome-bluetooth-applet [Bastien; #719341]
* Add support for EAP-FAST password requests [Dan; #719813]
* Fix entry focus of chat notifications [Jasper; #709853]
* Make window previews keyboard navigatable [Jasper; #644306]
* Fix app switcher order with dialog windows [Florian; #719824]
* Allow remote search providers without icons [Debarshi; #719965]
* Fix various alignment issues in RTL locales [Yosef; #712638, #712596,
#712594, #712600, #712579]
* Misc. bug fixes and cleanups [Jasper, Florian, Giovanni, Dan; #712727,
#712753, #719378, #719730, #719803, #710115, #720017, #719815, #719567,
#720298]
Contributors:
Giovanni Campagna, Carlos Garnacho, Sebastien Lafargue, Tim Lunn,
Florian Müllner, Bastien Nocera, Yosef Or Boczko, Debarshi Ray,
Jasper St. Pierre, Ray Strode, Dan Williams
Translations:
Kjartan Maraas [nb], Reinout van Schouwen [nl], Rafael Ferreira [pt_BR],
Mattias Põldaru [et], Emin Tufan Çetin [tr], Jiri Grönroos [fi],
Khaled Hosny [ar], Fran Diéguez [gl], Victor Ibragimov [tg],
Daniel Mustieles [es]
3.11.2
======
* Cache search result display actors [Jasper; #704912]
* Use username in userWidget if real name doesn't fit [Jasper; #706851]
* Support shell_global_reexec_self() on OpenBSD [Antoine; #709571]
* Support disabling browser plugin [Colin; #711218]
* Restore support for 'disable-restart-buttons' [Florian; #711244]
* Validate parameters of exposed DBus methods [Florian; #699752]
* Connect applications to systemd journal if available [Colin; #711626]
* Misc bug fixes and cleanups [Florian, Jasper; #711205, #698486, #711416,
#644306, #711555, #709806, #711631, #711732]
Contributors:
Cosimo Cecchi, Antoine Jacoutot, Florian Müllner, Jasper St. Pierre,
Rico Tzschichholz, Colin Walters
Translations:
Yuri Myasoedov [ru], Kjartan Maraas [nb], Efstathios Iosifidis [el],
Benjamin Steinwender [de], eternalhui [zh_CN], Shantha kumar [ta]
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]
* Fix changing slider values via keyboard [Alejandro; #706386]
* Fix accessibility of sliders [Alejandro; #706391]
* Tweak system actions style [Jakub; #706638]
* Add support for auth without username / fix Not Listed? [Ray; #706607]
* Dash: Don't show tooltips for apps with open popups [Giovanni; #705611]
* Implement new end-session/power-off dialog design [Jasper, Matthias; #706612]
* Implement building separate binaries for x11 and wayland [Giovanni; #705497]
* authPrompt: Fix controls moving when showing messages [Ray; #706670]
* Tweak padding between system status icons [Allan; #706796]
* Add a generic accessible usable by JS code [Alejandro; #648623]
* Improve keynav and accessibility of the calendar [Alejandro; #706903]
* Update to new NetworkManager APIs [Jasper; #706098]
* Hide system actions section in the lock screen [Jasper; #706852]
* Don't show other logged in users at log out [Giovanni; #707124]
* Remove "Session" subtitle heading in login dialog [Jasper; #707072]
* dash: Reload favorites when installed apps change [Giovanni; #706878]
* Don't open overview after closing last window on workspace [Florian; #662581]
* Add FocusApp DBus method [Giovanni; #654086]
* Add ShowApplications DBus method [Giovanni; #698743]
* Implement new app picker design [Carlos, Florian; #706081]
* Improve frequent apps being empty by default [Carlos, Florian; #694710]
* Extend clickable area of page indicators [Giovanni; #707314]
* Misc bug fixes [Ray, Giovanni, Jasper, Emmanuele; #706542, #706654, #706005,
#706681, #706841, #706843, #707064, #706262, #707197, #707269]
Contributors:
Emmanuele Bassi, Giovanni Campagna, Matthias Clasen, Allan Day, Adel Gadllah,
Florian Müllner, Alejandro Piñeiro, Carlos Soriano, Jasper St. Pierre,
Jakub Steiner, Ray Strode, Seán de Búrca
Translations:
Piotr Drąg [pl], Kjartan Maraas [nb], Victor Ibragimov [tg],
Enrico Nicoletto [pt_BR], Benjamin Steinwender [de],
Baurzhan Muftakhidinov [kk], Aurimas Černius [lt], Seán de Búrca [ga],
Fran Diéguez [gl], Daniel Mustieles [es], Dušan Kazik [sk],
Matej Urbančič [sl], Andika Triwidada [id], Jordi Mas [ca],
Ihar Hrachyshka [be]
3.9.90
======
* workspaceThumbnails: Exclude transient windows when shifting workspaces
[Bradley; #705174]
* Never show a horizontal scrollbar on lock screen [Jasper; #704327]
* authPrompt: Fix disable-user-list / Not Listed? [Ray; #705370]
* Animate the lock screen notification transitions [Giovanni; #687660]
* Wake up the screen when new notifications appear [Giovanni; #703084]
* Use StartupWMClass for application matching [Giovanni; #673657, #705801]
* dateMenu: Add style class for the clock label [Jonh; #705634]
* keyboard: Translate IBus IME name if possible [Daiki; #695673]
* power: Display single digit minutes correctly [Sebastian; #705803]
* Implement new aggregate status menu [Jasper; #705845]
* Improve triangle animation when expanding sub-menus [Tarun; #703109]
* Fix alignment of search provider icons [Tarun; #695760]
* Slide dash and workspace switcher on overview transitions [Tarun; #694262]
* Respect always-show-universal-access-status setting [Tanner; #705733]
* Handle .desktop files with capital letters [Giovanni; #706252]
* authPrompt: Add smartcard support [Ray; #683437]
* Fix call notifications in busy mode [Emilio; #666221]
* Improve triangle animation when expanding sub-menus [Tarun; #703109]
* Move message tray menu to a tray button [Jasper; #699272]
* Wi-fi dialog improvements [Jasper, Allan; #705916, #706136]
* Work towards running as wayland compositor [Giovanni]
- Switch to Mutter abstraction layer for cursor tracking [#705911]
- Add confirmation dialog for display changes [#706208]
* Use a different background in screen shield [Giovanni; #688210]
* Add fade animation before blanking the screen [Giovanni; #699112]
* Misc. bugfixes and cleanups [Jasper, Giovanni, Adel, Colin, Ray, Florian,
Magdalen; #704448, #702536, #686855, #695581, #700901, #701761, #701495,
#701848, #697833, #701731, #705664, #705840, #705898, #706089, #706153,
#704646, #706262, #706324, #703810, #703811, #704015, #706232, #705917,
#706536]
Contributors:
Magdalen Berns, Giovanni Campagna, Allan Day, Tanner Doshier, Adel Gadllah,
Sebastian Keller, Tarun Kumar Joshi, Florian Müllner, Bradley Pankow,
Emilio Pozuelo Monfort, Jasper St. Pierre, Ray Strode, Rico Tzschichholz,
Daiki Ueno, Colin Walters, Jonh Wendell
Translations:
Kjartan Maraas [nb], Aurimas Černius [lt], Yaron Shahrabani [he],
Fran Diéguez [gl], Gabor Kelemen [hu],
Juan Diego Martins da Costa Cruz [pt_BR], Inaki Larranaga Murgoitio [eu],
Yuri Myasoedov [ru], Daniel Mustieles [es], Seán de Búrca [ga],
Khaled Hosny [ar], Victor Ibragimov [tg], Friedel Wolff [af],
Marek Černocký [cs], Matej Urbančič [sl], A S Alam [pa],
Rafael Ferreira [pt_BR], Andika Triwidada [id], Dušan Kazik [sk]
3.9.5
=====
* Fix width changes of the calendar popup [Florian; #704200]
* Work towards aggregate status menu [Jasper; #702539, #704336, #704368,
#704670]
* Update design of lock screen notifications [Allan; #702305]
* Don't show empty backgroundMenu [Michael; #703868]
* Add option to limit app switcher to current workspace [Adel; #703538]
* Consolidate design of login screen and unlock dialog [Ray; #702308, #704795]
* Respect hasWorkspace property of session mode [Jasper; #698593]
* Fix fade of app menu icon in RTL locales [Jasper; #704583]
* Destroy notifications when the close button is clicked [Adel; #687016]
* Fix clicks on legacy tray icons in the message tray [Florian; #704095]
* authPrompt: Fade out message if users start to type [Ray; #704817]
* Export timestamps of global shortcuts on DBus [Bastien; #704859]
* Fix duplicate search provider results [Jasper; #700283]
* Misc bug fixes and cleanups [Lionel, Florian, Emilio, Ray, Jasper; #703859,
#703540, #704077, #703997, #704318, #704347, #704265, #704411, #704430,
#704347, #704453, #704471, #704542, #704707, #703905, #705037]
Contributors:
Allan Day, Adel Gadllah, Lionel Landwerlin, Florian Müllner, Bastien Nocera,
Emilio Pozuelo Monfort, Jasper St. Pierre, Ray Strode, Colin Walters,
Michael Wood
Translations:
eternalhui [zh_CN], Victor Ibragimov [tg], Dušan Kazik [sk],
Jiro Matsuzawa [ja], Kjartan Maraas [nb], Milo Casagrande [it],
Marek Černocký [cs], Daniel Mustieles [es], Benjamin Steinwender [de]
3.9.4
=====
* Fix chat entries not being focused when expanded [Jasper; #698778]
* Fix alignment of "Not Listed?" label [Mathieu; #702307]
* Fix alignment of time stamps in chat notifications [Carlos; #687809]
* Round the ends of slider trough [Jasper; #702825]
* Add support for "box-shadow: none" [Cosimo; #702782]
* Keep chrome below popup windows [Florian; #702338]
* Move the session list to a popup menu [Ray; #702818]
* Fix autorun notifications for "non-native" volumes [Matthias; #703418]
* dnd: Speed up by not picking on each motion event [Jasper; #703443]
* Fix management of asynchronous background loading [Lionel; #703001]
* Rework focus handling [Jasper; #700735]
* Optimize box-shadow rendering [Lionel; #689858]
* Remove support for fixed positioning in BoxLayouts [Florian; #703808]
* Misc bug fixes and cleanups [Adel, Jasper, Florian, Ray, Lionel, Emilio;
#702849, #610279, #703132, #703105, #703160, #703126, #703304, #703403,
#698593, #703442, #703565, #700901, #703874, #703807, #703893, #703909]
Contributors:
Mathieu Bridon, Giovanni Campagna, Cosimo Cecchi, Matthias Clasen,
Fran Diéguez, Adel Gadllah, Lionel Landwerlin, Florian Müllner,
Emilio Pozuelo Monfort, Carlos Soriano, Jasper St. Pierre, Ray Strode
Translations:
Baurzhan Muftakhidinov [kk], Marek Černocký [cs], Daniel Mustieles [es],
Fran Diéguez [gl], Kjartan Maraas [nb], Andika Triwidada [id],
Benjamin Steinwender [de], Nguyễn Thái Ngọc Duy [vi], Trần Ngọc Quân [vi]
3.9.3
=====
* Don't push window thumbs when workspace switcher is hidden [Jasper; #701167]
* Tweak timeout for activating windows during XDND [Adel; #700150]
* Fix ellipsization in control buttons in app picker [Carlos; #696307]
* Fix DND to empty dash [Florian; #684618]
* Fix OSD window appearing below system modal dialogs [Rui; #701269]
* Clear clipboard on screen lock to prevent information leak [Florian; #698922]
* Allow session mode specific overrides schema [Florian; #701717]
* window-switcher: Only show windows from current workspace by default
[Florian; #701214]
* logout dialog: Show the correct text right away [Matthias; #702056]
* bluetooth: Port to bluez 5 [Emilio; #700891]
* dateMenu: Allow events to span multiple lines [Giovanni; #701231]
* gdm: Clear message queue when no more messages are pending [Jonh; #702458]
* Misc bug fixes and cleanups [Jasper, Florian, Adel, Giovanni; #693836,
#700972, #701386, #700877, #701755, #698918, #701224, #702125, #701954,
#701849, #702121]
Contributors:
Giovanni Campagna, Matthias Clasen, Fran Diéguez, Adel Gadllah, Rui Matos,
Florian Müllner, Emilio Pozuelo Monfort, Carlos Soriano, Jasper St. Pierre,
Jonh Wendell
Translations:
Marek Černocký [cs], Victor Ibragimov [tg], Fran Diéguez [gl],
Benjamin Steinwender [de], Cheng-Chia Tseng [zh_HK, zh_TW],
eternalhui [zh_CN], Ivaylo Valkov [bg], Kjartan Maraas [nb],
Daniel Mustieles [es]
3.9.2
=====
* Use a symbolic icon for DESKTOP windows [Matthias; #697914]
* Move paint state cache into StWidget [Jasper; #697274]
* gdm: Fix regression where domain login hint not shown [Stef; #698200]
* Make calendar keyboard navigable [Tanner; #667434]
* Hide "Open Calendar" item when no calendar app is installed [Lionel; #697725]
* Update how branding appears on login screen [Florian; #694912, #699877]
* Allow OSD popups to grow if necessary [Marta; #696523]
* Fix offset of shadow offscreen rendering [Lionel; #698301]
* Fix insensitive button preventing empty keyring password [Stef; #696304]
* Allow cancelling keyring dialog between prompts [Stef; #682830]
* modalDialog: Show spinner while working [Stef; #684438]
* overview: Only show close buttons for windows that may close [Jasper; #699269]
* Add input purpose and hints to StEntry and StIMText [Daiki; #691392]
* Set input-purpose property for password entries [Rui; #700043]
* Provide a DBus API for screencasting [Florian; #696247]
* overview: Disable hotcorner during DND [Jasper; #698484]
* polkitAgent: Allow retrying after mistyped passwords [Stef; #684431]
* Add a way to get backtraces from criticals and warnings [Giovanni; #700262]
* Allow switch-to-workspace-n keybindings in overview [Florian; #649977]
* Update man page [Matthias; #700339]
* Add FocusSearch DBus method [Florian; #700536]
* Hide frequent view when app monitoring is disabled [Florian; #699714]
* Show switcher popup for switch-to-workspace-n keybindings [Elad; #659288]
* gdm: Update the session chooser style [Allan; #695742]
* Fix some app folders getting truncated at the top [Florian; #694371]
* Don't block the message tray while a notification is showing [Jasper; #700639]
* popupMenu: Allow for an optional border for slider handle [Florian; #697917]
* Re-lock screen when restarted after a crash [Colin; #691987]
* Synchronize input source switching with key events [Rui; #697007]
* Switch input source on modifiers-only accelerator [Rui; #697008]
* Allow input source switching in message tray [Rui; #697009]
* Misc bug fixes and cleanups [Alban, Jasper, Giovanni, Florian, Rui, Tomeu,
Stef, Gustavo; #698863, #699799, #699800, #676285, #699975, #700097, #698812,
#698486, #700194, #695314, #700257, #699678, #700356, #700322, #700394,
#700409, #700595, #700625, #691746, #700620, #700807, #659288, #700784,
#700842, #700847, #700488, #700735, #696159, #700900, #700853, #700923,
#700944, #697661, #700854, #700190, #699189, #701097]
Contributors:
Elad Alfassa, Alban Browaeys, Giovanni Campagna, Matthias Clasen, Allan Day,
Tanner Doshier, Lionel Landwerlin, Rui Matos, Simon McVittie,
Marta Milakovic, Florian Müllner, Gustavo Padovan, Jasper St. Pierre,
Daiki Ueno, Tomeu Vizoso, Stef Walter, Colin Walters
Translations:
Matej Urbančič [sl], Kjartan Maraas [nb], Victor Ibragimov [tg],
Dušan Kazik [sk], Gil Forcada [ca], Daniel Mustieles [es]
3.9.1
=====
* Add additional toggle-overview keybinding [Matthias; #698251]
* Disable <super> shortcut when sticky keys are enabled [Matthias; #685974]
* Disable tray context menu while a notification displays [Jasper; #695800]
* Watch GApplication busy state [Cosimo; #697207]
* Disable style transitions if animations are disabled [Jasper; #698391]
* Filter out hidden applications from "Frequent" view [Giovanni; #696949]
* Fix window previews swapping place randomly [Jasper; #694469, #698776]
* Add support for serialized GIcons in remote search providers [Cosimo; #698761]
* Fix hotcorner regression in RTL locales [Jasper; #698884]
* Allow some keybindings to work while a top bar menu is open [Florian; #698938]
* Make open-app-menu keybinding a toggle action [Florian; #686756]
* Only recognize common URL schemes in notification messages [Monica; #661225]
* Misc fixes and cleanups [Tim, Jasper, Florian, Giovanni, Owen; #698531,
#698622, #698427, #698483, #698513, #697203, #698959, #698918, #699029,
#699075, #696720, #649748]
Contributors:
Giovanni Campagna, Cosimo Cecchi, Monica Chelliah, Matthias Clasen, Tim Lunn,
Florian Müllner, Jasper St. Pierre, Michael Wood, Owen W. Taylor
Translations:
Fran Diéguez [gl], Muhammet Kara [tr], Daniel Mustieles [es],
Gil Forcada [ia], Anish A [ml], Dimitris Spingos [el], Marek Černocký [cs],
Žygimantas Beručka [lt]
3.8.1
=====
* Clip window group during startup animation [Jasper; #696323]
* Check for logind rather than systemd [Martin; #696252]
* Don't special-case last remote search provider position [Giovanni; #694974]
* Fix memory leaks [Ray, Jasper; ##697119, #697295, #697300, #697395]
* AppSwitcherPopup: Activate only the selected window if any [Rui; #697480]
* Enable screen recorder keybinding in all modes [Florian; #696200]
* Remove box-shadow from screen shield for performance reasons [Adel; #697274]
* Add support for -st-natural-width/height CSS properties [Giovanni; #664411]
* Remove excessive padding from notification buttons [Allan; #664411]
* Fix thumbnail dragging in overview [Jasper; #697504]
* theme-node: Add get_url()/lookup_url() methods [Florian; #693688]
* Misc bug fixes and cleanups [Jasper, Rui, Colin, David, Ray, Matthias:
#695859, #696259, #696585, #696436, #697432, #697435, #697560, #697722,
#697709]
Contributors:
Giovanni Campagna, Matthias Clasen, Allan Day, Adel Gadllah, David Gumberg,
Rui Matos, Florian Müllner, Martin Pitt, Jasper St. Pierre, Ray Strode,
Colin Walters
Translations:
Daniel Martinez [an], Bruce Cowan [en_GB], Khaled Hosny [ar],
Ihar Hrachyshka [be], Aron Xu [zh_CN], Wojciech Szczęsny [pl],
Inaki Larranaga Murgoitio [eu], Kjartan Maraas [nb],
Милош Поповић [sr, sr@latin], Trần Ngọc Quân [vi]
3.8.0.1 3.8.0.1
======= =======
* Background bug fixes [Ray; #696712] * Background bug fixes [Ray; #696712]

2
README
View File

@ -8,7 +8,7 @@ For more information about GNOME Shell, including instructions on how
to build GNOME Shell from source and how to get involved with the project, to build GNOME Shell from source and how to get involved with the project,
see: see:
https://wiki.gnome.org/Projects/GnomeShell http://live.gnome.org/GnomeShell
Bugs should be reported at http://bugzilla.gnome.org against the 'gnome-shell' Bugs should be reported at http://bugzilla.gnome.org against the 'gnome-shell'
product. product.

View File

@ -1,4 +1,4 @@
#!/bin/sh #!/bin/bash
# Run this to generate all the initial makefiles, etc. # Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0` srcdir=`dirname $0`
@ -14,7 +14,7 @@ PKG_NAME="gnome-shell"
} }
# Fetch submodules if needed # Fetch submodules if needed
if test ! -f src/gvc/Makefile.am || test ! -f data/theme/gnome-shell-sass/COPYING; if test ! -f src/gvc/Makefile.am;
then then
echo "+ Setting up submodules" echo "+ Setting up submodules"
git submodule init git submodule init

View File

@ -17,4 +17,5 @@ libgnome_shell_browser_plugin_la_SOURCES = \
libgnome_shell_browser_plugin_la_CFLAGS = \ libgnome_shell_browser_plugin_la_CFLAGS = \
$(BROWSER_PLUGIN_CFLAGS) \ $(BROWSER_PLUGIN_CFLAGS) \
-DG_DISABLE_DEPRECATED \
-DG_LOG_DOMAIN=\"GnomeShellBrowserPlugin\" -DG_LOG_DOMAIN=\"GnomeShellBrowserPlugin\"

View File

@ -13,7 +13,9 @@
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* *
* Authors: * Authors:
* Jasper St. Pierre <jstpierre@mecheye.net> * Jasper St. Pierre <jstpierre@mecheye.net>
@ -41,8 +43,6 @@
#define PLUGIN_API_VERSION 5 #define PLUGIN_API_VERSION 5
#define EXTENSION_DISABLE_VERSION_CHECK_KEY "disable-extension-version-validation"
typedef struct { typedef struct {
GDBusProxy *proxy; GDBusProxy *proxy;
} PluginData; } PluginData;
@ -833,16 +833,6 @@ plugin_get_shell_version (PluginObject *obj,
return ret; return ret;
} }
static gboolean
plugin_get_version_validation_enabled (PluginObject *obj,
NPVariant *result)
{
gboolean is_enabled = !g_settings_get_boolean (obj->settings, EXTENSION_DISABLE_VERSION_CHECK_KEY);
BOOLEAN_TO_NPVARIANT(is_enabled, *result);
return TRUE;
}
#define METHODS \ #define METHODS \
METHOD (list_extensions) \ METHOD (list_extensions) \
METHOD (get_info) \ METHOD (get_info) \
@ -862,8 +852,6 @@ static NPIdentifier api_version_id;
static NPIdentifier shell_version_id; static NPIdentifier shell_version_id;
static NPIdentifier onextension_changed_id; static NPIdentifier onextension_changed_id;
static NPIdentifier onrestart_id; static NPIdentifier onrestart_id;
static NPIdentifier version_validation_enabled_id;
static bool static bool
plugin_object_has_method (NPObject *npobj, plugin_object_has_method (NPObject *npobj,
@ -906,8 +894,7 @@ plugin_object_has_property (NPObject *npobj,
return (name == onextension_changed_id || return (name == onextension_changed_id ||
name == onrestart_id || name == onrestart_id ||
name == api_version_id || name == api_version_id ||
name == shell_version_id || name == shell_version_id);
name == version_validation_enabled_id);
} }
static bool static bool
@ -925,8 +912,6 @@ plugin_object_get_property (NPObject *npobj,
return plugin_get_api_version (obj, result); return plugin_get_api_version (obj, result);
else if (name == shell_version_id) else if (name == shell_version_id)
return plugin_get_shell_version (obj, result); return plugin_get_shell_version (obj, result);
else if (name == version_validation_enabled_id)
return plugin_get_version_validation_enabled (obj, result);
else if (name == onextension_changed_id) else if (name == onextension_changed_id)
{ {
if (obj->listener) if (obj->listener)
@ -1005,7 +990,6 @@ init_methods_and_properties (void)
/* this is the JS public API; it is manipulated through NPIdentifiers for speed */ /* this is the JS public API; it is manipulated through NPIdentifiers for speed */
api_version_id = funcs.getstringidentifier ("apiVersion"); api_version_id = funcs.getstringidentifier ("apiVersion");
shell_version_id = funcs.getstringidentifier ("shellVersion"); shell_version_id = funcs.getstringidentifier ("shellVersion");
version_validation_enabled_id = funcs.getstringidentifier ("versionValidationEnabled");
get_info_id = funcs.getstringidentifier ("getExtensionInfo"); get_info_id = funcs.getstringidentifier ("getExtensionInfo");
list_extensions_id = funcs.getstringidentifier ("listExtensions"); list_extensions_id = funcs.getstringidentifier ("listExtensions");

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.63) AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.15.4],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell]) AC_INIT([gnome-shell],[3.8.0.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c]) AC_CONFIG_SRCDIR([src/shell-global.c])
@ -16,7 +16,6 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
# Checks for programs. # Checks for programs.
AC_PROG_CC AC_PROG_CC
AC_PROG_CXX
# Initialize libtool # Initialize libtool
LT_PREREQ([2.2.6]) LT_PREREQ([2.2.6])
@ -25,6 +24,9 @@ LT_INIT([disable-static])
# i18n # i18n
IT_PROG_INTLTOOL([0.40]) IT_PROG_INTLTOOL([0.40])
AM_GNU_GETTEXT([external])
AM_GNU_GETTEXT_VERSION([0.17])
GETTEXT_PACKAGE=gnome-shell GETTEXT_PACKAGE=gnome-shell
AC_SUBST(GETTEXT_PACKAGE) AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
@ -37,7 +39,7 @@ AC_PATH_PROG([XSLTPROC], [xsltproc])
GLIB_GSETTINGS GLIB_GSETTINGS
# Get a value to substitute into gnome-shell.in # Get a value to substitute into gnome-shell.in
AM_PATH_PYTHON([3]) AM_PATH_PYTHON([2.5])
AC_SUBST(PYTHON) AC_SUBST(PYTHON)
# We need at least this, since gst_plugin_register_static() was added # We need at least this, since gst_plugin_register_static() was added
@ -51,90 +53,74 @@ if $PKG_CONFIG --exists gstreamer-1.0 '>=' $GSTREAMER_MIN_VERSION ; then
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
build_recorder=true build_recorder=true
recorder_modules="gstreamer-1.0 gstreamer-base-1.0 x11 gtk+-3.0" recorder_modules="gstreamer-1.0 gstreamer-base-1.0 x11 gtk+-3.0"
PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0) PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0 xfixes)
else else
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
fi fi
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder) AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
AC_ARG_ENABLE([systemd], CLUTTER_MIN_VERSION=1.13.4
AS_HELP_STRING([--enable-systemd], [Use systemd]),
[enable_systemd=$enableval],
[enable_systemd=auto])
AS_IF([test x$enable_systemd != xno], [
AC_MSG_CHECKING([for libsystemd-journal])
PKG_CHECK_EXISTS([libsystemd-journal],
[have_systemd=yes
AC_DEFINE([HAVE_SYSTEMD], [1], [Define if we have systemd])],
[have_systemd=no])
AC_MSG_RESULT($have_systemd)
])
AC_MSG_RESULT($enable_systemd)
CLUTTER_MIN_VERSION=1.15.90
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1 GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.39.0 GJS_MIN_VERSION=1.35.4
MUTTER_MIN_VERSION=3.15.4 MUTTER_MIN_VERSION=3.8.0
GTK_MIN_VERSION=3.15.0 GTK_MIN_VERSION=3.7.9
GIO_MIN_VERSION=2.37.0 GIO_MIN_VERSION=2.35.0
LIBECAL_MIN_VERSION=3.5.3 LIBECAL_MIN_VERSION=3.5.3
LIBEDATASERVER_MIN_VERSION=3.13.90 LIBEDATASERVER_MIN_VERSION=3.5.3
TELEPATHY_GLIB_MIN_VERSION=0.17.5 TELEPATHY_GLIB_MIN_VERSION=0.17.5
POLKIT_MIN_VERSION=0.100 POLKIT_MIN_VERSION=0.100
STARTUP_NOTIFICATION_MIN_VERSION=0.11 STARTUP_NOTIFICATION_MIN_VERSION=0.11
GCR_MIN_VERSION=3.7.5 GCR_MIN_VERSION=3.3.90
GNOME_DESKTOP_REQUIRED_VERSION=3.7.90 GNOME_DESKTOP_REQUIRED_VERSION=3.7.90
NETWORKMANAGER_MIN_VERSION=0.9.8 GNOME_MENUS_REQUIRED_VERSION=3.5.3
NETWORKMANAGER_MIN_VERSION=0.9.6
PULSE_MIN_VERS=2.0 PULSE_MIN_VERS=2.0
# Collect more than 20 libraries for a prize! # Collect more than 20 libraries for a prize!
SHARED_PCS="gio-unix-2.0 >= $GIO_MIN_VERSION PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
libxml-2.0 libxml-2.0
gtk+-3.0 >= $GTK_MIN_VERSION gtk+-3.0 >= $GTK_MIN_VERSION
atk-bridge-2.0 atk-bridge-2.0
gjs-internals-1.0 >= $GJS_MIN_VERSION libmutter >= $MUTTER_MIN_VERSION
$recorder_modules gjs-internals-1.0 >= $GJS_MIN_VERSION
gdk-x11-3.0 libsoup-2.4 libgnome-menu-3.0 >= $GNOME_MENUS_REQUIRED_VERSION
clutter-x11-1.0 >= $CLUTTER_MIN_VERSION $recorder_modules
clutter-glx-1.0 >= $CLUTTER_MIN_VERSION gdk-x11-3.0 libsoup-2.4
libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_MIN_VERSION clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
libcanberra libcanberra-gtk3 libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_MIN_VERSION
telepathy-glib >= $TELEPATHY_GLIB_MIN_VERSION gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION
polkit-agent-1 >= $POLKIT_MIN_VERSION libcanberra libcanberra-gtk3
gcr-base-3 >= $GCR_MIN_VERSION" telepathy-glib >= $TELEPATHY_GLIB_MIN_VERSION
if test x$have_systemd = xyes; then polkit-agent-1 >= $POLKIT_MIN_VERSION xfixes
SHARED_PCS="${SHARED_PCS} libsystemd-journal" libnm-glib libnm-util >= $NETWORKMANAGER_MIN_VERSION
fi libnm-gtk >= $NETWORKMANAGER_MIN_VERSION
libsecret-unstable gcr-3 >= $GCR_MIN_VERSION)
PKG_CHECK_MODULES(GNOME_SHELL, $SHARED_PCS)
PKG_CHECK_MODULES(MUTTER, libmutter >= $MUTTER_MIN_VERSION)
PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION) PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11) PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0) PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0) PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0)
PKG_CHECK_MODULES(BROWSER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION json-glib-1.0 >= 0.13.2)
PKG_CHECK_MODULES(TRAY, gtk+-3.0) PKG_CHECK_MODULES(TRAY, gtk+-3.0)
PKG_CHECK_MODULES(GVC, libpulse >= $PULSE_MIN_VERS libpulse-mainloop-glib gobject-2.0) PKG_CHECK_MODULES(GVC, libpulse >= $PULSE_MIN_VERS libpulse-mainloop-glib gobject-2.0)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.13.1) PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.4)
PKG_CHECK_MODULES(CARIBOU, caribou-1.0 >= 0.4.8) PKG_CHECK_MODULES(CARIBOU, caribou-1.0 >= 0.4.8)
AC_ARG_ENABLE(browser-plugin, AC_MSG_CHECKING([for bluetooth support])
[AS_HELP_STRING([--enable-browser-plugin], PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
[Enable browser plugin [default=yes]])],, [BLUETOOTH_DIR=`$PKG_CONFIG --variable=applet_libdir gnome-bluetooth-1.0`
enable_browser_plugin=yes) BLUETOOTH_LIBS=`$PKG_CONFIG --variable=applet_libs gnome-bluetooth-1.0`
AS_IF([test x$enable_browser_plugin = xyes], [ AC_SUBST([BLUETOOTH_LIBS],["$BLUETOOTH_LIBS"])
PKG_CHECK_MODULES(BROWSER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION json-glib-1.0 >= 0.13.2) AC_SUBST([BLUETOOTH_DIR],["$BLUETOOTH_DIR"])
]) AC_DEFINE_UNQUOTED([BLUETOOTH_DIR],["$BLUETOOTH_DIR"],[Path to installed GnomeBluetooth typelib and library])
AM_CONDITIONAL(BUILD_BROWSER_PLUGIN, test x$enable_browser_plugin = xyes) AC_DEFINE([HAVE_BLUETOOTH],[1],[Define if you have libgnome-bluetooth-applet])
AC_SUBST([HAVE_BLUETOOTH],[1])
PKG_CHECK_MODULES(BLUETOOTH, gnome-bluetooth-1.0 >= 3.9.0, AC_MSG_RESULT([yes])],
[AC_DEFINE([HAVE_BLUETOOTH],[1],[Define if you have libgnome-bluetooth-applet])
AC_SUBST([HAVE_BLUETOOTH],[1])],
[AC_DEFINE([HAVE_BLUETOOTH],[0]) [AC_DEFINE([HAVE_BLUETOOTH],[0])
AC_SUBST([HAVE_BLUETOOTH],[0])]) AC_SUBST([HAVE_BLUETOOTH],[0])
AC_MSG_RESULT([no])])
PKG_CHECK_MODULES(CALENDAR_SERVER, libecal-1.2 >= $LIBECAL_MIN_VERSION libedataserver-1.2 >= $LIBEDATASERVER_MIN_VERSION gio-2.0) PKG_CHECK_MODULES(CALENDAR_SERVER, libecal-1.2 >= $LIBECAL_MIN_VERSION libedataserver-1.2 >= $LIBEDATASERVER_MIN_VERSION gio-2.0)
AC_SUBST(CALENDAR_SERVER_CFLAGS) AC_SUBST(CALENDAR_SERVER_CFLAGS)
@ -146,17 +132,13 @@ AC_SUBST([GNOME_KEYBINDINGS_KEYSDIR])
GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION]) GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION])
MUTTER_GIR_DIR=`$PKG_CONFIG --variable=girdir libmutter` MUTTER_GIR_DIR=`$PKG_CONFIG --variable=girdir libmutter`
AC_SUBST(MUTTER_GIR_DIR)
MUTTER_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter` MUTTER_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter`
AC_SUBST(MUTTER_GIR_DIR)
AC_SUBST(MUTTER_TYPELIB_DIR) AC_SUBST(MUTTER_TYPELIB_DIR)
GJS_CONSOLE=`$PKG_CONFIG --variable=gjs_console gjs-1.0` GJS_CONSOLE=`$PKG_CONFIG --variable=gjs_console gjs-1.0`
AC_SUBST(GJS_CONSOLE) AC_SUBST(GJS_CONSOLE)
GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable glib_compile_resources gio-2.0`
AC_SUBST(GLIB_COMPILE_RESOURCES)
AC_CHECK_FUNCS(fdwalk) AC_CHECK_FUNCS(fdwalk)
AC_CHECK_FUNCS(mallinfo) AC_CHECK_FUNCS(mallinfo)
AC_CHECK_HEADERS([sys/resource.h]) AC_CHECK_HEADERS([sys/resource.h])
@ -172,38 +154,6 @@ if test "$langinfo_ok" = "yes"; then
[Define if _NL_TIME_FIRST_WEEKDAY is available]) [Define if _NL_TIME_FIRST_WEEKDAY is available])
fi fi
AC_ARG_ENABLE(networkmanager,
AS_HELP_STRING([--disable-networkmanager],
[disable NetworkManager support @<:@default=auto@:>@]),,
[enable_networkmanager=auto])
if test "x$enable_networkmanager" != "xno"; then
PKG_CHECK_MODULES(NETWORKMANAGER,
[libnm-glib
libnm-util >= $NETWORKMANAGER_MIN_VERSION
libnm-gtk >= $NETWORKMANAGER_MIN_VERSION
libsecret-unstable],
[have_networkmanager=yes],
[have_networkmanager=no])
GNOME_SHELL_CFLAGS="$GNOME_SHELL_CFLAGS $NETWORKMANAGER_CFLAGS"
GNOME_SHELL_LIBS="$GNOME_SHELL_LIBS $NETWORKMANAGER_LIBS"
else
have_networkmanager="no (disabled)"
fi
if test "x$have_networkmanager" = "xyes"; then
AC_DEFINE(HAVE_NETWORKMANAGER, [1], [Define if we have NetworkManager])
AC_SUBST([HAVE_NETWORKMANAGER], [1])
else
if test "x$enable_networkmanager" = "xyes"; then
AC_MSG_ERROR([Couldn't find NetworkManager.])
fi
AC_SUBST([HAVE_NETWORKMANAGER], [0])
fi
AM_CONDITIONAL(HAVE_NETWORKMANAGER, test "$have_networkmanager" = "yes")
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS # Sets GLIB_GENMARSHAL and GLIB_MKENUMS
AM_PATH_GLIB_2_0() AM_PATH_GLIB_2_0()
@ -222,26 +172,14 @@ fi
AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no) AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no)
GNOME_COMPILE_WARNINGS([error]) GNOME_COMPILE_WARNINGS([error])
case "$WARN_CFLAGS" in
*-Werror*)
WARN_CFLAGS="$WARN_CFLAGS -Wno-error=deprecated-declarations"
;;
esac
AM_CFLAGS="$AM_CFLAGS $WARN_CFLAGS" AC_ARG_ENABLE(jhbuild-wrapper-script,
AC_SUBST(AM_CFLAGS) AS_HELP_STRING([--enable-jhbuild-wrapper-script],[Make "gnome-shell" script work for jhbuild]),,enable_jhbuild_wrapper_script=no)
AM_CONDITIONAL(USE_JHBUILD_WRAPPER_SCRIPT, test "x$enable_jhbuild_wrapper_script" = xyes)
if test -z "${BROWSER_PLUGIN_DIR}"; then BROWSER_PLUGIN_DIR="${BROWSER_PLUGIN_DIR:-"\${libdir}/mozilla/plugins"}"
BROWSER_PLUGIN_DIR="\${libdir}/mozilla/plugins"
fi
AC_ARG_VAR([BROWSER_PLUGIN_DIR],[Where to install the plugin to]) AC_ARG_VAR([BROWSER_PLUGIN_DIR],[Where to install the plugin to])
AC_ARG_VAR([GDBUS_CODEGEN],[the gdbus-codegen programme])
AC_PATH_PROG([GDBUS_CODEGEN],[gdbus-codegen],[])
if test -z "$GDBUS_CODEGEN"; then
AC_MSG_ERROR([gdbus-codegen not found])
fi
AC_CONFIG_FILES([ AC_CONFIG_FILES([
Makefile Makefile
data/Makefile data/Makefile
@ -261,15 +199,3 @@ AC_CONFIG_FILES([
man/Makefile man/Makefile
]) ])
AC_OUTPUT AC_OUTPUT
echo "
Build configuration:
Prefix: ${prefix}
Source code location: ${srcdir}
Compiler: ${CC}
Compiler Warnings: $enable_compile_warnings
Support for NetworkManager: $have_networkmanager
Support for GStreamer recording: $build_recorder
"

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<KeyListEntries schema="org.gnome.shell.keybindings"
group="system"
_name="Screenshots"
wm_name="GNOME Shell"
package="gnome-shell">
<KeyListEntry name="toggle-recording"
_description="Record a screencast"/>
</KeyListEntries>

View File

@ -11,9 +11,6 @@
<KeyListEntry name="focus-active-notification" <KeyListEntry name="focus-active-notification"
_description="Focus the active notification"/> _description="Focus the active notification"/>
<KeyListEntry name="toggle-overview"
_description="Show the overview"/>
<KeyListEntry name="toggle-application-view" <KeyListEntry name="toggle-application-view"
_description="Show all applications"/> _description="Show all applications"/>

View File

@ -1,23 +1,8 @@
CLEANFILES = wandadir = $(pkgdatadir)
dist_wanda_DATA = wanda.png
desktopdir=$(datadir)/applications desktopdir=$(datadir)/applications
desktop_DATA = gnome-shell.desktop gnome-shell-wayland.desktop gnome-shell-extension-prefs.desktop desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
if HAVE_NETWORKMANAGER
desktop_DATA += org.gnome.Shell.PortalHelper.desktop
servicedir = $(datadir)/dbus-1/services
service_DATA = org.gnome.Shell.PortalHelper.service
CLEANFILES += \
org.gnome.Shell.PortalHelper.service \
org.gnome.Shell.PortalHelper.desktop
endif
%.service: %.service.in
$(AM_V_GEN) sed -e "s|@libexecdir[@]|$(libexecdir)|" \
$< > $@ || rm $@
# We substitute in bindir so it works as an autostart # We substitute in bindir so it works as an autostart
# file when built in a non-system prefix # file when built in a non-system prefix
@ -30,26 +15,50 @@ endif
introspectiondir = $(datadir)/dbus-1/interfaces introspectiondir = $(datadir)/dbus-1/interfaces
introspection_DATA = \ introspection_DATA = \
org.gnome.Shell.Screencast.xml \
org.gnome.Shell.Screenshot.xml \ org.gnome.Shell.Screenshot.xml \
org.gnome.ShellSearchProvider.xml \ org.gnome.ShellSearchProvider.xml \
org.gnome.ShellSearchProvider2.xml org.gnome.ShellSearchProvider2.xml
resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir)/theme --generate-dependencies $(srcdir)/gnome-shell-theme.gresource.xml) themedir = $(pkgdatadir)/theme
gnome-shell-theme.gresource: gnome-shell-theme.gresource.xml $(resource_files) dist_theme_DATA = \
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir)/theme $< theme/calendar-arrow-left.svg \
resourcedir = $(pkgdatadir) theme/calendar-arrow-right.svg \
resource_DATA = gnome-shell-theme.gresource theme/calendar-today.svg \
theme/checkbox-focused.svg \
backgrounddir = $(pkgdatadir) theme/checkbox-off-focused.svg \
background_DATA = perf-background.xml theme/checkbox-off.svg \
theme/checkbox.svg \
perf-background.xml: perf-background.xml.in theme/close-window.svg \
$(AM_V_GEN) sed -e "s|@datadir[@]|$(datadir)|" \ theme/close.svg \
$< > $@ || rm $@ theme/corner-ripple-ltr.png \
theme/corner-ripple-rtl.png \
theme/dash-placeholder.svg \
theme/filter-selected-ltr.svg \
theme/filter-selected-rtl.svg \
theme/gnome-shell.css \
theme/logged-in-indicator.svg \
theme/message-tray-background.png \
theme/more-results.svg \
theme/noise-texture.png \
theme/panel-button-border.svg \
theme/panel-button-highlight-narrow.svg \
theme/panel-button-highlight-wide.svg \
theme/process-working.svg \
theme/running-indicator.svg \
theme/source-button-border.svg \
theme/summary-counter.svg \
theme/toggle-off-us.svg \
theme/toggle-off-intl.svg \
theme/toggle-on-us.svg \
theme/toggle-on-intl.svg \
theme/ws-switch-arrow-up.png \
theme/ws-switch-arrow-down.png
keysdir = @GNOME_KEYBINDINGS_KEYSDIR@ keysdir = @GNOME_KEYBINDINGS_KEYSDIR@
keys_in_files = 50-gnome-shell-system.xml.in keys_in_files = \
50-gnome-shell-screenshot.xml.in \
50-gnome-shell-system.xml.in \
$(NULL)
keys_DATA = $(keys_in_files:.xml.in=.xml) keys_DATA = $(keys_in_files:.xml.in=.xml)
gsettings_SCHEMAS = org.gnome.shell.gschema.xml gsettings_SCHEMAS = org.gnome.shell.gschema.xml
@ -74,28 +83,19 @@ convert_DATA = gnome-shell-overrides.convert
EXTRA_DIST = \ EXTRA_DIST = \
gnome-shell.desktop.in.in \ gnome-shell.desktop.in.in \
gnome-shell-wayland.desktop.in.in \
gnome-shell-extension-prefs.desktop.in.in \ gnome-shell-extension-prefs.desktop.in.in \
$(introspection_DATA) \ $(introspection_DATA) \
$(menu_DATA) \ $(menu_DATA) \
$(convert_DATA) \ $(convert_DATA) \
$(keys_in_files) \ $(keys_in_files) \
perf-background.xml.in \ org.gnome.shell.gschema.xml.in.in
org.gnome.Shell.PortalHelper.desktop.in \
org.gnome.Shell.PortalHelper.service.in \
org.gnome.shell.gschema.xml.in.in \
gnome-shell-theme.gresource.xml \
$(resource_files)
CLEANFILES += \ CLEANFILES = \
gnome-shell.desktop.in \ gnome-shell.desktop.in \
gnome-shell-wayland.desktop.in \
gnome-shell-extension-prefs.in \ gnome-shell-extension-prefs.in \
$(desktop_DATA) \ $(desktop_DATA) \
$(keys_DATA) \ $(keys_DATA) \
$(gsettings_SCHEMAS) \ $(gsettings_SCHEMAS) \
perf-background.xml \
gschemas.compiled \ gschemas.compiled \
org.gnome.shell.gschema.valid \ org.gnome.shell.gschema.valid \
org.gnome.shell.gschema.xml.in \ org.gnome.shell.gschema.xml.in
gnome-shell-theme.gresource

View File

@ -1,4 +1,5 @@
[org.gnome.shell.overrides] [org.gnome.shell.overrides]
attach-modal-dialogs = /desktop/gnome/shell/windows/attach_modal_dialogs attach-modal-dialogs = /desktop/gnome/shell/windows/attach_modal_dialogs
button-layout = /desktop/gnome/shell/windows/button_layout
edge-tiling = /desktop/gnome/shell/windows/edge_tiling edge-tiling = /desktop/gnome/shell/windows/edge_tiling
workspaces-only-on-primary = /desktop/gnome/shell/windows/workspaces_only_on_primary workspaces-only-on-primary = /desktop/gnome/shell/windows/workspaces_only_on_primary

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/shell/theme">
<file>calendar-arrow-left.svg</file>
<file>calendar-arrow-right.svg</file>
<file>calendar-today.svg</file>
<file>checkbox-focused.svg</file>
<file>checkbox-off-focused.svg</file>
<file>checkbox-off.svg</file>
<file>checkbox.svg</file>
<file>close-window.svg</file>
<file>close.svg</file>
<file>corner-ripple-ltr.png</file>
<file>corner-ripple-rtl.png</file>
<file>dash-placeholder.svg</file>
<file>filter-selected-ltr.svg</file>
<file>filter-selected-rtl.svg</file>
<file>gnome-shell.css</file>
<file>gnome-shell-high-contrast.css</file>
<file>logged-in-indicator.svg</file>
<file>more-results.svg</file>
<file>noise-texture.png</file>
<file>page-indicator-active.svg</file>
<file>page-indicator-inactive.svg</file>
<file>page-indicator-checked.svg</file>
<file>page-indicator-hover.svg</file>
<file>process-working.svg</file>
<file>running-indicator.svg</file>
<file>source-button-border.svg</file>
<file>summary-counter.svg</file>
<file>toggle-off-us.svg</file>
<file>toggle-off-intl.svg</file>
<file>toggle-on-us.svg</file>
<file>toggle-on-intl.svg</file>
<file>ws-switch-arrow-up.png</file>
<file>ws-switch-arrow-down.png</file>
</gresource>
</gresources>

View File

@ -1,15 +0,0 @@
[Desktop Entry]
Type=Application
_Name=GNOME Shell (wayland compositor)
_Comment=Window management and application launching
Exec=@bindir@/gnome-shell --wayland --display-server
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

View File

@ -1,9 +0,0 @@
[Desktop Entry]
_Name=Network Login
Type=Application
Exec=gapplication launch org.gnome.Shell.PortalHelper
DBusActivatable=true
NoDisplay=true
Icon=network-workgroup
StartupNotify=true
OnlyShowIn=GNOME;

View File

@ -1,3 +0,0 @@
[D-BUS Service]
Name=org.gnome.Shell.PortalHelper
Exec=@libexecdir@/gnome-shell-portal-helper

View File

@ -1,95 +0,0 @@
<!DOCTYPE node PUBLIC
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
<node>
<!--
org.gnome.Shell.Screencast:
@short_description: Screencast interface
The interface used to record screen contents.
-->
<interface name="org.gnome.Shell.Screencast">
<!--
Screencast:
@file_template: the template for the filename to use
@options: a dictionary of optional parameters
@success: whether the screencast was started successfully
@filename_used: the file where the screencast is being saved
Records a screencast of the whole screen and saves it
(by default) as webm video under a filename derived from
@file_template. The template is either a relative or absolute
filename which may contain some escape sequences - %d and %t
will be replaced by the start date and time of the recording.
If a relative name is used, the screencast will be saved in the
$XDG_VIDEOS_DIR if it exists, or the home directory otherwise.
The actual filename of the saved video is returned in @filename_used.
The set of optional parameters in @options currently consists of:
'draw-cursor'(b): whether the cursor should be included in the
recording (true)
'framerate'(i): the number of frames per second that should be
recorded if possible (30)
'pipeline'(s): the GStreamer pipeline used to encode recordings
in gst-launch format; if not specified, the
recorder will produce vp8 (webm) video (unset)
-->
<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>
<!--
ScreencastArea:
@x: the X coordinate of the area to capture
@y: the Y coordinate of the area to capture
@width: the width of the area to capture
@height: the height of the area to capture
@file_template: the template for the filename to use
@options: a dictionary of optional parameters
@success: whether the screencast was started successfully
@filename_used: the file where the screencast is being saved
Records a screencast of the passed in area and saves it
(by default) as webm video under a filename derived from
@file_template. The template is either a relative or absolute
filename which may contain some escape sequences - %d and %t
will be replaced by the start date and time of the recording.
If a relative name is used, the screencast will be saved in the
$XDG_VIDEOS_DIR if it exists, or the home directory otherwise.
The actual filename of the saved video is returned in @filename_used.
The set of optional parameters in @options currently consists of:
'draw-cursor'(b): whether the cursor should be included in the
recording (true)
'framerate'(i): the number of frames per second that should be
recorded if possible (30)
'pipeline'(s): the GStreamer pipeline used to encode recordings
in gst-launch format; if not specified, the
recorder will produce vp8 (webm) video (unset)
-->
<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>
<!--
StopScreencast:
@success: whether stopping the recording was successful
Stop the recording started by either Screencast or ScreencastArea.
-->
<method name="StopScreencast">
<arg type="b" direction="out" name="success"/>
</method>
</interface>
</node>

View File

@ -46,7 +46,7 @@
<!-- <!--
GetResultMetas: GetResultMetas:
@identifiers: An array of result identifiers as returned by GetInitialResultSet() or GetSubsearchResultSet() @identifiers: An array of result identifiers as returned by GetInitialResultSet() or GetSubsearchResultSet()
@metas: A dictionary describing the given search result, containing a human-readable 'name' (string), along with the result identifier this meta is for, 'id' (string). Optionally, 'icon' (a serialized GIcon as obtained by g_icon_serialize) can be specified if the result can be better served with a thumbnail of the content (such as with images). 'gicon' (a serialized GIcon as obtained by g_icon_to_string) or 'icon-data' (raw image data as (iiibiiay) - width, height, rowstride, has-alpha, bits per sample, channels, data) are deprecated values that can also be used for that purpose. A 'description' field (string) may also be specified if more context would help the user find the desired result. @metas: A dictionary describing the given search result, containing a human-readable 'name' (string), along with the result identifier this meta is for, 'id' (string). Optionally, either 'gicon' (a serialized GIcon) or 'icon-data' (raw image data as (iiibiiay) - width, height, rowstride, has-alpha, bits per sample, channels, data) can be specified if the result can be better served with a thumbnail of the content (such as with images). A 'description' field (string) may also be specified if more context would help the user find the desired result.
Return an array of meta data used to display each given result Return an array of meta data used to display each given result
--> -->

View File

@ -13,36 +13,38 @@
</key> </key>
<key name="enabled-extensions" type="as"> <key name="enabled-extensions" type="as">
<default>[]</default> <default>[]</default>
<_summary>UUIDs of extensions to enable</_summary> <_summary>Uuids of extensions to enable</_summary>
<_description> <_description>
GNOME Shell extensions have a UUID property; this key lists extensions GNOME Shell extensions have a uuid property; this key lists extensions
which should be loaded. Any extension that wants to be loaded needs which should be loaded. Any extension that wants to be loaded needs
to be in this list. You can also manipulate this list with the to be in this list. You can also manipulate this list with the
EnableExtension and DisableExtension D-Bus methods on org.gnome.Shell. EnableExtension and DisableExtension DBus methods on org.gnome.Shell.
</_description> </_description>
</key> </key>
<key name="disable-extension-version-validation" type="b"> <key name="enable-app-monitoring" type="b">
<default>false</default> <default>true</default>
<_summary>Disables the validation of extension version compatibility</_summary> <_summary>Whether to collect stats about applications usage</_summary>
<_description> <_description>
GNOME Shell will only load extensions that claim to support the current The shell normally monitors active applications in order to present
running version. Enabling this option will disable this check and try to the most used ones (e.g. in launchers). While this data will be
load all extensions regardless of the versions they claim to support. kept private, you may want to disable this for privacy reasons.
Please note that doing so won't remove already saved data.
</_description> </_description>
</key> </key>
<key name="favorite-apps" type="as"> <key name="favorite-apps" type="as">
<default>[ 'epiphany.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ]</default> <default>[ 'epiphany.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'libreoffice-writer.desktop', 'nautilus.desktop', 'gnome-documents.desktop' ]</default>
<_summary>List of desktop file IDs for favorite applications</_summary> <_summary>List of desktop file IDs for favorite applications</_summary>
<_description> <_description>
The applications corresponding to these identifiers The applications corresponding to these identifiers
will be displayed in the favorites area. will be displayed in the favorites area.
</_description> </_description>
</key> </key>
<key name="app-picker-view" type="u"> <key name="app-folder-categories" type="as">
<default>0</default> <default>[ 'Utilities', 'Sundry' ]</default>
<_summary>App Picker View</_summary> <_summary>List of categories that should be displayed as folders</_summary>
<_description> <_description>
Index of the currently selected view in the application picker. Each category name in this list will be represented as folder in the
application view, rather than being displayed inline in the main view.
</_description> </_description>
</key> </key>
<key name="command-history" type="as"> <key name="command-history" type="as">
@ -53,12 +55,22 @@
<default>[]</default> <default>[]</default>
<_summary>History for the looking glass dialog</_summary> <_summary>History for the looking glass dialog</_summary>
</key> </key>
<key name="saved-im-presence" type="i">
<default>1</default>
<_summary>Internally used to store the last IM presence explicitly set by the user. The
value here is from the TpConnectionPresenceType enumeration.</_summary>
</key>
<key name="saved-session-presence" type="i">
<default>0</default>
<_summary>Internally used to store the last session presence status for the user. The
value here is from the GsmPresenceStatus enumeration.</_summary>
</key>
<key name="always-show-log-out" type="b"> <key name="always-show-log-out" type="b">
<default>false</default> <default>false</default>
<_summary>Always show the 'Log out' menu item in the user menu.</_summary> <_summary>Always show the 'Log out' menuitem in the user menu.</_summary>
<_description> <_description>
This key overrides the automatic hiding of the 'Log out' This key overrides the automatic hiding of the 'Log out'
menu item in single-user, single-session situations. menuitem in single-user, single-session situations.
</_description> </_description>
</key> </key>
<key name="remember-mount-password" type="b"> <key name="remember-mount-password" type="b">
@ -72,6 +84,7 @@
</_description> </_description>
</key> </key>
<child name="calendar" schema="org.gnome.shell.calendar"/> <child name="calendar" schema="org.gnome.shell.calendar"/>
<child name="recorder" schema="org.gnome.shell.recorder"/>
<child name="keybindings" schema="org.gnome.shell.keybindings"/> <child name="keybindings" schema="org.gnome.shell.keybindings"/>
<child name="keyboard" schema="org.gnome.shell.keyboard"/> <child name="keyboard" schema="org.gnome.shell.keyboard"/>
</schema> </schema>
@ -104,13 +117,6 @@
Overview. Overview.
</_description> </_description>
</key> </key>
<key name="toggle-overview" type="as">
<default>["&lt;Super&gt;s"]</default>
<_summary>Keybinding to open the overview</_summary>
<_description>
Keybinding to open the Activities Overview.
</_description>
</key>
<key name="toggle-message-tray" type="as"> <key name="toggle-message-tray" type="as">
<default>["&lt;Super&gt;m"]</default> <default>["&lt;Super&gt;m"]</default>
<_summary>Keybinding to toggle the visibility of the message tray</_summary> <_summary>Keybinding to toggle the visibility of the message tray</_summary>
@ -125,10 +131,12 @@
Keybinding to focus the active notification. Keybinding to focus the active notification.
</_description> </_description>
</key> </key>
<key name="pause-resume-tweens" type="as"> <key name="toggle-recording" type="as">
<default>[]</default> <default><![CDATA[['<Control><Shift><Alt>r']]]></default>
<_summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</_summary> <_summary>Keybinding to toggle the screen recorder</_summary>
<_description></_description> <_description>
Keybinding to start/stop the builtin screen recorder.
</_description>
</key> </key>
</schema> </schema>
@ -143,15 +151,40 @@
</key> </key>
</schema> </schema>
<schema id="org.gnome.shell.app-switcher" <schema id="org.gnome.shell.recorder" path="/org/gnome/shell/recorder/"
path="/org/gnome/shell/app-switcher/"
gettext-domain="@GETTEXT_PACKAGE@"> gettext-domain="@GETTEXT_PACKAGE@">
<key type="b" name="current-workspace-only"> <key name="framerate" type="i">
<default>false</default> <default>30</default>
<_summary>Limit switcher to current workspace.</_summary> <_summary>Framerate used for recording screencasts.</_summary>
<_description> <_description>
If true, only applications that have windows on the current workspace are shown in the switcher. The framerate of the resulting screencast recordered
Otherwise, all applications are included. by GNOME Shell's screencast recorder in frames-per-second.
</_description>
</key>
<key name="pipeline" type="s">
<default>''</default>
<_summary>The gstreamer pipeline used to encode the screencast</_summary>
<_description>
Sets the GStreamer pipeline used to encode recordings.
It follows the syntax used for gst-launch. The pipeline should have
an unconnected sink pad where the recorded video is recorded. It will
normally have a unconnected source pad; output from that pad
will be written into the output file. However the pipeline can also
take care of its own output - this might be used to send the output
to an icecast server via shout2send or similar. When unset or set
to an empty value, the default pipeline will be used. This is currently
'vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! queue ! webmmux'
and records to WEBM using the VP8 codec. %T is used as a placeholder
for a guess at the optimal thread count on the system.
</_description>
</key>
<key name="file-extension" type="s">
<default>'webm'</default>
<_summary>File extension used for storing the screencast</_summary>
<_description>
The filename for recorded screencasts will be a unique filename
based on the current date, and use this extension. It should be
changed when recording to a different container format.
</_description> </_description>
</key> </key>
</schema> </schema>
@ -174,12 +207,12 @@
</_description> </_description>
</key> </key>
<key type="b" name="current-workspace-only"> <key type="b" name="current-workspace-only">
<default>true</default> <default>false</default>
<_summary>Limit switcher to current workspace.</_summary> <summary>Limit switcher to current workspace.</summary>
<_description> <description>
If true, only windows from the current workspace are shown in the switcher. If true, only windows from the current workspace are shown in the switcher.
Otherwise, all windows are included. Otherwise, all windows are included.
</_description> </description>
</key> </key>
</schema> </schema>
@ -194,6 +227,15 @@
</_description> </_description>
</key> </key>
<key name="button-layout" type="s">
<default>":close"</default>
<_summary>Arrangement of buttons on the titlebar</_summary>
<_description>
This key overrides the key in org.gnome.desktop.wm.preferences when
running GNOME Shell.
</_description>
</key>
<key name="edge-tiling" type="b"> <key name="edge-tiling" type="b">
<default>true</default> <default>true</default>
<_summary>Enable edge tiling when dropping windows on screen edges</_summary> <_summary>Enable edge tiling when dropping windows on screen edges</_summary>
@ -220,10 +262,10 @@
<key name="focus-change-on-pointer-rest" type="b"> <key name="focus-change-on-pointer-rest" type="b">
<default>true</default> <default>true</default>
<_summary>Delay focus changes in mouse mode until the pointer stops moving</_summary> <summary>Delay focus changes in mouse mode until the pointer stops moving</summary>
<_description> <description>
This key overrides the key in org.gnome.mutter when running GNOME Shell. This key overrides the key in org.gnome.mutter when running GNOME Shell.
</_description> </description>
</key> </key>
</schema> </schema>
</schemalist> </schemalist>

View File

@ -1,31 +0,0 @@
<!-- With an animated background, performance will differ depending on whether
one layer or two layers are being blended together. This messes up our
benchmarks. We could just benchmark a single image, but since blended
images are present for much of the day with the GNOME default background,
we want to make sure that also performs well; for that reason we ship
an "animated" background that animates super-slowly to use during
performance tests; it will be in the blended state until 2030. -->
<background>
<starttime>
<year>1990</year>
<month>1</month>
<day>1</day>
<hour>0</hour>
<minute>00</minute>
<second>00</second>
</starttime>
<!-- One transition that takes 40 years -->
<transition type="overlay">
<duration>1261440000.0</duration>
<from>@datadir@/backgrounds/gnome/adwaita-morning.jpg</from>
<to>@datadir@/backgrounds/gnome/adwaita-day.jpg</to>
</transition>
<!-- A single slide doesn't work, so another slide for 1 minute after 40 years -->
<static>
<duration>60</duration>
<file>/usr/share/backgrounds/gnome/Sandstone.jpg</file>
</static>
</background>

View File

@ -1,3 +0,0 @@
To generate the css files, from the project directory:
sass --sourcemap=none --update .

View File

@ -14,7 +14,7 @@
height="22" height="22"
id="svg3199" id="svg3199"
version="1.1" version="1.1"
inkscape:version="0.48.5 r10040" inkscape:version="0.48.1 r9760"
sodipodi:docname="checkbox.svg"> sodipodi:docname="checkbox.svg">
<defs <defs
id="defs3201"> id="defs3201">
@ -132,54 +132,51 @@
xlink:href="#linearGradient10597-5" xlink:href="#linearGradient10597-5"
inkscape:collect="always" /> inkscape:collect="always" />
<linearGradient <linearGradient
inkscape:collect="always" y2="-388.72955"
xlink:href="#linearGradient5581-5-2-4-6-8-7-35-8" x2="-93.031357"
id="linearGradient11811" y1="-396.34738"
x1="-93.031357"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
gradientUnits="userSpaceOnUse" gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.0317573,0,0,1.0053174,-102.66338,-0.82153381)" id="linearGradient14219-6"
x1="63.568954" xlink:href="#linearGradient15404-9"
y1="127.16142" inkscape:collect="always" />
x2="63.568954"
y2="152.6618" />
<linearGradient <linearGradient
id="linearGradient5581-5-2-4-6-8-7-35-8"> id="linearGradient15404-9"
inkscape:collect="always">
<stop <stop
id="stop5583-0-92-8-0-7-6-5-1" id="stop15406-6"
offset="0" offset="0"
style="stop-color:#454c4c;stop-opacity:1;" /> style="stop-color:#515151;stop-opacity:1" />
<stop <stop
style="stop-color:#393f3f;stop-opacity:1;" id="stop15408-7"
offset="0.40000001"
id="stop5585-4-7-2-7-9-9-92-0" />
<stop
id="stop5587-6-7-2-0-3-1-21-5"
offset="1" offset="1"
style="stop-color:#2d3232;stop-opacity:1;" /> style="stop-color:#292929;stop-opacity:1" />
</linearGradient> </linearGradient>
</defs> </defs>
<sodipodi:namedview <sodipodi:namedview
id="base" id="base"
pagecolor="#a2a2a2" pagecolor="#000000"
bordercolor="#2d2d2d" bordercolor="#2d2d2d"
borderopacity="1" borderopacity="1"
inkscape:pageopacity="1" inkscape:pageopacity="1"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="22.627417" inkscape:zoom="1"
inkscape:cx="9.6447897" inkscape:cx="71.516955"
inkscape:cy="12.591409" inkscape:cy="5.8710559"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
inkscape:window-width="1412" inkscape:window-width="1412"
inkscape:window-height="1067" inkscape:window-height="1067"
inkscape:window-x="184" inkscape:window-x="2635"
inkscape:window-y="233" inkscape:window-y="226"
inkscape:window-maximized="0" inkscape:window-maximized="0"
borderlayer="true" borderlayer="true"
inkscape:showpageshadow="false" inkscape:showpageshadow="false"
inkscape:snap-nodes="false" inkscape:snap-nodes="false"
inkscape:snap-bbox="true" inkscape:snap-bbox="true"
showborder="true"> showborder="false">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid14843" id="grid14843"
@ -206,56 +203,87 @@
id="layer1" id="layer1"
transform="translate(-342.5,-521.36218)"> transform="translate(-342.5,-521.36218)">
<g <g
style="display:inline" transform="matrix(0.80230061,0,0,0.80230061,-87.624044,-453.10297)"
id="use5671" id="g14586-0"
transform="matrix(1.3594109,0,0,1.3564242,319.2059,481.99447)"> style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none">
<rect <g
transform="matrix(0.47304779,0,0,0.4807373,-6.3607039,-29.396216)" inkscape:export-ydpi="90"
rx="4.4136767" inkscape:export-xdpi="90"
y="125.3458" inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
x="50.440369" transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
height="29.154205" id="g15291-9-6"
width="29.559635" style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new">
id="rect11803" <g
style="color:#000000;fill:url(#linearGradient11811);fill-opacity:1;stroke:#3465a4;stroke-width:1.54426003000000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" transform="translate(877.50354,-102.83507)"
ry="4.4233952" /> id="g16853-4-9"
<path style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;enable-background:new">
inkscape:connector-curvature="0" <rect
id="path11809" transform="scale(1,-1)"
d="m 17.87105,33.844107 0,-0.773112 c 0,-1.031264 0.807171,-1.836142 1.811982,-1.836142 l 9.612456,0 c 1.004811,0 1.787822,0.804878 1.787822,1.836142 l 0,0.773112 c 0,-1.031264 -0.783011,-1.836142 -1.787822,-1.836142 l -9.612456,0 c -1.004811,0 -1.811982,0.804878 -1.811982,1.836142 z" style="color:#000000;fill:url(#linearGradient14219-6);fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:1.24833274;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" id="rect6506-6"
sodipodi:nodetypes="csssscssc" /> width="11.281681"
<path height="11.26221"
sodipodi:nodetypes="csssscssc" x="-409.59354"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" y="-284.40115"
d="m 17.87105,41.158551 0,0.773112 c 0,1.031264 0.807171,1.836142 1.811982,1.836142 l 9.612456,0 c 1.004811,0 1.787822,-0.804878 1.787822,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z" rx="1.0052766"
id="path11867" ry="1.0052764" />
inkscape:connector-curvature="0" /> </g>
<path </g>
inkscape:connector-curvature="0" <g
id="path11869" inkscape:export-ydpi="90"
d="m 17.87105,41.895784 0,0.773112 c 0,1.031264 0.644622,1.836142 1.649433,1.836142 l 10.067593,0 c 1.004811,0 1.495234,-0.804878 1.495234,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z" inkscape:export-xdpi="90"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#000000;fill-opacity:0.85253451;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
sodipodi:nodetypes="csssscssc" /> transform="translate(343.99999,987.99997)"
id="g5886-5"
style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new" />
</g>
<g
transform="matrix(0.84337,0,0,0.84337,-110.16632,-503.56182)"
id="g14586">
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
id="g15291-9"
style="display:inline;enable-background:new">
<g
transform="translate(877.50354,-102.83507)"
id="g16853-4"
style="enable-background:new" />
</g>
<g
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
transform="translate(343.99999,987.99997)"
id="g5886"
style="display:inline;enable-background:new">
<path
style="fill:none;stroke:url(#linearGradient5891-0-4);stroke-width:7.11431503;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
id="path5835"
inkscape:path-effect="#path-effect5837-4-6"
inkscape:original-d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
inkscape:connector-curvature="0"
inkscape:original-d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
inkscape:path-effect="#path-effect5837-4-6"
id="path5880"
d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
style="fill:none;stroke:#4787c8;stroke-width:3.55715752;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#7ea7d3;stroke-width:1.18571913px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 197.45937,240.47455 c -0.17828,-0.29362 -0.20087,-0.67548 -0.0603,-0.98892 0.14055,-0.31344 0.43739,-0.54812 0.77144,-0.62817 0.33405,-0.08 0.69314,-0.01 0.99635,0.15175 0.30321,0.16144 0.55146,0.40727 0.79165,0.65284 l 3.66429,3.74643 12.87946,-12.98973 c 0.20796,-0.20974 0.42306,-0.41969 0.68548,-0.55522 0.26242,-0.13553 0.57293,-0.19052 0.85827,-0.11426 0.14267,0.0381 0.27708,0.10787 0.38874,0.20452 0.11167,0.0966 0.20021,0.22004 0.25479,0.35726 0.0546,0.13722 0.075,0.28793 0.0585,0.43468 -0.0165,0.14674 -0.07,0.28919 -0.15422,0.41052"
id="path5882"
inkscape:path-effect="#path-effect5884-4-7"
inkscape:original-d="m 197.45937,240.47455 c 0.65604,-0.56057 2.02485,-1.34847 2.49911,-0.8125 l 3.66429,3.74643 12.87946,-12.98973 c 0.6875,-0.6875 2.09152,0.7375 2.09152,0.7375"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csccc" />
</g>
</g> </g>
<rect
style="color:#000000;fill:none;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect17347"
width="21.943846"
height="21.943846"
x="342.29913"
y="521.58435" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 359.97505,524.8252 -7.88606,7.71465 -2.57155,-2.57155 -2.91442,-0.0427 0,2.35727 4.02875,3.98587 c 0.80342,0.80309 2.111,0.80309 2.91442,0 l 8.18609,-8.22894 0,-0.38573 c 0,-1.24128 0.19944,-1.76801 -0.82915,-2.29836 z"
id="rect5147-9-1-5-7-6-5-8-7"
sodipodi:nodetypes="ccccccccscc" />
<path
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:sans-serif;-inkscape-font-specification:sans-serif"
d="m 361.65223,524.52745 -9.5602,9.36735 -2.56345,-2.56344 -2.92846,-0.0214 0.0153,2.32639 4.02203,4.02206 c 0.80341,0.80309 2.10565,0.80309 2.90906,0 l 10.95049,-11.05765 0.003,-2.1502 z"
id="path12830-4-17-0"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -14,10 +14,22 @@
height="22" height="22"
id="svg3199" id="svg3199"
version="1.1" version="1.1"
inkscape:version="0.48.5 r10040" inkscape:version="0.48.1 r9760"
sodipodi:docname="checkbox-off.svg"> sodipodi:docname="checkbox-off.svg">
<defs <defs
id="defs3201"> id="defs3201">
<linearGradient
id="linearGradient15404"
inkscape:collect="always">
<stop
id="stop15406"
offset="0"
style="stop-color:#515151;stop-opacity:1" />
<stop
id="stop15408"
offset="1"
style="stop-color:#292929;stop-opacity:1" />
</linearGradient>
<inkscape:perspective <inkscape:perspective
sodipodi:type="inkscape:persp3d" sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1" inkscape:vp_x="0 : 526.18109 : 1"
@ -44,6 +56,16 @@
effect="spiro" effect="spiro"
id="path-effect5884-4-7" id="path-effect5884-4-7"
is_visible="true" /> is_visible="true" />
<linearGradient
y2="-388.72955"
x2="-93.031357"
y1="-396.34738"
x1="-93.031357"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
gradientUnits="userSpaceOnUse"
id="linearGradient14219"
xlink:href="#linearGradient15404"
inkscape:collect="always" />
<linearGradient <linearGradient
inkscape:collect="always" inkscape:collect="always"
id="linearGradient10013-4-63-6"> id="linearGradient10013-4-63-6">
@ -88,55 +110,30 @@
id="linearGradient15376" id="linearGradient15376"
xlink:href="#linearGradient10597-5" xlink:href="#linearGradient10597-5"
inkscape:collect="always" /> inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5581-5-2-4-6-8-7-35-8"
id="linearGradient11811"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.0317573,0,0,1.0053174,-102.66338,-0.82153381)"
x1="63.568954"
y1="127.16142"
x2="63.568954"
y2="152.6618" />
<linearGradient
id="linearGradient5581-5-2-4-6-8-7-35-8">
<stop
id="stop5583-0-92-8-0-7-6-5-1"
offset="0"
style="stop-color:#454c4c;stop-opacity:1;" />
<stop
style="stop-color:#393f3f;stop-opacity:1;"
offset="0.40000001"
id="stop5585-4-7-2-7-9-9-92-0" />
<stop
id="stop5587-6-7-2-0-3-1-21-5"
offset="1"
style="stop-color:#2d3232;stop-opacity:1;" />
</linearGradient>
</defs> </defs>
<sodipodi:namedview <sodipodi:namedview
id="base" id="base"
pagecolor="#a2a2a2" pagecolor="#000000"
bordercolor="#2d2d2d" bordercolor="#2d2d2d"
borderopacity="1" borderopacity="1"
inkscape:pageopacity="1" inkscape:pageopacity="1"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="5.6568542" inkscape:zoom="1"
inkscape:cx="19.79113" inkscape:cx="6.1225392"
inkscape:cy="11.232334" inkscape:cy="3.6003241"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
inkscape:window-width="1412" inkscape:window-width="1412"
inkscape:window-height="1067" inkscape:window-height="1067"
inkscape:window-x="184" inkscape:window-x="2116"
inkscape:window-y="233" inkscape:window-y="261"
inkscape:window-maximized="0" inkscape:window-maximized="0"
borderlayer="true" borderlayer="true"
inkscape:showpageshadow="false" inkscape:showpageshadow="false"
inkscape:snap-nodes="false" inkscape:snap-nodes="false"
inkscape:snap-bbox="true" inkscape:snap-bbox="true"
showborder="true"> showborder="false">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid14843" id="grid14843"
@ -163,44 +160,39 @@
id="layer1" id="layer1"
transform="translate(-342.5,-521.36218)"> transform="translate(-342.5,-521.36218)">
<g <g
style="display:inline" transform="matrix(0.80230061,0,0,0.80230061,-87.624044,-453.10297)"
id="use5671" id="g14586"
transform="matrix(1.3594109,0,0,1.3564242,319.2059,481.99447)"> style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none">
<rect <g
transform="matrix(0.47304779,0,0,0.4807373,-6.3607039,-29.396216)" inkscape:export-ydpi="90"
rx="4.4136767" inkscape:export-xdpi="90"
y="125.3458" inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
x="50.440369" transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
height="29.154205" id="g15291-9"
width="29.559635" style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new">
id="rect11803" <g
style="color:#000000;fill:url(#linearGradient11811);fill-opacity:1;stroke:#3465a4;stroke-width:1.54426003000000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" transform="translate(877.50354,-102.83507)"
ry="4.4233952" /> id="g16853-4"
<path style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;enable-background:new">
inkscape:connector-curvature="0" <rect
id="path11809" transform="scale(1,-1)"
d="m 17.87105,33.844107 0,-0.773112 c 0,-1.031264 0.807171,-1.836142 1.811982,-1.836142 l 9.612456,0 c 1.004811,0 1.787822,0.804878 1.787822,1.836142 l 0,0.773112 c 0,-1.031264 -0.783011,-1.836142 -1.787822,-1.836142 l -9.612456,0 c -1.004811,0 -1.811982,0.804878 -1.811982,1.836142 z" style="color:#000000;fill:url(#linearGradient14219);fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:1.24833274;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" id="rect6506-6"
sodipodi:nodetypes="csssscssc" /> width="11.281681"
<path height="11.26221"
sodipodi:nodetypes="csssscssc" x="-409.59354"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" y="-284.40115"
d="m 17.87105,41.158551 0,0.773112 c 0,1.031264 0.807171,1.836142 1.811982,1.836142 l 9.612456,0 c 1.004811,0 1.787822,-0.804878 1.787822,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z" rx="1.0052766"
id="path11867" ry="1.0052764" />
inkscape:connector-curvature="0" /> </g>
<path </g>
inkscape:connector-curvature="0" <g
id="path11869" inkscape:export-ydpi="90"
d="m 17.87105,41.895784 0,0.773112 c 0,1.031264 0.644622,1.836142 1.649433,1.836142 l 10.067593,0 c 1.004811,0 1.495234,-0.804878 1.495234,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z" inkscape:export-xdpi="90"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#000000;fill-opacity:0.85253451;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
sodipodi:nodetypes="csssscssc" /> transform="translate(343.99999,987.99997)"
id="g5886"
style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new" />
</g> </g>
<rect
style="color:#000000;fill:none;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect17347"
width="21.943846"
height="21.943846"
x="342.29913"
y="521.58435" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -14,10 +14,22 @@
height="22" height="22"
id="svg3199" id="svg3199"
version="1.1" version="1.1"
inkscape:version="0.48.5 r10040" inkscape:version="0.48.1 r9760"
sodipodi:docname="checkbox-focused.svg"> sodipodi:docname="checkbox.svg">
<defs <defs
id="defs3201"> id="defs3201">
<linearGradient
id="linearGradient15404"
inkscape:collect="always">
<stop
id="stop15406"
offset="0"
style="stop-color:#515151;stop-opacity:1" />
<stop
id="stop15408"
offset="1"
style="stop-color:#292929;stop-opacity:1" />
</linearGradient>
<inkscape:perspective <inkscape:perspective
sodipodi:type="inkscape:persp3d" sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1" inkscape:vp_x="0 : 526.18109 : 1"
@ -32,6 +44,27 @@
inkscape:vp_y="0 : 1000 : 0" inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1" inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" /> sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5872-5-1"
id="linearGradient5891-0-4"
gradientUnits="userSpaceOnUse"
x1="205.84143"
y1="246.7094"
x2="206.74803"
y2="231.24142" />
<linearGradient
inkscape:collect="always"
id="linearGradient5872-5-1">
<stop
style="stop-color:#0b2e52;stop-opacity:1"
offset="0"
id="stop5874-4-4" />
<stop
style="stop-color:#1862af;stop-opacity:1"
offset="1"
id="stop5876-0-5" />
</linearGradient>
<inkscape:path-effect <inkscape:path-effect
effect="spiro" effect="spiro"
id="path-effect5837-4-6" id="path-effect5837-4-6"
@ -44,6 +77,16 @@
effect="spiro" effect="spiro"
id="path-effect5884-4-7" id="path-effect5884-4-7"
is_visible="true" /> is_visible="true" />
<linearGradient
y2="-388.72955"
x2="-93.031357"
y1="-396.34738"
x1="-93.031357"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
gradientUnits="userSpaceOnUse"
id="linearGradient14219"
xlink:href="#linearGradient15404"
inkscape:collect="always" />
<linearGradient <linearGradient
inkscape:collect="always" inkscape:collect="always"
id="linearGradient10013-4-63-6"> id="linearGradient10013-4-63-6">
@ -88,55 +131,30 @@
id="linearGradient15376" id="linearGradient15376"
xlink:href="#linearGradient10597-5" xlink:href="#linearGradient10597-5"
inkscape:collect="always" /> inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5581-5-2-4-6-8-7-35-8"
id="linearGradient11811"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.0317573,0,0,1.0053174,-102.66338,-0.82153381)"
x1="63.568954"
y1="127.16142"
x2="63.568954"
y2="152.6618" />
<linearGradient
id="linearGradient5581-5-2-4-6-8-7-35-8">
<stop
id="stop5583-0-92-8-0-7-6-5-1"
offset="0"
style="stop-color:#454c4c;stop-opacity:1;" />
<stop
style="stop-color:#393f3f;stop-opacity:1;"
offset="0.40000001"
id="stop5585-4-7-2-7-9-9-92-0" />
<stop
id="stop5587-6-7-2-0-3-1-21-5"
offset="1"
style="stop-color:#2d3232;stop-opacity:1;" />
</linearGradient>
</defs> </defs>
<sodipodi:namedview <sodipodi:namedview
id="base" id="base"
pagecolor="#a2a2a2" pagecolor="#000000"
bordercolor="#2d2d2d" bordercolor="#2d2d2d"
borderopacity="1" borderopacity="1"
inkscape:pageopacity="1" inkscape:pageopacity="1"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="1" inkscape:zoom="4"
inkscape:cx="9.6447897" inkscape:cx="71.247925"
inkscape:cy="12.591409" inkscape:cy="33.339093"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
inkscape:window-width="1412" inkscape:window-width="1412"
inkscape:window-height="1067" inkscape:window-height="1067"
inkscape:window-x="184" inkscape:window-x="2116"
inkscape:window-y="233" inkscape:window-y="261"
inkscape:window-maximized="0" inkscape:window-maximized="0"
borderlayer="true" borderlayer="true"
inkscape:showpageshadow="false" inkscape:showpageshadow="false"
inkscape:snap-nodes="false" inkscape:snap-nodes="false"
inkscape:snap-bbox="true" inkscape:snap-bbox="true"
showborder="true"> showborder="false">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid14843" id="grid14843"
@ -163,44 +181,38 @@
id="layer1" id="layer1"
transform="translate(-342.5,-521.36218)"> transform="translate(-342.5,-521.36218)">
<g <g
style="display:inline" transform="matrix(0.84337,0,0,0.84337,-110.16632,-503.56182)"
id="use5671" id="g14586">
transform="matrix(1.3594109,0,0,1.3564242,319.2059,481.99447)"> <g
<rect inkscape:export-ydpi="90"
transform="matrix(0.47304779,0,0,0.4807373,-6.3607039,-29.396216)" inkscape:export-xdpi="90"
rx="4.4136767" inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
y="125.3458" transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
x="50.440369" id="g15291-9"
height="29.154205" style="display:inline;enable-background:new">
width="29.559635" <g
id="rect11803" transform="translate(877.50354,-102.83507)"
style="color:#000000;fill:url(#linearGradient11811);fill-opacity:1;stroke:#1c1f1f;stroke-width:1.54426003;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="g16853-4"
ry="4.4233952" /> style="enable-background:new">
<path <rect
inkscape:connector-curvature="0" transform="scale(1,-1)"
id="path11809" style="color:#000000;fill:url(#linearGradient14219);fill-opacity:1;fill-rule:nonzero;stroke:#868686;stroke-width:0.59377144999999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
d="m 17.87105,33.844107 0,-0.773112 c 0,-1.031264 0.807171,-1.836142 1.811982,-1.836142 l 9.612456,0 c 1.004811,0 1.787822,0.804878 1.787822,1.836142 l 0,0.773112 c 0,-1.031264 -0.783011,-1.836142 -1.787822,-1.836142 l -9.612456,0 c -1.004811,0 -1.811982,0.804878 -1.811982,1.836142 z" id="rect6506-6"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" width="11.281681"
sodipodi:nodetypes="csssscssc" /> height="11.26221"
<path x="-409.59354"
sodipodi:nodetypes="csssscssc" y="-284.40115"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" rx="0.95632279"
d="m 17.87105,41.158551 0,0.773112 c 0,1.031264 0.807171,1.836142 1.811982,1.836142 l 9.612456,0 c 1.004811,0 1.787822,-0.804878 1.787822,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z" ry="0.95632273" />
id="path11867" </g>
inkscape:connector-curvature="0" /> </g>
<path <g
inkscape:connector-curvature="0" inkscape:export-ydpi="90"
id="path11869" inkscape:export-xdpi="90"
d="m 17.87105,41.895784 0,0.773112 c 0,1.031264 0.644622,1.836142 1.649433,1.836142 l 10.067593,0 c 1.004811,0 1.495234,-0.804878 1.495234,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z" inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#000000;fill-opacity:0.85253451;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" transform="translate(343.99999,987.99997)"
sodipodi:nodetypes="csssscssc" /> id="g5886"
style="display:inline;enable-background:new" />
</g> </g>
<rect
style="color:#000000;fill:none;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect17347"
width="21.943846"
height="21.943846"
x="342.29913"
y="521.58435" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -14,8 +14,8 @@
height="22" height="22"
id="svg3199" id="svg3199"
version="1.1" version="1.1"
inkscape:version="0.48.5 r10040" inkscape:version="0.48.1 r9760"
sodipodi:docname="checkbox.svg"> sodipodi:docname="checkbox-focused.svg">
<defs <defs
id="defs3201"> id="defs3201">
<linearGradient <linearGradient
@ -131,55 +131,30 @@
id="linearGradient15376" id="linearGradient15376"
xlink:href="#linearGradient10597-5" xlink:href="#linearGradient10597-5"
inkscape:collect="always" /> inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5581-5-2-4-6-8-7-35-8"
id="linearGradient11811"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.0317573,0,0,1.0053174,-102.66338,-0.82153381)"
x1="63.568954"
y1="127.16142"
x2="63.568954"
y2="152.6618" />
<linearGradient
id="linearGradient5581-5-2-4-6-8-7-35-8">
<stop
id="stop5583-0-92-8-0-7-6-5-1"
offset="0"
style="stop-color:#454c4c;stop-opacity:1;" />
<stop
style="stop-color:#393f3f;stop-opacity:1;"
offset="0.40000001"
id="stop5585-4-7-2-7-9-9-92-0" />
<stop
id="stop5587-6-7-2-0-3-1-21-5"
offset="1"
style="stop-color:#2d3232;stop-opacity:1;" />
</linearGradient>
</defs> </defs>
<sodipodi:namedview <sodipodi:namedview
id="base" id="base"
pagecolor="#a2a2a2" pagecolor="#000000"
bordercolor="#2d2d2d" bordercolor="#2d2d2d"
borderopacity="1" borderopacity="1"
inkscape:pageopacity="1" inkscape:pageopacity="1"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="1" inkscape:zoom="1"
inkscape:cx="-0.17876005" inkscape:cx="64.516955"
inkscape:cy="11.944326" inkscape:cy="13.871056"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
inkscape:window-width="2560" inkscape:window-width="1412"
inkscape:window-height="1375" inkscape:window-height="1067"
inkscape:window-x="0" inkscape:window-x="2635"
inkscape:window-y="27" inkscape:window-y="226"
inkscape:window-maximized="1" inkscape:window-maximized="0"
borderlayer="true" borderlayer="true"
inkscape:showpageshadow="false" inkscape:showpageshadow="false"
inkscape:snap-nodes="false" inkscape:snap-nodes="false"
inkscape:snap-bbox="true" inkscape:snap-bbox="true"
showborder="true"> showborder="false">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid14843" id="grid14843"
@ -196,7 +171,7 @@
<dc:format>image/svg+xml</dc:format> <dc:format>image/svg+xml</dc:format>
<dc:type <dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title /> <dc:title></dc:title>
</cc:Work> </cc:Work>
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
@ -206,56 +181,63 @@
id="layer1" id="layer1"
transform="translate(-342.5,-521.36218)"> transform="translate(-342.5,-521.36218)">
<g <g
style="display:inline" transform="matrix(0.84337,0,0,0.84337,-110.16632,-503.56182)"
id="use5671" id="g14586">
transform="matrix(1.3594109,0,0,1.3564242,319.2059,481.99447)"> <g
<rect inkscape:export-ydpi="90"
transform="matrix(0.47304779,0,0,0.4807373,-6.3607039,-29.396216)" inkscape:export-xdpi="90"
rx="4.4136767" inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
y="125.3458" transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
x="50.440369" id="g15291-9"
height="29.154205" style="display:inline;enable-background:new">
width="29.559635" <g
id="rect11803" transform="translate(877.50354,-102.83507)"
style="color:#000000;fill:url(#linearGradient11811);fill-opacity:1;stroke:#1c1f1f;stroke-width:1.54426003;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="g16853-4"
ry="4.4233952" /> style="enable-background:new">
<path <rect
inkscape:connector-curvature="0" transform="scale(1,-1)"
id="path11809" style="color:#000000;fill:url(#linearGradient14219);fill-opacity:1;fill-rule:nonzero;stroke:#868686;stroke-width:0.59377144999999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
d="m 17.87105,33.844107 0,-0.773112 c 0,-1.031264 0.807171,-1.836142 1.811982,-1.836142 l 9.612456,0 c 1.004811,0 1.787822,0.804878 1.787822,1.836142 l 0,0.773112 c 0,-1.031264 -0.783011,-1.836142 -1.787822,-1.836142 l -9.612456,0 c -1.004811,0 -1.811982,0.804878 -1.811982,1.836142 z" id="rect6506-6"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" width="11.281681"
sodipodi:nodetypes="csssscssc" /> height="11.26221"
<path x="-409.59354"
sodipodi:nodetypes="csssscssc" y="-284.40115"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" rx="0.95632279"
d="m 17.87105,41.158551 0,0.773112 c 0,1.031264 0.807171,1.836142 1.811982,1.836142 l 9.612456,0 c 1.004811,0 1.787822,-0.804878 1.787822,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z" ry="0.95632273" />
id="path11867" </g>
inkscape:connector-curvature="0" /> </g>
<path <g
inkscape:connector-curvature="0" inkscape:export-ydpi="90"
id="path11869" inkscape:export-xdpi="90"
d="m 17.87105,41.895784 0,0.773112 c 0,1.031264 0.644622,1.836142 1.649433,1.836142 l 10.067593,0 c 1.004811,0 1.495234,-0.804878 1.495234,-1.836142 l 0,-0.773112 c 0,1.031264 -0.783011,1.836142 -1.787822,1.836142 l -9.612456,0 c -1.004811,0 -1.811982,-0.804878 -1.811982,-1.836142 z" inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.15;color:#000000;fill:#000000;fill-opacity:0.85253451;fill-rule:nonzero;stroke:none;stroke-width:1.00000012;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" transform="translate(343.99999,987.99997)"
sodipodi:nodetypes="csssscssc" /> id="g5886"
style="display:inline;enable-background:new">
<path
style="fill:none;stroke:url(#linearGradient5891-0-4);stroke-width:7.11431503;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
id="path5835"
inkscape:path-effect="#path-effect5837-4-6"
inkscape:original-d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
inkscape:connector-curvature="0"
inkscape:original-d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
inkscape:path-effect="#path-effect5837-4-6"
id="path5880"
d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
style="fill:none;stroke:#4787c8;stroke-width:3.55715752;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#7ea7d3;stroke-width:1.18571913px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 197.45937,240.47455 c -0.17828,-0.29362 -0.20087,-0.67548 -0.0603,-0.98892 0.14055,-0.31344 0.43739,-0.54812 0.77144,-0.62817 0.33405,-0.08 0.69314,-0.01 0.99635,0.15175 0.30321,0.16144 0.55146,0.40727 0.79165,0.65284 l 3.66429,3.74643 12.87946,-12.98973 c 0.20796,-0.20974 0.42306,-0.41969 0.68548,-0.55522 0.26242,-0.13553 0.57293,-0.19052 0.85827,-0.11426 0.14267,0.0381 0.27708,0.10787 0.38874,0.20452 0.11167,0.0966 0.20021,0.22004 0.25479,0.35726 0.0546,0.13722 0.075,0.28793 0.0585,0.43468 -0.0165,0.14674 -0.07,0.28919 -0.15422,0.41052"
id="path5882"
inkscape:path-effect="#path-effect5884-4-7"
inkscape:original-d="m 197.45937,240.47455 c 0.65604,-0.56057 2.02485,-1.34847 2.49911,-0.8125 l 3.66429,3.74643 12.87946,-12.98973 c 0.6875,-0.6875 2.09152,0.7375 2.09152,0.7375"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csccc" />
</g>
</g> </g>
<rect
style="color:#000000;fill:none;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect17347"
width="21.943846"
height="21.943846"
x="342.29913"
y="521.58435" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 359.97505,524.8252 -7.88606,7.71465 -2.57155,-2.57155 -2.91442,-0.0427 0,2.35727 4.02875,3.98587 c 0.80342,0.80309 2.111,0.80309 2.91442,0 l 8.18609,-8.22894 0,-0.38573 c 0,-1.24128 0.19944,-1.76801 -0.82915,-2.29836 z"
id="rect5147-9-1-5-7-6-5-8-7"
sodipodi:nodetypes="ccccccccscc" />
<path
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:sans-serif;-inkscape-font-specification:sans-serif"
d="m 361.65223,524.52745 -9.5602,9.36735 -2.56345,-2.56344 -2.92846,-0.0214 0.0153,2.32639 4.02203,4.02206 c 0.80341,0.80309 2.10565,0.80309 2.90906,0 l 10.95049,-11.05765 0.003,-2.1502 z"
id="path12830-4-17-0"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +0,0 @@
@import "gnome-shell-sass/_high-contrast-colors"; //use gtk colors
@import "gnome-shell-sass/_drawing";
@import "gnome-shell-sass/_common";
//force symbolic icons
stage {
-st-icon-style: symbolic;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +0,0 @@
$variant: 'dark';
@import "gnome-shell-sass/_colors"; //use gtk colors
@import "gnome-shell-sass/_drawing";
@import "gnome-shell-sass/_common";

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -14,7 +14,7 @@
height="16" height="16"
id="svg12430" id="svg12430"
version="1.1" version="1.1"
inkscape:version="0.48.4 r9939" inkscape:version="0.48.3.1 r9886"
sodipodi:docname="more-results.svg"> sodipodi:docname="more-results.svg">
<defs <defs
id="defs12432" /> id="defs12432" />
@ -25,18 +25,18 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="1" inkscape:pageopacity="1"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="90.509668" inkscape:zoom="1"
inkscape:cx="6.5009792" inkscape:cx="8.3155237"
inkscape:cy="8.3589595" inkscape:cy="0.89548874"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="g14642-3-0" inkscape:current-layer="g14642-3-0"
showgrid="false" showgrid="false"
borderlayer="true" borderlayer="true"
inkscape:showpageshadow="false" inkscape:showpageshadow="false"
inkscape:window-width="1440" inkscape:window-width="2560"
inkscape:window-height="840" inkscape:window-height="1376"
inkscape:window-x="0" inkscape:window-x="1200"
inkscape:window-y="27" inkscape:window-y="187"
inkscape:window-maximized="1"> inkscape:window-maximized="1">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
@ -90,11 +90,6 @@
transform="translate(-2,0)" transform="translate(-2,0)"
width="16" width="16"
height="16" /> height="16" />
<path
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
d="M 7 5 L 7 7 L 5 7 L 5 9 L 7 9 L 7 11 L 9 11 L 9 9 L 11 9 L 11 7 L 9 7 L 9 5 L 7 5 z "
transform="translate(141.99984,397.99107)"
id="rect3757" />
<path <path
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
style="color:#bebebe;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible" style="color:#bebebe;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible"

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="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>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="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>

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="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 />
</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:0.39215686000000000;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>

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -9,63 +9,66 @@
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="18" width="17"
height="18" height="10"
id="svg4703" id="svg2"
version="1.1" version="1.1"
inkscape:version="0.48.4 r9939" inkscape:version="0.48.1 r9760"
sodipodi:docname="page-indicator-pushed.svg"> sodipodi:docname="panel-button-border.svg">
<defs <defs
id="defs4705" /> id="defs4" />
<sodipodi:namedview <sodipodi:namedview
id="base" id="base"
pagecolor="#ffffff" pagecolor="#000000"
bordercolor="#666666" bordercolor="#666666"
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="0.0" inkscape:pageopacity="0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="31.392433" inkscape:zoom="44.8"
inkscape:cx="1.0245308" inkscape:cx="8.6594891"
inkscape:cy="13.3715" inkscape:cy="5.7029946"
inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="true" showgrid="true"
inkscape:grid-bbox="true" showguides="true"
inkscape:document-units="px" inkscape:guide-bbox="true"
inkscape:window-width="2560" inkscape:window-width="1440"
inkscape:window-height="1374" inkscape:window-height="843"
inkscape:window-x="0" inkscape:window-x="0"
inkscape:window-y="27" inkscape:window-y="26"
inkscape:window-maximized="1"> inkscape:window-maximized="1"
guidetolerance="10000"
objecttolerance="10000">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid6140" /> id="grid3792"
empspacing="10"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview> </sodipodi:namedview>
<metadata <metadata
id="metadata4708"> id="metadata7">
<rdf:RDF> <rdf:RDF>
<cc:Work <cc:Work
rdf:about=""> rdf:about="">
<dc:format>image/svg+xml</dc:format> <dc:format>image/svg+xml</dc:format>
<dc:type <dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title> <dc:title />
</cc:Work> </cc:Work>
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
<g <g
id="layer1"
inkscape:label="Layer 1" inkscape:label="Layer 1"
inkscape:groupmode="layer" inkscape:groupmode="layer"
transform="translate(0,2)"> id="layer1">
<path <rect
transform="matrix(0.54617904,0,0,0.62523128,-1131.9904,-392.39214)" style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke-width:0.43599999;stroke-miterlimit:4;stroke-dasharray:none"
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" id="rect3796"
sodipodi:ry="9.5964489" width="7"
sodipodi:rx="10.985409" height="2"
sodipodi:cy="638.83099" x="5"
sodipodi:cx="2088.9954" y="8" />
id="path4711"
style="fill:#fdffff;fill-opacity:1;stroke:none"
sodipodi:type="arc" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,111 @@
<?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:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="30"
height="25"
id="svg10621"
version="1.1"
inkscape:version="0.48.1 r9760"
sodipodi:docname="panel-button-highlight-narrow.svg">
<defs
id="defs10623">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient34508-1-3"
id="radialGradient99561-1"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.72146227,0,0,0.27484277,14.205424,21.754717)"
cx="51"
cy="30"
fx="51"
fy="30"
r="42" />
<linearGradient
inkscape:collect="always"
id="linearGradient34508-1-3">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop34510-1-9" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop34512-4-5" />
</linearGradient>
<radialGradient
r="42"
fy="30"
fx="51"
cy="30"
cx="51"
gradientTransform="matrix(0.72146227,0,0,0.27484277,14.205424,21.754717)"
gradientUnits="userSpaceOnUse"
id="radialGradient10592"
xlink:href="#linearGradient34508-1-3"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="-171.36384"
inkscape:cy="-53.255157"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1440"
inkscape:window-height="843"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata10626">
<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
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-468.08632,-537.03477)">
<path
sodipodi:type="arc"
style="opacity:0.4625;color:#000000;fill:url(#radialGradient10592);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path34506-3"
sodipodi:cx="51"
sodipodi:cy="30"
sodipodi:rx="42"
sodipodi:ry="16"
d="M 9,29.999999 C 9.0000011,21.163443 27.804042,14 51.000002,14 74.195961,14 93,21.163444 93,30 l -42,0 z"
sodipodi:start="3.1415927"
sodipodi:end="6.2831853"
transform="matrix(0.35714286,0,0,1.5625,464.87203,515.15977)"
inkscape:export-filename="/home/jimmac/src/cvs/gnome/gnome-shell-design/mockups/motion/textures/panel.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,111 @@
<?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:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="84"
height="25"
id="svg10621"
version="1.1"
inkscape:version="0.48.0 r9654"
sodipodi:docname="panel-button-highlight-wide.svg">
<defs
id="defs10623">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient34508-1-3"
id="radialGradient99561-1"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.72146227,0,0,0.27484277,14.205424,21.754717)"
cx="51"
cy="30"
fx="51"
fy="30"
r="42" />
<linearGradient
inkscape:collect="always"
id="linearGradient34508-1-3">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop34510-1-9" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop34512-4-5" />
</linearGradient>
<radialGradient
r="42"
fy="30"
fx="51"
cy="30"
cx="51"
gradientTransform="matrix(0.72146227,0,0,0.27484277,14.205424,21.754717)"
gradientUnits="userSpaceOnUse"
id="radialGradient10592"
xlink:href="#linearGradient34508-1-3"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="-118.50071"
inkscape:cy="27.304508"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1440"
inkscape:window-height="843"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata10626">
<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
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-441.08632,-537.03477)">
<path
sodipodi:type="arc"
style="opacity:0.4625;color:#000000;fill:url(#radialGradient10592);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path34506-3"
sodipodi:cx="51"
sodipodi:cy="30"
sodipodi:rx="42"
sodipodi:ry="16"
d="M 9,29.999999 C 9.0000011,21.163443 27.804042,14 51.000002,14 74.195961,14 93,21.163444 93,30 l -42,0 z"
sodipodi:start="3.1415927"
sodipodi:end="6.2831853"
transform="matrix(1,0,0,1.5625,432.08632,515.15977)"
inkscape:export-filename="/home/jimmac/src/cvs/gnome/gnome-shell-design/mockups/motion/textures/panel.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -12,7 +12,7 @@
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg5369" id="svg5369"
version="1.1" version="1.1"
inkscape:version="0.48.5 r10040" inkscape:version="0.48+devel r10053 custom"
width="96" width="96"
height="48" height="48"
sodipodi:docname="process-working.svg" sodipodi:docname="process-working.svg"
@ -25,597 +25,12 @@
<dc:format>image/svg+xml</dc:format> <dc:format>image/svg+xml</dc:format>
<dc:type <dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title /> <dc:title></dc:title>
</cc:Work> </cc:Work>
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
<defs <defs
id="defs5373"> id="defs5373" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8231-1-4-4-1"
id="radialGradient35326"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.229454,-1.2865389,1.2087442,2.0939897,-228.90301,-208.08725)"
cx="-0.067823187"
cy="188.51917"
fx="-0.067823187"
fy="188.51917"
r="27.330345" />
<linearGradient
id="linearGradient8231-1-4-4-1">
<stop
id="stop8233-28-5-27-1"
offset="0"
style="stop-color:#ffffff;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0.15428571"
offset="0.31861392"
id="stop8235-7-3-94-3" />
<stop
id="stop8237-7-8-20-2"
offset="0.54270232"
style="stop-color:#ffffff;stop-opacity:0.33714285" />
<stop
id="stop8239-2-9-1-9"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5767-6"
id="radialGradient35230"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1252013,-0.60470548,0.56813832,1.0568583,-107.67128,-11.948108)"
cx="0.053942412"
cy="189.15244"
fx="0.053942412"
fy="189.15244"
r="27.330345" />
<linearGradient
id="linearGradient5767-6">
<stop
id="stop5769-0"
offset="0"
style="stop-color:#bebebe;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0"
offset="0.31861392"
id="stop5771-1" />
<stop
id="stop5773-7"
offset="0.75051737"
style="stop-color:#ffffff;stop-opacity:0.42857143" />
<stop
id="stop5775-8"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8231-1-4-4-1"
id="radialGradient10255"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.229454,-1.2865389,1.2087442,2.0939897,-228.90301,-208.08725)"
cx="-0.067823187"
cy="188.51917"
fx="-0.067823187"
fy="188.51917"
r="27.330345" />
<linearGradient
id="linearGradient10257">
<stop
id="stop10259"
offset="0"
style="stop-color:#ffffff;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0.15428571"
offset="0.31861392"
id="stop10261" />
<stop
id="stop10263"
offset="0.54270232"
style="stop-color:#ffffff;stop-opacity:0.33714285" />
<stop
id="stop10265"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5767-6"
id="radialGradient10267"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1252013,-0.60470548,0.56813832,1.0568583,-107.67128,-11.948108)"
cx="0.053942412"
cy="189.15244"
fx="0.053942412"
fy="189.15244"
r="27.330345" />
<linearGradient
id="linearGradient10269">
<stop
id="stop10271"
offset="0"
style="stop-color:#bebebe;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0"
offset="0.31861392"
id="stop10273" />
<stop
id="stop10275"
offset="0.75051737"
style="stop-color:#ffffff;stop-opacity:0.42857143" />
<stop
id="stop10277"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8231-1-4-4-1"
id="radialGradient10279"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.229454,-1.2865389,1.2087442,2.0939897,-228.90301,-208.08725)"
cx="-0.067823187"
cy="188.51917"
fx="-0.067823187"
fy="188.51917"
r="27.330345" />
<linearGradient
id="linearGradient10281">
<stop
id="stop10283"
offset="0"
style="stop-color:#ffffff;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0.15428571"
offset="0.31861392"
id="stop10285" />
<stop
id="stop10287"
offset="0.54270232"
style="stop-color:#ffffff;stop-opacity:0.33714285" />
<stop
id="stop10289"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5767-6"
id="radialGradient10291"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1252013,-0.60470548,0.56813832,1.0568583,-107.67128,-11.948108)"
cx="0.053942412"
cy="189.15244"
fx="0.053942412"
fy="189.15244"
r="27.330345" />
<linearGradient
id="linearGradient10293">
<stop
id="stop10295"
offset="0"
style="stop-color:#bebebe;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0"
offset="0.31861392"
id="stop10297" />
<stop
id="stop10299"
offset="0.75051737"
style="stop-color:#ffffff;stop-opacity:0.42857143" />
<stop
id="stop10301"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8231-1-4-4-1"
id="radialGradient10303"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.229454,-1.2865389,1.2087442,2.0939897,-228.90301,-208.08725)"
cx="-0.067823187"
cy="188.51917"
fx="-0.067823187"
fy="188.51917"
r="27.330345" />
<linearGradient
id="linearGradient10305">
<stop
id="stop10307"
offset="0"
style="stop-color:#ffffff;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0.15428571"
offset="0.31861392"
id="stop10309" />
<stop
id="stop10311"
offset="0.54270232"
style="stop-color:#ffffff;stop-opacity:0.33714285" />
<stop
id="stop10313"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5767-6"
id="radialGradient10315"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1252013,-0.60470548,0.56813832,1.0568583,-107.67128,-11.948108)"
cx="0.053942412"
cy="189.15244"
fx="0.053942412"
fy="189.15244"
r="27.330345" />
<linearGradient
id="linearGradient10317">
<stop
id="stop10319"
offset="0"
style="stop-color:#bebebe;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0"
offset="0.31861392"
id="stop10321" />
<stop
id="stop10323"
offset="0.75051737"
style="stop-color:#ffffff;stop-opacity:0.42857143" />
<stop
id="stop10325"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8231-1-4-4-1"
id="radialGradient10327"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.229454,-1.2865389,1.2087442,2.0939897,-228.90301,-208.08725)"
cx="-0.067823187"
cy="188.51917"
fx="-0.067823187"
fy="188.51917"
r="27.330345" />
<linearGradient
id="linearGradient10329">
<stop
id="stop10331"
offset="0"
style="stop-color:#ffffff;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0.15428571"
offset="0.31861392"
id="stop10333" />
<stop
id="stop10335"
offset="0.54270232"
style="stop-color:#ffffff;stop-opacity:0.33714285" />
<stop
id="stop10337"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5767-6"
id="radialGradient10339"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1252013,-0.60470548,0.56813832,1.0568583,-107.67128,-11.948108)"
cx="0.053942412"
cy="189.15244"
fx="0.053942412"
fy="189.15244"
r="27.330345" />
<linearGradient
id="linearGradient10341">
<stop
id="stop10343"
offset="0"
style="stop-color:#bebebe;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0"
offset="0.31861392"
id="stop10345" />
<stop
id="stop10347"
offset="0.75051737"
style="stop-color:#ffffff;stop-opacity:0.42857143" />
<stop
id="stop10349"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8231-1-4-4-1"
id="radialGradient10351"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.229454,-1.2865389,1.2087442,2.0939897,-228.90301,-208.08725)"
cx="-0.067823187"
cy="188.51917"
fx="-0.067823187"
fy="188.51917"
r="27.330345" />
<linearGradient
id="linearGradient10353">
<stop
id="stop10355"
offset="0"
style="stop-color:#ffffff;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0.15428571"
offset="0.31861392"
id="stop10357" />
<stop
id="stop10359"
offset="0.54270232"
style="stop-color:#ffffff;stop-opacity:0.33714285" />
<stop
id="stop10361"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5767-6"
id="radialGradient10363"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1252013,-0.60470548,0.56813832,1.0568583,-107.67128,-11.948108)"
cx="0.053942412"
cy="189.15244"
fx="0.053942412"
fy="189.15244"
r="27.330345" />
<linearGradient
id="linearGradient10365">
<stop
id="stop10367"
offset="0"
style="stop-color:#bebebe;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0"
offset="0.31861392"
id="stop10369" />
<stop
id="stop10371"
offset="0.75051737"
style="stop-color:#ffffff;stop-opacity:0.42857143" />
<stop
id="stop10373"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8231-1-4-4-1"
id="radialGradient10375"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.229454,-1.2865389,1.2087442,2.0939897,-228.90301,-208.08725)"
cx="-0.067823187"
cy="188.51917"
fx="-0.067823187"
fy="188.51917"
r="27.330345" />
<linearGradient
id="linearGradient10377">
<stop
id="stop10379"
offset="0"
style="stop-color:#ffffff;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0.15428571"
offset="0.31861392"
id="stop10381" />
<stop
id="stop10383"
offset="0.54270232"
style="stop-color:#ffffff;stop-opacity:0.33714285" />
<stop
id="stop10385"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5767-6"
id="radialGradient10387"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1252013,-0.60470548,0.56813832,1.0568583,-107.67128,-11.948108)"
cx="0.053942412"
cy="189.15244"
fx="0.053942412"
fy="189.15244"
r="27.330345" />
<linearGradient
id="linearGradient10389">
<stop
id="stop10391"
offset="0"
style="stop-color:#bebebe;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0"
offset="0.31861392"
id="stop10393" />
<stop
id="stop10395"
offset="0.75051737"
style="stop-color:#ffffff;stop-opacity:0.42857143" />
<stop
id="stop10397"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8231-1-4-4-1"
id="radialGradient10399"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.229454,-1.2865389,1.2087442,2.0939897,-228.90301,-208.08725)"
cx="-0.067823187"
cy="188.51917"
fx="-0.067823187"
fy="188.51917"
r="27.330345" />
<linearGradient
id="linearGradient10401">
<stop
id="stop10403"
offset="0"
style="stop-color:#ffffff;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0.15428571"
offset="0.31861392"
id="stop10405" />
<stop
id="stop10407"
offset="0.54270232"
style="stop-color:#ffffff;stop-opacity:0.33714285" />
<stop
id="stop10409"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5767-6"
id="radialGradient10411"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1252013,-0.60470548,0.56813832,1.0568583,-107.67128,-11.948108)"
cx="0.053942412"
cy="189.15244"
fx="0.053942412"
fy="189.15244"
r="27.330345" />
<linearGradient
id="linearGradient10413">
<stop
id="stop10415"
offset="0"
style="stop-color:#bebebe;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0"
offset="0.31861392"
id="stop10417" />
<stop
id="stop10419"
offset="0.75051737"
style="stop-color:#ffffff;stop-opacity:0.42857143" />
<stop
id="stop10421"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8231-1-4-4-1"
id="radialGradient10423"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.229454,-1.2865389,1.2087442,2.0939897,-228.90301,-208.08725)"
cx="-0.067823187"
cy="188.51917"
fx="-0.067823187"
fy="188.51917"
r="27.330345" />
<linearGradient
id="linearGradient10425">
<stop
id="stop10427"
offset="0"
style="stop-color:#ffffff;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0.15428571"
offset="0.31861392"
id="stop10429" />
<stop
id="stop10431"
offset="0.54270232"
style="stop-color:#ffffff;stop-opacity:0.33714285" />
<stop
id="stop10433"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5767-6"
id="radialGradient10435"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1252013,-0.60470548,0.56813832,1.0568583,-107.67128,-11.948108)"
cx="0.053942412"
cy="189.15244"
fx="0.053942412"
fy="189.15244"
r="27.330345" />
<linearGradient
id="linearGradient10437">
<stop
id="stop10439"
offset="0"
style="stop-color:#bebebe;stop-opacity:0" />
<stop
style="stop-color:#ffffff;stop-opacity:0"
offset="0.31861392"
id="stop10441" />
<stop
id="stop10443"
offset="0.75051737"
style="stop-color:#ffffff;stop-opacity:0.42857143" />
<stop
id="stop10445"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8231-1-4-4-1"
id="radialGradient10709"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.229454,-1.2865389,1.2087442,2.0939897,-228.90301,-208.08725)"
cx="-0.067823187"
cy="188.51917"
fx="-0.067823187"
fy="188.51917"
r="27.330345" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5767-6"
id="radialGradient10711"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1252013,-0.60470548,0.56813832,1.0568583,-107.67128,-11.948108)"
cx="0.053942412"
cy="189.15244"
fx="0.053942412"
fy="189.15244"
r="27.330345" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8231-1-4-4-1"
id="radialGradient10713"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.229454,-1.2865389,1.2087442,2.0939897,-228.90301,-208.08725)"
cx="-0.067823187"
cy="188.51917"
fx="-0.067823187"
fy="188.51917"
r="27.330345" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5767-6"
id="radialGradient10715"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1252013,-0.60470548,0.56813832,1.0568583,-107.67128,-11.948108)"
cx="0.053942412"
cy="189.15244"
fx="0.053942412"
fy="189.15244"
r="27.330345" />
</defs>
<sodipodi:namedview <sodipodi:namedview
pagecolor="#808080" pagecolor="#808080"
bordercolor="#666666" bordercolor="#666666"
@ -631,15 +46,13 @@
showgrid="true" showgrid="true"
borderlayer="true" borderlayer="true"
inkscape:showpageshadow="false" inkscape:showpageshadow="false"
inkscape:zoom="5.6568542" inkscape:zoom="16"
inkscape:cx="40.82607" inkscape:cx="53.997662"
inkscape:cy="30.594699" inkscape:cy="22.367695"
inkscape:window-x="2560" inkscape:window-x="1600"
inkscape:window-y="33" inkscape:window-y="33"
inkscape:window-maximized="0" inkscape:window-maximized="0"
inkscape:current-layer="layer2" inkscape:current-layer="layer2">
inkscape:snap-bbox="true"
inkscape:snap-nodes="false">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
id="grid11933" id="grid11933"
@ -715,97 +128,134 @@
id="layer2" id="layer2"
inkscape:label="spinner"> inkscape:label="spinner">
<g <g
transform="matrix(0.43142675,0,0,0.43298814,218.13188,-592.92581)" transform="matrix(0.28240106,0,0,0.28240106,146.92015,-382.52444)"
id="g10450-5-3" id="g10450-5"
style="display:inline"> style="display:inline">
<path <path
inkscape:export-ydpi="90" inkscape:connector-curvature="0"
inkscape:export-xdpi="90" style="opacity:0.6;color:#000000;fill:none;stroke:#ffffff;stroke-width:7.08212566;stroke-linecap:round;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
inkscape:export-filename="/home/hbons/Moblin/git/carrick-ng/data/icons/network-connecting.png" d="m -477.76072,1373.3569 0,9.4717"
sodipodi:open="true" id="path18768"
sodipodi:end="4.712389" sodipodi:nodetypes="cc"
sodipodi:start="0.23191105" inkscape:transform-center-y="-4.6808838" />
sodipodi:type="arc"
style="fill:none;stroke:url(#radialGradient10713);stroke-width:12.18051815;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
id="path10452-5"
sodipodi:cx="-25.809397"
sodipodi:cy="179.43886"
sodipodi:rx="22.98097"
sodipodi:ry="22.98097"
d="m -3.4436513,184.72075 c -2.9171108,12.35226 -15.2953817,20.00096 -27.6476417,17.08385 -12.35226,-2.91711 -20.00096,-15.29538 -17.083849,-27.64764 2.449452,-10.372 11.708437,-17.69907 22.365746,-17.69907"
transform="matrix(-0.16397381,0.61157081,-0.61162275,-0.16377992,-372.32298,1442.5061)" />
<path <path
transform="matrix(-0.63300818,0.01438356,-0.01458424,-0.63300359,-491.4014,1510.996)" inkscape:connector-curvature="0"
d="m -3.4436513,184.72075 c -2.9171108,12.35226 -15.2953817,20.00096 -27.6476417,17.08385 -12.35226,-2.91711 -20.00096,-15.29538 -17.083849,-27.64764 2.449452,-10.372 11.708437,-17.69907 22.365746,-17.69907" inkscape:transform-center-y="-3.3099227"
sodipodi:ry="22.98097" sodipodi:nodetypes="cc"
sodipodi:rx="22.98097" id="path18770"
sodipodi:cy="179.43886" d="m -461.0171,1380.2922 -7.23427,7.3824"
sodipodi:cx="-25.809397" style="opacity:0.7;color:#000000;fill:none;stroke:#ffffff;stroke-width:7.08212566;stroke-linecap:round;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path10454-7" inkscape:transform-center-x="-3.3098966" />
style="fill:none;stroke:url(#radialGradient10715);stroke-width:12.18051815;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline" <path
sodipodi:type="arc" inkscape:connector-curvature="0"
sodipodi:start="0.23191105" inkscape:transform-center-x="-4.6808962"
sodipodi:end="4.712389" style="opacity:0.8;color:#000000;fill:none;stroke:#ffffff;stroke-width:7.08212566;stroke-linecap:round;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
sodipodi:open="true" d="m -454.08163,1397.0359 -9.47165,0"
inkscape:export-filename="/home/hbons/Moblin/git/carrick-ng/data/icons/network-connecting.png" id="path18772"
inkscape:export-xdpi="90" sodipodi:nodetypes="cc"
inkscape:export-ydpi="90" /> inkscape:transform-center-y="-2.6596956e-05" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path18774"
d="m -461.01709,1413.7796 -6.93831,-7.0864"
style="opacity:0.9;color:#000000;fill:none;stroke:#ffffff;stroke-width:7.08212566;stroke-linecap:round;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
inkscape:transform-center-x="-3.3098966"
inkscape:transform-center-y="3.3098652" />
<path
inkscape:connector-curvature="0"
inkscape:transform-center-y="4.6808757"
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:7.08212566;stroke-linecap:round;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m -477.76074,1420.715 9e-5,-9.4716"
id="path18776"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path18778"
d="m -494.50442,1413.7796 6.79048,-6.9384"
style="opacity:0.3;color:#000000;fill:none;stroke:#ffffff;stroke-width:7.08212566;stroke-linecap:round;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
inkscape:transform-center-y="3.3098769"
inkscape:transform-center-x="3.3098883" />
<path
inkscape:connector-curvature="0"
inkscape:transform-center-x="4.6808941"
style="opacity:0.4;color:#000000;fill:none;stroke:#ffffff;stroke-width:7.08212566;stroke-linecap:round;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m -501.43987,1397.0359 9.47174,0"
id="path18780"
sodipodi:nodetypes="cc"
inkscape:transform-center-y="-2.6596956e-05" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path18782"
d="m -494.5044,1380.2922 6.64243,6.9384"
style="opacity:0.5;color:#000000;fill:none;stroke:#ffffff;stroke-width:7.08212566;stroke-linecap:round;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
inkscape:transform-center-x="3.3098902"
inkscape:transform-center-y="-3.3099302" />
</g> </g>
<use <use
style="display:inline"
x="0" x="0"
y="0" y="0"
xlink:href="#g10450-5-3" xlink:href="#g10450-5"
id="use13294" id="use4981"
transform="matrix(0.70710678,0.70710679,-0.70710679,0.70710678,35.986458,-4.9737924)" transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,36,-4.9705636)"
width="96" width="400"
height="48" /> height="400" />
<use <use
style="display:inline"
x="0" x="0"
y="0" y="0"
xlink:href="#use13294" xlink:href="#use4981"
id="use13314" id="use4983"
transform="matrix(0.70710678,0.70710679,-0.70710679,0.70710678,43.036943,-21.933639)" transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,43.032478,-21.909695)"
width="96" width="400"
height="48" /> height="400" />
<use <use
style="display:inline"
x="0" x="0"
y="0" y="0"
xlink:href="#use13314" xlink:href="#use4983"
id="use13334" id="use4985"
transform="matrix(0.70710678,0.70710679,-0.70710679,0.70710678,50.085328,-38.904987)" transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,50.081986,-38.904617)"
width="96" width="400"
height="48" /> height="400" />
<use <use
style="display:inline"
x="0" x="0"
y="0" y="0"
xlink:href="#use13334" xlink:href="#use4985"
id="use13354" id="use4987"
transform="matrix(0.70710678,0.70710679,-0.70710679,0.70710678,-38.894841,-31.888724)" transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,-38.919996,-31.872139)"
width="96" width="400"
height="48" /> height="400" />
<use <use
style="display:inline"
x="0" x="0"
y="0" y="0"
xlink:href="#use13354" xlink:href="#use4987"
id="use13374" id="use4989"
transform="matrix(0.70710678,0.70710679,-0.70710679,0.70710678,52.971072,2.0670843)" transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,52.986628,2.0890543)"
width="96" width="400"
height="48" /> height="400" />
<use <use
style="display:inline"
x="0" x="0"
y="0" y="0"
xlink:href="#use13374" xlink:href="#use4989"
id="use13394" id="use4991"
transform="matrix(0.70710678,0.70710679,-0.70710679,0.70710678,60.017834,-14.929741)" transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,60.013026,-14.912936)"
width="96" width="400"
height="48" /> height="400" />
<use <use
style="display:inline"
x="0" x="0"
y="0" y="0"
xlink:href="#use13394" xlink:href="#use4991"
id="use13414" id="use4993"
transform="matrix(0.86602541,0.50000001,-0.50000001,0.86602541,50.044124,-25.16226)" transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,67.022396,-31.859127)"
width="96" width="400"
height="48" /> height="400" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -7,127 +7,51 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65" width="65"
height="22" height="22"
id="svg2857" id="svg3273"
version="1.1" version="1.1"
inkscape:version="0.48.5 r10040" inkscape:version="0.47 r22583"
sodipodi:docname="toggle-off-us.svg"> sodipodi:docname="New document 14">
<defs <defs
id="defs2859"> id="defs3275">
<inkscape:perspective <inkscape:perspective
sodipodi:type="inkscape:persp3d" sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1" inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0" inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1" inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1" inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2865" /> id="perspective3281" />
<inkscape:perspective <inkscape:perspective
id="perspective2843" id="perspective3261"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1" inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1" inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0" inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1" inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" /> sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4"
id="linearGradient38024"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4-0"
is_visible="true" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient37802-8"
id="linearGradient12311-3-1-0-5-4"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.071426)"
x1="610.13782"
y1="501.43866"
x2="610.13782"
y2="492.52756" />
<linearGradient
id="linearGradient37802-8"
inkscape:collect="always">
<stop
id="stop37804-1"
offset="0"
style="stop-color:#2c2c2c;stop-opacity:1" />
<stop
id="stop37806-8"
offset="1"
style="stop-color:#16191a;stop-opacity:1" />
</linearGradient>
<linearGradient
y2="492.52756"
x2="610.13782"
y1="501.43866"
x1="610.13782"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-900.56122,-423.92857)"
gradientUnits="userSpaceOnUse"
id="linearGradient13602"
xlink:href="#linearGradient37802-8"
inkscape:collect="always" />
</defs> </defs>
<sodipodi:namedview <sodipodi:namedview
id="base" id="base"
pagecolor="#000000" pagecolor="#ffffff"
bordercolor="#666666" bordercolor="#666666"
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="1" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="1" inkscape:zoom="0.35"
inkscape:cx="-5.0602834" inkscape:cx="32.000004"
inkscape:cy="16.473273" inkscape:cy="10.999997"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="g37994" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
inkscape:window-width="2560" inkscape:window-width="609"
inkscape:window-height="1375" inkscape:window-height="501"
inkscape:window-x="0" inkscape:window-x="0"
inkscape:window-y="27" inkscape:window-y="26"
inkscape:window-maximized="1" inkscape:window-maximized="0" />
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="false">
<inkscape:grid
type="xygrid"
id="grid12954"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata <metadata
id="metadata2862"> id="metadata3278">
<rdf:RDF> <rdf:RDF>
<cc:Work <cc:Work
rdf:about=""> rdf:about="">
@ -142,68 +66,61 @@
inkscape:label="Layer 1" inkscape:label="Layer 1"
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1" id="layer1"
transform="translate(-444.64286,-781.36218)"> transform="translate(-343,-521.36218)">
<g <g
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)" id="g17454"
id="g37994"> transform="translate(-453,448.36218)"
style="display:inline">
<rect
transform="scale(-1,1)"
ry="4"
rx="4"
y="74.5"
x="-859.5"
height="19"
width="63.000004"
id="rect17456"
style="color:#000000;fill:none;stroke:#2e3436;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect
transform="scale(-1,1)"
ry="4"
rx="4"
y="74"
x="-828"
height="20"
width="31"
id="rect17458"
style="fill:#000000;fill-opacity:1;stroke:#5f5f5f;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline" />
<g <g
id="g37996" transform="matrix(-1,0,0,1,1619.1239,-33.986291)"
transform="translate(-115,1277)"> id="g17460"
<rect style="display:inline">
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837" <path
id="rect13475" style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
width="98" d="m 803.6322,115.48629 0,4.29495"
height="25" id="path17462"
x="644.5" inkscape:connector-curvature="0" />
y="484.61118" <path
rx="4.7429576" style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
ry="3.8424656" /> d="m 806.62805,115.48629 0,4.29495"
<rect id="path17464"
ry="3.8424656" inkscape:connector-curvature="0" />
rx="4.7429576" <path
y="483.5" style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
x="644.5" d="m 809.6239,115.48629 0,4.29495"
height="25" id="path17466"
width="98" inkscape:connector-curvature="0" />
id="rect38000"
style="color:#000000;fill:url(#linearGradient12311-3-1-0-5-4);fill-opacity:1;fill-rule:nonzero;stroke:#16191a;stroke-width:1.37920942;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
</g>
<g
transform="translate(-49.946213,-1.890275)"
id="g38002">
<g
transform="translate(-115,1247)"
style="display:inline"
id="g38004">
<rect
ry="3.7972314"
rx="4.6871223"
y="515.5"
x="694.53046"
height="25"
width="45.969578"
id="rect38006"
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
sodipodi:nodetypes="cc"
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 699.09675,516.7365 36.86904,0"
id="path38016"
inkscape:path-effect="#path-effect77541-4"
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
inkscape:connector-curvature="0" />
</g>
</g> </g>
<path <path
sodipodi:type="arc" sodipodi:type="arc"
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:2.15627193;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.96875012;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path13479" id="path18722"
sodipodi:cx="16.4375" sodipodi:cx="47.6875"
sodipodi:cy="10.8125" sodipodi:cy="11.5625"
sodipodi:rx="4.3125" sodipodi:rx="3.9375"
sodipodi:ry="4.3125" sodipodi:ry="3.9375"
d="m 20.75,10.8125 a 4.3125,4.3125 0 1 1 -8.625,0 4.3125,4.3125 0 1 1 8.625,0 z" d="m 51.625,11.5625 c 0,2.174621 -1.762879,3.9375 -3.9375,3.9375 -2.174621,0 -3.9375,-1.762879 -3.9375,-3.9375 0,-2.1746212 1.762879,-3.9375 3.9375,-3.9375 2.174621,0 3.9375,1.7628788 3.9375,3.9375 z"
transform="matrix(1.4212691,0,0,1.1514287,577.38488,1761.1138)" /> transform="matrix(1.0158729,0,0,1.0158729,795.55556,72.25399)" />
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -7,171 +7,51 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65" width="65"
height="22" height="22"
id="svg2857" id="svg3012"
version="1.1" version="1.1"
inkscape:version="0.48.5 r10040" inkscape:version="0.47 r22583"
sodipodi:docname="toggle-on-intl.svg"> sodipodi:docname="New document 6">
<defs <defs
id="defs2859"> id="defs3014">
<inkscape:perspective <inkscape:perspective
sodipodi:type="inkscape:persp3d" sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1" inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0" inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1" inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1" inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2865" /> id="perspective3020" />
<inkscape:perspective <inkscape:perspective
id="perspective2843" id="perspective2997"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1" inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1" inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0" inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1" inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" /> sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4"
id="linearGradient38024"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4"
is_visible="true" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient37802"
id="linearGradient12311-3-1-0-5"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.071426)"
x1="610.13782"
y1="501.43866"
x2="610.13782"
y2="492.52756" />
<linearGradient
id="linearGradient37802"
inkscape:collect="always">
<stop
id="stop37804"
offset="0"
style="stop-color:#2c2c2c;stop-opacity:1" />
<stop
id="stop37806"
offset="1"
style="stop-color:#16191a;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4-3"
id="linearGradient77680"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,1.0322581,717.71949,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4-3">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5-7" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0-9" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4-0"
is_visible="true" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient37802-8"
id="linearGradient12311-3-1-0-5-4"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.071426)"
x1="610.13782"
y1="501.43866"
x2="610.13782"
y2="492.52756" />
<linearGradient
id="linearGradient37802-8"
inkscape:collect="always">
<stop
id="stop37804-1"
offset="0"
style="stop-color:#2c2c2c;stop-opacity:1" />
<stop
id="stop37806-8"
offset="1"
style="stop-color:#16191a;stop-opacity:1" />
</linearGradient>
<linearGradient
y2="492.52756"
x2="610.13782"
y1="501.43866"
x1="610.13782"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-900.56122,-423.92857)"
gradientUnits="userSpaceOnUse"
id="linearGradient13602"
xlink:href="#linearGradient37802-8"
inkscape:collect="always" />
</defs> </defs>
<sodipodi:namedview <sodipodi:namedview
id="base" id="base"
pagecolor="#000000" pagecolor="#ffffff"
bordercolor="#666666" bordercolor="#666666"
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="1" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="1" inkscape:zoom="0.35"
inkscape:cx="16.760995" inkscape:cx="32.000004"
inkscape:cy="21.955673" inkscape:cy="10.999997"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="g37994" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
inkscape:window-width="2560" inkscape:window-width="609"
inkscape:window-height="1375" inkscape:window-height="501"
inkscape:window-x="0" inkscape:window-x="0"
inkscape:window-y="27" inkscape:window-y="26"
inkscape:window-maximized="1" inkscape:window-maximized="0" />
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="false">
<inkscape:grid
type="xygrid"
id="grid12954"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata <metadata
id="metadata2862"> id="metadata3017">
<rdf:RDF> <rdf:RDF>
<cc:Work <cc:Work
rdf:about=""> rdf:about="">
@ -186,70 +66,73 @@
inkscape:label="Layer 1" inkscape:label="Layer 1"
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1" id="layer1"
transform="translate(-444.64286,-781.36218)"> transform="translate(-343,-521.36218)">
<g <g
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)" id="g17454"
id="g37994"> transform="translate(-453,448.36218)"
style="display:inline">
<rect
transform="scale(-1,1)"
ry="4"
rx="4"
y="74.5"
x="-859.5"
height="19"
width="63.000004"
id="rect17456"
style="color:#000000;fill:none;stroke:#2e3436;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect
transform="scale(-1,1)"
ry="4"
rx="4"
y="74"
x="-828"
height="20"
width="31"
id="rect17458"
style="fill:#000000;fill-opacity:1;stroke:#5f5f5f;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline" />
<g <g
id="g37996" transform="matrix(-1,0,0,1,1619.1239,-33.986291)"
transform="translate(-115,1277)"> id="g17460"
<rect style="display:inline">
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837" <path
id="rect13475" style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
width="98" d="m 803.6322,115.48629 0,4.29495"
height="25" id="path17462"
x="644.5" inkscape:connector-curvature="0" />
y="484.61118" <path
rx="4.7429576" style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
ry="3.8424656" /> d="m 806.62805,115.48629 0,4.29495"
<rect id="path17464"
ry="3.8424656" inkscape:connector-curvature="0" />
rx="4.7429576" <path
y="483.5" style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
x="644.5" d="m 809.6239,115.48629 0,4.29495"
height="25" id="path17466"
width="98" inkscape:connector-curvature="0" />
id="rect38000"
style="color:#000000;fill:url(#linearGradient12311-3-1-0-5-4);fill-opacity:1;fill-rule:nonzero;stroke:#16191a;stroke-width:1.37920942;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
</g> </g>
<g <g
transform="translate(-49.946213,-1.890275)" style="font-size:8.95877075px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="g38002"> id="text17468"
<g transform="translate(0.34375,0)">
transform="translate(-115,1247)" <path
style="display:inline" d="m 837.28518,80.750726 c 0.63282,6e-6 1.19566,0.123947 1.68852,0.371824 0.49284,0.247888 0.8807,0.609505 1.16359,1.084851 0.28287,0.472439 0.42431,1.022155 0.42431,1.649149 0,0.635748 -0.13853,1.200045 -0.41556,1.692892 -0.27706,0.489934 -0.66638,0.870507 -1.16797,1.141719 -0.5016,0.271213 -1.07756,0.406819 -1.72789,0.406819 -0.42869,0 -0.83551,-0.06562 -1.22045,-0.196848 -0.38495,-0.134148 -0.73053,-0.32808 -1.03674,-0.581795 -0.30329,-0.256631 -0.54534,-0.589085 -0.72615,-0.997363 -0.17789,-0.408276 -0.26684,-0.869045 -0.26683,-1.382311 -10e-6,-0.638658 0.13997,-1.200039 0.41994,-1.684144 0.27996,-0.487011 0.66782,-0.858835 1.16359,-1.115472 0.49576,-0.259541 1.06297,-0.389315 1.70164,-0.389321 m 0.57305,1.089225 c -0.20123,-0.05249 -0.40683,-0.07873 -0.61679,-0.07874 -0.20998,5e-6 -0.41412,0.02625 -0.61242,0.07874 -0.19831,0.04958 -0.38933,0.129779 -0.57305,0.240592 -0.18081,0.107907 -0.33974,0.242055 -0.47681,0.402445 -0.13706,0.160399 -0.24642,0.358705 -0.32808,0.594918 -0.0816,0.233306 -0.12248,0.491395 -0.12248,0.774269 0,0.67366 0.20851,1.214627 0.62554,1.622903 0.41702,0.408278 0.93758,0.612416 1.56166,0.612416 0.25954,0 0.51034,-0.04229 0.7524,-0.126858 0.24496,-0.08457 0.47097,-0.20997 0.67803,-0.376198 0.20705,-0.166226 0.37328,-0.392236 0.49868,-0.678032 0.12539,-0.285792 0.18809,-0.610956 0.1881,-0.975492 -10e-6,-0.297455 -0.0437,-0.568668 -0.13123,-0.813638 -0.0875,-0.247878 -0.20415,-0.453475 -0.34995,-0.61679 -0.14291,-0.163307 -0.31059,-0.301829 -0.50306,-0.415568 -0.18956,-0.11373 -0.38641,-0.195385 -0.59054,-0.244967"
id="g38004"> style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
<rect id="path18599"
ry="3.7972314" inkscape:connector-curvature="0" />
rx="4.6871223" <path
y="515.5" d="m 843.5362,81.831203 0,1.17917 2.94834,0 0,1.014861 -2.94834,0 0,3.00713 -1.10673,0 0,-6.216022 4.31754,0 0,1.014861 -3.21081,0"
x="694.53046" style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
height="25" id="path18601"
width="45.969578" inkscape:connector-curvature="0"
id="rect38006" sodipodi:nodetypes="ccccccccccc" />
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> <path
<path d="m 849.71285,81.831203 0,1.17917 2.94834,0 0,1.014861 -2.94834,0 0,3.00713 -1.10672,0 0,-6.216022 4.31753,0 0,1.014861 -3.21081,0"
sodipodi:nodetypes="cc" style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" id="path18603"
d="m 699.09675,516.7365 36.86904,0" inkscape:connector-curvature="0"
id="path38016" sodipodi:nodetypes="ccccccccccc" />
inkscape:path-effect="#path-effect77541-4"
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
inkscape:connector-curvature="0" />
</g>
</g> </g>
<text
xml:space="preserve"
style="font-size:13.79166794px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
x="520.29974"
y="1997.0011"
id="text75614"
sodipodi:linespacing="125%"
transform="scale(1.1236771,0.88993537)"><tspan
sodipodi:role="line"
id="tspan75616"
x="520.29974"
y="1997.0011">OFF</tspan></text>
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -7,113 +7,51 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65" width="65"
height="22" height="22"
id="svg2857" id="svg3199"
version="1.1" version="1.1"
inkscape:version="0.48.5 r10040" inkscape:version="0.48.1 r9760"
sodipodi:docname="toggle-on-intl.svg"> sodipodi:docname="toggle-on-intl.svg">
<defs <defs
id="defs2859"> id="defs3201">
<inkscape:perspective <inkscape:perspective
sodipodi:type="inkscape:persp3d" sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1" inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0" inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1" inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1" inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2865" /> id="perspective3207" />
<inkscape:perspective <inkscape:perspective
id="perspective2843" id="perspective3187"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1" inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1" inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0" inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1" inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" /> sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient77461"
id="linearGradient77551"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3066667,0,0,1,-841.64667,-483)"
x1="1164.7644"
y1="962.93695"
x2="1164.7644"
y2="970.51404" />
<linearGradient
id="linearGradient77461"
inkscape:collect="always">
<stop
id="stop77463"
offset="0"
style="stop-color:#182f4c;stop-opacity:1" />
<stop
id="stop77465"
offset="1"
style="stop-color:#204a87;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4"
id="linearGradient38024"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4"
is_visible="true" />
</defs> </defs>
<sodipodi:namedview <sodipodi:namedview
id="base" id="base"
pagecolor="#000000" pagecolor="#ffffff"
bordercolor="#666666" bordercolor="#666666"
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="1" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="32" inkscape:zoom="1"
inkscape:cx="17.255148" inkscape:cx="49.147112"
inkscape:cy="8.9252639" inkscape:cy="17.532036"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="g37994" inkscape:current-layer="layer1"
showgrid="true" showgrid="false"
inkscape:window-width="2560" inkscape:window-width="1412"
inkscape:window-height="1375" inkscape:window-height="1067"
inkscape:window-x="0" inkscape:window-x="0"
inkscape:window-y="27" inkscape:window-y="26"
inkscape:window-maximized="1" inkscape:window-maximized="0" />
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="false">
<inkscape:grid
type="xygrid"
id="grid12954"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata <metadata
id="metadata2862"> id="metadata3204">
<rdf:RDF> <rdf:RDF>
<cc:Work <cc:Work
rdf:about=""> rdf:about="">
@ -128,65 +66,57 @@
inkscape:label="Layer 1" inkscape:label="Layer 1"
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1" id="layer1"
transform="translate(-444.64286,-781.36218)"> transform="translate(-342.5,-521.36218)">
<g <g
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)" style="display:inline"
id="g37994"> transform="translate(-453.5,448.36218)"
<g id="g16453">
id="g37996"
transform="translate(-115,1277)">
<rect
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837"
id="rect13475"
width="98"
height="25"
x="644.5"
y="484.61118"
rx="4.7429576"
ry="3.8424656" />
<rect
ry="3.8424656"
rx="4.7429576"
y="483.5"
x="644.5"
height="25"
width="98"
id="rect38000"
style="color:#000000;fill:url(#linearGradient77551);fill-opacity:1;fill-rule:nonzero;stroke:#182f4c;stroke-width:1.37920964;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
<g
transform="translate(2.0625,-2)"
id="g38002">
<g
transform="translate(-115,1247)"
style="display:inline"
id="g38004">
<rect
ry="3.7972314"
rx="4.6871223"
y="515.5"
x="694.53046"
height="25"
width="45.969578"
id="rect38006"
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
sodipodi:nodetypes="cc"
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 699.09675,516.7365 36.86904,0"
id="path38016"
inkscape:path-effect="#path-effect77541-4"
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
inkscape:connector-curvature="0" />
</g>
</g>
<rect <rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" style="color:#000000;fill:#4a90d9;fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:0.99999994000000003;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect13678" id="rect16256-9-4"
width="3.0646207" width="63.000004"
height="12.414008" height="19"
x="554.77728" x="-859.5"
y="1767.3566" /> y="74.5"
rx="4"
ry="4"
transform="scale(-1,1)" />
<rect
style="fill:#000000;fill-opacity:1;stroke:#5f5f5f;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
id="rect16258-5-4"
width="31"
height="20"
x="-860"
y="74"
rx="4"
ry="4"
transform="scale(-1,1)" />
<g
style="display:inline"
id="g16298-3-6"
transform="matrix(-1,0,0,1,1651.1322,-33.986291)">
<path
inkscape:connector-curvature="0"
id="path16265-3-5"
d="m 803.6322,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path16265-0-2-0"
d="m 806.62805,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
<path
inkscape:connector-curvature="0"
id="path16265-8-7-1"
d="m 809.6239,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
</g>
<path
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 16,27.9375 0,10.125"
id="path19232"
inkscape:connector-curvature="0"
transform="translate(796,51.00002)" />
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -7,14 +7,13 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65" width="65"
height="22" height="22"
id="svg2857" id="svg2857"
version="1.1" version="1.1"
inkscape:version="0.48.5 r10040" inkscape:version="0.48.1 r9760"
sodipodi:docname="toggle-on-us.svg"> sodipodi:docname="toggle-on-us.svg">
<defs <defs
id="defs2859"> id="defs2859">
@ -32,86 +31,27 @@
inkscape:vp_y="0 : 1000 : 0" inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1" inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" /> sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient77461"
id="linearGradient77551"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3066667,0,0,1,-841.64667,-483)"
x1="1164.7644"
y1="962.93695"
x2="1164.7644"
y2="970.51404" />
<linearGradient
id="linearGradient77461"
inkscape:collect="always">
<stop
id="stop77463"
offset="0"
style="stop-color:#182f4c;stop-opacity:1" />
<stop
id="stop77465"
offset="1"
style="stop-color:#204a87;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4"
id="linearGradient38024"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4"
is_visible="true" />
</defs> </defs>
<sodipodi:namedview <sodipodi:namedview
id="base" id="base"
pagecolor="#000000" pagecolor="#ffffff"
bordercolor="#666666" bordercolor="#666666"
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="1" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="1" inkscape:zoom="1"
inkscape:cx="33.380898" inkscape:cx="19.689855"
inkscape:cy="6.9658271" inkscape:cy="2.0517979"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="g37994" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
inkscape:window-width="2560" inkscape:window-width="941"
inkscape:window-height="1375" inkscape:window-height="751"
inkscape:window-x="0" inkscape:window-x="2577"
inkscape:window-y="27" inkscape:window-y="206"
inkscape:window-maximized="1" inkscape:window-maximized="0"
borderlayer="true" borderlayer="true"
inkscape:showpageshadow="false" inkscape:showpageshadow="false" />
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="false">
<inkscape:grid
type="xygrid"
id="grid12954"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata <metadata
id="metadata2862"> id="metadata2862">
<rdf:RDF> <rdf:RDF>
@ -130,68 +70,61 @@
id="layer1" id="layer1"
transform="translate(-444.64286,-781.36218)"> transform="translate(-444.64286,-781.36218)">
<g <g
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)" style="display:inline"
id="g37994"> transform="translate(-351.35714,708.36218)"
id="g16453">
<rect
style="color:#000000;fill:#4a90d9;fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:0.99999994000000003;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect16256-9-4"
width="63.000004"
height="19"
x="-859.5"
y="74.5"
rx="4"
ry="4"
transform="scale(-1,1)" />
<rect
style="fill:#000000;fill-opacity:1;stroke:#5f5f5f;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
id="rect16258-5-4"
width="31"
height="20"
x="-860"
y="74"
rx="4"
ry="4"
transform="scale(-1,1)" />
<g <g
id="g37996" style="display:inline"
transform="translate(-115,1277)"> id="g16298-3-6"
<rect transform="matrix(-1,0,0,1,1651.1322,-33.986291)">
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837" <path
id="rect13475" inkscape:connector-curvature="0"
width="98" id="path16265-3-5"
height="25" d="m 803.6322,115.48629 0,4.29495"
x="644.5" style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
y="484.61118" <path
rx="4.7429576" inkscape:connector-curvature="0"
ry="3.8424656" /> id="path16265-0-2-0"
<rect d="m 806.62805,115.48629 0,4.29495"
ry="3.8424656" style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
rx="4.7429576" <path
y="483.5" inkscape:connector-curvature="0"
x="644.5" id="path16265-8-7-1"
height="25" d="m 809.6239,115.48629 0,4.29495"
width="98" style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
id="rect38000"
style="color:#000000;fill:url(#linearGradient77551);fill-opacity:1;fill-rule:nonzero;stroke:#182f4c;stroke-width:1.37920964;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g> </g>
<g <g
transform="translate(2.0625,-2)" style="font-size:8.95877075px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="g38002"> id="text42229-3-0">
<g <path
transform="translate(-115,1247)" d="m 808.01473,80.573953 c 0.63283,6e-6 1.19567,0.123947 1.68852,0.371824 0.49284,0.247888 0.88071,0.609505 1.16359,1.084851 0.28287,0.472439 0.42431,1.022155 0.42432,1.649149 -10e-6,0.635748 -0.13853,1.200045 -0.41557,1.692892 -0.27705,0.489934 -0.66637,0.870506 -1.16796,1.141719 -0.50161,0.271212 -1.07757,0.406819 -1.72789,0.406819 -0.4287,0 -0.83552,-0.06562 -1.22046,-0.196848 -0.38495,-0.134148 -0.73053,-0.32808 -1.03673,-0.581795 -0.3033,-0.256631 -0.54535,-0.589085 -0.72615,-0.997363 -0.1779,-0.408276 -0.26684,-0.869045 -0.26684,-1.382311 0,-0.638658 0.13998,-1.200039 0.41994,-1.684144 0.27996,-0.487011 0.66782,-0.858835 1.16359,-1.115472 0.49576,-0.259541 1.06298,-0.389315 1.70164,-0.389321 m 0.57305,1.089225 c -0.20123,-0.05249 -0.40682,-0.07873 -0.61679,-0.07874 -0.20998,5e-6 -0.41411,0.02625 -0.61242,0.07874 -0.19831,0.04958 -0.38932,0.129779 -0.57304,0.240592 -0.18081,0.107907 -0.33975,0.242055 -0.47681,0.402445 -0.13707,0.160399 -0.24643,0.358705 -0.32808,0.594918 -0.0817,0.233305 -0.12249,0.491395 -0.12249,0.774269 0,0.67366 0.20851,1.214627 0.62554,1.622902 0.41703,0.408279 0.93758,0.612417 1.56166,0.612416 0.25955,10e-7 0.51035,-0.04228 0.7524,-0.126857 0.24496,-0.08457 0.47097,-0.20997 0.67803,-0.376199 0.20705,-0.166225 0.37328,-0.392236 0.49868,-0.678031 0.1254,-0.285792 0.1881,-0.610956 0.1881,-0.975492 0,-0.297455 -0.0437,-0.568668 -0.13123,-0.813638 -0.0875,-0.247878 -0.20414,-0.453475 -0.34995,-0.61679 -0.1429,-0.163307 -0.31059,-0.301829 -0.50306,-0.415568 -0.18956,-0.11373 -0.38641,-0.195385 -0.59054,-0.244967"
style="display:inline" style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="g38004"> id="path18606" />
<rect <path
ry="3.7972314" d="m 813.15903,80.639569 1.21608,0 3.4689,4.776844 0,-4.776844 1.10235,0 0,6.216022 -1.22921,0 -3.45577,-4.785594 0,4.785594 -1.10235,0 0,-6.216022"
rx="4.6871223" style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
y="515.5" id="path18608" />
x="694.53046"
height="25"
width="45.969578"
id="rect38006"
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
sodipodi:nodetypes="cc"
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 699.09675,516.7365 36.86904,0"
id="path38016"
inkscape:path-effect="#path-effect77541-4"
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
inkscape:connector-curvature="0" />
</g>
</g> </g>
<text
transform="scale(1.1000946,0.90901274)"
sodipodi:linespacing="125%"
id="text38018"
y="1955.5205"
x="495.94223"
style="font-size:13.29953671px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
xml:space="preserve"><tspan
y="1955.5205"
x="495.94223"
id="tspan38020"
sodipodi:role="line">ON</tspan></text>
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
data/wanda.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -66,7 +66,6 @@ IGNORE_HFILES= \
gactionmuxer.h \ gactionmuxer.h \
gactionobservable.h \ gactionobservable.h \
gactionobserver.h \ gactionobserver.h \
shell-network-agent.h \
shell-recorder-src.h shell-recorder-src.h
if !BUILD_RECORDER if !BUILD_RECORDER
@ -113,7 +112,7 @@ expand_content_files=
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=$(GNOME_SHELL_CFLAGS) GTKDOC_CFLAGS=$(GNOME_SHELL_CFLAGS)
GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(top_builddir)/src/libgnome-shell-menu.la $(top_builddir)/src/libgnome-shell-base.la $(top_builddir)/src/libgnome-shell.la GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(BLUETOOTH_LIBS) $(top_builddir)/src/libgnome-shell.la
# This includes the standard gtk-doc make rules, copied by gtkdocize. # This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make include $(top_srcdir)/gtk-doc.make

View File

@ -17,6 +17,7 @@
<chapter> <chapter>
<title>Actors</title> <title>Actors</title>
<xi:include href="xml/shell-generic-container.xml"/> <xi:include href="xml/shell-generic-container.xml"/>
<xi:include href="xml/shell-slicer.xml"/>
<xi:include href="xml/shell-stack.xml"/> <xi:include href="xml/shell-stack.xml"/>
</chapter> </chapter>
<chapter> <chapter>
@ -45,10 +46,11 @@
<xi:include href="doc-gen-org.gnome.Shell.SearchProvider.xml"/> <xi:include href="doc-gen-org.gnome.Shell.SearchProvider.xml"/>
<xi:include href="doc-gen-org.gnome.Shell.SearchProvider2.xml"/> <xi:include href="doc-gen-org.gnome.Shell.SearchProvider2.xml"/>
<xi:include href="xml/shell-global.xml"/> <xi:include href="xml/shell-global.xml"/>
<xi:include href="xml/shell-action-modes.xml"/>
<xi:include href="xml/shell-wm.xml"/> <xi:include href="xml/shell-wm.xml"/>
<xi:include href="xml/shell-xfixes-cursor.xml"/>
<xi:include href="xml/shell-util.xml"/> <xi:include href="xml/shell-util.xml"/>
<xi:include href="xml/shell-mount-operation.xml"/> <xi:include href="xml/shell-mount-operation.xml"/>
<xi:include href="xml/shell-network-agent.xml"/>
<xi:include href="xml/shell-polkit-authentication-agent.xml"/> <xi:include href="xml/shell-polkit-authentication-agent.xml"/>
<xi:include href="xml/shell-tp-client.xml"/> <xi:include href="xml/shell-tp-client.xml"/>
</chapter> </chapter>

View File

@ -17,19 +17,19 @@ packages. If you are interested in building GNOME Shell from source,
we would recommend building from version control using the build we would recommend building from version control using the build
script described at: script described at:
https://wiki.gnome.org/Projects/GnomeShell http://live.gnome.org/GnomeShell
Not only will that give you the very latest version of this rapidly Not only will that give you the very latest version of this rapidly
changing project, it will be much easier than get GNOME Shell and changing project, it will be much easier than get GNOME Shell and
its dependencies to build from tarballs.</description> its dependencies to build from tarballs.</description>
<homepage rdf:resource="https://wiki.gnome.org/Projects/GnomeShell" /> <!--
<homepage rdf:resource="http://live.gnome.org/GnomeShell" />
-->
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" /> <mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" />
<download-page rdf:resource="http://download.gnome.org/sources/gnome-shell/" /> <download-page rdf:resource="http://download.gnome.org/sources/gnome-shell/" />
<bug-database rdf:resource="https://bugzilla.gnome.org/browse.cgi?product=gnome-shell" /> <bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=gnome-shell" />
<category rdf:resource="http://api.gnome.org/doap-extensions#core" /> <category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
<programming-language>JavaScript</programming-language>
<programming-language>C</programming-language>
<maintainer> <maintainer>
<foaf:Person> <foaf:Person>

View File

@ -1,38 +1,116 @@
NULL = NULL =
BUILT_SOURCES =
EXTRA_DIST = misc/config.js.in
CLEANFILES = misc/config.js
misc/config.js: misc/config.js.in Makefile misc/config.js: misc/config.js.in Makefile
[ -d $(@D) ] || $(mkdir_p) $(@D) ; \ [ -d $(@D) ] || $(mkdir_p) $(@D) ; \
sed -e "s|[@]PACKAGE_NAME@|$(PACKAGE_NAME)|g" \ sed -e "s|[@]PACKAGE_NAME@|$(PACKAGE_NAME)|g" \
-e "s|[@]PACKAGE_VERSION@|$(PACKAGE_VERSION)|g" \ -e "s|[@]PACKAGE_VERSION@|$(PACKAGE_VERSION)|g" \
-e "s|[@]HAVE_BLUETOOTH@|$(HAVE_BLUETOOTH)|g" \ -e "s|[@]HAVE_BLUETOOTH@|$(HAVE_BLUETOOTH)|g" \
-e "s|[@]HAVE_NETWORKMANAGER@|$(HAVE_NETWORKMANAGER)|g" \
-e "s|[@]GETTEXT_PACKAGE@|$(GETTEXT_PACKAGE)|g" \ -e "s|[@]GETTEXT_PACKAGE@|$(GETTEXT_PACKAGE)|g" \
-e "s|[@]datadir@|$(datadir)|g" \ -e "s|[@]datadir@|$(datadir)|g" \
-e "s|[@]libexecdir@|$(libexecdir)|g" \ -e "s|[@]libexecdir@|$(libexecdir)|g" \
-e "s|[@]sysconfdir@|$(sysconfdir)|g" \ -e "s|[@]sysconfdir@|$(sysconfdir)|g" \
$< > $@ $< > $@
js_resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --sourcedir=$(builddir) --generate-dependencies $(srcdir)/js-resources.gresource.xml) jsdir = $(pkgdatadir)/js
js-resources.h: js-resources.gresource.xml $(js_resource_files) misc/config.js
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --sourcedir=$(builddir) --generate --c-name shell_js_resources $<
js-resources.c: js-resources.gresource.xml $(js_resource_files) misc/config.js
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --sourcedir=$(builddir) --generate --c-name shell_js_resources $<
js_built_sources = js-resources.c js-resources.h nobase_dist_js_DATA = \
gdm/batch.js \
BUILT_SOURCES += $(js_built_sources) gdm/fingerprint.js \
gdm/loginDialog.js \
all-local: $(js_built_sources) gdm/powerMenu.js \
gdm/realmd.js \
js_resource_dist_files = $(filter-out misc/config.js, $(js_resource_files)) gdm/util.js \
extensionPrefs/main.js \
EXTRA_DIST = \ misc/config.js \
$(js_resource_dist_files) \ misc/extensionUtils.js \
js-resources.gresource.xml \ misc/fileUtils.js \
misc/config.js.in \ misc/gnomeSession.js \
$(NULL) misc/hash.js \
misc/history.js \
CLEANFILES = \ misc/jsParse.js \
$(js_built_sources) \ misc/loginManager.js \
misc/modemManager.js \
misc/params.js \
misc/util.js \
perf/core.js \
ui/altTab.js \
ui/appDisplay.js \
ui/appFavorites.js \
ui/backgroundMenu.js \
ui/background.js \
ui/boxpointer.js \
ui/calendar.js \
ui/checkBox.js \
ui/ctrlAltTab.js \
ui/dash.js \
ui/dateMenu.js \
ui/dnd.js \
ui/endSessionDialog.js \
ui/extensionSystem.js \
ui/extensionDownloader.js \
ui/environment.js \
ui/ibusCandidatePopup.js\
ui/grabHelper.js \
ui/iconGrid.js \
ui/keyboard.js \
ui/layout.js \
ui/lightbox.js \
ui/lookingGlass.js \
ui/magnifier.js \
ui/magnifierDBus.js \
ui/main.js \
ui/messageTray.js \
ui/modalDialog.js \
ui/separator.js \
ui/sessionMode.js \
ui/shellEntry.js \
ui/shellMountOperation.js \
ui/notificationDaemon.js \
ui/osdWindow.js \
ui/overview.js \
ui/overviewControls.js \
ui/panel.js \
ui/panelMenu.js \
ui/pointerWatcher.js \
ui/popupMenu.js \
ui/remoteSearch.js \
ui/runDialog.js \
ui/screenshot.js \
ui/screenShield.js \
ui/scripting.js \
ui/search.js \
ui/searchDisplay.js \
ui/shellDBus.js \
ui/status/accessibility.js \
ui/status/keyboard.js \
ui/status/lockScreenMenu.js \
ui/status/network.js \
ui/status/power.js \
ui/status/volume.js \
ui/status/bluetooth.js \
ui/switcherPopup.js \
ui/tweener.js \
ui/unlockDialog.js \
ui/userMenu.js \
ui/userWidget.js \
ui/viewSelector.js \
ui/wanda.js \
ui/windowAttentionHandler.js \
ui/windowManager.js \
ui/workspace.js \
ui/workspaceThumbnail.js \
ui/workspacesView.js \
ui/workspaceSwitcherPopup.js \
ui/xdndHandler.js \
ui/components/__init__.js \
ui/components/autorunManager.js \
ui/components/automountManager.js \
ui/components/networkAgent.js \
ui/components/polkitAgent.js \
ui/components/recorder.js \
ui/components/telepathyClient.js \
ui/components/keyring.js \
$(NULL) $(NULL)

View File

@ -13,20 +13,13 @@ const _ = Gettext.gettext;
const Config = imports.misc.config; const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const GnomeShellIface = '<node> \ const GnomeShellIface = <interface name="org.gnome.Shell.Extensions">
<interface name="org.gnome.Shell.Extensions"> \ <signal name="ExtensionStatusChanged">
<signal name="ExtensionStatusChanged"> \ <arg type="s" name="uuid"/>
<arg type="s" name="uuid"/> \ <arg type="i" name="state"/>
<arg type="i" name="state"/> \ <arg type="s" name="error"/>
<arg type="s" name="error"/> \ </signal>
</signal> \ </interface>;
</interface> \
</node>';
const customCss = '.prefs-button { \
padding: 8px; \
border-radius: 20px; \
}';
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface); const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
@ -51,10 +44,13 @@ const Application = new Lang.Class({
this._extensionPrefsModules = {}; this._extensionPrefsModules = {};
this._extensionIters = {};
this._startupUuid = null; this._startupUuid = null;
this._loaded = false; },
this._skipMainWindow = false;
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' }); _buildModel: function() {
this._model = new Gtk.ListStore();
this._model.set_column_types([GObject.TYPE_STRING, GObject.TYPE_STRING]);
}, },
_extensionAvailable: function(uuid) { _extensionAvailable: function(uuid) {
@ -63,12 +59,20 @@ const Application = new Lang.Class({
if (!extension) if (!extension)
return false; return false;
if (ExtensionUtils.isOutOfDate(extension))
return false;
if (!extension.dir.get_child('prefs.js').query_exists(null)) if (!extension.dir.get_child('prefs.js').query_exists(null))
return false; return false;
return true; return true;
}, },
_setExtensionInsensitive: function(layout, cell, model, iter, data) {
let uuid = model.get_value(iter, 0);
cell.set_sensitive(this._extensionAvailable(uuid));
},
_getExtensionPrefsModule: function(extension) { _getExtensionPrefsModule: function(extension) {
let uuid = extension.metadata.uuid; let uuid = extension.metadata.uuid;
@ -98,23 +102,21 @@ const Application = new Lang.Class({
widget = this._buildErrorUI(extension, e); widget = this._buildErrorUI(extension, e);
} }
let dialog = new Gtk.Dialog({ use_header_bar: true, // Destroy the current prefs widget, if it exists
modal: true, if (this._extensionPrefsBin.get_child())
title: extension.metadata.name }); this._extensionPrefsBin.get_child().destroy();
if (this._skipMainWindow) { this._extensionPrefsBin.add(widget);
this.application.add_window(dialog); this._extensionSelector.set_active_iter(this._extensionIters[uuid]);
if (this._window) },
this._window.destroy();
this._window = dialog;
this._window.window_position = Gtk.WindowPosition.CENTER;
} else {
dialog.transient_for = this._window;
}
dialog.set_default_size(600, 400); _extensionSelected: function() {
dialog.get_content_area().add(widget); let [success, iter] = this._extensionSelector.get_active_iter();
dialog.show(); if (!success)
return;
let uuid = this._model.get_value(iter, 0);
this._selectExtension(uuid);
}, },
_buildErrorUI: function(extension, exc) { _buildErrorUI: function(extension, exc) {
@ -147,26 +149,48 @@ const Application = new Lang.Class({
_buildUI: function(app) { _buildUI: function(app) {
this._window = new Gtk.ApplicationWindow({ application: app, this._window = new Gtk.ApplicationWindow({ application: app,
window_position: Gtk.WindowPosition.CENTER }); window_position: Gtk.WindowPosition.CENTER,
title: _("GNOME Shell Extension Preferences") });
this._window.set_size_request(800, 500); this._window.set_size_request(600, 400);
this._titlebar = new Gtk.HeaderBar({ show_close_button: true, let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
title: _("GNOME Shell Extensions") }); this._window.add(vbox);
this._window.set_titlebar(this._titlebar);
let scroll = new Gtk.ScrolledWindow({ hscrollbar_policy: Gtk.PolicyType.NEVER, let toolbar = new Gtk.Toolbar();
shadow_type: Gtk.ShadowType.IN, toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR);
halign: Gtk.Align.CENTER, vbox.add(toolbar);
margin: 18 }); let toolitem;
this._window.add(scroll);
this._extensionSelector = new Gtk.ListBox({ selection_mode: Gtk.SelectionMode.NONE }); let label = new Gtk.Label({ label: '<b>' + _("Extension") + '</b>',
this._extensionSelector.set_sort_func(Lang.bind(this, this._sortList)); use_markup: true });
this._extensionSelector.set_header_func(Lang.bind(this, this._updateHeader)); toolitem = new Gtk.ToolItem({ child: label });
toolbar.add(toolitem);
scroll.add(this._extensionSelector); this._extensionSelector = new Gtk.ComboBox({ model: this._model,
margin_left: 8,
hexpand: true });
this._extensionSelector.get_style_context().add_class(Gtk.STYLE_CLASS_RAISED);
let renderer = new Gtk.CellRendererText();
this._extensionSelector.pack_start(renderer, true);
this._extensionSelector.add_attribute(renderer, 'text', 1);
this._extensionSelector.set_cell_data_func(renderer, Lang.bind(this, this._setExtensionInsensitive));
this._extensionSelector.connect('changed', Lang.bind(this, this._extensionSelected));
toolitem = new Gtk.ToolItem({ child: this._extensionSelector });
toolitem.set_expand(true);
toolbar.add(toolitem);
this._extensionPrefsBin = new Gtk.Frame();
vbox.add(this._extensionPrefsBin);
let label = new Gtk.Label({
label: _("Select an extension to configure using the combobox above."),
vexpand: true
});
this._extensionPrefsBin.add(label);
this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell'); this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell');
this._shellProxy.connectSignal('ExtensionStatusChanged', Lang.bind(this, function(proxy, senderName, [uuid, state, error]) { this._shellProxy.connectSignal('ExtensionStatusChanged', Lang.bind(this, function(proxy, senderName, [uuid, state, error]) {
@ -177,61 +201,23 @@ const Application = new Lang.Class({
this._window.show_all(); this._window.show_all();
}, },
_addCustomStyle: function() {
let provider = new Gtk.CssProvider();
try {
provider.load_from_data(customCss, -1);
} catch(e) {
log('Failed to add application style');
return;
}
let screen = this._window.window.get_screen();
let priority = Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION;
Gtk.StyleContext.add_provider_for_screen(screen, provider, priority);
},
_sortList: function(row1, row2) {
let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name;
let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name;
return name1.localeCompare(name2);
},
_updateHeader: function(row, before) {
if (!before || row.get_header())
return;
let sep = new Gtk.Separator({ orientation: Gtk.Orientation.HORIZONTAL });
row.set_header(sep);
},
_scanExtensions: function() { _scanExtensions: function() {
let finder = new ExtensionUtils.ExtensionFinder(); let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', Lang.bind(this, this._extensionFound)); finder.connect('extension-found', Lang.bind(this, this._extensionFound));
finder.connect('extensions-loaded', Lang.bind(this, this._extensionsLoaded));
finder.scanExtensions(); finder.scanExtensions();
this._extensionsLoaded();
}, },
_extensionFound: function(finder, extension) { _extensionFound: function(signals, extension) {
let row = new ExtensionRow(extension.uuid); let iter = this._model.append();
this._model.set(iter, [0, 1], [extension.uuid, extension.metadata.name]);
row.prefsButton.visible = this._extensionAvailable(row.uuid); this._extensionIters[extension.uuid] = iter;
row.prefsButton.connect('clicked', Lang.bind(this,
function() {
this._selectExtension(row.uuid);
}));
row.show_all();
this._extensionSelector.add(row);
}, },
_extensionsLoaded: function() { _extensionsLoaded: function() {
if (this._startupUuid && this._extensionAvailable(this._startupUuid)) if (this._startupUuid && this._extensionAvailable(this._startupUuid))
this._selectExtension(this._startupUuid); this._selectExtension(this._startupUuid);
this._startupUuid = null; this._startupUuid = null;
this._skipMainWindow = false;
this._loaded = true;
}, },
_onActivate: function() { _onActivate: function() {
@ -239,137 +225,29 @@ const Application = new Lang.Class({
}, },
_onStartup: function(app) { _onStartup: function(app) {
this._buildModel();
this._buildUI(app); this._buildUI(app);
this._addCustomStyle();
this._scanExtensions(); this._scanExtensions();
}, },
_onCommandLine: function(app, commandLine) { _onCommandLine: function(app, commandLine) {
app.activate(); app.activate();
let args = commandLine.get_arguments(); let args = commandLine.get_arguments();
if (args.length) { if (args.length) {
let uuid = args[0]; let uuid = args[0];
this._skipMainWindow = true;
// Strip off "extension:///" prefix which fakes a URI, if it exists // Strip off "extension:///" prefix which fakes a URI, if it exists
uuid = stripPrefix(uuid, "extension:///"); uuid = stripPrefix(uuid, "extension:///");
if (this._extensionAvailable(uuid)) if (this._extensionAvailable(uuid))
this._selectExtension(uuid); this._selectExtension(uuid);
else if (!this._loaded)
this._startupUuid = uuid;
else else
this._skipMainWindow = false; this._startupUuid = uuid;
} }
return 0; return 0;
} }
}); });
const ExtensionRow = new Lang.Class({
Name: 'ExtensionRow',
Extends: Gtk.ListBoxRow,
_init: function(uuid) {
this.parent();
this.uuid = uuid;
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
this._settings.connect('changed::enabled-extensions', Lang.bind(this,
function() {
this._switch.state = this._isEnabled();
}));
this._settings.connect('changed::disable-extension-version-validation',
Lang.bind(this, function() {
this._switch.sensitive = this._canEnable();
}));
this._buildUI();
},
_buildUI: function() {
let extension = ExtensionUtils.extensions[this.uuid];
let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL,
hexpand: true, margin: 12, spacing: 6 });
this.add(hbox);
let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL,
spacing: 6, hexpand: true });
hbox.add(vbox);
let name = GLib.markup_escape_text(extension.metadata.name, -1);
let label = new Gtk.Label({ label: '<b>' + name + '</b>',
use_markup: true,
halign: Gtk.Align.START });
vbox.add(label);
let desc = extension.metadata.description.split('\n')[0];
label = new Gtk.Label({ label: desc,
ellipsize: Pango.EllipsizeMode.END,
halign: Gtk.Align.START });
vbox.add(label);
let button = new Gtk.Button({ valign: Gtk.Align.CENTER,
no_show_all: true });
button.add(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
icon_size: Gtk.IconSize.BUTTON,
visible: true }));
button.get_style_context().add_class('prefs-button');
hbox.add(button);
this.prefsButton = button;
this._switch = new Gtk.Switch({ valign: Gtk.Align.CENTER,
sensitive: this._canEnable(),
state: this._isEnabled() });
this._switch.connect('notify::active', Lang.bind(this,
function() {
if (this._switch.active)
this._enable();
else
this._disable();
}));
this._switch.connect('state-set', function() { return true; });
hbox.add(this._switch);
},
_canEnable: function() {
let extension = ExtensionUtils.extensions[this.uuid];
let checkVersion = !this._settings.get_boolean('disable-extension-version-validation');
return !(checkVersion && ExtensionUtils.isOutOfDate(extension));
},
_isEnabled: function() {
let extensions = this._settings.get_strv('enabled-extensions');
return extensions.indexOf(this.uuid) != -1;
},
_enable: function() {
let extensions = this._settings.get_strv('enabled-extensions');
if (extensions.indexOf(this.uuid) != -1)
return;
extensions.push(this.uuid);
this._settings.set_strv('enabled-extensions', extensions);
},
_disable: function() {
let extensions = this._settings.get_strv('enabled-extensions');
let pos = extensions.indexOf(this.uuid);
if (pos == -1)
return;
do {
extensions.splice(pos, 1);
pos = extensions.indexOf(this.uuid);
} while (pos != -1);
this._settings.set_strv('enabled-extensions', extensions);
}
});
function initEnvironment() { function initEnvironment() {
// Monkey-patch in a "global" object that fakes some Shell utilities // Monkey-patch in a "global" object that fakes some Shell utilities
// that ExtensionUtils depends on. // that ExtensionUtils depends on.

View File

@ -1,512 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Signals = imports.signals;
const St = imports.gi.St;
const Animation = imports.ui.animation;
const Batch = imports.gdm.batch;
const GdmUtil = imports.gdm.util;
const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget;
const DEFAULT_BUTTON_WELL_ICON_SIZE = 24;
const DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1.0;
const DEFAULT_BUTTON_WELL_ANIMATION_TIME = 0.3;
const MESSAGE_FADE_OUT_ANIMATION_TIME = 0.5;
const AuthPromptMode = {
UNLOCK_ONLY: 0,
UNLOCK_OR_LOG_IN: 1
};
const AuthPromptStatus = {
NOT_VERIFYING: 0,
VERIFYING: 1,
VERIFICATION_FAILED: 2,
VERIFICATION_SUCCEEDED: 3
};
const BeginRequestType = {
PROVIDE_USERNAME: 0,
DONT_PROVIDE_USERNAME: 1
};
const AuthPrompt = new Lang.Class({
Name: 'AuthPrompt',
_init: function(gdmClient, mode) {
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this._gdmClient = gdmClient;
this._mode = mode;
let reauthenticationOnly;
if (this._mode == AuthPromptMode.UNLOCK_ONLY)
reauthenticationOnly = true;
else if (this._mode == AuthPromptMode.UNLOCK_OR_LOG_IN)
reauthenticationOnly = false;
this._userVerifier = new GdmUtil.ShellUserVerifier(this._gdmClient, { reauthenticationOnly: reauthenticationOnly });
this._userVerifier.connect('ask-question', Lang.bind(this, this._onAskQuestion));
this._userVerifier.connect('show-message', Lang.bind(this, this._onShowMessage));
this._userVerifier.connect('verification-failed', Lang.bind(this, this._onVerificationFailed));
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() {
this.updateSensitivity(false);
this.startSpinning();
if (this._queryingService) {
this._userVerifier.answerQuery(this._queryingService, this._entry.text);
} else {
this._preemptiveAnswer = this._entry.text;
}
}));
this.actor = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
vertical: true });
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this.actor.connect('key-press-event',
Lang.bind(this, function(actor, event) {
if (event.get_key_symbol() == Clutter.KEY_Escape) {
this.cancel();
}
return Clutter.EVENT_PROPAGATE;
}));
this._userWell = new St.Bin({ x_fill: true,
x_align: St.Align.START });
this.actor.add(this._userWell,
{ x_align: St.Align.START,
x_fill: true,
y_fill: true,
expand: true });
this._label = new St.Label({ style_class: 'login-dialog-prompt-label' });
this.actor.add(this._label,
{ expand: true,
x_fill: false,
y_fill: true,
x_align: St.Align.START });
this._entry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
can_focus: true });
ShellEntry.addContextMenu(this._entry, { isPassword: true });
this.actor.add(this._entry,
{ expand: true,
x_fill: true,
y_fill: false,
x_align: St.Align.START });
this._entry.grab_key_focus();
this._message = new St.Label({ opacity: 0,
styleClass: 'login-dialog-message' });
this._message.clutter_text.line_wrap = true;
this.actor.add(this._message, { x_fill: false, x_align: St.Align.START, y_align: St.Align.START });
this._buttonBox = new St.BoxLayout({ style_class: 'login-dialog-button-box',
vertical: false });
this.actor.add(this._buttonBox,
{ expand: true,
x_align: St.Align.MIDDLE,
y_align: St.Align.END });
this._defaultButtonWell = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._defaultButtonWellActor = null;
this._initButtons();
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
this._spinner = new Animation.AnimatedIcon(spinnerIcon, DEFAULT_BUTTON_WELL_ICON_SIZE);
this._spinner.actor.opacity = 0;
this._spinner.actor.show();
this._defaultButtonWell.add_child(this._spinner.actor);
},
_onDestroy: function() {
this._userVerifier.destroy();
this._userVerifier = null;
},
_initButtons: function() {
this.cancelButton = new St.Button({ style_class: 'modal-dialog-button button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true,
can_focus: true,
label: _("Cancel") });
this.cancelButton.connect('clicked',
Lang.bind(this, function() {
this.cancel();
}));
this._buttonBox.add(this.cancelButton,
{ expand: false,
x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.END });
this._buttonBox.add(this._defaultButtonWell,
{ expand: true,
x_fill: false,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
this.nextButton = new St.Button({ style_class: 'modal-dialog-button button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true,
can_focus: true,
label: _("Next") });
this.nextButton.connect('clicked',
Lang.bind(this, function() {
this.emit('next');
}));
this.nextButton.add_style_pseudo_class('default');
this._buttonBox.add(this.nextButton,
{ expand: false,
x_fill: false,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.END });
this._updateNextButtonSensitivity(this._entry.text.length > 0);
this._entry.clutter_text.connect('text-changed',
Lang.bind(this, function() {
if (!this._userVerifier.hasPendingMessages)
this._fadeOutMessage();
this._updateNextButtonSensitivity(this._entry.text.length > 0);
}));
this._entry.clutter_text.connect('activate', Lang.bind(this, function() {
this.emit('next');
}));
},
_onAskQuestion: function(verifier, serviceName, question, passwordChar) {
if (this._preemptiveAnswer) {
if (this._queryingService)
this._userVerifier.answerQuery(this._queryingService, this._preemptiveAnswer);
this._preemptiveAnswer = null;
return;
}
if (this._queryingService)
this.clear();
this._queryingService = serviceName;
this.setPasswordChar(passwordChar);
this.setQuestion(question);
if (passwordChar) {
if (this._userVerifier.reauthenticating)
this.nextButton.label = _("Unlock");
else
this.nextButton.label = C_("button", "Sign In");
} else {
this.nextButton.label = _("Next");
}
this.updateSensitivity(true);
this.emit('prompted');
},
_onOVirtUserAuthenticated: function() {
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
this.reset();
},
_onSmartcardStatusChanged: function() {
this.smartcardDetected = this._userVerifier.smartcardDetected;
// Most of the time we want to reset if the user inserts or removes
// a smartcard. Smartcard insertion "preempts" what the user was
// doing, and smartcard removal aborts the preemption.
// The exceptions are: 1) Don't reset on smartcard insertion if we're already verifying
// with a smartcard
// 2) Don't reset if we've already succeeded at verification and
// the user is getting logged in.
if (this._userVerifier.serviceIsDefault(GdmUtil.SMARTCARD_SERVICE_NAME) &&
this.verificationStatus == AuthPromptStatus.VERIFYING &&
this.smartcardDetected)
return;
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
this.reset();
},
_onShowMessage: function(userVerifier, message, type) {
this.setMessage(message, type);
this.emit('prompted');
},
_onVerificationFailed: function() {
this._queryingService = null;
this.clear();
this.updateSensitivity(true);
this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
},
_onVerificationComplete: function() {
this.verificationStatus = AuthPromptStatus.VERIFICATION_SUCCEEDED;
this.cancelButton.reactive = false;
},
_onReset: function() {
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this.reset();
},
addActorToDefaultButtonWell: function(actor) {
this._defaultButtonWell.add_child(actor);
},
setActorInDefaultButtonWell: function(actor, animate) {
if (!this._defaultButtonWellActor &&
!actor)
return;
let oldActor = this._defaultButtonWellActor;
if (oldActor)
Tweener.removeTweens(oldActor);
let isSpinner;
if (actor == this._spinner.actor)
isSpinner = true;
else
isSpinner = false;
if (this._defaultButtonWellActor != actor && oldActor) {
if (!animate) {
oldActor.opacity = 0;
} else {
Tweener.addTween(oldActor,
{ opacity: 0,
time: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
transition: 'linear',
onCompleteScope: this,
onComplete: function() {
if (isSpinner) {
if (this._spinner)
this._spinner.stop();
}
}
});
}
}
if (actor) {
if (isSpinner)
this._spinner.play();
if (!animate)
actor.opacity = 255;
else
Tweener.addTween(actor,
{ opacity: 255,
time: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
transition: 'linear' });
}
this._defaultButtonWellActor = actor;
},
startSpinning: function() {
this.setActorInDefaultButtonWell(this._spinner.actor, true);
},
stopSpinning: function() {
this.setActorInDefaultButtonWell(null, false);
},
clear: function() {
this._entry.text = '';
this.stopSpinning();
},
setPasswordChar: function(passwordChar) {
this._entry.clutter_text.set_password_char(passwordChar);
this._entry.menu.isPassword = passwordChar != '';
},
setQuestion: function(question) {
this._label.set_text(question);
this._label.show();
this._entry.show();
this._entry.grab_key_focus();
},
getAnswer: function() {
let text;
if (this._preemptiveAnswer) {
text = this._preemptiveAnswer;
this._preemptiveAnswer = null;
} else {
text = this._entry.get_text();
}
return text;
},
_fadeOutMessage: function() {
if (this._message.opacity == 0)
return;
Tweener.removeTweens(this._message);
Tweener.addTween(this._message,
{ opacity: 0,
time: MESSAGE_FADE_OUT_ANIMATION_TIME,
transition: 'easeOutQuad'
});
},
setMessage: function(message, type) {
if (type == GdmUtil.MessageType.ERROR)
this._message.add_style_class_name('login-dialog-message-warning');
else
this._message.remove_style_class_name('login-dialog-message-warning');
if (type == GdmUtil.MessageType.HINT)
this._message.add_style_class_name('login-dialog-message-hint');
else
this._message.remove_style_class_name('login-dialog-message-hint');
if (message) {
Tweener.removeTweens(this._message);
this._message.text = message;
this._message.opacity = 255;
} else {
this._message.opacity = 0;
}
},
_updateNextButtonSensitivity: function(sensitive) {
this.nextButton.reactive = sensitive;
this.nextButton.can_focus = sensitive;
},
updateSensitivity: function(sensitive) {
this._updateNextButtonSensitivity(sensitive);
this._entry.reactive = sensitive;
this._entry.clutter_text.editable = sensitive;
},
hide: function() {
this.setActorInDefaultButtonWell(null, true);
this.actor.hide();
this._message.opacity = 0;
this.setUser(null);
this.updateSensitivity(true);
this._entry.set_text('');
},
setUser: function(user) {
let oldChild = this._userWell.get_child();
if (oldChild)
oldChild.destroy();
if (user) {
let userWidget = new UserWidget.UserWidget(user);
this._userWell.set_child(userWidget.actor);
}
},
reset: function() {
let oldStatus = this.verificationStatus;
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this.cancelButton.reactive = true;
if (oldStatus == AuthPromptStatus.VERIFYING)
this._userVerifier.cancel();
this._queryingService = null;
this.clear();
this._message.opacity = 0;
this.setUser(null);
this.stopSpinning();
if (oldStatus == AuthPromptStatus.VERIFICATION_FAILED)
this.emit('failed');
let beginRequestType;
if (this._mode == AuthPromptMode.UNLOCK_ONLY) {
// 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._userVerifier.serviceIsForeground(GdmUtil.OVIRT_SERVICE_NAME) ||
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 or with preauthenticated oVirt credentials
beginRequestType = BeginRequestType.DONT_PROVIDE_USERNAME;
} else {
// In all other cases, we should get the username up front.
beginRequestType = BeginRequestType.PROVIDE_USERNAME;
}
this.emit('reset', beginRequestType);
},
addCharacter: function(unichar) {
if (!this._entry.visible)
return;
this._entry.grab_key_focus();
this._entry.clutter_text.insert_unichar(unichar);
},
begin: function(params) {
params = Params.parse(params, { userName: null,
hold: null });
this.updateSensitivity(false);
let hold = params.hold;
if (!hold)
hold = new Batch.Hold();
this._userVerifier.begin(params.userName, hold);
this.verificationStatus = AuthPromptStatus.VERIFYING;
},
finish: function(onComplete) {
if (!this._userVerifier.hasPendingMessages) {
onComplete();
return;
}
let signalId = this._userVerifier.connect('no-more-messages',
Lang.bind(this, function() {
this._userVerifier.disconnect(signalId);
onComplete();
}));
},
cancel: function() {
if (this.verificationStatus == AuthPromptStatus.NOT_VERIFYING || this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED) {
return;
}
this.reset();
this.emit('cancelled');
}
});
Signals.addSignalMethods(AuthPrompt.prototype);

View File

@ -13,7 +13,9 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/ */
const Lang = imports.lang; const Lang = imports.lang;

View File

@ -5,13 +5,11 @@ const Lang = imports.lang;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const FprintManagerIface = '<node> \ const FprintManagerIface = <interface name='net.reactivated.Fprint.Manager'>
<interface name="net.reactivated.Fprint.Manager"> \ <method name='GetDefaultDevice'>
<method name="GetDefaultDevice"> \ <arg type='o' direction='out' />
<arg type="o" direction="out" /> \ </method>
</method> \ </interface>;
</interface> \
</node>';
const FprintManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(FprintManagerIface); const FprintManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(FprintManagerIface);

File diff suppressed because it is too large Load Diff

View File

@ -1,64 +0,0 @@
// -*- 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;
}

129
js/gdm/powerMenu.js Normal file
View File

@ -0,0 +1,129 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/*
* Copyright 2011 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const LoginManager = imports.misc.loginManager;
const GdmUtil = imports.gdm.util;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const PowerMenuButton = new Lang.Class({
Name: 'PowerMenuButton',
Extends: PanelMenu.SystemStatusButton,
_init: function() {
/* Translators: accessible name of the power menu in the login screen */
this.parent('system-shutdown-symbolic', _("Power"));
this._loginManager = LoginManager.getLoginManager();
this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
this._settings.connect('changed::disable-restart-buttons',
Lang.bind(this, this._updateVisibility));
this._createSubMenu();
// ConsoleKit doesn't send notifications when shutdown/reboot
// are disabled, so we update the menu item each time the menu opens
this.menu.connect('open-state-changed', Lang.bind(this,
function(menu, open) {
if (open) {
this._updateHaveShutdown();
this._updateHaveRestart();
this._updateHaveSuspend();
}
}));
this._updateHaveShutdown();
this._updateHaveRestart();
this._updateHaveSuspend();
},
_updateVisibility: function() {
let shouldBeVisible = (this._haveSuspend || this._haveShutdown || this._haveRestart);
this.actor.visible = shouldBeVisible && !this._settings.get_boolean('disable-restart-buttons');
},
_updateHaveShutdown: function() {
this._loginManager.canPowerOff(Lang.bind(this, function(result) {
this._haveShutdown = result;
this._powerOffItem.actor.visible = this._haveShutdown;
this._updateVisibility();
}));
},
_updateHaveRestart: function() {
this._loginManager.canReboot(Lang.bind(this, function(result) {
this._haveRestart = result;
this._restartItem.actor.visible = this._haveRestart;
this._updateVisibility();
}));
},
_updateHaveSuspend: function() {
this._loginManager.canSuspend(Lang.bind(this, function(result) {
this._haveSuspend = result;
this._suspendItem.actor.visible = this._haveSuspend;
this._updateVisibility();
}));
},
_createSubMenu: function() {
let item;
item = new PopupMenu.PopupMenuItem(_("Suspend"));
item.connect('activate', Lang.bind(this, this._onActivateSuspend));
this.menu.addMenuItem(item);
this._suspendItem = item;
item = new PopupMenu.PopupMenuItem(_("Restart"));
item.connect('activate', Lang.bind(this, this._onActivateRestart));
this.menu.addMenuItem(item);
this._restartItem = item;
item = new PopupMenu.PopupMenuItem(_("Power Off"));
item.connect('activate', Lang.bind(this, this._onActivatePowerOff));
this.menu.addMenuItem(item);
this._powerOffItem = item;
},
_onActivateSuspend: function() {
if (!this._haveSuspend)
return;
this._loginManager.suspend();
},
_onActivateRestart: function() {
if (!this._haveRestart)
return;
this._loginManager.reboot();
},
_onActivatePowerOff: function() {
if (!this._haveShutdown)
return;
this._loginManager.powerOff();
}
});

View File

@ -5,58 +5,52 @@ const Lang = imports.lang;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const ProviderIface = '<node> \ const ProviderIface = <interface name='org.freedesktop.realmd.Provider'>
<interface name="org.freedesktop.realmd.Provider"> \ <property name="Name" type="s" access="read"/>
<property name="Name" type="s" access="read"/> \ <property name="Version" type="s" access="read"/>
<property name="Version" type="s" access="read"/> \ <property name="Realms" type="ao" access="read"/>
<property name="Realms" type="ao" access="read"/> \ <method name="Discover">
<method name="Discover"> \ <arg name="string" type="s" direction="in"/>
<arg name="string" type="s" direction="in"/> \ <arg name="options" type="a{sv}" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/> \ <arg name="relevance" type="i" direction="out"/>
<arg name="relevance" type="i" direction="out"/> \ <arg name="realm" type="ao" direction="out"/>
<arg name="realm" type="ao" direction="out"/> \ </method>
</method> \ </interface>;
</interface> \
</node>';
const Provider = Gio.DBusProxy.makeProxyWrapper(ProviderIface); const Provider = Gio.DBusProxy.makeProxyWrapper(ProviderIface);
const ServiceIface = '<node> \ const ServiceIface = <interface name="org.freedesktop.realmd.Service">
<interface name="org.freedesktop.realmd.Service"> \ <method name="Cancel">
<method name="Cancel"> \ <arg name="operation" type="s" direction="in"/>
<arg name="operation" type="s" direction="in"/> \ </method>
</method> \ <method name="Release" />
<method name="Release" /> \ <method name="SetLocale">
<method name="SetLocale"> \ <arg name="locale" type="s" direction="in"/>
<arg name="locale" type="s" direction="in"/> \ </method>
</method> \ <signal name="Diagnostics">
<signal name="Diagnostics"> \ <arg name="data" type="s"/>
<arg name="data" type="s"/> \ <arg name="operation" type="s"/>
<arg name="operation" type="s"/> \ </signal>
</signal> \ </interface>;
</interface> \
</node>';
const Service = Gio.DBusProxy.makeProxyWrapper(ServiceIface); const Service = Gio.DBusProxy.makeProxyWrapper(ServiceIface);
const RealmIface = '<node> \ const RealmIface = <interface name="org.freedesktop.realmd.Realm">
<interface name="org.freedesktop.realmd.Realm"> \ <property name="Name" type="s" access="read"/>
<property name="Name" type="s" access="read"/> \ <property name="Configured" type="s" access="read"/>
<property name="Configured" type="s" access="read"/> \ <property name="Details" type="a(ss)" access="read"/>
<property name="Details" type="a(ss)" access="read"/> \ <property name="LoginFormats" type="as" access="read"/>
<property name="LoginFormats" type="as" access="read"/> \ <property name="LoginPolicy" type="s" access="read"/>
<property name="LoginPolicy" type="s" access="read"/> \ <property name="PermittedLogins" type="as" access="read"/>
<property name="PermittedLogins" type="as" access="read"/> \ <property name="SupportedInterfaces" type="as" access="read"/>
<property name="SupportedInterfaces" type="as" access="read"/> \ <method name="ChangeLoginPolicy">
<method name="ChangeLoginPolicy"> \ <arg name="login_policy" type="s" direction="in"/>
<arg name="login_policy" type="s" direction="in"/> \ <arg name="permitted_add" type="as" direction="in"/>
<arg name="permitted_add" type="as" direction="in"/> \ <arg name="permitted_remove" type="as" direction="in"/>
<arg name="permitted_remove" type="as" direction="in"/> \ <arg name="options" type="a{sv}" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/> \ </method>
</method> \ <method name="Deconfigure">
<method name="Deconfigure"> \ <arg name="options" type="a{sv}" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/> \ </method>
</method> \ </interface>;
</interface> \
</node>';
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface); const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
const Manager = new Lang.Class({ const Manager = new Lang.Class({
@ -69,7 +63,7 @@ const Manager = new Lang.Class({
Lang.bind(this, this._reloadRealms)) Lang.bind(this, this._reloadRealms))
this._realms = {}; this._realms = {};
this._signalId = this._aggregateProvider.connect('g-properties-changed', this._aggregateProvider.connect('g-properties-changed',
Lang.bind(this, function(proxy, properties) { Lang.bind(this, function(proxy, properties) {
if ('Realms' in properties.deep_unpack()) if ('Realms' in properties.deep_unpack())
this._reloadRealms(); this._reloadRealms();
@ -112,7 +106,7 @@ const Manager = new Lang.Class({
realm.connect('g-properties-changed', realm.connect('g-properties-changed',
Lang.bind(this, function(proxy, properties) { Lang.bind(this, function(proxy, properties) {
if ('Configured' in properties.deep_unpack()) if ('Configured' in properties.deep_unpack())
this._reloadRealm(realm); this._reloadRealm();
})); }));
}, },
@ -140,18 +134,6 @@ const Manager = new Lang.Class({
this._updateLoginFormat(); this._updateLoginFormat();
return this._loginFormat; return this._loginFormat;
},
release: function() {
Service(Gio.DBus.system,
'org.freedesktop.realmd',
'/org/freedesktop/realmd',
function(service) {
service.ReleaseRemote();
});
this._aggregateProvider.disconnect(this._signalId);
this._realms = { };
this._updateLoginFormat();
} }
}); });
Signals.addSignalMethods(Manager.prototype) Signals.addSignalMethods(Manager.prototype)

View File

@ -6,28 +6,21 @@ const GLib = imports.gi.GLib;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Signals = imports.signals; const Signals = imports.signals;
const St = imports.gi.St;
const Batch = imports.gdm.batch; const Batch = imports.gdm.batch;
const Fprint = imports.gdm.fingerprint; const Fprint = imports.gdm.fingerprint;
const OVirt = imports.gdm.oVirt; const Realmd = imports.gdm.realmd;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry;
const SmartcardManager = imports.misc.smartcardManager;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const PASSWORD_SERVICE_NAME = 'gdm-password'; const PASSWORD_SERVICE_NAME = 'gdm-password';
const FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint'; 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 FADE_ANIMATION_TIME = 0.16;
const CLONE_FADE_ANIMATION_TIME = 0.25; const CLONE_FADE_ANIMATION_TIME = 0.25;
const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen'; const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
const PASSWORD_AUTHENTICATION_KEY = 'enable-password-authentication';
const FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication'; const FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication';
const SMARTCARD_AUTHENTICATION_KEY = 'enable-smartcard-authentication';
const BANNER_MESSAGE_KEY = 'banner-message-enable'; const BANNER_MESSAGE_KEY = 'banner-message-enable';
const BANNER_MESSAGE_TEXT_KEY = 'banner-message-text'; const BANNER_MESSAGE_TEXT_KEY = 'banner-message-text';
const ALLOWED_FAILURES_KEY = 'allowed-failures'; const ALLOWED_FAILURES_KEY = 'allowed-failures';
@ -38,13 +31,6 @@ const DISABLE_USER_LIST_KEY = 'disable-user-list';
// Give user 16ms to read each character of a PAM message // Give user 16ms to read each character of a PAM message
const USER_READ_TIME = 16 const USER_READ_TIME = 16
const MessageType = {
NONE: 0,
ERROR: 1,
INFO: 2,
HINT: 3
};
function fadeInActor(actor) { function fadeInActor(actor) {
if (actor.opacity == 255 && actor.visible) if (actor.opacity == 255 && actor.visible)
return null; return null;
@ -128,46 +114,21 @@ const ShellUserVerifier = new Lang.Class({
this._client = client; this._client = client;
this._settings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA }); this._settings = new Gio.Settings({ schema: LOGIN_SCREEN_SCHEMA });
this._settings.connect('changed',
Lang.bind(this, this._updateDefaultService));
this._updateDefaultService();
this._fprintManager = new Fprint.FprintManager(); this._fprintManager = new Fprint.FprintManager();
this._smartcardManager = SmartcardManager.getSmartcardManager(); this._realmManager = new Realmd.Manager();
// We check for smartcards right away, since an inserted smartcard
// at startup should result in immediately initiating authentication.
// This is different than fingeprint readers, where we only check them
// after a user has been picked.
this._checkForSmartcard();
this._smartcardInsertedId = this._smartcardManager.connect('smartcard-inserted',
Lang.bind(this, this._checkForSmartcard));
this._smartcardRemovedId = this._smartcardManager.connect('smartcard-removed',
Lang.bind(this, this._checkForSmartcard));
this._messageQueue = []; this._messageQueue = [];
this._messageQueueTimeoutId = 0; this._messageQueueTimeoutId = 0;
this.hasPendingMessages = false; this.hasPendingMessages = false;
this.reauthenticating = false;
this._failCounter = 0; this._failCounter = 0;
this._oVirtCredentialsManager = OVirt.getOVirtCredentialsManager();
if (this._oVirtCredentialsManager.hasToken())
this._oVirtUserAuthenticated(this._oVirtCredentialsManager.getToken());
this._oVirtUserAuthenticatedId = this._oVirtCredentialsManager.connect('user-authenticated',
Lang.bind(this, this._oVirtUserAuthenticated));
}, },
begin: function(userName, hold) { begin: function(userName, hold) {
this._cancellable = new Gio.Cancellable(); this._cancellable = new Gio.Cancellable();
this._hold = hold; this._hold = hold;
this._userName = userName; this._userName = userName;
this.reauthenticating = false;
this._checkForFingerprintReader(); this._checkForFingerprintReader();
@ -185,17 +146,8 @@ const ShellUserVerifier = new Lang.Class({
if (this._cancellable) if (this._cancellable)
this._cancellable.cancel(); this._cancellable.cancel();
if (this._userVerifier) { if (this._userVerifier)
this._userVerifier.call_cancel_sync(null); this._userVerifier.call_cancel_sync(null);
this.clear();
}
},
_clearUserVerifier: function() {
if (this._userVerifier) {
this._userVerifier.run_dispose();
this._userVerifier = null;
}
}, },
clear: function() { clear: function() {
@ -204,33 +156,23 @@ const ShellUserVerifier = new Lang.Class({
this._cancellable = null; this._cancellable = null;
} }
this._clearUserVerifier(); if (this._userVerifier) {
this._userVerifier.run_dispose();
this._userVerifier = null;
}
this._clearMessageQueue(); this._clearMessageQueue();
}, },
destroy: function() {
this.clear();
this._settings.run_dispose();
this._settings = null;
this._smartcardManager.disconnect(this._smartcardInsertedId);
this._smartcardManager.disconnect(this._smartcardRemovedId);
this._smartcardManager = null;
this._oVirtCredentialsManager.disconnect(this._oVirtUserAuthenticatedId);
this._oVirtCredentialsManager = null;
},
answerQuery: function(serviceName, answer) { answerQuery: function(serviceName, answer) {
if (!this.hasPendingMessages) { if (!this._userVerifier.hasPendingMessages) {
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null); this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
} else { } else {
let signalId = this.connect('no-more-messages', let signalId = this._userVerifier.connect('no-more-messages',
Lang.bind(this, function() { Lang.bind(this, function() {
this.disconnect(signalId); this._userVerifier.disconnect(signalId);
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null); this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
})); }));
} }
}, },
@ -259,24 +201,21 @@ const ShellUserVerifier = new Lang.Class({
return; return;
let message = this._messageQueue.shift(); let message = this._messageQueue.shift();
this.emit('show-message', message.text, message.iconName);
this.emit('show-message', message.text, message.type);
this._messageQueueTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, this._messageQueueTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
message.interval, message.interval,
Lang.bind(this, function() { Lang.bind(this, function() {
this._messageQueueTimeoutId = 0; this._messageQueueTimeoutId = 0;
this._queueMessageTimeout(); this._queueMessageTimeout();
return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._messageQueueTimeoutId, '[gnome-shell] this._queueMessageTimeout');
}, },
_queueMessage: function(message, messageType) { _queueMessage: function(message, iconName) {
let interval = this._getIntervalForMessage(message); let interval = this._getIntervalForMessage(message);
this.hasPendingMessages = true; this.hasPendingMessages = true;
this._messageQueue.push({ text: message, type: messageType, interval: interval }); this._messageQueue.push({ text: message, interval: interval, iconName: iconName });
this._queueMessageTimeout(); this._queueMessageTimeout();
}, },
@ -287,64 +226,32 @@ const ShellUserVerifier = new Lang.Class({
GLib.source_remove(this._messageQueueTimeoutId); GLib.source_remove(this._messageQueueTimeoutId);
this._messageQueueTimeoutId = 0; this._messageQueueTimeoutId = 0;
} }
this.emit('show-message', null, MessageType.NONE); this.emit('show-message', null, null);
}, },
_checkForFingerprintReader: function() { _checkForFingerprintReader: function() {
this._haveFingerprintReader = false; this._haveFingerprintReader = false;
if (!this._settings.get_boolean(FINGERPRINT_AUTHENTICATION_KEY)) { if (!this._settings.get_boolean(FINGERPRINT_AUTHENTICATION_KEY))
this._updateDefaultService();
return; return;
}
this._fprintManager.GetDefaultDeviceRemote(Gio.DBusCallFlags.NONE, this._cancellable, Lang.bind(this, this._fprintManager.GetDefaultDeviceRemote(Gio.DBusCallFlags.NONE, this._cancellable, Lang.bind(this,
function(device, error) { function(device, error) {
if (!error && device) { if (!error && device)
this._haveFingerprintReader = true; this._haveFingerprintReader = true;
this._updateDefaultService();
}
})); }));
}, },
_oVirtUserAuthenticated: function(token) {
this._preemptingService = OVIRT_SERVICE_NAME;
this.emit('ovirt-user-authenticated');
},
_checkForSmartcard: function() {
let smartcardDetected;
if (!this._settings.get_boolean(SMARTCARD_AUTHENTICATION_KEY))
smartcardDetected = false;
else if (this._reauthOnly)
smartcardDetected = this._smartcardManager.hasInsertedLoginToken();
else
smartcardDetected = this._smartcardManager.hasInsertedTokens();
if (smartcardDetected != this.smartcardDetected) {
this.smartcardDetected = smartcardDetected;
if (this.smartcardDetected)
this._preemptingService = SMARTCARD_SERVICE_NAME;
else if (this._preemptingService == SMARTCARD_SERVICE_NAME)
this._preemptingService = null;
this.emit('smartcard-status-changed');
}
},
_reportInitError: function(where, error) { _reportInitError: function(where, error) {
logError(error, where); logError(error, where);
this._hold.release(); this._hold.release();
this._queueMessage(_("Authentication error"), MessageType.ERROR); this._queueMessage(_("Authentication error"), 'login-dialog-message-warning');
this._verificationFailed(false); this._verificationFailed(false);
}, },
_reauthenticationChannelOpened: function(client, result) { _reauthenticationChannelOpened: function(client, result) {
try { try {
this._clearUserVerifier();
this._userVerifier = client.open_reauthentication_channel_finish(result); this._userVerifier = client.open_reauthentication_channel_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return; return;
@ -360,7 +267,6 @@ const ShellUserVerifier = new Lang.Class({
return; return;
} }
this.reauthenticating = true;
this._connectSignals(); this._connectSignals();
this._beginVerification(); this._beginVerification();
this._hold.release(); this._hold.release();
@ -368,7 +274,6 @@ const ShellUserVerifier = new Lang.Class({
_userVerifierGot: function(client, result) { _userVerifierGot: function(client, result) {
try { try {
this._clearUserVerifier();
this._userVerifier = client.get_user_verifier_finish(result); this._userVerifier = client.get_user_verifier_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return; return;
@ -392,119 +297,124 @@ const ShellUserVerifier = new Lang.Class({
this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete)); this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete));
}, },
_getForegroundService: function() { _beginVerification: function() {
if (this._preemptingService)
return this._preemptingService;
return this._defaultService;
},
serviceIsForeground: function(serviceName) {
return serviceName == this._getForegroundService();
},
serviceIsDefault: function(serviceName) {
return serviceName == this._defaultService;
},
_updateDefaultService: function() {
if (this._settings.get_boolean(PASSWORD_AUTHENTICATION_KEY))
this._defaultService = PASSWORD_SERVICE_NAME;
else if (this.smartcardDetected)
this._defaultService = SMARTCARD_SERVICE_NAME;
else if (this._haveFingerprintReader)
this._defaultService = FINGERPRINT_SERVICE_NAME;
},
_startService: function(serviceName) {
this._hold.acquire(); this._hold.acquire();
if (this._userName) { if (this._userName) {
this._userVerifier.call_begin_verification_for_user(serviceName, this._userVerifier.call_begin_verification_for_user(PASSWORD_SERVICE_NAME,
this._userName, this._userName,
this._cancellable, this._cancellable,
Lang.bind(this, function(obj, result) { Lang.bind(this, function(obj, result) {
try { try {
obj.call_begin_verification_for_user_finish(result); obj.call_begin_verification_for_user_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return; return;
} catch(e) { } catch(e) {
this._reportInitError('Failed to start verification for user', e); this._reportInitError('Failed to start verification for user', e);
return; return;
} }
this._hold.release(); this._hold.release();
})); }));
if (this._haveFingerprintReader) {
this._hold.acquire();
this._userVerifier.call_begin_verification_for_user(FINGERPRINT_SERVICE_NAME,
this._userName,
this._cancellable,
Lang.bind(this, function(obj, result) {
try {
obj.call_begin_verification_for_user_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
} catch(e) {
this._reportInitError('Failed to start fingerprint verification for user', e);
return;
}
this._hold.release();
}));
}
} else { } else {
this._userVerifier.call_begin_verification(serviceName, this._userVerifier.call_begin_verification(PASSWORD_SERVICE_NAME,
this._cancellable, this._cancellable,
Lang.bind(this, function(obj, result) { Lang.bind(this, function(obj, result) {
try { try {
obj.call_begin_verification_finish(result); obj.call_begin_verification_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return; return;
} catch(e) { } catch(e) {
this._reportInitError('Failed to start verification', e); this._reportInitError('Failed to start verification', e);
return; return;
} }
this._hold.release(); this._hold.release();
})); }));
} }
}, },
_beginVerification: function() {
this._startService(this._getForegroundService());
if (this._userName && this._haveFingerprintReader && !this.serviceIsForeground(FINGERPRINT_SERVICE_NAME))
this._startService(FINGERPRINT_SERVICE_NAME);
},
_onInfo: function(client, serviceName, info) { _onInfo: function(client, serviceName, info) {
if (this.serviceIsForeground(serviceName)) { // We don't display fingerprint messages, because they
this._queueMessage(info, MessageType.INFO); // have words like UPEK in them. Instead we use the messages
} else if (serviceName == FINGERPRINT_SERVICE_NAME && // as a cue to display our own message.
if (serviceName == FINGERPRINT_SERVICE_NAME &&
this._haveFingerprintReader) { this._haveFingerprintReader) {
// We don't show fingerprint messages directly since it's
// not the main auth service. Instead we use the messages
// as a cue to display our own message.
// Translators: this message is shown below the password entry field // Translators: this message is shown below the password entry field
// to indicate the user can swipe their finger instead // to indicate the user can swipe their finger instead
this._queueMessage(_("(or swipe finger)"), MessageType.HINT); this.emit('show-login-hint', _("(or swipe finger)"));
} else if (serviceName == PASSWORD_SERVICE_NAME) {
this._queueMessage(info, 'login-dialog-message-info');
} }
}, },
_onProblem: function(client, serviceName, problem) { _onProblem: function(client, serviceName, problem) {
if (!this.serviceIsForeground(serviceName)) // we don't want to show auth failed messages to
// users who haven't enrolled their fingerprint.
if (serviceName != PASSWORD_SERVICE_NAME)
return; return;
this._queueMessage(problem, 'login-dialog-message-warning');
},
this._queueMessage(problem, MessageType.ERROR); _showRealmLoginHint: function() {
if (this._realmManager.loginFormat) {
let hint = this._realmManager.loginFormat;
hint = hint.replace(/%U/g, 'user');
hint = hint.replace(/%D/g, 'DOMAIN');
hint = hint.replace(/%[^UD]/g, '');
// 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.emit('show-login-hint',
_("(e.g., user or %s)").format(hint));
}
}, },
_onInfoQuery: function(client, serviceName, question) { _onInfoQuery: function(client, serviceName, question) {
if (!this.serviceIsForeground(serviceName)) // We only expect questions to come from the main auth service
if (serviceName != PASSWORD_SERVICE_NAME)
return; return;
this._showRealmLoginHint();
this._realmLoginHintSignalId = this._realmManager.connect('login-format-changed',
Lang.bind(this, this._showRealmLoginHint));
this.emit('ask-question', serviceName, question, ''); this.emit('ask-question', serviceName, question, '');
}, },
_onSecretInfoQuery: function(client, serviceName, secretQuestion) { _onSecretInfoQuery: function(client, serviceName, secretQuestion) {
if (!this.serviceIsForeground(serviceName)) // We only expect secret requests to come from the main auth service
if (serviceName != PASSWORD_SERVICE_NAME)
return; 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'); this.emit('ask-question', serviceName, secretQuestion, '\u25cf');
}, },
_onReset: function() { _onReset: function() {
// Clear previous attempts to authenticate // Clear previous attempts to authenticate
this._failCounter = 0; this._failCounter = 0;
this._updateDefaultService();
this.emit('reset'); this.emit('reset');
}, },
@ -533,24 +443,24 @@ const ShellUserVerifier = new Lang.Class({
this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY); this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY);
if (canRetry) { if (canRetry) {
if (!this.hasPendingMessages) { if (!this._userVerifier.hasPendingMessages) {
this._retry(); this._retry();
} else { } else {
let signalId = this.connect('no-more-messages', let signalId = this._userVerifier.connect('no-more-messages',
Lang.bind(this, function() { Lang.bind(this, function() {
this.disconnect(signalId); this._userVerifier.disconnect(signalId);
this._retry(); this._retry();
})); }));
} }
} else { } else {
if (!this.hasPendingMessages) { if (!this._userVerifier.hasPendingMessages) {
this._cancelAndReset(); this._cancelAndReset();
} else { } else {
let signalId = this.connect('no-more-messages', let signalId = this._userVerifier.connect('no-more-messages',
Lang.bind(this, function() { Lang.bind(this, function() {
this.disconnect(signalId); this._userVerifier.disconnect(signalId);
this._cancelAndReset(); this._cancelAndReset();
})); }));
} }
} }
@ -558,22 +468,19 @@ const ShellUserVerifier = new Lang.Class({
}, },
_onConversationStopped: function(client, serviceName) { _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. // if the password service fails, then cancel everything.
// But if, e.g., fingerprint fails, still give // But if, e.g., fingerprint fails, still give
// password authentication a chance to succeed // password authentication a chance to succeed
if (this.serviceIsForeground(serviceName)) { if (serviceName == PASSWORD_SERVICE_NAME) {
this._verificationFailed(true); this._verificationFailed(true);
} }
this.emit('hide-login-hint');
if (this._realmLoginHintSignalId) {
this._realmManager.disconnect(this._realmLoginHintSignalId);
this._realmLoginHintSignalId = 0;
}
}, },
}); });
Signals.addSignalMethods(ShellUserVerifier.prototype); Signals.addSignalMethods(ShellUserVerifier.prototype);

View File

@ -1,122 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/shell">
<file>gdm/authPrompt.js</file>
<file>gdm/batch.js</file>
<file>gdm/fingerprint.js</file>
<file>gdm/loginDialog.js</file>
<file>gdm/oVirt.js</file>
<file>gdm/realmd.js</file>
<file>gdm/util.js</file>
<file>extensionPrefs/main.js</file>
<file>misc/config.js</file>
<file>misc/extensionUtils.js</file>
<file>misc/fileUtils.js</file>
<file>misc/gnomeSession.js</file>
<file>misc/history.js</file>
<file>misc/ibusManager.js</file>
<file>misc/jsParse.js</file>
<file>misc/keyboardManager.js</file>
<file>misc/loginManager.js</file>
<file>misc/modemManager.js</file>
<file>misc/objectManager.js</file>
<file>misc/params.js</file>
<file>misc/smartcardManager.js</file>
<file>misc/util.js</file>
<file>perf/core.js</file>
<file>perf/hwtest.js</file>
<file>portalHelper/main.js</file>
<file>ui/altTab.js</file>
<file>ui/animation.js</file>
<file>ui/appDisplay.js</file>
<file>ui/appFavorites.js</file>
<file>ui/backgroundMenu.js</file>
<file>ui/background.js</file>
<file>ui/boxpointer.js</file>
<file>ui/calendar.js</file>
<file>ui/checkBox.js</file>
<file>ui/ctrlAltTab.js</file>
<file>ui/dash.js</file>
<file>ui/dateMenu.js</file>
<file>ui/dnd.js</file>
<file>ui/edgeDragAction.js</file>
<file>ui/endSessionDialog.js</file>
<file>ui/environment.js</file>
<file>ui/extensionDownloader.js</file>
<file>ui/extensionSystem.js</file>
<file>ui/focusCaretTracker.js</file>
<file>ui/grabHelper.js</file>
<file>ui/ibusCandidatePopup.js</file>
<file>ui/iconGrid.js</file>
<file>ui/keyboard.js</file>
<file>ui/layout.js</file>
<file>ui/lightbox.js</file>
<file>ui/lookingGlass.js</file>
<file>ui/magnifier.js</file>
<file>ui/magnifierDBus.js</file>
<file>ui/main.js</file>
<file>ui/messageTray.js</file>
<file>ui/modalDialog.js</file>
<file>ui/notificationDaemon.js</file>
<file>ui/osdWindow.js</file>
<file>ui/osdMonitorLabeler.js</file>
<file>ui/overview.js</file>
<file>ui/overviewControls.js</file>
<file>ui/panel.js</file>
<file>ui/panelMenu.js</file>
<file>ui/pointerWatcher.js</file>
<file>ui/popupMenu.js</file>
<file>ui/remoteMenu.js</file>
<file>ui/remoteSearch.js</file>
<file>ui/runDialog.js</file>
<file>ui/screenShield.js</file>
<file>ui/screencast.js</file>
<file>ui/screenshot.js</file>
<file>ui/scripting.js</file>
<file>ui/search.js</file>
<file>ui/separator.js</file>
<file>ui/sessionMode.js</file>
<file>ui/shellDBus.js</file>
<file>ui/shellEntry.js</file>
<file>ui/shellMountOperation.js</file>
<file>ui/slider.js</file>
<file>ui/switcherPopup.js</file>
<file>ui/tweener.js</file>
<file>ui/unlockDialog.js</file>
<file>ui/userWidget.js</file>
<file>ui/viewSelector.js</file>
<file>ui/windowAttentionHandler.js</file>
<file>ui/windowMenu.js</file>
<file>ui/windowManager.js</file>
<file>ui/workspace.js</file>
<file>ui/workspaceSwitcherPopup.js</file>
<file>ui/workspaceThumbnail.js</file>
<file>ui/workspacesView.js</file>
<file>ui/xdndHandler.js</file>
<file>ui/components/__init__.js</file>
<file>ui/components/autorunManager.js</file>
<file>ui/components/automountManager.js</file>
<file>ui/components/networkAgent.js</file>
<file>ui/components/polkitAgent.js</file>
<file>ui/components/telepathyClient.js</file>
<file>ui/components/keyring.js</file>
<file>ui/status/accessibility.js</file>
<file>ui/status/brightness.js</file>
<file>ui/status/location.js</file>
<file>ui/status/keyboard.js</file>
<file>ui/status/network.js</file>
<file>ui/status/power.js</file>
<file>ui/status/rfkill.js</file>
<file>ui/status/volume.js</file>
<file>ui/status/bluetooth.js</file>
<file>ui/status/screencast.js</file>
<file>ui/status/system.js</file>
</gresource>
</gresources>

View File

@ -6,8 +6,6 @@ const PACKAGE_NAME = '@PACKAGE_NAME@';
const PACKAGE_VERSION = '@PACKAGE_VERSION@'; const PACKAGE_VERSION = '@PACKAGE_VERSION@';
/* 1 if gnome-bluetooth is available, 0 otherwise */ /* 1 if gnome-bluetooth is available, 0 otherwise */
const HAVE_BLUETOOTH = @HAVE_BLUETOOTH@; const HAVE_BLUETOOTH = @HAVE_BLUETOOTH@;
/* 1 if networkmanager is available, 0 otherwise */
const HAVE_NETWORKMANAGER = @HAVE_NETWORKMANAGER@;
/* gettext package */ /* gettext package */
const GETTEXT_PACKAGE = '@GETTEXT_PACKAGE@'; const GETTEXT_PACKAGE = '@GETTEXT_PACKAGE@';
/* locale dir */ /* locale dir */

View File

@ -43,7 +43,7 @@ function getCurrentExtension() {
let path = match[1]; let path = match[1];
let file = Gio.File.new_for_path(path); let file = Gio.File.new_for_path(path);
// Walk up the directory tree, looking for an extension with // Walk up the directory tree, looking for an extesion with
// the same UUID as a directory name. // the same UUID as a directory name.
while (file != null) { while (file != null) {
let extension = extensions[file.get_basename()]; let extension = extensions[file.get_basename()];
@ -174,9 +174,17 @@ const ExtensionFinder = new Lang.Class({
this.emit('extension-found', extension); this.emit('extension-found', extension);
}, },
_extensionsLoaded: function() {
this.emit('extensions-loaded');
},
scanExtensions: function() { scanExtensions: function() {
let perUserDir = Gio.File.new_for_path(global.userdatadir); let perUserDir = Gio.File.new_for_path(global.userdatadir);
FileUtils.collectFromDatadirs('extensions', true, Lang.bind(this, this._loadExtension, perUserDir)); FileUtils.collectFromDatadirsAsync('extensions',
{ processFile: Lang.bind(this, this._loadExtension),
loadedCallback: Lang.bind(this, this._extensionsLoaded),
includeUserDir: true,
data: perUserDir });
} }
}); });
Signals.addSignalMethods(ExtensionFinder.prototype); Signals.addSignalMethods(ExtensionFinder.prototype);

View File

@ -5,27 +5,80 @@ const GLib = imports.gi.GLib;
const Lang = imports.lang; const Lang = imports.lang;
const Params = imports.misc.params; const Params = imports.misc.params;
function collectFromDatadirs(subdir, includeUserDir, processFile) { function listDirAsync(file, callback) {
let allFiles = [];
file.enumerate_children_async('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE,
GLib.PRIORITY_LOW, null, function (obj, res) {
let enumerator = obj.enumerate_children_finish(res);
function onNextFileComplete(obj, res) {
let files = obj.next_files_finish(res);
if (files.length) {
allFiles = allFiles.concat(files);
enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, onNextFileComplete);
} else {
enumerator.close(null);
callback(allFiles);
}
}
enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, onNextFileComplete);
});
}
function _collectFromDirectoryAsync(dir, loadState) {
function done() {
loadState.numLoading--;
if (loadState.loadedCallback &&
loadState.numLoading == 0)
loadState.loadedCallback(loadState.data);
}
dir.query_info_async('standard::type', Gio.FileQueryInfoFlags.NONE,
GLib.PRIORITY_DEFAULT, null, function(object, res) {
try {
object.query_info_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
log(e.message);
done();
return;
}
listDirAsync(dir, Lang.bind(this, function(infos) {
for (let i = 0; i < infos.length; i++)
loadState.processFile(dir.get_child(infos[i].get_name()),
infos[i], loadState.data);
done();
}));
});
}
function collectFromDatadirsAsync(subdir, params) {
params = Params.parse(params, { includeUserDir: false,
processFile: null,
loadedCallback: null,
data: null });
let loadState = { data: params.data,
numLoading: 0,
loadedCallback: params.loadedCallback,
processFile: params.processFile };
if (params.processFile == null) {
if (params.loadedCallback)
params.loadedCallback(params.data);
return;
}
let dataDirs = GLib.get_system_data_dirs(); let dataDirs = GLib.get_system_data_dirs();
if (includeUserDir) if (params.includeUserDir)
dataDirs.unshift(GLib.get_user_data_dir()); dataDirs.unshift(GLib.get_user_data_dir());
loadState.numLoading = dataDirs.length;
for (let i = 0; i < dataDirs.length; i++) { for (let i = 0; i < dataDirs.length; i++) {
let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', subdir]); let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', subdir]);
let dir = Gio.File.new_for_path(path); let dir = Gio.File.new_for_path(path);
let fileEnum; _collectFromDirectoryAsync(dir, loadState);
try {
fileEnum = dir.enumerate_children('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE, null);
} catch (e) {
fileEnum = null;
}
if (fileEnum != null) {
let info;
while ((info = fileEnum.next_file(null)))
processFile(fileEnum.get_child(info), info);
}
} }
} }
@ -64,6 +117,7 @@ function recursivelyMoveDir(srcDir, destDir) {
let type = info.get_file_type(); let type = info.get_file_type();
let srcChild = srcDir.get_child(info.get_name()); let srcChild = srcDir.get_child(info.get_name());
let destChild = destDir.get_child(info.get_name()); let destChild = destDir.get_child(info.get_name());
log([srcChild.get_path(), destChild.get_path()]);
if (type == Gio.FileType.REGULAR) if (type == Gio.FileType.REGULAR)
srcChild.move(destChild, Gio.FileCopyFlags.NONE, null, null); srcChild.move(destChild, Gio.FileCopyFlags.NONE, null, null);
else if (type == Gio.FileType.DIRECTORY) else if (type == Gio.FileType.DIRECTORY)

View File

@ -4,17 +4,15 @@ const Gio = imports.gi.Gio;
const Lang = imports.lang; const Lang = imports.lang;
const Signals = imports.signals; const Signals = imports.signals;
const PresenceIface = '<node> \ const PresenceIface = <interface name="org.gnome.SessionManager.Presence">
<interface name="org.gnome.SessionManager.Presence"> \ <method name="SetStatus">
<method name="SetStatus"> \ <arg type="u" direction="in"/>
<arg type="u" direction="in"/> \ </method>
</method> \ <property name="status" type="u" access="readwrite"/>
<property name="status" type="u" access="readwrite"/> \ <signal name="StatusChanged">
<signal name="StatusChanged"> \ <arg type="u" direction="out"/>
<arg type="u" direction="out"/> \ </signal>
</signal> \ </interface>;
</interface> \
</node>';
const PresenceStatus = { const PresenceStatus = {
AVAILABLE: 0, AVAILABLE: 0,
@ -32,16 +30,14 @@ function Presence(initCallback, cancellable) {
// Note inhibitors are immutable objects, so they don't // Note inhibitors are immutable objects, so they don't
// change at runtime (changes always come in the form // change at runtime (changes always come in the form
// of new inhibitors) // of new inhibitors)
const InhibitorIface = '<node> \ const InhibitorIface = <interface name="org.gnome.SessionManager.Inhibitor">
<interface name="org.gnome.SessionManager.Inhibitor"> \ <method name="GetAppId">
<method name="GetAppId"> \ <arg type="s" direction="out" />
<arg type="s" direction="out" /> \ </method>
</method> \ <method name="GetReason">
<method name="GetReason"> \ <arg type="s" direction="out" />
<arg type="s" direction="out" /> \ </method>
</method> \ </interface>;
</interface> \
</node>';
var InhibitorProxy = Gio.DBusProxy.makeProxyWrapper(InhibitorIface); var InhibitorProxy = Gio.DBusProxy.makeProxyWrapper(InhibitorIface);
function Inhibitor(objectPath, initCallback, cancellable) { function Inhibitor(objectPath, initCallback, cancellable) {
@ -49,29 +45,27 @@ function Inhibitor(objectPath, initCallback, cancellable) {
} }
// Not the full interface, only the methods we use // Not the full interface, only the methods we use
const SessionManagerIface = '<node> \ const SessionManagerIface = <interface name="org.gnome.SessionManager">
<interface name="org.gnome.SessionManager"> \ <method name="Logout">
<method name="Logout"> \ <arg type="u" direction="in" />
<arg type="u" direction="in" /> \ </method>
</method> \ <method name="Shutdown" />
<method name="Shutdown" /> \ <method name="Reboot" />
<method name="Reboot" /> \ <method name="CanShutdown">
<method name="CanShutdown"> \ <arg type="b" direction="out" />
<arg type="b" direction="out" /> \ </method>
</method> \ <method name="IsInhibited">
<method name="IsInhibited"> \ <arg type="u" direction="in" />
<arg type="u" direction="in" /> \ <arg type="b" direction="out" />
<arg type="b" direction="out" /> \ </method>
</method> \ <property name="SessionIsActive" type="b" access="read"/>
<property name="SessionIsActive" type="b" access="read"/> \ <signal name="InhibitorAdded">
<signal name="InhibitorAdded"> \ <arg type="o" direction="out"/>
<arg type="o" direction="out"/> \ </signal>
</signal> \ <signal name="InhibitorRemoved">
<signal name="InhibitorRemoved"> \ <arg type="o" direction="out"/>
<arg type="o" direction="out"/> \ </signal>
</signal> \ </interface>;
</interface> \
</node>';
var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface); var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface);
function SessionManager(initCallback, cancellable) { function SessionManager(initCallback, cancellable) {

141
js/misc/hash.js Normal file
View File

@ -0,0 +1,141 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const System = imports.system;
const Params = imports.misc.params;
// This is an implementation of EcmaScript SameValue algorithm,
// which returns true if two values are not observably distinguishable.
// It was taken from http://wiki.ecmascript.org/doku.php?id=harmony:egal
//
// In the future, we may want to use the 'is' operator instead.
function _sameValue(x, y) {
if (x === y) {
// 0 === -0, but they are not identical
return x !== 0 || 1 / x === 1 / y;
}
// NaN !== NaN, but they are identical.
// NaNs are the only non-reflexive value, i.e., if x !== x,
// then x is a NaN.
// isNaN is broken: it converts its argument to number, so
// isNaN("foo") => true
return x !== x && y !== y;
}
const _hashers = {
object: function(o) { return o ? System.addressOf(o) : 'null'; },
function: function(f) { return System.addressOf(f); },
string: function(s) { return s; },
number: function(n) { return String(n); },
undefined: function() { return 'undefined'; },
};
/* Map is meant to be similar in usage to ES6 Map, which is
described at http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets,
without requiring more than ES5 + Gjs extensions.
Known differences from other implementations:
Polyfills around the web usually implement HashMaps for
primitive values and reversed WeakMaps for object keys,
but we want real maps with real O(1) semantics in all cases,
and the easiest way is to have different hashers for different
types.
Known differences from the ES6 specification:
- Map is a Lang.Class, not a ES6 class, so inheritance,
prototype, sealing, etc. work differently.
- items(), keys() and values() don't return iterators,
they return actual arrays, so they incur a full copy everytime
they're called, and they don't see changes if you mutate
the table while iterating
(admittedly, the ES6 spec is a bit unclear on this, and
the reference code would just blow up)
*/
const Map = new Lang.Class({
Name: 'Map',
_init: function(iterable) {
this._pool = { };
if (iterable) {
for (let i = 0; i < iterable.length; i++) {
let [key, value] = iterable[i];
this.set(key, value);
}
}
},
_hashKey: function(key) {
let type = typeof(key);
return type + ':' + _hashers[type](key);
},
_internalGet: function(key) {
let hash = this._hashKey(key);
let node = this._pool[hash];
if (node && _sameValue(node.key, key))
return [true, node.value];
else
return [false, null];
},
get: function(key) {
return this._internalGet(key)[1];
},
has: function(key) {
return this._internalGet(key)[0];
},
set: function(key, value) {
let hash = this._hashKey(key);
let node = this._pool[hash];
if (node) {
node.key = key;
node.value = value;
} else {
this._pool[hash] = { key: key, value: value };
}
},
delete: function(key) {
let hash = this._hashKey(key);
let node = this._pool[hash];
if (node && _sameValue(node.key, key)) {
delete this._pool[hash];
return [node.key, node.value];
} else {
return [null, null];
}
},
keys: function() {
let pool = this._pool;
return Object.getOwnPropertyNames(pool).map(function(hash) {
return pool[hash].key;
});
},
values: function() {
let pool = this._pool;
return Object.getOwnPropertyNames(pool).map(function(hash) {
return pool[hash].value;
});
},
items: function() {
let pool = this._pool;
return Object.getOwnPropertyNames(pool).map(function(hash) {
return [pool[hash].key, pool[hash].value];
});
},
size: function() {
return Object.getOwnPropertyNames(this._pool).length;
},
});

View File

@ -89,7 +89,7 @@ const HistoryManager = new Lang.Class({
} else if (symbol == Clutter.KEY_Down) { } else if (symbol == Clutter.KEY_Down) {
return this._setNextItem(entry.get_text()); return this._setNextItem(entry.get_text());
} }
return Clutter.EVENT_PROPAGATE; return false;
}, },
_indexChanged: function() { _indexChanged: function() {

View File

@ -1,234 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
try {
var IBus = imports.gi.IBus;
_checkIBusVersion(1, 5, 2);
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
} catch (e) {
var IBus = null;
log(e);
}
let _ibusManager = null;
function _checkIBusVersion(requiredMajor, requiredMinor, requiredMicro) {
if ((IBus.MAJOR_VERSION > requiredMajor) ||
(IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION > requiredMinor) ||
(IBus.MAJOR_VERSION == requiredMajor && IBus.MINOR_VERSION == requiredMinor &&
IBus.MICRO_VERSION >= requiredMicro))
return;
throw "Found IBus version %d.%d.%d but required is %d.%d.%d".
format(IBus.MAJOR_VERSION, IBus.MINOR_VERSION, IBus.MINOR_VERSION,
requiredMajor, requiredMinor, requiredMicro);
}
function getIBusManager() {
if (_ibusManager == null)
_ibusManager = new IBusManager();
return _ibusManager;
}
const IBusManager = new Lang.Class({
Name: 'IBusManager',
// This is the longest we'll keep the keyboard frozen until an input
// source is active.
_MAX_INPUT_SOURCE_ACTIVATION_TIME: 4000, // ms
_PRELOAD_ENGINES_DELAY_TIME: 30, // sec
_init: function() {
if (!IBus)
return;
IBus.init();
this._candidatePopup = new IBusCandidatePopup.CandidatePopup();
this._panelService = null;
this._engines = {};
this._ready = false;
this._registerPropertiesId = 0;
this._currentEngineName = null;
this._preloadEnginesId = 0;
this._ibus = IBus.Bus.new_async();
this._ibus.connect('connected', Lang.bind(this, this._onConnected));
this._ibus.connect('disconnected', Lang.bind(this, this._clear));
// Need to set this to get 'global-engine-changed' emitions
this._ibus.set_watch_ibus_signal(true);
this._ibus.connect('global-engine-changed', Lang.bind(this, this._engineChanged));
this._spawn();
},
_spawn: function() {
try {
Gio.Subprocess.new(['ibus-daemon', '--xim', '--panel', 'disable'],
Gio.SubprocessFlags.NONE);
} catch(e) {
log('Failed to launch ibus-daemon: ' + e.message);
}
},
_clear: function() {
if (this._panelService)
this._panelService.destroy();
this._panelService = null;
this._candidatePopup.setPanelService(null);
this._engines = {};
this._ready = false;
this._registerPropertiesId = 0;
this._currentEngineName = null;
this.emit('ready', false);
this._spawn();
},
_onConnected: function() {
this._ibus.list_engines_async(-1, null, Lang.bind(this, this._initEngines));
this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING,
-1, null,
Lang.bind(this, this._initPanelService));
},
_initEngines: function(ibus, result) {
let enginesList = this._ibus.list_engines_async_finish(result);
if (enginesList) {
for (let i = 0; i < enginesList.length; ++i) {
let name = enginesList[i].get_name();
this._engines[name] = enginesList[i];
}
this._updateReadiness();
} else {
this._clear();
}
},
_initPanelService: function(ibus, result) {
let success = this._ibus.request_name_async_finish(result);
if (success) {
this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(),
object_path: IBus.PATH_PANEL });
this._candidatePopup.setPanelService(this._panelService);
this._panelService.connect('update-property', Lang.bind(this, this._updateProperty));
try {
// IBus versions older than 1.5.10 have a bug which
// causes spurious set-content-type emissions when
// switching input focus that temporarily lose purpose
// and hints defeating its intended semantics and
// confusing users. We thus don't use it in that case.
_checkIBusVersion(1, 5, 10);
this._panelService.connect('set-content-type', Lang.bind(this, this._setContentType));
} catch (e) {
}
// If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, null, Lang.bind(this, function(i, result) {
let engine;
try {
engine = this._ibus.get_global_engine_async_finish(result);
if (!engine)
return;
} catch(e) {
return;
}
this._engineChanged(this._ibus, engine.get_name());
}));
this._updateReadiness();
} else {
this._clear();
}
},
_updateReadiness: function() {
this._ready = (Object.keys(this._engines).length > 0 &&
this._panelService != null);
this.emit('ready', this._ready);
},
_engineChanged: function(bus, engineName) {
if (!this._ready)
return;
this._currentEngineName = engineName;
if (this._registerPropertiesId != 0)
return;
this._registerPropertiesId =
this._panelService.connect('register-properties', Lang.bind(this, function(p, props) {
if (!props.get(0))
return;
this._panelService.disconnect(this._registerPropertiesId);
this._registerPropertiesId = 0;
this.emit('properties-registered', this._currentEngineName, props);
}));
},
_updateProperty: function(panel, prop) {
this.emit('property-updated', this._currentEngineName, prop);
},
_setContentType: function(panel, purpose, hints) {
this.emit('set-content-type', purpose, hints);
},
activateProperty: function(key, state) {
this._panelService.property_activate(key, state);
},
getEngineDesc: function(id) {
if (!IBus || !this._ready)
return null;
return this._engines[id];
},
setEngine: function(id, callback) {
// Send id even if id == this._currentEngineName
// because 'properties-registered' signal can be emitted
// while this._ibusSources == null on a lock screen.
if (!IBus || !this._ready) {
if (callback)
callback();
return;
}
this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
null, callback);
},
preloadEngines: function(ids) {
if (!IBus || !this._ibus || ids.length == 0)
return;
if (this._preloadEnginesId != 0) {
Mainloop.source_remove(this._preloadEnginesId);
this._preloadEnginesId = 0;
}
this._preloadEnginesId =
Mainloop.timeout_add_seconds(this._PRELOAD_ENGINES_DELAY_TIME,
Lang.bind(this, function() {
this._ibus.preload_engines_async(
ids,
-1,
null,
null);
this._preloadEnginesId = 0;
return GLib.SOURCE_REMOVE;
}));
},
});
Signals.addSignalMethods(IBusManager.prototype);

View File

@ -1,153 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GLib = imports.gi.GLib;
const GnomeDesktop = imports.gi.GnomeDesktop;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Main = imports.ui.main;
const DEFAULT_LOCALE = 'en_US';
const DEFAULT_LAYOUT = 'us';
const DEFAULT_VARIANT = '';
let _xkbInfo = null;
function getXkbInfo() {
if (_xkbInfo == null)
_xkbInfo = new GnomeDesktop.XkbInfo();
return _xkbInfo;
}
let _keyboardManager = null;
function getKeyboardManager() {
if (_keyboardManager == null)
_keyboardManager = new KeyboardManager();
return _keyboardManager;
}
function releaseKeyboard() {
if (Main.modalCount > 0)
global.display.unfreeze_keyboard(global.get_current_time());
else
global.display.ungrab_keyboard(global.get_current_time());
}
function holdKeyboard() {
global.display.freeze_keyboard(global.get_current_time());
}
const KeyboardManager = new Lang.Class({
Name: 'KeyboardManager',
// The XKB protocol doesn't allow for more that 4 layouts in a
// keymap. Wayland doesn't impose this limit and libxkbcommon can
// handle up to 32 layouts but since we need to support X clients
// even as a Wayland compositor, we can't bump this.
MAX_LAYOUTS_PER_GROUP: 4,
_init: function() {
this._xkbInfo = getXkbInfo();
this._current = null;
this._localeLayoutInfo = this._getLocaleLayout();
this._layoutInfos = {};
},
_applyLayoutGroup: function(group) {
let options = this._buildOptionsString();
let [layouts, variants] = this._buildGroupStrings(group);
Meta.get_backend().set_keymap(layouts, variants, options);
},
_applyLayoutGroupIndex: function(idx) {
Meta.get_backend().lock_layout_group(idx);
},
apply: function(id) {
let info = this._layoutInfos[id];
if (!info)
return;
if (this._current && this._current.group == info.group) {
if (this._current.groupIndex != info.groupIndex)
this._applyLayoutGroupIndex(info.groupIndex);
} else {
this._applyLayoutGroup(info.group);
this._applyLayoutGroupIndex(info.groupIndex);
}
this._current = info;
},
reapply: function() {
if (!this._current)
return;
this._applyLayoutGroup(this._current.group);
this._applyLayoutGroupIndex(this._current.groupIndex);
},
setUserLayouts: function(ids) {
this._current = null;
this._layoutInfos = {};
for (let i = 0; i < ids.length; ++i) {
let [found, , , _layout, _variant] = this._xkbInfo.get_layout_info(ids[i]);
if (found)
this._layoutInfos[ids[i]] = { id: ids[i], layout: _layout, variant: _variant };
}
let i = 0;
let group = [];
for (let id in this._layoutInfos) {
// We need to leave one slot on each group free so that we
// can add a layout containing the symbols for the
// language used in UI strings to ensure that toolkits can
// handle mnemonics like Alt+Ф even if the user is
// actually typing in a different layout.
let groupIndex = i % (this.MAX_LAYOUTS_PER_GROUP - 1);
if (groupIndex == 0)
group = [];
let info = this._layoutInfos[id];
group[groupIndex] = info;
info.group = group;
info.groupIndex = groupIndex;
i += 1;
}
},
_getLocaleLayout: function() {
let locale = GLib.get_language_names()[0];
if (locale.indexOf('_') == -1)
locale = DEFAULT_LOCALE;
let [found, , id] = GnomeDesktop.get_input_source_from_locale(locale);
if (!found)
[, , id] = GnomeDesktop.get_input_source_from_locale(DEFAULT_LOCALE);
let [found, , , _layout, _variant] = this._xkbInfo.get_layout_info(id);
if (found)
return { layout: _layout, variant: _variant };
else
return { layout: DEFAULT_LAYOUT, variant: DEFAULT_VARIANT };
},
_buildGroupStrings: function(_group) {
let group = _group.concat(this._localeLayoutInfo);
let layouts = group.map(function(g) { return g.layout; }).join(',');
let variants = group.map(function(g) { return g.variant; }).join(',');
return [layouts, variants];
},
setKeyboardOptions: function(options) {
this._xkbOptions = options;
},
_buildOptionsString: function() {
let options = this._xkbOptions.join(',');
return options;
}
});

View File

@ -7,45 +7,74 @@ const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const SystemdLoginManagerIface = '<node> \ const SystemdLoginManagerIface = <interface name='org.freedesktop.login1.Manager'>
<interface name="org.freedesktop.login1.Manager"> \ <method name='PowerOff'>
<method name="Suspend"> \ <arg type='b' direction='in'/>
<arg type="b" direction="in"/> \ </method>
</method> \ <method name='Reboot'>
<method name="CanSuspend"> \ <arg type='b' direction='in'/>
<arg type="s" direction="out"/> \ </method>
</method> \ <method name='Suspend'>
<method name="Inhibit"> \ <arg type='b' direction='in'/>
<arg type="s" direction="in"/> \ </method>
<arg type="s" direction="in"/> \ <method name='CanPowerOff'>
<arg type="s" direction="in"/> \ <arg type='s' direction='out'/>
<arg type="s" direction="in"/> \ </method>
<arg type="h" direction="out"/> \ <method name='CanReboot'>
</method> \ <arg type='s' direction='out'/>
<method name="GetSession"> \ </method>
<arg type="s" direction="in"/> \ <method name='CanSuspend'>
<arg type="o" direction="out"/> \ <arg type='s' direction='out'/>
</method> \ </method>
<method name="ListSessions"> \ <method name='Inhibit'>
<arg name="sessions" type="a(susso)" direction="out"/> \ <arg type='s' direction='in'/>
</method> \ <arg type='s' direction='in'/>
<signal name="PrepareForSleep"> \ <arg type='s' direction='in'/>
<arg type="b" direction="out"/> \ <arg type='s' direction='in'/>
</signal> \ <arg type='h' direction='out'/>
</interface> \ </method>
</node>'; <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 SystemdLoginSessionIface = '<node> \ const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session'>
<interface name="org.freedesktop.login1.Session"> \ <signal name='Lock' />
<signal name="Lock" /> \ <signal name='Unlock' />
<signal name="Unlock" /> \ </interface>;
<property name="Active" type="b" access="read" /> \
</interface> \
</node>';
const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface); const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface);
const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface); 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 ConsoleKitSessionIface = <interface name='org.freedesktop.ConsoleKit.Session'>
<signal name='Lock' />
<signal name='Unlock' />
</interface>;
const ConsoleKitSession = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
const ConsoleKitManager = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface);
function haveSystemd() { function haveSystemd() {
return GLib.access("/run/systemd/seats", 0) >= 0; return GLib.access("/run/systemd/seats", 0) >= 0;
} }
@ -55,10 +84,8 @@ function versionCompare(required, reference) {
reference = reference.split('.'); reference = reference.split('.');
for (let i = 0; i < required.length; i++) { for (let i = 0; i < required.length; i++) {
let requiredInt = parseInt(required[i]); if (required[i] != reference[i])
let referenceInt = parseInt(reference[i]); return required[i] < reference[i];
if (requiredInt != referenceInt)
return requiredInt < referenceInt;
} }
return true; return true;
@ -75,7 +102,7 @@ function canLock() {
-1, null); -1, null);
let version = result.deep_unpack()[0].deep_unpack(); let version = result.deep_unpack()[0].deep_unpack();
return haveSystemd() && versionCompare('3.5.91', version); return versionCompare('3.5.91', version);
} catch(e) { } catch(e) {
return false; return false;
} }
@ -93,7 +120,7 @@ function getLoginManager() {
if (haveSystemd()) if (haveSystemd())
_loginManager = new LoginManagerSystemd(); _loginManager = new LoginManagerSystemd();
else else
_loginManager = new LoginManagerDummy(); _loginManager = new LoginManagerConsoleKit();
} }
return _loginManager; return _loginManager;
@ -110,6 +137,9 @@ const LoginManagerSystemd = new Lang.Class({
Lang.bind(this, this._prepareForSleep)); Lang.bind(this, this._prepareForSleep));
}, },
// Having this function is a bit of a hack since the Systemd and ConsoleKit
// session objects have different interfaces - but in both cases there are
// Lock/Unlock signals, and that's all we count upon at the moment.
getCurrentSessionProxy: function(callback) { getCurrentSessionProxy: function(callback) {
if (this._currentSession) { if (this._currentSession) {
callback (this._currentSession); callback (this._currentSession);
@ -129,6 +159,24 @@ const LoginManagerSystemd = new Lang.Class({
})); }));
}, },
canPowerOff: function(asyncCallback) {
this._proxy.CanPowerOffRemote(function(result, error) {
if (error)
asyncCallback(false);
else
asyncCallback(result[0] != 'no');
});
},
canReboot: function(asyncCallback) {
this._proxy.CanRebootRemote(function(result, error) {
if (error)
asyncCallback(false);
else
asyncCallback(result[0] != 'no');
});
},
canSuspend: function(asyncCallback) { canSuspend: function(asyncCallback) {
this._proxy.CanSuspendRemote(function(result, error) { this._proxy.CanSuspendRemote(function(result, error) {
if (error) if (error)
@ -147,6 +195,14 @@ const LoginManagerSystemd = new Lang.Class({
}); });
}, },
powerOff: function() {
this._proxy.PowerOffRemote(true);
},
reboot: function() {
this._proxy.RebootRemote(true);
},
suspend: function() { suspend: function() {
this._proxy.SuspendRemote(true); this._proxy.SuspendRemote(true);
}, },
@ -162,7 +218,7 @@ const LoginManagerSystemd = new Lang.Class({
let fd = -1; let fd = -1;
try { try {
let [outVariant, fdList] = proxy.call_with_unix_fd_list_finish(result); let [outVariant, fdList] = proxy.call_with_unix_fd_list_finish(result);
fd = fdList.steal_fds()[0]; fd = fdList.steal_fds(outVariant.deep_unpack())[0];
callback(new Gio.UnixInputStream({ fd: fd })); callback(new Gio.UnixInputStream({ fd: fd }));
} catch(e) { } catch(e) {
logError(e, "Error getting systemd inhibitor"); logError(e, "Error getting systemd inhibitor");
@ -177,13 +233,53 @@ const LoginManagerSystemd = new Lang.Class({
}); });
Signals.addSignalMethods(LoginManagerSystemd.prototype); Signals.addSignalMethods(LoginManagerSystemd.prototype);
const LoginManagerDummy = new Lang.Class({ const LoginManagerConsoleKit = new Lang.Class({
Name: 'LoginManagerDummy', Name: 'LoginManagerConsoleKit',
_init: function() {
this._proxy = new ConsoleKitManager(Gio.DBus.system,
'org.freedesktop.ConsoleKit',
'/org/freedesktop/ConsoleKit/Manager');
},
// Having this function is a bit of a hack since the Systemd and ConsoleKit
// session objects have different interfaces - but in both cases there are
// Lock/Unlock signals, and that's all we count upon at the moment.
getCurrentSessionProxy: function(callback) { getCurrentSessionProxy: function(callback) {
// we could return a DummySession object that fakes whatever callers if (this._currentSession) {
// expect (at the time of writing: connect() and connectSignal() callback (this._currentSession);
// methods), but just never calling the callback should be safer return;
}
this._proxy.GetCurrentSessionRemote(Lang.bind(this,
function(result, error) {
if (error) {
logError(error, 'Could not get a proxy for the current session');
} else {
this._currentSession = new ConsoleKitSession(Gio.DBus.system,
'org.freedesktop.ConsoleKit',
result[0]);
callback(this._currentSession);
}
}));
},
canPowerOff: function(asyncCallback) {
this._proxy.CanStopRemote(function(result, error) {
if (error)
asyncCallback(false);
else
asyncCallback(result[0]);
});
},
canReboot: function(asyncCallback) {
this._proxy.CanRestartRemote(function(result, error) {
if (error)
asyncCallback(false);
else
asyncCallback(result[0]);
});
}, },
canSuspend: function(asyncCallback) { canSuspend: function(asyncCallback) {
@ -194,6 +290,14 @@ const LoginManagerDummy = new Lang.Class({
asyncCallback([]); asyncCallback([]);
}, },
powerOff: function() {
this._proxy.StopRemote();
},
reboot: function() {
this._proxy.RestartRemote();
},
suspend: function() { suspend: function() {
this.emit('prepare-for-sleep', true); this.emit('prepare-for-sleep', true);
this.emit('prepare-for-sleep', false); this.emit('prepare-for-sleep', false);
@ -203,4 +307,4 @@ const LoginManagerDummy = new Lang.Class({
callback(null); callback(null);
} }
}); });
Signals.addSignalMethods(LoginManagerDummy.prototype); Signals.addSignalMethods(LoginManagerConsoleKit.prototype);

View File

@ -92,41 +92,37 @@ function _findProviderForSid(sid) {
// The following are not the complete interfaces, just the methods we need // The following are not the complete interfaces, just the methods we need
// (or may need in the future) // (or may need in the future)
const ModemGsmNetworkInterface = '<node> \ const ModemGsmNetworkInterface = <interface name="org.freedesktop.ModemManager.Modem.Gsm.Network">
<interface name="org.freedesktop.ModemManager.Modem.Gsm.Network"> \ <method name="GetRegistrationInfo">
<method name="GetRegistrationInfo"> \ <arg type="(uss)" direction="out" />
<arg type="(uss)" direction="out" /> \ </method>
</method> \ <method name="GetSignalQuality">
<method name="GetSignalQuality"> \ <arg type="u" direction="out" />
<arg type="u" direction="out" /> \ </method>
</method> \ <property name="AccessTechnology" type="u" access="read" />
<property name="AccessTechnology" type="u" access="read" /> \ <signal name="SignalQuality">
<signal name="SignalQuality"> \ <arg type="u" direction="out" />
<arg type="u" direction="out" /> \ </signal>
</signal> \ <signal name="RegistrationInfo">
<signal name="RegistrationInfo"> \ <arg type="u" direction="out" />
<arg type="u" direction="out" /> \ <arg type="s" direction="out" />
<arg type="s" direction="out" /> \ <arg type="s" direction="out" />
<arg type="s" direction="out" /> \ </signal>
</signal> \ </interface>;
</interface> \
</node>';
const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInterface); const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInterface);
const ModemCdmaInterface = '<node> \ const ModemCdmaInterface = <interface name="org.freedesktop.ModemManager.Modem.Cdma">
<interface name="org.freedesktop.ModemManager.Modem.Cdma"> \ <method name="GetSignalQuality">
<method name="GetSignalQuality"> \ <arg type="u" direction="out" />
<arg type="u" direction="out" /> \ </method>
</method> \ <method name="GetServingSystem">
<method name="GetServingSystem"> \ <arg type="(usu)" direction="out" />
<arg type="(usu)" direction="out" /> \ </method>
</method> \ <signal name="SignalQuality">
<signal name="SignalQuality"> \ <arg type="u" direction="out" />
<arg type="u" direction="out" /> \ </signal>
</signal> \ </interface>;
</interface> \
</node>';
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface); const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
@ -222,26 +218,20 @@ Signals.addSignalMethods(ModemCdma.prototype);
// Support for the new ModemManager1 interface (MM >= 0.7) // Support for the new ModemManager1 interface (MM >= 0.7)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
const BroadbandModemInterface = '<node> \ const BroadbandModemInterface = <interface name="org.freedesktop.ModemManager1.Modem">
<interface name="org.freedesktop.ModemManager1.Modem"> \ <property name="SignalQuality" type="(ub)" access="read" />
<property name="SignalQuality" type="(ub)" access="read" /> \ </interface>;
</interface> \
</node>';
const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface); const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface);
const BroadbandModem3gppInterface = '<node> \ const BroadbandModem3gppInterface = <interface name="org.freedesktop.ModemManager1.Modem.Modem3gpp">
<interface name="org.freedesktop.ModemManager1.Modem.Modem3gpp"> \ <property name="OperatorCode" type="s" access="read" />
<property name="OperatorCode" type="s" access="read" /> \ <property name="OperatorName" type="s" access="read" />
<property name="OperatorName" type="s" access="read" /> \ </interface>;
</interface> \
</node>';
const BroadbandModem3gppProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModem3gppInterface); const BroadbandModem3gppProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModem3gppInterface);
const BroadbandModemCdmaInterface = '<node> \ const BroadbandModemCdmaInterface = <interface name="org.freedesktop.ModemManager1.Modem.ModemCdma">
<interface name="org.freedesktop.ModemManager1.Modem.ModemCdma"> \ <property name="Sid" type="u" access="read" />
<property name="Sid" type="u" access="read" /> \ </interface>;
</interface> \
</node>';
const BroadbandModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemCdmaInterface); const BroadbandModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemCdmaInterface);
const BroadbandModem = new Lang.Class({ const BroadbandModem = new Lang.Class({

View File

@ -1,259 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Params = imports.misc.params;
const Signals = imports.signals;
// Specified in the D-Bus specification here:
// http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
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);
const ObjectManager = new Lang.Class({
Name: 'ObjectManager',
_init: function(params) {
params = Params.parse(params, { connection: null,
name: null,
objectPath: null,
knownInterfaces: null,
cancellable: null,
onLoaded: null });
this._connection = params.connection;
this._serviceName = params.name;
this._managerPath = params.objectPath;
this._cancellable = params.cancellable;
this._managerProxy = new Gio.DBusProxy({ g_connection: this._connection,
g_interface_name: ObjectManagerInfo.name,
g_interface_info: ObjectManagerInfo,
g_name: this._serviceName,
g_object_path: this._managerPath,
g_flags: Gio.DBusProxyFlags.NONE });
this._interfaceInfos = {};
this._objects = {};
this._interfaces = {};
this._onLoaded = params.onLoaded;
if (params.knownInterfaces)
this._registerInterfaces(params.knownInterfaces);
// Start out inhibiting load until at least the proxy
// manager is loaded and the remote objects are fetched
this._numLoadInhibitors = 1;
this._managerProxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable,
Lang.bind(this, this._onManagerProxyLoaded));
},
_tryToCompleteLoad: function() {
this._numLoadInhibitors--;
if (this._numLoadInhibitors == 0) {
if (this._onLoaded)
this._onLoaded();
}
},
_addInterface: function(objectPath, interfaceName, onFinished) {
let info = this._interfaceInfos[interfaceName];
if (!info) {
if (onFinished)
onFinished();
return;
}
let proxy = new Gio.DBusProxy({ g_connection: this._connection,
g_name: this._serviceName,
g_object_path: objectPath,
g_interface_name: interfaceName,
g_interface_info: info,
g_flags: Gio.DBusProxyFlags.NONE });
proxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable,
Lang.bind(this, function(initable, result) {
let error = null;
try {
initable.init_finish(result);
} catch(e) {
logError(e, 'could not initialize proxy for interface ' + interfaceName);
if (onFinished)
onFinished();
return;
}
let isNewObject;
if (!this._objects[objectPath]) {
this._objects[objectPath] = {};
isNewObject = true;
} else {
isNewObject = false;
}
this._objects[objectPath][interfaceName] = proxy;
if (!this._interfaces[interfaceName])
this._interfaces[interfaceName] = [];
this._interfaces[interfaceName].push(proxy);
if (isNewObject)
this.emit('object-added', objectPath);
this.emit('interface-added', interfaceName, proxy);
if (onFinished)
onFinished();
}));
},
_removeInterface: function(objectPath, interfaceName) {
if (!this._objects[objectPath])
return;
let proxy = this._objects[objectPath][interfaceName];
if (this._interfaces[interfaceName]) {
let index = this._interfaces[interfaceName].indexOf(proxy);
if (index >= 0)
this._interfaces[interfaceName].splice(index, 1);
if (this._interfaces[interfaceName].length == 0)
delete this._interfaces[interfaceName];
}
this.emit('interface-removed', interfaceName, proxy);
this._objects[objectPath][interfaceName] = null;
if (Object.keys(this._objects[objectPath]).length == 0) {
delete this._objects[objectPath];
this.emit('object-removed', objectPath);
}
},
_onManagerProxyLoaded: function(initable, result) {
let error = null;
try {
initable.init_finish(result);
} catch(e) {
logError(e, 'could not initialize object manager for object ' + params.name);
this._tryToCompleteLoad();
return;
}
this._managerProxy.connectSignal('InterfacesAdded',
Lang.bind(this, function(objectManager, sender, [objectPath, interfaces]) {
let interfaceNames = Object.keys(interfaces);
for (let i = 0; i < interfaceNames.length; i++)
this._addInterface(objectPath, interfaceNames[i]);
}));
this._managerProxy.connectSignal('InterfacesRemoved',
Lang.bind(this, function(objectManager, sender, [objectPath, interfaceNames]) {
for (let i = 0; i < interfaceNames.length; i++)
this._removeInterface(objectPath, interfaceNames[i]);
}));
if (Object.keys(this._interfaceInfos).length == 0) {
this._tryToCompleteLoad();
return;
}
this._managerProxy.GetManagedObjectsRemote(Lang.bind(this, function(result, error) {
if (!result) {
if (error) {
logError(error, 'could not get remote objects for service ' + this._serviceName + ' path ' + this._managerPath);
}
this._tryToCompleteLoad();
return;
}
let [objects] = result;
let objectPaths = Object.keys(objects);
for (let i = 0; i < objectPaths.length; i++) {
let objectPath = objectPaths[i];
let object = objects[objectPath];
let interfaceNames = Object.getOwnPropertyNames(object);
for (let j = 0; j < interfaceNames.length; j++) {
let interfaceName = interfaceNames[j];
// Prevent load from completing until the interface is loaded
this._numLoadInhibitors++;
this._addInterface(objectPath,
interfaceName,
Lang.bind(this, this._tryToCompleteLoad));
}
}
this._tryToCompleteLoad();
}));
},
_registerInterfaces: function(interfaces) {
for (let i = 0; i < interfaces.length; i++) {
let info = Gio.DBusInterfaceInfo.new_for_xml(interfaces[i]);
this._interfaceInfos[info.name] = info;
}
},
getProxy: function(objectPath, interfaceName) {
let object = this._objects[objectPath];
if (!object)
return null;
return object[interfaceName];
},
getProxiesForInterface: function(interfaceName) {
let proxyList = this._interfaces[interfaceName];
if (!proxyList)
return [];
return proxyList;
},
getAllProxies: function() {
let proxies = [];
let objectPaths = Object.keys(this._objects);
for (let i = 0; i < objectPaths.length; i++) {
let object = this._objects[objectPaths];
let interfaceNames = Object.keys(object);
for (let j = 0; i < interfaceNames.length; i++) {
let interfaceName = interfaceNames[i];
if (object[interfaceName])
proxies.push(object(interfaceName));
}
}
return proxies;
}
});
Signals.addSignalMethods(ObjectManager.prototype);

View File

@ -1,119 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const ObjectManager = imports.misc.objectManager;
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;
function getSmartcardManager() {
if (_smartcardManager == null)
_smartcardManager = new SmartcardManager();
return _smartcardManager;
}
const SmartcardManager = new Lang.Class({
Name: 'SmartcardManager',
_init: function() {
this._objectManager = new ObjectManager.ObjectManager({ connection: Gio.DBus.session,
name: "org.gnome.SettingsDaemon.Smartcard",
objectPath: '/org/gnome/SettingsDaemon/Smartcard',
knownInterfaces: [ SmartcardTokenIface ],
onLoaded: Lang.bind(this, this._onLoaded) });
this._insertedTokens = {};
this._loginToken = null;
},
_onLoaded: function() {
let tokens = this._objectManager.getProxiesForInterface('org.gnome.SettingsDaemon.Smartcard.Token');
for (let i = 0; i < tokens.length; i++)
this._addToken(tokens[i]);
this._objectManager.connect('interface-added', Lang.bind(this, function(objectManager, interfaceName, proxy) {
if (interfaceName == 'org.gnome.SettingsDaemon.Smartcard.Token')
this._addToken(proxy);
}));
this._objectManager.connect('interface-removed', Lang.bind(this, function(objectManager, interfaceName, proxy) {
if (interfaceName == 'org.gnome.SettingsDaemon.Smartcard.Token')
this._removeToken(proxy);
}));
},
_updateToken: function(token) {
let objectPath = token.get_object_path();
delete this._insertedTokens[objectPath];
if (token.IsInserted)
this._insertedTokens[objectPath] = token;
if (token.UsedToLogin)
this._loginToken = token;
},
_addToken: function(token) {
this._updateToken(token);
token.connect('g-properties-changed',
Lang.bind(this, function(proxy, properties) {
if ('IsInserted' in properties.deep_unpack()) {
this._updateToken(token);
if (token.IsInserted) {
this.emit('smartcard-inserted', token);
} else {
this.emit('smartcard-removed', token);
}
}
}));
// Emit a smartcard-inserted at startup if it's already plugged in
if (token.IsInserted)
this.emit('smartcard-inserted', token);
},
_removeToken: function(token) {
let objectPath = token.get_object_path();
if (this._insertedTokens[objectPath] == token) {
delete this._insertedTokens[objectPath];
this.emit('smartcard-removed', token);
}
if (this._loginToken == token)
this._loginToken = null;
token.disconnectAll();
},
hasInsertedTokens: function() {
return Object.keys(this._insertedTokens).length > 0;
},
hasInsertedLoginToken: function() {
if (!this._loginToken)
return false;
if (!this._loginToken.IsInserted)
return false;
return true;
}
});
Signals.addSignalMethods(SmartcardManager.prototype);

View File

@ -1,9 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const Lang = imports.lang;
const St = imports.gi.St; const St = imports.gi.St;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -20,7 +18,7 @@ const _urlRegexp = new RegExp(
'(^|' + _leadingJunk + ')' + '(^|' + _leadingJunk + ')' +
'(' + '(' +
'(?:' + '(?:' +
'(?:http|https|ftp)://' + // scheme:// '[a-z][\\w-]+://' + // scheme://
'|' + '|' +
'www\\d{0,3}[.]' + // www. 'www\\d{0,3}[.]' + // www.
'|' + '|' +
@ -80,22 +78,6 @@ 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(0, -1);
app.launch([], context);
} catch(err) {
_handleSpawnError(argv[0], err);
}
}
// trySpawn: // trySpawn:
// @argv: an argv array // @argv: an argv array
// //
@ -129,7 +111,7 @@ function trySpawn(argv)
// Dummy child watch; we don't want to double-fork internally // Dummy child watch; we don't want to double-fork internally
// because then we lose the parent-child relationship, which // because then we lose the parent-child relationship, which
// can break polkit. See https://bugzilla.redhat.com//show_bug.cgi?id=819275 // can break polkit. See https://bugzilla.redhat.com//show_bug.cgi?id=819275
GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function () {}); GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function () {}, null);
} }
// trySpawnCommandLine: // trySpawnCommandLine:
@ -153,10 +135,35 @@ function trySpawnCommandLine(command_line) {
} }
function _handleSpawnError(command, err) { function _handleSpawnError(command, err) {
let title = _("Execution of %s failed:").format(command); let title = _("Execution of '%s' failed:").format(command);
Main.notifyError(title, err.message); Main.notifyError(title, err.message);
} }
// killall:
// @processName: a process name
//
// Kills @processName. If no process with the given name is found,
// this will fail silently.
function killall(processName) {
try {
// pkill is more portable than killall, but on Linux at least
// it won't match if you pass more than 15 characters of the
// process name... However, if you use the '-f' flag to match
// the entire command line, it will work, but we have to be
// careful in that case that we can match
// '/usr/bin/processName' but not 'gedit processName.c' or
// whatever...
let argv = ['pkill', '-f', '^([^ ]*/)?' + processName + '($| )'];
GLib.spawn_sync(null, argv, null, GLib.SpawnFlags.SEARCH_PATH, null);
// It might be useful to return success/failure, but we'd need
// a wrapper around WIFEXITED and WEXITSTATUS. Since none of
// the current callers care, we don't bother.
} catch (e) {
logError(e, 'Failed to kill ' + processName);
}
}
// lowerBound: // lowerBound:
// @array: an array or array-like object, already sorted // @array: an array or array-like object, already sorted
// according to @cmp // according to @cmp
@ -207,57 +214,28 @@ function insertSorted(array, val, cmp) {
return pos; return pos;
} }
const CloseButton = new Lang.Class({ function makeCloseButton() {
Name: 'CloseButton', let closeButton = new St.Button({ style_class: 'notification-close'});
Extends: St.Button,
_init: function(boxpointer) { // This is a bit tricky. St.Bin has its own x-align/y-align properties
this.parent({ style_class: 'notification-close'}); // 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);
// This is a bit tricky. St.Bin has its own x-align/y-align properties // XXX Clutter 2.0 workaround: ClutterBinLayout needs expand
// that compete with Clutter's properties. This should be fixed for // to respect the alignments.
// Clutter 2.0. Since St.Bin doesn't define its own setters, the closeButton.set_x_expand(true);
// setters are a workaround to get Clutter's version. closeButton.set_y_expand(true);
this.set_x_align(Clutter.ActorAlign.END);
this.set_y_align(Clutter.ActorAlign.START);
// XXX Clutter 2.0 workaround: ClutterBinLayout needs expand closeButton.connect('style-changed', function() {
// to respect the alignments. let themeNode = closeButton.get_theme_node();
this.set_x_expand(true); closeButton.translation_x = themeNode.get_length('-shell-close-overlap-x');
this.set_y_expand(true); closeButton.translation_y = themeNode.get_length('-shell-close-overlap-y');
});
this._boxPointer = boxpointer; return closeButton;
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) { function ensureActorVisibleInScrollView(scrollView, actor) {

View File

@ -72,9 +72,6 @@ function run() {
Scripting.defineScriptEvent("applicationsShowStart", "Starting to switch to applications view"); Scripting.defineScriptEvent("applicationsShowStart", "Starting to switch to applications view");
Scripting.defineScriptEvent("applicationsShowDone", "Done switching to applications view"); Scripting.defineScriptEvent("applicationsShowDone", "Done switching to applications view");
// Enable recording of timestamps for different points in the frame cycle
global.frame_timestamps = true;
Main.overview.connect('shown', function() { Main.overview.connect('shown', function() {
Scripting.scriptEvent('overviewShowDone'); Scripting.scriptEvent('overviewShowDone');
}); });
@ -90,10 +87,7 @@ function run() {
yield Scripting.destroyTestWindows(); yield Scripting.destroyTestWindows();
for (let k = 0; k < config.count; k++) for (let k = 0; k < config.count; k++)
yield Scripting.createTestWindow({ width: config.width, yield Scripting.createTestWindow(config.width, config.height, config.alpha, config.maximized);
height: config.height,
alpha: config.alpha,
maximized: config.maximized });
yield Scripting.waitTestWindows(); yield Scripting.waitTestWindows();
yield Scripting.sleep(1000); yield Scripting.sleep(1000);

View File

@ -1,308 +0,0 @@
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
const Main = imports.ui.main;
const Scripting = imports.ui.scripting;
const Shell = imports.gi.Shell;
let METRICS = {
timeToDesktop:
{ description: "Time from starting graphical.target to desktop showing",
units: "us" },
overviewShowTime:
{ description: "Time to switch to overview view, first time",
units: "us" },
applicationsShowTime:
{ description: "Time to switch to applications view, first time",
units: "us" },
mainViewRedrawTime:
{ description: "Time to redraw the main view, full screen",
units: "us" },
overviewRedrawTime:
{ description: "Time to redraw the overview, full screen, 5 windows",
units: "us" },
applicationRedrawTime:
{ description: "Time to redraw frame with a maximized application update",
units: "us" },
geditStartTime:
{ description: "Time from gedit launch to window drawn",
units: "us" },
}
function waitAndDraw(milliseconds) {
let cb;
let timeline = new Clutter.Timeline({ duration: milliseconds });
timeline.start();
timeline.connect('new-frame',
function(timeline, frame) {
global.stage.queue_redraw();
});
timeline.connect('completed',
function() {
timeline.stop();
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
}
function waitSignal(object, signal) {
let cb;
let id = object.connect(signal, function() {
object.disconnect(id);
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
}
function extractBootTimestamp() {
let sp = Gio.Subprocess.new(['journalctl', '-b',
'MESSAGE_ID=7d4958e842da4a758f6c1cdc7b36dcc5',
'UNIT=graphical.target',
'-o',
'json'],
Gio.SubprocessFlags.STDOUT_PIPE);
let result = null;
let datastream = Gio.DataInputStream.new(sp.get_stdout_pipe());
while (true) {
let [line, length] = datastream.read_line_utf8(null);
if (line === null)
break;
let fields = JSON.parse(line);
result = Number(fields['__MONOTONIC_TIMESTAMP']);
}
datastream.close(null);
return result;
}
function run() {
Scripting.defineScriptEvent("desktopShown", "Finished initial animation");
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
Scripting.defineScriptEvent("applicationsShowStart", "Starting to switch to applications view");
Scripting.defineScriptEvent("applicationsShowDone", "Done switching to applications view");
Scripting.defineScriptEvent("mainViewDrawStart", "Drawing main view");
Scripting.defineScriptEvent("mainViewDrawDone", "Ending timing main view drawing");
Scripting.defineScriptEvent("overviewDrawStart", "Drawing overview");
Scripting.defineScriptEvent("overviewDrawDone", "Ending timing overview drawing");
Scripting.defineScriptEvent("redrawTestStart", "Drawing application window");
Scripting.defineScriptEvent("redrawTestDone", "Ending timing application window drawing");
Scripting.defineScriptEvent("collectTimings", "Accumulate frame timings from redraw tests");
Scripting.defineScriptEvent("geditLaunch", "gedit application launch");
Scripting.defineScriptEvent("geditFirstFrame", "first frame of gedit window drawn");
yield Scripting.waitLeisure();
Scripting.scriptEvent('desktopShown');
Gtk.Settings.get_default().gtk_enable_animations = false;
Scripting.scriptEvent('overviewShowStart');
Main.overview.show();
yield Scripting.waitLeisure();
Scripting.scriptEvent('overviewShowDone');
yield Scripting.sleep(1000);
Scripting.scriptEvent('applicationsShowStart');
Main.overview._dash.showAppsButton.checked = true;
yield Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone');
yield Scripting.sleep(1000);
Main.overview.hide();
yield Scripting.waitLeisure();
////////////////////////////////////////
// Tests of redraw speed
////////////////////////////////////////
global.frame_timestamps = true;
global.frame_finish_timestamp = true;
for (let k = 0; k < 5; k++)
yield Scripting.createTestWindow(640, 480,
{ maximized: true });
yield Scripting.waitTestWindows();
yield Scripting.sleep(1000);
Scripting.scriptEvent('mainViewDrawStart');
yield waitAndDraw(1000);
Scripting.scriptEvent('mainViewDrawDone');
Main.overview.show();
Scripting.waitLeisure();
yield Scripting.sleep(1500);
Scripting.scriptEvent('overviewDrawStart');
yield waitAndDraw(1000);
Scripting.scriptEvent('overviewDrawDone');
yield Scripting.destroyTestWindows();
Main.overview.hide();
yield Scripting.createTestWindow(640, 480,
{ maximized: true,
redraws: true});
yield Scripting.waitTestWindows();
yield Scripting.sleep(1000);
Scripting.scriptEvent('redrawTestStart');
yield Scripting.sleep(1000);
Scripting.scriptEvent('redrawTestDone');
yield Scripting.sleep(1000);
Scripting.scriptEvent('collectTimings');
yield Scripting.destroyTestWindows();
global.frame_timestamps = false;
global.frame_finish_timestamp = false;
yield Scripting.sleep(1000);
////////////////////////////////////////
let appSys = Shell.AppSystem.get_default();
let app = appSys.lookup_app('org.gnome.gedit.desktop');
Scripting.scriptEvent('geditLaunch');
app.activate();
let windows = app.get_windows();
if (windows.length > 0)
throw new Error('gedit was already running');
while (windows.length == 0) {
yield waitSignal(global.display, 'window-created');
windows = app.get_windows();
}
let actor = windows[0].get_compositor_private();
yield waitSignal(actor, 'first-frame');
Scripting.scriptEvent('geditFirstFrame');
yield Scripting.sleep(1000);
windows[0].delete(global.get_current_time());
yield Scripting.sleep(1000);
Gtk.Settings.get_default().gtk_enable_animations = true;
}
let overviewShowStart;
let applicationsShowStart;
let stagePaintStart;
let redrawTiming;
let redrawTimes = {};
let geditLaunchTime;
function script_desktopShown(time) {
let bootTimestamp = extractBootTimestamp();
METRICS.timeToDesktop.value = time - bootTimestamp;
}
function script_overviewShowStart(time) {
overviewShowStart = time;
}
function script_overviewShowDone(time) {
METRICS.overviewShowTime.value = time - overviewShowStart;
}
function script_applicationsShowStart(time) {
applicationsShowStart = time;
}
function script_applicationsShowDone(time) {
METRICS.applicationsShowTime.value = time - applicationsShowStart;
}
function script_mainViewDrawStart(time) {
redrawTiming = 'mainView';
}
function script_mainViewDrawDone(time) {
redrawTiming = null;
}
function script_overviewDrawStart(time) {
redrawTiming = 'overview';
}
function script_overviewDrawDone(time) {
redrawTiming = null;
}
function script_redrawTestStart(time) {
redrawTiming = 'application';
}
function script_redrawTestDone(time) {
redrawTiming = null;
}
function script_collectTimings(time) {
for (let timing in redrawTimes) {
let times = redrawTimes[timing];
times.sort(function(a, b) { return a - b });
let len = times.length;
let median;
if (len == 0)
median = -1;
else if (len % 2 == 1)
median = times[(len - 1)/ 2];
else
median = Math.round((times[len / 2 - 1] + times[len / 2]) / 2);
METRICS[timing + 'RedrawTime'].value = median;
}
}
function script_geditLaunch(time) {
geditLaunchTime = time;
}
function script_geditFirstFrame(time) {
METRICS.geditStartTime.value = time - geditLaunchTime;
}
function clutter_stagePaintStart(time) {
stagePaintStart = time;
}
function clutter_paintCompletedTimestamp(time) {
if (redrawTiming != null && stagePaintStart != null) {
if (!(redrawTiming in redrawTimes))
redrawTimes[redrawTiming] = [];
redrawTimes[redrawTiming].push(time - stagePaintStart);
}
stagePaintStart = null;
}

View File

@ -1,247 +0,0 @@
const Format = imports.format;
const Gettext = imports.gettext;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Pango = imports.gi.Pango;
const Soup = imports.gi.Soup;
const WebKit = imports.gi.WebKit2;
const _ = Gettext.gettext;
const Config = imports.misc.config;
const PortalHelperResult = {
CANCELLED: 0,
COMPLETED: 1,
RECHECK: 2
};
const INACTIVITY_TIMEOUT = 30000; //ms
const CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT = 30 * GLib.USEC_PER_SEC;
const HelperDBusInterface = '<node> \
<interface name="org.gnome.Shell.PortalHelper"> \
<method name="Authenticate"> \
<arg type="o" direction="in" name="connection" /> \
<arg type="s" direction="in" name="url" /> \
<arg type="u" direction="in" name="timestamp" /> \
</method> \
<method name="Close"> \
<arg type="o" direction="in" name="connection" /> \
</method> \
<method name="Refresh"> \
<arg type="o" direction="in" name="connection" /> \
</method> \
<signal name="Done"> \
<arg type="o" name="connection" /> \
<arg type="u" name="result" /> \
</signal> \
</interface> \
</node>';
const PortalWindow = new Lang.Class({
Name: 'PortalWindow',
Extends: Gtk.ApplicationWindow,
_init: function(application, url, timestamp, doneCallback) {
this.parent({ application: application });
if (!url) {
url = 'http://www.gnome.org';
this._originalUrlWasGnome = true;
} else {
this._originalUrlWasGnome = false;
}
this._uri = new Soup.URI(url);
this._everSeenRedirect = false;
this._originalUrl = url;
this._doneCallback = doneCallback;
this._lastRecheck = 0;
this._recheckAtExit = false;
this._webView = new WebKit.WebView();
this._webView.connect('decide-policy', Lang.bind(this, this._onDecidePolicy));
this._webView.load_uri(url);
this._webView.connect('notify::title', Lang.bind(this, this._syncTitle));
this._syncTitle();
this.add(this._webView);
this._webView.show();
this.maximize();
this.present_with_time(timestamp);
},
_syncTitle: function() {
let title = this._webView.title;
if (title) {
this.title = title;
} else {
/* TRANSLATORS: this is the title of the wifi captive portal login
* window, until we know the title of the actual login page */
this.title = _("Web Authentication Redirect");
}
},
refresh: function() {
this._everSeenRedirect = false;
this._webView.load_uri(this._originalUrl);
},
vfunc_delete_event: function(event) {
if (this._recheckAtExit)
this._doneCallback(PortalHelperResult.RECHECK);
else
this._doneCallback(PortalHelperResult.CANCELLED);
return false;
},
_onDecidePolicy: function(view, decision, type) {
if (type == WebKit.PolicyDecisionType.NEW_WINDOW_ACTION) {
decision.ignore();
return true;
}
if (type != WebKit.PolicyDecisionType.NAVIGATION_ACTION)
return false;
let request = decision.get_request();
let uri = new Soup.URI(request.get_uri());
if (!uri.host_equal(this._uri) && this._originalUrlWasGnome) {
if (uri.get_host() == 'www.gnome.org' && this._everSeenRedirect) {
// Yay, we got to gnome!
decision.ignore();
this._doneCallback(PortalHelperResult.COMPLETED);
return true;
} else if (uri.get_host() != 'www.gnome.org') {
this._everSeenRedirect = true;
}
}
// We *may* have finished here, but we don't know for
// sure. Tell gnome-shell to run another connectivity check
// (but ratelimit the checks, we don't want to spam
// nmcheck.gnome.org for portals that have 10 or more internal
// redirects - and unfortunately they exist)
// If we hit the rate limit, we also queue a recheck
// when the window is closed, just in case we miss the
// final check and don't realize we're connected
// This should not be a problem in the cancelled logic,
// because if the user doesn't want to start the login,
// we should not see any redirect at all, outside this._uri
let now = GLib.get_monotonic_time();
let shouldRecheck = (now - this._lastRecheck) >
CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT;
if (shouldRecheck) {
this._lastRecheck = now;
this._recheckAtExit = false;
this._doneCallback(PortalHelperResult.RECHECK);
} else {
this._recheckAtExit = true;
}
// Update the URI, in case of chained redirects, so we still
// think we're doing the login until gnome-shell kills us
this._uri = uri;
decision.use();
return true;
},
});
const WebPortalHelper = new Lang.Class({
Name: 'WebPortalHelper',
Extends: Gtk.Application,
_init: function() {
this.parent({ application_id: 'org.gnome.Shell.PortalHelper',
flags: Gio.ApplicationFlags.IS_SERVICE,
inactivity_timeout: 30000 });
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(HelperDBusInterface, this);
this._queue = [];
},
vfunc_dbus_register: function(connection, path) {
this._dbusImpl.export(connection, path);
this.parent(connection, path);
return true;
},
vfunc_dbus_unregister: function(connection, path) {
this._dbusImpl.unexport_from_connection(connection);
this.parent(connection, path);
},
vfunc_activate: function() {
// If launched manually (for example for testing), force a dummy authentication
// session with the default url
this.Authenticate('/org/gnome/dummy', '', 0);
},
Authenticate: function(connection, url, timestamp) {
this._queue.push({ connection: connection, url: url, timestamp: timestamp });
this._processQueue();
},
Close: function(connection) {
for (let i = 0; i < this._queue.length; i++) {
let obj = this._queue[i];
if (obj.connection == connection) {
if (obj.window)
obj.window.destroy();
this._queue.splice(i, 1);
break;
}
}
this._processQueue();
},
Refresh: function(connection) {
for (let i = 0; i < this._queue.length; i++) {
let obj = this._queue[i];
if (obj.connection == connection) {
if (obj.window)
obj.window.refresh();
break;
}
}
},
_processQueue: function() {
if (this._queue.length == 0)
return;
let top = this._queue[0];
if (top.window != null)
return;
top.window = new PortalWindow(this, top.uri, top.timestamp, Lang.bind(this, function(result) {
this._dbusImpl.emit_signal('Done', new GLib.Variant('(ou)', [top.connection, result]));
}));
},
});
function initEnvironment() {
String.prototype.format = Format.format;
}
function main(argv) {
initEnvironment();
Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
Gettext.textdomain(Config.GETTEXT_PACKAGE);
let app = new WebPortalHelper();
return app.run(argv);
}

View File

@ -2,7 +2,6 @@
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta; const Meta = imports.gi.Meta;
@ -24,7 +23,7 @@ const WINDOW_PREVIEW_SIZE = 128;
const APP_ICON_SIZE = 96; const APP_ICON_SIZE = 96;
const APP_ICON_SIZE_SMALL = 48; const APP_ICON_SIZE_SMALL = 48;
const baseIconSizes = [96, 64, 48, 32, 22]; const iconSizes = [96, 64, 48, 32, 22];
const AppIconMode = { const AppIconMode = {
THUMBNAIL_ONLY: 1, THUMBNAIL_ONLY: 1,
@ -58,14 +57,6 @@ const AppSwitcherPopup = new Lang.Class({
this._currentWindow = -1; this._currentWindow = -1;
this.thumbnailsVisible = false; this.thumbnailsVisible = false;
let apps = Shell.AppSystem.get_default().get_running ();
if (apps.length == 0)
return;
this._switcherList = new AppSwitcher(apps, this);
this._items = this._switcherList.icons;
}, },
_allocate: function (actor, box, flags) { _allocate: function (actor, box, flags) {
@ -81,6 +72,7 @@ const AppSwitcherPopup = new Lang.Class({
let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT); let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
let rightPadding = this.actor.get_theme_node().get_padding(St.Side.RIGHT); let rightPadding = this.actor.get_theme_node().get_padding(St.Side.RIGHT);
let bottomPadding = this.actor.get_theme_node().get_padding(St.Side.BOTTOM); let bottomPadding = this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
let vPadding = this.actor.get_theme_node().get_vertical_padding();
let hPadding = leftPadding + rightPadding; let hPadding = leftPadding + rightPadding;
let icon = this._items[this._selectedIndex].actor; let icon = this._items[this._selectedIndex].actor;
@ -106,6 +98,18 @@ const AppSwitcherPopup = new Lang.Class({
} }
}, },
_createSwitcher: function() {
let apps = Shell.AppSystem.get_default().get_running ();
if (apps.length == 0)
return false;
this._switcherList = new AppSwitcher(apps, this);
this._items = this._switcherList.icons;
return true;
},
_initialSelection: function(backward, binding) { _initialSelection: function(backward, binding) {
if (binding == 'switch-group') { if (binding == 'switch-group') {
if (backward) { if (backward) {
@ -144,13 +148,13 @@ const AppSwitcherPopup = new Lang.Class({
this._items[this._selectedIndex].cachedWindows.length); this._items[this._selectedIndex].cachedWindows.length);
}, },
_keyPressHandler: function(keysym, action) { _keyPressHandler: function(keysym, backwards, action) {
if (action == Meta.KeyBindingAction.SWITCH_GROUP) { if (action == Meta.KeyBindingAction.SWITCH_GROUP) {
this._select(this._selectedIndex, this._nextWindow()); this._select(this._selectedIndex, backwards ? this._previousWindow() : this._nextWindow());
} else if (action == Meta.KeyBindingAction.SWITCH_GROUP_BACKWARD) { } else if (action == Meta.KeyBindingAction.SWITCH_GROUP_BACKWARD) {
this._select(this._selectedIndex, this._previousWindow()); this._select(this._selectedIndex, this._previousWindow());
} else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS) { } else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS) {
this._select(this._next()); this._select(backwards ? this._previous() : this._next());
} else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS_BACKWARD) { } else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS_BACKWARD) {
this._select(this._previous()); this._select(this._previous());
} else if (this._thumbnailsFocused) { } else if (this._thumbnailsFocused) {
@ -160,8 +164,6 @@ const AppSwitcherPopup = new Lang.Class({
this._select(this._selectedIndex, this._nextWindow()); this._select(this._selectedIndex, this._nextWindow());
else if (keysym == Clutter.Up) else if (keysym == Clutter.Up)
this._select(this._selectedIndex, null, true); this._select(this._selectedIndex, null, true);
else
return Clutter.EVENT_PROPAGATE;
} else { } else {
if (keysym == Clutter.Left) if (keysym == Clutter.Left)
this._select(this._previous()); this._select(this._previous());
@ -169,11 +171,7 @@ const AppSwitcherPopup = new Lang.Class({
this._select(this._next()); this._select(this._next());
else if (keysym == Clutter.Down) else if (keysym == Clutter.Down)
this._select(this._selectedIndex, 0); this._select(this._selectedIndex, 0);
else
return Clutter.EVENT_PROPAGATE;
} }
return Clutter.EVENT_STOP;
}, },
_scrollHandler: function(direction) { _scrollHandler: function(direction) {
@ -235,10 +233,8 @@ const AppSwitcherPopup = new Lang.Class({
_finish : function(timestamp) { _finish : function(timestamp) {
let appIcon = this._items[this._selectedIndex]; let appIcon = this._items[this._selectedIndex];
if (this._currentWindow < 0) let window = this._currentWindow > 0 ? this._currentWindow : 0;
appIcon.app.activate_window(appIcon.cachedWindows[0], timestamp); appIcon.app.activate_window(appIcon.cachedWindows[window], timestamp);
else
Main.activateWindow(appIcon.cachedWindows[this._currentWindow], timestamp);
this.parent(); this.parent();
}, },
@ -304,7 +300,6 @@ const AppSwitcherPopup = new Lang.Class({
this._thumbnailTimeoutId = Mainloop.timeout_add ( this._thumbnailTimeoutId = Mainloop.timeout_add (
THUMBNAIL_POPUP_TIME, THUMBNAIL_POPUP_TIME,
Lang.bind(this, this._timeoutPopupThumbnails)); Lang.bind(this, this._timeoutPopupThumbnails));
GLib.Source.set_name_by_id(this._thumbnailTimeoutId, '[gnome-shell] this._timeoutPopupThumbnails');
} }
}, },
@ -313,7 +308,7 @@ const AppSwitcherPopup = new Lang.Class({
this._createThumbnails(); this._createThumbnails();
this._thumbnailTimeoutId = 0; this._thumbnailTimeoutId = 0;
this._thumbnailsFocused = false; this._thumbnailsFocused = false;
return GLib.SOURCE_REMOVE; return false;
}, },
_destroyThumbnails : function() { _destroyThumbnails : function() {
@ -358,28 +353,37 @@ const WindowSwitcherPopup = new Lang.Class({
Name: 'WindowSwitcherPopup', Name: 'WindowSwitcherPopup',
Extends: SwitcherPopup.SwitcherPopup, Extends: SwitcherPopup.SwitcherPopup,
_init: function() { _getWindowList: function() {
this.parent(); let settings = new Gio.Settings({ schema: 'org.gnome.shell.window-switcher' });
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' }); let workspace = settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace()
: null;
return global.display.get_tab_list(Meta.TabList.NORMAL, global.screen, workspace);
},
_createSwitcher: function() {
let windows = this._getWindowList(); let windows = this._getWindowList();
if (windows.length == 0) if (windows.length == 0)
return; return false;
let mode = this._settings.get_enum('app-icon-mode'); this._switcherList = new WindowList(windows);
this._switcherList = new WindowList(windows, mode);
this._items = this._switcherList.icons; this._items = this._switcherList.icons;
return true;
}, },
_getWindowList: function() { _initialSelection: function(backward, binding) {
let workspace = this._settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() : null; if (binding == 'switch-windows-backward' || backward)
return global.display.get_tab_list(Meta.TabList.NORMAL, workspace); this._select(this._items.length - 1);
else if (this._items.length == 1)
this._select(0);
else
this._select(1);
}, },
_keyPressHandler: function(keysym, action) { _keyPressHandler: function(keysym, backwards, action) {
if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) { if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) {
this._select(this._next()); this._select(backwards ? this._previous() : this._next());
} else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD) { } else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD) {
this._select(this._previous()); this._select(this._previous());
} else { } else {
@ -387,11 +391,7 @@ const WindowSwitcherPopup = new Lang.Class({
this._select(this._previous()); this._select(this._previous());
else if (keysym == Clutter.Right) else if (keysym == Clutter.Right)
this._select(this._next()); this._select(this._next());
else
return Clutter.EVENT_PROPAGATE;
} }
return Clutter.EVENT_STOP;
}, },
_finish: function() { _finish: function() {
@ -418,6 +418,7 @@ const AppIcon = new Lang.Class({
set_size: function(size) { set_size: function(size) {
this.icon = this.app.create_icon_texture(size); this.icon = this.app.create_icon_texture(size);
this._iconBin.set_size(size, size);
this._iconBin.child = this.icon; this._iconBin.child = this.icon;
} }
}); });
@ -433,10 +434,8 @@ const AppSwitcher = new Lang.Class({
this._arrows = []; this._arrows = [];
let windowTracker = Shell.WindowTracker.get_default(); let windowTracker = Shell.WindowTracker.get_default();
let settings = new Gio.Settings({ schema_id: 'org.gnome.shell.app-switcher' }); let allWindows = global.display.get_tab_list(Meta.TabList.NORMAL,
let workspace = settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() global.screen, null);
: null;
let allWindows = global.display.get_tab_list(Meta.TabList.NORMAL, workspace);
// Construct the AppIcons, add to the popup // Construct the AppIcons, add to the popup
for (let i = 0; i < apps.length; i++) { for (let i = 0; i < apps.length; i++) {
@ -446,10 +445,7 @@ const AppSwitcher = new Lang.Class({
appIcon.cachedWindows = allWindows.filter(function(w) { appIcon.cachedWindows = allWindows.filter(function(w) {
return windowTracker.get_window_app (w) == appIcon.app; return windowTracker.get_window_app (w) == appIcon.app;
}); });
if (appIcon.cachedWindows.length > 0) this._addIcon(appIcon);
this._addIcon(appIcon);
else if (workspace == null)
throw new Error('%s appears to be running, but doesn\'t have any windows'.format(appIcon.app.get_name()));
} }
this._curApp = -1; this._curApp = -1;
@ -465,13 +461,12 @@ const AppSwitcher = new Lang.Class({
Mainloop.source_remove(this._mouseTimeOutId); Mainloop.source_remove(this._mouseTimeOutId);
}, },
_setIconSize: function() { _getPreferredHeight: function (actor, forWidth, alloc) {
let j = 0; let j = 0;
while(this._items.length > 1 && this._items[j].style_class != 'item-box') { while(this._items.length > 1 && this._items[j].style_class != 'item-box') {
j++; j++;
} }
let themeNode = this._items[j].get_theme_node(); let themeNode = this._items[j].get_theme_node();
let iconPadding = themeNode.get_horizontal_padding(); let iconPadding = themeNode.get_horizontal_padding();
let iconBorder = themeNode.get_border_width(St.Side.LEFT) + themeNode.get_border_width(St.Side.RIGHT); let iconBorder = themeNode.get_border_width(St.Side.LEFT) + themeNode.get_border_width(St.Side.RIGHT);
let [iconMinHeight, iconNaturalHeight] = this.icons[j].label.get_preferred_height(-1); let [iconMinHeight, iconNaturalHeight] = this.icons[j].label.get_preferred_height(-1);
@ -482,22 +477,19 @@ const AppSwitcher = new Lang.Class({
let primary = Main.layoutManager.primaryMonitor; let primary = Main.layoutManager.primaryMonitor;
let parentPadding = this.actor.get_parent().get_theme_node().get_horizontal_padding(); let parentPadding = this.actor.get_parent().get_theme_node().get_horizontal_padding();
let availWidth = primary.width - parentPadding - this.actor.get_theme_node().get_horizontal_padding(); let availWidth = primary.width - parentPadding - this.actor.get_theme_node().get_horizontal_padding();
let height = 0;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; for(let i = 0; i < iconSizes.length; i++) {
let iconSizes = baseIconSizes.map(function(s) { this._iconSize = iconSizes[i];
return s * scaleFactor; height = iconSizes[i] + iconSpacing;
});
if (this._items.length == 1) {
this._iconSize = baseIconSizes[0];
} else {
for(let i = 0; i < baseIconSizes.length; i++) {
this._iconSize = baseIconSizes[i];
let height = iconSizes[i] + iconSpacing;
let w = height * this._items.length + totalSpacing; let w = height * this._items.length + totalSpacing;
if (w <= availWidth) if (w <= availWidth)
break; break;
} }
if (this._items.length == 1) {
this._iconSize = iconSizes[0];
height = iconSizes[0] + iconSpacing;
} }
for(let i = 0; i < this.icons.length; i++) { for(let i = 0; i < this.icons.length; i++) {
@ -505,11 +497,9 @@ const AppSwitcher = new Lang.Class({
break; break;
this.icons[i].set_size(this._iconSize); this.icons[i].set_size(this._iconSize);
} }
},
_getPreferredHeight: function (actor, forWidth, alloc) { alloc.min_size = height;
this._setIconSize(); alloc.natural_size = height;
this.parent(actor, forWidth, alloc);
}, },
_allocate: function (actor, box, flags) { _allocate: function (actor, box, flags) {
@ -541,9 +531,8 @@ const AppSwitcher = new Lang.Class({
Lang.bind(this, function () { Lang.bind(this, function () {
this._enterItem(index); this._enterItem(index);
this._mouseTimeOutId = 0; this._mouseTimeOutId = 0;
return GLib.SOURCE_REMOVE; return false;
})); }));
GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem');
} else } else
this._itemEntered(index); this._itemEntered(index);
}, },
@ -643,19 +632,17 @@ const ThumbnailList = new Lang.Class({
totalPadding += this.actor.get_theme_node().get_horizontal_padding() + this.actor.get_theme_node().get_vertical_padding(); totalPadding += this.actor.get_theme_node().get_horizontal_padding() + this.actor.get_theme_node().get_vertical_padding();
let [labelMinHeight, labelNaturalHeight] = this._labels[0].get_preferred_height(-1); let [labelMinHeight, labelNaturalHeight] = this._labels[0].get_preferred_height(-1);
let spacing = this._items[0].child.get_theme_node().get_length('spacing'); let spacing = this._items[0].child.get_theme_node().get_length('spacing');
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let thumbnailSize = THUMBNAIL_DEFAULT_SIZE * scaleFactor;
availHeight = Math.min(availHeight - labelNaturalHeight - totalPadding - spacing, thumbnailSize); availHeight = Math.min(availHeight - labelNaturalHeight - totalPadding - spacing, THUMBNAIL_DEFAULT_SIZE);
let binHeight = availHeight + this._items[0].get_theme_node().get_vertical_padding() + this.actor.get_theme_node().get_vertical_padding() - spacing; let binHeight = availHeight + this._items[0].get_theme_node().get_vertical_padding() + this.actor.get_theme_node().get_vertical_padding() - spacing;
binHeight = Math.min(thumbnailSize, binHeight); binHeight = Math.min(THUMBNAIL_DEFAULT_SIZE, binHeight);
for (let i = 0; i < this._thumbnailBins.length; i++) { for (let i = 0; i < this._thumbnailBins.length; i++) {
let mutterWindow = this._windows[i].get_compositor_private(); let mutterWindow = this._windows[i].get_compositor_private();
if (!mutterWindow) if (!mutterWindow)
continue; continue;
let clone = _createWindowClone(mutterWindow, thumbnailSize); let clone = _createWindowClone(mutterWindow, THUMBNAIL_DEFAULT_SIZE);
this._thumbnailBins[i].set_height(binHeight); this._thumbnailBins[i].set_height(binHeight);
this._thumbnailBins[i].add_actor(clone); this._thumbnailBins[i].add_actor(clone);
this._clones.push(clone); this._clones.push(clone);
@ -669,7 +656,7 @@ const ThumbnailList = new Lang.Class({
const WindowIcon = new Lang.Class({ const WindowIcon = new Lang.Class({
Name: 'WindowIcon', Name: 'WindowIcon',
_init: function(window, mode) { _init: function(window) {
this.window = window; this.window = window;
this.actor = new St.BoxLayout({ style_class: 'alt-tab-app', this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
@ -687,7 +674,8 @@ const WindowIcon = new Lang.Class({
this._icon.destroy_all_children(); this._icon.destroy_all_children();
switch (mode) { let settings = new Gio.Settings({ schema: 'org.gnome.shell.window-switcher' });
switch (settings.get_enum('app-icon-mode')) {
case AppIconMode.THUMBNAIL_ONLY: case AppIconMode.THUMBNAIL_ONLY:
size = WINDOW_PREVIEW_SIZE; size = WINDOW_PREVIEW_SIZE;
this._icon.add_actor(_createWindowClone(mutterWindow, WINDOW_PREVIEW_SIZE)); this._icon.add_actor(_createWindowClone(mutterWindow, WINDOW_PREVIEW_SIZE));
@ -725,7 +713,7 @@ const WindowList = new Lang.Class({
Name: 'WindowList', Name: 'WindowList',
Extends: SwitcherPopup.SwitcherList, Extends: SwitcherPopup.SwitcherList,
_init : function(windows, mode) { _init : function(windows) {
this.parent(true); this.parent(true);
this._label = new St.Label({ x_align: Clutter.ActorAlign.CENTER, this._label = new St.Label({ x_align: Clutter.ActorAlign.CENTER,
@ -737,7 +725,7 @@ const WindowList = new Lang.Class({
for (let i = 0; i < windows.length; i++) { for (let i = 0; i < windows.length; i++) {
let win = windows[i]; let win = windows[i];
let icon = new WindowIcon(win, mode); let icon = new WindowIcon(win);
this.addItem(icon.actor, icon.label); this.addItem(icon.actor, icon.label);
this.icons.push(icon); this.icons.push(icon);

View File

@ -1,88 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const St = imports.gi.St;
const Signals = imports.signals;
const Atk = imports.gi.Atk;
const ANIMATED_ICON_UPDATE_TIMEOUT = 100;
const Animation = new Lang.Class({
Name: 'Animation',
_init: function(file, width, height, speed) {
this.actor = new St.Bin();
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._speed = speed;
this._isLoaded = false;
this._isPlaying = false;
this._timeoutId = 0;
this._frame = 0;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._animations = St.TextureCache.get_default().load_sliced_image (file, width, height, scaleFactor,
Lang.bind(this, this._animationsLoaded));
this.actor.set_child(this._animations);
},
play: function() {
if (this._isLoaded && this._timeoutId == 0) {
if (this._frame == 0)
this._showFrame(0);
this._timeoutId = Mainloop.timeout_add(this._speed, Lang.bind(this, this._update));
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._update');
}
this._isPlaying = true;
},
stop: function() {
if (this._timeoutId > 0) {
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
}
this._isPlaying = false;
},
_showFrame: function(frame) {
let oldFrameActor = this._animations.get_child_at_index(this._frame);
if (oldFrameActor)
oldFrameActor.hide();
this._frame = (frame % this._animations.get_n_children());
let newFrameActor = this._animations.get_child_at_index(this._frame);
if (newFrameActor)
newFrameActor.show();
},
_update: function() {
this._showFrame(this._frame + 1);
return GLib.SOURCE_CONTINUE;
},
_animationsLoaded: function() {
this._isLoaded = true;
if (this._isPlaying)
this.play();
},
_onDestroy: function() {
this.stop();
}
});
const AnimatedIcon = new Lang.Class({
Name: 'AnimatedIcon',
Extends: Animation,
_init: function(file, size) {
this.parent(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
}
});

File diff suppressed because it is too large Load Diff

View File

@ -6,36 +6,6 @@ const Signals = imports.signals;
const Main = imports.ui.main; const Main = imports.ui.main;
const RENAMED_DESKTOP_IDS = {
'baobab.desktop': 'org.gnome.baobab.desktop',
'cheese.desktop': 'org.gnome.Cheese.desktop',
'dconf-editor.desktop': 'ca.desrt.dconf-editor.desktop',
'file-roller.desktop': 'org.gnome.FileRoller.desktop',
'gcalctool.desktop': 'gnome-calculator.desktop',
'gedit.desktop': 'org.gnome.gedit.desktop',
'glchess.desktop': 'gnome-chess.desktop',
'glines.desktop': 'five-or-more.desktop',
'gnect.desktop': 'four-in-a-row.desktop',
'gnibbles.desktop': 'gnome-nibbles.desktop',
'gnobots2.desktop': 'gnome-robots.desktop',
'gnome-boxes.desktop': 'org.gnome.Boxes.desktop',
'gnome-clocks.desktop': 'org.gnome.clocks.desktop',
'gnome-contacts.desktop': 'org.gnome.Contacts.desktop',
'gnome-documents.desktop': 'org.gnome.Documents.desktop',
'gnome-font-viewer.desktop': 'org.gnome.font-viewer.desktop',
'gnome-photos.desktop': 'org.gnome.Photos.desktop',
'gnome-screenshot.desktop': 'org.gnome.Screenshot.desktop',
'gnome-software.desktop': 'org.gnome.Software.desktop',
'gnome-weather.desktop': 'org.gnome.Weather.Application.desktop',
'gnomine.desktop': 'gnome-mines.desktop',
'gnotravex.desktop': 'gnome-tetravex.desktop',
'gnotski.desktop': 'gnome-klotski.desktop',
'gtali.desktop': 'tali.desktop',
'nautilus.desktop': 'org.gnome.Nautilus.desktop',
'polari.desktop': 'org.gnome.Polari.desktop',
'totem.desktop': 'org.gnome.Totem.desktop',
};
const AppFavorites = new Lang.Class({ const AppFavorites = new Lang.Class({
Name: 'AppFavorites', Name: 'AppFavorites',
@ -44,31 +14,16 @@ const AppFavorites = new Lang.Class({
_init: function() { _init: function() {
this._favorites = {}; this._favorites = {};
global.settings.connect('changed::' + this.FAVORITE_APPS_KEY, Lang.bind(this, this._onFavsChanged)); global.settings.connect('changed::' + this.FAVORITE_APPS_KEY, Lang.bind(this, this._onFavsChanged));
this.reload(); this._reload();
}, },
_onFavsChanged: function() { _onFavsChanged: function() {
this.reload(); this._reload();
this.emit('changed'); this.emit('changed');
}, },
reload: function() { _reload: function() {
let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY); let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY);
// Map old desktop file names to the current ones
let updated = false;
ids = ids.map(function (id) {
let newId = RENAMED_DESKTOP_IDS[id];
if (newId !== undefined) {
updated = true;
return newId;
}
return id;
});
// ... and write back the updated desktop file names
if (updated)
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
let appSys = Shell.AppSystem.get_default(); let appSys = Shell.AppSystem.get_default();
let apps = ids.map(function (id) { let apps = ids.map(function (id) {
return appSys.lookup_app(id); return appSys.lookup_app(id);

File diff suppressed because it is too large Load Diff

View File

@ -13,8 +13,8 @@ const BackgroundMenu = new Lang.Class({
Name: 'BackgroundMenu', Name: 'BackgroundMenu',
Extends: PopupMenu.PopupMenu, Extends: PopupMenu.PopupMenu,
_init: function(layoutManager) { _init: function(source) {
this.parent(layoutManager.dummyCursor, 0, St.Side.TOP); this.parent(source, 0, St.Side.TOP);
this.addSettingsAction(_("Settings"), 'gnome-control-center.desktop'); this.addSettingsAction(_("Settings"), 'gnome-control-center.desktop');
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
@ -22,51 +22,43 @@ const BackgroundMenu = new Lang.Class({
this.actor.add_style_class_name('background-menu'); this.actor.add_style_class_name('background-menu');
layoutManager.uiGroup.add_actor(this.actor); Main.uiGroup.add_actor(this.actor);
this.actor.hide(); this.actor.hide();
} }
}); });
function addBackgroundMenu(actor, layoutManager) { function addBackgroundMenu(actor) {
let cursor = new St.Bin({ opacity: 0 });
Main.uiGroup.add_actor(cursor);
actor.reactive = true; actor.reactive = true;
actor._backgroundMenu = new BackgroundMenu(layoutManager); actor._backgroundMenu = new BackgroundMenu(cursor);
actor._backgroundManager = new PopupMenu.PopupMenuManager({ actor: actor }); actor._backgroundManager = new PopupMenu.PopupMenuManager({ actor: actor });
actor._backgroundManager.addMenu(actor._backgroundMenu); actor._backgroundManager.addMenu(actor._backgroundMenu);
function openMenu(x, y) { function openMenu() {
Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0); let [x, y] = global.get_pointer();
cursor.set_position(x, y);
actor._backgroundMenu.open(BoxPointer.PopupAnimation.NONE); actor._backgroundMenu.open(BoxPointer.PopupAnimation.NONE);
} }
let clickAction = new Clutter.ClickAction(); let clickAction = new Clutter.ClickAction();
clickAction.connect('long-press', function(action, actor, state) { clickAction.connect('long-press', function(action, actor, state) {
if (state == Clutter.LongPressState.QUERY) if (state == Clutter.LongPressState.QUERY)
return ((action.get_button() == 0 || return action.get_button() == 1 && !actor._backgroundMenu.isOpen;
action.get_button() == 1) && if (state == Clutter.LongPressState.ACTIVATE)
!actor._backgroundMenu.isOpen); openMenu();
if (state == Clutter.LongPressState.ACTIVATE) {
let [x, y] = action.get_coords();
openMenu(x, y);
actor._backgroundManager.ignoreRelease();
}
return true; return true;
}); });
clickAction.connect('clicked', function(action) { clickAction.connect('clicked', function(action) {
if (action.get_button() == 3) { if (action.get_button() == 3)
let [x, y] = action.get_coords(); openMenu();
openMenu(x, y);
}
}); });
actor.add_action(clickAction); actor.add_action(clickAction);
let grabOpBeginId = global.display.connect('grab-op-begin', function () {
clickAction.release();
});
actor.connect('destroy', function() { actor.connect('destroy', function() {
actor._backgroundMenu.destroy(); actor._backgroundMenu.destroy();
actor._backgroundMenu = null; actor._backgroundMenu = null;
actor._backgroundManager = null; actor._backgroundManager = null;
global.display.disconnect(grabOpBeginId); });
});
} }

View File

@ -3,9 +3,8 @@
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Lang = imports.lang; const Lang = imports.lang;
const Meta = imports.gi.Meta; const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St; const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
@ -62,14 +61,10 @@ const BoxPointer = new Lang.Class({
this._muteInput(); this._muteInput();
}, },
get arrowSide() {
return this._arrowSide;
},
_muteInput: function() { _muteInput: function() {
if (this._capturedEventId == 0) if (this._capturedEventId == 0)
this._capturedEventId = this.actor.connect('captured-event', this._capturedEventId = this.actor.connect('captured-event',
function() { return Clutter.EVENT_STOP; }); function() { return true; });
}, },
_unmuteInput: function() { _unmuteInput: function() {
@ -121,9 +116,6 @@ const BoxPointer = new Lang.Class({
}, },
hide: function(animate, onComplete) { hide: function(animate, onComplete) {
if (!this.actor.visible)
return;
let xOffset = 0; let xOffset = 0;
let yOffset = 0; let yOffset = 0;
let themeNode = this.actor.get_theme_node(); let themeNode = this.actor.get_theme_node();
@ -188,9 +180,7 @@ const BoxPointer = new Lang.Class({
}, },
_getPreferredHeight: function(actor, forWidth, alloc) { _getPreferredHeight: function(actor, forWidth, alloc) {
let themeNode = this.actor.get_theme_node(); let [minSize, naturalSize] = this.bin.get_preferred_height(forWidth);
let borderWidth = themeNode.get_length('-arrow-border-width');
let [minSize, naturalSize] = this.bin.get_preferred_height(forWidth - 2 * borderWidth);
alloc.min_size = minSize; alloc.min_size = minSize;
alloc.natural_size = naturalSize; alloc.natural_size = naturalSize;
this._adjustAllocationForArrow(false, alloc); this._adjustAllocationForArrow(false, alloc);
@ -287,40 +277,38 @@ const BoxPointer = new Lang.Class({
let skipBottomLeft = false; let skipBottomLeft = false;
let skipBottomRight = false; let skipBottomRight = false;
if (rise) { switch (this._arrowSide) {
switch (this._arrowSide) { case St.Side.TOP:
case St.Side.TOP: if (this._arrowOrigin == x1)
if (this._arrowOrigin == x1) skipTopLeft = true;
skipTopLeft = true; else if (this._arrowOrigin == x2)
else if (this._arrowOrigin == x2) skipTopRight = true;
skipTopRight = true; break;
break;
case St.Side.RIGHT: case St.Side.RIGHT:
if (this._arrowOrigin == y1) if (this._arrowOrigin == y1)
skipTopRight = true; skipTopRight = true;
else if (this._arrowOrigin == y2) else if (this._arrowOrigin == y2)
skipBottomRight = true; skipBottomRight = true;
break; break;
case St.Side.BOTTOM: case St.Side.BOTTOM:
if (this._arrowOrigin == x1) if (this._arrowOrigin == x1)
skipBottomLeft = true; skipBottomLeft = true;
else if (this._arrowOrigin == x2) else if (this._arrowOrigin == x2)
skipBottomRight = true; skipBottomRight = true;
break; break;
case St.Side.LEFT: case St.Side.LEFT:
if (this._arrowOrigin == y1) if (this._arrowOrigin == y1)
skipTopLeft = true; skipTopLeft = true;
else if (this._arrowOrigin == y2) else if (this._arrowOrigin == y2)
skipBottomLeft = true; skipBottomLeft = true;
break; break;
}
} }
cr.moveTo(x1 + borderRadius, y1); cr.moveTo(x1 + borderRadius, y1);
if (this._arrowSide == St.Side.TOP && rise) { if (this._arrowSide == St.Side.TOP) {
if (skipTopLeft) { if (skipTopLeft) {
cr.moveTo(x1, y2 - borderRadius); cr.moveTo(x1, y2 - borderRadius);
cr.lineTo(x1, y1 - rise); cr.lineTo(x1, y1 - rise);
@ -342,7 +330,7 @@ const BoxPointer = new Lang.Class({
3*Math.PI/2, Math.PI*2); 3*Math.PI/2, Math.PI*2);
} }
if (this._arrowSide == St.Side.RIGHT && rise) { if (this._arrowSide == St.Side.RIGHT) {
if (skipTopRight) { if (skipTopRight) {
cr.lineTo(x2 + rise, y1); cr.lineTo(x2 + rise, y1);
cr.lineTo(x2 + rise, y1 + halfBase); cr.lineTo(x2 + rise, y1 + halfBase);
@ -363,7 +351,7 @@ const BoxPointer = new Lang.Class({
0, Math.PI/2); 0, Math.PI/2);
} }
if (this._arrowSide == St.Side.BOTTOM && rise) { if (this._arrowSide == St.Side.BOTTOM) {
if (skipBottomLeft) { if (skipBottomLeft) {
cr.lineTo(x1 + halfBase, y2); cr.lineTo(x1 + halfBase, y2);
cr.lineTo(x1, y2 + rise); cr.lineTo(x1, y2 + rise);
@ -384,7 +372,7 @@ const BoxPointer = new Lang.Class({
Math.PI/2, Math.PI); Math.PI/2, Math.PI);
} }
if (this._arrowSide == St.Side.LEFT && rise) { if (this._arrowSide == St.Side.LEFT) {
if (skipTopLeft) { if (skipTopLeft) {
cr.lineTo(x1, y1 + halfBase); cr.lineTo(x1, y1 + halfBase);
cr.lineTo(x1 - rise, y1); cr.lineTo(x1 - rise, y1);
@ -601,12 +589,12 @@ const BoxPointer = new Lang.Class({
return St.Side.TOP; return St.Side.TOP;
break; break;
case St.Side.LEFT: case St.Side.LEFT:
if (sourceAllocation.x2 + boxWidth > monitor.x + monitor.width && if (sourceAllocation.y2 + boxWidth > monitor.x + monitor.width &&
boxWidth < sourceAllocation.x1 - monitor.x) boxWidth < sourceAllocation.x1 - monitor.x)
return St.Side.RIGHT; return St.Side.RIGHT;
break; break;
case St.Side.RIGHT: case St.Side.RIGHT:
if (sourceAllocation.x1 - boxWidth < monitor.x && if (sourceAllocation.y1 - boxWidth < monitor.x &&
boxWidth < monitor.x + monitor.width - sourceAllocation.x2) boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
return St.Side.LEFT; return St.Side.LEFT;
break; break;
@ -624,8 +612,6 @@ const BoxPointer = new Lang.Class({
this._container.queue_relayout(); this._container.queue_relayout();
return false; return false;
})); }));
this.emit('arrow-side-changed');
} }
}, },
@ -653,21 +639,5 @@ const BoxPointer = new Lang.Class({
get opacity() { get opacity() {
return this.actor.opacity; return this.actor.opacity;
},
updateArrowSide: function(side) {
this._arrowSide = side;
this._border.queue_repaint();
this.emit('arrow-side-changed');
},
getPadding: function(side) {
return this.bin.get_theme_node().get_padding(side);
},
getArrowHeight: function() {
return this.actor.get_theme_node().get_length('-arrow-rise');
} }
}); });
Signals.addSignalMethods(BoxPointer.prototype);

View File

@ -13,31 +13,26 @@ const Shell = imports.gi.Shell;
const MSECS_IN_DAY = 24 * 60 * 60 * 1000; const MSECS_IN_DAY = 24 * 60 * 60 * 1000;
const SHOW_WEEKDATE_KEY = 'show-weekdate'; const SHOW_WEEKDATE_KEY = 'show-weekdate';
const ELLIPSIS_CHAR = '\u2026';
// alias to prevent xgettext from picking up strings translated in GTK+
const gtk30_ = Gettext_gtk30.gettext;
const NC_ = function(context, str) { return str; };
// in org.gnome.desktop.interface // in org.gnome.desktop.interface
const CLOCK_FORMAT_KEY = 'clock-format'; const CLOCK_FORMAT_KEY = 'clock-format';
function _sameDay(dateA, dateB) {
return (dateA.getDate() == dateB.getDate() &&
dateA.getMonth() == dateB.getMonth() &&
dateA.getYear() == dateB.getYear());
}
function _sameYear(dateA, dateB) { function _sameYear(dateA, dateB) {
return (dateA.getYear() == dateB.getYear()); return (dateA.getYear() == dateB.getYear());
} }
function _sameMonth(dateA, dateB) { /* TODO: maybe needs config - right now we assume that Saturday and
return _sameYear(dateA, dateB) && (dateA.getMonth() == dateB.getMonth()); * Sunday are non-work days (not true in e.g. Israel, it's Sunday and
} * Monday there)
*/
function _sameDay(dateA, dateB) {
return _sameMonth(dateA, dateB) && (dateA.getDate() == dateB.getDate());
}
function _isWorkDay(date) { function _isWorkDay(date) {
/* Translators: Enter 0-6 (Sunday-Saturday) for non-work days. Examples: "0" (Sunday) "6" (Saturday) "06" (Sunday and Saturday). */ return date.getDay() != 0 && date.getDay() != 6;
let days = C_('calendar-no-work', "06");
return days.indexOf(date.getDay().toString()) == -1;
} }
function _getBeginningOfDay(date) { function _getBeginningOfDay(date) {
@ -58,21 +53,19 @@ function _getEndOfDay(date) {
return ret; return ret;
} }
function _formatEventTime(event, clockFormat, periodBegin, periodEnd) { function _formatEventTime(event, clockFormat) {
let ret; let ret;
let allDay = (event.allDay || (event.date <= periodBegin && event.end >= periodEnd)); if (event.allDay) {
if (allDay) {
/* Translators: Shown in calendar event list for all day events /* Translators: Shown in calendar event list for all day events
* Keep it short, best if you can use less then 10 characters * Keep it short, best if you can use less then 10 characters
*/ */
ret = C_("event list time", "All Day"); ret = C_("event list time", "All Day");
} else { } else {
let date = event.date >= periodBegin ? event.date : event.end;
switch (clockFormat) { switch (clockFormat) {
case '24h': case '24h':
/* Translators: Shown in calendar event list, if 24h format, /* Translators: Shown in calendar event list, if 24h format,
\u2236 is a ratio character, similar to : */ \u2236 is a ratio character, similar to : */
ret = date.toLocaleFormat(C_("event list time", "%H\u2236%M")); ret = event.date.toLocaleFormat(C_("event list time", "%H\u2236%M"));
break; break;
default: default:
@ -81,13 +74,30 @@ function _formatEventTime(event, clockFormat, periodBegin, periodEnd) {
/* Translators: Shown in calendar event list, if 12h format, /* Translators: Shown in calendar event list, if 12h format,
\u2236 is a ratio character, similar to : and \u2009 is \u2236 is a ratio character, similar to : and \u2009 is
a thin space */ a thin space */
ret = date.toLocaleFormat(C_("event list time", "%l\u2236%M\u2009%p")); ret = event.date.toLocaleFormat(C_("event list time", "%l\u2236%M\u2009%p"));
break; break;
} }
} }
return ret; return ret;
} }
function _getCalendarWeekForDate(date) {
// Based on the algorithms found here:
// http://en.wikipedia.org/wiki/Talk:ISO_week_date
let midnightDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
// Need to get Monday to be 1 ... Sunday to be 7
let dayOfWeek = 1 + ((midnightDate.getDay() + 6) % 7);
let nearestThursday = new Date(midnightDate.getFullYear(), midnightDate.getMonth(),
midnightDate.getDate() + (4 - dayOfWeek));
let jan1st = new Date(nearestThursday.getFullYear(), 0, 1);
let diffDate = nearestThursday - jan1st;
let dayNumber = Math.floor(Math.abs(diffDate) / MSECS_IN_DAY);
let weekNumber = Math.floor(dayNumber / 7) + 1;
return weekNumber;
}
function _getCalendarDayAbbreviation(dayNumber) { function _getCalendarDayAbbreviation(dayNumber) {
let abbreviations = [ let abbreviations = [
/* Translators: Calendar grid abbreviation for Sunday. /* Translators: Calendar grid abbreviation for Sunday.
@ -180,18 +190,16 @@ const EmptyEventSource = new Lang.Class({
}); });
Signals.addSignalMethods(EmptyEventSource.prototype); Signals.addSignalMethods(EmptyEventSource.prototype);
const CalendarServerIface = '<node> \ const CalendarServerIface = <interface name="org.gnome.Shell.CalendarServer">
<interface name="org.gnome.Shell.CalendarServer"> \ <method name="GetEvents">
<method name="GetEvents"> \ <arg type="x" direction="in" />
<arg type="x" direction="in" /> \ <arg type="x" direction="in" />
<arg type="x" direction="in" /> \ <arg type="b" direction="in" />
<arg type="b" direction="in" /> \ <arg type="a(sssbxxa{sv})" direction="out" />
<arg type="a(sssbxxa{sv})" direction="out" /> \ </method>
</method> \ <property name="HasCalendars" type="b" access="read" />
<property name="HasCalendars" type="b" access="read" /> \ <signal name="Changed" />
<signal name="Changed" /> \ </interface>;
</interface> \
</node>';
const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface); const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);
@ -233,24 +241,11 @@ const DBusEventSource = new Lang.Class({
this._initialized = false; this._initialized = false;
this._dbusProxy = new CalendarServer(); this._dbusProxy = new CalendarServer();
this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(object, result) { this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(object, result) {
let loaded = false;
try { try {
this._dbusProxy.init_finish(result); this._dbusProxy.init_finish(result);
loaded = true;
} catch(e) { } catch(e) {
if (e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) { log('Error loading calendars: ' + e.message);
// Ignore timeouts and install signals as normal, because with high return;
// probability the service will appear later on, and we will get a
// NameOwnerChanged which will finish loading
//
// (But still _initialized to false, because the proxy does not know
// about the HasCalendars property and would cause an exception trying
// to read it)
} else {
log('Error loading calendars: ' + e.message);
return;
}
} }
this._dbusProxy.connectSignal('Changed', Lang.bind(this, this._onChanged)); this._dbusProxy.connectSignal('Changed', Lang.bind(this, this._onChanged));
@ -266,11 +261,9 @@ const DBusEventSource = new Lang.Class({
this.emit('notify::has-calendars'); this.emit('notify::has-calendars');
})); }));
this._initialized = loaded; this._initialized = true;
if (loaded) { this.emit('notify::has-calendars');
this.emit('notify::has-calendars'); this._onNameAppeared();
this._onNameAppeared();
}
})); }));
}, },
@ -292,7 +285,6 @@ const DBusEventSource = new Lang.Class({
}, },
_onNameAppeared: function(owner) { _onNameAppeared: function(owner) {
this._initialized = true;
this._resetCache(); this._resetCache();
this._loadEvents(true); this._loadEvents(true);
}, },
@ -335,22 +327,25 @@ const DBusEventSource = new Lang.Class({
return; return;
if (this._curRequestBegin && this._curRequestEnd){ if (this._curRequestBegin && this._curRequestEnd){
let callFlags = Gio.DBusCallFlags.NO_AUTO_START;
if (forceReload)
callFlags = Gio.DBusCallFlags.NONE;
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000, this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000, this._curRequestEnd.getTime() / 1000,
forceReload, forceReload,
Lang.bind(this, this._onEventsReceived), Lang.bind(this, this._onEventsReceived),
Gio.DBusCallFlags.NONE); callFlags);
} }
}, },
requestRange: function(begin, end) { requestRange: function(begin, end, forceReload) {
if (!(_datesEqual(begin, this._lastRequestBegin) && _datesEqual(end, this._lastRequestEnd))) { if (forceReload || !(_datesEqual(begin, this._lastRequestBegin) && _datesEqual(end, this._lastRequestEnd))) {
this.isLoading = true; this.isLoading = true;
this._lastRequestBegin = begin; this._lastRequestBegin = begin;
this._lastRequestEnd = end; this._lastRequestEnd = end;
this._curRequestBegin = begin; this._curRequestBegin = begin;
this._curRequestEnd = end; this._curRequestEnd = end;
this._loadEvents(false); this._loadEvents(forceReload);
} }
}, },
@ -362,12 +357,6 @@ const DBusEventSource = new Lang.Class({
result.push(event); result.push(event);
} }
} }
result.sort(function(event1, event2) {
// sort events by end time on ending day
let d1 = event1.date < begin && event1.end <= end ? event1.end : event1.date;
let d2 = event2.date < begin && event2.end <= end ? event2.end : event2.date;
return d1.getTime() - d2.getTime();
});
return result; return result;
}, },
@ -390,14 +379,14 @@ const Calendar = new Lang.Class({
_init: function() { _init: function() {
this._weekStart = Shell.util_get_week_start(); this._weekStart = Shell.util_get_week_start();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.calendar' }); this._settings = new Gio.Settings({ schema: 'org.gnome.shell.calendar' });
this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, Lang.bind(this, this._onSettingsChange)); this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, Lang.bind(this, this._onSettingsChange));
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY); this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
// Find the ordering for month/year in the calendar heading // Find the ordering for month/year in the calendar heading
this._headerFormatWithoutYear = '%B'; this._headerFormatWithoutYear = '%B';
switch (gtk30_('calendar:MY')) { switch (Gettext_gtk30.gettext('calendar:MY')) {
case 'calendar:MY': case 'calendar:MY':
this._headerFormat = '%B %Y'; this._headerFormat = '%B %Y';
break; break;
@ -413,11 +402,9 @@ const Calendar = new Lang.Class({
// Start off with the current date // Start off with the current date
this._selectedDate = new Date(); this._selectedDate = new Date();
this._shouldDateGrabFocus = false; this.actor = new St.Table({ homogeneous: false,
style_class: 'calendar',
this.actor = new St.Widget({ style_class: 'calendar', reactive: true });
layout_manager: new Clutter.GridLayout(),
reactive: true });
this.actor.connect('scroll-event', this.actor.connect('scroll-event',
Lang.bind(this, this._onScroll)); Lang.bind(this, this._onScroll));
@ -430,47 +417,42 @@ const Calendar = new Lang.Class({
setEventSource: function(eventSource) { setEventSource: function(eventSource) {
this._eventSource = eventSource; this._eventSource = eventSource;
this._eventSource.connect('changed', Lang.bind(this, function() { this._eventSource.connect('changed', Lang.bind(this, function() {
this._rebuildCalendar(); this._update(false);
this._update();
})); }));
this._rebuildCalendar(); this._update(true);
this._update();
}, },
// Sets the calendar to show a specific date // Sets the calendar to show a specific date
setDate: function(date) { setDate: function(date, forceReload) {
if (_sameDay(date, this._selectedDate)) if (!_sameDay(date, this._selectedDate)) {
return; this._selectedDate = date;
this._update(forceReload);
this._selectedDate = date; this.emit('selected-date-changed', new Date(this._selectedDate));
this._update(); } else {
this.emit('selected-date-changed', new Date(this._selectedDate)); if (forceReload)
this._update(forceReload);
}
}, },
_buildHeader: function() { _buildHeader: function() {
let layout = this.actor.layout_manager;
let offsetCols = this._useWeekdate ? 1 : 0; let offsetCols = this._useWeekdate ? 1 : 0;
this.actor.destroy_all_children(); this.actor.destroy_all_children();
// Top line of the calendar '<| September 2009 |>' // Top line of the calendar '<| September 2009 |>'
this._topBox = new St.BoxLayout(); this._topBox = new St.BoxLayout();
layout.attach(this._topBox, 0, 0, offsetCols + 7, 1); this.actor.add(this._topBox,
{ row: 0, col: 0, col_span: offsetCols + 7 });
this._backButton = new St.Button({ style_class: 'calendar-change-month-back pager-button', let back = new St.Button({ style_class: 'calendar-change-month-back' });
accessible_name: _("Previous month"), this._topBox.add(back);
can_focus: true }); back.connect('clicked', Lang.bind(this, this._onPrevMonthButtonClicked));
this._topBox.add(this._backButton);
this._backButton.connect('clicked', Lang.bind(this, this._onPrevMonthButtonClicked));
this._monthLabel = new St.Label({style_class: 'calendar-month-label', this._monthLabel = new St.Label({style_class: 'calendar-month-label'});
can_focus: true });
this._topBox.add(this._monthLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE }); this._topBox.add(this._monthLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE });
this._forwardButton = new St.Button({ style_class: 'calendar-change-month-forward pager-button', let forward = new St.Button({ style_class: 'calendar-change-month-forward' });
accessible_name: _("Next month"), this._topBox.add(forward);
can_focus: true }); forward.connect('clicked', Lang.bind(this, this._onNextMonthButtonClicked));
this._topBox.add(this._forwardButton);
this._forwardButton.connect('clicked', Lang.bind(this, this._onNextMonthButtonClicked));
// Add weekday labels... // Add weekday labels...
// //
@ -486,12 +468,10 @@ const Calendar = new Lang.Class({
let customDayAbbrev = _getCalendarDayAbbreviation(iter.getDay()); let customDayAbbrev = _getCalendarDayAbbreviation(iter.getDay());
let label = new St.Label({ style_class: 'calendar-day-base calendar-day-heading', let label = new St.Label({ style_class: 'calendar-day-base calendar-day-heading',
text: customDayAbbrev }); text: customDayAbbrev });
let col; this.actor.add(label,
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) { row: 1,
col = 6 - (7 + iter.getDay() - this._weekStart) % 7; col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7,
else x_fill: false, x_align: St.Align.MIDDLE });
col = offsetCols + (7 + iter.getDay() - this._weekStart) % 7;
layout.attach(label, col, 1, 1, 1);
iter.setTime(iter.getTime() + MSECS_IN_DAY); iter.setTime(iter.getTime() + MSECS_IN_DAY);
} }
@ -510,7 +490,6 @@ const Calendar = new Lang.Class({
this._onNextMonthButtonClicked(); this._onNextMonthButtonClicked();
break; break;
} }
return Clutter.EVENT_PROPAGATE;
}, },
_onPrevMonthButtonClicked: function() { _onPrevMonthButtonClicked: function() {
@ -532,12 +511,10 @@ const Calendar = new Lang.Class({
} }
} }
this._backButton.grab_key_focus(); this.setDate(newDate, false);
},
this.setDate(newDate); _onNextMonthButtonClicked: function() {
},
_onNextMonthButtonClicked: function() {
let newDate = new Date(this._selectedDate); let newDate = new Date(this._selectedDate);
let oldMonth = newDate.getMonth(); let oldMonth = newDate.getMonth();
if (oldMonth == 11) { if (oldMonth == 11) {
@ -556,28 +533,28 @@ const Calendar = new Lang.Class({
} }
} }
this._forwardButton.grab_key_focus(); this.setDate(newDate, false);
this.setDate(newDate);
}, },
_onSettingsChange: function() { _onSettingsChange: function() {
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY); this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
this._buildHeader(); this._buildHeader();
this._rebuildCalendar(); this._update(false);
this._update();
}, },
_rebuildCalendar: function() { _update: function(forceReload) {
let now = new Date(); let now = new Date();
if (_sameYear(this._selectedDate, now))
this._monthLabel.text = this._selectedDate.toLocaleFormat(this._headerFormatWithoutYear);
else
this._monthLabel.text = this._selectedDate.toLocaleFormat(this._headerFormat);
// Remove everything but the topBox and the weekday labels // Remove everything but the topBox and the weekday labels
let children = this.actor.get_children(); let children = this.actor.get_children();
for (let i = this._firstDayIndex; i < children.length; i++) for (let i = this._firstDayIndex; i < children.length; i++)
children[i].destroy(); children[i].destroy();
this._buttons = [];
// Start at the beginning of the week before the start of the month // Start at the beginning of the week before the start of the month
// //
// We want to show always 6 weeks (to keep the calendar menu at the same // We want to show always 6 weeks (to keep the calendar menu at the same
@ -595,14 +572,11 @@ const Calendar = new Lang.Class({
// Actually computing the number of weeks is complex, but we know that the // Actually computing the number of weeks is complex, but we know that the
// problematic categories (2 and 4) always start on week start, and that // problematic categories (2 and 4) always start on week start, and that
// all months at the end have 6 weeks. // all months at the end have 6 weeks.
let beginDate = new Date(this._selectedDate); let beginDate = new Date(this._selectedDate);
beginDate.setDate(1); beginDate.setDate(1);
beginDate.setSeconds(0); beginDate.setSeconds(0);
beginDate.setHours(12); beginDate.setHours(12);
this._calendarBegin = new Date(beginDate);
this._markedAsToday = now;
let year = beginDate.getYear(); let year = beginDate.getYear();
let daysToWeekStart = (7 + beginDate.getDay() - this._weekStart) % 7; let daysToWeekStart = (7 + beginDate.getDay() - this._weekStart) % 7;
@ -611,33 +585,30 @@ const Calendar = new Lang.Class({
beginDate.setTime(beginDate.getTime() - (weekPadding + daysToWeekStart) * MSECS_IN_DAY); beginDate.setTime(beginDate.getTime() - (weekPadding + daysToWeekStart) * MSECS_IN_DAY);
let layout = this.actor.layout_manager;
let iter = new Date(beginDate); let iter = new Date(beginDate);
let row = 2; let row = 2;
// nRows here means 6 weeks + one header + one navbar // nRows here means 6 weeks + one header + one navbar
let nRows = 8; let nRows = 8;
while (row < 8) { while (row < 8) {
let button = new St.Button({ label: iter.getDate().toString(), let button = new St.Button({ label: iter.getDate().toString() });
can_focus: true });
let rtl = button.get_text_direction() == Clutter.TextDirection.RTL; let rtl = button.get_text_direction() == Clutter.TextDirection.RTL;
if (this._eventSource.isDummy) if (this._eventSource.isDummy)
button.reactive = false; button.reactive = false;
button._date = new Date(iter); let iterStr = iter.toUTCString();
button.connect('clicked', Lang.bind(this, function() { button.connect('clicked', Lang.bind(this, function() {
this._shouldDateGrabFocus = true; let newlySelectedDate = new Date(iterStr);
this.setDate(button._date); this.setDate(newlySelectedDate, false);
this._shouldDateGrabFocus = false;
})); }));
let hasEvents = this._eventSource.hasEvents(iter); let hasEvents = this._eventSource.hasEvents(iter);
let styleClass = 'calendar-day-base calendar-day'; let styleClass = 'calendar-day-base calendar-day';
if (_isWorkDay(iter)) if (_isWorkDay(iter))
styleClass += ' calendar-work-day'; styleClass += ' calendar-work-day'
else else
styleClass += ' calendar-nonwork-day'; styleClass += ' calendar-nonwork-day'
// Hack used in lieu of border-collapse - see gnome-shell.css // Hack used in lieu of border-collapse - see gnome-shell.css
if (row == 2) if (row == 2)
@ -653,25 +624,23 @@ const Calendar = new Lang.Class({
else if (iter.getMonth() != this._selectedDate.getMonth()) else if (iter.getMonth() != this._selectedDate.getMonth())
styleClass += ' calendar-other-month-day'; styleClass += ' calendar-other-month-day';
if (_sameDay(this._selectedDate, iter))
button.add_style_pseudo_class('active');
if (hasEvents) if (hasEvents)
styleClass += ' calendar-day-with-events'; styleClass += ' calendar-day-with-events'
button.style_class = styleClass; button.style_class = styleClass;
let offsetCols = this._useWeekdate ? 1 : 0; let offsetCols = this._useWeekdate ? 1 : 0;
let col; this.actor.add(button,
if (rtl) { row: row, col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7 });
col = 6 - (7 + iter.getDay() - this._weekStart) % 7;
else
col = offsetCols + (7 + iter.getDay() - this._weekStart) % 7;
layout.attach(button, col, row, 1, 1);
this._buttons.push(button);
if (this._useWeekdate && iter.getDay() == 4) { if (this._useWeekdate && iter.getDay() == 4) {
let label = new St.Label({ text: iter.toLocaleFormat('%V'), let label = new St.Label({ text: _getCalendarWeekForDate(iter).toString(),
style_class: 'calendar-day-base calendar-week-number'}); style_class: 'calendar-day-base calendar-week-number'});
layout.attach(label, rtl ? 7 : 0, row, 1, 1); this.actor.add(label,
{ row: row, col: 0, y_align: St.Align.MIDDLE });
} }
iter.setTime(iter.getTime() + MSECS_IN_DAY); iter.setTime(iter.getTime() + MSECS_IN_DAY);
@ -679,32 +648,9 @@ const Calendar = new Lang.Class({
if (iter.getDay() == this._weekStart) if (iter.getDay() == this._weekStart)
row++; row++;
} }
// Signal to the event source that we are interested in events // Signal to the event source that we are interested in events
// only from this date range // only from this date range
this._eventSource.requestRange(beginDate, iter); this._eventSource.requestRange(beginDate, iter, forceReload);
},
_update: function() {
let now = new Date();
if (_sameYear(this._selectedDate, now))
this._monthLabel.text = this._selectedDate.toLocaleFormat(this._headerFormatWithoutYear);
else
this._monthLabel.text = this._selectedDate.toLocaleFormat(this._headerFormat);
if (!this._calendarBegin || !_sameMonth(this._selectedDate, this._calendarBegin) || !_sameDay(now, this._markedAsToday))
this._rebuildCalendar();
this._buttons.forEach(Lang.bind(this, function(button) {
if (_sameDay(button._date, this._selectedDate)) {
button.add_style_pseudo_class('active');
if (this._shouldDateGrabFocus)
button.grab_key_focus();
}
else
button.remove_style_pseudo_class('active');
}));
} }
}); });
@ -714,12 +660,9 @@ const EventsList = new Lang.Class({
Name: 'EventsList', Name: 'EventsList',
_init: function() { _init: function() {
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL }); this.actor = new St.BoxLayout({ vertical: true, style_class: 'events-header-vbox'});
this.actor = new St.Widget({ style_class: 'events-table',
layout_manager: layout });
layout.hookup_style(this.actor);
this._date = new Date(); this._date = new Date();
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
this._desktopSettings.connect('changed', Lang.bind(this, this._update)); this._desktopSettings.connect('changed', Lang.bind(this, this._update));
this._weekStart = Shell.util_get_week_start(); this._weekStart = Shell.util_get_week_start();
}, },
@ -729,86 +672,55 @@ const EventsList = new Lang.Class({
this._eventSource.connect('changed', Lang.bind(this, this._update)); this._eventSource.connect('changed', Lang.bind(this, this._update));
}, },
_addEvent: function(event, index, includeDayName, periodBegin, periodEnd) { _addEvent: function(dayNameBox, timeBox, eventTitleBox, includeDayName, day, time, desc) {
let dayString;
if (includeDayName) { if (includeDayName) {
if (event.date >= periodBegin) dayNameBox.add(new St.Label( { style_class: 'events-day-dayname',
dayString = _getEventDayAbbreviation(event.date.getDay()); text: day } ),
else /* show event end day if it began earlier */ { x_fill: true } );
dayString = _getEventDayAbbreviation(event.end.getDay());
} else {
dayString = '';
} }
timeBox.add(new St.Label( { style_class: 'events-day-time',
let dayLabel = new St.Label({ style_class: 'events-day-dayname', text: time} ),
text: dayString, { x_fill: true } );
x_align: Clutter.ActorAlign.END, eventTitleBox.add(new St.Label( { style_class: 'events-day-task',
y_align: Clutter.ActorAlign.START }); text: desc} ));
dayLabel.clutter_text.line_wrap = false;
dayLabel.clutter_text.ellipsize = false;
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
let layout = this.actor.layout_manager;
layout.attach(dayLabel, rtl ? 2 : 0, index, 1, 1);
let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);
let timeString = _formatEventTime(event, clockFormat, periodBegin, periodEnd);
let timeLabel = new St.Label({ style_class: 'events-day-time',
text: timeString,
y_align: Clutter.ActorAlign.START });
timeLabel.clutter_text.line_wrap = false;
timeLabel.clutter_text.ellipsize = false;
let preEllipsisLabel = new St.Label({ style_class: 'events-day-time-ellipses',
text: ELLIPSIS_CHAR,
y_align: Clutter.ActorAlign.START });
let postEllipsisLabel = new St.Label({ style_class: 'events-day-time-ellipses',
text: ELLIPSIS_CHAR,
y_align: Clutter.ActorAlign.START });
if (event.allDay || event.date >= periodBegin)
preEllipsisLabel.opacity = 0;
if (event.allDay || event.end <= periodEnd)
postEllipsisLabel.opacity = 0;
let timeLabelBoxLayout = new St.BoxLayout();
timeLabelBoxLayout.add(preEllipsisLabel);
timeLabelBoxLayout.add(timeLabel);
timeLabelBoxLayout.add(postEllipsisLabel);
layout.attach(timeLabelBoxLayout, 1, index, 1, 1);
let titleLabel = new St.Label({ style_class: 'events-day-task',
text: event.summary,
x_expand: true });
titleLabel.clutter_text.line_wrap = true;
titleLabel.clutter_text.ellipsize = false;
layout.attach(titleLabel, rtl ? 0 : 2, index, 1, 1);
}, },
_addPeriod: function(header, index, periodBegin, periodEnd, includeDayName, showNothingScheduled) { _addPeriod: function(header, begin, end, includeDayName, showNothingScheduled) {
let events = this._eventSource.getEvents(periodBegin, periodEnd); let events = this._eventSource.getEvents(begin, end);
let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);;
if (events.length == 0 && !showNothingScheduled) if (events.length == 0 && !showNothingScheduled)
return index; return;
let label = new St.Label({ style_class: 'events-day-header', text: header }); let vbox = new St.BoxLayout( {vertical: true} );
let layout = this.actor.layout_manager; this.actor.add(vbox);
layout.attach(label, 0, index, 3, 1);
index++; vbox.add(new St.Label({ style_class: 'events-day-header', text: header }));
let box = new St.BoxLayout({style_class: 'events-header-hbox'});
let dayNameBox = new St.BoxLayout({ vertical: true, style_class: 'events-day-name-box' });
let timeBox = new St.BoxLayout({ vertical: true, style_class: 'events-time-box' });
let eventTitleBox = new St.BoxLayout({ vertical: true, style_class: 'events-event-box' });
box.add(dayNameBox, {x_fill: false});
box.add(timeBox, {x_fill: false});
box.add(eventTitleBox, {expand: true});
vbox.add(box);
for (let n = 0; n < events.length; n++) { for (let n = 0; n < events.length; n++) {
this._addEvent(events[n], index, includeDayName, periodBegin, periodEnd); let event = events[n];
index++; let dayString = _getEventDayAbbreviation(event.date.getDay());
let timeString = _formatEventTime(event, clockFormat);
let summaryString = event.summary;
this._addEvent(dayNameBox, timeBox, eventTitleBox, includeDayName, dayString, timeString, summaryString);
} }
if (events.length == 0 && showNothingScheduled) { if (events.length == 0 && showNothingScheduled) {
let now = new Date();
/* Translators: Text to show if there are no events */ /* Translators: Text to show if there are no events */
let nothingEvent = new CalendarEvent(periodBegin, periodBegin, _("Nothing Scheduled"), true); let nothingEvent = new CalendarEvent(now, now, _("Nothing Scheduled"), true);
this._addEvent(nothingEvent, index, false, periodBegin, periodEnd); let timeString = _formatEventTime(nothingEvent, clockFormat);
index++; this._addEvent(dayNameBox, timeBox, eventTitleBox, false, "", timeString, nothingEvent.summary);
} }
return index;
}, },
_showOtherDay: function(day) { _showOtherDay: function(day) {
@ -817,32 +729,28 @@ const EventsList = new Lang.Class({
let dayBegin = _getBeginningOfDay(day); let dayBegin = _getBeginningOfDay(day);
let dayEnd = _getEndOfDay(day); let dayEnd = _getEndOfDay(day);
let dayFormat; let dayString;
let now = new Date(); let now = new Date();
if (_sameYear(day, now)) if (_sameYear(day, now))
/* Translators: Shown on calendar heading when selected day occurs on current year */ /* Translators: Shown on calendar heading when selected day occurs on current year */
dayFormat = Shell.util_translate_time_string(NC_("calendar heading", dayString = day.toLocaleFormat(C_("calendar heading", "%A, %B %d"));
"%A, %B %d"));
else else
/* Translators: Shown on calendar heading when selected day occurs on different year */ /* Translators: Shown on calendar heading when selected day occurs on different year */
dayFormat = Shell.util_translate_time_string(NC_("calendar heading", dayString = day.toLocaleFormat(C_("calendar heading", "%A, %B %d, %Y"));
"%A, %B %d, %Y")); this._addPeriod(dayString, dayBegin, dayEnd, false, true);
let dayString = day.toLocaleFormat(dayFormat);
this._addPeriod(dayString, 0, dayBegin, dayEnd, false, true);
}, },
_showToday: function() { _showToday: function() {
this.actor.destroy_all_children(); this.actor.destroy_all_children();
let index = 0;
let now = new Date(); let now = new Date();
let dayBegin = _getBeginningOfDay(now); let dayBegin = _getBeginningOfDay(now);
let dayEnd = _getEndOfDay(now); let dayEnd = _getEndOfDay(now);
index = this._addPeriod(_("Today"), index, dayBegin, dayEnd, false, true); this._addPeriod(_("Today"), dayBegin, dayEnd, false, true);
let tomorrowBegin = new Date(dayBegin.getTime() + 86400 * 1000); let tomorrowBegin = new Date(dayBegin.getTime() + 86400 * 1000);
let tomorrowEnd = new Date(dayEnd.getTime() + 86400 * 1000); let tomorrowEnd = new Date(dayEnd.getTime() + 86400 * 1000);
index = this._addPeriod(_("Tomorrow"), index, tomorrowBegin, tomorrowEnd, false, true); this._addPeriod(_("Tomorrow"), tomorrowBegin, tomorrowEnd, false, true);
let dayInWeek = (dayEnd.getDay() - this._weekStart + 7) % 7; let dayInWeek = (dayEnd.getDay() - this._weekStart + 7) % 7;
@ -853,7 +761,7 @@ const EventsList = new Lang.Class({
*/ */
let thisWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000); let thisWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
let thisWeekEnd = new Date(dayEnd.getTime() + (6 - dayInWeek) * 86400 * 1000); let thisWeekEnd = new Date(dayEnd.getTime() + (6 - dayInWeek) * 86400 * 1000);
index = this._addPeriod(_("This week"), index, thisWeekBegin, thisWeekEnd, true, false); this._addPeriod(_("This week"), thisWeekBegin, thisWeekEnd, true, false);
} else { } else {
/* otherwise it's one of the two last days of the week ... show /* otherwise it's one of the two last days of the week ... show
* "Next week" and include events up until and including *next* * "Next week" and include events up until and including *next*
@ -861,7 +769,7 @@ const EventsList = new Lang.Class({
*/ */
let nextWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000); let nextWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
let nextWeekEnd = new Date(dayEnd.getTime() + (13 - dayInWeek) * 86400 * 1000); let nextWeekEnd = new Date(dayEnd.getTime() + (13 - dayInWeek) * 86400 * 1000);
index = this._addPeriod(_("Next week"), index, nextWeekBegin, nextWeekEnd, true, false); this._addPeriod(_("Next week"), nextWeekBegin, nextWeekEnd, true, false);
} }
}, },

View File

@ -1,40 +1,115 @@
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Pango = imports.gi.Pango; const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const St = imports.gi.St; const St = imports.gi.St;
const Lang = imports.lang; const Lang = imports.lang;
const CheckBoxContainer = new Lang.Class({
Name: 'CheckBoxContainer',
_init: function() {
this.actor = new Shell.GenericContainer();
this.actor.connect('get-preferred-width',
Lang.bind(this, this._getPreferredWidth));
this.actor.connect('get-preferred-height',
Lang.bind(this, this._getPreferredHeight));
this.actor.connect('allocate',
Lang.bind(this, this._allocate));
this.actor.connect('style-changed', Lang.bind(this,
function() {
let node = this.actor.get_theme_node();
this._spacing = node.get_length('spacing');
}));
this.actor.request_mode = Clutter.RequestMode.HEIGHT_FOR_WIDTH;
this._box = new St.Bin();
this.actor.add_actor(this._box);
this.label = new St.Label();
this.label.clutter_text.set_line_wrap(true);
this.label.clutter_text.set_ellipsize(Pango.EllipsizeMode.NONE);
this.actor.add_actor(this.label);
this._spacing = 0;
},
_getPreferredWidth: function(actor, forHeight, alloc) {
let [minWidth, natWidth] = this._box.get_preferred_width(forHeight);
alloc.min_size = minWidth + this._spacing;
alloc.natural_size = natWidth + this._spacing;
},
_getPreferredHeight: function(actor, forWidth, alloc) {
/* FIXME: StBoxlayout currently does not handle
height-for-width children correctly, so hard-code
two lines for the label until that problem is fixed.
https://bugzilla.gnome.org/show_bug.cgi?id=672543 */
/*
let [minBoxHeight, natBoxHeight] =
this._box.get_preferred_height(forWidth);
let [minLabelHeight, natLabelHeight] =
this.label.get_preferred_height(forWidth);
alloc.min_size = Math.max(minBoxHeight, minLabelHeight);
alloc.natural_size = Math.max(natBoxHeight, natLabelHeight);
*/
let [minBoxHeight, natBoxHeight] =
this._box.get_preferred_height(-1);
let [minLabelHeight, natLabelHeight] =
this.label.get_preferred_height(-1);
alloc.min_size = Math.max(minBoxHeight, 2 * minLabelHeight);
alloc.natural_size = Math.max(natBoxHeight, 2 * natLabelHeight);
},
_allocate: function(actor, box, flags) {
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let childBox = new Clutter.ActorBox();
let [minBoxWidth, natBoxWidth] =
this._box.get_preferred_width(-1);
let [minBoxHeight, natBoxHeight] =
this._box.get_preferred_height(-1);
childBox.x1 = box.x1;
childBox.x2 = box.x1 + natBoxWidth;
childBox.y1 = box.y1;
childBox.y2 = box.y1 + natBoxHeight;
this._box.allocate(childBox, flags);
childBox.x1 = box.x1 + natBoxWidth + this._spacing;
childBox.x2 = availWidth - childBox.x1;
childBox.y1 = box.y1;
childBox.y2 = box.y2;
this.label.allocate(childBox, flags);
}
});
const CheckBox = new Lang.Class({ const CheckBox = new Lang.Class({
Name: 'CheckBox', Name: 'CheckBox',
_init: function(label) { _init: function(label) {
let container = new St.BoxLayout();
this.actor = new St.Button({ style_class: 'check-box', this.actor = new St.Button({ style_class: 'check-box',
child: container,
button_mask: St.ButtonMask.ONE, button_mask: St.ButtonMask.ONE,
toggle_mode: true, toggle_mode: true,
can_focus: true, can_focus: true,
x_fill: true, x_fill: true,
y_fill: true }); y_fill: true });
this._container = new CheckBoxContainer();
this._box = new St.Bin(); this.actor.set_child(this._container.actor);
this._box.set_y_align(Clutter.ActorAlign.START);
container.add_actor(this._box);
this._label = new St.Label();
this._label.clutter_text.set_line_wrap(true);
this._label.clutter_text.set_ellipsize(Pango.EllipsizeMode.NONE);
container.add_actor(this._label);
if (label) if (label)
this.setLabel(label); this.setLabel(label);
}, },
setLabel: function(label) { setLabel: function(label) {
this._label.set_text(label); this._container.label.set_text(label);
}, },
getLabelActor: function() { getLabelActor: function() {
return this._label; return this._container.label;
} }
}); });

View File

@ -23,7 +23,7 @@ const AutomountManager = new Lang.Class({
Name: 'AutomountManager', Name: 'AutomountManager',
_init: function() { _init: function() {
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA }); this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
this._volumeQueue = []; this._volumeQueue = [];
this._session = new GnomeSession.SessionManager(); this._session = new GnomeSession.SessionManager();
this._session.connectSignal('InhibitorAdded', this._session.connectSignal('InhibitorAdded',
@ -43,7 +43,6 @@ const AutomountManager = new Lang.Class({
this._driveEjectButtonId = this._volumeMonitor.connect('drive-eject-button', Lang.bind(this, this._onDriveEjectButton)); this._driveEjectButtonId = this._volumeMonitor.connect('drive-eject-button', Lang.bind(this, this._onDriveEjectButton));
this._mountAllId = Mainloop.idle_add(Lang.bind(this, this._startupMountAll)); this._mountAllId = Mainloop.idle_add(Lang.bind(this, this._startupMountAll));
GLib.Source.set_name_by_id(this._mountAllId, '[gnome-shell] this._startupMountAll');
}, },
disable: function() { disable: function() {
@ -78,7 +77,7 @@ const AutomountManager = new Lang.Class({
})); }));
this._mountAllId = 0; this._mountAllId = 0;
return GLib.SOURCE_REMOVE; return false;
}, },
_onDriveConnected: function() { _onDriveConnected: function() {
@ -235,11 +234,10 @@ const AutomountManager = new Lang.Class({
}, },
_allowAutorunExpire: function(volume) { _allowAutorunExpire: function(volume) {
let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, function() { Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, function() {
volume.allowAutorun = false; volume.allowAutorun = false;
return GLib.SOURCE_REMOVE; return false;
}); });
GLib.Source.set_name_by_id(id, '[gnome-shell] volume.allowAutorun');
} }
}); });
const Component = AutomountManager; const Component = AutomountManager;

View File

@ -24,14 +24,14 @@ const AutorunSetting = {
}; };
// misc utils // misc utils
function shouldAutorunMount(mount) { function shouldAutorunMount(mount, forTransient) {
let root = mount.get_root(); let root = mount.get_root();
let volume = mount.get_volume(); let volume = mount.get_volume();
if (!volume || !volume.allowAutorun) if (!volume || (!volume.allowAutorun && forTransient))
return false; return false;
if (root.is_native() && isMountRootHidden(root)) if (!root.is_native() || isMountRootHidden(root))
return false; return false;
return true; return true;
@ -64,7 +64,7 @@ function startAppForMount(app, mount) {
try { try {
retval = app.launch(files, retval = app.launch(files,
global.create_app_launch_context(0, -1)) global.create_app_launch_context())
} catch (e) { } catch (e) {
log('Unable to launch the application ' + app.get_name() log('Unable to launch the application ' + app.get_name()
+ ': ' + e.toString()); + ': ' + e.toString());
@ -75,14 +75,12 @@ function startAppForMount(app, mount) {
/******************************************/ /******************************************/
const HotplugSnifferIface = '<node> \ const HotplugSnifferIface = <interface name="org.gnome.Shell.HotplugSniffer">
<interface name="org.gnome.Shell.HotplugSniffer"> \ <method name="SniffURI">
<method name="SniffURI"> \ <arg type="s" direction="in" />
<arg type="s" direction="in" /> \ <arg type="as" direction="out" />
<arg type="as" direction="out" /> \ </method>
</method> \ </interface>;
</interface> \
</node>';
const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface); const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
function HotplugSniffer() { function HotplugSniffer() {
@ -96,7 +94,7 @@ const ContentTypeDiscoverer = new Lang.Class({
_init: function(callback) { _init: function(callback) {
this._callback = callback; this._callback = callback;
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA }); this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
}, },
guessContentTypes: function(mount) { guessContentTypes: function(mount) {
@ -167,43 +165,281 @@ const AutorunManager = new Lang.Class({
this._session = new GnomeSession.SessionManager(); this._session = new GnomeSession.SessionManager();
this._volumeMonitor = Gio.VolumeMonitor.get(); this._volumeMonitor = Gio.VolumeMonitor.get();
this._dispatcher = new AutorunDispatcher(this); this._transDispatcher = new AutorunTransientDispatcher(this);
},
_ensureResidentSource: function() {
if (this._residentSource)
return;
this._residentSource = new AutorunResidentSource(this);
let destroyId = this._residentSource.connect('destroy', Lang.bind(this, function() {
this._residentSource.disconnect(destroyId);
this._residentSource = null;
}));
}, },
enable: function() { enable: function() {
this._scanMounts();
this._mountAddedId = this._volumeMonitor.connect('mount-added', Lang.bind(this, this._onMountAdded)); this._mountAddedId = this._volumeMonitor.connect('mount-added', Lang.bind(this, this._onMountAdded));
this._mountRemovedId = this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._onMountRemoved)); this._mountRemovedId = this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._onMountRemoved));
}, },
disable: function() { disable: function() {
if (this._residentSource)
this._residentSource.destroy();
this._volumeMonitor.disconnect(this._mountAddedId); this._volumeMonitor.disconnect(this._mountAddedId);
this._volumeMonitor.disconnect(this._mountRemovedId); this._volumeMonitor.disconnect(this._mountRemovedId);
}, },
_processMount: function(mount, hotplug) {
let discoverer = new ContentTypeDiscoverer(Lang.bind(this, function(mount, apps, contentTypes) {
this._ensureResidentSource();
this._residentSource.addMount(mount, apps);
if (hotplug)
this._transDispatcher.addMount(mount, apps, contentTypes);
}));
discoverer.guessContentTypes(mount);
},
_scanMounts: function() {
let mounts = this._volumeMonitor.get_mounts();
mounts.forEach(Lang.bind(this, function(mount) {
this._processMount(mount, false);
}));
},
_onMountAdded: function(monitor, mount) { _onMountAdded: function(monitor, mount) {
// don't do anything if our session is not the currently // don't do anything if our session is not the currently
// active one // active one
if (!this._session.SessionIsActive) if (!this._session.SessionIsActive)
return; return;
let discoverer = new ContentTypeDiscoverer(Lang.bind(this, function(mount, apps, contentTypes) { this._processMount(mount, true);
this._dispatcher.addMount(mount, apps, contentTypes);
}));
discoverer.guessContentTypes(mount);
}, },
_onMountRemoved: function(monitor, mount) { _onMountRemoved: function(monitor, mount) {
this._dispatcher.removeMount(mount); this._transDispatcher.removeMount(mount);
if (this._residentSource)
this._residentSource.removeMount(mount);
},
ejectMount: function(mount) {
let mountOp = new ShellMountOperation.ShellMountOperation(mount);
// first, see if we have a drive
let drive = mount.get_drive();
let volume = mount.get_volume();
if (drive &&
drive.get_start_stop_type() == Gio.DriveStartStopType.SHUTDOWN &&
drive.can_stop()) {
drive.stop(0, mountOp.mountOp, null,
Lang.bind(this, this._onStop));
} else {
if (mount.can_eject()) {
mount.eject_with_operation(0, mountOp.mountOp, null,
Lang.bind(this, this._onEject));
} else if (volume && volume.can_eject()) {
volume.eject_with_operation(0, mountOp.mountOp, null,
Lang.bind(this, this._onEject));
} else if (drive && drive.can_eject()) {
drive.eject_with_operation(0, mountOp.mountOp, null,
Lang.bind(this, this._onEject));
} else if (mount.can_unmount()) {
mount.unmount_with_operation(0, mountOp.mountOp, null,
Lang.bind(this, this._onUnmount));
}
}
},
_onUnmount: function(mount, res) {
try {
mount.unmount_with_operation_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
log('Unable to eject the mount ' + mount.get_name()
+ ': ' + e.toString());
}
},
_onEject: function(source, res) {
try {
source.eject_with_operation_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
log('Unable to eject the drive ' + source.get_name()
+ ': ' + e.toString());
}
},
_onStop: function(drive, res) {
try {
drive.stop_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
log('Unable to stop the drive ' + drive.get_name()
+ ': ' + e.toString());
}
},
});
const AutorunResidentSource = new Lang.Class({
Name: 'AutorunResidentSource',
Extends: MessageTray.Source,
_init: function(manager) {
this.parent(_("Removable Devices"), 'media-removable');
this.resident = true;
this._mounts = [];
this._manager = manager;
this._notification = new AutorunResidentNotification(this._manager, this);
},
_createPolicy: function() {
return new MessageTray.NotificationPolicy({ showInLockScreen: false });
},
buildRightClickMenu: function() {
return null;
},
addMount: function(mount, apps) {
if (!shouldAutorunMount(mount, false))
return;
let filtered = this._mounts.filter(function (element) {
return (element.mount == mount);
});
if (filtered.length != 0)
return;
let element = { mount: mount, apps: apps };
this._mounts.push(element);
this._redisplay();
},
removeMount: function(mount) {
this._mounts =
this._mounts.filter(function (element) {
return (element.mount != mount);
});
this._redisplay();
},
_redisplay: function() {
if (this._mounts.length == 0) {
this._notification.destroy();
this.destroy();
return;
}
this._notification.updateForMounts(this._mounts);
// add ourselves as a source, and push the notification
if (!Main.messageTray.contains(this)) {
Main.messageTray.add(this);
this.pushNotification(this._notification);
}
} }
}); });
const AutorunDispatcher = new Lang.Class({ const AutorunResidentNotification = new Lang.Class({
Name: 'AutorunDispatcher', Name: 'AutorunResidentNotification',
Extends: MessageTray.Notification,
_init: function(manager, source) {
this.parent(source, source.title, null, { customContent: true });
// set the notification as resident
this.setResident(true);
this._layout = new St.BoxLayout ({ style_class: 'hotplug-resident-box',
vertical: true });
this._manager = manager;
this.addActor(this._layout,
{ x_expand: true,
x_fill: true });
},
updateForMounts: function(mounts) {
// remove all the layout content
this._layout.destroy_all_children();
for (let idx = 0; idx < mounts.length; idx++) {
let element = mounts[idx];
let actor = this._itemForMount(element.mount, element.apps);
this._layout.add(actor, { x_fill: true,
expand: true });
}
},
_itemForMount: function(mount, apps) {
let item = new St.BoxLayout();
// prepare the mount button content
let mountLayout = new St.BoxLayout();
let mountIcon = new St.Icon({ gicon: mount.get_icon(),
style_class: 'hotplug-resident-mount-icon' });
mountLayout.add_actor(mountIcon);
let labelBin = new St.Bin({ y_align: St.Align.MIDDLE });
let mountLabel =
new St.Label({ text: mount.get_name(),
style_class: 'hotplug-resident-mount-label',
track_hover: true,
reactive: true });
labelBin.add_actor(mountLabel);
mountLayout.add_actor(labelBin);
let mountButton = new St.Button({ child: mountLayout,
x_align: St.Align.START,
x_fill: true,
style_class: 'hotplug-resident-mount',
button_mask: St.ButtonMask.ONE });
item.add(mountButton, { x_align: St.Align.START,
expand: true });
let ejectIcon =
new St.Icon({ icon_name: 'media-eject-symbolic',
style_class: 'hotplug-resident-eject-icon' });
let ejectButton =
new St.Button({ style_class: 'hotplug-resident-eject-button',
button_mask: St.ButtonMask.ONE,
child: ejectIcon });
item.add(ejectButton, { x_align: St.Align.END });
// now connect signals
mountButton.connect('clicked', Lang.bind(this, function(actor, event) {
startAppForMount(apps[0], mount);
}));
ejectButton.connect('clicked', Lang.bind(this, function() {
this._manager.ejectMount(mount);
}));
return item;
},
});
const AutorunTransientDispatcher = new Lang.Class({
Name: 'AutorunTransientDispatcher',
_init: function(manager) { _init: function(manager) {
this._manager = manager; this._manager = manager;
this._sources = []; this._sources = [];
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA }); this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
}, },
_getAutorunSettingForType: function(contentType) { _getAutorunSettingForType: function(contentType) {
@ -244,7 +480,7 @@ const AutorunDispatcher = new Lang.Class({
return; return;
// add a new source // add a new source
this._sources.push(new AutorunSource(this._manager, mount, apps)); this._sources.push(new AutorunTransientSource(this._manager, mount, apps));
}, },
addMount: function(mount, apps, contentTypes) { addMount: function(mount, apps, contentTypes) {
@ -253,7 +489,7 @@ const AutorunDispatcher = new Lang.Class({
return; return;
// if the mount doesn't want to be autorun, return // if the mount doesn't want to be autorun, return
if (!shouldAutorunMount(mount)) if (!shouldAutorunMount(mount, true))
return; return;
let setting = this._getAutorunSettingForType(contentTypes[0]); let setting = this._getAutorunSettingForType(contentTypes[0]);
@ -293,8 +529,8 @@ const AutorunDispatcher = new Lang.Class({
} }
}); });
const AutorunSource = new Lang.Class({ const AutorunTransientSource = new Lang.Class({
Name: 'AutorunSource', Name: 'AutorunTransientSource',
Extends: MessageTray.Source, Extends: MessageTray.Source,
_init: function(manager, mount, apps) { _init: function(manager, mount, apps) {
@ -304,7 +540,7 @@ const AutorunSource = new Lang.Class({
this.parent(mount.get_name()); this.parent(mount.get_name());
this._notification = new AutorunNotification(this._manager, this); this._notification = new AutorunTransientNotification(this._manager, this);
// add ourselves as a source, and popup the notification // add ourselves as a source, and popup the notification
Main.messageTray.add(this); Main.messageTray.add(this);
@ -316,24 +552,34 @@ const AutorunSource = new Lang.Class({
} }
}); });
const AutorunNotification = new Lang.Class({ const AutorunTransientNotification = new Lang.Class({
Name: 'AutorunNotification', Name: 'AutorunTransientNotification',
Extends: MessageTray.Notification, Extends: MessageTray.Notification,
_init: function(manager, source) { _init: function(manager, source) {
this.parent(source, source.title); this.parent(source, source.title, null, { customContent: true });
this._manager = manager; this._manager = manager;
this._box = new St.BoxLayout({ style_class: 'hotplug-transient-box',
vertical: true });
this.addActor(this._box);
this._mount = source.mount; this._mount = source.mount;
source.apps.forEach(Lang.bind(this, function (app) { source.apps.forEach(Lang.bind(this, function (app) {
let actor = this._buttonForApp(app); let actor = this._buttonForApp(app);
if (actor) if (actor)
this.addButton(actor); this._box.add(actor, { x_fill: true,
x_align: St.Align.START });
})); }));
// set the notification to urgent, so that it expands out this._box.add(this._buttonForEject(), { x_fill: true,
x_align: St.Align.START });
// set the notification to transient and urgent, so that it
// expands out
this.setTransient(true);
this.setUrgency(MessageTray.Urgency.CRITICAL); this.setUrgency(MessageTray.Urgency.CRITICAL);
}, },
@ -353,7 +599,7 @@ const AutorunNotification = new Lang.Class({
x_fill: true, x_fill: true,
x_align: St.Align.START, x_align: St.Align.START,
button_mask: St.ButtonMask.ONE, button_mask: St.ButtonMask.ONE,
style_class: 'hotplug-notification-item button' }); style_class: 'hotplug-notification-item' });
button.connect('clicked', Lang.bind(this, function() { button.connect('clicked', Lang.bind(this, function() {
startAppForMount(app, this._mount); startAppForMount(app, this._mount);
@ -363,11 +609,29 @@ const AutorunNotification = new Lang.Class({
return button; return button;
}, },
_onClicked: function() { _buttonForEject: function() {
this.parent(); let box = new St.BoxLayout();
let icon = new St.Icon({ icon_name: 'media-eject-symbolic',
style_class: 'hotplug-notification-item-icon' });
box.add(icon);
let app = Gio.app_info_get_default_for_type('inode/directory', false); let label = new St.Bin({ y_align: St.Align.MIDDLE,
startAppForMount(app, this._mount); child: new St.Label
({ text: _("Eject") })
});
box.add(label);
let button = new St.Button({ child: box,
x_fill: true,
x_align: St.Align.START,
button_mask: St.ButtonMask.ONE,
style_class: 'hotplug-notification-item' });
button.connect('clicked', Lang.bind(this, function() {
this._manager.ejectMount(this._mount);
}));
return button;
} }
}); });

View File

@ -13,6 +13,8 @@ const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const CheckBox = imports.ui.checkBox; const CheckBox = imports.ui.checkBox;
let prompter = null;
const KeyringDialog = new Lang.Class({ const KeyringDialog = new Lang.Class({
Name: 'KeyringDialog', Name: 'KeyringDialog',
Extends: ModalDialog.ModalDialog, Extends: ModalDialog.ModalDialog,
@ -23,7 +25,7 @@ const KeyringDialog = new Lang.Class({
this.prompt = new Shell.KeyringPrompt(); this.prompt = new Shell.KeyringPrompt();
this.prompt.connect('show-password', Lang.bind(this, this._onShowPassword)); this.prompt.connect('show-password', Lang.bind(this, this._onShowPassword));
this.prompt.connect('show-confirm', Lang.bind(this, this._onShowConfirm)); this.prompt.connect('show-confirm', Lang.bind(this, this._onShowConfirm));
this.prompt.connect('prompt-close', Lang.bind(this, this._onHidePrompt)); this.prompt.connect('hide-prompt', Lang.bind(this, this._onHidePrompt));
let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout', let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
vertical: false }); vertical: false });
@ -41,13 +43,11 @@ const KeyringDialog = new Lang.Class({
mainContentBox.add(this._messageBox, mainContentBox.add(this._messageBox,
{ y_align: St.Align.START, expand: true, x_fill: true, y_fill: true }); { y_align: St.Align.START, expand: true, x_fill: true, y_fill: true });
let subject = new St.Label({ style_class: 'prompt-dialog-headline headline' }); let subject = new St.Label({ style_class: 'prompt-dialog-headline' });
this.prompt.bind_property('message', subject, 'text', GObject.BindingFlags.SYNC_CREATE); this.prompt.bind_property('message', subject, 'text', GObject.BindingFlags.SYNC_CREATE);
this._messageBox.add(subject, this._messageBox.add(subject,
{ x_fill: false, { y_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START }); y_align: St.Align.START });
let description = new St.Label({ style_class: 'prompt-dialog-description' }); let description = new St.Label({ style_class: 'prompt-dialog-description' });
@ -63,75 +63,53 @@ const KeyringDialog = new Lang.Class({
this._cancelButton = this.addButton({ label: '', this._cancelButton = this.addButton({ label: '',
action: Lang.bind(this, this._onCancelButton), action: Lang.bind(this, this._onCancelButton),
key: Clutter.Escape }, key: Clutter.Escape });
{ expand: true, x_fill: false, x_align: St.Align.START });
this.placeSpinner({ expand: false,
x_fill: false,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
this._continueButton = this.addButton({ label: '', this._continueButton = this.addButton({ label: '',
action: Lang.bind(this, this._onContinueButton), action: Lang.bind(this, this._onContinueButton),
default: true }, default: true },
{ expand: false, x_fill: false, x_align: St.Align.END }); { expand: true, x_fill: false, x_align: St.Align.END });
this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE); this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE); this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE);
}, },
_buildControlTable: function() { _buildControlTable: function() {
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL }); let table = new St.Table({ style_class: 'keyring-dialog-control-table' });
let table = new St.Widget({ style_class: 'keyring-dialog-control-table',
layout_manager: layout });
layout.hookup_style(table);
let rtl = table.get_text_direction() == Clutter.TextDirection.RTL;
let row = 0; let row = 0;
if (this.prompt.password_visible) { 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' }));
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER });
label.set_text(_("Password:")); label.set_text(_("Password:"));
label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; 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 });
this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry', this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: '', text: '',
can_focus: true, can_focus: true});
x_expand: true });
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true }); ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onPasswordActivate)); 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 });
if (rtl) {
layout.attach(this._passwordEntry, 0, row, 1, 1);
layout.attach(label, 1, row, 1, 1);
} else {
layout.attach(label, 0, row, 1, 1);
layout.attach(this._passwordEntry, 1, row, 1, 1);
}
row++; row++;
} else { } else {
this._passwordEntry = null; this._passwordEntry = null;
} }
if (this.prompt.confirm_visible) { if (this.prompt.confirm_visible) {
var label = new St.Label(({ style_class: 'prompt-dialog-password-label', var label = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER }));
label.set_text(_("Type again:")); 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 });
this._confirmEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry', this._confirmEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: '', text: '',
can_focus: true, can_focus: true});
x_expand: true });
this._confirmEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE this._confirmEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
ShellEntry.addContextMenu(this._confirmEntry, { isPassword: true }); ShellEntry.addContextMenu(this._confirmEntry, { isPassword: true });
this._confirmEntry.clutter_text.connect('activate', Lang.bind(this, this._onConfirmActivate)); this._confirmEntry.clutter_text.connect('activate', Lang.bind(this, this._onConfirmActivate));
if (rtl) { table.add(this._confirmEntry, { row: row, col: 1, x_expand: true, x_fill: true, x_align: St.Align.START });
layout.attach(this._confirmEntry, 0, row, 1, 1);
layout.attach(label, 1, row, 1, 1);
} else {
layout.attach(label, 0, row, 1, 1);
layout.attach(this._confirmEntry, 1, row, 1, 1);
}
row++; row++;
} else { } else {
this._confirmEntry = null; this._confirmEntry = null;
@ -144,15 +122,14 @@ const KeyringDialog = new Lang.Class({
let choice = new CheckBox.CheckBox(); let choice = new CheckBox.CheckBox();
this.prompt.bind_property('choice-label', choice.getLabelActor(), 'text', GObject.BindingFlags.SYNC_CREATE); 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); this.prompt.bind_property('choice-chosen', choice.actor, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
layout.attach(choice.actor, rtl ? 0 : 1, row, 1, 1); table.add(choice.actor, { row: row, col: 1, x_expand: false, x_fill: true, x_align: St.Align.START });
row++; row++;
} }
let warning = new St.Label({ style_class: 'prompt-dialog-error-label', let warning = new St.Label({ style_class: 'prompt-dialog-error-label' });
x_align: Clutter.ActorAlign.START });
warning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; warning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
warning.clutter_text.line_wrap = true; warning.clutter_text.line_wrap = true;
layout.attach(warning, rtl ? 0 : 1, row, 1, 1); table.add(warning, { row: row, col: 1, x_expand: false, x_fill: false, x_align: St.Align.START });
this.prompt.bind_property('warning-visible', warning, 'visible', GObject.BindingFlags.SYNC_CREATE); this.prompt.bind_property('warning-visible', warning, 'visible', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('warning', warning, 'text', GObject.BindingFlags.SYNC_CREATE); this.prompt.bind_property('warning', warning, 'text', GObject.BindingFlags.SYNC_CREATE);
@ -166,19 +143,11 @@ const KeyringDialog = new Lang.Class({
}, },
_updateSensitivity: function(sensitive) { _updateSensitivity: function(sensitive) {
if (this._passwordEntry) { this._passwordEntry.reactive = sensitive;
this._passwordEntry.reactive = sensitive; this._passwordEntry.clutter_text.editable = sensitive;
this._passwordEntry.clutter_text.editable = sensitive;
}
if (this._confirmEntry) {
this._confirmEntry.reactive = sensitive;
this._confirmEntry.clutter_text.editable = sensitive;
}
this._continueButton.can_focus = sensitive; this._continueButton.can_focus = sensitive;
this._continueButton.reactive = sensitive; this._continueButton.reactive = sensitive;
this.setWorking(!sensitive);
}, },
_ensureOpen: function() { _ensureOpen: function() {
@ -238,56 +207,27 @@ 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({ const KeyringPrompter = new Lang.Class({
Name: 'KeyringPrompter', Name: 'KeyringPrompter',
_init: function() { _init: function() {
this._prompter = new Gcr.SystemPrompter(); this._prompter = new Gcr.SystemPrompter();
this._prompter.connect('new-prompt', Lang.bind(this, this._prompter.connect('new-prompt', function(prompter) {
function() { let dialog = new KeyringDialog();
let dialog = this._enabled ? new KeyringDialog() return dialog.prompt;
: new KeyringDummyDialog(); });
this._currentPrompt = dialog.prompt;
return this._currentPrompt;
}));
this._dbusId = null; this._dbusId = null;
this._registered = false;
this._enabled = false;
this._currentPrompt = null;
}, },
enable: function() { enable: function() {
if (!this._registered) { this._prompter.register(Gio.DBus.session);
this._prompter.register(Gio.DBus.session); this._dbusId = Gio.DBus.session.own_name('org.gnome.keyring.SystemPrompter',
this._dbusId = Gio.DBus.session.own_name('org.gnome.keyring.SystemPrompter', Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT, null, null);
Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT, null, null);
this._registered = true;
}
this._enabled = true;
}, },
disable: function() { disable: function() {
this._enabled = false; this._prompter.unregister(false);
Gio.DBus.session.unown_name(this._dbusId);
if (this._prompter.prompting)
this._currentPrompt.cancel();
this._currentPrompt = null;
} }
}); });

View File

@ -54,7 +54,7 @@ const NetworkSecretDialog = new Lang.Class({
mainContentBox.add(messageBox, mainContentBox.add(messageBox,
{ y_align: St.Align.START }); { y_align: St.Align.START });
let subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline headline', let subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline',
text: this._content.title }); text: this._content.title });
messageBox.add(subjectLabel, messageBox.add(subjectLabel,
{ y_fill: false, { y_fill: false,
@ -62,9 +62,14 @@ const NetworkSecretDialog = new Lang.Class({
if (this._content.message != null) { if (this._content.message != null) {
let descriptionLabel = new St.Label({ style_class: 'prompt-dialog-description', let descriptionLabel = new St.Label({ style_class: 'prompt-dialog-description',
text: this._content.message }); text: this._content.message,
// HACK: for reasons unknown to me, the label
// is not asked the correct height for width,
// and thus is underallocated
// place a fixed height to avoid overflowing
style: 'height: 3em'
});
descriptionLabel.clutter_text.line_wrap = true; descriptionLabel.clutter_text.line_wrap = true;
descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
messageBox.add(descriptionLabel, messageBox.add(descriptionLabel,
{ y_fill: true, { y_fill: true,
@ -72,28 +77,19 @@ const NetworkSecretDialog = new Lang.Class({
expand: true }); expand: true });
} }
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL }); let secretTable = new St.Table({ style_class: 'network-dialog-secret-table' });
let secretTable = new St.Widget({ style_class: 'network-dialog-secret-table',
layout_manager: layout });
layout.hookup_style(secretTable);
let rtl = secretTable.get_text_direction() == Clutter.TextDirection.RTL;
let initialFocusSet = false; let initialFocusSet = false;
let pos = 0; let pos = 0;
for (let i = 0; i < this._content.secrets.length; i++) { for (let i = 0; i < this._content.secrets.length; i++) {
let secret = this._content.secrets[i]; let secret = this._content.secrets[i];
let label = new St.Label({ style_class: 'prompt-dialog-password-label', let label = new St.Label({ style_class: 'prompt-dialog-password-label',
text: secret.label, text: secret.label });
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER });
label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
let reactive = secret.key != null; let reactive = secret.key != null;
secret.entry = new St.Entry({ style_class: 'prompt-dialog-password-entry', secret.entry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: secret.value, can_focus: reactive, text: secret.value, can_focus: reactive,
reactive: reactive, reactive: reactive });
x_expand: true });
ShellEntry.addContextMenu(secret.entry, ShellEntry.addContextMenu(secret.entry,
{ isPassword: secret.password }); { isPassword: secret.password });
@ -120,13 +116,11 @@ const NetworkSecretDialog = new Lang.Class({
} else } else
secret.valid = true; secret.valid = true;
if (rtl) { secretTable.add(label, { row: pos, col: 0,
layout.attach(secret.entry, 0, pos, 1, 1); x_expand: false, x_fill: true,
layout.attach(label, 1, pos, 1, 1); x_align: St.Align.START,
} else { y_fill: false, y_align: St.Align.MIDDLE });
layout.attach(label, 0, pos, 1, 1); secretTable.add(secret.entry, { row: pos, col: 1, x_expand: true, x_fill: true, y_align: St.Align.END });
layout.attach(secret.entry, 1, pos, 1, 1);
}
pos++; pos++;
if (secret.password) if (secret.password)
@ -145,8 +139,6 @@ const NetworkSecretDialog = new Lang.Class({
key: Clutter.KEY_Escape, key: Clutter.KEY_Escape,
}, },
this._okButton]); this._okButton]);
this._updateOkButton();
}, },
_updateOkButton: function() { _updateOkButton: function() {
@ -262,7 +254,6 @@ const NetworkSecretDialog = new Lang.Class({
case 'leap': case 'leap':
case 'ttls': case 'ttls':
case 'peap': case 'peap':
case 'fast':
// TTLS and PEAP are actually much more complicated, but this complication // TTLS and PEAP are actually much more complicated, but this complication
// is not visible here since we only care about phase2 authentication // is not visible here since we only care about phase2 authentication
// (and don't even care of which one) // (and don't even care of which one)
@ -316,7 +307,7 @@ const NetworkSecretDialog = new Lang.Class({
wirelessSetting = this._connection.get_setting_wireless(); wirelessSetting = this._connection.get_setting_wireless();
ssid = NetworkManager.utils_ssid_to_utf8(wirelessSetting.get_ssid()); ssid = NetworkManager.utils_ssid_to_utf8(wirelessSetting.get_ssid());
content.title = _("Authentication required by wireless network"); content.title = _("Authentication required by wireless network");
content.message = _("Passwords or encryption keys are required to access the wireless network %s.").format(ssid); content.message = _("Passwords or encryption keys are required to access the wireless network '%s'.").format(ssid);
this._getWirelessSecrets(content.secrets, wirelessSetting); this._getWirelessSecrets(content.secrets, wirelessSetting);
break; break;
case '802-3-ethernet': case '802-3-ethernet':
@ -343,7 +334,7 @@ const NetworkSecretDialog = new Lang.Class({
case 'cdma': case 'cdma':
case 'bluetooth': case 'bluetooth':
content.title = _("Mobile broadband network password"); content.title = _("Mobile broadband network password");
content.message = _("A password is required to connect to %s.").format(connectionSetting.get_id()); content.message = _("A password is required to connect to '%s'.").format(connectionSetting.get_id());
this._getMobileSecrets(content.secrets, connectionType); this._getMobileSecrets(content.secrets, connectionType);
break; break;
default: default:
@ -380,12 +371,6 @@ const VPNRequestHandler = new Lang.Class({
argv.push('-i'); argv.push('-i');
if (flags & NMClient.SecretAgentGetSecretsFlags.REQUEST_NEW) if (flags & NMClient.SecretAgentGetSecretsFlags.REQUEST_NEW)
argv.push('-r'); argv.push('-r');
if (authHelper.supportsHints) {
for (let i = 0; i < hints.length; i++) {
argv.push('-t');
argv.push(hints[i]);
}
}
this._newStylePlugin = authHelper.externalUIMode; this._newStylePlugin = authHelper.externalUIMode;
@ -400,7 +385,11 @@ const VPNRequestHandler = new Lang.Class({
this._childPid = pid; this._childPid = pid;
this._stdin = new Gio.UnixOutputStream({ fd: stdin, close_fd: true }); this._stdin = new Gio.UnixOutputStream({ fd: stdin, close_fd: true });
this._stdout = new Gio.UnixInputStream({ fd: stdout, close_fd: true }); this._stdout = new Gio.UnixInputStream({ fd: stdout, close_fd: true });
GLib.close(stderr); // We need this one too, even if don't actually care of what the process
// has to say on stderr, because otherwise the fd opened by g_spawn_async_with_pipes
// is kept open indefinitely
let stderrStream = new Gio.UnixInputStream({ fd: stderr, close_fd: true });
stderrStream.close(null);
this._dataStdout = new Gio.DataInputStream({ base_stream: this._stdout }); this._dataStdout = new Gio.DataInputStream({ base_stream: this._stdout });
if (this._newStylePlugin) if (this._newStylePlugin)
@ -448,7 +437,6 @@ const VPNRequestHandler = new Lang.Class({
}, },
_vpnChildFinished: function(pid, status, requestObj) { _vpnChildFinished: function(pid, status, requestObj) {
this._childWatch = 0;
if (this._newStylePlugin) { if (this._newStylePlugin) {
// For new style plugin, all work is done in the async reading functions // For new style plugin, all work is done in the async reading functions
// Just reap the process here // Just reap the process here
@ -523,12 +511,10 @@ const VPNRequestHandler = new Lang.Class({
_showNewStyleDialog: function() { _showNewStyleDialog: function() {
let keyfile = new GLib.KeyFile(); let keyfile = new GLib.KeyFile();
let data;
let contentOverride; let contentOverride;
try { try {
data = this._dataStdout.peek_buffer(); let data = this._dataStdout.peek_buffer();
keyfile.load_from_data(data.toString(), data.length, keyfile.load_from_data(data.toString(), data.length,
GLib.KeyFileFlags.NONE); GLib.KeyFileFlags.NONE);
@ -561,16 +547,13 @@ const VPNRequestHandler = new Lang.Class({
} }
} }
} catch(e) { } catch(e) {
// No output is a valid case it means "both secrets are stored" logError(e, 'error while reading VPN plugin output keyfile');
if (data.length > 0) {
logError(e, 'error while reading VPN plugin output keyfile');
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR); this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
return; return;
}
} }
if (contentOverride && contentOverride.secrets.length) { if (contentOverride.secrets.length) {
// Only show the dialog if we actually have something to ask // Only show the dialog if we actually have something to ask
this._shellDialog = new NetworkSecretDialog(this._agent, this._requestId, this._connection, 'vpn', [], contentOverride); this._shellDialog = new NetworkSecretDialog(this._agent, this._requestId, this._connection, 'vpn', [], contentOverride);
this._shellDialog.open(global.get_current_time()); this._shellDialog.open(global.get_current_time());
@ -604,9 +587,7 @@ const NetworkAgent = new Lang.Class({
Name: 'NetworkAgent', Name: 'NetworkAgent',
_init: function() { _init: function() {
this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent', this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent' });
capabilities: NMClient.SecretAgentCapabilities.VPN_HINTS
});
this._dialogs = { }; this._dialogs = { };
this._vpnRequests = { }; this._vpnRequests = { };
@ -706,23 +687,16 @@ const NetworkAgent = new Lang.Class({
let service = keyfile.get_string('VPN Connection', 'service'); let service = keyfile.get_string('VPN Connection', 'service');
let binary = keyfile.get_string('GNOME', 'auth-dialog'); let binary = keyfile.get_string('GNOME', 'auth-dialog');
let externalUIMode = false; let externalUIMode = false;
let hints = false;
try { try {
externalUIMode = keyfile.get_boolean('GNOME', 'supports-external-ui-mode'); externalUIMode = keyfile.get_boolean('GNOME', 'supports-external-ui-mode');
} catch(e) { } // ignore errors if key does not exist } catch(e) { } // ignore errors if key does not exist
try {
hints = keyfile.get_boolean('GNOME', 'supports-hints');
} catch(e) { } // ignore errors if key does not exist
let path = binary; let path = binary;
if (!GLib.path_is_absolute(path)) { if (!GLib.path_is_absolute(path)) {
path = GLib.build_filenamev([Config.LIBEXECDIR, path]); path = GLib.build_filenamev([Config.LIBEXECDIR, path]);
} }
if (GLib.file_test(path, GLib.FileTest.IS_EXECUTABLE)) if (GLib.file_test(path, GLib.FileTest.IS_EXECUTABLE))
this._vpnBinaries[service] = { fileName: path, externalUIMode: externalUIMode, supportsHints: hints }; this._vpnBinaries[service] = { fileName: path, externalUIMode: externalUIMode };
else else
throw new Error('VPN plugin at %s is not executable'.format(path)); throw new Error('VPN plugin at %s is not executable'.format(path));
} catch(e) { } catch(e) {

View File

@ -16,7 +16,7 @@ const PolkitAgent = imports.gi.PolkitAgent;
const Components = imports.ui.components; const Components = imports.ui.components;
const ModalDialog = imports.ui.modalDialog; const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const UserWidget = imports.ui.userWidget; const UserMenu = imports.ui.userMenu;
const DIALOG_ICON_SIZE = 48; const DIALOG_ICON_SIZE = 48;
@ -31,6 +31,7 @@ const AuthenticationDialog = new Lang.Class({
this.message = message; this.message = message;
this.userNames = userNames; this.userNames = userNames;
this._wasDismissed = false; this._wasDismissed = false;
this._completed = false;
let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout', let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
vertical: false }); vertical: false });
@ -50,13 +51,11 @@ const AuthenticationDialog = new Lang.Class({
mainContentBox.add(messageBox, mainContentBox.add(messageBox,
{ expand: true, y_align: St.Align.START }); { expand: true, y_align: St.Align.START });
this._subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline headline', this._subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline',
text: _("Authentication Required") }); text: _("Authentication Required") });
messageBox.add(this._subjectLabel, messageBox.add(this._subjectLabel,
{ x_fill: false, { y_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START }); y_align: St.Align.START });
this._descriptionLabel = new St.Label({ style_class: 'prompt-dialog-description', this._descriptionLabel = new St.Label({ style_class: 'prompt-dialog-description',
@ -65,9 +64,7 @@ const AuthenticationDialog = new Lang.Class({
this._descriptionLabel.clutter_text.line_wrap = true; this._descriptionLabel.clutter_text.line_wrap = true;
messageBox.add(this._descriptionLabel, messageBox.add(this._descriptionLabel,
{ x_fill: false, { y_fill: true,
y_fill: true,
x_align: St.Align.START,
y_align: St.Align.START }); y_align: St.Align.START });
if (userNames.length > 1) { if (userNames.length > 1) {
@ -99,15 +96,14 @@ const AuthenticationDialog = new Lang.Class({
if (userIsRoot) { if (userIsRoot) {
let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-root-label', let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-root-label',
text: userRealName })); text: userRealName }));
messageBox.add(userLabel, { x_fill: false, messageBox.add(userLabel);
x_align: St.Align.START });
} else { } else {
let userBox = new St.BoxLayout({ style_class: 'polkit-dialog-user-layout', let userBox = new St.BoxLayout({ style_class: 'polkit-dialog-user-layout',
vertical: false }); vertical: false });
messageBox.add(userBox); messageBox.add(userBox);
this._userAvatar = new UserWidget.Avatar(this._user, this._userAvatar = new UserMenu.UserAvatarWidget(this._user,
{ iconSize: DIALOG_ICON_SIZE, { iconSize: DIALOG_ICON_SIZE,
styleClass: 'polkit-dialog-user-icon' }); styleClass: 'polkit-dialog-user-icon' });
this._userAvatar.actor.hide(); this._userAvatar.actor.hide();
userBox.add(this._userAvatar.actor, userBox.add(this._userAvatar.actor,
{ x_fill: true, { x_fill: true,
@ -142,7 +138,7 @@ const AuthenticationDialog = new Lang.Class({
this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label' }); this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label' });
this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._errorMessageLabel.clutter_text.line_wrap = true; this._errorMessageLabel.clutter_text.line_wrap = true;
messageBox.add(this._errorMessageLabel, { x_fill: false, x_align: St.Align.START }); messageBox.add(this._errorMessageLabel);
this._errorMessageLabel.hide(); this._errorMessageLabel.hide();
this._infoMessageLabel = new St.Label({ style_class: 'prompt-dialog-info-label' }); this._infoMessageLabel = new St.Label({ style_class: 'prompt-dialog-info-label' });
@ -165,32 +161,26 @@ const AuthenticationDialog = new Lang.Class({
this._cancelButton = this.addButton({ label: _("Cancel"), this._cancelButton = this.addButton({ label: _("Cancel"),
action: Lang.bind(this, this.cancel), action: Lang.bind(this, this.cancel),
key: Clutter.Escape }, key: Clutter.Escape });
{ expand: true, x_fill: false, x_align: St.Align.START });
this.placeSpinner({ expand: false,
x_fill: false,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
this._okButton = this.addButton({ label: _("Authenticate"), this._okButton = this.addButton({ label: _("Authenticate"),
action: Lang.bind(this, this._onAuthenticateButtonPressed), action: Lang.bind(this, this._onAuthenticateButtonPressed),
default: true }, default: true },
{ expand: false, x_fill: false, x_align: St.Align.END }); { expand: true, x_fill: false, x_align: St.Align.END });
this._doneEmitted = false; this._doneEmitted = false;
this._identityToAuth = Polkit.UnixUser.new_for_name(userName); this._identityToAuth = Polkit.UnixUser.new_for_name(userName);
this._cookie = cookie; this._cookie = cookie;
},
performAuthentication: function() {
this.destroySession();
this._session = new PolkitAgent.Session({ identity: this._identityToAuth, this._session = new PolkitAgent.Session({ identity: this._identityToAuth,
cookie: this._cookie }); cookie: this._cookie });
this._session.connect('completed', Lang.bind(this, this._onSessionCompleted)); this._session.connect('completed', Lang.bind(this, this._onSessionCompleted));
this._session.connect('request', Lang.bind(this, this._onSessionRequest)); this._session.connect('request', Lang.bind(this, this._onSessionRequest));
this._session.connect('show-error', Lang.bind(this, this._onSessionShowError)); this._session.connect('show-error', Lang.bind(this, this._onSessionShowError));
this._session.connect('show-info', Lang.bind(this, this._onSessionShowInfo)); this._session.connect('show-info', Lang.bind(this, this._onSessionShowInfo));
},
startAuthentication: function() {
this._session.initiate(); this._session.initiate();
}, },
@ -212,14 +202,14 @@ const AuthenticationDialog = new Lang.Class({
log('polkitAuthenticationAgent: Failed to show modal dialog.' + log('polkitAuthenticationAgent: Failed to show modal dialog.' +
' Dismissing authentication request for action-id ' + this.actionId + ' Dismissing authentication request for action-id ' + this.actionId +
' cookie ' + this._cookie); ' cookie ' + this._cookie);
this._emitDone(true); this._emitDone(false, true);
} }
}, },
_emitDone: function(dismissed) { _emitDone: function(keepVisible, dismissed) {
if (!this._doneEmitted) { if (!this._doneEmitted) {
this._doneEmitted = true; this._doneEmitted = true;
this.emit('done', dismissed); this.emit('done', keepVisible, dismissed);
} }
}, },
@ -229,7 +219,6 @@ const AuthenticationDialog = new Lang.Class({
this._okButton.can_focus = sensitive; this._okButton.can_focus = sensitive;
this._okButton.reactive = sensitive; this._okButton.reactive = sensitive;
this.setWorking(!sensitive);
}, },
_onEntryActivate: function() { _onEntryActivate: function() {
@ -248,16 +237,12 @@ const AuthenticationDialog = new Lang.Class({
}, },
_onSessionCompleted: function(session, gainedAuthorization) { _onSessionCompleted: function(session, gainedAuthorization) {
if (this._completed || this._doneEmitted) if (this._completed)
return; return;
this._completed = true; this._completed = true;
/* Yay, all done */ if (!gainedAuthorization) {
if (gainedAuthorization) {
this._emitDone(false);
} else {
/* Unless we are showing an existing error message from the PAM /* Unless we are showing an existing error message from the PAM
* module (the PAM module could be reporting the authentication * module (the PAM module could be reporting the authentication
* error providing authentication-method specific information), * error providing authentication-method specific information),
@ -273,10 +258,8 @@ const AuthenticationDialog = new Lang.Class({
this._infoMessageLabel.hide(); this._infoMessageLabel.hide();
this._nullMessageLabel.hide(); this._nullMessageLabel.hide();
} }
/* Try and authenticate again */
this.performAuthentication();
} }
this._emitDone(!gainedAuthorization, false);
}, },
_onSessionRequest: function(session, request, echo_on) { _onSessionRequest: function(session, request, echo_on) {
@ -320,7 +303,6 @@ const AuthenticationDialog = new Lang.Class({
if (this._session) { if (this._session) {
if (!this._completed) if (!this._completed)
this._session.cancel(); this._session.cancel();
this._completed = false;
this._session = null; this._session = null;
} }
}, },
@ -335,7 +317,7 @@ const AuthenticationDialog = new Lang.Class({
cancel: function() { cancel: function() {
this._wasDismissed = true; this._wasDismissed = true;
this.close(global.get_current_time()); this.close(global.get_current_time());
this._emitDone(true); this._emitDone(false, true);
}, },
}); });
Signals.addSignalMethods(AuthenticationDialog.prototype); Signals.addSignalMethods(AuthenticationDialog.prototype);
@ -345,6 +327,7 @@ const AuthenticationAgent = new Lang.Class({
_init: function() { _init: function() {
this._currentDialog = null; this._currentDialog = null;
this._isCompleting = false;
this._handle = null; this._handle = null;
this._native = new Shell.PolkitAuthenticationAgent(); this._native = new Shell.PolkitAuthenticationAgent();
this._native.connect('initiate', Lang.bind(this, this._onInitiate)); this._native.connect('initiate', Lang.bind(this, this._onInitiate));
@ -381,24 +364,45 @@ const AuthenticationAgent = new Lang.Class({
// discussion. // discussion.
this._currentDialog.connect('done', Lang.bind(this, this._onDialogDone)); this._currentDialog.connect('done', Lang.bind(this, this._onDialogDone));
this._currentDialog.performAuthentication(); this._currentDialog.startAuthentication();
}, },
_onCancel: function(nativeAgent) { _onCancel: function(nativeAgent) {
this._completeRequest(false); this._completeRequest(false, false);
}, },
_onDialogDone: function(dialog, dismissed) { _onDialogDone: function(dialog, keepVisible, dismissed) {
this._completeRequest(dismissed); this._completeRequest(keepVisible, dismissed);
}, },
_completeRequest: function(dismissed) { _reallyCompleteRequest: function(dismissed) {
this._currentDialog.close(); this._currentDialog.close();
this._currentDialog.destroySession(); this._currentDialog.destroySession();
this._currentDialog = null; this._currentDialog = null;
this._isCompleting = false;
this._native.complete(dismissed); this._native.complete(dismissed)
}, },
_completeRequest: function(keepVisible, wasDismissed) {
if (this._isCompleting)
return;
this._isCompleting = true;
if (keepVisible) {
// Give the user 2 seconds to read 'Authentication Failure' before
// dismissing the dialog
Mainloop.timeout_add(2000,
Lang.bind(this,
function() {
this._reallyCompleteRequest(wasDismissed);
return false;
}));
} else {
this._reallyCompleteRequest(wasDismissed);
}
}
}); });
const Component = AuthenticationAgent; const Component = AuthenticationAgent;

View File

@ -0,0 +1,62 @@
const Lang = imports.lang;
const Main = imports.ui.main;
const Gio = imports.gi.Gio;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Recorder = new Lang.Class({
Name: 'Recorder',
_init: function() {
this._recorderSettings = new Gio.Settings({ schema: 'org.gnome.shell.recorder' });
this._desktopLockdownSettings = new Gio.Settings({ schema: 'org.gnome.desktop.lockdown' });
this._bindingSettings = new Gio.Settings({ schema: 'org.gnome.shell.keybindings' });
this._recorder = null;
},
enable: function() {
Main.wm.addKeybinding('toggle-recording',
this._bindingSettings,
Meta.KeyBindingFlags.NONE,
Shell.KeyBindingMode.NORMAL |
Shell.KeyBindingMode.OVERVIEW,
Lang.bind(this, this._toggleRecorder));
},
disable: function() {
Main.wm.removeKeybinding('toggle-recording');
},
_ensureRecorder: function() {
if (this._recorder == null)
this._recorder = new Shell.Recorder({ stage: global.stage });
return this._recorder;
},
_toggleRecorder: function() {
let recorder = this._ensureRecorder();
if (recorder.is_recording()) {
recorder.close();
Meta.enable_unredirect_for_screen(global.screen);
} else if (!this._desktopLockdownSettings.get_boolean('disable-save-to-disk')) {
// read the parameters from GSettings always in case they have changed
recorder.set_framerate(this._recorderSettings.get_int('framerate'));
/* Translators: this is a filename used for screencast recording */
// xgettext:no-c-format
recorder.set_file_template(_("Screencast from %d %t") + '.' + this._recorderSettings.get_string('file-extension'));
let pipeline = this._recorderSettings.get_string('pipeline');
if (!pipeline.match(/^\s*$/))
recorder.set_pipeline(pipeline);
else
recorder.set_pipeline(null);
Meta.disable_unredirect_for_screen(global.screen);
recorder.record();
}
}
});
const Component = Recorder;

View File

@ -1,6 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const Lang = imports.lang; const Lang = imports.lang;
@ -14,11 +13,12 @@ const Tp = imports.gi.TelepathyGLib;
const History = imports.misc.history; const History = imports.misc.history;
const Main = imports.ui.main; const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
const NotificationDaemon = imports.ui.notificationDaemon;
const Params = imports.misc.params; const Params = imports.misc.params;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
// See Notification.appendMessage // See Notification.appendMessage
const SCROLLBACK_IMMEDIATE_TIME = 3 * 60; // 3 minutes const SCROLLBACK_IMMEDIATE_TIME = 60; // 1 minute
const SCROLLBACK_RECENT_TIME = 15 * 60; // 15 minutes const SCROLLBACK_RECENT_TIME = 15 * 60; // 15 minutes
const SCROLLBACK_RECENT_LENGTH = 20; const SCROLLBACK_RECENT_LENGTH = 20;
const SCROLLBACK_IDLE_LENGTH = 5; const SCROLLBACK_IDLE_LENGTH = 5;
@ -29,15 +29,11 @@ const SCROLLBACK_HISTORY_LINES = 10;
// See Notification._onEntryChanged // See Notification._onEntryChanged
const COMPOSING_STOP_TIMEOUT = 5; const COMPOSING_STOP_TIMEOUT = 5;
const CLOCK_FORMAT_KEY = 'clock-format';
const NotificationDirection = { const NotificationDirection = {
SENT: 'chat-sent', SENT: 'chat-sent',
RECEIVED: 'chat-received' RECEIVED: 'chat-received'
}; };
const N_ = function(s) { return s; };
function makeMessageFromTpMessage(tpMessage, direction) { function makeMessageFromTpMessage(tpMessage, direction) {
let [text, flags] = tpMessage.to_text(); let [text, flags] = tpMessage.to_text();
@ -420,7 +416,7 @@ const TelepathyClient = new Lang.Class({
_ensureAppSource: function() { _ensureAppSource: function() {
if (this._appSource == null) { if (this._appSource == null) {
this._appSource = new MessageTray.Source(_("Chat"), 'empathy'); this._appSource = new MessageTray.Source(_("Chat"), 'empathy');
this._appSource.policy = new MessageTray.NotificationApplicationPolicy('empathy'); this._appSource.policy = new NotificationDaemon.NotificationApplicationPolicy('empathy');
Main.messageTray.add(this._appSource); Main.messageTray.add(this._appSource);
this._appSource.connect('destroy', Lang.bind(this, function () { this._appSource.connect('destroy', Lang.bind(this, function () {
@ -451,7 +447,6 @@ const ChatSource = new Lang.Class({
this._closedId = this._channel.connect('invalidated', Lang.bind(this, this._channelClosed)); this._closedId = this._channel.connect('invalidated', Lang.bind(this, this._channelClosed));
this._notification = new ChatNotification(this); this._notification = new ChatNotification(this);
this._notification.connect('clicked', Lang.bind(this, this.open));
this._notification.setUrgency(MessageTray.Urgency.HIGH); this._notification.setUrgency(MessageTray.Urgency.HIGH);
this._notifyTimeoutId = 0; this._notifyTimeoutId = 0;
@ -493,7 +488,7 @@ const ChatSource = new Lang.Class({
}, },
_createPolicy: function() { _createPolicy: function() {
return new MessageTray.NotificationApplicationPolicy('empathy'); return new NotificationDaemon.NotificationApplicationPolicy('empathy');
}, },
_updateAlias: function() { _updateAlias: function() {
@ -550,19 +545,20 @@ const ChatSource = new Lang.Class({
this._notification.update(this._notification.title, null, { customContent: true }); this._notification.update(this._notification.title, null, { customContent: true });
}, },
open: function() { open: function(notification) {
if (this._client.is_handling_channel(this._channel)) { if (this._client.is_handling_channel(this._channel)) {
// We are handling the channel, try to pass it to Empathy // We are handling the channel, try to pass it to Empathy
this._client.delegate_channels_async([this._channel], this._client.delegate_channels_async([this._channel],
global.get_current_time(), global.get_current_time(),
'org.freedesktop.Telepathy.Client.Empathy.Chat', null); 'org.freedesktop.Telepathy.Client.Empathy.Chat', null);
} else { }
// We are not the handler, just ask to present the channel else {
let dbus = Tp.DBusDaemon.dup(); // We are not the handler, just ask to present the channel
let cd = Tp.ChannelDispatcher.new(dbus); 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() { _getLogMessages: function() {
@ -626,11 +622,7 @@ const ChatSource = new Lang.Class({
this.notify(); this.notify();
}, },
destroy: function(reason) { _channelClosed: function() {
if (this._destroyed)
return;
this._destroyed = true;
this._channel.disconnect(this._closedId); this._channel.disconnect(this._closedId);
this._channel.disconnect(this._receivedId); this._channel.disconnect(this._receivedId);
this._channel.disconnect(this._pendingId); this._channel.disconnect(this._pendingId);
@ -640,14 +632,7 @@ const ChatSource = new Lang.Class({
this._contact.disconnect(this._notifyAvatarId); this._contact.disconnect(this._notifyAvatarId);
this._contact.disconnect(this._presenceChangedId); this._contact.disconnect(this._presenceChangedId);
if (this._timestampTimeoutId) this.destroy();
Mainloop.source_remove(this._timestampTimeoutId);
this.parent(reason);
},
_channelClosed: function() {
this.destroy(MessageTray.NotificationDestroyedReason.SOURCE_CLOSED);
}, },
/* All messages are new messages for Telepathy sources */ /* All messages are new messages for Telepathy sources */
@ -683,7 +668,6 @@ const ChatSource = new Lang.Class({
Mainloop.source_remove(this._notifyTimeoutId); Mainloop.source_remove(this._notifyTimeoutId);
this._notifyTimeoutId = Mainloop.timeout_add(500, this._notifyTimeoutId = Mainloop.timeout_add(500,
Lang.bind(this, this._notifyTimeout)); Lang.bind(this, this._notifyTimeout));
GLib.Source.set_name_by_id(this._notifyTimeoutId, '[gnome-shell] this._notifyTimeout');
}, },
_notifyTimeout: function() { _notifyTimeout: function() {
@ -692,7 +676,7 @@ const ChatSource = new Lang.Class({
this._notifyTimeoutId = 0; this._notifyTimeoutId = 0;
return GLib.SOURCE_REMOVE; return false;
}, },
// This is called for both messages we send from // This is called for both messages we send from
@ -785,6 +769,7 @@ const ChatNotification = new Lang.Class({
this._createScrollArea(); this._createScrollArea();
this._lastGroup = null; this._lastGroup = null;
this._lastGroupActor = null;
// Keep track of the bottom position for the current adjustment and // Keep track of the bottom position for the current adjustment and
// force a scroll to the bottom if things change while we were at the // force a scroll to the bottom if things change while we were at the
@ -865,6 +850,13 @@ const ChatNotification = new Lang.Class({
for (let i = 0; i < expired.length; i++) for (let i = 0; i < expired.length; i++)
expired[i].actor.destroy(); expired[i].actor.destroy();
} }
let groups = this._contentArea.get_children();
for (let i = 0; i < groups.length; i++) {
let group = groups[i];
if (group.get_n_children() == 0)
group.destroy();
}
}, },
/** /**
@ -903,35 +895,30 @@ const ChatNotification = new Lang.Class({
let group = props.group; let group = props.group;
if (group != this._lastGroup) { if (group != this._lastGroup) {
let style = 'chat-group-' + group;
this._lastGroup = group; this._lastGroup = group;
let emptyLine = new St.Label({ style_class: 'chat-empty-line' }); this._lastGroupActor = new St.BoxLayout({ style_class: style,
this.addActor(emptyLine); vertical: true });
this._history.unshift({ actor: emptyLine, time: timestamp, this.addActor(this._lastGroupActor);
realMessage: false });
} }
let lineBox = new St.BoxLayout({ vertical: false }); this._lastGroupActor.add(body, props.childProps);
lineBox.add(body, props.childProps);
this.addActor(lineBox);
this._lastMessageBox = lineBox;
this.updated(); this.updated();
let timestamp = props.timestamp; let timestamp = props.timestamp;
this._history.unshift({ actor: lineBox, time: timestamp, this._history.unshift({ actor: body, time: timestamp,
realMessage: group != 'meta' }); realMessage: group != 'meta' });
if (!props.noTimestamp) { if (!props.noTimestamp) {
if (timestamp < currentTime - SCROLLBACK_IMMEDIATE_TIME) { if (timestamp < currentTime - SCROLLBACK_IMMEDIATE_TIME)
this.appendTimestamp(); this.appendTimestamp();
} else { else
// Schedule a new timestamp in SCROLLBACK_IMMEDIATE_TIME // Schedule a new timestamp in SCROLLBACK_IMMEDIATE_TIME
// from the timestamp of the message. // from the timestamp of the message.
this._timestampTimeoutId = Mainloop.timeout_add_seconds( this._timestampTimeoutId = Mainloop.timeout_add_seconds(
SCROLLBACK_IMMEDIATE_TIME - (currentTime - timestamp), SCROLLBACK_IMMEDIATE_TIME - (currentTime - timestamp),
Lang.bind(this, this.appendTimestamp)); Lang.bind(this, this.appendTimestamp));
GLib.Source.set_name_by_id(this._timestampTimeoutId, '[gnome-shell] this.appendTimestamp');
}
} }
this._filterMessages(); this._filterMessages();
@ -944,98 +931,49 @@ const ChatNotification = new Lang.Class({
let format; let format;
let desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); // Show only the hour if date is on today
let clockFormat = desktopSettings.get_string(CLOCK_FORMAT_KEY); if(daysAgo < 1){
let hasAmPm = date.toLocaleFormat('%p') != ''; format = "<b>%H:%M</b>";
if (clockFormat == '24h' || !hasAmPm) {
// Show only the time if date is on today
if(daysAgo < 1){
/* Translators: Time in 24h format */
format = N_("%H\u2236%M");
}
// Show the word "Yesterday" and time if date is on yesterday
else if(daysAgo <2){
/* Translators: this is the word "Yesterday" followed by a
time string in 24h format. i.e. "Yesterday, 14:30" */
// xgettext:no-c-format
format = N_("Yesterday, %H\u2236%M");
}
// Show a week day and time if date is in the last week
else if (daysAgo < 7) {
/* Translators: this is the week day name followed by a time
string in 24h format. i.e. "Monday, 14:30" */
// xgettext:no-c-format
format = N_("%A, %H\u2236%M");
} else if (date.getYear() == now.getYear()) {
/* Translators: this is the month name and day number
followed by a time string in 24h format.
i.e. "May 25, 14:30" */
// xgettext:no-c-format
format = N_("%B %d, %H\u2236%M");
} else {
/* Translators: this is the month name, day number, year
number followed by a time string in 24h format.
i.e. "May 25 2012, 14:30" */
// xgettext:no-c-format
format = N_("%B %d %Y, %H\u2236%M");
}
} else {
// Show only the time if date is on today
if(daysAgo < 1){
/* Translators: Time in 12h format */
format = N_("%l\u2236%M %p");
}
// Show the word "Yesterday" and time if date is on yesterday
else if(daysAgo <2){
/* Translators: this is the word "Yesterday" followed by a
time string in 12h format. i.e. "Yesterday, 2:30 pm" */
// xgettext:no-c-format
format = N_("Yesterday, %l\u2236%M %p");
}
// Show a week day and time if date is in the last week
else if (daysAgo < 7) {
/* Translators: this is the week day name followed by a time
string in 12h format. i.e. "Monday, 2:30 pm" */
// xgettext:no-c-format
format = N_("%A, %l\u2236%M %p");
} else if (date.getYear() == now.getYear()) {
/* Translators: this is the month name and day number
followed by a time string in 12h format.
i.e. "May 25, 2:30 pm" */
// xgettext:no-c-format
format = N_("%B %d, %l\u2236%M %p");
} else {
/* Translators: this is the month name, day number, year
number followed by a time string in 12h format.
i.e. "May 25 2012, 2:30 pm"*/
// xgettext:no-c-format
format = N_("%B %d %Y, %l\u2236%M %p");
}
} }
return date.toLocaleFormat(Shell.util_translate_time_string(format)); // Show the word "Yesterday" and time if date is on yesterday
else if(daysAgo <2){
/* Translators: this is the word "Yesterday" followed by a time string. i.e. "Yesterday, 14:30"*/
// xgettext:no-c-format
format = _("<b>Yesterday</b>, <b>%H:%M</b>");
}
// Show a week day and time if date is in the last week
else if (daysAgo < 7) {
/* Translators: this is the week day name followed by a time string. i.e. "Monday, 14:30*/
// xgettext:no-c-format
format = _("<b>%A</b>, <b>%H:%M</b>");
} else if (date.getYear() == now.getYear()) {
/* Translators: this is the month name and day number followed by a time string. i.e. "May 25, 14:30"*/
// xgettext:no-c-format
format = _("<b>%B</b> <b>%d</b>, <b>%H:%M</b>");
} else {
/* Translators: this is the month name, day number, year number followed by a time string. i.e. "May 25 2012, 14:30"*/
// xgettext:no-c-format
format = _("<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> ");
}
return date.toLocaleFormat(format);
}, },
appendTimestamp: function() { appendTimestamp: function() {
this._timestampTimeoutId = 0;
let lastMessageTime = this._history[0].time; let lastMessageTime = this._history[0].time;
let lastMessageDate = new Date(lastMessageTime * 1000); let lastMessageDate = new Date(lastMessageTime * 1000);
let timeLabel = new St.Label({ text: this._formatTimestamp(lastMessageDate), let timeLabel = this._append({ body: this._formatTimestamp(lastMessageDate),
style_class: 'chat-meta-message', group: 'meta',
x_expand: true, styles: ['chat-meta-message'],
y_expand: true, childProps: { expand: true, x_fill: false },
x_align: Clutter.ActorAlign.END, noTimestamp: true,
y_align: Clutter.ActorAlign.END }); timestamp: lastMessageTime });
this._lastMessageBox.add_actor(timeLabel);
this._filterMessages(); this._filterMessages();
return GLib.SOURCE_REMOVE; return false;
}, },
appendAliasChange: function(oldAlias, newAlias) { appendAliasChange: function(oldAlias, newAlias) {
@ -1073,7 +1011,7 @@ const ChatNotification = new Lang.Class({
this.source.setChatState(Tp.ChannelChatState.PAUSED); this.source.setChatState(Tp.ChannelChatState.PAUSED);
return GLib.SOURCE_REMOVE; return false;
}, },
_onEntryChanged: function() { _onEntryChanged: function() {
@ -1096,7 +1034,6 @@ const ChatNotification = new Lang.Class({
this._composingTimeoutId = Mainloop.timeout_add_seconds( this._composingTimeoutId = Mainloop.timeout_add_seconds(
COMPOSING_STOP_TIMEOUT, COMPOSING_STOP_TIMEOUT,
Lang.bind(this, this._composingStopTimeout)); Lang.bind(this, this._composingStopTimeout));
GLib.Source.set_name_by_id(this._composingTimeoutId, '[gnome-shell] this._composingStopTimeout');
} else { } else {
this.source.setChatState(Tp.ChannelChatState.ACTIVE); this.source.setChatState(Tp.ChannelChatState.ACTIVE);
} }
@ -1123,7 +1060,7 @@ const ApproverSource = new Lang.Class({
}, },
_createPolicy: function() { _createPolicy: function() {
return new MessageTray.NotificationApplicationPolicy('empathy'); return new NotificationDaemon.NotificationApplicationPolicy('empathy');
}, },
destroy: function() { destroy: function() {
@ -1158,16 +1095,22 @@ const RoomInviteNotification = new Lang.Class({
* for example. */ * for example. */
this.addBody(_("%s is inviting you to join %s").format(inviter.get_alias(), channel.get_identifier())); this.addBody(_("%s is inviting you to join %s").format(inviter.get_alias(), channel.get_identifier()));
this.addAction(_("Decline"), Lang.bind(this, function() { this.addButton('decline', _("Decline"));
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) { this.addButton('accept', _("Accept"));
src.leave_channels_finish(result);
}); this.connect('action-invoked', Lang.bind(this, function(self, action) {
this.destroy(); switch (action) {
})); case 'decline':
this.addAction(_("Accept"), Lang.bind(this, function() { dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE,
dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) { '', function(src, result) {
src.handle_with_time_finish(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.destroy(); this.destroy();
})); }));
} }
@ -1191,19 +1134,23 @@ const AudioVideoNotification = new Lang.Class({
this.parent(source, title, null, { customContent: true }); this.parent(source, title, null, { customContent: true });
this.setResident(true); this.setResident(true);
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 */ /* translators: this is a button label (verb), not a noun */
this.addAction(_("Answer"), Lang.bind(this, function() { this.addButton('answer', _("Answer"));
dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) {
src.handle_with_time_finish(result); 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.destroy(); this.destroy();
})); }));
} }
@ -1227,16 +1174,22 @@ const FileTransferNotification = new Lang.Class({
{ customContent: true }); { customContent: true });
this.setResident(true); this.setResident(true);
this.addAction(_("Decline"), Lang.bind(this, function() { this.addButton('decline', _("Decline"));
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) { this.addButton('accept', _("Accept"));
src.leave_channels_finish(result);
}); this.connect('action-invoked', Lang.bind(this, function(self, action) {
this.destroy(); switch (action) {
})); case 'decline':
this.addAction(_("Accept"), Lang.bind(this, function() { dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE,
dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) { '', function(src, result) {
src.handle_with_time_finish(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.destroy(); this.destroy();
})); }));
} }
@ -1266,8 +1219,8 @@ const SubscriptionRequestNotification = new Lang.Class({
let file = contact.get_avatar_file(); let file = contact.get_avatar_file();
if (file) { if (file) {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; let uri = file.get_uri();
iconBox.child = textureCache.load_file_async(file, iconBox._size, iconBox._size, scaleFactor); iconBox.child = textureCache.load_uri_async(uri, iconBox._size, iconBox._size);
} }
else { else {
iconBox.child = new St.Icon({ icon_name: 'avatar-default', iconBox.child = new St.Icon({ icon_name: 'avatar-default',
@ -1284,20 +1237,27 @@ const SubscriptionRequestNotification = new Lang.Class({
this.addActor(layout); this.addActor(layout);
this.addAction(_("Decline"), Lang.bind(this, function() { this.addButton('decline', _("Decline"));
contact.remove_async(function(src, result) { this.addButton('accept', _("Accept"));
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);
});
contact.request_subscription_async('', function(src, result) { this.connect('action-invoked', Lang.bind(this, function(self, action) {
src.request_subscription_finish(result); 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
})); }));
this._changedId = contact.connect('subscription-states-changed', this._changedId = contact.connect('subscription-states-changed',
@ -1396,11 +1356,18 @@ const AccountNotification = new Lang.Class({
this._account = account; this._account = account;
this.addAction(_("View account"), Lang.bind(this, function() { this.addButton('view', _("View account"));
let cmd = 'empathy-accounts --select-account=' +
account.get_path_suffix(); this.connect('action-invoked', Lang.bind(this, function(self, action) {
let app_info = Gio.app_info_create_from_commandline(cmd, null, 0); switch (action) {
app_info.launch([], global.create_app_launch_context(0, -1)); 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._enabledId = account.connect('notify::enabled', this._enabledId = account.connect('notify::enabled',
@ -1418,12 +1385,7 @@ const AccountNotification = new Lang.Class({
if (status == Tp.ConnectionStatus.CONNECTED) { if (status == Tp.ConnectionStatus.CONNECTED) {
this.destroy(); this.destroy();
} else if (status == Tp.ConnectionStatus.DISCONNECTED) { } else if (status == Tp.ConnectionStatus.DISCONNECTED) {
let connectionError = account.connection_error; this.update(this.title, this._getMessage(account.connection_error));
if (connectionError == Tp.error_get_dbus_name(Tp.Error.CANCELLED))
this.destroy();
else
this.update(this.title, this._getMessage(connectionError));
} }
})); }));
}, },

View File

@ -58,10 +58,15 @@ const CtrlAltTabManager = new Lang.Class({
}, },
focusGroup: function(item, timestamp) { focusGroup: function(item, timestamp) {
if (item.focusCallback) if (item.focusCallback) {
item.focusCallback(timestamp); item.focusCallback(timestamp);
else } else {
if (global.stage_input_mode == Shell.StageInputMode.NONREACTIVE ||
global.stage_input_mode == Shell.StageInputMode.NORMAL)
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
item.root.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); item.root.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
}
}, },
// Sort the items into a consistent order; panel first, tray last, // Sort the items into a consistent order; panel first, tray last,
@ -84,25 +89,19 @@ const CtrlAltTabManager = new Lang.Class({
let items = this._items.filter(function (item) { return item.proxy.mapped; }); let items = this._items.filter(function (item) { return item.proxy.mapped; });
// And add the windows metacity would show in its Ctrl-Alt-Tab list // And add the windows metacity would show in its Ctrl-Alt-Tab list
if (Main.sessionMode.hasWindows && !Main.overview.visible) { if (!Main.overview.visible) {
let screen = global.screen; let screen = global.screen;
let display = screen.get_display(); let display = screen.get_display();
let windows = display.get_tab_list(Meta.TabList.DOCKS, screen.get_active_workspace ()); let windows = display.get_tab_list(Meta.TabList.DOCKS, screen, screen.get_active_workspace ());
let windowTracker = Shell.WindowTracker.get_default(); let windowTracker = Shell.WindowTracker.get_default();
let textureCache = St.TextureCache.get_default(); let textureCache = St.TextureCache.get_default();
for (let i = 0; i < windows.length; i++) { for (let i = 0; i < windows.length; i++) {
let icon = null; let icon;
let iconName = null; let app = windowTracker.get_window_app(windows[i]);
if (windows[i].get_window_type () == Meta.WindowType.DESKTOP) { if (app)
iconName = 'video-display-symbolic'; icon = app.create_icon_texture(POPUP_APPICON_SIZE);
} else { else
let app = windowTracker.get_window_app(windows[i]); icon = textureCache.bind_pixbuf_property(windows[i], 'icon');
if (app)
icon = app.create_icon_texture(POPUP_APPICON_SIZE);
else
icon = textureCache.bind_cairo_surface_property(windows[i], 'icon');
}
items.push({ name: windows[i].title, items.push({ name: windows[i].title,
proxy: windows[i].get_compositor_private(), proxy: windows[i].get_compositor_private(),
focusCallback: Lang.bind(windows[i], focusCallback: Lang.bind(windows[i],
@ -110,7 +109,6 @@ const CtrlAltTabManager = new Lang.Class({
Main.activateWindow(this, timestamp); Main.activateWindow(this, timestamp);
}), }),
iconActor: icon, iconActor: icon,
iconName: iconName,
sortGroup: SortGroup.MIDDLE }); sortGroup: SortGroup.MIDDLE });
} }
} }
@ -132,6 +130,8 @@ const CtrlAltTabManager = new Lang.Class({
}, },
_focusWindows: function(timestamp) { _focusWindows: function(timestamp) {
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
global.stage.key_focus = null;
global.screen.focus_default_window(timestamp); global.screen.focus_default_window(timestamp);
} }
}); });
@ -140,25 +140,31 @@ const CtrlAltTabPopup = new Lang.Class({
Name: 'CtrlAltTabPopup', Name: 'CtrlAltTabPopup',
Extends: SwitcherPopup.SwitcherPopup, Extends: SwitcherPopup.SwitcherPopup,
_init: function(items) { _createSwitcher: function() {
this.parent(items);
this._switcherList = new CtrlAltTabSwitcher(this._items); this._switcherList = new CtrlAltTabSwitcher(this._items);
return true;
}, },
_keyPressHandler: function(keysym, action) { _initialSelection: function(backward, binding) {
if (binding == 'switch-panels') {
if (backward)
this._selectedIndex = this._items.length - 1;
} else if (binding == 'switch-panels-backward') {
if (!backward)
this._selectedIndex = this._items.length - 1;
}
this._select(this._selectedIndex);
},
_keyPressHandler: function(keysym, backwards, action) {
if (action == Meta.KeyBindingAction.SWITCH_PANELS) if (action == Meta.KeyBindingAction.SWITCH_PANELS)
this._select(this._next()); this._select(backwards ? this._previous() : this._next());
else if (action == Meta.KeyBindingAction.SWITCH_PANELS_BACKWARD) else if (action == Meta.KeyBindingAction.SWITCH_PANELS_BACKWARD)
this._select(this._previous()); this._select(backwards ? this._next() : this._previous());
else if (keysym == Clutter.Left) else if (keysym == Clutter.Left)
this._select(this._previous()); this._select(this._previous());
else if (keysym == Clutter.Right) else if (keysym == Clutter.Right)
this._select(this._next()); this._select(this._next());
else
return Clutter.EVENT_PROPAGATE;
return Clutter.EVENT_STOP;
}, },
_finish : function(time) { _finish : function(time) {

View File

@ -1,8 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Signals = imports.signals; const Signals = imports.signals;
const Lang = imports.lang; const Lang = imports.lang;
const Meta = imports.gi.Meta; const Meta = imports.gi.Meta;
@ -270,9 +268,6 @@ const ShowAppsIcon = new Lang.Class({
if (app == null) if (app == null)
return false; return false;
if (!this._settings.is_writable('favorite-apps'))
return false;
let id = app.get_id(); let id = app.get_id();
let isFavorite = AppFavorites.getAppFavorites().isFavorite(id); let isFavorite = AppFavorites.getAppFavorites().isFavorite(id);
return isFavorite; return isFavorite;
@ -292,7 +287,13 @@ const ShowAppsIcon = new Lang.Class({
}, },
handleDragOver: function(source, actor, x, y, time) { handleDragOver: function(source, actor, x, y, time) {
if (!this._canRemoveApp(getAppFromSource(source))) let app = getAppFromSource(source);
if (app == null)
return DND.DragMotionResult.NO_DROP;
let id = app.get_id();
let isFavorite = AppFavorites.getAppFavorites().isFavorite(id);
if (!isFavorite)
return DND.DragMotionResult.NO_DROP; return DND.DragMotionResult.NO_DROP;
return DND.DragMotionResult.MOVE_DROP; return DND.DragMotionResult.MOVE_DROP;
@ -300,7 +301,7 @@ const ShowAppsIcon = new Lang.Class({
acceptDrop: function(source, actor, x, y, time) { acceptDrop: function(source, actor, x, y, time) {
let app = getAppFromSource(source); let app = getAppFromSource(source);
if (!this._canRemoveApp(app)) if (app == null)
return false; return false;
let id = app.get_id(); let id = app.get_id();
@ -325,16 +326,6 @@ const DragPlaceholderItem = new Lang.Class({
} }
}); });
const EmptyDropTargetItem = new Lang.Class({
Name: 'EmptyDropTargetItem',
Extends: DashItemContainer,
_init: function() {
this.parent();
this.setChild(new St.Bin({ style_class: 'empty-dash-drop-target' }));
}
});
const DashActor = new Lang.Class({ const DashActor = new Lang.Class({
Name: 'DashActor', Name: 'DashActor',
Extends: St.Widget, Extends: St.Widget,
@ -385,8 +376,6 @@ const DashActor = new Lang.Class({
} }
}); });
const baseIconSizes = [ 16, 22, 24, 32, 48, 64 ];
const Dash = new Lang.Class({ const Dash = new Lang.Class({
Name: 'Dash', Name: 'Dash',
@ -428,14 +417,9 @@ const Dash = new Lang.Class({
this._workId = Main.initializeDeferredWork(this._box, Lang.bind(this, this._redisplay)); this._workId = Main.initializeDeferredWork(this._box, Lang.bind(this, this._redisplay));
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
this._appSystem = Shell.AppSystem.get_default(); this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed', Lang.bind(this, function() { this._appSystem.connect('installed-changed', Lang.bind(this, this._queueRedisplay));
AppFavorites.getAppFavorites().reload();
this._queueRedisplay();
}));
AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._queueRedisplay)); AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._queueRedisplay));
this._appSystem.connect('app-state-changed', Lang.bind(this, this._queueRedisplay)); this._appSystem.connect('app-state-changed', Lang.bind(this, this._queueRedisplay));
@ -457,12 +441,6 @@ const Dash = new Lang.Class({
dragMotion: Lang.bind(this, this._onDragMotion) dragMotion: Lang.bind(this, this._onDragMotion)
}; };
DND.addDragMonitor(this._dragMonitor); DND.addDragMonitor(this._dragMonitor);
if (this._box.get_n_children() == 0) {
this._emptyDropTarget = new EmptyDropTargetItem();
this._box.insert_child_at_index(this._emptyDropTarget, 0);
this._emptyDropTarget.show(true);
}
}, },
_onDragCancelled: function() { _onDragCancelled: function() {
@ -479,7 +457,6 @@ const Dash = new Lang.Class({
_endDrag: function() { _endDrag: function() {
this._clearDragPlaceholder(); this._clearDragPlaceholder();
this._clearEmptyDropTarget();
this._showAppsIcon.setDragApp(null); this._showAppsIcon.setDragApp(null);
DND.removeDragMonitor(this._dragMonitor); DND.removeDragMonitor(this._dragMonitor);
}, },
@ -514,38 +491,29 @@ const Dash = new Lang.Class({
Main.queueDeferredWork(this._workId); Main.queueDeferredWork(this._workId);
}, },
_hookUpLabel: function(item, appIcon) { _hookUpLabel: function(item) {
item.child.connect('notify::hover', Lang.bind(this, function() { item.child.connect('notify::hover', Lang.bind(this, function() {
this._syncLabel(item, appIcon); this._onHover(item);
})); }));
Main.overview.connect('hiding', Lang.bind(this, function() { Main.overview.connect('hiding', Lang.bind(this, function() {
this._labelShowing = false; this._labelShowing = false;
item.hideLabel(); item.hideLabel();
})); }));
if (appIcon) {
appIcon.connect('sync-tooltip', Lang.bind(this, function() {
this._syncLabel(item, appIcon);
}));
}
}, },
_createAppItem: function(app) { _createAppItem: function(app) {
let appIcon = new AppDisplay.AppIcon(app, let appIcon = new AppDisplay.AppIcon(app,
{ setSizeManually: true, { setSizeManually: true,
showLabel: false }); showLabel: false });
if (appIcon._draggable) { appIcon._draggable.connect('drag-begin',
appIcon._draggable.connect('drag-begin', Lang.bind(this, function() {
Lang.bind(this, function() { appIcon.actor.opacity = 50;
appIcon.actor.opacity = 50; }));
})); appIcon._draggable.connect('drag-end',
appIcon._draggable.connect('drag-end', Lang.bind(this, function() {
Lang.bind(this, function() { appIcon.actor.opacity = 255;
appIcon.actor.opacity = 255; }));
}));
}
appIcon.connect('menu-state-changed', appIcon.connect('menu-state-changed',
Lang.bind(this, function(appIcon, opened) { Lang.bind(this, function(appIcon, opened) {
this._itemMenuStateChanged(item, opened); this._itemMenuStateChanged(item, opened);
@ -560,7 +528,7 @@ const Dash = new Lang.Class({
item.setLabelText(app.get_name()); item.setLabelText(app.get_name());
appIcon.icon.setIconSize(this.iconSize); appIcon.icon.setIconSize(this.iconSize);
this._hookUpLabel(item, appIcon); this._hookUpLabel(item);
return item; return item;
}, },
@ -578,20 +546,16 @@ const Dash = new Lang.Class({
} }
}, },
_syncLabel: function (item, appIcon) { _onHover: function (item) {
let shouldShow = appIcon ? appIcon.shouldShowTooltip() : item.child.get_hover(); if (item.child.get_hover()) {
if (shouldShow) {
if (this._showLabelTimeoutId == 0) { if (this._showLabelTimeoutId == 0) {
let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT; let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT;
this._showLabelTimeoutId = Mainloop.timeout_add(timeout, this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
Lang.bind(this, function() { Lang.bind(this, function() {
this._labelShowing = true; this._labelShowing = true;
item.showLabel(); item.showLabel();
this._showLabelTimeoutId = 0; return false;
return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._showLabelTimeoutId, '[gnome-shell] item.showLabel');
if (this._resetHoverTimeoutId > 0) { if (this._resetHoverTimeoutId > 0) {
Mainloop.source_remove(this._resetHoverTimeoutId); Mainloop.source_remove(this._resetHoverTimeoutId);
this._resetHoverTimeoutId = 0; this._resetHoverTimeoutId = 0;
@ -606,10 +570,8 @@ const Dash = new Lang.Class({
this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT, this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
Lang.bind(this, function() { Lang.bind(this, function() {
this._labelShowing = false; this._labelShowing = false;
this._resetHoverTimeoutId = 0; return false;
return GLib.SOURCE_REMOVE;
})); }));
GLib.Source.set_name_by_id(this._resetHoverTimeoutId, '[gnome-shell] this._labelShowing');
} }
} }
}, },
@ -645,24 +607,25 @@ const Dash = new Lang.Class({
let minHeight, natHeight; let minHeight, natHeight;
// Enforce the current icon size during the size request // Enforce the current icon size during the size request
firstIcon.setIconSize(this.iconSize); let [currentWidth, currentHeight] = firstIcon.icon.get_size();
firstIcon.icon.set_size(this.iconSize, this.iconSize);
[minHeight, natHeight] = firstButton.get_preferred_height(-1); [minHeight, natHeight] = firstButton.get_preferred_height(-1);
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; firstIcon.icon.set_size(currentWidth, currentHeight);
let iconSizes = baseIconSizes.map(function(s) {
return s * scaleFactor;
});
// Subtract icon padding and box spacing from the available height // Subtract icon padding and box spacing from the available height
availHeight -= iconChildren.length * (natHeight - this.iconSize * scaleFactor) + availHeight -= iconChildren.length * (natHeight - this.iconSize) +
(iconChildren.length - 1) * spacing; (iconChildren.length - 1) * spacing;
let availSize = availHeight / iconChildren.length; let availSize = availHeight / iconChildren.length;
let newIconSize = baseIconSizes[0]; let iconSizes = [ 16, 22, 24, 32, 48, 64 ];
let newIconSize = 16;
for (let i = 0; i < iconSizes.length; i++) { for (let i = 0; i < iconSizes.length; i++) {
if (iconSizes[i] < availSize) if (iconSizes[i] < availSize)
newIconSize = baseIconSizes[i]; newIconSize = iconSizes[i];
} }
if (newIconSize == this.iconSize) if (newIconSize == this.iconSize)
@ -834,21 +797,9 @@ const Dash = new Lang.Class({
_clearDragPlaceholder: function() { _clearDragPlaceholder: function() {
if (this._dragPlaceholder) { if (this._dragPlaceholder) {
this._animatingPlaceholdersCount++;
this._dragPlaceholder.animateOutAndDestroy(); this._dragPlaceholder.animateOutAndDestroy();
this._dragPlaceholder.connect('destroy',
Lang.bind(this, function() {
this._animatingPlaceholdersCount--;
}));
this._dragPlaceholder = null; this._dragPlaceholder = null;
} this._dragPlaceholderPos = -1;
this._dragPlaceholderPos = -1;
},
_clearEmptyDropTarget: function() {
if (this._emptyDropTarget) {
this._emptyDropTarget.animateOutAndDestroy();
this._emptyDropTarget = null;
} }
}, },
@ -859,9 +810,6 @@ const Dash = new Lang.Class({
if (app == null || app.is_window_backed()) if (app == null || app.is_window_backed())
return DND.DragMotionResult.NO_DROP; return DND.DragMotionResult.NO_DROP;
if (!this._settings.is_writable('favorite-apps'))
return DND.DragMotionResult.NO_DROP;
let favorites = AppFavorites.getAppFavorites().getFavorites(); let favorites = AppFavorites.getAppFavorites().getFavorites();
let numFavorites = favorites.length; let numFavorites = favorites.length;
@ -879,18 +827,23 @@ const Dash = new Lang.Class({
numChildren--; numChildren--;
} }
let pos; let pos = Math.floor(y * numChildren / boxHeight);
if (!this._emptyDropTarget)
pos = Math.floor(y * numChildren / boxHeight);
else
pos = 0; // always insert at the top when dash is empty
if (pos != this._dragPlaceholderPos && pos <= numFavorites && this._animatingPlaceholdersCount == 0) { if (pos != this._dragPlaceholderPos && pos <= numFavorites && this._animatingPlaceholdersCount == 0) {
this._dragPlaceholderPos = pos; this._dragPlaceholderPos = pos;
// Don't allow positioning before or after self // Don't allow positioning before or after self
if (favPos != -1 && (pos == favPos || pos == favPos + 1)) { if (favPos != -1 && (pos == favPos || pos == favPos + 1)) {
this._clearDragPlaceholder(); if (this._dragPlaceholder) {
this._dragPlaceholder.animateOutAndDestroy();
this._animatingPlaceholdersCount++;
this._dragPlaceholder.connect('destroy',
Lang.bind(this, function() {
this._animatingPlaceholdersCount--;
}));
}
this._dragPlaceholder = null;
return DND.DragMotionResult.CONTINUE; return DND.DragMotionResult.CONTINUE;
} }
@ -915,9 +868,9 @@ const Dash = new Lang.Class({
// Remove the drag placeholder if we are not in the // Remove the drag placeholder if we are not in the
// "favorites zone" // "favorites zone"
if (pos > numFavorites) if (pos > numFavorites && this._dragPlaceholder) {
this._clearDragPlaceholder(); this._clearDragPlaceholder();
}
if (!this._dragPlaceholder) if (!this._dragPlaceholder)
return DND.DragMotionResult.NO_DROP; return DND.DragMotionResult.NO_DROP;
@ -938,9 +891,6 @@ const Dash = new Lang.Class({
return false; return false;
} }
if (!this._settings.is_writable('favorite-apps'))
return false;
let id = app.get_id(); let id = app.get_id();
let favorites = AppFavorites.getAppFavorites().getFavoriteMap(); let favorites = AppFavorites.getAppFavorites().getFavoriteMap();

View File

@ -3,7 +3,6 @@
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const GnomeDesktop = imports.gi.GnomeDesktop; const GnomeDesktop = imports.gi.GnomeDesktop;
const GObject = imports.gi.GObject;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Cairo = imports.cairo; const Cairo = imports.cairo;
@ -19,7 +18,8 @@ const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const Calendar = imports.ui.calendar; const Calendar = imports.ui.calendar;
function _onVertSepRepaint(area) { function _onVertSepRepaint (area)
{
let cr = area.get_context(); let cr = area.get_context();
let themeNode = area.get_theme_node(); let themeNode = area.get_theme_node();
let [width, height] = area.get_surface_size(); let [width, height] = area.get_surface_size();
@ -33,7 +33,7 @@ function _onVertSepRepaint(area) {
cr.setLineWidth(stippleWidth); cr.setLineWidth(stippleWidth);
cr.stroke(); cr.stroke();
cr.$dispose(); cr.$dispose();
} };
const DateMenuButton = new Lang.Class({ const DateMenuButton = new Lang.Class({
Name: 'DateMenuButton', Name: 'DateMenuButton',
@ -49,13 +49,16 @@ const DateMenuButton = new Lang.Class({
menuAlignment = 1.0 - menuAlignment; menuAlignment = 1.0 - menuAlignment;
this.parent(menuAlignment); this.parent(menuAlignment);
this._clockDisplay = new St.Label({ y_align: Clutter.ActorAlign.CENTER }); // At this moment calendar menu is not keyboard navigable at
this.actor.label_actor = this._clockDisplay; // all (so not accessible), so it doesn't make sense to set as
this.actor.add_actor(this._clockDisplay); // role ATK_ROLE_MENU like other elements of the panel.
this.actor.add_style_class_name ('clock-display'); this.actor.accessible_role = Atk.Role.LABEL;
hbox = new St.BoxLayout({ name: 'calendarArea' }); this._clockDisplay = new St.Label();
this.menu.box.add_child(hbox); this.actor.add_actor(this._clockDisplay);
hbox = new St.BoxLayout({name: 'calendarArea' });
this.menu.addActor(hbox);
// Fill up the first column // Fill up the first column
@ -63,47 +66,46 @@ const DateMenuButton = new Lang.Class({
hbox.add(vbox); hbox.add(vbox);
// Date // Date
// Having the ability to go to the current date if the user is already this._date = new St.Label();
// on the current date can be confusing. So don't make the button reactive this.actor.label_actor = this._clockDisplay;
// until the selected date changes. this._date.style_class = 'datemenu-date-label';
this._date = new St.Button({ style_class: 'datemenu-date-label', vbox.add(this._date);
reactive: false
});
this._date.connect('clicked',
Lang.bind(this, function() {
this._calendar.setDate(new Date(), false);
}));
vbox.add(this._date, { x_fill: false });
this._eventList = new Calendar.EventsList(); this._eventList = new Calendar.EventsList();
this._calendar = new Calendar.Calendar(); this._calendar = new Calendar.Calendar();
this._calendar.connect('selected-date-changed', this._calendar.connect('selected-date-changed',
Lang.bind(this, function(calendar, date) { Lang.bind(this, function(calendar, date) {
// we know this._eventList is defined here, because selected-data-changed
// only gets emitted when the user clicks a date in the calendar,
// and the calender makes those dates unclickable when instantiated with
// a null event source
this._eventList.setDate(date); this._eventList.setDate(date);
// Make the button reactive only if the selected date is not the current date.
this._date.can_focus = this._date.reactive = !this._isToday(date)
})); }));
vbox.add(this._calendar.actor); vbox.add(this._calendar.actor);
let separator = new PopupMenu.PopupSeparatorMenuItem(); let separator = new PopupMenu.PopupSeparatorMenuItem();
vbox.add(separator.actor, { y_align: St.Align.END, expand: true, y_fill: false }); separator.setColumnWidths(1);
vbox.add(separator.actor, {y_align: St.Align.END, expand: true, y_fill: false});
this._openCalendarItem = new PopupMenu.PopupMenuItem(_("Open Calendar")); this._openCalendarItem = new PopupMenu.PopupMenuItem(_("Open Calendar"));
this._openCalendarItem.connect('activate', Lang.bind(this, this._onOpenCalendarActivate)); this._openCalendarItem.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
this._openCalendarItem.actor.can_focus = false;
vbox.add(this._openCalendarItem.actor, {y_align: St.Align.END, expand: true, y_fill: false}); vbox.add(this._openCalendarItem.actor, {y_align: St.Align.END, expand: true, y_fill: false});
this._openClocksItem = new PopupMenu.PopupMenuItem(_("Open Clocks")); this._openClocksItem = new PopupMenu.PopupMenuItem(_("Open Clocks"));
this._openClocksItem.connect('activate', Lang.bind(this, this._onOpenClocksActivate)); this._openClocksItem.connect('activate', Lang.bind(this, this._onOpenClocksActivate));
this._openClocksItem.actor.can_focus = false;
vbox.add(this._openClocksItem.actor, {y_align: St.Align.END, expand: true, y_fill: false}); vbox.add(this._openClocksItem.actor, {y_align: St.Align.END, expand: true, y_fill: false});
Shell.AppSystem.get_default().connect('installed-changed', Shell.AppSystem.get_default().connect('installed-changed',
Lang.bind(this, this._appInstalledChanged)); Lang.bind(this, this._appInstalledChanged));
this._appInstalledChanged();
item = this.menu.addSettingsAction(_("Date & Time Settings"), 'gnome-datetime-panel.desktop'); item = this.menu.addSettingsAction(_("Date & Time Settings"), 'gnome-datetime-panel.desktop');
if (item) { if (item) {
item.actor.show_on_set_parent = false; item.actor.show_on_set_parent = false;
item.actor.can_focus = false;
item.actor.reparent(vbox); item.actor.reparent(vbox);
this._dateAndTimeSeparator = separator; this._dateAndTimeSeparator = separator;
} }
@ -114,65 +116,68 @@ const DateMenuButton = new Lang.Class({
hbox.add(this._separator); hbox.add(this._separator);
// Fill up the second column // Fill up the second column
hbox.add(this._eventList.actor, { expand: true, y_fill: false, y_align: St.Align.START }); vbox = new St.BoxLayout({ name: 'calendarEventsArea',
vertical: true });
hbox.add(vbox, { expand: true });
// Event list
vbox.add(this._eventList.actor, { expand: true });
// Whenever the menu is opened, select today // Whenever the menu is opened, select today
this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) { this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {
if (isOpen) { if (isOpen) {
let now = new Date(); let now = new Date();
this._calendar.setDate(now); /* Passing true to setDate() forces events to be reloaded. We
* want this behavior, because
/* Translators: This is the date format to use when the calendar popup is *
* shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM"). * o It will cause activation of the calendar server which is
* useful if it has crashed
*
* o It will cause the calendar server to reload events which
* is useful if dynamic updates are not supported or not
* properly working
*
* Since this only happens when the menu is opened, the cost
* isn't very big.
*/ */
let dateFormat = Shell.util_translate_time_string (N_("%A %B %e, %Y")); this._calendar.setDate(now, true);
this._date.set_label(now.toLocaleFormat(dateFormat)); // No need to update this._eventList as ::selected-date-changed
// signal will fire
} }
})); }));
// Done with hbox for calendar and event list // Done with hbox for calendar and event list
this._clock = new GnomeDesktop.WallClock(); this._clock = new GnomeDesktop.WallClock();
this._clock.bind_property('clock', this._clockDisplay, 'text', GObject.BindingFlags.SYNC_CREATE); this._clock.connect('notify::clock', Lang.bind(this, this._updateClockAndDate));
this._updateClockAndDate();
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated)); Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
this._sessionUpdated(); this._sessionUpdated();
}, },
_isToday: function(date) {
let now = new Date();
return now.getYear() == date.getYear() &&
now.getMonth() == date.getMonth() &&
now.getDate() == date.getDate();
},
_appInstalledChanged: function() { _appInstalledChanged: function() {
this._calendarApp = undefined; let app = Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop');
this._updateEventsVisibility(); this._openClocksItem.actor.visible = app !== null;
}, },
_updateEventsVisibility: function() { _updateEventsVisibility: function() {
let visible = this._eventSource.hasCalendars; let visible = this._eventSource.hasCalendars;
this._openCalendarItem.actor.visible = visible && this._openCalendarItem.actor.visible = visible;
(this._getCalendarApp() != null); this._openClocksItem.actor.visible = visible;
this._openClocksItem.actor.visible = visible &&
(this._getClockApp() != null);
this._separator.visible = visible; this._separator.visible = visible;
this._eventList.actor.visible = visible;
if (visible) { if (visible) {
let alignment = 0.25; let alignment = 0.25;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
alignment = 1.0 - alignment; alignment = 1.0 - alignment;
this.menu._arrowAlignment = alignment; this.menu._arrowAlignment = alignment;
this._eventList.actor.get_parent().show();
} else { } else {
this.menu._arrowAlignment = 0.5; this.menu._arrowAlignment = 0.5;
this._eventList.actor.get_parent().hide();
} }
}, },
_getEventSource: function() {
return new Calendar.DBusEventSource();
},
_setEventSource: function(eventSource) { _setEventSource: function(eventSource) {
if (this._eventSource) if (this._eventSource)
this._eventSource.destroy(); this._eventSource.destroy();
@ -190,7 +195,7 @@ const DateMenuButton = new Lang.Class({
let eventSource; let eventSource;
let showEvents = Main.sessionMode.showCalendarEvents; let showEvents = Main.sessionMode.showCalendarEvents;
if (showEvents) { if (showEvents) {
eventSource = this._getEventSource(); eventSource = new Calendar.DBusEventSource();
} else { } else {
eventSource = new Calendar.EmptyEventSource(); eventSource = new Calendar.EmptyEventSource();
} }
@ -202,37 +207,28 @@ const DateMenuButton = new Lang.Class({
this._dateAndTimeSeparator.actor.visible = Main.sessionMode.allowSettings; this._dateAndTimeSeparator.actor.visible = Main.sessionMode.allowSettings;
}, },
_getCalendarApp: function() { _updateClockAndDate: function() {
if (this._calendarApp !== undefined) this._clockDisplay.set_text(this._clock.clock);
return this._calendarApp; /* Translators: This is the date format to use when the calendar popup is
* shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
let apps = Gio.AppInfo.get_recommended_for_type('text/calendar'); */
if (apps && (apps.length > 0)) { let dateFormat = _("%A %B %e, %Y");
let app = Gio.AppInfo.get_default_for_type('text/calendar', false); let displayDate = new Date();
let defaultInRecommended = apps.some(function(a) { return a.equal(app); }); this._date.set_text(displayDate.toLocaleFormat(dateFormat));
this._calendarApp = defaultInRecommended ? app : apps[0];
} else {
this._calendarApp = null;
}
return this._calendarApp;
},
_getClockApp: function() {
return Shell.AppSystem.get_default().lookup_app('org.gnome.clocks.desktop');
}, },
_onOpenCalendarActivate: function() { _onOpenCalendarActivate: function() {
this.menu.close(); this.menu.close();
let app = this._getCalendarApp(); let app = Gio.AppInfo.get_default_for_type('text/calendar', false);
if (app.get_id() == 'evolution.desktop') if (app.get_id() == 'evolution')
app = Gio.DesktopAppInfo.new('evolution-calendar.desktop'); app = Gio.DesktopAppInfo.new('evolution-calendar');
app.launch([], global.create_app_launch_context(0, -1)); app.launch([], global.create_app_launch_context());
}, },
_onOpenClocksActivate: function() { _onOpenClocksActivate: function() {
this.menu.close(); this.menu.close();
let app = this._getClockApp(); let app = Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop');
app.activate(); app.activate();
} }
}); });

View File

@ -1,11 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk; const Gtk = imports.gi.Gtk;
const St = imports.gi.St; const St = imports.gi.St;
const Lang = imports.lang; const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
@ -28,9 +26,9 @@ const DragMotionResult = {
}; };
const DRAG_CURSOR_MAP = { const DRAG_CURSOR_MAP = {
0: Meta.Cursor.DND_UNSUPPORTED_TARGET, 0: Shell.Cursor.DND_UNSUPPORTED_TARGET,
1: Meta.Cursor.DND_COPY, 1: Shell.Cursor.DND_COPY,
2: Meta.Cursor.DND_MOVE 2: Shell.Cursor.DND_MOVE
}; };
const DragDropResult = { const DragDropResult = {
@ -45,7 +43,9 @@ let dragMonitors = [];
function _getEventHandlerActor() { function _getEventHandlerActor() {
if (!eventHandlerActor) { if (!eventHandlerActor) {
eventHandlerActor = new Clutter.Actor({ width: 0, height: 0 }); eventHandlerActor = new Clutter.Rectangle();
eventHandlerActor.width = 0;
eventHandlerActor.height = 0;
Main.uiGroup.add_actor(eventHandlerActor); Main.uiGroup.add_actor(eventHandlerActor);
// We connect to 'event' rather than 'captured-event' because the capturing phase doesn't happen // We connect to 'event' rather than 'captured-event' because the capturing phase doesn't happen
// when you've grabbed the pointer. // when you've grabbed the pointer.
@ -86,6 +86,11 @@ const _Draggable = new Lang.Class({
this.actor.connect('destroy', Lang.bind(this, function() { this.actor.connect('destroy', Lang.bind(this, function() {
this._actorDestroyed = true; 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) if (this._dragInProgress && this._dragCancellable)
this._cancelDrag(global.get_current_time()); this._cancelDrag(global.get_current_time());
this.disconnectAll(); this.disconnectAll();
@ -101,15 +106,21 @@ 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._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; 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; this._eventsGrabbed = false;
}, },
_onButtonPress : function (actor, event) { _onButtonPress : function (actor, event) {
if (event.get_button() != 1) if (event.get_button() != 1)
return Clutter.EVENT_PROPAGATE; return false;
if (Tweener.getTweenCount(actor)) if (Tweener.getTweenCount(actor))
return Clutter.EVENT_PROPAGATE; return false;
this._buttonDown = true; this._buttonDown = true;
this._grabActor(); this._grabActor();
@ -118,7 +129,7 @@ const _Draggable = new Lang.Class({
this._dragStartX = stageX; this._dragStartX = stageX;
this._dragStartY = stageY; this._dragStartY = stageY;
return Clutter.EVENT_PROPAGATE; return false;
}, },
_grabActor: function() { _grabActor: function() {
@ -138,16 +149,16 @@ const _Draggable = new Lang.Class({
_grabEvents: function() { _grabEvents: function() {
if (!this._eventsGrabbed) { if (!this._eventsGrabbed) {
this._eventsGrabbed = Main.pushModal(_getEventHandlerActor()); Clutter.grab_pointer(_getEventHandlerActor());
if (this._eventsGrabbed) Clutter.grab_keyboard(_getEventHandlerActor());
Clutter.grab_pointer(_getEventHandlerActor()); this._eventsGrabbed = true;
} }
}, },
_ungrabEvents: function() { _ungrabEvents: function() {
if (this._eventsGrabbed) { if (this._eventsGrabbed) {
Clutter.ungrab_pointer(); Clutter.ungrab_pointer();
Main.popModal(_getEventHandlerActor()); Clutter.ungrab_keyboard();
this._eventsGrabbed = false; this._eventsGrabbed = false;
} }
}, },
@ -164,11 +175,11 @@ const _Draggable = new Lang.Class({
} else if (this._dragActor != null && !this._animationInProgress) { } else if (this._dragActor != null && !this._animationInProgress) {
// Drag must have been cancelled with Esc. // Drag must have been cancelled with Esc.
this._dragComplete(); this._dragComplete();
return Clutter.EVENT_STOP; return true;
} else { } else {
// Drag has never started. // Drag has never started.
this._ungrabActor(); this._ungrabActor();
return Clutter.EVENT_PROPAGATE; return false;
} }
// We intercept MOTION event to figure out if the drag has started and to draw // We intercept MOTION event to figure out if the drag has started and to draw
// this._dragActor under the pointer when dragging is in progress // this._dragActor under the pointer when dragging is in progress
@ -184,11 +195,16 @@ const _Draggable = new Lang.Class({
let symbol = event.get_key_symbol(); let symbol = event.get_key_symbol();
if (symbol == Clutter.Escape) { if (symbol == Clutter.Escape) {
this._cancelDrag(event.get_time()); this._cancelDrag(event.get_time());
return Clutter.EVENT_STOP; 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 Clutter.EVENT_PROPAGATE; return false;
}, },
/** /**
@ -229,14 +245,14 @@ const _Draggable = new Lang.Class({
if (this._onEventId) if (this._onEventId)
this._ungrabActor(); this._ungrabActor();
this._grabEvents(); this._grabEvents();
global.screen.set_cursor(Meta.Cursor.DND_IN_DRAG); global.set_cursor(Shell.Cursor.DND_IN_DRAG);
this._dragX = this._dragStartX = stageX; this._dragX = this._dragStartX = stageX;
this._dragY = this._dragStartY = stageY; this._dragY = this._dragStartY = stageY;
if (this.actor._delegate && this.actor._delegate.getDragActor) { if (this.actor._delegate && this.actor._delegate.getDragActor) {
this._dragActor = this.actor._delegate.getDragActor(); this._dragActor = this.actor._delegate.getDragActor();
Main.uiGroup.add_child(this._dragActor); this._dragActor.reparent(Main.uiGroup);
this._dragActor.raise_top(); this._dragActor.raise_top();
Shell.util_set_hidden_from_pick(this._dragActor, true); Shell.util_set_hidden_from_pick(this._dragActor, true);
@ -275,20 +291,19 @@ const _Draggable = new Lang.Class({
this._dragOrigY = this._dragActor.y; this._dragOrigY = this._dragActor.y;
this._dragOrigScale = this._dragActor.scale_x; this._dragOrigScale = this._dragActor.scale_x;
// Set the actor's scale such that it will keep the same this._dragActor.reparent(Main.uiGroup);
// transformed size when it's reparented to the uiGroup this._dragActor.raise_top();
let [scaledWidth, scaledHeight] = this.actor.get_transformed_size(); Shell.util_set_hidden_from_pick(this._dragActor, true);
this._dragActor.set_scale(scaledWidth / this.actor.width,
scaledHeight / this.actor.height);
let [actorStageX, actorStageY] = this.actor.get_transformed_position(); let [actorStageX, actorStageY] = this.actor.get_transformed_position();
this._dragOffsetX = actorStageX - this._dragStartX; this._dragOffsetX = actorStageX - this._dragStartX;
this._dragOffsetY = actorStageY - this._dragStartY; this._dragOffsetY = actorStageY - this._dragStartY;
this._dragOrigParent.remove_actor(this._dragActor); // Set the actor's scale such that it will keep the same
Main.uiGroup.add_child(this._dragActor); // transformed size when it's reparented to the uiGroup
this._dragActor.raise_top(); let [scaledWidth, scaledHeight] = this.actor.get_transformed_size();
Shell.util_set_hidden_from_pick(this._dragActor, true); this.actor.set_scale(scaledWidth / this.actor.width,
scaledHeight / this.actor.height);
} }
this._dragOrigOpacity = this._dragActor.opacity; this._dragOrigOpacity = this._dragActor.opacity;
@ -345,67 +360,60 @@ const _Draggable = new Lang.Class({
return true; return true;
}, },
_updateDragHover : function () {
this._updateHoverId = 0;
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
this._dragX, this._dragY);
let dragEvent = {
x: this._dragX,
y: this._dragY,
dragActor: this._dragActor,
source: this.actor._delegate,
targetActor: target
};
for (let i = 0; i < dragMonitors.length; i++) {
let motionFunc = dragMonitors[i].dragMotion;
if (motionFunc) {
let result = motionFunc(dragEvent);
if (result != DragMotionResult.CONTINUE) {
global.screen.set_cursor(DRAG_CURSOR_MAP[result]);
return GLib.SOURCE_REMOVE;
}
}
}
while (target) {
if (target._delegate && target._delegate.handleDragOver) {
let [r, targX, targY] = target.transform_stage_point(this._dragX, this._dragY);
// We currently loop through all parents on drag-over even if one of the children has handled it.
// We can check the return value of the function and break the loop if it's true if we don't want
// to continue checking the parents.
let result = target._delegate.handleDragOver(this.actor._delegate,
this._dragActor,
targX,
targY,
0);
if (result != DragMotionResult.CONTINUE) {
global.screen.set_cursor(DRAG_CURSOR_MAP[result]);
return GLib.SOURCE_REMOVE;
}
}
target = target.get_parent();
}
global.screen.set_cursor(Meta.Cursor.DND_IN_DRAG);
return GLib.SOURCE_REMOVE;
},
_queueUpdateDragHover: function() {
if (this._updateHoverId)
return;
this._updateHoverId = GLib.idle_add(GLib.PRIORITY_DEFAULT,
Lang.bind(this, this._updateDragHover));
GLib.Source.set_name_by_id(this._updateHoverId, '[gnome-shell] this._updateDragHover');
},
_updateDragPosition : function (event) { _updateDragPosition : function (event) {
let [stageX, stageY] = event.get_coords(); let [stageX, stageY] = event.get_coords();
this._dragX = stageX; this._dragX = stageX;
this._dragY = stageY; this._dragY = stageY;
this._dragActor.set_position(stageX + this._dragOffsetX,
stageY + this._dragOffsetY);
this._queueUpdateDragHover(); // If we are dragging, update the position
if (this._dragActor) {
this._dragActor.set_position(stageX + this._dragOffsetX,
stageY + this._dragOffsetY);
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
stageX, stageY);
// We call observers only once per motion with the innermost
// target actor. If necessary, the observer can walk the
// parent itself.
let dragEvent = {
x: stageX,
y: stageY,
dragActor: this._dragActor,
source: this.actor._delegate,
targetActor: target
};
for (let i = 0; i < dragMonitors.length; i++) {
let motionFunc = dragMonitors[i].dragMotion;
if (motionFunc) {
let result = motionFunc(dragEvent);
if (result != DragMotionResult.CONTINUE) {
global.set_cursor(DRAG_CURSOR_MAP[result]);
return true;
}
}
}
while (target) {
if (target._delegate && target._delegate.handleDragOver) {
let [r, targX, targY] = target.transform_stage_point(stageX, stageY);
// We currently loop through all parents on drag-over even if one of the children has handled it.
// We can check the return value of the function and break the loop if it's true if we don't want
// to continue checking the parents.
let result = target._delegate.handleDragOver(this.actor._delegate,
this._dragActor,
targX,
targY,
event.get_time());
if (result != DragMotionResult.CONTINUE) {
global.set_cursor(DRAG_CURSOR_MAP[result]);
return true;
}
}
target = target.get_parent();
}
global.set_cursor(Shell.Cursor.DND_IN_DRAG);
}
return true; return true;
}, },
@ -458,7 +466,7 @@ const _Draggable = new Lang.Class({
} }
this._dragInProgress = false; this._dragInProgress = false;
global.screen.set_cursor(Meta.Cursor.DEFAULT); global.unset_cursor();
this.emit('drag-end', event.get_time(), true); this.emit('drag-end', event.get_time(), true);
this._dragComplete(); this._dragComplete();
return true; return true;
@ -510,7 +518,7 @@ const _Draggable = new Lang.Class({
let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation(); let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
if (this._actorDestroyed) { if (this._actorDestroyed) {
global.screen.set_cursor(Meta.Cursor.DEFAULT); global.unset_cursor();
if (!this._buttonDown) if (!this._buttonDown)
this._dragComplete(); this._dragComplete();
this.emit('drag-end', eventTime, false); this.emit('drag-end', eventTime, false);
@ -558,14 +566,13 @@ const _Draggable = new Lang.Class({
_onAnimationComplete : function (dragActor, eventTime) { _onAnimationComplete : function (dragActor, eventTime) {
if (this._dragOrigParent) { if (this._dragOrigParent) {
Main.uiGroup.remove_child(this._dragActor); dragActor.reparent(this._dragOrigParent);
this._dragOrigParent.add_actor(this._dragActor);
dragActor.set_scale(this._dragOrigScale, this._dragOrigScale); dragActor.set_scale(this._dragOrigScale, this._dragOrigScale);
dragActor.set_position(this._dragOrigX, this._dragOrigY); dragActor.set_position(this._dragOrigX, this._dragOrigY);
} else { } else {
dragActor.destroy(); dragActor.destroy();
} }
global.screen.set_cursor(Meta.Cursor.DEFAULT); global.unset_cursor();
this.emit('drag-end', eventTime, false); this.emit('drag-end', eventTime, false);
this._animationInProgress = false; this._animationInProgress = false;
@ -573,16 +580,32 @@ const _Draggable = new Lang.Class({
this._dragComplete(); 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() { _dragComplete: function() {
if (!this._actorDestroyed) if (!this._actorDestroyed)
Shell.util_set_hidden_from_pick(this._dragActor, false); Shell.util_set_hidden_from_pick(this._dragActor, false);
this._ungrabEvents(); this._ungrabEvents();
global.sync_pointer();
if (this._updateHoverId) { if (this._firstLeaveActor) {
GLib.source_remove(this._updateHoverId); this._syncHover(this._firstLeaveActor);
this._updateHoverId = 0; this._firstLeaveActor = null;
}
if (this._lastEnterActor) {
this._syncHover(this._lastEnterActor);
this._lastEnterActor = null;
} }
this._dragActor = undefined; this._dragActor = undefined;

View File

@ -1,84 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Signals = imports.signals;
const Meta = imports.gi.Meta;
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const Main = imports.ui.main;
const EDGE_THRESHOLD = 20;
const DRAG_DISTANCE = 80;
const EdgeDragAction = new Lang.Class({
Name: 'EdgeDragAction',
Extends: Clutter.GestureAction,
_init : function(side, allowedModes) {
this.parent();
this._side = side;
this._allowedModes = allowedModes;
this.set_n_touch_points(1);
global.display.connect('grab-op-begin', Lang.bind(this, function() {
this.cancel();
}));
},
_getMonitorRect : function (x, y) {
let rect = new Meta.Rectangle({ x: x - 1, y: y - 1, width: 1, height: 1 });
let monitorIndex = global.screen.get_monitor_index_for_rect(rect);
return global.screen.get_monitor_geometry(monitorIndex);
},
vfunc_gesture_prepare : function(action, actor) {
if (this.get_n_current_points() == 0)
return false;
if (!(this._allowedModes & Main.actionMode))
return false;
let [x, y] = this.get_press_coords(0);
let monitorRect = this._getMonitorRect(x, y);
return ((this._side == St.Side.LEFT && x < monitorRect.x + EDGE_THRESHOLD) ||
(this._side == St.Side.RIGHT && x > monitorRect.x + monitorRect.width - EDGE_THRESHOLD) ||
(this._side == St.Side.TOP && y < monitorRect.y + EDGE_THRESHOLD) ||
(this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD));
},
vfunc_gesture_progress : function (action, actor) {
let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0);
let offsetX = Math.abs (x - startX);
let offsetY = Math.abs (y - startY);
if (offsetX < EDGE_THRESHOLD && offsetY < EDGE_THRESHOLD)
return true;
if ((offsetX > offsetY &&
(this._side == St.Side.TOP || this._side == St.Side.BOTTOM)) ||
(offsetY > offsetX &&
(this._side == St.Side.LEFT || this._side == St.Side.RIGHT))) {
this.cancel();
return false;
}
return true;
},
vfunc_gesture_end : function (action, actor) {
let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0);
let monitorRect = this._getMonitorRect(startX, startY);
if ((this._side == St.Side.TOP && y > monitorRect.y + DRAG_DISTANCE) ||
(this._side == St.Side.BOTTOM && y < monitorRect.y + monitorRect.height - DRAG_DISTANCE) ||
(this._side == St.Side.LEFT && x > monitorRect.x + DRAG_DISTANCE) ||
(this._side == St.Side.RIGHT && x < monitorRect.x + monitorRect.width - DRAG_DISTANCE))
this.emit('activated');
}
});
Signals.addSignalMethods(EdgeDragAction.prototype);

View File

@ -13,11 +13,14 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/ */
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Signals = imports.signals;
const AccountsService = imports.gi.AccountsService; const AccountsService = imports.gi.AccountsService;
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
@ -25,172 +28,97 @@ const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk; const Gtk = imports.gi.Gtk;
const Pango = imports.gi.Pango; const Pango = imports.gi.Pango;
const Polkit = imports.gi.Polkit;
const St = imports.gi.St; const St = imports.gi.St;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const CheckBox = imports.ui.checkBox;
const GnomeSession = imports.misc.gnomeSession; const GnomeSession = imports.misc.gnomeSession;
const LoginManager = imports.misc.loginManager; const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog; const ModalDialog = imports.ui.modalDialog;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget; const UserMenu = imports.ui.userMenu;
let _endSessionDialog = null; let _endSessionDialog = null;
const _ITEM_ICON_SIZE = 48; const _ITEM_ICON_SIZE = 48;
const _DIALOG_ICON_SIZE = 48; const _DIALOG_ICON_SIZE = 32;
const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2; const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
const EndSessionDialogIface = '<node> \ const EndSessionDialogIface = <interface name="org.gnome.SessionManager.EndSessionDialog">
<interface name="org.gnome.SessionManager.EndSessionDialog"> \ <method name="Open">
<method name="Open"> \ <arg type="u" direction="in" />
<arg type="u" direction="in" /> \ <arg type="u" direction="in" />
<arg type="u" direction="in" /> \ <arg type="u" direction="in" />
<arg type="u" direction="in" /> \ <arg type="ao" direction="in" />
<arg type="ao" direction="in" /> \ </method>
</method> \ <method name="Close" />
<method name="Close" /> \ <signal name="ConfirmedLogout" />
<signal name="ConfirmedLogout" /> \ <signal name="ConfirmedReboot" />
<signal name="ConfirmedReboot" /> \ <signal name="ConfirmedShutdown" />
<signal name="ConfirmedShutdown" /> \ <signal name="Canceled" />
<signal name="Canceled" /> \ <signal name="Closed" />
<signal name="Closed" /> \ </interface>;
</interface> \
</node>';
const logoutDialogContent = { const logoutDialogContent = {
subjectWithUser: C_("title", "Log Out %s"), subjectWithUser: C_("title", "Log Out %s"),
subject: C_("title", "Log Out"), subject: C_("title", "Log Out"),
descriptionWithUser: function(user, seconds) { inhibitedDescription: _("Click Log Out to quit these applications and log out of the system."),
uninhibitedDescriptionWithUser: function(user, seconds) {
return ngettext("%s will be logged out automatically in %d second.", return ngettext("%s will be logged out automatically in %d second.",
"%s will be logged out automatically in %d seconds.", "%s will be logged out automatically in %d seconds.",
seconds).format(user, seconds); seconds).format(user, seconds);
}, },
description: function(seconds) { uninhibitedDescription: function(seconds) {
return ngettext("You will be logged out automatically in %d second.", return ngettext("You will be logged out automatically in %d second.",
"You will be logged out automatically in %d seconds.", "You will be logged out automatically in %d seconds.",
seconds).format(seconds); seconds).format(seconds);
}, },
showBatteryWarning: false, endDescription: _("Logging out of the system."),
confirmButtons: [{ signal: 'ConfirmedLogout', confirmButtons: [{ signal: 'ConfirmedLogout',
label: C_("button", "Log Out") }], label: C_("button", "Log Out") }],
iconStyleClass: 'end-session-dialog-logout-icon', iconStyleClass: 'end-session-dialog-logout-icon'
showOtherSessions: false,
}; };
const shutdownDialogContent = { const shutdownDialogContent = {
subject: C_("title", "Power Off"), subject: C_("title", "Power Off"),
subjectWithUpdates: C_("title", "Install Updates & Power Off"), inhibitedDescription: _("Click Power Off to quit these applications and power off the system."),
description: function(seconds) { uninhibitedDescription: function(seconds) {
return ngettext("The system will power off automatically in %d second.", return ngettext("The system will power off automatically in %d second.",
"The system will power off automatically in %d seconds.", "The system will power off automatically in %d seconds.",
seconds).format(seconds); seconds).format(seconds);
}, },
checkBoxText: C_("checkbox", "Install pending software updates"), endDescription: _("Powering off the system."),
showBatteryWarning: true,
confirmButtons: [{ signal: 'ConfirmedReboot', confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart") }, label: C_("button", "Restart") },
{ signal: 'ConfirmedShutdown', { signal: 'ConfirmedShutdown',
label: C_("button", "Power Off") }], label: C_("button", "Power Off") }],
iconName: 'system-shutdown-symbolic', iconName: 'system-shutdown-symbolic',
iconStyleClass: 'end-session-dialog-shutdown-icon', iconStyleClass: 'end-session-dialog-shutdown-icon'
showOtherSessions: true,
}; };
const restartDialogContent = { const restartDialogContent = {
subject: C_("title", "Restart"), subject: C_("title", "Restart"),
description: function(seconds) { inhibitedDescription: _("Click Restart to quit these applications and restart the system."),
uninhibitedDescription: function(seconds) {
return ngettext("The system will restart automatically in %d second.", return ngettext("The system will restart automatically in %d second.",
"The system will restart automatically in %d seconds.", "The system will restart automatically in %d seconds.",
seconds).format(seconds); seconds).format(seconds);
}, },
showBatteryWarning: false, endDescription: _("Restarting the system."),
confirmButtons: [{ signal: 'ConfirmedReboot', confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart") }], label: C_("button", "Restart") }],
iconName: 'view-refresh-symbolic', iconName: 'view-refresh-symbolic',
iconStyleClass: 'end-session-dialog-shutdown-icon', iconStyleClass: 'end-session-dialog-shutdown-icon'
showOtherSessions: true,
};
const restartInstallDialogContent = {
subject: C_("title", "Restart & Install Updates"),
description: function(seconds) {
return ngettext("The system will automatically restart and install updates in %d second.",
"The system will automatically restart and install updates in %d seconds.",
seconds).format(seconds);
},
showBatteryWarning: true,
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart &amp; Install") }],
unusedFutureButtonForTranslation: C_("button", "Install &amp; Power Off"),
unusedFutureCheckBoxForTranslation: C_("checkbox", "Power off after updates are installed"),
iconName: 'view-refresh-symbolic',
iconStyleClass: 'end-session-dialog-shutdown-icon',
showOtherSessions: true,
};
const DialogType = {
LOGOUT: 0 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT */,
SHUTDOWN: 1 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN */,
RESTART: 2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */,
UPDATE_RESTART: 3
}; };
const DialogContent = { const DialogContent = {
0 /* DialogType.LOGOUT */: logoutDialogContent, 0 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT */: logoutDialogContent,
1 /* DialogType.SHUTDOWN */: shutdownDialogContent, 1 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN */: shutdownDialogContent,
2 /* DialogType.RESTART */: restartDialogContent, 2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */: restartDialogContent
3 /* DialogType.UPDATE_RESTART */: restartInstallDialogContent
}; };
const MAX_USERS_IN_SESSION_DIALOG = 5;
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);
const PkOfflineIface = '<node> \
<interface name="org.freedesktop.PackageKit.Offline"> \
<property name="UpdatePrepared" type="b" access="read"/> \
<property name="TriggerAction" type="s" access="read"/> \
<method name="Trigger"> \
<arg type="s" name="action" direction="in"/> \
</method> \
<method name="Cancel"/> \
</interface> \
</node>';
const PkOfflineProxy = Gio.DBusProxy.makeProxyWrapper(PkOfflineIface);
const UPowerIface = '<node> \
<interface name="org.freedesktop.UPower"> \
<property name="OnBattery" type="b" access="read"/> \
</interface> \
</node>';
const UPowerProxy = Gio.DBusProxy.makeProxyWrapper(UPowerIface);
function findAppFromInhibitor(inhibitor) { function findAppFromInhibitor(inhibitor) {
let desktopFile; let [desktopFile] = inhibitor.GetAppIdSync();
try {
[desktopFile] = inhibitor.GetAppIdSync();
} catch(e) {
// XXX -- sometimes JIT inhibitors generated by gnome-session
// get removed too soon. Don't fail in this case.
log('gnome-session gave us a dead inhibitor: %s'.format(inhibitor.get_object_path()));
return null;
}
if (!GLib.str_has_suffix(desktopFile, '.desktop')) if (!GLib.str_has_suffix(desktopFile, '.desktop'))
desktopFile += '.desktop'; desktopFile += '.desktop';
@ -198,6 +126,58 @@ function findAppFromInhibitor(inhibitor) {
return Shell.AppSystem.get_default().lookup_heuristic_basename(desktopFile); return Shell.AppSystem.get_default().lookup_heuristic_basename(desktopFile);
} }
const ListItem = new Lang.Class({
Name: 'ListItem',
_init: function(app, reason) {
this._app = app;
this._reason = reason;
if (this._reason == null)
this._reason = '';
let layout = new St.BoxLayout({ vertical: false});
this.actor = new St.Button({ style_class: 'end-session-dialog-app-list-item',
can_focus: true,
child: layout,
reactive: true,
x_align: St.Align.START,
x_fill: true });
this._icon = this._app.create_icon_texture(_ITEM_ICON_SIZE);
let iconBin = new St.Bin({ style_class: 'end-session-dialog-app-list-item-icon',
child: this._icon });
layout.add(iconBin);
let textLayout = new St.BoxLayout({ style_class: 'end-session-dialog-app-list-item-text-box',
vertical: true });
layout.add(textLayout);
this._nameLabel = new St.Label({ text: this._app.get_name(),
style_class: 'end-session-dialog-app-list-item-name' });
textLayout.add(this._nameLabel,
{ expand: false,
x_fill: true });
this._descriptionLabel = new St.Label({ text: this._reason,
style_class: 'end-session-dialog-app-list-item-description' });
this.actor.label_actor = this._nameLabel;
textLayout.add(this._descriptionLabel,
{ expand: true,
x_fill: true });
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
},
_onClicked: function() {
this.emit('activate');
this._app.activate();
}
});
Signals.addSignalMethods(ListItem.prototype);
// The logout timer only shows updates every 10 seconds // The logout timer only shows updates every 10 seconds
// until the last 10 seconds, then it shows updates every // until the last 10 seconds, then it shows updates every
// second. This function takes a given time and returns // second. This function takes a given time and returns
@ -233,18 +213,6 @@ function _setLabelText(label, text) {
} }
} }
function _setCheckBoxLabel(checkBox, text) {
let label = checkBox.getLabelActor();
if (text) {
label.set_text(text);
checkBox.actor.show();
} else {
label.set_text('');
checkBox.actor.hide();
}
}
function init() { function init() {
// This always returns the same singleton object // This always returns the same singleton object
// By instantiating it initially, we register the // By instantiating it initially, we register the
@ -260,42 +228,22 @@ const EndSessionDialog = new Lang.Class({
this.parent({ styleClass: 'end-session-dialog', this.parent({ styleClass: 'end-session-dialog',
destroyOnClose: false }); destroyOnClose: false });
this._loginManager = LoginManager.getLoginManager(); this._user = AccountsService.UserManager.get_default().get_user(GLib.get_user_name());
this._userManager = AccountsService.UserManager.get_default();
this._user = this._userManager.get_user(GLib.get_user_name());
this._pkOfflineProxy = new PkOfflineProxy(Gio.DBus.system,
'org.freedesktop.PackageKit',
'/org/freedesktop/PackageKit',
Lang.bind(this, function(proxy, error) {
if (error)
log(error.message);
}));
this._powerProxy = new UPowerProxy(Gio.DBus.system,
'org.freedesktop.UPower',
'/org/freedesktop/UPower',
Lang.bind(this, function(proxy, error) {
if (error) {
log(error.message);
return;
}
this._powerProxy.connect('g-properties-changed',
Lang.bind(this, this._sync));
this._sync();
}));
this._secondsLeft = 0; this._secondsLeft = 0;
this._totalSecondsToStayOpen = 0; this._totalSecondsToStayOpen = 0;
this._applications = []; this._inhibitors = [];
this._sessions = [];
this.connect('destroy', this.connect('destroy',
Lang.bind(this, this._onDestroy)); Lang.bind(this, this._onDestroy));
this.connect('opened', this.connect('opened',
Lang.bind(this, this._onOpened)); Lang.bind(this, this._onOpened));
this._userLoadedId = this._user.connect('notify::is_loaded', Lang.bind(this, this._sync)); this._userLoadedId = this._user.connect('notify::is_loaded',
this._userChangedId = this._user.connect('changed', Lang.bind(this, this._sync)); Lang.bind(this, this._updateContent));
this._userChangedId = this._user.connect('changed',
Lang.bind(this, this._updateContent));
let mainContentLayout = new St.BoxLayout({ vertical: false }); let mainContentLayout = new St.BoxLayout({ vertical: false });
this.contentLayout.add(mainContentLayout, this.contentLayout.add(mainContentLayout,
@ -309,17 +257,14 @@ const EndSessionDialog = new Lang.Class({
x_align: St.Align.END, x_align: St.Align.END,
y_align: St.Align.START }); y_align: St.Align.START });
let messageLayout = new St.BoxLayout({ vertical: true, let messageLayout = new St.BoxLayout({ vertical: true });
style_class: 'end-session-dialog-layout' });
mainContentLayout.add(messageLayout, mainContentLayout.add(messageLayout,
{ y_align: St.Align.START }); { y_align: St.Align.START });
this._subjectLabel = new St.Label({ style_class: 'end-session-dialog-subject' }); this._subjectLabel = new St.Label({ style_class: 'end-session-dialog-subject' });
messageLayout.add(this._subjectLabel, messageLayout.add(this._subjectLabel,
{ x_fill: false, { y_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START }); y_align: St.Align.START });
this._descriptionLabel = new St.Label({ style_class: 'end-session-dialog-description' }); this._descriptionLabel = new St.Label({ style_class: 'end-session-dialog-description' });
@ -330,46 +275,28 @@ const EndSessionDialog = new Lang.Class({
{ y_fill: true, { y_fill: true,
y_align: St.Align.START }); y_align: St.Align.START });
this._checkBox = new CheckBox.CheckBox(); let scrollView = new St.ScrollView({ style_class: 'end-session-dialog-app-list'});
this._checkBox.actor.connect('clicked', Lang.bind(this, this._sync)); scrollView.set_policy(Gtk.PolicyType.NEVER,
messageLayout.add(this._checkBox.actor); Gtk.PolicyType.AUTOMATIC);
this.contentLayout.add(scrollView,
this._batteryWarning = new St.Label({ style_class: 'end-session-dialog-warning',
text: _("Running on battery power: please plug in before installing updates.") });
this._batteryWarning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._batteryWarning.clutter_text.line_wrap = true;
messageLayout.add(this._batteryWarning);
this._scrollView = new St.ScrollView({ style_class: 'end-session-dialog-list' });
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this.contentLayout.add(this._scrollView,
{ x_fill: true, { x_fill: true,
y_fill: true }); y_fill: true });
this._scrollView.hide(); scrollView.hide();
this._inhibitorSection = new St.BoxLayout({ vertical: true, this._applicationList = new St.BoxLayout({ vertical: true });
style_class: 'end-session-dialog-inhibitor-layout' }); scrollView.add_actor(this._applicationList);
this._scrollView.add_actor(this._inhibitorSection);
this._applicationHeader = new St.Label({ style_class: 'end-session-dialog-list-header', this._applicationList.connect('actor-added',
text: _("Some applications are busy or have unsaved work.") }); Lang.bind(this, function() {
this._applicationList = new St.BoxLayout({ style_class: 'end-session-dialog-app-list', if (this._applicationList.get_n_children() == 1)
vertical: true }); scrollView.show();
this._inhibitorSection.add_actor(this._applicationHeader); }));
this._inhibitorSection.add_actor(this._applicationList);
this._sessionHeader = new St.Label({ style_class: 'end-session-dialog-list-header', this._applicationList.connect('actor-removed',
text: _("Other users are logged in.") }); Lang.bind(this, function() {
this._sessionList = new St.BoxLayout({ style_class: 'end-session-dialog-session-list', if (this._applicationList.get_n_children() == 0)
vertical: true }); scrollView.hide();
this._inhibitorSection.add_actor(this._sessionHeader); }));
this._inhibitorSection.add_actor(this._sessionList);
try {
this._updatesPermission = Polkit.Permission.new_sync("org.freedesktop.packagekit.trigger-offline-update", null, null);
} catch(e) {
log('No permission to trigger offline updates: %s'.format(e.toString()));
}
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(EndSessionDialogIface, this); this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(EndSessionDialogIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog'); this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
@ -380,51 +307,52 @@ const EndSessionDialog = new Lang.Class({
this._user.disconnect(this._userChangedId); this._user.disconnect(this._userChangedId);
}, },
_sync: function() { _updateDescription: function() {
let open = (this.state == ModalDialog.State.OPENING || this.state == ModalDialog.State.OPENED); if (this.state != ModalDialog.State.OPENING &&
if (!open) this.state != ModalDialog.State.OPENED)
return; return;
let dialogContent = DialogContent[this._type]; let dialogContent = DialogContent[this._type];
let subject = dialogContent.subject; let subject = dialogContent.subject;
// Use different title when we are installing updates
if (dialogContent.subjectWithUpdates && this._checkBox.actor.checked)
subject = dialogContent.subjectWithUpdates;
if (dialogContent.showBatteryWarning) {
// Warn when running on battery power
if (this._powerProxy.OnBattery && this._checkBox.actor.checked)
this._batteryWarning.opacity = 255;
else
this._batteryWarning.opacity = 0;
}
let description; let description;
let displayTime = _roundSecondsToInterval(this._totalSecondsToStayOpen,
this._secondsLeft,
10);
if (this._user.is_loaded) { if (this._inhibitors.length > 0) {
let realName = this._user.get_real_name(); this._stopTimer();
description = dialogContent.inhibitedDescription;
} else if (this._secondsLeft > 0 && this._inhibitors.length == 0) {
let displayTime = _roundSecondsToInterval(this._totalSecondsToStayOpen,
this._secondsLeft,
10);
if (realName != null) { if (this._user.is_loaded) {
if (dialogContent.subjectWithUser) let realName = this._user.get_real_name();
subject = dialogContent.subjectWithUser.format(realName);
if (dialogContent.descriptionWithUser) if (realName != null) {
description = dialogContent.descriptionWithUser(realName, displayTime); if (dialogContent.subjectWithUser)
else subject = dialogContent.subjectWithUser.format(realName);
description = dialogContent.description(displayTime);
if (dialogContent.uninhibitedDescriptionWithUser)
description = dialogContent.uninhibitedDescriptionWithUser(realName, displayTime);
else
description = dialogContent.uninhibitedDescription(displayTime);
}
} }
if (!description)
description = dialogContent.uninhibitedDescription(displayTime);
} else {
description = dialogContent.endDescription;
} }
if (!description)
description = dialogContent.description(displayTime);
_setLabelText(this._descriptionLabel, description);
_setLabelText(this._subjectLabel, subject); _setLabelText(this._subjectLabel, subject);
_setLabelText(this._descriptionLabel, description);
},
_updateContent: function() {
if (this.state != ModalDialog.State.OPENING &&
this.state != ModalDialog.State.OPENED)
return;
let dialogContent = DialogContent[this._type]; let dialogContent = DialogContent[this._type];
if (dialogContent.iconName) { if (dialogContent.iconName) {
@ -432,18 +360,14 @@ const EndSessionDialog = new Lang.Class({
icon_size: _DIALOG_ICON_SIZE, icon_size: _DIALOG_ICON_SIZE,
style_class: dialogContent.iconStyleClass }); style_class: dialogContent.iconStyleClass });
} else { } else {
let avatarWidget = new UserWidget.Avatar(this._user, let avatarWidget = new UserMenu.UserAvatarWidget(this._user,
{ iconSize: _DIALOG_ICON_SIZE, { iconSize: _DIALOG_ICON_SIZE,
styleClass: dialogContent.iconStyleClass }); styleClass: dialogContent.iconStyleClass });
this._iconBin.child = avatarWidget.actor; this._iconBin.child = avatarWidget.actor;
avatarWidget.update(); avatarWidget.update();
} }
let hasApplications = this._applications.length > 0; this._updateDescription();
let hasSessions = this._sessions.length > 0;
this._scrollView.visible = hasApplications || hasSessions;
this._applicationHeader.visible = hasApplications;
this._sessionHeader.visible = hasSessions;
}, },
_updateButtons: function() { _updateButtons: function() {
@ -483,71 +407,14 @@ const EndSessionDialog = new Lang.Class({
}, },
_confirm: function(signal) { _confirm: function(signal) {
let callback = Lang.bind(this, function() { this._fadeOutDialog();
this._fadeOutDialog(); this._stopTimer();
this._stopTimer(); this._dbusImpl.emit_signal(signal, null);
this._dbusImpl.emit_signal(signal, null);
});
// Offline update not available; just emit the signal
if (!this._checkBox.actor.visible) {
callback();
return;
}
// Trigger the offline update as requested
if (this._checkBox.actor.checked) {
switch (signal) {
case "ConfirmedReboot":
this._triggerOfflineUpdateReboot(callback);
break;
case "ConfirmedShutdown":
// To actually trigger the offline update, we need to
// reboot to do the upgrade. When the upgrade is complete,
// the computer will shut down automatically.
signal = "ConfirmedReboot";
this._triggerOfflineUpdateShutdown(callback);
break;
default:
callback();
break;
}
} else {
this._triggerOfflineUpdateCancel(callback);
}
}, },
_onOpened: function() { _onOpened: function() {
this._sync(); if (this._inhibitors.length == 0)
}, this._startTimer();
_triggerOfflineUpdateReboot: function(callback) {
this._pkOfflineProxy.TriggerRemote('reboot',
function (result, error) {
if (error)
log(error.message);
callback();
});
},
_triggerOfflineUpdateShutdown: function(callback) {
this._pkOfflineProxy.TriggerRemote('power-off',
function (result, error) {
if (error)
log(error.message);
callback();
});
},
_triggerOfflineUpdateCancel: function(callback) {
this._pkOfflineProxy.CancelRemote(function (result, error) {
if (error)
log(error.message);
callback();
});
}, },
_startTimer: function() { _startTimer: function() {
@ -561,22 +428,20 @@ const EndSessionDialog = new Lang.Class({
this._secondsLeft = this._totalSecondsToStayOpen - secondsElapsed; this._secondsLeft = this._totalSecondsToStayOpen - secondsElapsed;
if (this._secondsLeft > 0) { if (this._secondsLeft > 0) {
this._sync(); this._updateDescription();
return GLib.SOURCE_CONTINUE; return true;
} }
let dialogContent = DialogContent[this._type]; let dialogContent = DialogContent[this._type];
let button = dialogContent.confirmButtons[dialogContent.confirmButtons.length - 1]; let button = dialogContent.confirmButtons[dialogContent.confirmButtons.length - 1];
this._confirm(button.signal); this._confirm(button.signal);
this._timerId = 0;
return GLib.SOURCE_REMOVE; return false;
})); }));
GLib.Source.set_name_by_id(this._timerId, '[gnome-shell] this._confirm');
}, },
_stopTimer: function() { _stopTimer: function() {
if (this._timerId > 0) { if (this._timerId != 0) {
Mainloop.source_remove(this._timerId); Mainloop.source_remove(this._timerId);
this._timerId = 0; this._timerId = 0;
} }
@ -584,33 +449,8 @@ const EndSessionDialog = new Lang.Class({
this._secondsLeft = 0; this._secondsLeft = 0;
}, },
_constructListItemForApp: function(inhibitor, app) {
let actor = new St.BoxLayout({ style_class: 'end-session-dialog-app-list-item',
can_focus: true });
actor.add(app.create_icon_texture(_ITEM_ICON_SIZE));
let textLayout = new St.BoxLayout({ vertical: true,
y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
actor.add(textLayout);
let nameLabel = new St.Label({ text: app.get_name(),
style_class: 'end-session-dialog-app-list-item-name' });
textLayout.add(nameLabel);
actor.label_actor = nameLabel;
let [reason] = inhibitor.GetReasonSync();
if (reason) {
let reasonLabel = new St.Label({ text: reason,
style_class: 'end-session-dialog-app-list-item-description' });
textLayout.add(reasonLabel);
}
return actor;
},
_onInhibitorLoaded: function(inhibitor) { _onInhibitorLoaded: function(inhibitor) {
if (this._applications.indexOf(inhibitor) < 0) { if (this._inhibitors.indexOf(inhibitor) < 0) {
// Stale inhibitor // Stale inhibitor
return; return;
} }
@ -618,95 +458,28 @@ const EndSessionDialog = new Lang.Class({
let app = findAppFromInhibitor(inhibitor); let app = findAppFromInhibitor(inhibitor);
if (app) { if (app) {
let actor = this._constructListItemForApp(inhibitor, app); let [reason] = inhibitor.GetReasonSync();
this._applicationList.add(actor); let item = new ListItem(app, reason);
item.connect('activate',
Lang.bind(this, function() {
this.close();
}));
this._applicationList.add(item.actor, { x_fill: true });
this._stopTimer();
} else { } else {
// inhibiting app is a service, not an application // inhibiting app is a service, not an application
this._applications.splice(this._applications.indexOf(inhibitor), 1); this._inhibitors.splice(this._inhibitors.indexOf(inhibitor), 1);
} }
this._sync(); this._updateContent();
},
_constructListItemForSession: function(session) {
let avatar = new UserWidget.Avatar(session.user, { iconSize: _ITEM_ICON_SIZE });
avatar.update();
let userName = session.user.get_real_name() ? session.user.get_real_name() : session.username;
let userLabelText;
if (session.remote)
/* Translators: Remote here refers to a remote session, like a ssh login */
userLabelText = _("%s (remote)").format(userName);
else if (session.type == "tty")
/* Translators: Console here refers to a tty like a VT console */
userLabelText = _("%s (console)").format(userName);
else
userLabelText = userName;
let actor = new St.BoxLayout({ style_class: 'end-session-dialog-session-list-item',
can_focus: true });
actor.add(avatar.actor);
let nameLabel = new St.Label({ text: userLabelText,
style_class: 'end-session-dialog-session-list-item-name',
y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
actor.add(nameLabel);
actor.label_actor = nameLabel;
return actor;
},
_loadSessions: function() {
this._loginManager.listSessions(Lang.bind(this, function(result) {
let n = 0;
for (let i = 0; i < result.length; i++) {
let[id, uid, userName, seat, sessionPath] = result[i];
let proxy = new LogindSession(Gio.DBus.system, 'org.freedesktop.login1', sessionPath);
if (proxy.Class != 'user')
continue;
if (proxy.State == 'closing')
continue;
if (proxy.Id == GLib.getenv('XDG_SESSION_ID'))
continue;
let session = { user: this._userManager.get_user(userName),
username: userName,
type: proxy.Type,
remote: proxy.Remote };
this._sessions.push(session);
let actor = this._constructListItemForSession(session);
this._sessionList.add(actor);
// limit the number of entries
n++;
if (n == MAX_USERS_IN_SESSION_DIALOG)
break;
}
this._sync();
}));
}, },
OpenAsync: function(parameters, invocation) { OpenAsync: function(parameters, invocation) {
let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters; let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters;
this._totalSecondsToStayOpen = totalSecondsToStayOpen; this._totalSecondsToStayOpen = totalSecondsToStayOpen;
this._type = type; this._inhibitors = [];
if (this._type == DialogType.RESTART &&
this._pkOfflineProxy.TriggerAction == 'reboot')
this._type = DialogType.UPDATE_RESTART;
this._applications = [];
this._applicationList.destroy_all_children(); this._applicationList.destroy_all_children();
this._type = type;
this._sessions = [];
this._sessionList.destroy_all_children();
if (!(this._type in DialogContent)) { if (!(this._type in DialogContent)) {
invocation.return_dbus_error('org.gnome.Shell.ModalDialog.TypeError', invocation.return_dbus_error('org.gnome.Shell.ModalDialog.TypeError',
@ -714,33 +487,14 @@ const EndSessionDialog = new Lang.Class({
return; return;
} }
let dialogContent = DialogContent[this._type];
for (let i = 0; i < inhibitorObjectPaths.length; i++) { for (let i = 0; i < inhibitorObjectPaths.length; i++) {
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], Lang.bind(this, function(proxy, error) { let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], Lang.bind(this, function(proxy, error) {
this._onInhibitorLoaded(proxy); this._onInhibitorLoaded(proxy);
})); }));
this._applications.push(inhibitor); this._inhibitors.push(inhibitor);
} }
if (dialogContent.showOtherSessions)
this._loadSessions();
let updateAlreadyTriggered = this._pkOfflineProxy.TriggerAction == 'power-off' || this._pkOfflineProxy.TriggerAction == 'reboot';
let updatePrepared = this._pkOfflineProxy.UpdatePrepared;
let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed;
_setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText);
this._checkBox.actor.visible = (dialogContent.checkBoxText && updatePrepared && updatesAllowed);
this._checkBox.actor.checked = (updatePrepared && updateAlreadyTriggered);
// We show the warning either together with the checkbox, or when
// updates have already been triggered, but the user doesn't have
// enough permissions to cancel them.
this._batteryWarning.visible = (dialogContent.showBatteryWarning &&
(this._checkBox.actor.visible || updatePrepared && updateAlreadyTriggered && !updatesAllowed));
this._updateButtons(); this._updateButtons();
if (!this.open(timestamp)) { if (!this.open(timestamp)) {
@ -749,8 +503,7 @@ const EndSessionDialog = new Lang.Class({
return; return;
} }
this._startTimer(); this._updateContent();
this._sync();
let signalId = this.connect('opened', let signalId = this.connect('opened',
Lang.bind(this, function() { Lang.bind(this, function() {

View File

@ -5,14 +5,11 @@ imports.gi.versions.Gio = '2.0';
imports.gi.versions.Gdk = '3.0'; imports.gi.versions.Gdk = '3.0';
imports.gi.versions.GdkPixbuf = '2.0'; imports.gi.versions.GdkPixbuf = '2.0';
imports.gi.versions.Gtk = '3.0'; imports.gi.versions.Gtk = '3.0';
imports.gi.versions.TelepathyGLib = '0.12';
imports.gi.versions.TelepathyLogger = '0.2';
const Clutter = imports.gi.Clutter;; const Clutter = imports.gi.Clutter;;
const Gettext = imports.gettext; const Gettext = imports.gettext;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk; const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const St = imports.gi.St; const St = imports.gi.St;
@ -42,25 +39,6 @@ function _patchContainerClass(containerClass) {
}; };
} }
function _patchLayoutClass(layoutClass, styleProps) {
if (styleProps)
layoutClass.prototype.hookup_style = function(container) {
container.connect('style-changed', Lang.bind(this, function() {
let node = container.get_theme_node();
for (let prop in styleProps) {
let [found, length] = node.lookup_length(styleProps[prop], false);
if (found)
this[prop] = length;
}
}));
};
layoutClass.prototype.child_set = function(actor, props) {
let meta = this.get_child_meta(actor.get_parent(), actor);
for (let prop in props)
meta[prop] = props[prop];
};
}
function _makeLoggingFunc(func) { function _makeLoggingFunc(func) {
return function() { return function() {
return func([].join.call(arguments, ', ')); return func([].join.call(arguments, ', '));
@ -77,18 +55,11 @@ function init() {
window._ = Gettext.gettext; window._ = Gettext.gettext;
window.C_ = Gettext.pgettext; window.C_ = Gettext.pgettext;
window.ngettext = Gettext.ngettext; window.ngettext = Gettext.ngettext;
window.N_ = function(s) { return s; };
// Miscellaneous monkeypatching // Miscellaneous monkeypatching
_patchContainerClass(St.BoxLayout); _patchContainerClass(St.BoxLayout);
_patchContainerClass(St.Table); _patchContainerClass(St.Table);
_patchLayoutClass(Clutter.TableLayout, { row_spacing: 'spacing-rows',
column_spacing: 'spacing-columns' });
_patchLayoutClass(Clutter.GridLayout, { row_spacing: 'spacing-rows',
column_spacing: 'spacing-columns' });
_patchLayoutClass(Clutter.BoxLayout, { spacing: 'spacing' });
Clutter.Actor.prototype.toString = function() { Clutter.Actor.prototype.toString = function() {
return St.describe_actor(this); return St.describe_actor(this);
}; };

Some files were not shown because too many files have changed in this diff Show More