Compare commits
	
		
			2 Commits
		
	
	
		
			3.22.1
			...
			wip/loc-ap
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 11db28b216 | ||
|   | 614f37b116 | 
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -16,6 +16,7 @@ config.log | ||||
| config.status | ||||
| config | ||||
| configure | ||||
| data/50-gnome-shell-*.xml | ||||
| data/org.gnome.Shell.desktop | ||||
| data/org.gnome.Shell.desktop.in | ||||
| data/gnome-shell-extension-prefs.desktop | ||||
| @@ -25,6 +26,8 @@ data/gschemas.compiled | ||||
| data/perf-background.xml | ||||
| data/org.gnome.shell.gschema.xml | ||||
| data/org.gnome.shell.gschema.valid | ||||
| data/org.gnome.shell.evolution.calendar.gschema.xml | ||||
| data/org.gnome.shell.evolution.calendar.gschema.valid | ||||
| data/org.gnome.Shell.PortalHelper.desktop | ||||
| data/org.gnome.Shell.PortalHelper.service | ||||
| data/theme/.sass-cache | ||||
| @@ -71,6 +74,7 @@ src/*-marshal.[ch] | ||||
| src/Makefile | ||||
| src/Makefile.in | ||||
| src/calendar-server/evolution-calendar.desktop | ||||
| src/calendar-server/evolution-calendar.desktop.in | ||||
| src/calendar-server/org.gnome.Shell.CalendarServer.service | ||||
| src/gnome-shell | ||||
| src/gnome-shell-calendar-server | ||||
|   | ||||
							
								
								
									
										218
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										218
									
								
								NEWS
									
									
									
									
									
								
							| @@ -1,221 +1,3 @@ | ||||
| 3.22.1 | ||||
| ====== | ||||
| * Fix hidden network indicator on startup [Florian; #772249] | ||||
| * Fix order of windows with modal dialogs in window switcher [Florian; #747153] | ||||
| * Fix feedback loop between StClipboard and X11 bridge [Carlos; #760745] | ||||
| * Reliably match windows from Flatpak apps [Florian; #772615] | ||||
| * Misc. bug fixes [Philip; #742249] | ||||
|  | ||||
| Contributors: | ||||
|   Philip Chimento, Carlos Garnacho, Florian Müllner | ||||
|  | ||||
| Translations: | ||||
|   Inaki Larranaga Murgoitio [eu], Khaled Hosny [ar], BM [uz@cyrillic], | ||||
|   Milo Casagrande [it], Cheng-Chia Tseng [zh_TW], gogo [hr] | ||||
|  | ||||
| 3.22.0 | ||||
| ====== | ||||
| * Misc. bug fixes [Florian, Rui; #771391, #771536] #771656] | ||||
|  | ||||
| Contributors: | ||||
|   Rui Matos, Florian Müllner | ||||
|  | ||||
| Translations: | ||||
|   Ask Hjorth Larsen [da], GNOME Translation Robot [gd], Alexandre Franke [fr], | ||||
|   Daniel Korostil [uk], Jordi Mas [ca], Khaled Hosny [ar], David King [en_GB] | ||||
|  | ||||
| 3.21.92 | ||||
| ======= | ||||
| * Adjust screen capture to work with multiple stage views [Jonas; #770128] | ||||
| * Improve handling of cycle shortcuts [Florian; #771063] | ||||
| * Fix windows not getting undimmed in some cases [Rui; #770163, #752524] | ||||
| * Disable extension version check by default [Florian; #770887] | ||||
| * Misc. bug fixes [Rui, Florian, Michael; #770382, #770888, #770328] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Michael Catanzaro, Fran Dieguez, Olivier Fourdan, Rui Matos, | ||||
|   Florian Müllner | ||||
|  | ||||
| Translations: | ||||
|   Changwoo Ryu [ko], Baurzhan Muftakhidinov [kk], Aurimas Černius [lt], | ||||
|   Muhammet Kara [tr], Trần Ngọc Quân [vi], A S Alam [pa], Yosef Or Boczko [he], | ||||
|   Anders Jonsson [sv], Tiago Santos [pt], Hannie Dumoleyn [nl], | ||||
|   Rūdolfs Mazurs [lv], Claude Paroz [fr], Arash Mousavi [fa], | ||||
|   Fran Dieguez [gl], Stas Solovey [ru], Tom Tryfonidis [el] | ||||
|  | ||||
| 3.21.91 | ||||
| ======= | ||||
| Translations: | ||||
|   Mario Blättermann [de], Jiri Grönroos [fi], Dušan Kazik [sk], | ||||
|   Andika Triwidada [id], Daniel Mustieles [es], Fabio Tomat [fur], | ||||
|   Enrico Nicoletto [pt_BR], Matej Urbančič [sl], Мирослав Николић [sr, sr@latin] | ||||
|  | ||||
| 3.21.90.1 | ||||
| ========= | ||||
| Contributors: | ||||
|   Piotr Drąg | ||||
|  | ||||
| Translations: | ||||
|   Marek Černocký [cs], Balázs Úr [hu] | ||||
|  | ||||
| 3.21.90 | ||||
| ======= | ||||
| * Improve on-screen keyboard on wayland [Carlos; #765009] | ||||
| * Misc. bug fixes [Florian; #769156, #769216, #769074] | ||||
|  | ||||
| Contributors: | ||||
|   Carlos Garnacho, Florian Müllner | ||||
|  | ||||
| Translations: | ||||
|   Fabio Tomat [fur], Tiago Santos [pt], Daniel Mustieles [es], | ||||
|   Bernd Homuth [de], Aurimas Černius [lt], Balázs Úr [hu], | ||||
|   Yosef Or Boczko [he], Jiri Grönroos [fi], Marek Cernocky [cs], | ||||
|   Muhammet Kara [tr], Enrico Nicoletto [pt_BR], Andika Triwidada [id] | ||||
|  | ||||
| 3.21.4 | ||||
| ====== | ||||
| * overview: Fix switching workspaces when scrolling on non-primary monitors | ||||
|   [Florian; #766883, #768316] | ||||
| * Fix crash when using screen recorder under wayland [Rui; #767001] | ||||
| * Update theme on video memory purge errors [Rui; #739178] | ||||
| * Free old backgrounds immediately [Hyungwon; #766353] | ||||
| * Add support for system upgrades to end session dialog [Kalev; #763611] | ||||
| * Fix maximized windows flickering to the wrong size on restart [Owen; #761566] | ||||
| * Hide ignored events in calendar as well [Florian; #768538] | ||||
| * calendar: Only hide dismissed occurrence of recurring event [Florian; #748226] | ||||
| * Provide org.freedesktop.impl.portal.access implementation [Florian; #768669] | ||||
| * Misc. bug fixes and cleanups [Rui, Florian, Marinus, Jonas; #767954, #768317, | ||||
|   #746867, #762206, #768956, #768979] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Piotr Drąg, Hyungwon Hwang, Kalev Lember, Rui Matos, | ||||
|   Florian Müllner, Marinus Schraal, Owen W. Taylor | ||||
|  | ||||
| Translations: | ||||
|   Andika Triwidada [id], Daniel Mustieles [es], Bruce Cowan [en_GB], | ||||
|   Dušan Kazik [sk], Piotr Drąg [pl], Chao-Hsiung Liao [zh_HK] | ||||
|  | ||||
| 3.21.3 | ||||
| ====== | ||||
|  * Do not disable suspend action when locked [Florian; #725960] | ||||
|  * Remember input sources MRU list [Cosimo; #766826] | ||||
|  * networkAgent: Handle VPN service aliases [David; #658484] | ||||
|  * Plug a memory leak [Hans; #710230] | ||||
|  | ||||
| Contributors: | ||||
|   Cosimo Cecchi, Florian Müllner, Hans Petter Jansson, David Woodhouse | ||||
|  | ||||
| Translations: | ||||
|   Tiago Santos [pt], Cédric Valmary [oc], Muhammet Kara [tr], | ||||
|   Daniel Mustieles [es], Rafael Fontenelle [pt_BR] | ||||
|  | ||||
| 3.21.2 | ||||
| ====== | ||||
| * Fix sorting of hidden apps in app switcher [Florian; #766238] | ||||
| * Set logind's LockedHint property when locked [Victor; #764773] | ||||
| * Allocate framebuffers early to fix a crash on NVIDIA [Martin; #764898] | ||||
| * Fix cycle-windows/cycle-group keybindings [Florian; #730739] | ||||
| * Switch to shared desktop schema for calendar settings [Iain; #766318] | ||||
| * Misc. bug fixes [Florian, Cosimo, Michele; #766325, #758471, #757556, | ||||
|   #757019, #766598] | ||||
|  | ||||
| Contributors: | ||||
|   Cosimo Cecchi, Michele Gaio, Iain Lane, Florian Müllner, Martin Szulecki, | ||||
|   Victor Toso | ||||
|  | ||||
| Translations: | ||||
|   Tiago Santos [pt], Kjartan Maraas [nb], Jiro Matsuzawa [ja], | ||||
|   Cédric Valmary [oc], Sveinn í Felli [is] | ||||
|  | ||||
| 3.21.1 | ||||
| ====== | ||||
| * Save screencasts in HOME if XDG_VIDEO_DIR doesn't exist [Florian; #765015] | ||||
| * Don't show orientation lock when g-s-d won't rotate [Florian; #765267] | ||||
| * Misc. bug fixes [Heiher, Florian, Marek, Rui; #722752, #765061, #763068, | ||||
|   #765607, #757676, #760439] | ||||
|  | ||||
| Contributors: | ||||
|   Heiher, Marek Chalupa, Rui Matos, Florian Müllner | ||||
|  | ||||
| Translations: | ||||
|   Arash Mousavi [fa], Kristjan SCHMIDT [eo], GNOME Translation Robot [gd] | ||||
|  | ||||
| 3.20.1 | ||||
| ====== | ||||
| * Plug a memory leak [Aaron; #735705] | ||||
|  | ||||
| Contributors: | ||||
|   Aaron Plattner | ||||
|  | ||||
| Translations: | ||||
|   Daniel Korostil [uk], Matej Urbančič [sl], Inaki Larranaga Murgoitio [eu], | ||||
|   Cheng-Chia Tseng [zh_TW], Fabio Tomat [fur], Trần Ngọc Quân [vi], | ||||
|   YunQiang Su [zh_CN], Marek Černocký [cs], Arash Mousavi [fa], | ||||
|   Alexander Shopov [bg], Khaled Hosny [ar] | ||||
|  | ||||
| 3.20.0 | ||||
| ====== | ||||
|  | ||||
| Translations: | ||||
|   Changwoo Ryu [ko], Baurzhan Muftakhidinov [kk], Milo Casagrande [it], | ||||
|   Anders Jonsson [sv], Muhammet Kara [tr], Alexandre Franke [fr], | ||||
|   Rūdolfs Mazurs [lv], Ask Hjorth Larsen [da], Jiro Matsuzawa [ja] | ||||
|  | ||||
| 3.19.92 | ||||
| ======= | ||||
| * Update location dialog according to latest mockups [Zeeshan; #762480] | ||||
| * Fix deleting chat notifications in calendar [Florian; #747991] | ||||
|  | ||||
| Contributors: | ||||
|   Zeeshan Ali (Khattak), Florian Müllner | ||||
|  | ||||
| Translations: | ||||
|   Rūdolfs Mazurs [lv], Changwoo Ryu [ko], Matej Urbančič [sl], | ||||
|   Justin van Steijn [nl], Fabio Tomat [fur], Kris Thomsen [da], | ||||
|   Marek Černocký [cs], Piotr Drąg [pl], Dušan Kazik [sk], | ||||
|   Мирослав Николић [sr, sr@latin], Balázs Úr [hu], Yosef Or Boczko [he], | ||||
|   Daniel Mustieles [es], Fran Dieguez [gl], Bernd Homuth [de], | ||||
|   Tom Tryfonidis [el], Jiri Grönroos [fi], Gil Forcada [ca], | ||||
|   Artur Morais [pt_BR], Aurimas Černius [lt], Stas Solovey [ru] | ||||
|  | ||||
| 3.19.91 | ||||
| ======= | ||||
| * location: Ask user only once [Zeeshan; #762559] | ||||
| * Fix jiggling when auto-hiding legacy tray [Florian; #747957] | ||||
| * Misc. bug fixes [Florian, Michael, Ting-Wei; #762475, #762507, #755659] | ||||
|  | ||||
| Contributors: | ||||
|   Zeeshan Ali (Khattak), Michael Catanzaro, Ting-Wei Lan, Florian Müllner | ||||
|  | ||||
| Translations: | ||||
|   Мирослав Николић [sr, sr@latin], Piotr Drąg [pl], A S Alam [pa], | ||||
|   Artur de Aquino Morais [pt_BR], Daniel Mustieles [es], | ||||
|   Chao-Hsiung Liao [zh_TW], Daniel Korostil [uk], Fran Dieguez [gl], | ||||
|   Tom Tryfonidis [el], Bernd Homuth [de], Sebastian Rasmussen [sv], | ||||
|   Jordi Mas [ca], Piotr Drąg [ga], Cédric Valmary [oc], Gábor Kelemen [hu], | ||||
|   Baurzhan Muftakhidinov [kk], Friedel Wolff [af], Marek Černocký [cs], | ||||
|   Mingye Wang (Arthur2e5) [zh_CN], Aron Xu [zh_CN], Khaled Hosny [ar], | ||||
|   Aurimas Černius [lt], Stas Solovey [ru], Yosef Or Boczko [he] | ||||
|  | ||||
| 3.19.90 | ||||
| ======= | ||||
| * Correctly identify VPN secret requests [Lubomir; #760999] | ||||
| * Improve week number presentation [Jakub; #683245] | ||||
| * Add audio device selection dialog [Florian; #760284] | ||||
| * Add media controls to the time and date drop down [Florian; #756491] | ||||
| * Fix IBus candidate popup position under wayland [Rui; #753476] | ||||
| * Ask user to grant applications access to location [Zeeshan; #762119] | ||||
| * Misc. bug fixes [Mario, Jakub, Florian; #761208, #761772, #762270] | ||||
|  | ||||
| Contributors: | ||||
|   Zeeshan Ali (Khattak), Michael Catanzaro, Rui Matos, Florian Müllner, | ||||
|   Lubomir Rintel, Mario Sanchez Prada, Jakub Steiner | ||||
|  | ||||
| Translations: | ||||
|   Alexander Shopov [bg], Balázs Meskó [hu], Fabio Tomat [fur], | ||||
|   Dušan Kazik [sk], Piotr Drąg [pl], Alexandre Franke [fr], | ||||
|   Mario Blättermann [de], Milo Casagrande [it], Jordi Mas [ca] | ||||
|  | ||||
| 3.19.4 | ||||
| ====== | ||||
| * gdm: Do not allow bypassing disabled Sign In button [Michael; #746180] | ||||
|   | ||||
							
								
								
									
										24
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								configure.ac
									
									
									
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| AC_PREREQ(2.63) | ||||
| AC_INIT([gnome-shell],[3.22.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell]) | ||||
| AC_INIT([gnome-shell],[3.19.4],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell]) | ||||
| AX_IS_RELEASE([git-directory]) | ||||
|  | ||||
| AC_CONFIG_HEADERS([config.h]) | ||||
| @@ -24,14 +24,13 @@ LT_PREREQ([2.2.6]) | ||||
| LT_INIT([disable-static]) | ||||
|  | ||||
| # i18n | ||||
| IT_PROG_INTLTOOL([0.40]) | ||||
|  | ||||
| GETTEXT_PACKAGE=gnome-shell | ||||
| AC_SUBST(GETTEXT_PACKAGE) | ||||
| AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", | ||||
|                    [The prefix for our gettext translation domains.]) | ||||
|  | ||||
| AM_GNU_GETTEXT_VERSION([0.19.6]) | ||||
| AM_GNU_GETTEXT([external]) | ||||
|  | ||||
| PKG_PROG_PKG_CONFIG([0.22]) | ||||
|  | ||||
| AC_PATH_PROG([XSLTPROC], [xsltproc]) | ||||
| @@ -53,7 +52,7 @@ if $PKG_CONFIG --exists gstreamer-1.0 '>=' $GSTREAMER_MIN_VERSION ; then | ||||
|    AC_MSG_RESULT(yes) | ||||
|    build_recorder=true | ||||
|    recorder_modules="gstreamer-1.0 gstreamer-base-1.0 x11 gtk+-3.0" | ||||
|    PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules mutter-clutter-1.0) | ||||
|    PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0) | ||||
| else | ||||
|    AC_MSG_RESULT(no) | ||||
| fi | ||||
| @@ -76,9 +75,9 @@ AS_IF([test x$enable_systemd != xno], [ | ||||
| AC_MSG_RESULT($enable_systemd) | ||||
|  | ||||
| CLUTTER_MIN_VERSION=1.21.5 | ||||
| GOBJECT_INTROSPECTION_MIN_VERSION=1.49.1 | ||||
| GOBJECT_INTROSPECTION_MIN_VERSION=1.45.4 | ||||
| GJS_MIN_VERSION=1.39.0 | ||||
| MUTTER_MIN_VERSION=3.22.1 | ||||
| MUTTER_MIN_VERSION=3.19.4 | ||||
| GTK_MIN_VERSION=3.15.0 | ||||
| GIO_MIN_VERSION=2.45.3 | ||||
| LIBECAL_MIN_VERSION=3.5.3 | ||||
| @@ -99,8 +98,8 @@ SHARED_PCS="gio-unix-2.0 >= $GIO_MIN_VERSION | ||||
|             gjs-internals-1.0 >= $GJS_MIN_VERSION | ||||
|             $recorder_modules | ||||
|             gdk-x11-3.0 libsoup-2.4 | ||||
|             mutter-clutter-1.0 >= $CLUTTER_MIN_VERSION | ||||
|             mutter-cogl-pango-1.0 | ||||
|             clutter-x11-1.0 >= $CLUTTER_MIN_VERSION | ||||
|             clutter-glx-1.0 >= $CLUTTER_MIN_VERSION | ||||
|             libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_MIN_VERSION | ||||
|             gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION | ||||
|             libcanberra libcanberra-gtk3 | ||||
| @@ -115,12 +114,12 @@ 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(ST, mutter-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_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0) | ||||
| PKG_CHECK_MODULES(TRAY, mutter-clutter-1.0 gtk+-3.0) | ||||
| PKG_CHECK_MODULES(TRAY, clutter-1.0 gtk+-3.0) | ||||
| PKG_CHECK_MODULES(GVC, libpulse >= $PULSE_MIN_VERS libpulse-mainloop-glib gobject-2.0) | ||||
| PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.21.3) | ||||
| PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.19.2) | ||||
|  | ||||
| AC_ARG_ENABLE(browser-plugin, | ||||
|               [AS_HELP_STRING([--enable-browser-plugin], | ||||
| @@ -255,6 +254,7 @@ AC_CONFIG_FILES([ | ||||
|   docs/reference/st/Makefile | ||||
|   docs/reference/st/st-docs.sgml | ||||
|   js/Makefile | ||||
|   src/calendar-server/evolution-calendar.desktop.in | ||||
|   src/Makefile | ||||
|   src/gvc/Makefile | ||||
|   browser-plugin/Makefile | ||||
|   | ||||
| @@ -1,24 +1,24 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" ?> | ||||
| <KeyListEntries schema="org.gnome.shell.keybindings" | ||||
|                 group="system" | ||||
|                 name="System" | ||||
|                 _name="System" | ||||
|                 wm_name="GNOME Shell" | ||||
|                 package="gnome-shell"> | ||||
| 
 | ||||
| 	<KeyListEntry name="toggle-message-tray" | ||||
|                       description="Show the notification list"/> | ||||
|                       _description="Show the notification list"/> | ||||
| 
 | ||||
| 	<KeyListEntry name="focus-active-notification" | ||||
|                       description="Focus the active notification"/> | ||||
|                       _description="Focus the active notification"/> | ||||
| 
 | ||||
| 	<KeyListEntry name="toggle-overview" | ||||
|                       description="Show the overview"/> | ||||
|                       _description="Show the overview"/> | ||||
| 
 | ||||
| 	<KeyListEntry name="toggle-application-view" | ||||
|                       description="Show all applications"/> | ||||
|                       _description="Show all applications"/> | ||||
| 
 | ||||
| 	<KeyListEntry name="open-application-menu" | ||||
|                       description="Open the application menu"/> | ||||
|                       _description="Open the application menu"/> | ||||
| 
 | ||||
| </KeyListEntries> | ||||
| 
 | ||||
| @@ -7,16 +7,12 @@ desktop_DATA = org.gnome.Shell.desktop gnome-shell-extension-prefs.desktop | ||||
| if HAVE_NETWORKMANAGER | ||||
| desktop_DATA += org.gnome.Shell.PortalHelper.desktop | ||||
|  | ||||
| portaldir = $(datadir)/xdg-desktop-portal/portals | ||||
| portal_DATA = gnome-shell.portal | ||||
|  | ||||
| servicedir = $(datadir)/dbus-1/services | ||||
| service_DATA = org.gnome.Shell.PortalHelper.service | ||||
|  | ||||
| CLEANFILES += \ | ||||
| 	org.gnome.Shell.PortalHelper.service 	\ | ||||
| 	org.gnome.Shell.PortalHelper.desktop 	\ | ||||
| 	org.gnome.Shell.PortalHelper.desktop.in \ | ||||
| 	org.gnome.Shell.PortalHelper.service \ | ||||
| 	org.gnome.Shell.PortalHelper.desktop \ | ||||
| 	$(NULL) | ||||
|  | ||||
| endif | ||||
| @@ -32,9 +28,7 @@ endif | ||||
| 	    -e "s|@VERSION[@]|$(VERSION)|" \ | ||||
| 	    $< > $@ || rm $@ | ||||
|  | ||||
| %.desktop:%.desktop.in | ||||
| 	$(AM_V_GEN) $(MSGFMT) --desktop --template $(builddir)/$< \ | ||||
| 	                      -d $(top_srcdir)/po -o $@ | ||||
| @INTLTOOL_DESKTOP_RULE@ | ||||
|  | ||||
| introspectiondir = $(datadir)/dbus-1/interfaces | ||||
| introspection_DATA =				\ | ||||
| @@ -86,11 +80,14 @@ perf-background.xml: perf-background.xml.in | ||||
| 	    $< > $@ || rm $@ | ||||
|  | ||||
| keysdir = @GNOME_KEYBINDINGS_KEYSDIR@ | ||||
| keys_DATA = 50-gnome-shell-system.xml | ||||
| keys_in_files = 50-gnome-shell-system.xml.in | ||||
| keys_DATA = $(keys_in_files:.xml.in=.xml) | ||||
|  | ||||
| gsettings_SCHEMAS = org.gnome.shell.gschema.xml | ||||
|  | ||||
| %.gschema.xml: %.gschema.xml.in Makefile | ||||
| @INTLTOOL_XML_NOMERGE_RULE@ | ||||
|  | ||||
| %.gschema.xml.in: %.gschema.xml.in.in Makefile | ||||
| 	$(AM_V_GEN) sed -e 's|@GETTEXT_PACKAGE[@]|$(GETTEXT_PACKAGE)|g' \ | ||||
| 	$< > $@ || rm $@ | ||||
|  | ||||
| @@ -109,16 +106,15 @@ convert_DATA = gnome-shell-overrides.convert | ||||
| EXTRA_DIST =						\ | ||||
| 	org.gnome.Shell.desktop.in.in			\ | ||||
| 	gnome-shell-extension-prefs.desktop.in.in	\ | ||||
| 	$(portal_DATA)					\ | ||||
| 	$(introspection_DATA)				\ | ||||
| 	$(menu_DATA)					\ | ||||
| 	$(convert_DATA)					\ | ||||
| 	$(keys_DATA)					\ | ||||
| 	$(keys_in_files)				\ | ||||
| 	$(dist_theme_files)				\ | ||||
| 	perf-background.xml.in				\ | ||||
| 	org.gnome.Shell.PortalHelper.desktop.in.in	\ | ||||
| 	org.gnome.Shell.PortalHelper.desktop.in		\ | ||||
| 	org.gnome.Shell.PortalHelper.service.in		\ | ||||
| 	org.gnome.shell.gschema.xml.in			\ | ||||
| 	org.gnome.shell.gschema.xml.in.in		\ | ||||
| 	gnome-shell-theme.gresource.xml 		\ | ||||
| 	$(resource_files)				\ | ||||
| 	$(NULL) | ||||
| @@ -127,9 +123,11 @@ CLEANFILES +=						\ | ||||
| 	org.gnome.Shell.desktop.in			\ | ||||
| 	gnome-shell-extension-prefs.in			\ | ||||
| 	$(desktop_DATA)					\ | ||||
| 	$(keys_DATA)					\ | ||||
| 	$(gsettings_SCHEMAS)				\ | ||||
| 	perf-background.xml				\ | ||||
| 	gschemas.compiled				\ | ||||
| 	org.gnome.shell.gschema.valid			\ | ||||
| 	org.gnome.shell.gschema.xml.in			\ | ||||
| 	gnome-shell-theme.gresource			\ | ||||
| 	$(NULL) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| [Desktop Entry] | ||||
| Type=Application | ||||
| Name=GNOME Shell Extension Preferences | ||||
| Comment=Configure GNOME Shell Extensions | ||||
| _Name=GNOME Shell Extension Preferences | ||||
| _Comment=Configure GNOME Shell Extensions | ||||
| Exec=@bindir@/gnome-shell-extension-prefs %u | ||||
| X-GNOME-Bugzilla-Bugzilla=GNOME | ||||
| X-GNOME-Bugzilla-Product=gnome-shell | ||||
|   | ||||
| @@ -1,4 +0,0 @@ | ||||
| [portal] | ||||
| DBusName=org.freedesktop.impl.portal.desktop.gnome | ||||
| Interfaces=org.freedesktop.impl.portal.Access | ||||
| UseIn=gnome | ||||
| @@ -1,10 +1,9 @@ | ||||
| [Desktop Entry] | ||||
| Name=Network Login | ||||
| _Name=Network Login | ||||
| Type=Application | ||||
| Exec=gapplication launch org.gnome.Shell.PortalHelper | ||||
| DBusActivatable=true | ||||
| NoDisplay=true | ||||
| # Translators: Do NOT translate or transliterate this text (this is an icon file name)! | ||||
| Icon=network-workgroup | ||||
| StartupNotify=true | ||||
| OnlyShowIn=GNOME; | ||||
| @@ -1,7 +1,7 @@ | ||||
| [Desktop Entry] | ||||
| Type=Application | ||||
| Name=GNOME Shell | ||||
| Comment=Window management and application launching | ||||
| _Name=GNOME Shell | ||||
| _Comment=Window management and application launching | ||||
| Exec=@bindir@/gnome-shell | ||||
| X-GNOME-Bugzilla-Bugzilla=GNOME | ||||
| X-GNOME-Bugzilla-Product=gnome-shell | ||||
|   | ||||
| @@ -3,131 +3,143 @@ | ||||
|           gettext-domain="@GETTEXT_PACKAGE@"> | ||||
|     <key name="development-tools" type="b"> | ||||
|       <default>true</default> | ||||
|       <summary> | ||||
|       <_summary> | ||||
|         Enable internal tools useful for developers and testers from Alt-F2 | ||||
|       </summary> | ||||
|       <description> | ||||
|       </_summary> | ||||
|       <_description> | ||||
|         Allows access to internal debugging and monitoring tools | ||||
|         using the Alt-F2 dialog. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="enabled-extensions" type="as"> | ||||
|       <default>[]</default> | ||||
|       <summary>UUIDs of extensions to enable</summary> | ||||
|       <description> | ||||
|       <_summary>UUIDs of extensions to enable</_summary> | ||||
|       <_description> | ||||
|         GNOME Shell extensions have a UUID property; this key lists extensions | ||||
|         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 | ||||
|         EnableExtension and DisableExtension D-Bus methods on org.gnome.Shell. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="disable-extension-version-validation" type="b"> | ||||
|       <default>true</default> | ||||
|       <summary>Disables the validation of extension version compatibility</summary> | ||||
|       <description> | ||||
|       <default>false</default> | ||||
|       <_summary>Disables the validation of extension version compatibility</_summary> | ||||
|       <_description> | ||||
|         GNOME Shell will only load extensions that claim to support the current | ||||
|         running version. Enabling this option will disable this check and try to | ||||
|         load all extensions regardless of the versions they claim to support. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="favorite-apps" type="as"> | ||||
|       <default>[ 'epiphany.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ]</default> | ||||
|       <summary>List of desktop file IDs for favorite applications</summary> | ||||
|       <description> | ||||
|       <_summary>List of desktop file IDs for favorite applications</_summary> | ||||
|       <_description> | ||||
|         The applications corresponding to these identifiers | ||||
|         will be displayed in the favorites area. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="app-picker-view" type="u"> | ||||
|       <default>0</default> | ||||
|       <summary>App Picker View</summary> | ||||
|       <description> | ||||
|       <_summary>App Picker View</_summary> | ||||
|       <_description> | ||||
|         Index of the currently selected view in the application picker. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="command-history" type="as"> | ||||
|       <default>[]</default> | ||||
|       <summary>History for command (Alt-F2) dialog</summary> | ||||
|       <_summary>History for command (Alt-F2) dialog</_summary> | ||||
|     </key> | ||||
|     <key name="looking-glass-history" type="as"> | ||||
|       <default>[]</default> | ||||
|       <!-- Translators: looking glass is a debugger and inspector tool, see https://wiki.gnome.org/Projects/GnomeShell/LookingGlass --> | ||||
|       <summary>History for the looking glass dialog</summary> | ||||
|       <!-- Translators: looking glass is a debugger and inspector tool, see https://live.gnome.org/GnomeShell/LookingGlass --> | ||||
|       <_summary>History for the looking glass dialog</_summary> | ||||
|     </key> | ||||
|     <key name="always-show-log-out" type="b"> | ||||
|       <default>false</default> | ||||
|       <summary>Always show the 'Log out' menu item in the user menu.</summary> | ||||
|       <description> | ||||
|       <_summary>Always show the 'Log out' menu item in the user menu.</_summary> | ||||
|       <_description> | ||||
|         This key overrides the automatic hiding of the 'Log out' | ||||
|         menu item in single-user, single-session situations. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="remember-mount-password" type="b"> | ||||
|       <default>false</default> | ||||
|       <summary>Whether to remember password for mounting encrypted or remote filesystems</summary> | ||||
|       <description> | ||||
|       <_summary>Whether to remember password for mounting encrypted or remote filesystems</_summary> | ||||
|       <_description> | ||||
|         The shell will request a password when an encrypted device or a | ||||
|         remote filesystem is mounted.  If the password can be saved for | ||||
|         future use a 'Remember Password' checkbox will be present. | ||||
|         This key sets the default state of the checkbox. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="had-bluetooth-devices-setup" type="b"> | ||||
|       <default>false</default> | ||||
|       <summary>Whether the default Bluetooth adapter had set up devices associated to it</summary> | ||||
|       <description> | ||||
|       <_summary>Whether the default Bluetooth adapter had set up devices associated to it</_summary> | ||||
|       <_description> | ||||
|         The shell will only show a Bluetooth menu item if a Bluetooth | ||||
|         adapter is powered, or if there were devices set up associated | ||||
|         with the default adapter. This will be reset if the default | ||||
|         adapter is ever seen not to have devices associated to it. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <child name="calendar" schema="org.gnome.shell.calendar"/> | ||||
|     <child name="keybindings" schema="org.gnome.shell.keybindings"/> | ||||
|     <child name="keyboard" schema="org.gnome.shell.keyboard"/> | ||||
|   </schema> | ||||
| 
 | ||||
|   <schema id="org.gnome.shell.calendar" path="/org/gnome/shell/calendar/" | ||||
|           gettext-domain="@GETTEXT_PACKAGE@"> | ||||
|     <key name="show-weekdate" type="b"> | ||||
|       <default>false</default> | ||||
|       <_summary>Show the week date in the calendar</_summary> | ||||
|       <_description> | ||||
|         If true, display the ISO week date in the calendar. | ||||
|       </_description> | ||||
|       </key> | ||||
|   </schema> | ||||
| 
 | ||||
|   <schema id="org.gnome.shell.keybindings" path="/org/gnome/shell/keybindings/" | ||||
|           gettext-domain="@GETTEXT_PACKAGE@"> | ||||
|     <key name="open-application-menu" type="as"> | ||||
|       <default>["<Super>F10"]</default> | ||||
|       <summary>Keybinding to open the application menu</summary> | ||||
|       <description> | ||||
|       <_summary>Keybinding to open the application menu</_summary> | ||||
|       <_description> | ||||
|         Keybinding to open the application menu. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="toggle-application-view" type="as"> | ||||
|       <default>["<Super>a"]</default> | ||||
|       <summary>Keybinding to open the "Show Applications" view</summary> | ||||
|       <description> | ||||
|       <_summary>Keybinding to open the "Show Applications" view</_summary> | ||||
|       <_description> | ||||
|         Keybinding to open the "Show Applications" view of the Activities | ||||
|         Overview. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="toggle-overview" type="as"> | ||||
|       <default>["<Super>s"]</default> | ||||
|       <summary>Keybinding to open the overview</summary> | ||||
|       <description> | ||||
|       <_summary>Keybinding to open the overview</_summary> | ||||
|       <_description> | ||||
|         Keybinding to open the Activities Overview. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="toggle-message-tray" type="as"> | ||||
|       <default>["<Super>v","<Super>m"]</default> | ||||
|       <summary>Keybinding to toggle the visibility of the notification list</summary> | ||||
|       <description> | ||||
|       <_summary>Keybinding to toggle the visibility of the notification list</_summary> | ||||
|       <_description> | ||||
|         Keybinding to toggle the visibility of the notification list. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="focus-active-notification" type="as"> | ||||
|       <default>["<Super>n"]</default> | ||||
|       <summary>Keybinding to focus the active notification</summary> | ||||
|       <description> | ||||
|       <_summary>Keybinding to focus the active notification</_summary> | ||||
|       <_description> | ||||
|         Keybinding to focus the active notification. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="pause-resume-tweens" type="as"> | ||||
|       <default>[]</default> | ||||
|       <summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</summary> | ||||
|       <description></description> | ||||
|       <_summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</_summary> | ||||
|       <_description></_description> | ||||
|     </key> | ||||
|   </schema> | ||||
| 
 | ||||
| @@ -135,10 +147,10 @@ | ||||
|           gettext-domain="@GETTEXT_PACKAGE@"> | ||||
|     <key name="keyboard-type" type="s"> | ||||
|       <default>'touch'</default> | ||||
|       <summary>Which keyboard to use</summary> | ||||
|       <description> | ||||
|       <_summary>Which keyboard to use</_summary> | ||||
|       <_description> | ||||
|         The type of keyboard to use. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|   </schema> | ||||
| 
 | ||||
| @@ -147,11 +159,11 @@ | ||||
|           gettext-domain="@GETTEXT_PACKAGE@"> | ||||
|     <key type="b" name="current-workspace-only"> | ||||
|       <default>false</default> | ||||
|       <summary>Limit switcher to current workspace.</summary> | ||||
|       <description> | ||||
|       <_summary>Limit switcher to current workspace.</_summary> | ||||
|       <_description> | ||||
| 	If true, only applications that have windows on the current workspace are shown in the switcher. | ||||
| 	Otherwise, all applications are included. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|   </schema> | ||||
| 
 | ||||
| @@ -165,20 +177,20 @@ | ||||
|           gettext-domain="@GETTEXT_PACKAGE@"> | ||||
|     <key name="app-icon-mode" enum="org.gnome.shell.window-switcher.AppIconMode"> | ||||
|       <default>'both'</default> | ||||
|       <summary>The application icon mode.</summary> | ||||
|       <description> | ||||
|       <_summary>The application icon mode.</_summary> | ||||
|       <_description> | ||||
| 	Configures how the windows are shown in the switcher. Valid possibilities | ||||
| 	are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-only' | ||||
| 	(shows only the application icon) or 'both'. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key type="b" name="current-workspace-only"> | ||||
|       <default>true</default> | ||||
|       <summary>Limit switcher to current workspace.</summary> | ||||
|       <description> | ||||
|       <_summary>Limit switcher to current workspace.</_summary> | ||||
|       <_description> | ||||
| 	If true, only windows from the current workspace are shown in the switcher. | ||||
| 	Otherwise, all windows are included. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|   </schema> | ||||
| 
 | ||||
| @@ -186,43 +198,43 @@ | ||||
| 	  gettext-domain="@GETTEXT_PACKAGE@"> | ||||
|     <key name="attach-modal-dialogs" type="b"> | ||||
|       <default>true</default> | ||||
|       <summary>Attach modal dialog to the parent window</summary> | ||||
|       <description> | ||||
|       <_summary>Attach modal dialog to the parent window</_summary> | ||||
|       <_description> | ||||
|         This key overrides the key in org.gnome.mutter when running | ||||
|         GNOME Shell. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
| 
 | ||||
|     <key name="edge-tiling" type="b"> | ||||
|       <default>true</default> | ||||
|       <summary>Enable edge tiling when dropping windows on screen edges</summary> | ||||
|       <description> | ||||
|       <_summary>Enable edge tiling when dropping windows on screen edges</_summary> | ||||
|       <_description> | ||||
|         This key overrides the key in org.gnome.mutter when running GNOME Shell. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
| 
 | ||||
|     <key name="dynamic-workspaces" type="b"> | ||||
|       <default>true</default> | ||||
|       <summary>Workspaces are managed dynamically</summary> | ||||
|       <description> | ||||
|       <_summary>Workspaces are managed dynamically</_summary> | ||||
|       <_description> | ||||
|         This key overrides the key in org.gnome.mutter when running GNOME Shell. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
| 
 | ||||
|     <key name="workspaces-only-on-primary" type="b"> | ||||
|       <default>true</default> | ||||
|       <summary>Workspaces only on primary monitor</summary> | ||||
|       <description> | ||||
|       <_summary>Workspaces only on primary monitor</_summary> | ||||
|       <_description> | ||||
|         This key overrides the key in org.gnome.mutter when running GNOME Shell. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
| 
 | ||||
|     <key name="focus-change-on-pointer-rest" type="b"> | ||||
|       <default>true</default> | ||||
|       <summary>Delay focus changes in mouse mode until the pointer stops moving</summary> | ||||
|       <description> | ||||
|       <_summary>Delay focus changes in mouse mode until the pointer stops moving</_summary> | ||||
|       <_description> | ||||
|         This key overrides the key in org.gnome.mutter when running GNOME Shell. | ||||
|       </description> | ||||
|       </_description> | ||||
|     </key> | ||||
|   </schema> | ||||
| </schemalist> | ||||
| @@ -399,77 +399,6 @@ StScrollBar { | ||||
|   width: 48px; | ||||
|   height: 48px; } | ||||
|  | ||||
| /* Audio selection dialog */ | ||||
| .audio-device-selection-dialog { | ||||
|   spacing: 30px; } | ||||
|  | ||||
| .audio-selection-content { | ||||
|   spacing: 20px; | ||||
|   padding: 24px; } | ||||
|  | ||||
| .audio-selection-title { | ||||
|   font-weight: bold; | ||||
|   text-align: center; } | ||||
|  | ||||
| .audio-selection-box { | ||||
|   spacing: 20px; } | ||||
|  | ||||
| .audio-selection-device { | ||||
|   border: 1px solid rgba(238, 238, 236, 0.2); | ||||
|   border-radius: 12px; } | ||||
|   .audio-selection-device:active, .audio-selection-device:hover, .audio-selection-device:focus { | ||||
|     background-color: #215d9c; } | ||||
|  | ||||
| .audio-selection-device-box { | ||||
|   padding: 20px; | ||||
|   spacing: 20px; } | ||||
|  | ||||
| .audio-selection-device-icon { | ||||
|   icon-size: 64px; } | ||||
|  | ||||
| /* Access Dialog */ | ||||
| .access-dialog { | ||||
|   spacing: 30px; } | ||||
|  | ||||
| .access-dialog-main-layout { | ||||
|   padding: 12px 20px 0; | ||||
|   spacing: 12px; } | ||||
|  | ||||
| .access-dialog-content { | ||||
|   max-width: 28em; | ||||
|   spacing: 20px; } | ||||
|  | ||||
| .access-dialog-icon { | ||||
|   min-width: 48px; | ||||
|   icon-size: 48px; } | ||||
|  | ||||
| .access-dialog-title { | ||||
|   font-weight: bold; } | ||||
|  | ||||
| .access-dialog-subtitle { | ||||
|   color: #999999; | ||||
|   font-weight: bold; } | ||||
|  | ||||
| /* Geolocation Dialog */ | ||||
| .geolocation-dialog { | ||||
|   spacing: 30px; } | ||||
|  | ||||
| .geolocation-dialog-main-layout { | ||||
|   spacing: 12px; } | ||||
|  | ||||
| .geolocation-dialog-content { | ||||
|   spacing: 20px; } | ||||
|  | ||||
| .geolocation-dialog-icon { | ||||
|   icon-size: 48px; } | ||||
|  | ||||
| .geolocation-dialog-title { | ||||
|   font-weight: bold; } | ||||
|  | ||||
| .geolocation-dialog-reason { | ||||
|   color: #999999; | ||||
|   font-weight: bold; } | ||||
|  | ||||
| /* Network Agent Dialog */ | ||||
| .network-dialog-secret-table { | ||||
|   spacing-rows: 15px; | ||||
| @@ -558,9 +487,6 @@ StScrollBar { | ||||
|     border-radius: 0.3em; | ||||
|     background-color: rgba(11, 12, 13, 0.5); | ||||
|     color: #eeeeec; } | ||||
|   .osd-window .level-bar { | ||||
|     background-color: #eeeeec; | ||||
|     border-radius: 0.3em; } | ||||
|  | ||||
| /* App Switcher */ | ||||
| .switcher-popup { | ||||
| @@ -604,10 +530,6 @@ StScrollBar { | ||||
|   width: 96px; | ||||
|   height: 96px; } | ||||
|  | ||||
| /* Window Cycler */ | ||||
| .cycler-highlight { | ||||
|   border: 5px solid #215d9c; } | ||||
|  | ||||
| /* Workspace Switcher */ | ||||
| .workspace-switcher-group { | ||||
|   padding: 12px; } | ||||
| @@ -796,7 +718,7 @@ StScrollBar { | ||||
|   border-radius: 1.4em; } | ||||
|   .calendar-day-base:hover, .calendar-day-base:focus { | ||||
|     background-color: #0d0d0d; } | ||||
|   .calendar-day-base:active, .calendar-day-base:selected { | ||||
|   .calendar-day-base:active { | ||||
|     color: white; | ||||
|     background-color: #215d9c; | ||||
|     border-color: transparent; } | ||||
| @@ -833,12 +755,12 @@ StScrollBar { | ||||
| .calendar-week-number { | ||||
|   font-size: 70%; | ||||
|   font-weight: bold; | ||||
|   width: 2.3em; | ||||
|   height: 1.8em; | ||||
|   border-radius: 2px; | ||||
|   padding: 0.5em 0 0; | ||||
|   margin: 6px; | ||||
|   background-color: rgba(255, 255, 255, 0.3); | ||||
|   width: 2.8em; | ||||
|   height: 2em; | ||||
|   border-radius: 2px 1em 2px 2px; | ||||
|   padding: 0.9em 0 0; | ||||
|   margin: 3px; | ||||
|   background-color: rgba(255, 255, 255, 0.1); | ||||
|   color: #000; } | ||||
|  | ||||
| /* Message list */ | ||||
| @@ -899,23 +821,6 @@ StScrollBar { | ||||
|   padding: 8px; | ||||
|   font-size: .9em; } | ||||
|  | ||||
| .message-media-control { | ||||
|   padding: 6px; } | ||||
|   .message-media-control:last-child:ltr { | ||||
|     padding-right: 18px; } | ||||
|   .message-media-control:last-child:rtl { | ||||
|     padding-left: 18px; } | ||||
|  | ||||
| .media-message-cover-icon { | ||||
|   icon-size: 32px; } | ||||
|   .media-message-cover-icon.fallback { | ||||
|     color: #1a1a1a; | ||||
|     background-color: #000; | ||||
|     border: 2px solid #000; | ||||
|     border-radius: 2px; | ||||
|     icon-size: 16px; | ||||
|     padding: 8px; } | ||||
|  | ||||
| .system-switch-user-submenu-icon.user-icon { | ||||
|   icon-size: 20px; | ||||
|   padding: 0 2px; } | ||||
|   | ||||
 Submodule data/theme/gnome-shell-sass updated: b2190083c2...1d35c2890a
									
								
							| @@ -399,77 +399,6 @@ StScrollBar { | ||||
|   width: 48px; | ||||
|   height: 48px; } | ||||
|  | ||||
| /* Audio selection dialog */ | ||||
| .audio-device-selection-dialog { | ||||
|   spacing: 30px; } | ||||
|  | ||||
| .audio-selection-content { | ||||
|   spacing: 20px; | ||||
|   padding: 24px; } | ||||
|  | ||||
| .audio-selection-title { | ||||
|   font-weight: bold; | ||||
|   text-align: center; } | ||||
|  | ||||
| .audio-selection-box { | ||||
|   spacing: 20px; } | ||||
|  | ||||
| .audio-selection-device { | ||||
|   border: 1px solid rgba(238, 238, 236, 0.2); | ||||
|   border-radius: 12px; } | ||||
|   .audio-selection-device:active, .audio-selection-device:hover, .audio-selection-device:focus { | ||||
|     background-color: #215d9c; } | ||||
|  | ||||
| .audio-selection-device-box { | ||||
|   padding: 20px; | ||||
|   spacing: 20px; } | ||||
|  | ||||
| .audio-selection-device-icon { | ||||
|   icon-size: 64px; } | ||||
|  | ||||
| /* Access Dialog */ | ||||
| .access-dialog { | ||||
|   spacing: 30px; } | ||||
|  | ||||
| .access-dialog-main-layout { | ||||
|   padding: 12px 20px 0; | ||||
|   spacing: 12px; } | ||||
|  | ||||
| .access-dialog-content { | ||||
|   max-width: 28em; | ||||
|   spacing: 20px; } | ||||
|  | ||||
| .access-dialog-icon { | ||||
|   min-width: 48px; | ||||
|   icon-size: 48px; } | ||||
|  | ||||
| .access-dialog-title { | ||||
|   font-weight: bold; } | ||||
|  | ||||
| .access-dialog-subtitle { | ||||
|   color: #8e8e80; | ||||
|   font-weight: bold; } | ||||
|  | ||||
| /* Geolocation Dialog */ | ||||
| .geolocation-dialog { | ||||
|   spacing: 30px; } | ||||
|  | ||||
| .geolocation-dialog-main-layout { | ||||
|   spacing: 12px; } | ||||
|  | ||||
| .geolocation-dialog-content { | ||||
|   spacing: 20px; } | ||||
|  | ||||
| .geolocation-dialog-icon { | ||||
|   icon-size: 48px; } | ||||
|  | ||||
| .geolocation-dialog-title { | ||||
|   font-weight: bold; } | ||||
|  | ||||
| .geolocation-dialog-reason { | ||||
|   color: #8e8e80; | ||||
|   font-weight: bold; } | ||||
|  | ||||
| /* Network Agent Dialog */ | ||||
| .network-dialog-secret-table { | ||||
|   spacing-rows: 15px; | ||||
| @@ -558,9 +487,6 @@ StScrollBar { | ||||
|     border-radius: 0.3em; | ||||
|     background-color: rgba(11, 12, 13, 0.5); | ||||
|     color: #eeeeec; } | ||||
|   .osd-window .level-bar { | ||||
|     background-color: #eeeeec; | ||||
|     border-radius: 0.3em; } | ||||
|  | ||||
| /* App Switcher */ | ||||
| .switcher-popup { | ||||
| @@ -604,10 +530,6 @@ StScrollBar { | ||||
|   width: 96px; | ||||
|   height: 96px; } | ||||
|  | ||||
| /* Window Cycler */ | ||||
| .cycler-highlight { | ||||
|   border: 5px solid #215d9c; } | ||||
|  | ||||
| /* Workspace Switcher */ | ||||
| .workspace-switcher-group { | ||||
|   padding: 12px; } | ||||
| @@ -796,7 +718,7 @@ StScrollBar { | ||||
|   border-radius: 1.4em; } | ||||
|   .calendar-day-base:hover, .calendar-day-base:focus { | ||||
|     background-color: #454c4c; } | ||||
|   .calendar-day-base:active, .calendar-day-base:selected { | ||||
|   .calendar-day-base:active { | ||||
|     color: white; | ||||
|     background-color: #215d9c; | ||||
|     border-color: transparent; } | ||||
| @@ -833,12 +755,12 @@ StScrollBar { | ||||
| .calendar-week-number { | ||||
|   font-size: 70%; | ||||
|   font-weight: bold; | ||||
|   width: 2.3em; | ||||
|   height: 1.8em; | ||||
|   border-radius: 2px; | ||||
|   padding: 0.5em 0 0; | ||||
|   margin: 6px; | ||||
|   background-color: rgba(238, 238, 236, 0.3); | ||||
|   width: 2.8em; | ||||
|   height: 2em; | ||||
|   border-radius: 2px 1em 2px 2px; | ||||
|   padding: 0.9em 0 0; | ||||
|   margin: 3px; | ||||
|   background-color: rgba(238, 238, 236, 0.1); | ||||
|   color: #393f3f; } | ||||
|  | ||||
| /* Message list */ | ||||
| @@ -899,23 +821,6 @@ StScrollBar { | ||||
|   padding: 8px; | ||||
|   font-size: .9em; } | ||||
|  | ||||
| .message-media-control { | ||||
|   padding: 6px; } | ||||
|   .message-media-control:last-child:ltr { | ||||
|     padding-right: 18px; } | ||||
|   .message-media-control:last-child:rtl { | ||||
|     padding-left: 18px; } | ||||
|  | ||||
| .media-message-cover-icon { | ||||
|   icon-size: 32px; } | ||||
|   .media-message-cover-icon.fallback { | ||||
|     color: #515a5a; | ||||
|     background-color: #393f3f; | ||||
|     border: 2px solid #393f3f; | ||||
|     border-radius: 2px; | ||||
|     icon-size: 16px; | ||||
|     padding: 8px; } | ||||
|  | ||||
| .system-switch-user-submenu-icon.user-icon { | ||||
|   icon-size: 20px; | ||||
|   padding: 0 2px; } | ||||
|   | ||||
| @@ -113,7 +113,7 @@ expand_content_files= | ||||
| # e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) | ||||
| # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) | ||||
| 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 -rpath $(MUTTER_TYPELIB_DIR) | ||||
| 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 | ||||
|  | ||||
| # This includes the standard gtk-doc make rules, copied by gtkdocize. | ||||
| include $(top_srcdir)/gtk-doc.make | ||||
|   | ||||
| @@ -78,7 +78,7 @@ expand_content_files= | ||||
| # e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) | ||||
| # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) | ||||
| GTKDOC_CFLAGS= | ||||
| GTKDOC_LIBS=$(top_builddir)/src/libst-1.0.la -rpath $(MUTTER_TYPELIB_DIR) | ||||
| GTKDOC_LIBS=$(top_builddir)/src/libst-1.0.la | ||||
|  | ||||
| # This includes the standard gtk-doc make rules, copied by gtkdocize. | ||||
| include $(top_srcdir)/gtk-doc.make | ||||
|   | ||||
| @@ -23,6 +23,11 @@ const GnomeShellIface = '<node> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const customCss = '.prefs-button { \ | ||||
|                        padding: 8px; \ | ||||
|                        border-radius: 20px; \ | ||||
|                    }'; | ||||
|  | ||||
| const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface); | ||||
|  | ||||
| function stripPrefix(string, prefix) { | ||||
| @@ -152,7 +157,6 @@ const Application = new Lang.Class({ | ||||
|         let scroll = new Gtk.ScrolledWindow({ hscrollbar_policy: Gtk.PolicyType.NEVER, | ||||
|                                               shadow_type: Gtk.ShadowType.IN, | ||||
|                                               halign: Gtk.Align.CENTER, | ||||
|                                               propagate_natural_width: true, | ||||
|                                               margin: 18 }); | ||||
|         this._window.add(scroll); | ||||
|  | ||||
| @@ -172,6 +176,21 @@ const Application = new Lang.Class({ | ||||
|         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; | ||||
| @@ -220,6 +239,7 @@ const Application = new Lang.Class({ | ||||
|  | ||||
|     _onStartup: function(app) { | ||||
|         this._buildUI(app); | ||||
|         this._addCustomStyle(); | ||||
|         this._scanExtensions(); | ||||
|     }, | ||||
|  | ||||
| @@ -296,7 +316,7 @@ const ExtensionRow = new Lang.Class({ | ||||
|         button.add(new Gtk.Image({ icon_name: 'emblem-system-symbolic', | ||||
|                                    icon_size: Gtk.IconSize.BUTTON, | ||||
|                                    visible: true })); | ||||
|         button.get_style_context().add_class('circular'); | ||||
|         button.get_style_context().add_class('prefs-button'); | ||||
|         hbox.add(button); | ||||
|  | ||||
|         this.prefsButton = button; | ||||
|   | ||||
| @@ -804,11 +804,6 @@ const LoginDialog = new Lang.Class({ | ||||
|  | ||||
|         this._user = null; | ||||
|  | ||||
|         if (this._nextSignalId) { | ||||
|             this._authPrompt.disconnect(this._nextSignalId); | ||||
|             this._nextSignalId = 0; | ||||
|         } | ||||
|  | ||||
|         if (beginRequest == AuthPrompt.BeginRequestType.PROVIDE_USERNAME) { | ||||
|             if (!this._disableUserList) | ||||
|                 this._showUserList(); | ||||
|   | ||||
| @@ -31,12 +31,10 @@ | ||||
|  | ||||
|     <file>portalHelper/main.js</file> | ||||
|  | ||||
|     <file>ui/accessDialog.js</file> | ||||
|     <file>ui/altTab.js</file> | ||||
|     <file>ui/animation.js</file> | ||||
|     <file>ui/appDisplay.js</file> | ||||
|     <file>ui/appFavorites.js</file> | ||||
|     <file>ui/audioDeviceSelection.js</file> | ||||
|     <file>ui/backgroundMenu.js</file> | ||||
|     <file>ui/background.js</file> | ||||
|     <file>ui/boxpointer.js</file> | ||||
| @@ -64,9 +62,7 @@ | ||||
|     <file>ui/magnifierDBus.js</file> | ||||
|     <file>ui/main.js</file> | ||||
|     <file>ui/messageTray.js</file> | ||||
|     <file>ui/messageList.js</file> | ||||
|     <file>ui/modalDialog.js</file> | ||||
|     <file>ui/mpris.js</file> | ||||
|     <file>ui/notificationDaemon.js</file> | ||||
|     <file>ui/osdWindow.js</file> | ||||
|     <file>ui/osdMonitorLabeler.js</file> | ||||
|   | ||||
| @@ -40,9 +40,6 @@ const SystemdLoginSessionIface = '<node> \ | ||||
| <signal name="Lock" /> \ | ||||
| <signal name="Unlock" /> \ | ||||
| <property name="Active" type="b" access="read" /> \ | ||||
| <method name="SetLockedHint"> \ | ||||
|     <arg type="b" direction="in"/> \ | ||||
| </method> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| @@ -134,13 +131,10 @@ const LoginManagerSystemd = new Lang.Class({ | ||||
|  | ||||
|     canSuspend: function(asyncCallback) { | ||||
|         this._proxy.CanSuspendRemote(function(result, error) { | ||||
|             if (error) { | ||||
|                 asyncCallback(false, false); | ||||
|             } else { | ||||
|                 let needsAuth = result[0] == 'challenge'; | ||||
|                 let canSuspend = needsAuth || result[0] == 'yes'; | ||||
|                 asyncCallback(canSuspend, needsAuth); | ||||
|             } | ||||
|             if (error) | ||||
|                 asyncCallback(false); | ||||
|             else | ||||
|                 asyncCallback(result[0] != 'no' && result[0] != 'na'); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
| @@ -193,7 +187,7 @@ const LoginManagerDummy = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     canSuspend: function(asyncCallback) { | ||||
|         asyncCallback(false, false); | ||||
|         asyncCallback(false); | ||||
|     }, | ||||
|  | ||||
|     listSessions: function(asyncCallback) { | ||||
|   | ||||
| @@ -1,202 +0,0 @@ | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Gio = imports.gi.Gio; | ||||
| const GLib = imports.gi.GLib; | ||||
| const Lang = imports.lang; | ||||
| const Pango = imports.gi.Pango; | ||||
| const Shell = imports.gi.Shell; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const CheckBox = imports.ui.checkBox; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
|  | ||||
| const RequestIface = '<node> \ | ||||
| <interface name="org.freedesktop.impl.portal.Request"> \ | ||||
| <method name="Close"/> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const AccessIface = '<node> \ | ||||
| <interface name="org.freedesktop.impl.portal.Access"> \ | ||||
| <method name="AccessDialog"> \ | ||||
|   <arg type="o" name="handle" direction="in"/> \ | ||||
|   <arg type="s" name="app_id" direction="in"/> \ | ||||
|   <arg type="s" name="parent_window" direction="in"/> \ | ||||
|   <arg type="s" name="title" direction="in"/> \ | ||||
|   <arg type="s" name="subtitle" direction="in"/> \ | ||||
|   <arg type="s" name="body" direction="in"/> \ | ||||
|   <arg type="a{sv}" name="options" direction="in"/> \ | ||||
|   <arg type="u" name="response" direction="out"/> \ | ||||
|   <arg type="a{sv}" name="results" direction="out"/> \ | ||||
| </method> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const DialogResponse = { | ||||
|     OK: 0, | ||||
|     CANCEL: 1, | ||||
|     CLOSED: 2 | ||||
| }; | ||||
|  | ||||
| const AccessDialog = new Lang.Class({ | ||||
|     Name: 'AccessDialog', | ||||
|     Extends: ModalDialog.ModalDialog, | ||||
|  | ||||
|     _init: function(invocation, handle, title, subtitle, body, options) { | ||||
|         this.parent({ styleClass: 'access-dialog' }); | ||||
|  | ||||
|         this._invocation = invocation; | ||||
|         this._handle = handle; | ||||
|  | ||||
|         this._requestExported = false; | ||||
|         this._request = Gio.DBusExportedObject.wrapJSObject(RequestIface, this); | ||||
|  | ||||
|         for (let option in options) | ||||
|             options[option] = options[option].deep_unpack(); | ||||
|  | ||||
|         this._buildLayout(title, subtitle, body, options); | ||||
|     }, | ||||
|  | ||||
|     _buildLayout: function(title, subtitle, body, options) { | ||||
|         // No support for non-modal system dialogs, so ignore the option | ||||
|         //let modal = options['modal'] || true; | ||||
|         let denyLabel = options['deny_label'] || _("Deny Access"); | ||||
|         let grantLabel = options['grant_label'] || _("Grant Access"); | ||||
|         let iconName = options['icon'] || null; | ||||
|         let choices = options['choices'] || []; | ||||
|  | ||||
|         let mainContentBox = new St.BoxLayout(); | ||||
|         mainContentBox.style_class = 'access-dialog-main-layout'; | ||||
|         this.contentLayout.add_actor(mainContentBox); | ||||
|  | ||||
|         let icon = new St.Icon({ style_class: 'access-dialog-icon', | ||||
|                                  icon_name: iconName, | ||||
|                                  y_align: Clutter.ActorAlign.START }); | ||||
|         mainContentBox.add_actor(icon); | ||||
|  | ||||
|         let messageBox = new St.BoxLayout({ vertical: true }); | ||||
|         messageBox.style_class = 'access-dialog-content', | ||||
|         mainContentBox.add_actor(messageBox); | ||||
|  | ||||
|         let label; | ||||
|         label = new St.Label({ style_class: 'access-dialog-title headline', | ||||
|                                text: title }); | ||||
|         messageBox.add_actor(label); | ||||
|  | ||||
|         label = new St.Label({ style_class: 'access-dialog-subtitle', | ||||
|                                text: subtitle }); | ||||
|         label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; | ||||
|         label.clutter_text.line_wrap = true; | ||||
|         messageBox.add_actor(label); | ||||
|  | ||||
|         this._choices = new Map(); | ||||
|  | ||||
|         for (let i = 0; i < choices.length; i++) { | ||||
|             let [id, name, opts, selected] = choices[i]; | ||||
|             if (opts.length > 0) | ||||
|                 continue; // radio buttons, not implemented | ||||
|  | ||||
|             let check = new CheckBox.CheckBox(); | ||||
|             check.getLabelActor().text = name; | ||||
|             check.actor.checked = selected == "true"; | ||||
|             messageBox.add_actor(check.actor); | ||||
|  | ||||
|             this._choices.set(id, check); | ||||
|         } | ||||
|  | ||||
|         label = new St.Label({ text: body }); | ||||
|         label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; | ||||
|         label.clutter_text.line_wrap = true; | ||||
|         messageBox.add_actor(label); | ||||
|  | ||||
|         this.addButton({ label: denyLabel, | ||||
|                          action: () => { | ||||
|                              this._sendResponse(DialogResponse.CANCEL); | ||||
|                          }, | ||||
|                          key: Clutter.KEY_Escape }); | ||||
|         this.addButton({ label: grantLabel, | ||||
|                          action: () => { | ||||
|                              this._sendResponse(DialogResponse.OK); | ||||
|                          }}); | ||||
|     }, | ||||
|  | ||||
|     open: function() { | ||||
|         this.parent(); | ||||
|  | ||||
|         let connection = this._invocation.get_connection(); | ||||
|         this._requestExported = this._request.export(connection, this._handle); | ||||
|     }, | ||||
|  | ||||
|     CloseAsync: function(invocation, params) { | ||||
|         if (this._invocation.get_sender() != invocation.get_sender()) { | ||||
|             invocation.return_error_literal(Gio.DBusError, | ||||
|                                             Gio.DBusError.ACCESS_DENIED, | ||||
|                                             ''); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this._sendResponse(DialogResponse.CLOSED); | ||||
|     }, | ||||
|  | ||||
|     _sendResponse: function(response) { | ||||
|         if (this._requestExported) | ||||
|             this._request.unexport(); | ||||
|         this._requestExported = false; | ||||
|  | ||||
|         let results = {}; | ||||
|         if (response == DialogResponse.OK) { | ||||
|             for (let [id, check] of this._choices) { | ||||
|                 let checked = check.actor.checked ? 'true' : 'false'; | ||||
|                 results[id] = new GLib.Variant('s', checked); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Delay actual response until the end of the close animation (if any) | ||||
|         this.connect('closed', () => { | ||||
|             this._invocation.return_value(new GLib.Variant('(ua{sv})', | ||||
|                                                            [response, results])); | ||||
|         }); | ||||
|         this.close(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const AccessDialogDBus = new Lang.Class({ | ||||
|     Name: 'AccessDialogDBus', | ||||
|  | ||||
|     _init: function() { | ||||
|         this._accessDialog = null; | ||||
|  | ||||
|         this._windowTracker = Shell.WindowTracker.get_default(); | ||||
|  | ||||
|         this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(AccessIface, this); | ||||
|         this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/portal/desktop'); | ||||
|  | ||||
|         Gio.DBus.session.own_name('org.freedesktop.impl.portal.desktop.gnome', Gio.BusNameOwnerFlags.REPLACE, null, null); | ||||
|     }, | ||||
|  | ||||
|     AccessDialogAsync: function(params, invocation) { | ||||
|         if (this._accessDialog) { | ||||
|             invocation.return_error_literal(Gio.DBusError, | ||||
|                                             Gio.DBusError.LIMITS_EXCEEDED, | ||||
|                                             'Already showing a system access dialog'); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let [handle, appId, parentWindow, title, subtitle, body, options] = params; | ||||
|         // We probably want to use parentWindow and global.display.focus_window | ||||
|         // for this check in the future | ||||
|         if (appId && appId + '.desktop' != this._windowTracker.focus_app.id) { | ||||
|             invocation.return_error_literal(Gio.DBusError, | ||||
|                                             Gio.DBusError.ACCESS_DENIED, | ||||
|                                             'Only the focused app is allowed to show a system access dialog'); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let dialog = new AccessDialog(invocation, handle, title, | ||||
|                                       subtitle, body, options); | ||||
|         dialog.open(); | ||||
|  | ||||
|         dialog.connect('closed', () => { this._accessDialog = null; }); | ||||
|  | ||||
|         this._accessDialog = dialog; | ||||
|     } | ||||
| }); | ||||
							
								
								
									
										184
									
								
								js/ui/altTab.js
									
									
									
									
									
								
							
							
						
						
									
										184
									
								
								js/ui/altTab.js
									
									
									
									
									
								
							| @@ -46,19 +46,6 @@ function _createWindowClone(window, size) { | ||||
|                                y_expand: true }); | ||||
| }; | ||||
|  | ||||
| function getWindows(workspace) { | ||||
|     // We ignore skip-taskbar windows in switchers, but if they are attached | ||||
|     // to their parent, their position in the MRU list may be more appropriate | ||||
|     // than the parent; so start with the complete list ... | ||||
|     let windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, | ||||
|                                               workspace); | ||||
|     // ... map windows to their parent where appropriate ... | ||||
|     return windows.map(w => { | ||||
|         return w.is_attached_dialog() ? w.get_transient_for() : w; | ||||
|     // ... and filter out skip-taskbar windows and duplicates | ||||
|     }).filter((w, i, a) => !w.skip_taskbar && a.indexOf(w) == i); | ||||
| } | ||||
|  | ||||
| const AppSwitcherPopup = new Lang.Class({ | ||||
|     Name: 'AppSwitcherPopup', | ||||
|     Extends: SwitcherPopup.SwitcherPopup, | ||||
| @@ -367,149 +354,6 @@ const AppSwitcherPopup = new Lang.Class({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const CyclerHighlight = new Lang.Class({ | ||||
|     Name: 'CyclerHighlight', | ||||
|  | ||||
|     _init: function() { | ||||
|         this._window = null; | ||||
|  | ||||
|         this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout() }); | ||||
|  | ||||
|         this._clone = new Clutter.Clone(); | ||||
|         this.actor.add_actor(this._clone); | ||||
|  | ||||
|         this._highlight = new St.Widget({ style_class: 'cycler-highlight' }); | ||||
|         this.actor.add_actor(this._highlight); | ||||
|  | ||||
|         let coordinate = Clutter.BindCoordinate.ALL; | ||||
|         let constraint = new Clutter.BindConstraint({ coordinate: coordinate }); | ||||
|         this._clone.bind_property('source', constraint, 'source', 0); | ||||
|  | ||||
|         this.actor.add_constraint(constraint); | ||||
|  | ||||
|         this.actor.connect('notify::allocation', | ||||
|                            Lang.bind(this, this._onAllocationChanged)); | ||||
|         this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | ||||
|     }, | ||||
|  | ||||
|     set window(w) { | ||||
|         if (this._window == w) | ||||
|             return; | ||||
|  | ||||
|         this._window = w; | ||||
|  | ||||
|         if (this._clone.source) | ||||
|             this._clone.source.sync_visibility(); | ||||
|  | ||||
|         let windowActor = this._window ? this._window.get_compositor_private() | ||||
|                                        : null; | ||||
|  | ||||
|         if (windowActor) | ||||
|             windowActor.hide(); | ||||
|  | ||||
|         this._clone.source = windowActor; | ||||
|     }, | ||||
|  | ||||
|     _onAllocationChanged: function() { | ||||
|         if (!this._window) { | ||||
|             this._highlight.set_size(0, 0); | ||||
|             this._highlight.hide(); | ||||
|         } else { | ||||
|             let [x, y] = this.actor.allocation.get_origin(); | ||||
|             let rect = this._window.get_frame_rect(); | ||||
|             this._highlight.set_size(rect.width, rect.height); | ||||
|             this._highlight.set_position(rect.x - x, rect.y - y); | ||||
|             this._highlight.show(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _onDestroy: function() { | ||||
|         this.window = null; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const CyclerPopup = new Lang.Class({ | ||||
|     Name: 'CyclerPopup', | ||||
|     Extends: SwitcherPopup.SwitcherPopup, | ||||
|     Abstract: true, | ||||
|  | ||||
|     _init : function() { | ||||
|         this.parent(); | ||||
|  | ||||
|         this._items = this._getWindows(); | ||||
|  | ||||
|         if (this._items.length == 0) | ||||
|             return; | ||||
|  | ||||
|         this._highlight = new CyclerHighlight(); | ||||
|         global.window_group.add_actor(this._highlight.actor); | ||||
|  | ||||
|         // We don't show an actual popup, so just provide what SwitcherPopup | ||||
|         // expects instead of inheriting from SwitcherList | ||||
|         this._switcherList = { actor: new St.Widget(), | ||||
|                                highlight: Lang.bind(this, this._highlightItem), | ||||
|                                connect: function() {} }; | ||||
|     }, | ||||
|  | ||||
|     _highlightItem: function(index, justOutline) { | ||||
|         this._highlight.window = this._items[index]; | ||||
|         global.window_group.set_child_above_sibling(this._highlight.actor, null); | ||||
|     }, | ||||
|  | ||||
|     _finish: function() { | ||||
|         let window = this._items[this._selectedIndex]; | ||||
|         let ws = window.get_workspace(); | ||||
|         let activeWs = global.screen.get_active_workspace(); | ||||
|  | ||||
|         if (window.minimized) { | ||||
|             Main.wm.skipNextEffect(window.get_compositor_private()); | ||||
|             window.unminimize(); | ||||
|         } | ||||
|  | ||||
|         if (activeWs == ws) { | ||||
|             Main.activateWindow(window); | ||||
|         } else { | ||||
|             // If the selected window is on a different workspace, we don't | ||||
|             // want it to disappear, then slide in with the workspace; instead, | ||||
|             // always activate it on the active workspace ... | ||||
|             activeWs.activate_with_focus(window, global.get_current_time()); | ||||
|  | ||||
|             // ... then slide it over to the original workspace if necessary | ||||
|             Main.wm.actionMoveWindow(window, ws); | ||||
|         } | ||||
|  | ||||
|         this.parent(); | ||||
|     }, | ||||
|  | ||||
|     _onDestroy: function() { | ||||
|         this._highlight.actor.destroy(); | ||||
|  | ||||
|         this.parent(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
|  | ||||
| const GroupCyclerPopup = new Lang.Class({ | ||||
|     Name: 'GroupCyclerPopup', | ||||
|     Extends: CyclerPopup, | ||||
|  | ||||
|     _getWindows: function() { | ||||
|         let app = Shell.WindowTracker.get_default().focus_app; | ||||
|         return app ? app.get_windows() : []; | ||||
|     }, | ||||
|  | ||||
|     _keyPressHandler: function(keysym, action) { | ||||
|         if (action == Meta.KeyBindingAction.CYCLE_GROUP) | ||||
|             this._select(this._next()); | ||||
|         else if (action == Meta.KeyBindingAction.CYCLE_GROUP_BACKWARD) | ||||
|             this._select(this._previous()); | ||||
|         else | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const WindowSwitcherPopup = new Lang.Class({ | ||||
|     Name: 'WindowSwitcherPopup', | ||||
|     Extends: SwitcherPopup.SwitcherPopup, | ||||
| @@ -530,7 +374,7 @@ const WindowSwitcherPopup = new Lang.Class({ | ||||
|  | ||||
|     _getWindowList: function() { | ||||
|         let workspace = this._settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() : null; | ||||
|         return getWindows(workspace); | ||||
|         return global.display.get_tab_list(Meta.TabList.NORMAL, workspace); | ||||
|     }, | ||||
|  | ||||
|     _keyPressHandler: function(keysym, action) { | ||||
| @@ -557,32 +401,6 @@ const WindowSwitcherPopup = new Lang.Class({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const WindowCyclerPopup = new Lang.Class({ | ||||
|     Name: 'WindowCyclerPopup', | ||||
|     Extends: CyclerPopup, | ||||
|  | ||||
|     _init: function() { | ||||
|         this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' }); | ||||
|         this.parent(); | ||||
|     }, | ||||
|  | ||||
|     _getWindows: function() { | ||||
|         let workspace = this._settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() : null; | ||||
|         return getWindows(workspace); | ||||
|     }, | ||||
|  | ||||
|     _keyPressHandler: function(keysym, action) { | ||||
|         if (action == Meta.KeyBindingAction.CYCLE_WINDOWS) | ||||
|             this._select(this._next()); | ||||
|         else if (action == Meta.KeyBindingAction.CYCLE_WINDOWS_BACKWARD) | ||||
|             this._select(this._previous()); | ||||
|         else | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         return Clutter.EVENT_STOP; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const AppIcon = new Lang.Class({ | ||||
|     Name: 'AppIcon', | ||||
|  | ||||
|   | ||||
| @@ -1814,7 +1814,7 @@ const AppIconMenu = new Lang.Class({ | ||||
|             if (!source.actor.mapped) | ||||
|                 this.close(); | ||||
|         })); | ||||
|         source.actor.connect('destroy', Lang.bind(this, this.destroy)); | ||||
|         source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); })); | ||||
|  | ||||
|         Main.uiGroup.add_actor(this.actor); | ||||
|     }, | ||||
|   | ||||
| @@ -16,14 +16,13 @@ const RENAMED_DESKTOP_IDS = { | ||||
|     'glchess.desktop': 'gnome-chess.desktop', | ||||
|     'glines.desktop': 'five-or-more.desktop', | ||||
|     'gnect.desktop': 'four-in-a-row.desktop', | ||||
|     'gnibbles.desktop': 'org.gnome.Nibbles.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-nibbles.desktop': 'org.gnome.Nibbles.desktop', | ||||
|     'gnome-photos.desktop': 'org.gnome.Photos.desktop', | ||||
|     'gnome-screenshot.desktop': 'org.gnome.Screenshot.desktop', | ||||
|     'gnome-software.desktop': 'org.gnome.Software.desktop', | ||||
|   | ||||
| @@ -1,216 +0,0 @@ | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Gio = imports.gi.Gio; | ||||
| const GLib = imports.gi.GLib; | ||||
| const Lang = imports.lang; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Shell = imports.gi.Shell; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const Main = imports.ui.main; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
|  | ||||
| const AudioDevice = { | ||||
|     HEADPHONES: 1 << 0, | ||||
|     HEADSET:    1 << 1, | ||||
|     MICROPHONE: 1 << 2 | ||||
| }; | ||||
|  | ||||
| const AudioDeviceSelectionIface = '<node> \ | ||||
| <interface name="org.gnome.Shell.AudioDeviceSelection"> \ | ||||
| <method name="Open"> \ | ||||
|     <arg name="devices" direction="in" type="as" /> \ | ||||
| </method> \ | ||||
| <method name="Close"> \ | ||||
| </method> \ | ||||
| <signal name="DeviceSelected"> \ | ||||
|     <arg name="device" type="s" /> \ | ||||
| </signal> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const AudioDeviceSelectionDialog = new Lang.Class({ | ||||
|     Name: 'AudioDeviceSelectionDialog', | ||||
|     Extends: ModalDialog.ModalDialog, | ||||
|  | ||||
|     _init: function(devices) { | ||||
|         this.parent({ styleClass: 'audio-device-selection-dialog' }); | ||||
|  | ||||
|         this._deviceItems = {}; | ||||
|  | ||||
|         this._buildLayout(); | ||||
|  | ||||
|         if (devices & AudioDevice.HEADPHONES) | ||||
|             this._addDevice(AudioDevice.HEADPHONES); | ||||
|         if (devices & AudioDevice.HEADSET) | ||||
|             this._addDevice(AudioDevice.HEADSET); | ||||
|         if (devices & AudioDevice.MICROPHONE) | ||||
|             this._addDevice(AudioDevice.MICROPHONE); | ||||
|  | ||||
|         if (this._selectionBox.get_n_children() < 2) | ||||
|             throw new Error('Too few devices for a selection'); | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
|         this.parent(); | ||||
|     }, | ||||
|  | ||||
|     _buildLayout: function(devices) { | ||||
|         let title = new St.Label({ style_class: 'audio-selection-title', | ||||
|                                    text: _("Select Audio Device"), | ||||
|                                    x_align: Clutter.ActorAlign.CENTER }); | ||||
|  | ||||
|         this.contentLayout.style_class = 'audio-selection-content'; | ||||
|         this.contentLayout.add(title); | ||||
|  | ||||
|         this._selectionBox = new St.BoxLayout({ style_class: 'audio-selection-box' }); | ||||
|         this.contentLayout.add(this._selectionBox, { expand: true }); | ||||
|  | ||||
|         this.addButton({ action: Lang.bind(this, this._openSettings), | ||||
|                          label: _("Sound Settings") }); | ||||
|         this.addButton({ action: Lang.bind(this, this.close), | ||||
|                          label: _("Cancel"), | ||||
|                          key: Clutter.Escape }); | ||||
|     }, | ||||
|  | ||||
|     _getDeviceLabel: function(device) { | ||||
|         switch(device) { | ||||
|             case AudioDevice.HEADPHONES: | ||||
|                 return _("Headphones"); | ||||
|             case AudioDevice.HEADSET: | ||||
|                 return _("Headset"); | ||||
|             case AudioDevice.MICROPHONE: | ||||
|                 return _("Microphone"); | ||||
|             default: | ||||
|                 return null; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _getDeviceIcon: function(device) { | ||||
|         switch(device) { | ||||
|             case AudioDevice.HEADPHONES: | ||||
|                 return 'audio-headphones-symbolic'; | ||||
|             case AudioDevice.HEADSET: | ||||
|                 return 'audio-headset-symbolic'; | ||||
|             case AudioDevice.MICROPHONE: | ||||
|                 return 'audio-input-microphone-symbolic'; | ||||
|             default: | ||||
|                 return null; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _addDevice: function(device) { | ||||
|         let box = new St.BoxLayout({ style_class: 'audio-selection-device-box', | ||||
|                                      vertical: true }); | ||||
|         box.connect('notify::height', | ||||
|             function() { | ||||
|                 Meta.later_add(Meta.LaterType.BEFORE_REDRAW, | ||||
|                     function() { | ||||
|                         box.width = box.height; | ||||
|                     }); | ||||
|             }); | ||||
|  | ||||
|         let icon = new St.Icon({ style_class: 'audio-selection-device-icon', | ||||
|                                  icon_name: this._getDeviceIcon(device) }); | ||||
|         box.add(icon); | ||||
|  | ||||
|         let label = new St.Label({ style_class: 'audio-selection-device-label', | ||||
|                                    text: this._getDeviceLabel(device), | ||||
|                                    x_align: Clutter.ActorAlign.CENTER }); | ||||
|         box.add(label); | ||||
|  | ||||
|         let button = new St.Button({ style_class: 'audio-selection-device', | ||||
|                                      can_focus: true, | ||||
|                                      child: box }); | ||||
|         this._selectionBox.add(button); | ||||
|  | ||||
|         button.connect('clicked', Lang.bind(this, | ||||
|             function() { | ||||
|                 this.emit('device-selected', device); | ||||
|                 this.close(); | ||||
|                 Main.overview.hide(); | ||||
|             })); | ||||
|     }, | ||||
|  | ||||
|     _openSettings: function() { | ||||
|         let desktopFile = 'gnome-sound-panel.desktop' | ||||
|         let app = Shell.AppSystem.get_default().lookup_app(desktopFile); | ||||
|  | ||||
|         if (!app) { | ||||
|             log('Settings panel for desktop file ' + desktopFile + ' could not be loaded!'); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this.close(); | ||||
|         Main.overview.hide(); | ||||
|         app.activate(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const AudioDeviceSelectionDBus = new Lang.Class({ | ||||
|     Name: 'AudioDeviceSelectionDBus', | ||||
|  | ||||
|     _init: function() { | ||||
|         this._audioSelectionDialog = null; | ||||
|  | ||||
|         this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(AudioDeviceSelectionIface, this); | ||||
|         this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/AudioDeviceSelection'); | ||||
|  | ||||
|         Gio.DBus.session.own_name('org.gnome.Shell.AudioDeviceSelection', Gio.BusNameOwnerFlags.REPLACE, null, null); | ||||
|     }, | ||||
|  | ||||
|     _onDialogClosed: function() { | ||||
|         this._audioSelectionDialog = null; | ||||
|     }, | ||||
|  | ||||
|     _onDeviceSelected: function(dialog, device) { | ||||
|         let connection = this._dbusImpl.get_connection(); | ||||
|         let info = this._dbusImpl.get_info(); | ||||
|         let deviceName = Object.keys(AudioDevice).filter( | ||||
|             function(dev) { | ||||
|                 return AudioDevice[dev] == device; | ||||
|             })[0].toLowerCase(); | ||||
|         connection.emit_signal(this._audioSelectionDialog._sender, | ||||
|                                this._dbusImpl.get_object_path(), | ||||
|                                info ? info.name : null, | ||||
|                                'DeviceSelected', | ||||
|                                GLib.Variant.new('(s)', [deviceName])); | ||||
|     }, | ||||
|  | ||||
|     OpenAsync: function(params, invocation) { | ||||
|         if (this._audioSelectionDialog) { | ||||
|             invocation.return_value(null); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let [deviceNames] = params; | ||||
|         let devices = 0; | ||||
|         deviceNames.forEach(function(n) { | ||||
|             devices |= AudioDevice[n.toUpperCase()]; | ||||
|         }); | ||||
|  | ||||
|         let dialog; | ||||
|         try { | ||||
|             dialog = new AudioDeviceSelectionDialog(devices); | ||||
|         } catch(e) { | ||||
|             invocation.return_value(null); | ||||
|             return; | ||||
|         } | ||||
|         dialog._sender = invocation.get_sender(); | ||||
|  | ||||
|         dialog.connect('closed', Lang.bind(this, this._onDialogClosed)); | ||||
|         dialog.connect('device-selected', | ||||
|                        Lang.bind(this, this._onDeviceSelected)); | ||||
|         dialog.open(); | ||||
|  | ||||
|         this._audioSelectionDialog = dialog; | ||||
|         invocation.return_value(null); | ||||
|     }, | ||||
|  | ||||
|     CloseAsync: function(params, invocation) { | ||||
|         if (this._audioSelectionDialog && | ||||
|             this._audioSelectionDialog._sender == invocation.get_sender()) | ||||
|             this._audioSelectionDialog.close(); | ||||
|  | ||||
|         invocation.return_value(null); | ||||
|     } | ||||
| }); | ||||
| @@ -696,7 +696,6 @@ const BackgroundManager = new Lang.Class({ | ||||
|                            time: FADE_ANIMATION_TIME, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            onComplete: function() { | ||||
|                                oldBackgroundActor.background.run_dispose(); | ||||
|                                oldBackgroundActor.destroy(); | ||||
|                            } | ||||
|                          }); | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -796,18 +796,10 @@ const NetworkAgent = new Lang.Class({ | ||||
|                         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 }; | ||||
|                         try { | ||||
|                             let aliases = keyfile.get_string_list('VPN Connection', 'aliases'); | ||||
|  | ||||
|                             for (let alias of aliases) { | ||||
|                                 this._vpnBinaries[alias] = { fileName: path, externalUIMode: externalUIMode, supportsHints: hints }; | ||||
|                             } | ||||
|                         } catch(e) { } // ignore errors if key does not exist | ||||
|                     } else { | ||||
|                     else | ||||
|                         throw new Error('VPN plugin at %s is not executable'.format(path)); | ||||
|                     } | ||||
|                 } catch(e) { | ||||
|                     log('Error \'%s\' while processing VPN keyfile \'%s\''. | ||||
|                         format(e.message, dir.get_child(name).get_path())); | ||||
|   | ||||
| @@ -12,9 +12,9 @@ const St = imports.gi.St; | ||||
| const Tpl = imports.gi.TelepathyLogger; | ||||
| const Tp = imports.gi.TelepathyGLib; | ||||
|  | ||||
| const Calendar = imports.ui.calendar; | ||||
| const History = imports.misc.history; | ||||
| const Main = imports.ui.main; | ||||
| const MessageList = imports.ui.messageList; | ||||
| const MessageTray = imports.ui.messageTray; | ||||
| const Params = imports.misc.params; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
| @@ -469,17 +469,11 @@ const ChatSource = new Lang.Class({ | ||||
|  | ||||
|     destroy: function(reason) { | ||||
|         if (this._client.is_handling_channel(this._channel)) { | ||||
|             this._ackMessages(); | ||||
|             // The chat box has been destroyed so it can't | ||||
|             // handle the channel any more. | ||||
|             this._channel.close_async(function(channel, result) { | ||||
|                 channel.close_finish(result); | ||||
|             }); | ||||
|         } else { | ||||
|             // Don't indicate any unread messages when the notification | ||||
|             // that represents them has been destroyed. | ||||
|             this._pendingMessages = []; | ||||
|             this.countUpdated(); | ||||
|         } | ||||
|  | ||||
|         // Keep source alive while the channel is open | ||||
| @@ -872,7 +866,7 @@ const ChatNotificationBanner = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _addMessage: function(message) { | ||||
|         let highlighter = new MessageList.URLHighlighter(message.body, true, true); | ||||
|         let highlighter = new Calendar.URLHighlighter(message.body, true, true); | ||||
|         let body = highlighter.actor; | ||||
|  | ||||
|         let styles = message.styles; | ||||
|   | ||||
| @@ -259,7 +259,7 @@ const ShowAppsIcon = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _createIcon: function(size) { | ||||
|         this._iconActor = new St.Icon({ icon_name: 'view-app-grid-symbolic', | ||||
|         this._iconActor = new St.Icon({ icon_name: 'view-grid-symbolic', | ||||
|                                         icon_size: size, | ||||
|                                         style_class: 'show-apps-icon', | ||||
|                                         track_hover: true }); | ||||
|   | ||||
| @@ -360,7 +360,7 @@ const DateMenuButton = new Lang.Class({ | ||||
|         })); | ||||
|  | ||||
|         // Fill up the first column | ||||
|         this._messageList = new Calendar.CalendarMessageList(); | ||||
|         this._messageList = new Calendar.MessageList(); | ||||
|         hbox.add(this._messageList.actor, { expand: true, y_fill: false, y_align: St.Align.START }); | ||||
|  | ||||
|         // Fill up the second column | ||||
|   | ||||
							
								
								
									
										70
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							| @@ -571,13 +571,20 @@ const _Draggable = new Lang.Class({ | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this._animateDragEnd(eventTime, | ||||
|                              { x: snapBackX, | ||||
|                                y: snapBackY, | ||||
|                                scale_x: snapBackScale, | ||||
|                                scale_y: snapBackScale, | ||||
|                                time: SNAP_BACK_ANIMATION_TIME, | ||||
|                              }); | ||||
|         this._animationInProgress = true; | ||||
|         // No target, so snap back | ||||
|         Tweener.addTween(this._dragActor, | ||||
|                          { x: snapBackX, | ||||
|                            y: snapBackY, | ||||
|                            scale_x: snapBackScale, | ||||
|                            scale_y: snapBackScale, | ||||
|                            opacity: this._dragOrigOpacity, | ||||
|                            time: SNAP_BACK_ANIMATION_TIME, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            onComplete: this._onAnimationComplete, | ||||
|                            onCompleteScope: this, | ||||
|                            onCompleteParams: [this._dragActor, eventTime] | ||||
|                          }); | ||||
|     }, | ||||
|  | ||||
|     _restoreDragActor: function(eventTime) { | ||||
| @@ -589,44 +596,18 @@ const _Draggable = new Lang.Class({ | ||||
|         this._dragActor.set_scale(restoreScale, restoreScale); | ||||
|         this._dragActor.opacity = 0; | ||||
|  | ||||
|         this._animateDragEnd(eventTime, | ||||
|                              { time: REVERT_ANIMATION_TIME }); | ||||
|     }, | ||||
|  | ||||
|     _animateDragEnd: function (eventTime, params) { | ||||
|         this._animationInProgress = true; | ||||
|  | ||||
|         // finish animation if the actor gets destroyed | ||||
|         // during it | ||||
|         this._dragActorDestroyId = | ||||
|             this._dragActor.connect('destroy', | ||||
|                                     Lang.bind(this, this._finishAnimation)); | ||||
|  | ||||
|         params['opacity']          = this._dragOrigOpacity; | ||||
|         params['transition']       = 'easeOutQuad'; | ||||
|         params['onComplete']       = this._onAnimationComplete; | ||||
|         params['onCompleteScope']  = this; | ||||
|         params['onCompleteParams'] = [this._dragActor, eventTime]; | ||||
|  | ||||
|         // start the animation | ||||
|         Tweener.addTween(this._dragActor, params) | ||||
|     }, | ||||
|  | ||||
|     _finishAnimation : function () { | ||||
|         if (!this._animationInProgress) | ||||
|             return | ||||
|  | ||||
|         this._animationInProgress = false; | ||||
|         if (!this._buttonDown) | ||||
|             this._dragComplete(); | ||||
|  | ||||
|         global.screen.set_cursor(Meta.Cursor.DEFAULT); | ||||
|         Tweener.addTween(this._dragActor, | ||||
|                          { opacity: this._dragOrigOpacity, | ||||
|                            time: REVERT_ANIMATION_TIME, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            onComplete: this._onAnimationComplete, | ||||
|                            onCompleteScope: this, | ||||
|                            onCompleteParams: [this._dragActor, eventTime] | ||||
|                          }); | ||||
|     }, | ||||
|  | ||||
|     _onAnimationComplete : function (dragActor, eventTime) { | ||||
|         dragActor.disconnect(this._dragActorDestroyId); | ||||
|         this._dragActorDestroyId = 0; | ||||
|  | ||||
|         if (this._dragOrigParent) { | ||||
|             Main.uiGroup.remove_child(this._dragActor); | ||||
|             this._dragOrigParent.add_actor(this._dragActor); | ||||
| @@ -635,9 +616,12 @@ const _Draggable = new Lang.Class({ | ||||
|         } else { | ||||
|             dragActor.destroy(); | ||||
|         } | ||||
|  | ||||
|         global.screen.set_cursor(Meta.Cursor.DEFAULT); | ||||
|         this.emit('drag-end', eventTime, false); | ||||
|         this._finishAnimation(); | ||||
|  | ||||
|         this._animationInProgress = false; | ||||
|         if (!this._buttonDown) | ||||
|             this._dragComplete(); | ||||
|     }, | ||||
|  | ||||
|     _dragComplete: function() { | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
| /* | ||||
|  * Copyright 2010-2016 Red Hat, Inc | ||||
|  * Copyright 2010 Red Hat, Inc | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
| @@ -114,7 +114,7 @@ const restartDialogContent = { | ||||
|     showOtherSessions: true, | ||||
| }; | ||||
|  | ||||
| const restartUpdateDialogContent = { | ||||
| const restartInstallDialogContent = { | ||||
|  | ||||
|     subject: C_("title", "Restart & Install Updates"), | ||||
|     description: function(seconds) { | ||||
| @@ -132,38 +132,18 @@ const restartUpdateDialogContent = { | ||||
|     showOtherSessions: true, | ||||
| }; | ||||
|  | ||||
| const restartUpgradeDialogContent = { | ||||
|  | ||||
|     subject: C_("title", "Restart & Install Upgrade"), | ||||
|     upgradeDescription: function(distroName, distroVersion) { | ||||
|         /* Translators: This is the text displayed for system upgrades in the | ||||
|            shut down dialog. First %s gets replaced with the distro name and | ||||
|            second %s with the distro version to upgrade to */ | ||||
|         return _("%s %s will be installed after restart. Upgrade installation can take a long time: ensure that you have backed up and that the computer is plugged in.").format(distroName, distroVersion); | ||||
|     }, | ||||
|     disableTimer: true, | ||||
|     showBatteryWarning: false, | ||||
|     confirmButtons: [{ signal: 'ConfirmedReboot', | ||||
|                        label:  C_("button", "Restart & Install") }], | ||||
|     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, | ||||
|   UPGRADE_RESTART: 4 | ||||
|   UPDATE_RESTART: 3 | ||||
| }; | ||||
|  | ||||
| const DialogContent = { | ||||
|     0 /* DialogType.LOGOUT */: logoutDialogContent, | ||||
|     1 /* DialogType.SHUTDOWN */: shutdownDialogContent, | ||||
|     2 /* DialogType.RESTART */: restartDialogContent, | ||||
|     3 /* DialogType.UPDATE_RESTART */: restartUpdateDialogContent, | ||||
|     4 /* DialogType.UPGRADE_RESTART */: restartUpgradeDialogContent | ||||
|     3 /* DialogType.UPDATE_RESTART */: restartInstallDialogContent | ||||
| }; | ||||
|  | ||||
| const MAX_USERS_IN_SESSION_DIALOG = 5; | ||||
| @@ -183,10 +163,7 @@ const LogindSession = Gio.DBusProxy.makeProxyWrapper(LogindSessionIface); | ||||
| const PkOfflineIface = '<node> \ | ||||
| <interface name="org.freedesktop.PackageKit.Offline"> \ | ||||
|     <property name="UpdatePrepared" type="b" access="read"/> \ | ||||
|     <property name="UpdateTriggered" type="b" access="read"/> \ | ||||
|     <property name="UpgradePrepared" type="b" access="read"/> \ | ||||
|     <property name="UpgradeTriggered" type="b" access="read"/> \ | ||||
|     <property name="PreparedUpgrade" type="a{sv}" access="read"/> \ | ||||
|     <property name="TriggerAction" type="s" access="read"/> \ | ||||
|     <method name="Trigger"> \ | ||||
|         <arg type="s" name="action" direction="in"/> \ | ||||
|     </method> \ | ||||
| @@ -438,19 +415,11 @@ const EndSessionDialog = new Lang.Class({ | ||||
|  | ||||
|                 if (dialogContent.descriptionWithUser) | ||||
|                     description = dialogContent.descriptionWithUser(realName, displayTime); | ||||
|                 else | ||||
|                     description = dialogContent.description(displayTime); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Use a different description when we are installing a system upgrade | ||||
|         if (dialogContent.upgradeDescription) { | ||||
|             let name = this._pkOfflineProxy.PreparedUpgrade['name'].deep_unpack(); | ||||
|             let version = this._pkOfflineProxy.PreparedUpgrade['version'].deep_unpack(); | ||||
|  | ||||
|             if (name != null && version != null) | ||||
|                 description = dialogContent.upgradeDescription(name, version); | ||||
|         } | ||||
|  | ||||
|         // Fall back to regular description | ||||
|         if (!description) | ||||
|             description = dialogContent.description(displayTime); | ||||
|  | ||||
| @@ -729,12 +698,9 @@ const EndSessionDialog = new Lang.Class({ | ||||
|         this._totalSecondsToStayOpen = totalSecondsToStayOpen; | ||||
|         this._type = type; | ||||
|  | ||||
|         if (this._type == DialogType.RESTART) { | ||||
|             if (this._pkOfflineProxy.UpdateTriggered) | ||||
|                 this._type = DialogType.UPDATE_RESTART; | ||||
|             else if (this._pkOfflineProxy.UpgradeTriggered) | ||||
|                 this._type = DialogType.UPGRADE_RESTART; | ||||
|         } | ||||
|         if (this._type == DialogType.RESTART && | ||||
|             this._pkOfflineProxy.TriggerAction == 'reboot') | ||||
|             this._type = DialogType.UPDATE_RESTART; | ||||
|  | ||||
|         this._applications = []; | ||||
|         this._applicationList.destroy_all_children(); | ||||
| @@ -761,19 +727,19 @@ const EndSessionDialog = new Lang.Class({ | ||||
|         if (dialogContent.showOtherSessions) | ||||
|             this._loadSessions(); | ||||
|  | ||||
|         let updateTriggered = this._pkOfflineProxy.UpdateTriggered; | ||||
|         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 && updateTriggered); | ||||
|         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 && updateTriggered && !updatesAllowed)); | ||||
|                                         (this._checkBox.actor.visible || updatePrepared && updateAlreadyTriggered && !updatesAllowed)); | ||||
|  | ||||
|         this._updateButtons(); | ||||
|  | ||||
| @@ -783,9 +749,7 @@ const EndSessionDialog = new Lang.Class({ | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (!dialogContent.disableTimer) | ||||
|             this._startTimer(); | ||||
|  | ||||
|         this._startTimer(); | ||||
|         this._sync(); | ||||
|  | ||||
|         let signalId = this.connect('opened', | ||||
|   | ||||
| @@ -158,22 +158,10 @@ const CandidatePopup = new Lang.Class({ | ||||
|  | ||||
|         panelService.connect('set-cursor-location', | ||||
|                              Lang.bind(this, function(ps, x, y, w, h) { | ||||
|                                  this._setDummyCursorGeometry(x, y, w, h); | ||||
|                                  Main.layoutManager.setDummyCursorGeometry(x, y, w, h); | ||||
|                                  if (this._boxPointer.actor.visible) | ||||
|                                      this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0); | ||||
|                              })); | ||||
|         try { | ||||
|             panelService.connect('set-cursor-location-relative', | ||||
|                                  Lang.bind(this, function(ps, x, y, w, h) { | ||||
|                                      if (!global.display.focus_window) | ||||
|                                          return; | ||||
|                                      let window = global.display.focus_window.get_compositor_private(); | ||||
|                                      this._setDummyCursorGeometry(window.x + x, window.y + y, w, h); | ||||
|                                  })); | ||||
|         } catch(e) { | ||||
|             // Only recent IBus versions have support for this signal | ||||
|             // which is used for wayland clients. In order to work | ||||
|             // with older IBus versions we can silently ignore the | ||||
|             // signal's absence. | ||||
|         } | ||||
|         panelService.connect('update-preedit-text', | ||||
|                              Lang.bind(this, function(ps, text, cursorPosition, visible) { | ||||
|                                  this._preeditText.visible = visible; | ||||
| @@ -258,12 +246,6 @@ const CandidatePopup = new Lang.Class({ | ||||
|                              })); | ||||
|     }, | ||||
|  | ||||
|     _setDummyCursorGeometry: function(x, y, w, h) { | ||||
|         Main.layoutManager.setDummyCursorGeometry(x, y, w, h); | ||||
|         if (this._boxPointer.actor.visible) | ||||
|             this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0); | ||||
|     }, | ||||
|  | ||||
|     _updateVisibility: function() { | ||||
|         let isVisible = (this._preeditText.visible || | ||||
|                          this._auxText.visible || | ||||
|   | ||||
| @@ -10,7 +10,6 @@ const Meta = imports.gi.Meta; | ||||
| const Shell = imports.gi.Shell; | ||||
| const Signals = imports.signals; | ||||
| const St = imports.gi.St; | ||||
| const InputSourceManager = imports.ui.status.keyboard; | ||||
|  | ||||
| const BoxPointer = imports.ui.boxpointer; | ||||
| const Layout = imports.ui.layout; | ||||
| @@ -758,48 +757,19 @@ const ShellWaylandAdapter = new Lang.Class({ | ||||
|     Name: 'ShellWaylandAdapter', | ||||
|     Extends: Caribou.XAdapter, | ||||
|  | ||||
|     _init: function () { | ||||
|         this.parent(); | ||||
|         let deviceManager = Clutter.DeviceManager.get_default(); | ||||
|         this._virtualDevice = deviceManager.create_virtual_device(Clutter.InputDeviceType.KEYBOARD_DEVICE); | ||||
|  | ||||
|         this._inputSourceManager = InputSourceManager.getInputSourceManager(); | ||||
|         this._sourceChangedId = this._inputSourceManager.connect('current-source-changed', | ||||
|                                                                  Lang.bind(this, this._onSourceChanged)); | ||||
|         this._sourcesModifiedId = this._inputSourceManager.connect ('sources-changed', | ||||
|                                                                     Lang.bind(this, this._onSourcesModified)); | ||||
|     }, | ||||
|  | ||||
|     _onSourcesModified: function () { | ||||
|         this.emit('config-changed'); | ||||
|     }, | ||||
|  | ||||
|     _onSourceChanged: function (inputSourceManager, oldSource) { | ||||
|         let source = inputSourceManager.currentSource; | ||||
|         this.emit('group-changed', source.index, source.id, ''); | ||||
|     }, | ||||
|  | ||||
|     vfunc_get_groups: function () { | ||||
|         let inputSources = this._inputSourceManager.inputSources; | ||||
|         let groups = [] | ||||
|         let variants = []; | ||||
|  | ||||
|         for (let i in inputSources) { | ||||
|             let is = inputSources[i]; | ||||
|             groups[is.index] = is.id; | ||||
|             variants[is.index] = ''; | ||||
|         } | ||||
|  | ||||
|         return [groups, groups.length, variants, variants.length]; | ||||
|     }, | ||||
|  | ||||
|     vfunc_keyval_press: function(keyval) { | ||||
|         this._virtualDevice.notify_keyval(Clutter.get_current_event_time(), | ||||
|                                           keyval, Clutter.KeyState.PRESSED); | ||||
|         let focus = global.stage.get_key_focus(); | ||||
|         if (focus instanceof Clutter.Text) | ||||
|             Shell.util_text_insert_keyval(focus, keyval); | ||||
|         else | ||||
|             this.parent(keyval); | ||||
|     }, | ||||
|  | ||||
|     vfunc_keyval_release: function(keyval) { | ||||
|         this._virtualDevice.notify_keyval(Clutter.get_current_event_time(), | ||||
|                                           keyval, Clutter.KeyState.RELEASED); | ||||
|         let focus = global.stage.get_key_focus(); | ||||
|         if (focus instanceof Clutter.Text) | ||||
|             return;             // do nothing | ||||
|         else | ||||
|             this.parent(keyval); | ||||
|     }, | ||||
| }); | ||||
|   | ||||
| @@ -220,8 +220,7 @@ const LayoutManager = new Lang.Class({ | ||||
|         global.stage.add_child(this.uiGroup); | ||||
|  | ||||
|         this.overviewGroup = new St.Widget({ name: 'overviewGroup', | ||||
|                                              visible: false, | ||||
|                                              reactive: true }); | ||||
|                                              visible: false }); | ||||
|         this.addChrome(this.overviewGroup); | ||||
|  | ||||
|         this.screenShieldGroup = new St.Widget({ name: 'screenShieldGroup', | ||||
| @@ -592,10 +591,7 @@ const LayoutManager = new Lang.Class({ | ||||
|         this.addChrome(this._coverPane); | ||||
|  | ||||
|         if (Meta.is_restart()) { | ||||
|             // On restart, we don't do an animation. Force an update of the | ||||
|             // regions immediately so that maximized windows restore to the | ||||
|             // right size taking struts into account. | ||||
|             this._updateRegions(); | ||||
|             // On restart, we don't do an animation | ||||
|         } else if (Main.sessionMode.isGreeter) { | ||||
|             this.panelBox.translation_y = -this.panelBox.height; | ||||
|         } else { | ||||
| @@ -942,11 +938,6 @@ const LayoutManager = new Lang.Class({ | ||||
|         if (Main.modalCount > 0) | ||||
|             return GLib.SOURCE_REMOVE; | ||||
|  | ||||
|         // Bug workaround - get_transformed_position()/get_transformed_size() don't work after | ||||
|         // a change in stage size until the first pick or paint. | ||||
|         // https://bugzilla.gnome.org/show_bug.cgi?id=761565 | ||||
|         global.stage.get_actor_at_pos(Clutter.PickMode.ALL, 0, 0); | ||||
|  | ||||
|         let rects = [], struts = [], i; | ||||
|         let isPopupMenuVisible = global.top_window_group.get_children().some(isPopupMetaWindow); | ||||
|         let wantsInputRegion = !isPopupMenuVisible; | ||||
|   | ||||
| @@ -50,14 +50,15 @@ const LegacyTray = new Lang.Class({ | ||||
|         this._slideLayout.translationX = 0; | ||||
|         this._slideLayout.slideDirection = OverviewControls.SlideDirection.LEFT; | ||||
|  | ||||
|         this._slider = new St.Widget({ x_expand: true, y_expand: true, | ||||
|         this._slider = new St.Widget({ style_class: 'legacy-tray', | ||||
|                                        x_expand: true, y_expand: true, | ||||
|                                        x_align: Clutter.ActorAlign.START, | ||||
|                                        y_align: Clutter.ActorAlign.END, | ||||
|                                        layout_manager: this._slideLayout }); | ||||
|         this.actor.add_actor(this._slider); | ||||
|         this._slider.connect('notify::allocation', Lang.bind(this, this._syncBarrier)); | ||||
|  | ||||
|         this._box = new St.BoxLayout({ style_class: 'legacy-tray' }); | ||||
|         this._box = new St.BoxLayout(); | ||||
|         this._slider.add_actor(this._box); | ||||
|  | ||||
|         this._concealHandle = new St.Button({ style_class: 'legacy-tray-handle', | ||||
|   | ||||
| @@ -11,8 +11,6 @@ const Meta = imports.gi.Meta; | ||||
| const Shell = imports.gi.Shell; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const AccessDialog = imports.ui.accessDialog; | ||||
| const AudioDeviceSelection = imports.ui.audioDeviceSelection; | ||||
| const Components = imports.ui.components; | ||||
| const CtrlAltTab = imports.ui.ctrlAltTab; | ||||
| const EndSessionDialog = imports.ui.endSessionDialog; | ||||
| @@ -64,8 +62,6 @@ let ctrlAltTabManager = null; | ||||
| let osdWindowManager = null; | ||||
| let osdMonitorLabeler = null; | ||||
| let sessionMode = null; | ||||
| let shellAccessDialogDBusService = null; | ||||
| let shellAudioSelectionDBusService = null; | ||||
| let shellDBusService = null; | ||||
| let shellMountOpDBusService = null; | ||||
| let screenSaverDBus = null; | ||||
| @@ -124,8 +120,6 @@ function start() { | ||||
|                                        _loadDefaultStylesheet); | ||||
|     _initializeUI(); | ||||
|  | ||||
|     shellAccessDialogDBusService = new AccessDialog.AccessDialogDBus(); | ||||
|     shellAudioSelectionDBusService = new AudioDeviceSelection.AudioDeviceSelectionDBus(); | ||||
|     shellDBusService = new ShellDBus.GnomeShell(); | ||||
|     shellMountOpDBusService = new ShellMountOperation.GnomeShellMountOpHandler(); | ||||
|  | ||||
| @@ -194,8 +188,6 @@ function _initializeUI() { | ||||
|         return true; | ||||
|     }); | ||||
|  | ||||
|     global.display.connect('gl-video-memory-purged', loadTheme); | ||||
|  | ||||
|     // Provide the bus object for gnome-session to | ||||
|     // initiate logouts. | ||||
|     EndSessionDialog.init(); | ||||
|   | ||||
| @@ -1,726 +0,0 @@ | ||||
| const Atk = imports.gi.Atk; | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Gio = imports.gi.Gio; | ||||
| const GLib = imports.gi.GLib; | ||||
| const GObject = imports.gi.GObject; | ||||
| const Lang = imports.lang; | ||||
| const Main = imports.ui.main; | ||||
| const MessageTray = imports.ui.messageTray; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Pango = imports.gi.Pango; | ||||
| const Signals = imports.signals; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const Calendar = imports.ui.calendar; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const Util = imports.misc.util; | ||||
|  | ||||
| const MESSAGE_ANIMATION_TIME = 0.1; | ||||
|  | ||||
| const DEFAULT_EXPAND_LINES = 6; | ||||
|  | ||||
| function _fixMarkup(text, allowMarkup) { | ||||
|     if (allowMarkup) { | ||||
|         // Support &, ", ', < and >, escape all other | ||||
|         // occurrences of '&'. | ||||
|         let _text = text.replace(/&(?!amp;|quot;|apos;|lt;|gt;)/g, '&'); | ||||
|  | ||||
|         // Support <b>, <i>, and <u>, escape anything else | ||||
|         // so it displays as raw markup. | ||||
|         _text = _text.replace(/<(?!\/?[biu]>)/g, '<'); | ||||
|  | ||||
|         try { | ||||
|             Pango.parse_markup(_text, -1, ''); | ||||
|             return _text; | ||||
|         } catch (e) {} | ||||
|     } | ||||
|  | ||||
|     // !allowMarkup, or invalid markup | ||||
|     return GLib.markup_escape_text(text, -1); | ||||
| } | ||||
|  | ||||
| const URLHighlighter = new Lang.Class({ | ||||
|     Name: 'URLHighlighter', | ||||
|  | ||||
|     _init: function(text, lineWrap, allowMarkup) { | ||||
|         if (!text) | ||||
|             text = ''; | ||||
|         this.actor = new St.Label({ reactive: true, style_class: 'url-highlighter', | ||||
|                                     x_expand: true, x_align: Clutter.ActorAlign.START }); | ||||
|         this._linkColor = '#ccccff'; | ||||
|         this.actor.connect('style-changed', Lang.bind(this, function() { | ||||
|             let [hasColor, color] = this.actor.get_theme_node().lookup_color('link-color', false); | ||||
|             if (hasColor) { | ||||
|                 let linkColor = color.to_string().substr(0, 7); | ||||
|                 if (linkColor != this._linkColor) { | ||||
|                     this._linkColor = linkColor; | ||||
|                     this._highlightUrls(); | ||||
|                 } | ||||
|             } | ||||
|         })); | ||||
|         this.actor.clutter_text.line_wrap = lineWrap; | ||||
|         this.actor.clutter_text.line_wrap_mode = Pango.WrapMode.WORD_CHAR; | ||||
|  | ||||
|         this.setMarkup(text, allowMarkup); | ||||
|         this.actor.connect('button-press-event', Lang.bind(this, function(actor, event) { | ||||
|             // Don't try to URL highlight when invisible. | ||||
|             // The MessageTray doesn't actually hide us, so | ||||
|             // we need to check for paint opacities as well. | ||||
|             if (!actor.visible || actor.get_paint_opacity() == 0) | ||||
|                 return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|             // Keep Notification.actor from seeing this and taking | ||||
|             // a pointer grab, which would block our button-release-event | ||||
|             // handler, if an URL is clicked | ||||
|             return this._findUrlAtPos(event) != -1; | ||||
|         })); | ||||
|         this.actor.connect('button-release-event', Lang.bind(this, function (actor, event) { | ||||
|             if (!actor.visible || actor.get_paint_opacity() == 0) | ||||
|                 return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|             let urlId = this._findUrlAtPos(event); | ||||
|             if (urlId != -1) { | ||||
|                 let url = this._urls[urlId].url; | ||||
|                 if (url.indexOf(':') == -1) | ||||
|                     url = 'http://' + url; | ||||
|  | ||||
|                 Gio.app_info_launch_default_for_uri(url, global.create_app_launch_context(0, -1)); | ||||
|                 return Clutter.EVENT_STOP; | ||||
|             } | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|         })); | ||||
|         this.actor.connect('motion-event', Lang.bind(this, function(actor, event) { | ||||
|             if (!actor.visible || actor.get_paint_opacity() == 0) | ||||
|                 return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|             let urlId = this._findUrlAtPos(event); | ||||
|             if (urlId != -1 && !this._cursorChanged) { | ||||
|                 global.screen.set_cursor(Meta.Cursor.POINTING_HAND); | ||||
|                 this._cursorChanged = true; | ||||
|             } else if (urlId == -1) { | ||||
|                 global.screen.set_cursor(Meta.Cursor.DEFAULT); | ||||
|                 this._cursorChanged = false; | ||||
|             } | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|         })); | ||||
|         this.actor.connect('leave-event', Lang.bind(this, function() { | ||||
|             if (!this.actor.visible || this.actor.get_paint_opacity() == 0) | ||||
|                 return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|             if (this._cursorChanged) { | ||||
|                 this._cursorChanged = false; | ||||
|                 global.screen.set_cursor(Meta.Cursor.DEFAULT); | ||||
|             } | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     setMarkup: function(text, allowMarkup) { | ||||
|         text = text ? _fixMarkup(text, allowMarkup) : ''; | ||||
|         this._text = text; | ||||
|  | ||||
|         this.actor.clutter_text.set_markup(text); | ||||
|         /* clutter_text.text contain text without markup */ | ||||
|         this._urls = Util.findUrls(this.actor.clutter_text.text); | ||||
|         this._highlightUrls(); | ||||
|     }, | ||||
|  | ||||
|     _highlightUrls: function() { | ||||
|         // text here contain markup | ||||
|         let urls = Util.findUrls(this._text); | ||||
|         let markup = ''; | ||||
|         let pos = 0; | ||||
|         for (let i = 0; i < urls.length; i++) { | ||||
|             let url = urls[i]; | ||||
|             let str = this._text.substr(pos, url.pos - pos); | ||||
|             markup += str + '<span foreground="' + this._linkColor + '"><u>' + url.url + '</u></span>'; | ||||
|             pos = url.pos + url.url.length; | ||||
|         } | ||||
|         markup += this._text.substr(pos); | ||||
|         this.actor.clutter_text.set_markup(markup); | ||||
|     }, | ||||
|  | ||||
|     _findUrlAtPos: function(event) { | ||||
|         let success; | ||||
|         let [x, y] = event.get_coords(); | ||||
|         [success, x, y] = this.actor.transform_stage_point(x, y); | ||||
|         let find_pos = -1; | ||||
|         for (let i = 0; i < this.actor.clutter_text.text.length; i++) { | ||||
|             let [success, px, py, line_height] = this.actor.clutter_text.position_to_coords(i); | ||||
|             if (py > y || py + line_height < y || x < px) | ||||
|                 continue; | ||||
|             find_pos = i; | ||||
|         } | ||||
|         if (find_pos != -1) { | ||||
|             for (let i = 0; i < this._urls.length; i++) | ||||
|             if (find_pos >= this._urls[i].pos && | ||||
|                 this._urls[i].pos + this._urls[i].url.length > find_pos) | ||||
|                 return i; | ||||
|         } | ||||
|         return -1; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const ScaleLayout = new Lang.Class({ | ||||
|     Name: 'ScaleLayout', | ||||
|     Extends: Clutter.BinLayout, | ||||
|  | ||||
|     _connectContainer: function(container) { | ||||
|         if (this._container == container) | ||||
|             return; | ||||
|  | ||||
|         if (this._container) | ||||
|             for (let id of this._signals) | ||||
|                 this._container.disconnect(id); | ||||
|  | ||||
|         this._container = container; | ||||
|         this._signals = []; | ||||
|  | ||||
|         if (this._container) | ||||
|             for (let signal of ['notify::scale-x', 'notify::scale-y']) { | ||||
|                 let id = this._container.connect(signal, Lang.bind(this, | ||||
|                     function() { | ||||
|                         this.layout_changed(); | ||||
|                     })); | ||||
|                 this._signals.push(id); | ||||
|             } | ||||
|     }, | ||||
|  | ||||
|     vfunc_get_preferred_width: function(container, forHeight) { | ||||
|         this._connectContainer(container); | ||||
|  | ||||
|         let [min, nat] = this.parent(container, forHeight); | ||||
|         return [Math.floor(min * container.scale_x), | ||||
|                 Math.floor(nat * container.scale_x)]; | ||||
|     }, | ||||
|  | ||||
|     vfunc_get_preferred_height: function(container, forWidth) { | ||||
|         this._connectContainer(container); | ||||
|  | ||||
|         let [min, nat] = this.parent(container, forWidth); | ||||
|         return [Math.floor(min * container.scale_y), | ||||
|                 Math.floor(nat * container.scale_y)]; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const LabelExpanderLayout = new Lang.Class({ | ||||
|     Name: 'LabelExpanderLayout', | ||||
|     Extends: Clutter.LayoutManager, | ||||
|     Properties: { 'expansion': GObject.ParamSpec.double('expansion', | ||||
|                                                         'Expansion', | ||||
|                                                         'Expansion of the layout, between 0 (collapsed) ' + | ||||
|                                                         'and 1 (fully expanded', | ||||
|                                                          GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE, | ||||
|                                                          0, 1, 0)}, | ||||
|  | ||||
|     _init: function(params) { | ||||
|         this._expansion = 0; | ||||
|         this._expandLines = DEFAULT_EXPAND_LINES; | ||||
|  | ||||
|         this.parent(params); | ||||
|     }, | ||||
|  | ||||
|     get expansion() { | ||||
|         return this._expansion; | ||||
|     }, | ||||
|  | ||||
|     set expansion(v) { | ||||
|         if (v == this._expansion) | ||||
|             return; | ||||
|         this._expansion = v; | ||||
|         this.notify('expansion'); | ||||
|  | ||||
|         let visibleIndex = this._expansion > 0 ? 1 : 0; | ||||
|         for (let i = 0; this._container && i < this._container.get_n_children(); i++) | ||||
|             this._container.get_child_at_index(i).visible = (i == visibleIndex); | ||||
|  | ||||
|         this.layout_changed(); | ||||
|     }, | ||||
|  | ||||
|     set expandLines(v) { | ||||
|         if (v == this._expandLines) | ||||
|             return; | ||||
|         this._expandLines = v; | ||||
|         if (this._expansion > 0) | ||||
|             this.layout_changed(); | ||||
|     }, | ||||
|  | ||||
|     vfunc_set_container: function(container) { | ||||
|         this._container = container; | ||||
|     }, | ||||
|  | ||||
|     vfunc_get_preferred_width: function(container, forHeight) { | ||||
|         let [min, nat] = [0, 0]; | ||||
|  | ||||
|         for (let i = 0; i < container.get_n_children(); i++) { | ||||
|             if (i > 1) | ||||
|                 break; // we support one unexpanded + one expanded child | ||||
|  | ||||
|             let child = container.get_child_at_index(i); | ||||
|             let [childMin, childNat] = child.get_preferred_width(forHeight); | ||||
|             [min, nat] = [Math.max(min, childMin), Math.max(nat, childNat)]; | ||||
|         } | ||||
|  | ||||
|         return [min, nat]; | ||||
|     }, | ||||
|  | ||||
|     vfunc_get_preferred_height: function(container, forWidth) { | ||||
|         let [min, nat] = [0, 0]; | ||||
|  | ||||
|         let children = container.get_children(); | ||||
|         if (children[0]) | ||||
|             [min, nat] = children[0].get_preferred_height(forWidth); | ||||
|  | ||||
|         if (children[1]) { | ||||
|             let [min2, nat2] = children[1].get_preferred_height(forWidth); | ||||
|             let [expMin, expNat] = [Math.min(min2, min * this._expandLines), | ||||
|                                     Math.min(nat2, nat * this._expandLines)]; | ||||
|             [min, nat] = [min + this._expansion * (expMin - min), | ||||
|                           nat + this._expansion * (expNat - nat)]; | ||||
|         } | ||||
|  | ||||
|         return [min, nat]; | ||||
|     }, | ||||
|  | ||||
|     vfunc_allocate: function(container, box, flags) { | ||||
|         for (let i = 0; i < container.get_n_children(); i++) { | ||||
|             let child = container.get_child_at_index(i); | ||||
|  | ||||
|             if (child.visible) | ||||
|                 child.allocate(box, flags); | ||||
|         } | ||||
|  | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const Message = new Lang.Class({ | ||||
|     Name: 'Message', | ||||
|  | ||||
|     _init: function(title, body) { | ||||
|         this.expanded = false; | ||||
|  | ||||
|         this.actor = new St.Button({ style_class: 'message', | ||||
|                                      accessible_role: Atk.Role.NOTIFICATION, | ||||
|                                      can_focus: true, | ||||
|                                      x_expand: true, x_fill: true }); | ||||
|         this.actor.connect('key-press-event', | ||||
|                            Lang.bind(this, this._onKeyPressed)); | ||||
|  | ||||
|         let vbox = new St.BoxLayout({ vertical: true }); | ||||
|         this.actor.set_child(vbox); | ||||
|  | ||||
|         let hbox = new St.BoxLayout(); | ||||
|         vbox.add_actor(hbox); | ||||
|  | ||||
|         this._actionBin = new St.Widget({ layout_manager: new ScaleLayout(), | ||||
|                                           visible: false }); | ||||
|         vbox.add_actor(this._actionBin); | ||||
|  | ||||
|         this._iconBin = new St.Bin({ style_class: 'message-icon-bin', | ||||
|                                      y_expand: true, | ||||
|                                      visible: false }); | ||||
|         hbox.add_actor(this._iconBin); | ||||
|  | ||||
|         let contentBox = new St.BoxLayout({ style_class: 'message-content', | ||||
|                                             vertical: true, x_expand: true }); | ||||
|         hbox.add_actor(contentBox); | ||||
|  | ||||
|         this._mediaControls = new St.BoxLayout(); | ||||
|         hbox.add_actor(this._mediaControls); | ||||
|  | ||||
|         let titleBox = new St.BoxLayout(); | ||||
|         contentBox.add_actor(titleBox); | ||||
|  | ||||
|         this.titleLabel = new St.Label({ style_class: 'message-title', | ||||
|                                          x_expand: true, | ||||
|                                          x_align: Clutter.ActorAlign.START }); | ||||
|         this.setTitle(title); | ||||
|         titleBox.add_actor(this.titleLabel); | ||||
|  | ||||
|         this._secondaryBin = new St.Bin({ style_class: 'message-secondary-bin' }); | ||||
|         titleBox.add_actor(this._secondaryBin); | ||||
|  | ||||
|         let closeIcon = new St.Icon({ icon_name: 'window-close-symbolic', | ||||
|                                       icon_size: 16 }); | ||||
|         this._closeButton = new St.Button({ child: closeIcon, visible: false }); | ||||
|         titleBox.add_actor(this._closeButton); | ||||
|  | ||||
|         this._bodyStack = new St.Widget({ x_expand: true }); | ||||
|         this._bodyStack.layout_manager = new LabelExpanderLayout(); | ||||
|         contentBox.add_actor(this._bodyStack); | ||||
|  | ||||
|         this.bodyLabel = new URLHighlighter('', false, this._useBodyMarkup); | ||||
|         this.bodyLabel.actor.add_style_class_name('message-body'); | ||||
|         this._bodyStack.add_actor(this.bodyLabel.actor); | ||||
|         this.setBody(body); | ||||
|  | ||||
|         this._closeButton.connect('clicked', Lang.bind(this, this.close)); | ||||
|         this.actor.connect('notify::hover', Lang.bind(this, this._sync)); | ||||
|         this.actor.connect('clicked', Lang.bind(this, this._onClicked)); | ||||
|         this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | ||||
|         this._sync(); | ||||
|     }, | ||||
|  | ||||
|     close: function() { | ||||
|         this.emit('close'); | ||||
|     }, | ||||
|  | ||||
|     setIcon: function(actor) { | ||||
|         this._iconBin.child = actor; | ||||
|         this._iconBin.visible = (actor != null); | ||||
|     }, | ||||
|  | ||||
|     setSecondaryActor: function(actor) { | ||||
|         this._secondaryBin.child = actor; | ||||
|     }, | ||||
|  | ||||
|     setTitle: function(text) { | ||||
|         let title = text ? _fixMarkup(text.replace(/\n/g, ' '), false) : ''; | ||||
|         this.titleLabel.clutter_text.set_markup(title); | ||||
|     }, | ||||
|  | ||||
|     setBody: function(text) { | ||||
|         this._bodyText = text; | ||||
|         this.bodyLabel.setMarkup(text ? text.replace(/\n/g, ' ') : '', | ||||
|                                  this._useBodyMarkup); | ||||
|         if (this._expandedLabel) | ||||
|             this._expandedLabel.setMarkup(text, this._useBodyMarkup); | ||||
|     }, | ||||
|  | ||||
|     setUseBodyMarkup: function(enable) { | ||||
|         if (this._useBodyMarkup === enable) | ||||
|             return; | ||||
|         this._useBodyMarkup = enable; | ||||
|         if (this.bodyLabel) | ||||
|             this.setBody(this._bodyText); | ||||
|     }, | ||||
|  | ||||
|     setActionArea: function(actor) { | ||||
|         if (actor == null) { | ||||
|             if (this._actionBin.get_n_children() > 0) | ||||
|                 this._actionBin.get_child_at_index(0).destroy(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (this._actionBin.get_n_children() > 0) | ||||
|             throw new Error('Message already has an action area'); | ||||
|  | ||||
|         this._actionBin.add_actor(actor); | ||||
|         this._actionBin.visible = this.expanded; | ||||
|     }, | ||||
|  | ||||
|     addMediaControl: function(iconName, callback) { | ||||
|         let icon = new St.Icon({ icon_name: iconName, icon_size: 16 }); | ||||
|         let button = new St.Button({ style_class: 'message-media-control', | ||||
|                                      child: icon }); | ||||
|         button.connect('clicked', callback); | ||||
|         this._mediaControls.add_actor(button); | ||||
|         return button; | ||||
|     }, | ||||
|  | ||||
|     setExpandedBody: function(actor) { | ||||
|         if (actor == null) { | ||||
|             if (this._bodyStack.get_n_children() > 1) | ||||
|                 this._bodyStack.get_child_at_index(1).destroy(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (this._bodyStack.get_n_children() > 1) | ||||
|             throw new Error('Message already has an expanded body actor'); | ||||
|  | ||||
|         this._bodyStack.insert_child_at_index(actor, 1); | ||||
|     }, | ||||
|  | ||||
|     setExpandedLines: function(nLines) { | ||||
|         this._bodyStack.layout_manager.expandLines = nLines; | ||||
|     }, | ||||
|  | ||||
|     expand: function(animate) { | ||||
|         this.expanded = true; | ||||
|  | ||||
|         this._actionBin.visible = (this._actionBin.get_n_children() > 0); | ||||
|  | ||||
|         if (this._bodyStack.get_n_children() < 2) { | ||||
|             this._expandedLabel = new URLHighlighter(this._bodyText, | ||||
|                                                      true, this._useBodyMarkup); | ||||
|             this.setExpandedBody(this._expandedLabel.actor); | ||||
|         } | ||||
|  | ||||
|         if (animate) { | ||||
|             Tweener.addTween(this._bodyStack.layout_manager, | ||||
|                              { expansion: 1, | ||||
|                                time: MessageTray.ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad' }); | ||||
|             this._actionBin.scale_y = 0; | ||||
|             Tweener.addTween(this._actionBin, | ||||
|                              { scale_y: 1, | ||||
|                                time: MessageTray.ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad' }); | ||||
|         } else { | ||||
|             this._bodyStack.layout_manager.expansion = 1; | ||||
|             this._actionBin.scale_y = 1; | ||||
|         } | ||||
|  | ||||
|         this.emit('expanded'); | ||||
|     }, | ||||
|  | ||||
|     unexpand: function(animate) { | ||||
|         if (animate) { | ||||
|             Tweener.addTween(this._bodyStack.layout_manager, | ||||
|                              { expansion: 0, | ||||
|                                time: MessageTray.ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad' }); | ||||
|             Tweener.addTween(this._actionBin, | ||||
|                              { scale_y: 0, | ||||
|                                time: MessageTray.ANIMATION_TIME, | ||||
|                                transition: 'easeOutQuad', | ||||
|                                onCompleteScope: this, | ||||
|                                onComplete: function() { | ||||
|                                    this._actionBin.hide(); | ||||
|                                    this.expanded = false; | ||||
|                                }}); | ||||
|         } else { | ||||
|             this._bodyStack.layout_manager.expansion = 0; | ||||
|             this._actionBin.scale_y = 0; | ||||
|             this.expanded = false; | ||||
|         } | ||||
|  | ||||
|         this.emit('unexpanded'); | ||||
|     }, | ||||
|  | ||||
|     canClose: function() { | ||||
|         return this._mediaControls.get_n_children() == 0; | ||||
|     }, | ||||
|  | ||||
|     _sync: function() { | ||||
|         let hovered = this.actor.hover; | ||||
|         this._closeButton.visible = hovered && this.canClose(); | ||||
|         this._secondaryBin.visible = !hovered; | ||||
|     }, | ||||
|  | ||||
|     _onClicked: function() { | ||||
|     }, | ||||
|  | ||||
|     _onDestroy: function() { | ||||
|     }, | ||||
|  | ||||
|     _onKeyPressed: function(a, event) { | ||||
|         let keysym = event.get_key_symbol(); | ||||
|  | ||||
|         if (keysym == Clutter.KEY_Delete || | ||||
|             keysym == Clutter.KEY_KP_Delete) { | ||||
|             this.close(); | ||||
|             return Clutter.EVENT_STOP; | ||||
|         } | ||||
|         return Clutter.EVENT_PROPAGATE; | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(Message.prototype); | ||||
|  | ||||
| const MessageListSection = new Lang.Class({ | ||||
|     Name: 'MessageListSection', | ||||
|  | ||||
|     _init: function(title) { | ||||
|         this.actor = new St.BoxLayout({ style_class: 'message-list-section', | ||||
|                                         clip_to_allocation: true, | ||||
|                                         x_expand: true, vertical: true }); | ||||
|         let titleBox = new St.BoxLayout({ style_class: 'message-list-section-title-box' }); | ||||
|         this.actor.add_actor(titleBox); | ||||
|  | ||||
|         this._title = new St.Button({ style_class: 'message-list-section-title', | ||||
|                                       label: title, | ||||
|                                       can_focus: true, | ||||
|                                       x_expand: true, | ||||
|                                       x_align: St.Align.START }); | ||||
|         titleBox.add_actor(this._title); | ||||
|  | ||||
|         this._title.connect('clicked', Lang.bind(this, this._onTitleClicked)); | ||||
|         this._title.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn)); | ||||
|  | ||||
|         let closeIcon = new St.Icon({ icon_name: 'window-close-symbolic' }); | ||||
|         this._closeButton = new St.Button({ style_class: 'message-list-section-close', | ||||
|                                             child: closeIcon, | ||||
|                                             accessible_name: _("Clear section"), | ||||
|                                             can_focus: true }); | ||||
|         this._closeButton.set_x_align(Clutter.ActorAlign.END); | ||||
|         titleBox.add_actor(this._closeButton); | ||||
|  | ||||
|         this._closeButton.connect('clicked', Lang.bind(this, this.clear)); | ||||
|  | ||||
|         this._list = new St.BoxLayout({ style_class: 'message-list-section-list', | ||||
|                                         vertical: true }); | ||||
|         this.actor.add_actor(this._list); | ||||
|  | ||||
|         this._list.connect('actor-added', Lang.bind(this, this._sync)); | ||||
|         this._list.connect('actor-removed', Lang.bind(this, this._sync)); | ||||
|  | ||||
|         let id = Main.sessionMode.connect('updated', | ||||
|                                           Lang.bind(this, this._sync)); | ||||
|         this.actor.connect('destroy', function() { | ||||
|             Main.sessionMode.disconnect(id); | ||||
|         }); | ||||
|  | ||||
|         this._messages = new Map(); | ||||
|         this._date = new Date(); | ||||
|         this.empty = true; | ||||
|         this._sync(); | ||||
|     }, | ||||
|  | ||||
|     _onTitleClicked: function() { | ||||
|         Main.overview.hide(); | ||||
|         Main.panel.closeCalendar(); | ||||
|     }, | ||||
|  | ||||
|     _onKeyFocusIn: function(actor) { | ||||
|         this.emit('key-focus-in', actor); | ||||
|     }, | ||||
|  | ||||
|     get allowed() { | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     setDate: function(date) { | ||||
|         if (Calendar.sameDay(date, this._date)) | ||||
|             return; | ||||
|         this._date = date; | ||||
|         this._sync(); | ||||
|     }, | ||||
|  | ||||
|     addMessage: function(message, animate) { | ||||
|         this.addMessageAtIndex(message, -1, animate); | ||||
|     }, | ||||
|  | ||||
|     addMessageAtIndex: function(message, index, animate) { | ||||
|         let obj = { | ||||
|             container: null, | ||||
|             destroyId: 0, | ||||
|             keyFocusId: 0, | ||||
|             closeId: 0 | ||||
|         }; | ||||
|         let pivot = new Clutter.Point({ x: .5, y: .5 }); | ||||
|         let scale = animate ? 0 : 1; | ||||
|         obj.container = new St.Widget({ layout_manager: new ScaleLayout(), | ||||
|                                         pivot_point: pivot, | ||||
|                                         scale_x: scale, scale_y: scale }); | ||||
|         obj.keyFocusId = message.actor.connect('key-focus-in', | ||||
|             Lang.bind(this, this._onKeyFocusIn)); | ||||
|         obj.destroyId = message.actor.connect('destroy', | ||||
|             Lang.bind(this, function() { | ||||
|                 this.removeMessage(message, false); | ||||
|             })); | ||||
|         obj.closeId = message.connect('close', | ||||
|             Lang.bind(this, function() { | ||||
|                 this.removeMessage(message, true); | ||||
|             })); | ||||
|  | ||||
|         this._messages.set(message, obj); | ||||
|         obj.container.add_actor(message.actor); | ||||
|  | ||||
|         this._list.insert_child_at_index(obj.container, index); | ||||
|  | ||||
|         if (animate) | ||||
|             Tweener.addTween(obj.container, { scale_x: 1, | ||||
|                                               scale_y: 1, | ||||
|                                               time: MESSAGE_ANIMATION_TIME, | ||||
|                                               transition: 'easeOutQuad' }); | ||||
|     }, | ||||
|  | ||||
|     moveMessage: function(message, index, animate) { | ||||
|         let obj = this._messages.get(message); | ||||
|  | ||||
|         if (!animate) { | ||||
|             this._list.set_child_at_index(obj.container, index); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let onComplete = Lang.bind(this, function() { | ||||
|             this._list.set_child_at_index(obj.container, index); | ||||
|             Tweener.addTween(obj.container, { scale_x: 1, | ||||
|                                               scale_y: 1, | ||||
|                                               time: MESSAGE_ANIMATION_TIME, | ||||
|                                               transition: 'easeOutQuad' }); | ||||
|         }); | ||||
|         Tweener.addTween(obj.container, { scale_x: 0, | ||||
|                                           scale_y: 0, | ||||
|                                           time: MESSAGE_ANIMATION_TIME, | ||||
|                                           transition: 'easeOutQuad', | ||||
|                                           onComplete: onComplete }); | ||||
|     }, | ||||
|  | ||||
|     removeMessage: function(message, animate) { | ||||
|         let obj = this._messages.get(message); | ||||
|  | ||||
|         message.actor.disconnect(obj.destroyId); | ||||
|         message.actor.disconnect(obj.keyFocusId); | ||||
|         message.disconnect(obj.closeId); | ||||
|  | ||||
|         this._messages.delete(message); | ||||
|  | ||||
|         if (animate) { | ||||
|             Tweener.addTween(obj.container, { scale_x: 0, scale_y: 0, | ||||
|                                               time: MESSAGE_ANIMATION_TIME, | ||||
|                                               transition: 'easeOutQuad', | ||||
|                                               onComplete: function() { | ||||
|                                                   obj.container.destroy(); | ||||
|                                                   global.sync_pointer(); | ||||
|                                               }}); | ||||
|         } else { | ||||
|             obj.container.destroy(); | ||||
|             global.sync_pointer(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     clear: function() { | ||||
|         let messages = [...this._messages.keys()].filter(function(message) { | ||||
|             return message.canClose(); | ||||
|         }); | ||||
|  | ||||
|         // If there are few messages, letting them all zoom out looks OK | ||||
|         if (messages.length < 2) { | ||||
|             messages.forEach(function(message) { | ||||
|                 message.close(); | ||||
|             }); | ||||
|         } else { | ||||
|             // Otherwise we slide them out one by one, and then zoom them | ||||
|             // out "off-screen" in the end to smoothly shrink the parent | ||||
|             let delay = MESSAGE_ANIMATION_TIME / Math.max(messages.length, 5); | ||||
|             for (let i = 0; i < messages.length; i++) { | ||||
|                 let message = messages[i]; | ||||
|                 let obj = this._messages.get(message); | ||||
|                 Tweener.addTween(obj.container, | ||||
|                                  { anchor_x: this._list.width, | ||||
|                                    opacity: 0, | ||||
|                                    time: MESSAGE_ANIMATION_TIME, | ||||
|                                    delay: i * delay, | ||||
|                                    transition: 'easeOutQuad', | ||||
|                                    onComplete: function() { | ||||
|                                        message.close(); | ||||
|                                    }}); | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _canClear: function() { | ||||
|         for (let message of this._messages.keys()) | ||||
|             if (message.canClose()) | ||||
|                 return true; | ||||
|         return false; | ||||
|     }, | ||||
|  | ||||
|     _shouldShow: function() { | ||||
|         return !this.empty; | ||||
|     }, | ||||
|  | ||||
|     _sync: function() { | ||||
|         let empty = this._list.get_n_children() == 0; | ||||
|         let changed = this.empty !== empty; | ||||
|         this.empty = empty; | ||||
|  | ||||
|         if (changed) | ||||
|             this.emit('empty-changed'); | ||||
|  | ||||
|         this._closeButton.visible = this._canClear(); | ||||
|         this.actor.visible = this.allowed && this._shouldShow(); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(MessageListSection.prototype); | ||||
| @@ -259,7 +259,7 @@ const ModalDialog = new Lang.Class({ | ||||
|         if (this.state == State.OPENED || this.state == State.OPENING) | ||||
|             return true; | ||||
|  | ||||
|         if (!this.pushModal(timestamp)) | ||||
|         if (!this.pushModal({ timestamp: timestamp })) | ||||
|             return false; | ||||
|  | ||||
|         this._fadeOpen(onPrimary); | ||||
| @@ -318,11 +318,8 @@ const ModalDialog = new Lang.Class({ | ||||
|     pushModal: function (timestamp) { | ||||
|         if (this._hasModal) | ||||
|             return true; | ||||
|  | ||||
|         let params = { actionMode: this._actionMode }; | ||||
|         if (timestamp) | ||||
|             params['timestamp'] = timestamp; | ||||
|         if (!Main.pushModal(this._group, params)) | ||||
|         if (!Main.pushModal(this._group, { timestamp: timestamp, | ||||
|                                            actionMode: this._actionMode })) | ||||
|             return false; | ||||
|  | ||||
|         this._hasModal = true; | ||||
|   | ||||
							
								
								
									
										270
									
								
								js/ui/mpris.js
									
									
									
									
									
								
							
							
						
						
									
										270
									
								
								js/ui/mpris.js
									
									
									
									
									
								
							| @@ -1,270 +0,0 @@ | ||||
| const Gio = imports.gi.Gio; | ||||
| const Lang = imports.lang; | ||||
| const Signals = imports.signals; | ||||
| const Shell = imports.gi.Shell; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const Calendar = imports.ui.calendar; | ||||
| const Main = imports.ui.main; | ||||
| const MessageList = imports.ui.messageList; | ||||
|  | ||||
| const DBusIface = '<node> \ | ||||
| <interface name="org.freedesktop.DBus"> \ | ||||
|   <method name="ListNames"> \ | ||||
|     <arg type="as" direction="out" name="names" /> \ | ||||
|   </method> \ | ||||
|   <signal name="NameOwnerChanged"> \ | ||||
|     <arg type="s" direction="out" name="name" /> \ | ||||
|     <arg type="s" direction="out" name="oldOwner" /> \ | ||||
|     <arg type="s" direction="out" name="newOwner" /> \ | ||||
|   </signal> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
| const DBusProxy = Gio.DBusProxy.makeProxyWrapper(DBusIface); | ||||
|  | ||||
| const MprisIface = '<node> \ | ||||
| <interface name="org.mpris.MediaPlayer2"> \ | ||||
|   <method name="Raise" /> \ | ||||
|   <property name="CanRaise" type="b" access="read" /> \ | ||||
|   <property name="DesktopEntry" type="s" access="read" /> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
| const MprisProxy = Gio.DBusProxy.makeProxyWrapper(MprisIface); | ||||
|  | ||||
| const MprisPlayerIface = '<node> \ | ||||
| <interface name="org.mpris.MediaPlayer2.Player"> \ | ||||
|   <method name="PlayPause" /> \ | ||||
|   <method name="Next" /> \ | ||||
|   <method name="Previous" /> \ | ||||
|   <property name="CanPlay" type="b" access="read" /> \ | ||||
|   <property name="Metadata" type="a{sv}" access="read" /> \ | ||||
|   <property name="PlaybackStatus" type="s" access="read" /> \ | ||||
| </interface> \ | ||||
| </node>'; | ||||
| const MprisPlayerProxy = Gio.DBusProxy.makeProxyWrapper(MprisPlayerIface); | ||||
|  | ||||
| const MPRIS_PLAYER_PREFIX = 'org.mpris.MediaPlayer2.'; | ||||
|  | ||||
| const MediaMessage = new Lang.Class({ | ||||
|     Name: 'MediaMessage', | ||||
|     Extends: MessageList.Message, | ||||
|  | ||||
|     _init: function(player) { | ||||
|         this._player = player; | ||||
|  | ||||
|         this.parent('', ''); | ||||
|  | ||||
|         this._icon = new St.Icon({ style_class: 'media-message-cover-icon' }); | ||||
|         this.setIcon(this._icon); | ||||
|  | ||||
|         this.addMediaControl('media-skip-backward-symbolic', | ||||
|             Lang.bind(this, function() { | ||||
|                 this._player.previous(); | ||||
|             })); | ||||
|  | ||||
|         this._playPauseButton = this.addMediaControl(null, | ||||
|             Lang.bind(this, function() { | ||||
|                 this._player.playPause(); | ||||
|             })); | ||||
|  | ||||
|         this.addMediaControl('media-skip-forward-symbolic', | ||||
|             Lang.bind(this, function() { | ||||
|                 this._player.next(); | ||||
|             })); | ||||
|  | ||||
|         this._player.connect('changed', Lang.bind(this, this._update)); | ||||
|         this._player.connect('closed', Lang.bind(this, this.close)); | ||||
|         this._update(); | ||||
|     }, | ||||
|  | ||||
|     _onClicked: function() { | ||||
|         this._player.raise(); | ||||
|         Main.panel.closeCalendar(); | ||||
|     }, | ||||
|  | ||||
|     _update: function() { | ||||
|         this.setTitle(this._player.trackArtists.join(', ')); | ||||
|         this.setBody(this._player.trackTitle); | ||||
|  | ||||
|         if (this._player.trackCoverUrl) { | ||||
|             let file = Gio.File.new_for_uri(this._player.trackCoverUrl); | ||||
|             this._icon.gicon = new Gio.FileIcon({ file: file }); | ||||
|             this._icon.remove_style_class_name('fallback'); | ||||
|         } else { | ||||
|             this._icon.icon_name = 'audio-x-generic-symbolic'; | ||||
|             this._icon.add_style_class_name('fallback'); | ||||
|         } | ||||
|  | ||||
|         let isPlaying = this._player.status == 'Playing'; | ||||
|         let iconName = isPlaying ? 'media-playback-pause-symbolic' | ||||
|                                  : 'media-playback-start-symbolic'; | ||||
|         this._playPauseButton.child.icon_name = iconName; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const MprisPlayer = new Lang.Class({ | ||||
|     Name: 'MprisPlayer', | ||||
|  | ||||
|     _init: function(busName) { | ||||
|         this._mprisProxy = new MprisProxy(Gio.DBus.session, busName, | ||||
|                                           '/org/mpris/MediaPlayer2', | ||||
|                                           Lang.bind(this, this._onMprisProxyReady)); | ||||
|         this._playerProxy = new MprisPlayerProxy(Gio.DBus.session, busName, | ||||
|                                                  '/org/mpris/MediaPlayer2', | ||||
|                                                  Lang.bind(this, this._onPlayerProxyReady)); | ||||
|  | ||||
|         this._visible = false; | ||||
|         this._trackArtists = []; | ||||
|         this._trackTitle = ''; | ||||
|         this._trackCoverUrl = ''; | ||||
|     }, | ||||
|  | ||||
|     get status() { | ||||
|         return this._playerProxy.PlaybackStatus; | ||||
|     }, | ||||
|  | ||||
|     get trackArtists() { | ||||
|         return this._trackArtists; | ||||
|     }, | ||||
|  | ||||
|     get trackTitle() { | ||||
|         return this._trackTitle; | ||||
|     }, | ||||
|  | ||||
|     get trackCoverUrl() { | ||||
|         return this._trackCoverUrl; | ||||
|     }, | ||||
|  | ||||
|     playPause: function() { | ||||
|         this._playerProxy.PlayPauseRemote(); | ||||
|     }, | ||||
|  | ||||
|     next: function() { | ||||
|         this._playerProxy.NextRemote(); | ||||
|     }, | ||||
|  | ||||
|     previous: function() { | ||||
|         this._playerProxy.PreviousRemote(); | ||||
|     }, | ||||
|  | ||||
|     raise: function() { | ||||
|         // The remote Raise() method may run into focus stealing prevention, | ||||
|         // so prefer activating the app via .desktop file if possible | ||||
|         let app = null; | ||||
|         if (this._mprisProxy.DesktopEntry) { | ||||
|             let desktopId = this._mprisProxy.DesktopEntry + '.desktop'; | ||||
|             app = Shell.AppSystem.get_default().lookup_app(desktopId); | ||||
|         } | ||||
|  | ||||
|         if (app) | ||||
|             app.activate(); | ||||
|         else if (this._mprisProxy.CanRaise) | ||||
|             this._mprisProxy.RaiseRemote(); | ||||
|     }, | ||||
|  | ||||
|     _close: function() { | ||||
|         this._mprisProxy.disconnect(this._ownerNotifyId); | ||||
|         this._mprisProxy = null; | ||||
|  | ||||
|         this._playerProxy.disconnect(this._propsChangedId); | ||||
|         this._playerProxy = null; | ||||
|  | ||||
|         this.emit('closed'); | ||||
|     }, | ||||
|  | ||||
|     _onMprisProxyReady: function() { | ||||
|         this._ownerNotifyId = this._mprisProxy.connect('notify::g-name-owner', | ||||
|             Lang.bind(this, function() { | ||||
|                 if (!this._mprisProxy.g_name_owner) | ||||
|                     this._close(); | ||||
|             })); | ||||
|     }, | ||||
|  | ||||
|     _onPlayerProxyReady: function() { | ||||
|         this._propsChangedId = this._playerProxy.connect('g-properties-changed', | ||||
|                                                          Lang.bind(this, this._updateState)); | ||||
|         this._updateState(); | ||||
|     }, | ||||
|  | ||||
|     _updateState: function() { | ||||
|         let metadata = {}; | ||||
|         for (let prop in this._playerProxy.Metadata) | ||||
|             metadata[prop] = this._playerProxy.Metadata[prop].deep_unpack(); | ||||
|  | ||||
|         this._trackArtists = metadata['xesam:artist'] || [_("Unknown artist")]; | ||||
|         this._trackTitle = metadata['xesam:title'] || _("Unknown title"); | ||||
|         this._trackCoverUrl = metadata['mpris:artUrl'] || ''; | ||||
|         this.emit('changed'); | ||||
|  | ||||
|         let visible = this._playerProxy.CanPlay; | ||||
|  | ||||
|         if (this._visible != visible) { | ||||
|             this._visible = visible; | ||||
|             if (visible) | ||||
|                 this.emit('show'); | ||||
|             else | ||||
|                 this._close(); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(MprisPlayer.prototype); | ||||
|  | ||||
| const MediaSection = new Lang.Class({ | ||||
|     Name: 'MediaSection', | ||||
|     Extends: MessageList.MessageListSection, | ||||
|  | ||||
|     _init: function() { | ||||
|         this.parent(_("Media")); | ||||
|  | ||||
|         this._players = new Map(); | ||||
|  | ||||
|         this._proxy = new DBusProxy(Gio.DBus.session, | ||||
|                                     'org.freedesktop.DBus', | ||||
|                                     '/org/freedesktop/DBus', | ||||
|                                     Lang.bind(this, this._onProxyReady)); | ||||
|     }, | ||||
|  | ||||
|     _shouldShow: function() { | ||||
|         return !this.empty && Calendar.isToday(this._date); | ||||
|     }, | ||||
|  | ||||
|     _addPlayer: function(busName) { | ||||
|         if (this._players.get(busName)) | ||||
|             return; | ||||
|  | ||||
|         let player = new MprisPlayer(busName); | ||||
|         player.connect('closed', Lang.bind(this, | ||||
|             function() { | ||||
|                 this._players.delete(busName); | ||||
|             })); | ||||
|         player.connect('show', Lang.bind(this, | ||||
|             function() { | ||||
|                 let message = new MediaMessage(player); | ||||
|                 this.addMessage(message, true); | ||||
|             })); | ||||
|         this._players.set(busName, player); | ||||
|     }, | ||||
|  | ||||
|     _onProxyReady: function() { | ||||
|         this._proxy.ListNamesRemote(Lang.bind(this, | ||||
|             function([names]) { | ||||
|                 names.forEach(Lang.bind(this, | ||||
|                     function(name) { | ||||
|                         if (!name.startsWith(MPRIS_PLAYER_PREFIX)) | ||||
|                             return; | ||||
|  | ||||
|                         this._addPlayer(name); | ||||
|                     })); | ||||
|             })); | ||||
|         this._proxy.connectSignal('NameOwnerChanged', | ||||
|                                   Lang.bind(this, this._onNameOwnerChanged)); | ||||
|     }, | ||||
|  | ||||
|     _onNameOwnerChanged: function(proxy, sender, [name, oldOwner, newOwner]) { | ||||
|         if (!name.startsWith(MPRIS_PLAYER_PREFIX)) | ||||
|             return; | ||||
|  | ||||
|         if (newOwner && !oldOwner) | ||||
|             this._addPlayer(name); | ||||
|     } | ||||
| }); | ||||
| @@ -22,13 +22,11 @@ const LevelBar = new Lang.Class({ | ||||
|         this._level = 0; | ||||
|  | ||||
|         this.actor = new St.Bin({ style_class: 'level', | ||||
|                                   x_align: St.Align.START, | ||||
|                                   y_fill: true }); | ||||
|         this._bar = new St.Widget({ style_class: 'level-bar' }); | ||||
|                                   x_fill: true, y_fill: true }); | ||||
|         this._bar = new St.DrawingArea(); | ||||
|         this._bar.connect('repaint', Lang.bind(this, this._repaint)); | ||||
|  | ||||
|         this.actor.set_child(this._bar); | ||||
|  | ||||
|         this.actor.connect('notify::width', () => { this.level = this.level; }); | ||||
|     }, | ||||
|  | ||||
|     get level() { | ||||
| @@ -36,44 +34,39 @@ const LevelBar = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     set level(value) { | ||||
|         this._level = Math.max(0, Math.min(value, 100)); | ||||
|  | ||||
|         let alloc = this.actor.get_allocation_box(); | ||||
|         let newWidth = Math.round((alloc.x2 - alloc.x1) * this._level / 100); | ||||
|         if (newWidth != this._bar.width) | ||||
|             this._bar.width = newWidth; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const OsdWindowConstraint = new Lang.Class({ | ||||
|     Name: 'OsdWindowConstraint', | ||||
|     Extends: Clutter.Constraint, | ||||
|  | ||||
|     _init: function(props) { | ||||
|         this._minSize = 0; | ||||
|         this.parent(props); | ||||
|         let newValue = Math.max(0, Math.min(value, 100)); | ||||
|         if (newValue == this._level) | ||||
|             return; | ||||
|         this._level = newValue; | ||||
|         this._bar.queue_repaint(); | ||||
|     }, | ||||
|  | ||||
|     set minSize(v) { | ||||
|         this._minSize = v; | ||||
|         if (this.actor) | ||||
|             this.actor.queue_relayout(); | ||||
|     }, | ||||
|     _repaint: function() { | ||||
|         let cr = this._bar.get_context(); | ||||
|  | ||||
|     vfunc_update_allocation: function(actor, actorBox) { | ||||
|         // Clutter will adjust the allocation for margins, | ||||
|         // so add it to our minimum size | ||||
|         let minSize = this._minSize + actor.margin_top + actor.margin_bottom; | ||||
|         let [width, height] = actorBox.get_size(); | ||||
|         let node = this.actor.get_theme_node(); | ||||
|         let radius = node.get_border_radius(0); // assume same radius for all corners | ||||
|         Clutter.cairo_set_source_color(cr, node.get_foreground_color()); | ||||
|  | ||||
|         // Enforce a ratio of 1 | ||||
|         let size = Math.ceil(Math.max(minSize, height)); | ||||
|         actorBox.set_size(size, size); | ||||
|         let [w, h] = this._bar.get_surface_size(); | ||||
|         w *= (this._level / 100.); | ||||
|  | ||||
|         // Recenter | ||||
|         let [x, y] = actorBox.get_origin(); | ||||
|         actorBox.set_origin(Math.floor(x + width / 2 - size / 2), | ||||
|                             Math.floor(y + height / 2 - size / 2)); | ||||
|         if (w == 0) | ||||
|             return; | ||||
|  | ||||
|         cr.moveTo(radius, 0); | ||||
|         if (w >= radius) | ||||
|             cr.arc(w - radius, radius, radius, 1.5 * Math.PI, 2. * Math.PI); | ||||
|         else | ||||
|             cr.lineTo(w, 0); | ||||
|         if (w >= radius) | ||||
|             cr.arc(w - radius, h - radius, radius, 0, 0.5 * Math.PI); | ||||
|         else | ||||
|             cr.lineTo(w, h); | ||||
|         cr.arc(radius, h - radius, radius, 0.5 * Math.PI, Math.PI); | ||||
|         cr.arc(radius, radius, radius, Math.PI, 1.5 * Math.PI); | ||||
|         cr.fill(); | ||||
|         cr.$dispose(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -81,6 +74,7 @@ const OsdWindow = new Lang.Class({ | ||||
|     Name: 'OsdWindow', | ||||
|  | ||||
|     _init: function(monitorIndex) { | ||||
|         this._popupSize = 0; | ||||
|         this.actor = new St.Widget({ x_expand: true, | ||||
|                                      y_expand: true, | ||||
|                                      x_align: Clutter.ActorAlign.CENTER, | ||||
| @@ -90,12 +84,19 @@ const OsdWindow = new Lang.Class({ | ||||
|         let constraint = new Layout.MonitorConstraint({ index: monitorIndex }); | ||||
|         this.actor.add_constraint(constraint); | ||||
|  | ||||
|         this._boxConstraint = new OsdWindowConstraint(); | ||||
|         this._box = new St.BoxLayout({ style_class: 'osd-window', | ||||
|                                        vertical: true }); | ||||
|         this._box.add_constraint(this._boxConstraint); | ||||
|         this.actor.add_actor(this._box); | ||||
|  | ||||
|         this._box.connect('style-changed', Lang.bind(this, this._onStyleChanged)); | ||||
|         this._box.connect('notify::height', Lang.bind(this, | ||||
|             function() { | ||||
|                 Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, | ||||
|                     function() { | ||||
|                         this._box.width = this._box.height; | ||||
|                     })); | ||||
|             })); | ||||
|  | ||||
|         this._icon = new St.Icon(); | ||||
|         this._box.add(this._icon, { expand: true }); | ||||
|  | ||||
| @@ -197,12 +198,30 @@ const OsdWindow = new Lang.Class({ | ||||
|         let scalew = monitor.width / 640.0; | ||||
|         let scaleh = monitor.height / 480.0; | ||||
|         let scale = Math.min(scalew, scaleh); | ||||
|         let popupSize = 110 * Math.max(1, scale); | ||||
|         this._popupSize = 110 * Math.max(1, scale); | ||||
|  | ||||
|         let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; | ||||
|         this._icon.icon_size = popupSize / (2 * scaleFactor); | ||||
|         this._icon.icon_size = this._popupSize / (2 * scaleFactor); | ||||
|         this._box.translation_y = monitor.height / 4; | ||||
|         this._boxConstraint.minSize = popupSize; | ||||
|         this._box.style_changed(); | ||||
|     }, | ||||
|  | ||||
|     _onStyleChanged: function() { | ||||
|         let themeNode = this._box.get_theme_node(); | ||||
|         let horizontalPadding = themeNode.get_horizontal_padding(); | ||||
|         let verticalPadding = themeNode.get_vertical_padding(); | ||||
|         let topBorder = themeNode.get_border_width(St.Side.TOP); | ||||
|         let bottomBorder = themeNode.get_border_width(St.Side.BOTTOM); | ||||
|         let leftBorder = themeNode.get_border_width(St.Side.LEFT); | ||||
|         let rightBorder = themeNode.get_border_width(St.Side.RIGHT); | ||||
|  | ||||
|         let minWidth = this._popupSize - verticalPadding - leftBorder - rightBorder; | ||||
|         let minHeight = this._popupSize - horizontalPadding - topBorder - bottomBorder; | ||||
|  | ||||
|         // minWidth/minHeight here are in real pixels, | ||||
|         // but the theme takes measures in unscaled dimensions | ||||
|         let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; | ||||
|         this._box.style = 'min-height: %dpx;'.format(Math.max(minWidth, minHeight) / scaleFactor); | ||||
|     } | ||||
| }); | ||||
|  | ||||
|   | ||||
| @@ -107,12 +107,18 @@ const Overview = new Lang.Class({ | ||||
|  | ||||
|         this._overviewCreated = true; | ||||
|  | ||||
|         let layout = new Clutter.BinLayout(); | ||||
|         this._stack = new Clutter.Actor({ layout_manager: layout }); | ||||
|         this._stack.add_constraint(new LayoutManager.MonitorConstraint({ primary: true })); | ||||
|  | ||||
|         /* Translators: This is the main view to select | ||||
|            activities. See also note for "Activities" string. */ | ||||
|         this._overview = new St.BoxLayout({ name: 'overview', | ||||
|                                             accessible_name: _("Overview"), | ||||
|                                             vertical: true }); | ||||
|         this._overview.add_constraint(new LayoutManager.MonitorConstraint({ primary: true })); | ||||
|                                             reactive: true, | ||||
|                                             vertical: true, | ||||
|                                             x_expand: true, | ||||
|                                             y_expand: true }); | ||||
|         this._overview._delegate = this; | ||||
|  | ||||
|         // The main Background actors are inside global.window_group which are | ||||
| @@ -120,7 +126,7 @@ const Overview = new Lang.Class({ | ||||
|         // one. Instances of this class share a single CoglTexture behind the | ||||
|         // scenes which allows us to show the background with different | ||||
|         // rendering options without duplicating the texture data. | ||||
|         this._backgroundGroup = new Meta.BackgroundGroup({ reactive: true }); | ||||
|         this._backgroundGroup = new Meta.BackgroundGroup(); | ||||
|         Main.layoutManager.overviewGroup.add_child(this._backgroundGroup); | ||||
|         this._bgManagers = []; | ||||
|  | ||||
| @@ -143,7 +149,8 @@ const Overview = new Lang.Class({ | ||||
|         Main.layoutManager.overviewGroup.add_child(this._coverPane); | ||||
|         this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return Clutter.EVENT_STOP; })); | ||||
|  | ||||
|         Main.layoutManager.overviewGroup.add_child(this._overview); | ||||
|         this._stack.add_actor(this._overview); | ||||
|         Main.layoutManager.overviewGroup.add_child(this._stack); | ||||
|  | ||||
|         this._coverPane.hide(); | ||||
|  | ||||
| @@ -152,9 +159,6 @@ const Overview = new Lang.Class({ | ||||
|             dragMotion: Lang.bind(this, this._onDragMotion) | ||||
|         }; | ||||
|  | ||||
|  | ||||
|         Main.layoutManager.overviewGroup.connect('scroll-event', | ||||
|                                                  Lang.bind(this, this._onScrollEvent)); | ||||
|         Main.xdndHandler.connect('drag-begin', Lang.bind(this, this._onDragBegin)); | ||||
|         Main.xdndHandler.connect('drag-end', Lang.bind(this, this._onDragEnd)); | ||||
|  | ||||
| @@ -251,6 +255,7 @@ const Overview = new Lang.Class({ | ||||
|  | ||||
|         // Add our same-line elements after the search entry | ||||
|         this._overview.add(this._controls.actor, { y_fill: true, expand: true }); | ||||
|         this._controls.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); | ||||
|  | ||||
|         // TODO - recalculate everything when desktop size changes | ||||
|         this.dashIconSize = this._dash.iconSize; | ||||
| @@ -367,7 +372,7 @@ const Overview = new Lang.Class({ | ||||
|         if (this.isDummy) | ||||
|             return; | ||||
|  | ||||
|         this._backgroundGroup.add_action(action); | ||||
|         this._overview.add_action(action); | ||||
|     }, | ||||
|  | ||||
|     _getDesktopClone: function() { | ||||
| @@ -547,8 +552,8 @@ const Overview = new Lang.Class({ | ||||
|         Meta.disable_unredirect_for_screen(global.screen); | ||||
|         this.viewSelector.show(); | ||||
|  | ||||
|         this._overview.opacity = 0; | ||||
|         Tweener.addTween(this._overview, | ||||
|         this._stack.opacity = 0; | ||||
|         Tweener.addTween(this._stack, | ||||
|                          { opacity: 255, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            time: ANIMATION_TIME, | ||||
| @@ -613,7 +618,7 @@ const Overview = new Lang.Class({ | ||||
|         this.viewSelector.animateFromOverview(); | ||||
|  | ||||
|         // Make other elements fade out. | ||||
|         Tweener.addTween(this._overview, | ||||
|         Tweener.addTween(this._stack, | ||||
|                          { opacity: 0, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            time: ANIMATION_TIME, | ||||
|   | ||||
| @@ -421,6 +421,7 @@ const ControlsManager = new Lang.Class({ | ||||
|  | ||||
|         let layout = new ControlsLayout(); | ||||
|         this.actor = new St.Widget({ layout_manager: layout, | ||||
|                                      reactive: true, | ||||
|                                      x_expand: true, y_expand: true, | ||||
|                                      clip_to_allocation: true }); | ||||
|         this._group = new St.BoxLayout({ name: 'overview-group', | ||||
|   | ||||
| @@ -349,6 +349,7 @@ const Arrow = new Lang.Class({ | ||||
|     _init: function(params) { | ||||
|         this.parent(params); | ||||
|         this.x_fill = this.y_fill = true; | ||||
|         this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS); | ||||
|  | ||||
|         this._drawingArea = new St.DrawingArea(); | ||||
|         this._drawingArea.connect('repaint', Lang.bind(this, this._drawArrow)); | ||||
| @@ -376,22 +377,6 @@ const Arrow = new Lang.Class({ | ||||
|         cr.$dispose(); | ||||
|     }, | ||||
|  | ||||
|     vfunc_get_paint_volume: function(volume) { | ||||
|         if (!this.parent(volume)) | ||||
|             return false; | ||||
|  | ||||
|         if (!this._shadow) | ||||
|             return true; | ||||
|  | ||||
|         let shadow_box = new Clutter.ActorBox(); | ||||
|         this._shadow.get_box(this._drawingArea.get_allocation_box(), shadow_box); | ||||
|  | ||||
|         volume.set_width(Math.max(shadow_box.x2 - shadow_box.x1, volume.get_width())); | ||||
|         volume.set_height(Math.max(shadow_box.y2 - shadow_box.y1, volume.get_height())); | ||||
|  | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     vfunc_style_changed: function() { | ||||
|         let node = this.get_theme_node(); | ||||
|         this._shadow = node.get_shadow('-arrow-shadow'); | ||||
| @@ -399,8 +384,6 @@ const Arrow = new Lang.Class({ | ||||
|             this._shadowHelper = St.ShadowHelper.new(this._shadow); | ||||
|         else | ||||
|             this._shadowHelper = null; | ||||
|  | ||||
|         this.parent(); | ||||
|     }, | ||||
|  | ||||
|     vfunc_paint: function() { | ||||
| @@ -576,9 +559,6 @@ const ScreenShield = new Lang.Class({ | ||||
|         if (prevIsActive != this._isActive) | ||||
|             this.emit('active-changed'); | ||||
|  | ||||
|         if (this._loginSession) | ||||
|             this._loginSession.SetLockedHintRemote(active); | ||||
|  | ||||
|         this._syncInhibitor(); | ||||
|     }, | ||||
|  | ||||
| @@ -728,7 +708,7 @@ const ScreenShield = new Lang.Class({ | ||||
|         let unitaryDelay = ARROW_ANIMATION_TIME / (arrows.length + 1); | ||||
|         let maxOpacity = 255 * ARROW_ANIMATION_PEAK_OPACITY; | ||||
|         for (let i = 0; i < arrows.length; i++) { | ||||
|             arrows[i].opacity = 0; | ||||
|             arrows.opacity = 0; | ||||
|             Tweener.addTween(arrows[i], | ||||
|                              { opacity: 0, | ||||
|                                delay: unitaryDelay * (N_ARROWS - (i + 1)), | ||||
|   | ||||
| @@ -61,8 +61,8 @@ const InputSource = new Lang.Class({ | ||||
|         this.emit('changed'); | ||||
|     }, | ||||
|  | ||||
|     activate: function(interactive) { | ||||
|         this.emit('activate', !!interactive); | ||||
|     activate: function() { | ||||
|         this.emit('activate'); | ||||
|     }, | ||||
|  | ||||
|     _getXkbId: function() { | ||||
| @@ -109,7 +109,7 @@ const InputSourcePopup = new Lang.Class({ | ||||
|     _finish : function() { | ||||
|         this.parent(); | ||||
|  | ||||
|         this._items[this._selectedIndex].activate(true); | ||||
|         this._items[this._selectedIndex].activate(); | ||||
|     }, | ||||
| }); | ||||
|  | ||||
| @@ -159,14 +159,6 @@ const InputSourceSettings = new Lang.Class({ | ||||
|         return []; | ||||
|     }, | ||||
|  | ||||
|     get mruSources() { | ||||
|         return []; | ||||
|     }, | ||||
|  | ||||
|     set mruSources(sourcesList) { | ||||
|         // do nothing | ||||
|     }, | ||||
|  | ||||
|     get keyboardOptions() { | ||||
|         return []; | ||||
|     }, | ||||
| @@ -259,7 +251,6 @@ const InputSourceSessionSettings = new Lang.Class({ | ||||
|  | ||||
|     _DESKTOP_INPUT_SOURCES_SCHEMA: 'org.gnome.desktop.input-sources', | ||||
|     _KEY_INPUT_SOURCES: 'sources', | ||||
|     _KEY_MRU_SOURCES: 'mru-sources', | ||||
|     _KEY_KEYBOARD_OPTIONS: 'xkb-options', | ||||
|     _KEY_PER_WINDOW: 'per-window', | ||||
|  | ||||
| @@ -270,9 +261,9 @@ const InputSourceSessionSettings = new Lang.Class({ | ||||
|         this._settings.connect('changed::' + this._KEY_PER_WINDOW, Lang.bind(this, this._emitPerWindowChanged)); | ||||
|     }, | ||||
|  | ||||
|     _getSourcesList: function(key) { | ||||
|     get inputSources() { | ||||
|         let sourcesList = []; | ||||
|         let sources = this._settings.get_value(key); | ||||
|         let sources = this._settings.get_value(this._KEY_INPUT_SOURCES); | ||||
|         let nSources = sources.n_children(); | ||||
|  | ||||
|         for (let i = 0; i < nSources; i++) { | ||||
| @@ -282,19 +273,6 @@ const InputSourceSessionSettings = new Lang.Class({ | ||||
|         return sourcesList; | ||||
|     }, | ||||
|  | ||||
|     get inputSources() { | ||||
|         return this._getSourcesList(this._KEY_INPUT_SOURCES); | ||||
|     }, | ||||
|  | ||||
|     get mruSources() { | ||||
|         return this._getSourcesList(this._KEY_MRU_SOURCES); | ||||
|     }, | ||||
|  | ||||
|     set mruSources(sourcesList) { | ||||
|         let sources = GLib.Variant.new('a(ss)', sourcesList); | ||||
|         this._settings.set_value(this._KEY_MRU_SOURCES, sources); | ||||
|     }, | ||||
|  | ||||
|     get keyboardOptions() { | ||||
|         return this._settings.get_strv(this._KEY_KEYBOARD_OPTIONS); | ||||
|     }, | ||||
| @@ -394,7 +372,7 @@ const InputSourceManager = new Lang.Class({ | ||||
|         while (!(is = this._inputSources[nextIndex])) | ||||
|             nextIndex += 1; | ||||
|  | ||||
|         is.activate(true); | ||||
|         is.activate(); | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
| @@ -422,25 +400,6 @@ const InputSourceManager = new Lang.Class({ | ||||
|         this._keyboardManager.reapply(); | ||||
|     }, | ||||
|  | ||||
|     _updateMruSettings: function() { | ||||
|         // If IBus is not ready we don't have a full picture of all | ||||
|         // the available sources, so don't update the setting | ||||
|         if (!this._ibusReady) | ||||
|             return; | ||||
|  | ||||
|         // If IBus is temporarily disabled, don't update the setting | ||||
|         if (this._disableIBus) | ||||
|             return; | ||||
|  | ||||
|         let sourcesList = []; | ||||
|         for (let i = 0; i < this._mruSources.length; ++i) { | ||||
|             let source = this._mruSources[i]; | ||||
|             sourcesList.push([source.type, source.id]); | ||||
|         } | ||||
|  | ||||
|         this._settings.mruSources = sourcesList; | ||||
|     }, | ||||
|  | ||||
|     _currentInputSourceChanged: function(newSource) { | ||||
|         let oldSource; | ||||
|         [oldSource, this._currentSource] = [this._currentSource, newSource]; | ||||
| @@ -457,7 +416,7 @@ const InputSourceManager = new Lang.Class({ | ||||
|         this._changePerWindowSource(); | ||||
|     }, | ||||
|  | ||||
|     _activateInputSource: function(is, interactive) { | ||||
|     _activateInputSource: function(is) { | ||||
|         KeyboardManager.holdKeyboard(); | ||||
|         this._keyboardManager.apply(is.xkbId); | ||||
|  | ||||
| @@ -475,54 +434,6 @@ const InputSourceManager = new Lang.Class({ | ||||
|  | ||||
|         this._ibusManager.setEngine(engine, KeyboardManager.releaseKeyboard); | ||||
|         this._currentInputSourceChanged(is); | ||||
|  | ||||
|         if (interactive) | ||||
|             this._updateMruSettings(); | ||||
|     }, | ||||
|  | ||||
|     _updateMruSources: function() { | ||||
|         let sourcesList = []; | ||||
|         for (let i in this._inputSources) | ||||
|             sourcesList.push(this._inputSources[i]); | ||||
|  | ||||
|         this._keyboardManager.setUserLayouts(sourcesList.map(function(x) { return x.xkbId; })); | ||||
|  | ||||
|         if (!this._disableIBus && this._mruSourcesBackup) { | ||||
|             this._mruSources = this._mruSourcesBackup; | ||||
|             this._mruSourcesBackup = null; | ||||
|         } | ||||
|  | ||||
|         // Initialize from settings when we have no MRU sources list | ||||
|         if (this._mruSources.length == 0) { | ||||
|             let mruSettings = this._settings.mruSources; | ||||
|             for (let i = 0; i < mruSettings.length; i++) { | ||||
|                 let mruSettingSource = mruSettings[i]; | ||||
|                 let mruSource = null; | ||||
|  | ||||
|                 for (let j = 0; j < sourcesList.length; j++) { | ||||
|                     let source = sourcesList[j]; | ||||
|                     if (source.type == mruSettingSource.type && | ||||
|                         source.id == mruSettingSource.id) { | ||||
|                         mruSource = source; | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (mruSource) | ||||
|                     this._mruSources.push(mruSource); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         let mruSources = []; | ||||
|         for (let i = 0; i < this._mruSources.length; i++) { | ||||
|             for (let j = 0; j < sourcesList.length; j++) | ||||
|                 if (this._mruSources[i].type == sourcesList[j].type && | ||||
|                     this._mruSources[i].id == sourcesList[j].id) { | ||||
|                     mruSources = mruSources.concat(sourcesList.splice(j, 1)); | ||||
|                     break; | ||||
|                 } | ||||
|         } | ||||
|         this._mruSources = mruSources.concat(sourcesList); | ||||
|     }, | ||||
|  | ||||
|     _inputSourcesChanged: function() { | ||||
| @@ -599,10 +510,30 @@ const InputSourceManager = new Lang.Class({ | ||||
|  | ||||
|         this.emit('sources-changed'); | ||||
|  | ||||
|         this._updateMruSources(); | ||||
|         let sourcesList = []; | ||||
|         for (let i in this._inputSources) | ||||
|             sourcesList.push(this._inputSources[i]); | ||||
|  | ||||
|         this._keyboardManager.setUserLayouts(sourcesList.map(function(x) { return x.xkbId; })); | ||||
|  | ||||
|         if (!this._disableIBus && this._mruSourcesBackup) { | ||||
|             this._mruSources = this._mruSourcesBackup; | ||||
|             this._mruSourcesBackup = null; | ||||
|         } | ||||
|  | ||||
|         let mruSources = []; | ||||
|         for (let i = 0; i < this._mruSources.length; i++) { | ||||
|             for (let j = 0; j < sourcesList.length; j++) | ||||
|                 if (this._mruSources[i].type == sourcesList[j].type && | ||||
|                     this._mruSources[i].id == sourcesList[j].id) { | ||||
|                     mruSources = mruSources.concat(sourcesList.splice(j, 1)); | ||||
|                     break; | ||||
|                 } | ||||
|         } | ||||
|         this._mruSources = mruSources.concat(sourcesList); | ||||
|  | ||||
|         if (this._mruSources.length > 0) | ||||
|             this._mruSources[0].activate(false); | ||||
|             this._mruSources[0].activate(); | ||||
|  | ||||
|         // All ibus engines are preloaded here to reduce the launching time | ||||
|         // when users switch the input sources. | ||||
| @@ -711,7 +642,7 @@ const InputSourceManager = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         if (window._currentSource) | ||||
|             window._currentSource.activate(false); | ||||
|             window._currentSource.activate(); | ||||
|     }, | ||||
|  | ||||
|     _sourcesPerWindowChanged: function() { | ||||
| @@ -832,10 +763,7 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|             let is = this._inputSourceManager.inputSources[i]; | ||||
|  | ||||
|             let menuItem = new LayoutMenuItem(is.displayName, is.shortName); | ||||
|             menuItem.connect('activate', function() { | ||||
|                 is.activate(true); | ||||
|             }); | ||||
|  | ||||
|             menuItem.connect('activate', Lang.bind(is, is.activate)); | ||||
|             let indicatorLabel = new St.Label({ text: is.shortName, | ||||
|                                                 visible: false }); | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const GLib = imports.gi.GLib; | ||||
| const Gio = imports.gi.Gio; | ||||
| const Lang = imports.lang; | ||||
| @@ -10,14 +9,13 @@ const PanelMenu = imports.ui.panelMenu; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
| const Shell = imports.gi.Shell; | ||||
| const Signals = imports.signals; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const LOCATION_SCHEMA = 'org.gnome.system.location'; | ||||
| const MAX_ACCURACY_LEVEL = 'max-accuracy-level'; | ||||
| const ENABLED = 'enabled'; | ||||
|  | ||||
| const APP_PERMISSIONS_TABLE = 'gnome'; | ||||
| const APP_PERMISSIONS_TABLE = 'desktop'; | ||||
| const APP_PERMISSIONS_ID = 'geolocation'; | ||||
|  | ||||
| const GeoclueAccuracyLevel = { | ||||
| @@ -29,15 +27,6 @@ const GeoclueAccuracyLevel = { | ||||
|     EXACT: 8 | ||||
| }; | ||||
|  | ||||
| function accuracyLevelToString(accuracyLevel) { | ||||
|     for (let key in GeoclueAccuracyLevel) { | ||||
|         if (GeoclueAccuracyLevel[key] == accuracyLevel) | ||||
|             return key; | ||||
|     } | ||||
|  | ||||
|     return 'NONE'; | ||||
| } | ||||
|  | ||||
| var GeoclueIface = '<node> \ | ||||
|   <interface name="org.freedesktop.GeoClue2.Manager"> \ | ||||
|     <property name="InUse" type="b" access="read"/> \ | ||||
| @@ -62,8 +51,8 @@ var AgentIface = '<node> \ | ||||
|   </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| var PermissionStoreIface = '<node> \ | ||||
|   <interface name="org.freedesktop.impl.portal.PermissionStore"> \ | ||||
| var XdgAppIface = '<node> \ | ||||
|   <interface name="org.freedesktop.XdgApp.PermissionStore"> \ | ||||
|     <method name="Lookup"> \ | ||||
|       <arg name="table" type="s" direction="in"/> \ | ||||
|       <arg name="id" type="s" direction="in"/> \ | ||||
| @@ -80,7 +69,7 @@ var PermissionStoreIface = '<node> \ | ||||
|   </interface> \ | ||||
| </node>'; | ||||
|  | ||||
| const PermissionStore = Gio.DBusProxy.makeProxyWrapper(PermissionStoreIface); | ||||
| const PermissionStore = Gio.DBusProxy.makeProxyWrapper(XdgAppIface); | ||||
|  | ||||
| const Indicator = new Lang.Class({ | ||||
|     Name: 'LocationIndicator', | ||||
| @@ -127,18 +116,152 @@ const Indicator = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     AuthorizeAppAsync: function(params, invocation) { | ||||
|         let [desktopId, reqAccuracyLevel] = params; | ||||
|         let [desktop_id, reqAccuracyLevel] = params; | ||||
|         log("%s is requesting location".format(desktop_id)); | ||||
|  | ||||
|         let authorizer = new AppAuthorizer(desktopId, | ||||
|                                            reqAccuracyLevel, | ||||
|                                            this._permStoreProxy, | ||||
|                                            this._getMaxAccuracyLevel()); | ||||
|         let callback = function(level, timesAllowed) { | ||||
|             if (level >= GeoclueAccuracyLevel.NONE && timesAllowed > 2) { | ||||
|                 log("%s is in store".format(desktop_id)); | ||||
|                 let accuracyLevel = clamp(reqAccuracyLevel, 0, level); | ||||
|                 this._completeAuthorizeApp(desktop_id, | ||||
|                                            accuracyLevel, | ||||
|                                            timesAllowed, | ||||
|                                            invocation); | ||||
|             } else { | ||||
|                 log("%s not in store".format(desktop_id)); | ||||
|                 this._userAuthorizeApp(desktop_id, | ||||
|                                        reqAccuracyLevel, | ||||
|                                        timesAllowed, | ||||
|                                        invocation); | ||||
|             } | ||||
|         } | ||||
|         this._fetchPermissionFromStore(desktop_id, Lang.bind(this, callback); | ||||
|     }, | ||||
|  | ||||
|         authorizer.authorize(Lang.bind(this, function(accuracyLevel) { | ||||
|             let ret = (accuracyLevel != GeoclueAccuracyLevel.NONE); | ||||
|     _userAuthorizeApp: function(desktopId, reqAccuracyLevel, timesAllowed, invocation) { | ||||
|         var appSystem = Shell.AppSystem.get_default(); | ||||
|         var app = appSystem.lookup_app(desktopId + ".desktop"); | ||||
|         if (app == null) { | ||||
|             this._completeAuthorizeApp(desktopId, | ||||
|                                        GeoclueAccuracyLevel.NONE, | ||||
|                                        timesAllowed, | ||||
|                                        invocation); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         var name = app.get_name(); | ||||
|         var icon = app.get_app_info().get_icon(); | ||||
|         var reason = app.get_string("X-Geoclue-Reason"); | ||||
|         var allowCallback = function() { | ||||
|             this._completeAuthorizeApp(desktopId, | ||||
|                                        reqAccuracyLevel, | ||||
|                                        timesAllowed, | ||||
|                                        invocation); | ||||
|         }; | ||||
|         var denyCallback = function() { | ||||
|             this._completeAuthorizeApp(desktopId, | ||||
|                                        GeoclueAccuracyLevel.NONE, | ||||
|                                        timesAllowed, | ||||
|                                        invocation); | ||||
|         }; | ||||
|  | ||||
|         this._showAppAuthDialog(name, | ||||
|                                 reason, | ||||
|                                 icon, | ||||
|                                 Lang.bind(this, allowCallback), | ||||
|                                 Lang.bind(this, denyCallback)); | ||||
|     }, | ||||
|  | ||||
|     _showAppAuthDialog: function(name, reason, icon, allowCallback, denyCallback) { | ||||
|         if (this._dialog == null) | ||||
|             this._dialog = new GeolocationDialog(name, reason, icon); | ||||
|         else | ||||
|             this._dialog.update(name, reason, icon); | ||||
|  | ||||
|         let closedId = this._dialog.connect('closed', function() { | ||||
|             this._dialog.disconnect(closedId); | ||||
|             if (this._dialog.allowed) | ||||
|                 allowCallback (); | ||||
|             else | ||||
|                 denyCallback (); | ||||
|         }.bind(this)); | ||||
|  | ||||
|         this._dialog.open(global.get_current_time ()); | ||||
|     }, | ||||
|  | ||||
|     _completeAuthorizeApp: function(desktopId, | ||||
|                                     accuracyLevel, | ||||
|                                     timesAllowed, | ||||
|                                     invocation) { | ||||
|         if (accuracyLevel == GeoclueAccuracyLevel.NONE) { | ||||
|             invocation.return_value(GLib.Variant.new('(bu)', | ||||
|                                                      [ret, accuracyLevel])); | ||||
|         })); | ||||
|                                                      [false, accuracyLevel])); | ||||
|             this._saveToPermissionStore(desktopId, accuracyLevel, 0); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let allowedAccuracyLevel = clamp(accuracyLevel, | ||||
|                                          0, | ||||
|                                          this._getMaxAccuracyLevel()); | ||||
|         invocation.return_value(GLib.Variant.new('(bu)', | ||||
|                                                  [true, allowedAccuracyLevel])); | ||||
|  | ||||
|         this._saveToPermissionStore(desktopId, allowedAccuracyLevel, timesAllowed + 1); | ||||
|     }, | ||||
|  | ||||
|     _fetchPermissionFromStore: function(desktopId, callback) { | ||||
|         if (this._permStoreProxy == null) { | ||||
|             callback (-1, 0); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this._permStoreProxy.LookupRemote(APP_PERMISSIONS_TABLE, | ||||
|                                           APP_PERMISSIONS_ID, | ||||
|                                           function(result, error) { | ||||
|             if (error != null) { | ||||
|                 log(error.message); | ||||
|                 callback(-1, 0); | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             let [permissions, data] = result; | ||||
|             let permission = permissions[desktopId]; | ||||
|             if (permission == null) { | ||||
|                 callback(-1, 0); | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             let levelStr = permission[0]; | ||||
|             let level = GeoclueAccuracyLevel[levelStr.toUpperCase()] || | ||||
|                         GeoclueAccuracyLevel.NONE; | ||||
|             let timesAllowed = data.get_byte(); | ||||
|  | ||||
|             callback(level, timesAllowed); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     _saveToPermissionStore: function(desktopId, | ||||
|                                      allowedAccuracyLevel, | ||||
|                                      timesAllowed) { | ||||
|         if (timesAllowed > 2 || this._permStoreProxy == null) | ||||
|             return; | ||||
|  | ||||
|         let levelStr = Object.keys(GeoclueAccuracyLevel)[allowedAccuracyLevel];  | ||||
|         let permission = { desktopId: [levelStr] }; | ||||
|         let permissions = GLib.Variant.new('a{sas}', [permission])); | ||||
|         let data = GLib.Variant.new('y', timesAllowed); | ||||
|  | ||||
|         this._permStoreProxy.SetRemote(APP_PERMISSIONS_TABLE, | ||||
|                                        true, | ||||
|                                        APP_PERMISSIONS_ID, | ||||
|                                        permissions, | ||||
|                                        data, | ||||
|                                        function (result, error) { | ||||
|             log(error.message); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     _syncIndicator: function() { | ||||
| @@ -254,8 +377,8 @@ const Indicator = new Lang.Class({ | ||||
|     _connectToPermissionStore: function() { | ||||
|         this._permStoreProxy = null; | ||||
|         new PermissionStore(Gio.DBus.session, | ||||
|                            'org.freedesktop.impl.portal.PermissionStore', | ||||
|                            '/org/freedesktop/impl/portal/PermissionStore', | ||||
|                            'org.freedesktop.XdgApp', | ||||
|                            '/org/freedesktop/XdgApp/PermissionStore', | ||||
|                            Lang.bind(this, this._onPermStoreProxyReady)); | ||||
|     }, | ||||
|  | ||||
| @@ -273,182 +396,61 @@ function clamp(value, min, max) { | ||||
|     return Math.max(min, Math.min(max, value)); | ||||
| } | ||||
|  | ||||
| const AppAuthorizer = new Lang.Class({ | ||||
|     Name: 'LocationAppAuthorizer', | ||||
|  | ||||
|     _init: function(desktopId, | ||||
|                     reqAccuracyLevel, | ||||
|                     permStoreProxy, | ||||
|                     maxAccuracyLevel) { | ||||
|         this.desktopId = desktopId; | ||||
|         this.reqAccuracyLevel = reqAccuracyLevel; | ||||
|         this._permStoreProxy = permStoreProxy; | ||||
|         this._maxAccuracyLevel = maxAccuracyLevel; | ||||
|  | ||||
|         this._accuracyLevel = GeoclueAccuracyLevel.NONE; | ||||
|     }, | ||||
|  | ||||
|     authorize: function(onAuthDone) { | ||||
|         this._onAuthDone = onAuthDone; | ||||
|  | ||||
|         let appSystem = Shell.AppSystem.get_default(); | ||||
|         this._app = appSystem.lookup_app(this.desktopId + ".desktop"); | ||||
|         if (this._app == null || this._permStoreProxy == null) { | ||||
|             this._completeAuth(); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this._permStoreProxy.LookupRemote(APP_PERMISSIONS_TABLE, | ||||
|                                           APP_PERMISSIONS_ID, | ||||
|                                           Lang.bind(this, | ||||
|                                                     this._onPermLookupDone)); | ||||
|     }, | ||||
|  | ||||
|     _onPermLookupDone: function(result, error) { | ||||
|         if (error != null) { | ||||
|             if (error.domain == Gio.DBusError) { | ||||
|                 // Likely no xdg-app installed, just authorize the app | ||||
|                 this._accuracyLevel = this.reqAccuracyLevel; | ||||
|                 this._permStoreProxy = null; | ||||
|                 this._completeAuth(); | ||||
|             } else { | ||||
|                 // Currently xdg-app throws an error if we lookup for | ||||
|                 // unknown ID (which would be the case first time this code | ||||
|                 // runs) so we continue with user authorization as normal | ||||
|                 // and ID is added to the store if user says "yes". | ||||
|                 log(error.message); | ||||
|                 this._permissions = {}; | ||||
|                 this._userAuthorizeApp(); | ||||
|             } | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         [this._permissions] = result; | ||||
|         let permission = this._permissions[this.desktopId]; | ||||
|  | ||||
|         if (permission == null) { | ||||
|             this._userAuthorizeApp(); | ||||
|         } else { | ||||
|             let [levelStr] = permission || ['NONE']; | ||||
|             this._accuracyLevel = GeoclueAccuracyLevel[levelStr] || | ||||
|                                   GeoclueAccuracyLevel.NONE; | ||||
|             this._completeAuth(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _userAuthorizeApp: function() { | ||||
|         let name = this._app.get_name(); | ||||
|         let appInfo = this._app.get_app_info(); | ||||
|         let reason = appInfo.get_string("X-Geoclue-Reason"); | ||||
|  | ||||
|         this._showAppAuthDialog(name, reason); | ||||
|     }, | ||||
|  | ||||
|     _showAppAuthDialog: function(name, reason) { | ||||
|         this._dialog = new GeolocationDialog(name, | ||||
|                                              reason, | ||||
|                                              this.reqAccuracyLevel); | ||||
|  | ||||
|         let responseId = this._dialog.connect('response', Lang.bind(this, | ||||
|             function(dialog, level) { | ||||
|                 this._dialog.disconnect(responseId); | ||||
|                 this._accuracyLevel = level; | ||||
|                 this._completeAuth(); | ||||
|             })); | ||||
|  | ||||
|         this._dialog.open(); | ||||
|     }, | ||||
|  | ||||
|     _completeAuth: function() { | ||||
|         if (this._accuracyLevel != GeoclueAccuracyLevel.NONE) { | ||||
|             this._accuracyLevel = clamp(this._accuracyLevel, | ||||
|                                         0, | ||||
|                                         this._maxAccuracyLevel); | ||||
|         } | ||||
|         this._saveToPermissionStore(); | ||||
|  | ||||
|         this._onAuthDone(this._accuracyLevel); | ||||
|     }, | ||||
|  | ||||
|     _saveToPermissionStore: function() { | ||||
|         if (this._permStoreProxy == null) | ||||
|             return; | ||||
|  | ||||
|         let levelStr = accuracyLevelToString(this._accuracyLevel); | ||||
|         let dateStr = Math.round(Date.now() / 1000).toString(); | ||||
|         this._permissions[this.desktopId] = [levelStr, dateStr]; | ||||
|  | ||||
|         let data = GLib.Variant.new('av', {}); | ||||
|  | ||||
|         this._permStoreProxy.SetRemote(APP_PERMISSIONS_TABLE, | ||||
|                                        true, | ||||
|                                        APP_PERMISSIONS_ID, | ||||
|                                        this._permissions, | ||||
|                                        data, | ||||
|                                        function (result, error) { | ||||
|             if (error != null) | ||||
|                 log(error.message); | ||||
|         }); | ||||
|     }, | ||||
| }); | ||||
|  | ||||
| const GeolocationDialog = new Lang.Class({ | ||||
|     Name: 'GeolocationDialog', | ||||
|     Extends: ModalDialog.ModalDialog, | ||||
|  | ||||
|     _init: function(name, reason, reqAccuracyLevel) { | ||||
|         this.parent({ styleClass: 'geolocation-dialog' }); | ||||
|         this.reqAccuracyLevel = reqAccuracyLevel; | ||||
|     // FIXME: Would be nice to show the application icon too | ||||
|     _init: function(name, reason, icon) { | ||||
|         this.parent({ destroyOnClose: false }); | ||||
|  | ||||
|         let mainContentBox = new St.BoxLayout({ style_class: 'geolocation-dialog-main-layout' }); | ||||
|         this.contentLayout.add_actor(mainContentBox); | ||||
|         let text = _("'%s' is requesting access to location data.").format (name); | ||||
|         this._label = new St.Label({ style_class: 'prompt-dialog-description', | ||||
|                                      text: text }); | ||||
|  | ||||
|         let icon = new St.Icon({ style_class: 'geolocation-dialog-icon', | ||||
|                                  icon_name: 'find-location-symbolic', | ||||
|                                  y_align: Clutter.ActorAlign.START }); | ||||
|         mainContentBox.add_actor(icon); | ||||
|         this.contentLayout.add(this._label, {}); | ||||
|  | ||||
|         let messageBox = new St.BoxLayout({ style_class: 'geolocation-dialog-content', | ||||
|                                             vertical: true }); | ||||
|         mainContentBox.add_actor(messageBox); | ||||
|         if (reason != null) { | ||||
|             this._reasonLabel = new St.Label({ style_class: 'prompt-dialog-description', | ||||
|                                                text: reason }); | ||||
|             this.contentLayout.add(this._reasonLabel, {}); | ||||
|         } else { | ||||
|             this._reasonLabel = null; | ||||
|         } | ||||
|  | ||||
|         this._title = new St.Label({ style_class: 'geolocation-dialog-title headline' }); | ||||
|         messageBox.add_actor(this._title); | ||||
|  | ||||
|         this._reason = new St.Label({ style_class: 'geolocation-dialog-reason' }); | ||||
|         messageBox.add_actor(this._reason); | ||||
|  | ||||
|         this._privacyNote = new St.Label(); | ||||
|         messageBox.add_actor(this._privacyNote); | ||||
|  | ||||
|         let button = this.addButton({ label: _("Deny Access"), | ||||
|                                       action: Lang.bind(this, this._onDenyClicked), | ||||
|                                       key: Clutter.KEY_Escape }); | ||||
|         this.addButton({ label: _("Grant Access"), | ||||
|                          action: Lang.bind(this, this._onGrantClicked) }); | ||||
|  | ||||
|         this.setInitialKeyFocus(button); | ||||
|  | ||||
|         /* Translators: %s is an application name */ | ||||
|         this._title.text = _("Give %s access to your location?").format(name); | ||||
|  | ||||
|         this._privacyNote.text = _("Location access can be changed at any time from the privacy settings."); | ||||
|  | ||||
|         if (reason) | ||||
|             this._reason.text = reason; | ||||
|         this._reason.visible = (reason != null); | ||||
|         this._allowButton = this.addButton({ label: _("Confirm"), | ||||
|                                              action: this._onAllowClicked.bind(this), | ||||
|                                              default: false }, | ||||
|                                            { expand: true, x_fill: false, x_align: St.Align.END }); | ||||
|         this._denyButton = this.addButton({ label: _("Cancel"), | ||||
|                                             action: this._onDisallowClicked.bind(this), | ||||
|                                             default: true }, | ||||
|                                           { expand: true, x_fill: false, x_align: St.Align.START }); | ||||
|     }, | ||||
|  | ||||
|     _onGrantClicked: function() { | ||||
|         this.emit('response', this.reqAccuracyLevel); | ||||
|     update: function(name, reason, icon) { | ||||
|         let text = _("'%s' is requesting access to location data.").format (name); | ||||
|         this._label.text = text; | ||||
|  | ||||
|         if (this._reasonLabel != null) { | ||||
|             this.contentLayout.remove(this._reasonLabel, {}); | ||||
|             this._reasonLabel = null; | ||||
|         } | ||||
|  | ||||
|         if (reason != null) { | ||||
|             this._reasonLabel = new St.Label({ style_class: 'prompt-dialog-description', | ||||
|                                                text: reason }); | ||||
|             this.contentLayout.add(this._reasonLabel, {}); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _onAllowClicked: function() { | ||||
|         this.allowed = true; | ||||
|         this.close(); | ||||
|     }, | ||||
|  | ||||
|     _onDenyClicked: function() { | ||||
|         this.emit('response', GeoclueAccuracyLevel.NONE); | ||||
|     _onDisallowClicked: function() { | ||||
|         this.allowed = false; | ||||
|         this.close(); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(GeolocationDialog.prototype); | ||||
|   | ||||
| @@ -621,7 +621,7 @@ const NMDeviceBluetooth = new Lang.Class({ | ||||
|     _init: function(client, device, settings) { | ||||
|         this.parent(client, device, settings); | ||||
|  | ||||
|         this.item.menu.addMenuItem(createSettingsAction(_("Bluetooth Settings"), device)); | ||||
|         this.item.menu.addMenuItem(createSettingsAction(_("Mobile Broadband Settings"), device)); | ||||
|     }, | ||||
|  | ||||
|     _getDescription: function() { | ||||
| @@ -629,7 +629,7 @@ const NMDeviceBluetooth = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     getConnectLabel: function() { | ||||
|         return _("Connect to Internet"); | ||||
|         return _("Use as Internet connection"); | ||||
|     }, | ||||
|  | ||||
|     getIndicatorIcon: function() { | ||||
| @@ -1632,8 +1632,6 @@ const NMApplet = new Lang.Class({ | ||||
|         this._readConnections(); | ||||
|         this._readDevices(); | ||||
|         this._syncNMState(); | ||||
|         this._syncMainConnection(); | ||||
|         this._syncVPNConnections(); | ||||
|  | ||||
|         this._client.connect('notify::manager-running', Lang.bind(this, this._syncNMState)); | ||||
|         this._client.connect('notify::networking-enabled', Lang.bind(this, this._syncNMState)); | ||||
|   | ||||
| @@ -6,7 +6,6 @@ const Gdm = imports.gi.Gdm; | ||||
| const Gio = imports.gi.Gio; | ||||
| const GLib = imports.gi.GLib; | ||||
| const Lang = imports.lang; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Shell = imports.gi.Shell; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| @@ -111,7 +110,6 @@ const Indicator = new Lang.Class({ | ||||
|  | ||||
|         this._session = new GnomeSession.SessionManager(); | ||||
|         this._loginManager = LoginManager.getLoginManager(); | ||||
|         this._monitorManager = Meta.MonitorManager.get(); | ||||
|         this._haveShutdown = true; | ||||
|         this._haveSuspend = true; | ||||
|  | ||||
| @@ -157,8 +155,6 @@ const Indicator = new Lang.Class({ | ||||
|  | ||||
|         this._orientationSettings.connect('changed::orientation-lock', | ||||
|                                           Lang.bind(this, this._updateOrientationLock)); | ||||
|         Main.layoutManager.connect('monitors-changed', | ||||
|                                    Lang.bind(this, this._updateOrientationLock)); | ||||
|         Gio.DBus.system.watch_name(SENSOR_BUS_NAME, | ||||
|                                    Gio.BusNameWatcherFlags.NONE, | ||||
|                                    Lang.bind(this, this._sensorProxyAppeared), | ||||
| @@ -268,8 +264,7 @@ const Indicator = new Lang.Class({ | ||||
|  | ||||
|     _updateOrientationLock: function() { | ||||
|         if (this._sensorProxy) | ||||
|             this._orientationLockAction.visible = this._sensorProxy.HasAccelerometer && | ||||
|                                                   this._monitorManager.get_is_builtin_display_on(); | ||||
|             this._orientationLockAction.visible = this._sensorProxy.HasAccelerometer; | ||||
|         else | ||||
|             this._orientationLockAction.visible = false; | ||||
|  | ||||
| @@ -306,17 +301,14 @@ const Indicator = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _updateHaveSuspend: function() { | ||||
|         this._loginManager.canSuspend(Lang.bind(this, | ||||
|             function(canSuspend, needsAuth) { | ||||
|                 this._haveSuspend = canSuspend; | ||||
|                 this._suspendNeedsAuth = needsAuth; | ||||
|                 this._updateSuspend(); | ||||
|             })); | ||||
|         this._loginManager.canSuspend(Lang.bind(this, function(result) { | ||||
|             this._haveSuspend = result; | ||||
|             this._updateSuspend(); | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     _updateSuspend: function() { | ||||
|         let disabled = (Main.sessionMode.isLocked && | ||||
|                         this._suspendNeedsAuth) || | ||||
|         let disabled = Main.sessionMode.isLocked || | ||||
|                        (Main.sessionMode.isGreeter && | ||||
|                         this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY)); | ||||
|         this._suspendAction.visible = this._haveSuspend && !disabled; | ||||
|   | ||||
| @@ -156,7 +156,7 @@ const ViewSelector = new Lang.Class({ | ||||
|  | ||||
|         this.appDisplay = new AppDisplay.AppDisplay(); | ||||
|         this._appsPage = this._addPage(this.appDisplay.actor, | ||||
|                                        _("Applications"), 'view-app-grid-symbolic'); | ||||
|                                        _("Applications"), 'view-grid-symbolic'); | ||||
|  | ||||
|         this._searchResults = new Search.SearchResults(); | ||||
|         this._searchPage = this._addPage(this._searchResults.actor, | ||||
|   | ||||
| @@ -683,8 +683,6 @@ const WindowManager = new Lang.Class({ | ||||
|  | ||||
|         this._dimmedWindows = []; | ||||
|  | ||||
|         this._skippedActors = []; | ||||
|  | ||||
|         this._allowedKeybindings = {}; | ||||
|  | ||||
|         this._isWorkspacePrepended = false; | ||||
| @@ -852,34 +850,22 @@ const WindowManager = new Lang.Class({ | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-applications', | ||||
|                                         Shell.ActionMode.NORMAL, | ||||
|                                         Lang.bind(this, this._startSwitcher)); | ||||
|                                         Lang.bind(this, this._startAppSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-group', | ||||
|                                         Shell.ActionMode.NORMAL, | ||||
|                                         Lang.bind(this, this._startSwitcher)); | ||||
|                                         Lang.bind(this, this._startAppSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-applications-backward', | ||||
|                                         Shell.ActionMode.NORMAL, | ||||
|                                         Lang.bind(this, this._startSwitcher)); | ||||
|                                         Lang.bind(this, this._startAppSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-group-backward', | ||||
|                                         Shell.ActionMode.NORMAL, | ||||
|                                         Lang.bind(this, this._startSwitcher)); | ||||
|                                         Lang.bind(this, this._startAppSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-windows', | ||||
|                                         Shell.ActionMode.NORMAL, | ||||
|                                         Lang.bind(this, this._startSwitcher)); | ||||
|                                         Lang.bind(this, this._startWindowSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-windows-backward', | ||||
|                                         Shell.ActionMode.NORMAL, | ||||
|                                         Lang.bind(this, this._startSwitcher)); | ||||
|         this.setCustomKeybindingHandler('cycle-windows', | ||||
|                                         Shell.ActionMode.NORMAL, | ||||
|                                         Lang.bind(this, this._startSwitcher)); | ||||
|         this.setCustomKeybindingHandler('cycle-windows-backward', | ||||
|                                         Shell.ActionMode.NORMAL, | ||||
|                                         Lang.bind(this, this._startSwitcher)); | ||||
|         this.setCustomKeybindingHandler('cycle-group', | ||||
|                                         Shell.ActionMode.NORMAL, | ||||
|                                         Lang.bind(this, this._startSwitcher)); | ||||
|         this.setCustomKeybindingHandler('cycle-group-backward', | ||||
|                                         Shell.ActionMode.NORMAL, | ||||
|                                         Lang.bind(this, this._startSwitcher)); | ||||
|                                         Lang.bind(this, this._startWindowSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-panels', | ||||
|                                         Shell.ActionMode.NORMAL | | ||||
|                                         Shell.ActionMode.OVERVIEW | | ||||
| @@ -1037,10 +1023,6 @@ const WindowManager = new Lang.Class({ | ||||
|         this._workspaceTracker.keepWorkspaceAlive(workspace, duration); | ||||
|     }, | ||||
|  | ||||
|     skipNextEffect: function(actor) { | ||||
|         this._skippedActors.push(actor); | ||||
|     }, | ||||
|  | ||||
|     setCustomKeybindingHandler: function(name, modes, handler) { | ||||
|         if (Meta.keybindings_set_custom_handler(name, handler)) | ||||
|             this.allowKeybinding(name, modes); | ||||
| @@ -1067,9 +1049,6 @@ const WindowManager = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _shouldAnimateActor: function(actor, types) { | ||||
|         if (this._removeEffect(this._skippedActors, actor)) | ||||
|             return false; | ||||
|  | ||||
|         if (!this._shouldAnimate()) | ||||
|             return false; | ||||
|  | ||||
| @@ -1358,13 +1337,9 @@ const WindowManager = new Lang.Class({ | ||||
|     _hasAttachedDialogs: function(window, ignoreWindow) { | ||||
|         var count = 0; | ||||
|         window.foreach_transient(function(win) { | ||||
|             if (win != ignoreWindow && | ||||
|                 win.is_attached_dialog() && | ||||
|                 win.get_transient_for() == window) { | ||||
|             if (win != ignoreWindow && win.is_attached_dialog()) | ||||
|                 count++; | ||||
|                 return false; | ||||
|             } | ||||
|             return true; | ||||
|             return false; | ||||
|         }); | ||||
|         return count != 0; | ||||
|     }, | ||||
| @@ -1392,14 +1367,11 @@ const WindowManager = new Lang.Class({ | ||||
|         let dimmer = getWindowDimmer(actor); | ||||
|         if (!dimmer) | ||||
|             return; | ||||
|         if (this._shouldAnimate()) | ||||
|             Tweener.addTween(dimmer, | ||||
|                              { dimFactor: 1.0, | ||||
|                                time: DIM_TIME, | ||||
|                                transition: 'linear' | ||||
|                              }); | ||||
|         else | ||||
|             dimmer.dimFactor = 1.0; | ||||
|         Tweener.addTween(dimmer, | ||||
|                          { dimFactor: 1.0, | ||||
|                            time: DIM_TIME, | ||||
|                            transition: 'linear' | ||||
|                          }); | ||||
|     }, | ||||
|  | ||||
|     _undimWindow: function(window) { | ||||
| @@ -1409,13 +1381,10 @@ const WindowManager = new Lang.Class({ | ||||
|         let dimmer = getWindowDimmer(actor); | ||||
|         if (!dimmer) | ||||
|             return; | ||||
|         if (this._shouldAnimate()) | ||||
|             Tweener.addTween(dimmer, | ||||
|                              { dimFactor: 0.0, | ||||
|                                time: UNDIM_TIME, | ||||
|                                transition: 'linear' }); | ||||
|         else | ||||
|             dimmer.dimFactor = 0.0; | ||||
|         Tweener.addTween(dimmer, | ||||
|                          { dimFactor: 0.0, | ||||
|                            time: UNDIM_TIME, | ||||
|                            transition: 'linear' }); | ||||
|     }, | ||||
|  | ||||
|     _mapWindow : function(shellwm, actor) { | ||||
| @@ -1433,14 +1402,6 @@ const WindowManager = new Lang.Class({ | ||||
|  | ||||
|             actor._windowType = type; | ||||
|         })); | ||||
|         actor.meta_window.connect('unmanaged', Lang.bind(this, function(window) { | ||||
|                 let parent = window.get_transient_for(); | ||||
|                 if (parent) | ||||
|                     this._checkDimming(parent); | ||||
|         })); | ||||
|  | ||||
|         if (actor.meta_window.is_attached_dialog()) | ||||
|             this._checkDimming(actor.get_meta_window().get_transient_for()); | ||||
|  | ||||
|         let types = [Meta.WindowType.NORMAL, | ||||
|                      Meta.WindowType.DIALOG, | ||||
| @@ -1450,6 +1411,9 @@ const WindowManager = new Lang.Class({ | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (actor.meta_window.is_attached_dialog()) | ||||
|             this._checkDimming(actor.get_meta_window().get_transient_for()); | ||||
|  | ||||
|         switch (actor._windowType) { | ||||
|         case Meta.WindowType.NORMAL: | ||||
|             actor.set_pivot_point(0.5, 1.0); | ||||
| @@ -1532,9 +1496,6 @@ const WindowManager = new Lang.Class({ | ||||
|                                                              }); | ||||
|         } | ||||
|  | ||||
|         if (window.is_attached_dialog()) | ||||
|             this._checkDimming(window.get_transient_for(), window); | ||||
|  | ||||
|         let types = [Meta.WindowType.NORMAL, | ||||
|                      Meta.WindowType.DIALOG, | ||||
|                      Meta.WindowType.MODAL_DIALOG]; | ||||
| @@ -1569,6 +1530,7 @@ const WindowManager = new Lang.Class({ | ||||
|  | ||||
|             if (window.is_attached_dialog()) { | ||||
|                 let parent = window.get_transient_for(); | ||||
|                 this._checkDimming(parent, window); | ||||
|                 actor._parentDestroyId = parent.connect('unmanaged', Lang.bind(this, function () { | ||||
|                     Tweener.removeTweens(actor); | ||||
|                     this._destroyWindowDone(shellwm, actor); | ||||
| @@ -1774,37 +1736,23 @@ const WindowManager = new Lang.Class({ | ||||
|         this._windowMenuManager.showWindowMenuForWindow(window, menu, rect); | ||||
|     }, | ||||
|  | ||||
|     _startSwitcher: function(display, screen, window, binding) { | ||||
|         let constructor = null; | ||||
|         switch (binding.get_name()) { | ||||
|             case 'switch-applications': | ||||
|             case 'switch-applications-backward': | ||||
|             case 'switch-group': | ||||
|             case 'switch-group-backward': | ||||
|                 constructor = AltTab.AppSwitcherPopup; | ||||
|                 break; | ||||
|             case 'switch-windows': | ||||
|             case 'switch-windows-backward': | ||||
|                 constructor = AltTab.WindowSwitcherPopup; | ||||
|                 break; | ||||
|             case 'cycle-windows': | ||||
|             case 'cycle-windows-backward': | ||||
|                 constructor = AltTab.WindowCyclerPopup; | ||||
|                 break; | ||||
|             case 'cycle-group': | ||||
|             case 'cycle-group-backward': | ||||
|                 constructor = AltTab.GroupCyclerPopup; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         if (!constructor) | ||||
|             return; | ||||
|  | ||||
|     _startAppSwitcher : function(display, screen, window, binding) { | ||||
|         /* prevent a corner case where both popups show up at once */ | ||||
|         if (this._workspaceSwitcherPopup != null) | ||||
|             this._workspaceSwitcherPopup.destroy(); | ||||
|  | ||||
|         let tabPopup = new constructor(); | ||||
|         let tabPopup = new AltTab.AppSwitcherPopup(); | ||||
|  | ||||
|         if (!tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask())) | ||||
|             tabPopup.destroy(); | ||||
|     }, | ||||
|  | ||||
|     _startWindowSwitcher : function(display, screen, window, binding) { | ||||
|         /* prevent a corner case where both popups show up at once */ | ||||
|         if (this._workspaceSwitcherPopup != null) | ||||
|             this._workspaceSwitcherPopup.destroy(); | ||||
|  | ||||
|         let tabPopup = new AltTab.WindowSwitcherPopup(); | ||||
|  | ||||
|         if (!tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask())) | ||||
|             tabPopup.destroy(); | ||||
|   | ||||
| @@ -19,7 +19,8 @@ const WorkspaceSwitcherPopup = new Lang.Class({ | ||||
|     Name: 'WorkspaceSwitcherPopup', | ||||
|  | ||||
|     _init : function() { | ||||
|         this.actor = new St.Widget({ x: 0, | ||||
|         this.actor = new St.Widget({ reactive: true, | ||||
|                                      x: 0, | ||||
|                                      y: 0, | ||||
|                                      width: global.screen_width, | ||||
|                                      height: global.screen_height, | ||||
|   | ||||
| @@ -45,11 +45,11 @@ const PrimaryActorLayout = new Lang.Class({ | ||||
|         this.primaryActor = primaryActor; | ||||
|     }, | ||||
|  | ||||
|     vfunc_get_preferred_width: function(container, forHeight) { | ||||
|     vfunc_get_preferred_width: function(forHeight) { | ||||
|         return this.primaryActor.get_preferred_width(forHeight); | ||||
|     }, | ||||
|  | ||||
|     vfunc_get_preferred_height: function(container, forWidth) { | ||||
|     vfunc_get_preferred_height: function(forWidth) { | ||||
|         return this.primaryActor.get_preferred_height(forWidth); | ||||
|     }, | ||||
| }); | ||||
|   | ||||
| @@ -103,7 +103,7 @@ const WorkspacesView = new Lang.Class({ | ||||
|                                                     page_increment: 1, | ||||
|                                                     page_size: 1, | ||||
|                                                     step_increment: 0, | ||||
|                                                     upper: global.screen.n_workspaces }); | ||||
|                                                     upper: 0 }); | ||||
|         this.scrollAdjustment.connect('notify::value', | ||||
|                                       Lang.bind(this, this._onScroll)); | ||||
|  | ||||
| @@ -374,10 +374,6 @@ const ExtraWorkspaceView = new Lang.Class({ | ||||
|         this._workspace.setActualGeometry(this._actualGeometry); | ||||
|     }, | ||||
|  | ||||
|     getActiveWorkspace: function() { | ||||
|         return this._workspace; | ||||
|     }, | ||||
|  | ||||
|     animateToOverview: function(animationType) { | ||||
|         if (animationType == AnimationType.ZOOM) | ||||
|             this._workspace.zoomToOverview(); | ||||
| @@ -425,10 +421,8 @@ const WorkspacesDisplay = new Lang.Class({ | ||||
|             // Only switch to the workspace when there's no application | ||||
|             // windows open. The problem is that it's too easy to miss | ||||
|             // an app window and get the wrong one focused. | ||||
|             let event = Clutter.get_current_event(); | ||||
|             let index = this._getMonitorIndexForEvent(event); | ||||
|             if ((action.get_button() == 1 || action.get_button() == 0) && | ||||
|                 this._workspacesViews[index].getActiveWorkspace().isEmpty()) | ||||
|                 this._getPrimaryView().getActiveWorkspace().isEmpty()) | ||||
|                 Main.overview.hide(); | ||||
|         })); | ||||
|         Main.overview.addAction(clickAction); | ||||
| @@ -437,18 +431,11 @@ const WorkspacesDisplay = new Lang.Class({ | ||||
|         let panAction = new Clutter.PanAction({ threshold_trigger_edge: Clutter.GestureTriggerEdge.AFTER }); | ||||
|         panAction.connect('pan', Lang.bind(this, this._onPan)); | ||||
|         panAction.connect('gesture-begin', Lang.bind(this, function() { | ||||
|             if (this._workspacesOnlyOnPrimary) { | ||||
|                 let event = Clutter.get_current_event(); | ||||
|                 if (this._getMonitorIndexForEvent(event) != this._primaryIndex) | ||||
|                     return false; | ||||
|             } | ||||
|  | ||||
|             for (let i = 0; i < this._workspacesViews.length; i++) | ||||
|                 this._workspacesViews[i].startSwipeScroll(); | ||||
|             return true; | ||||
|         })); | ||||
|         panAction.connect('gesture-cancel', Lang.bind(this, function() { | ||||
|             clickAction.release(); | ||||
|             for (let i = 0; i < this._workspacesViews.length; i++) | ||||
|                 this._workspacesViews[i].endSwipeScroll(); | ||||
|         })); | ||||
| @@ -594,12 +581,6 @@ const WorkspacesDisplay = new Lang.Class({ | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _getMonitorIndexForEvent: function(event) { | ||||
|         let [x, y] = event.get_coords(); | ||||
|         let rect = new Meta.Rectangle({ x: x, y: y, width: 1, height: 1 }); | ||||
|         return global.screen.get_monitor_index_for_rect(rect); | ||||
|     }, | ||||
|  | ||||
|     _getPrimaryView: function() { | ||||
|         if (!this._workspacesViews.length) | ||||
|             return null; | ||||
| @@ -680,11 +661,6 @@ const WorkspacesDisplay = new Lang.Class({ | ||||
|     _onScrollEvent: function(actor, event) { | ||||
|         if (!this.actor.mapped) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         if (this._workspacesOnlyOnPrimary && | ||||
|             this._getMonitorIndexForEvent(event) != this._primaryIndex) | ||||
|             return Clutter.EVENT_PROPAGATE; | ||||
|  | ||||
|         let activeWs = global.screen.get_active_workspace(); | ||||
|         let ws; | ||||
|         switch (event.get_scroll_direction()) { | ||||
|   | ||||
| @@ -29,7 +29,6 @@ gl | ||||
| gu | ||||
| he | ||||
| hi | ||||
| hr | ||||
| hu | ||||
| ia | ||||
| id | ||||
|   | ||||
							
								
								
									
										68
									
								
								po/Makevars
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								po/Makevars
									
									
									
									
									
								
							| @@ -1,68 +0,0 @@ | ||||
| # Makefile variables for PO directory in any package using GNU gettext. | ||||
|  | ||||
| # Usually the message domain is the same as the package name. | ||||
| DOMAIN = $(PACKAGE) | ||||
|  | ||||
| # These two variables depend on the location of this directory. | ||||
| subdir = po | ||||
| top_builddir = .. | ||||
|  | ||||
| # These options get passed to xgettext. | ||||
| XGETTEXT_OPTIONS = --from-code=UTF-8 --keyword=_ --keyword=N_ \ | ||||
|         --keyword=C_:1c,2 --keyword=NC_:1c,2 \ | ||||
|         --keyword=g_dngettext:2,3 --add-comments \ | ||||
|         --flag=g_dngettext:2:pass-c-format \ | ||||
|         --flag=g_strdup_printf:1:c-format \ | ||||
|         --flag=g_string_printf:2:c-format \ | ||||
|         --flag=g_string_append_printf:2:c-format \ | ||||
|         --flag=g_error_new:3:c-format \ | ||||
|         --flag=g_set_error:4:c-format \ | ||||
|         --flag=g_markup_printf_escaped:1:c-format \ | ||||
|         --flag=g_log:3:c-format \ | ||||
|         --flag=g_print:1:c-format \ | ||||
|         --flag=g_printerr:1:c-format \ | ||||
|         --flag=g_printf:1:c-format \ | ||||
|         --flag=g_fprintf:2:c-format \ | ||||
|         --flag=g_sprintf:2:c-format \ | ||||
|         --flag=g_snprintf:3:c-format | ||||
|  | ||||
|  | ||||
| # This is the copyright holder that gets inserted into the header of the | ||||
| # $(DOMAIN).pot file.  Set this to the copyright holder of the surrounding | ||||
| # package.  (Note that the msgstr strings, extracted from the package's | ||||
| # sources, belong to the copyright holder of the package.)  Translators are | ||||
| # expected to transfer the copyright for their translations to this person | ||||
| # or entity, or to disclaim their copyright.  The empty string stands for | ||||
| # the public domain; in this case the translators are expected to disclaim | ||||
| # their copyright. | ||||
| COPYRIGHT_HOLDER = Translation copyright holder | ||||
| # This is the email address or URL to which the translators shall report | ||||
| # bugs in the untranslated strings: | ||||
| # - Strings which are not entire sentences, see the maintainer guidelines | ||||
| #   in the GNU gettext documentation, section 'Preparing Strings'. | ||||
| # - Strings which use unclear terms or require additional context to be | ||||
| #   understood. | ||||
| # - Strings which make invalid assumptions about notation of date, time or | ||||
| #   money. | ||||
| # - Pluralisation problems. | ||||
| # - Incorrect English spelling. | ||||
| # - Incorrect formatting. | ||||
| # It can be your email address, or a mailing list address where translators | ||||
| # can write to without being subscribed, or the URL of a web page through | ||||
| # which the translators can contact you. | ||||
| MSGID_BUGS_ADDRESS = http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&keywords=I18N+L10N&component=general | ||||
|  | ||||
| # This is the list of locale categories, beyond LC_MESSAGES, for which the | ||||
| # message catalogs shall be used.  It is usually empty. | ||||
| EXTRA_LOCALE_CATEGORIES = | ||||
|  | ||||
| # Ignore the timestamp of the .pot file, as git clones do not have | ||||
| # deterministic timestamps, and .po files are updated by translators | ||||
| # (only) in GNOME projects. | ||||
| PO_DEPENDS_ON_POT = no | ||||
|  | ||||
| # This tells whether or not to forcibly update $(DOMAIN).pot and | ||||
| # regenerate PO files on "make dist".  Possible values are "yes" and | ||||
| # "no".  Set this to no if the POT file and PO files are maintained | ||||
| # externally. | ||||
| DIST_DEPENDS_ON_UPDATE_PO = no | ||||
| @@ -1,20 +1,19 @@ | ||||
| # List of source files containing translatable strings. | ||||
| # Please keep this file sorted alphabetically. | ||||
| data/50-gnome-shell-system.xml | ||||
| [encoding: UTF-8] | ||||
| data/50-gnome-shell-system.xml.in | ||||
| data/gnome-shell-extension-prefs.desktop.in.in | ||||
| data/org.gnome.Shell.desktop.in.in | ||||
| data/org.gnome.shell.gschema.xml.in | ||||
| data/org.gnome.Shell.PortalHelper.desktop.in.in | ||||
| data/org.gnome.shell.gschema.xml.in.in | ||||
| data/org.gnome.Shell.PortalHelper.desktop.in | ||||
| js/extensionPrefs/main.js | ||||
| js/gdm/authPrompt.js | ||||
| js/gdm/loginDialog.js | ||||
| js/gdm/util.js | ||||
| js/misc/util.js | ||||
| js/portalHelper/main.js | ||||
| js/ui/accessDialog.js | ||||
| js/ui/appDisplay.js | ||||
| js/ui/appFavorites.js | ||||
| js/ui/audioDeviceSelection.js | ||||
| js/ui/backgroundMenu.js | ||||
| js/ui/calendar.js | ||||
| js/ui/components/automountManager.js | ||||
| @@ -33,9 +32,7 @@ js/ui/keyboard.js | ||||
| js/ui/legacyTray.js | ||||
| js/ui/lookingGlass.js | ||||
| js/ui/main.js | ||||
| js/ui/messageList.js | ||||
| js/ui/messageTray.js | ||||
| js/ui/mpris.js | ||||
| js/ui/notificationDaemon.js | ||||
| js/ui/overviewControls.js | ||||
| js/ui/overview.js | ||||
| @@ -61,7 +58,7 @@ js/ui/viewSelector.js | ||||
| js/ui/windowAttentionHandler.js | ||||
| js/ui/windowManager.js | ||||
| js/ui/windowMenu.js | ||||
| src/calendar-server/evolution-calendar.desktop.in | ||||
| src/calendar-server/evolution-calendar.desktop.in.in | ||||
| # Please do not remove this file from POTFILES.in. Run "git submodule init && git submodule update" to get it. | ||||
| src/gvc/gvc-mixer-control.c | ||||
| src/main.c | ||||
|   | ||||
							
								
								
									
										4
									
								
								po/POTFILES.skip
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								po/POTFILES.skip
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| data/org.gnome.shell.evolution.calendar.gschema.xml.in | ||||
| src/calendar-server/evolution-calendar.desktop.in | ||||
| # Meh, autofools :-( | ||||
| sub/src/calendar-server/evolution-calendar.desktop.in | ||||
							
								
								
									
										2
									
								
								po/as.po
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								po/as.po
									
									
									
									
									
								
							| @@ -13,7 +13,7 @@ msgstr "" | ||||
| "PO-Revision-Date: 2014-09-15 14:59+0530\n" | ||||
| "Last-Translator: Nilamdyuti Goswami <ngoswami@redhat.com>\n" | ||||
| "Language-Team: Assamese <kde-i18n-doc@kde.org>\n" | ||||
| "Language: as\n" | ||||
| "Language: as_IN\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
|   | ||||
							
								
								
									
										135
									
								
								po/bg.po
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								po/bg.po
									
									
									
									
									
								
							| @@ -9,8 +9,8 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: gnome-shell master\n" | ||||
| "Report-Msgid-Bugs-To: \n" | ||||
| "POT-Creation-Date: 2016-04-09 08:29+0300\n" | ||||
| "PO-Revision-Date: 2016-04-09 07:09+0300\n" | ||||
| "POT-Creation-Date: 2016-01-22 07:45+0200\n" | ||||
| "PO-Revision-Date: 2016-01-22 07:45+0200\n" | ||||
| "Last-Translator: Alexander Shopov <ash@kambanaria.org>\n" | ||||
| "Language-Team: Bulgarian <dict@fsa-bg.org>\n" | ||||
| "Language: bg\n" | ||||
| @@ -316,17 +316,16 @@ msgstr "" | ||||
| msgid "Network Login" | ||||
| msgstr "Мрежов вход" | ||||
|  | ||||
| #: ../js/extensionPrefs/main.js:117 | ||||
| #: ../js/extensionPrefs/main.js:122 | ||||
| #, javascript-format | ||||
| msgid "There was an error loading the preferences dialog for %s:" | ||||
| msgstr "Грешка при зареждане на прозореца с настройки за „%s“" | ||||
|  | ||||
| #: ../js/extensionPrefs/main.js:149 | ||||
| #: ../js/extensionPrefs/main.js:154 | ||||
| msgid "GNOME Shell Extensions" | ||||
| msgstr "Разширения на обвивката на GNOME" | ||||
|  | ||||
| #: ../js/gdm/authPrompt.js:147 ../js/ui/audioDeviceSelection.js:71 | ||||
| #: ../js/ui/components/networkAgent.js:145 | ||||
| #: ../js/gdm/authPrompt.js:147 ../js/ui/components/networkAgent.js:145 | ||||
| #: ../js/ui/components/polkitAgent.js:179 ../js/ui/endSessionDialog.js:452 | ||||
| #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 | ||||
| #: ../js/ui/status/network.js:916 | ||||
| @@ -510,36 +509,16 @@ msgstr "Добавяне в „Любими“" | ||||
| msgid "Show Details" | ||||
| msgstr "Показване на подробности" | ||||
|  | ||||
| #: ../js/ui/appFavorites.js:134 | ||||
| #: ../js/ui/appFavorites.js:133 | ||||
| #, javascript-format | ||||
| msgid "%s has been added to your favorites." | ||||
| msgstr "Програмата „%s“ беше добавена в „Любими“" | ||||
|  | ||||
| #: ../js/ui/appFavorites.js:168 | ||||
| #: ../js/ui/appFavorites.js:167 | ||||
| #, javascript-format | ||||
| msgid "%s has been removed from your favorites." | ||||
| msgstr "Програмата „%s“ беше премахната от „Любими“" | ||||
|  | ||||
| #: ../js/ui/audioDeviceSelection.js:59 | ||||
| msgid "Select Audio Device" | ||||
| msgstr "Избор на устройство за аудио" | ||||
|  | ||||
| #: ../js/ui/audioDeviceSelection.js:69 | ||||
| msgid "Sound Settings" | ||||
| msgstr "Настройки на звука" | ||||
|  | ||||
| #: ../js/ui/audioDeviceSelection.js:78 | ||||
| msgid "Headphones" | ||||
| msgstr "Слушалки" | ||||
|  | ||||
| #: ../js/ui/audioDeviceSelection.js:80 | ||||
| msgid "Headset" | ||||
| msgstr "Малки слушалки" | ||||
|  | ||||
| #: ../js/ui/audioDeviceSelection.js:82 ../js/ui/status/volume.js:213 | ||||
| msgid "Microphone" | ||||
| msgstr "Микрофон" | ||||
|  | ||||
| #: ../js/ui/backgroundMenu.js:19 | ||||
| msgid "Change Background…" | ||||
| msgstr "Смяна на фона…" | ||||
| @@ -553,7 +532,7 @@ msgid "Settings" | ||||
| msgstr "Настройки" | ||||
|  | ||||
| #. Translators: Enter 0-6 (Sunday-Saturday) for non-work days. Examples: "0" (Sunday) "6" (Saturday) "06" (Sunday and Saturday). | ||||
| #: ../js/ui/calendar.js:47 | ||||
| #: ../js/ui/calendar.js:55 | ||||
| msgctxt "calendar-no-work" | ||||
| msgid "06" | ||||
| msgstr "06" | ||||
| @@ -563,96 +542,100 @@ msgstr "06" | ||||
| #. * NOTE: These grid abbreviations are always shown together | ||||
| #. * and in order, e.g. "S M T W T F S". | ||||
| #. | ||||
| #: ../js/ui/calendar.js:76 | ||||
| #: ../js/ui/calendar.js:84 | ||||
| msgctxt "grid sunday" | ||||
| msgid "S" | ||||
| msgstr "Н" | ||||
|  | ||||
| #. Translators: Calendar grid abbreviation for Monday | ||||
| #: ../js/ui/calendar.js:78 | ||||
| #: ../js/ui/calendar.js:86 | ||||
| msgctxt "grid monday" | ||||
| msgid "M" | ||||
| msgstr "П" | ||||
|  | ||||
| #. Translators: Calendar grid abbreviation for Tuesday | ||||
| #: ../js/ui/calendar.js:80 | ||||
| #: ../js/ui/calendar.js:88 | ||||
| msgctxt "grid tuesday" | ||||
| msgid "T" | ||||
| msgstr "В" | ||||
|  | ||||
| #. Translators: Calendar grid abbreviation for Wednesday | ||||
| #: ../js/ui/calendar.js:82 | ||||
| #: ../js/ui/calendar.js:90 | ||||
| msgctxt "grid wednesday" | ||||
| msgid "W" | ||||
| msgstr "С" | ||||
|  | ||||
| #. Translators: Calendar grid abbreviation for Thursday | ||||
| #: ../js/ui/calendar.js:84 | ||||
| #: ../js/ui/calendar.js:92 | ||||
| msgctxt "grid thursday" | ||||
| msgid "T" | ||||
| msgstr "Ч" | ||||
|  | ||||
| #. Translators: Calendar grid abbreviation for Friday | ||||
| #: ../js/ui/calendar.js:86 | ||||
| #: ../js/ui/calendar.js:94 | ||||
| msgctxt "grid friday" | ||||
| msgid "F" | ||||
| msgstr "П" | ||||
|  | ||||
| #. Translators: Calendar grid abbreviation for Saturday | ||||
| #: ../js/ui/calendar.js:88 | ||||
| #: ../js/ui/calendar.js:96 | ||||
| msgctxt "grid saturday" | ||||
| msgid "S" | ||||
| msgstr "С" | ||||
|  | ||||
| #: ../js/ui/calendar.js:416 | ||||
| #: ../js/ui/calendar.js:566 | ||||
| msgid "Previous month" | ||||
| msgstr "Предния месец" | ||||
|  | ||||
| #: ../js/ui/calendar.js:426 | ||||
| #: ../js/ui/calendar.js:576 | ||||
| msgid "Next month" | ||||
| msgstr "Следващия месец" | ||||
|  | ||||
| #: ../js/ui/calendar.js:579 | ||||
| #: ../js/ui/calendar.js:729 | ||||
| #, no-javascript-format | ||||
| msgctxt "date day number format" | ||||
| msgid "%d" | ||||
| msgstr "%d" | ||||
|  | ||||
| #: ../js/ui/calendar.js:634 | ||||
| #: ../js/ui/calendar.js:784 | ||||
| msgid "Week %V" | ||||
| msgstr "%V-а седмица" | ||||
|  | ||||
| #. Translators: Shown in calendar event list for all day events | ||||
| #. * Keep it short, best if you can use less then 10 characters | ||||
| #. | ||||
| #: ../js/ui/calendar.js:695 | ||||
| #: ../js/ui/calendar.js:1189 | ||||
| msgctxt "event list time" | ||||
| msgid "All Day" | ||||
| msgstr "Цял ден" | ||||
|  | ||||
| #: ../js/ui/calendar.js:821 | ||||
| #: ../js/ui/calendar.js:1296 | ||||
| msgid "Clear section" | ||||
| msgstr "Изчистване" | ||||
|  | ||||
| #: ../js/ui/calendar.js:1523 | ||||
| msgid "Events" | ||||
| msgstr "Събития" | ||||
|  | ||||
| #: ../js/ui/calendar.js:830 | ||||
| #: ../js/ui/calendar.js:1532 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%A, %e %B" | ||||
|  | ||||
| #: ../js/ui/calendar.js:834 | ||||
| #: ../js/ui/calendar.js:1536 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d, %Y" | ||||
| msgstr "%A, %e %B %Y" | ||||
|  | ||||
| #: ../js/ui/calendar.js:919 | ||||
| #: ../js/ui/calendar.js:1621 | ||||
| msgid "Notifications" | ||||
| msgstr "Известия" | ||||
|  | ||||
| #: ../js/ui/calendar.js:1070 | ||||
| #: ../js/ui/calendar.js:1772 | ||||
| msgid "No Notifications" | ||||
| msgstr "Няма известия" | ||||
|  | ||||
| #: ../js/ui/calendar.js:1073 | ||||
| #: ../js/ui/calendar.js:1775 | ||||
| msgid "No Events" | ||||
| msgstr "Няма събития" | ||||
|  | ||||
| @@ -790,7 +773,7 @@ msgstr "Неуспешно действие. Опитайте отново." | ||||
|  | ||||
| #. Translators: this is the other person changing their old IM name to their new | ||||
| #. IM name. | ||||
| #: ../js/ui/components/telepathyClient.js:760 | ||||
| #: ../js/ui/components/telepathyClient.js:759 | ||||
| #, javascript-format | ||||
| msgid "%s is now known as %s" | ||||
| msgstr "„%s“ в момента е познат като „%s“" | ||||
| @@ -980,11 +963,11 @@ msgid "Keyboard" | ||||
| msgstr "Клавиатура" | ||||
|  | ||||
| #. translators: 'Hide' is a verb | ||||
| #: ../js/ui/legacyTray.js:65 | ||||
| #: ../js/ui/legacyTray.js:66 | ||||
| msgid "Hide tray" | ||||
| msgstr "Скриване на областта" | ||||
|  | ||||
| #: ../js/ui/legacyTray.js:106 | ||||
| #: ../js/ui/legacyTray.js:107 | ||||
| msgid "Status Icons" | ||||
| msgstr "Икони за състоянието" | ||||
|  | ||||
| @@ -1036,26 +1019,10 @@ msgstr "Преглед на изходния код" | ||||
| msgid "Web Page" | ||||
| msgstr "Домашна страница" | ||||
|  | ||||
| #: ../js/ui/messageList.js:543 | ||||
| msgid "Clear section" | ||||
| msgstr "Изчистване" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1486 | ||||
| msgid "System Information" | ||||
| msgstr "Информация за системата" | ||||
|  | ||||
| #: ../js/ui/mpris.js:194 | ||||
| msgid "Unknown artist" | ||||
| msgstr "Неизвестен изпълнител" | ||||
|  | ||||
| #: ../js/ui/mpris.js:195 | ||||
| msgid "Unknown title" | ||||
| msgstr "Неизвестно заглавие" | ||||
|  | ||||
| #: ../js/ui/mpris.js:217 | ||||
| msgid "Media" | ||||
| msgstr "Медиа" | ||||
|  | ||||
| #: ../js/ui/overview.js:84 | ||||
| msgid "Undo" | ||||
| msgstr "Отмяна" | ||||
| @@ -1274,50 +1241,30 @@ msgstr "Яркост" | ||||
| msgid "Show Keyboard Layout" | ||||
| msgstr "Показване на клавиатурната подредба" | ||||
|  | ||||
| #: ../js/ui/status/location.js:107 ../js/ui/status/location.js:215 | ||||
| #: ../js/ui/status/location.js:71 ../js/ui/status/location.js:177 | ||||
| msgid "Location Enabled" | ||||
| msgstr "Местоположението е включено" | ||||
|  | ||||
| #: ../js/ui/status/location.js:108 ../js/ui/status/location.js:216 | ||||
| #: ../js/ui/status/location.js:72 ../js/ui/status/location.js:178 | ||||
| msgid "Disable" | ||||
| msgstr "Изключване" | ||||
|  | ||||
| #: ../js/ui/status/location.js:109 | ||||
| #: ../js/ui/status/location.js:73 | ||||
| msgid "Privacy Settings" | ||||
| msgstr "Настройки за поверителност" | ||||
|  | ||||
| #: ../js/ui/status/location.js:214 | ||||
| #: ../js/ui/status/location.js:176 | ||||
| msgid "Location In Use" | ||||
| msgstr "Текущо местоположение" | ||||
|  | ||||
| #: ../js/ui/status/location.js:218 | ||||
| #: ../js/ui/status/location.js:180 | ||||
| msgid "Location Disabled" | ||||
| msgstr "Местоположението е изключено" | ||||
|  | ||||
| #: ../js/ui/status/location.js:219 | ||||
| #: ../js/ui/status/location.js:181 | ||||
| msgid "Enable" | ||||
| msgstr "Включване" | ||||
|  | ||||
| #: ../js/ui/status/location.js:426 | ||||
| msgid "Deny Access" | ||||
| msgstr "Отказване на достъп" | ||||
|  | ||||
| #: ../js/ui/status/location.js:429 | ||||
| msgid "Grant Access" | ||||
| msgstr "Позволяване на достъп" | ||||
|  | ||||
| #. Translators: %s is an application name | ||||
| #: ../js/ui/status/location.js:435 | ||||
| #, javascript-format | ||||
| msgid "Give %s access to your location?" | ||||
| msgstr "Да се сподели ли местоположението с „%s“?" | ||||
|  | ||||
| #: ../js/ui/status/location.js:437 | ||||
| msgid "Location access can be changed at any time from the privacy settings." | ||||
| msgstr "" | ||||
| "Може да промените правата за достъп до местоположението през настройките за " | ||||
| "лични данни." | ||||
|  | ||||
| #: ../js/ui/status/network.js:101 | ||||
| msgid "<unknown>" | ||||
| msgstr "<неизвестно>" | ||||
| @@ -1572,6 +1519,10 @@ msgstr "Променена сила на звука" | ||||
| msgid "Volume" | ||||
| msgstr "Сила на звука" | ||||
|  | ||||
| #: ../js/ui/status/volume.js:213 | ||||
| msgid "Microphone" | ||||
| msgstr "Микрофон" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:67 | ||||
| msgid "Log in as another user" | ||||
| msgstr "Вход като друг потребител" | ||||
|   | ||||
							
								
								
									
										1
									
								
								po/bn.po
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								po/bn.po
									
									
									
									
									
								
							| @@ -7,7 +7,6 @@ msgstr "" | ||||
| "PO-Revision-Date: 2011-04-04 11:04+0600\n" | ||||
| "Last-Translator: Israt Jahan <israt@ankur.org.bd>\n" | ||||
| "Language-Team: Bengali <ankur-bd-l10n@googlegroups.com>\n" | ||||
| "Language: bn\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
|   | ||||
| @@ -11,7 +11,7 @@ msgstr "" | ||||
| "PO-Revision-Date: 2014-12-30 16:45+0000\n" | ||||
| "Last-Translator: \n" | ||||
| "Language-Team: American English <kde-i18n-doc@kde.org>\n" | ||||
| "Language: bn_IN\n" | ||||
| "Language: en_US\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
|   | ||||
| @@ -14,7 +14,7 @@ msgstr "" | ||||
| "PO-Revision-Date: 2014-09-14 23:32+0200\n" | ||||
| "Last-Translator: Gil Forcada <gilforcada@guifi.net>\n" | ||||
| "Language-Team: Catalan <tradgnome@softcatala.org>\n" | ||||
| "Language: ca@valencia\n" | ||||
| "Language: ca-XV\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bits\n" | ||||
|   | ||||
							
								
								
									
										2126
									
								
								po/en_GB.po
									
									
									
									
									
								
							
							
						
						
									
										2126
									
								
								po/en_GB.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2
									
								
								po/ga.po
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								po/ga.po
									
									
									
									
									
								
							| @@ -715,7 +715,7 @@ msgstr "Tá brón orm, theip sé sin. Bain triail eile as, le do thoil." | ||||
| #. Translators: this is the other person changing their old IM name to their new | ||||
| #. IM name. | ||||
| #: ../js/ui/components/telepathyClient.js:759 | ||||
| #, fuzzy, javascript-format | ||||
| #, javascript-format | ||||
| msgid "%s is now known as %s" | ||||
| msgstr "Tugtar %2$s ar %1$s anois" | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								po/gu.po
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								po/gu.po
									
									
									
									
									
								
							| @@ -13,7 +13,7 @@ msgstr "" | ||||
| "PO-Revision-Date: 2014-10-01 15:51+0530\n" | ||||
| "Last-Translator: \n" | ||||
| "Language-Team: American English <kde-i18n-doc@kde.org>\n" | ||||
| "Language: gu\n" | ||||
| "Language: \n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
|   | ||||
							
								
								
									
										2
									
								
								po/ky.po
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								po/ky.po
									
									
									
									
									
								
							| @@ -14,7 +14,7 @@ msgstr "" | ||||
| "PO-Revision-Date: 2012-09-24 14:29+0600\n" | ||||
| "Last-Translator: Timur Zhamakeev <ztimur@gmail.com>\n" | ||||
| "Language-Team: Kirghiz <gnome-i18n@gnome.org>\n" | ||||
| "Language: ky\n" | ||||
| "Language: ky_KG\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
|   | ||||
							
								
								
									
										1
									
								
								po/mk.po
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								po/mk.po
									
									
									
									
									
								
							| @@ -11,7 +11,6 @@ msgstr "" | ||||
| "PO-Revision-Date: 2011-12-08 22:37+0100\n" | ||||
| "Last-Translator: Jovan N\n" | ||||
| "Language-Team: mk_MK <jovan@lugola.net>\n" | ||||
| "Language: mk\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
|   | ||||
							
								
								
									
										2
									
								
								po/ms.po
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								po/ms.po
									
									
									
									
									
								
							| @@ -11,7 +11,7 @@ msgstr "" | ||||
| "PO-Revision-Date: 2014-09-15 19:21+0730\n" | ||||
| "Last-Translator: Umarzuki Mochlis Moktar <umar@umarzuki.org>\n" | ||||
| "Language-Team: GNOME Malay Team <gnome-ms@googlegroups.com>\n" | ||||
| "Language: ms\n" | ||||
| "Language: \n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
|   | ||||
							
								
								
									
										159
									
								
								po/nb.po
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								po/nb.po
									
									
									
									
									
								
							| @@ -9,11 +9,11 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: gnome-shell 3.19.x\n" | ||||
| "Report-Msgid-Bugs-To: \n" | ||||
| "POT-Creation-Date: 2016-05-01 14:12+0200\n" | ||||
| "PO-Revision-Date: 2016-05-01 14:21+0200\n" | ||||
| "POT-Creation-Date: 2016-01-07 22:59+0100\n" | ||||
| "PO-Revision-Date: 2016-01-07 22:59+0100\n" | ||||
| "Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n" | ||||
| "Language-Team: Norwegian bokmål <i18n-nb@lister.ping.uio.no>\n" | ||||
| "Language: nb\n" | ||||
| "Language: Norwegian bokmål\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| @@ -305,34 +305,33 @@ msgstr "Utsett fokusendringer i musmodus til peker slutter å bevege seg" | ||||
| msgid "Network Login" | ||||
| msgstr "Nettverkspålogging" | ||||
|  | ||||
| #: ../js/extensionPrefs/main.js:117 | ||||
| #: ../js/extensionPrefs/main.js:122 | ||||
| #, javascript-format | ||||
| msgid "There was an error loading the preferences dialog for %s:" | ||||
| msgstr "Det oppsto en feil ved lasting av brukervalgdialog for %s:" | ||||
|  | ||||
| #: ../js/extensionPrefs/main.js:149 | ||||
| #: ../js/extensionPrefs/main.js:154 | ||||
| msgid "GNOME Shell Extensions" | ||||
| msgstr "Utvidelser for GNOME Shell" | ||||
|  | ||||
| #: ../js/gdm/authPrompt.js:147 ../js/ui/audioDeviceSelection.js:71 | ||||
| #: ../js/ui/components/networkAgent.js:145 | ||||
| #: ../js/gdm/authPrompt.js:147 ../js/ui/components/networkAgent.js:145 | ||||
| #: ../js/ui/components/polkitAgent.js:179 ../js/ui/endSessionDialog.js:452 | ||||
| #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 | ||||
| #: ../js/ui/status/network.js:916 | ||||
| msgid "Cancel" | ||||
| msgstr "Avbryt" | ||||
|  | ||||
| #: ../js/gdm/authPrompt.js:169 ../js/gdm/authPrompt.js:216 | ||||
| #: ../js/gdm/authPrompt.js:448 | ||||
| #: ../js/gdm/authPrompt.js:169 ../js/gdm/authPrompt.js:215 | ||||
| #: ../js/gdm/authPrompt.js:447 | ||||
| msgid "Next" | ||||
| msgstr "Neste" | ||||
|  | ||||
| #: ../js/gdm/authPrompt.js:212 ../js/ui/shellMountOperation.js:403 | ||||
| #: ../js/gdm/authPrompt.js:211 ../js/ui/shellMountOperation.js:403 | ||||
| #: ../js/ui/unlockDialog.js:59 | ||||
| msgid "Unlock" | ||||
| msgstr "Lås opp" | ||||
|  | ||||
| #: ../js/gdm/authPrompt.js:214 | ||||
| #: ../js/gdm/authPrompt.js:213 | ||||
| msgctxt "button" | ||||
| msgid "Sign In" | ||||
| msgstr "Logg inn" | ||||
| @@ -499,36 +498,16 @@ msgstr "Legg til i favoritter" | ||||
| msgid "Show Details" | ||||
| msgstr "Vis detaljer" | ||||
|  | ||||
| #: ../js/ui/appFavorites.js:134 | ||||
| #: ../js/ui/appFavorites.js:133 | ||||
| #, javascript-format | ||||
| msgid "%s has been added to your favorites." | ||||
| msgstr "%s ble lagt til i favoritter." | ||||
|  | ||||
| #: ../js/ui/appFavorites.js:168 | ||||
| #: ../js/ui/appFavorites.js:167 | ||||
| #, javascript-format | ||||
| msgid "%s has been removed from your favorites." | ||||
| msgstr "%s ble fjernet fra favoritter." | ||||
|  | ||||
| #: ../js/ui/audioDeviceSelection.js:59 | ||||
| msgid "Select Audio Device" | ||||
| msgstr "Velg lydenhet" | ||||
|  | ||||
| #: ../js/ui/audioDeviceSelection.js:69 | ||||
| msgid "Sound Settings" | ||||
| msgstr "Innstillinger for lyd" | ||||
|  | ||||
| #: ../js/ui/audioDeviceSelection.js:78 | ||||
| msgid "Headphones" | ||||
| msgstr "Hodetelefoner" | ||||
|  | ||||
| #: ../js/ui/audioDeviceSelection.js:80 | ||||
| msgid "Headset" | ||||
| msgstr "Headset" | ||||
|  | ||||
| #: ../js/ui/audioDeviceSelection.js:82 ../js/ui/status/volume.js:213 | ||||
| msgid "Microphone" | ||||
| msgstr "Mikrofon" | ||||
|  | ||||
| #: ../js/ui/backgroundMenu.js:19 | ||||
| msgid "Change Background…" | ||||
| msgstr "Bytt bakgrunn …" | ||||
| @@ -537,12 +516,12 @@ msgstr "Bytt bakgrunn …" | ||||
| msgid "Display Settings" | ||||
| msgstr "Innstillinger for skjerm" | ||||
|  | ||||
| #: ../js/ui/backgroundMenu.js:22 ../js/ui/status/system.js:371 | ||||
| #: ../js/ui/backgroundMenu.js:22 ../js/ui/status/system.js:366 | ||||
| msgid "Settings" | ||||
| msgstr "Innstillinger" | ||||
|  | ||||
| #. Translators: Enter 0-6 (Sunday-Saturday) for non-work days. Examples: "0" (Sunday) "6" (Saturday) "06" (Sunday and Saturday). | ||||
| #: ../js/ui/calendar.js:47 | ||||
| #: ../js/ui/calendar.js:55 | ||||
| msgctxt "calendar-no-work" | ||||
| msgid "06" | ||||
| msgstr "06" | ||||
| @@ -552,96 +531,100 @@ msgstr "06" | ||||
| #. * NOTE: These grid abbreviations are always shown together | ||||
| #. * and in order, e.g. "S M T W T F S". | ||||
| #. | ||||
| #: ../js/ui/calendar.js:76 | ||||
| #: ../js/ui/calendar.js:84 | ||||
| msgctxt "grid sunday" | ||||
| msgid "S" | ||||
| msgstr "S" | ||||
|  | ||||
| #. Translators: Calendar grid abbreviation for Monday | ||||
| #: ../js/ui/calendar.js:78 | ||||
| #: ../js/ui/calendar.js:86 | ||||
| msgctxt "grid monday" | ||||
| msgid "M" | ||||
| msgstr "M" | ||||
|  | ||||
| #. Translators: Calendar grid abbreviation for Tuesday | ||||
| #: ../js/ui/calendar.js:80 | ||||
| #: ../js/ui/calendar.js:88 | ||||
| msgctxt "grid tuesday" | ||||
| msgid "T" | ||||
| msgstr "T" | ||||
|  | ||||
| #. Translators: Calendar grid abbreviation for Wednesday | ||||
| #: ../js/ui/calendar.js:82 | ||||
| #: ../js/ui/calendar.js:90 | ||||
| msgctxt "grid wednesday" | ||||
| msgid "W" | ||||
| msgstr "O" | ||||
|  | ||||
| #. Translators: Calendar grid abbreviation for Thursday | ||||
| #: ../js/ui/calendar.js:84 | ||||
| #: ../js/ui/calendar.js:92 | ||||
| msgctxt "grid thursday" | ||||
| msgid "T" | ||||
| msgstr "T" | ||||
|  | ||||
| #. Translators: Calendar grid abbreviation for Friday | ||||
| #: ../js/ui/calendar.js:86 | ||||
| #: ../js/ui/calendar.js:94 | ||||
| msgctxt "grid friday" | ||||
| msgid "F" | ||||
| msgstr "F" | ||||
|  | ||||
| #. Translators: Calendar grid abbreviation for Saturday | ||||
| #: ../js/ui/calendar.js:88 | ||||
| #: ../js/ui/calendar.js:96 | ||||
| msgctxt "grid saturday" | ||||
| msgid "S" | ||||
| msgstr "L" | ||||
|  | ||||
| #: ../js/ui/calendar.js:416 | ||||
| #: ../js/ui/calendar.js:566 | ||||
| msgid "Previous month" | ||||
| msgstr "Forrige måned" | ||||
|  | ||||
| #: ../js/ui/calendar.js:426 | ||||
| #: ../js/ui/calendar.js:576 | ||||
| msgid "Next month" | ||||
| msgstr "Neste måned" | ||||
|  | ||||
| #: ../js/ui/calendar.js:579 | ||||
| #: ../js/ui/calendar.js:729 | ||||
| #, no-javascript-format | ||||
| msgctxt "date day number format" | ||||
| msgid "%d" | ||||
| msgstr "%d" | ||||
|  | ||||
| #: ../js/ui/calendar.js:634 | ||||
| #: ../js/ui/calendar.js:784 | ||||
| msgid "Week %V" | ||||
| msgstr "Uke %V" | ||||
|  | ||||
| #. Translators: Shown in calendar event list for all day events | ||||
| #. * Keep it short, best if you can use less then 10 characters | ||||
| #. | ||||
| #: ../js/ui/calendar.js:695 | ||||
| #: ../js/ui/calendar.js:1189 | ||||
| msgctxt "event list time" | ||||
| msgid "All Day" | ||||
| msgstr "Hele dagen" | ||||
|  | ||||
| #: ../js/ui/calendar.js:821 | ||||
| #: ../js/ui/calendar.js:1296 | ||||
| msgid "Clear section" | ||||
| msgstr "Tøm seksjon" | ||||
|  | ||||
| #: ../js/ui/calendar.js:1523 | ||||
| msgid "Events" | ||||
| msgstr "Hendelser" | ||||
|  | ||||
| #: ../js/ui/calendar.js:830 | ||||
| #: ../js/ui/calendar.js:1532 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%A %B %d" | ||||
|  | ||||
| #: ../js/ui/calendar.js:834 | ||||
| #: ../js/ui/calendar.js:1536 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d, %Y" | ||||
| msgstr "%A %B %d, %Y" | ||||
|  | ||||
| #: ../js/ui/calendar.js:919 | ||||
| #: ../js/ui/calendar.js:1621 | ||||
| msgid "Notifications" | ||||
| msgstr "Varslinger" | ||||
|  | ||||
| #: ../js/ui/calendar.js:1070 | ||||
| #: ../js/ui/calendar.js:1772 | ||||
| msgid "No Notifications" | ||||
| msgstr "Ingen varslinger" | ||||
|  | ||||
| #: ../js/ui/calendar.js:1073 | ||||
| #: ../js/ui/calendar.js:1775 | ||||
| msgid "No Events" | ||||
| msgstr "Ingen hendelser" | ||||
|  | ||||
| @@ -779,7 +762,7 @@ msgstr "Beklager, det virket ikke. Prøv igjen." | ||||
|  | ||||
| #. Translators: this is the other person changing their old IM name to their new | ||||
| #. IM name. | ||||
| #: ../js/ui/components/telepathyClient.js:760 | ||||
| #: ../js/ui/components/telepathyClient.js:759 | ||||
| #, javascript-format | ||||
| msgid "%s is now known as %s" | ||||
| msgstr "%s er nå kjent som %s" | ||||
| @@ -966,11 +949,11 @@ msgid "Keyboard" | ||||
| msgstr "Tastatur" | ||||
|  | ||||
| #. translators: 'Hide' is a verb | ||||
| #: ../js/ui/legacyTray.js:65 | ||||
| #: ../js/ui/legacyTray.js:66 | ||||
| msgid "Hide tray" | ||||
| msgstr "Skjul statusområde" | ||||
|  | ||||
| #: ../js/ui/legacyTray.js:106 | ||||
| #: ../js/ui/legacyTray.js:107 | ||||
| msgid "Status Icons" | ||||
| msgstr "Statusikoner" | ||||
|  | ||||
| @@ -1022,26 +1005,10 @@ msgstr "Vis kildekode" | ||||
| msgid "Web Page" | ||||
| msgstr "Nettside" | ||||
|  | ||||
| #: ../js/ui/messageList.js:543 | ||||
| msgid "Clear section" | ||||
| msgstr "Tøm seksjon" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1486 | ||||
| msgid "System Information" | ||||
| msgstr "Systeminformasjon" | ||||
|  | ||||
| #: ../js/ui/mpris.js:194 | ||||
| msgid "Unknown artist" | ||||
| msgstr "Ukjent artist" | ||||
|  | ||||
| #: ../js/ui/mpris.js:195 | ||||
| msgid "Unknown title" | ||||
| msgstr "Ukjent tittel" | ||||
|  | ||||
| #: ../js/ui/mpris.js:217 | ||||
| msgid "Media" | ||||
| msgstr "Media" | ||||
|  | ||||
| #: ../js/ui/overview.js:84 | ||||
| msgid "Undo" | ||||
| msgstr "Angre" | ||||
| @@ -1118,7 +1085,7 @@ msgid_plural "%d new notifications" | ||||
| msgstr[0] "%d ny varsling" | ||||
| msgstr[1] "%d nye varslinger" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:432 ../js/ui/status/system.js:379 | ||||
| #: ../js/ui/screenShield.js:432 ../js/ui/status/system.js:374 | ||||
| msgid "Lock" | ||||
| msgstr "Lås" | ||||
|  | ||||
| @@ -1260,48 +1227,30 @@ msgstr "Lysstyrke" | ||||
| msgid "Show Keyboard Layout" | ||||
| msgstr "Vis tastaturutforming" | ||||
|  | ||||
| #: ../js/ui/status/location.js:107 ../js/ui/status/location.js:215 | ||||
| #: ../js/ui/status/location.js:71 ../js/ui/status/location.js:177 | ||||
| msgid "Location Enabled" | ||||
| msgstr "Plassering slått på" | ||||
|  | ||||
| #: ../js/ui/status/location.js:108 ../js/ui/status/location.js:216 | ||||
| #: ../js/ui/status/location.js:72 ../js/ui/status/location.js:178 | ||||
| msgid "Disable" | ||||
| msgstr "Slå av" | ||||
|  | ||||
| #: ../js/ui/status/location.js:109 | ||||
| #: ../js/ui/status/location.js:73 | ||||
| msgid "Privacy Settings" | ||||
| msgstr "Innstillinger for personvern" | ||||
|  | ||||
| #: ../js/ui/status/location.js:214 | ||||
| #: ../js/ui/status/location.js:176 | ||||
| msgid "Location In Use" | ||||
| msgstr "Plassering i bruk" | ||||
|  | ||||
| #: ../js/ui/status/location.js:218 | ||||
| #: ../js/ui/status/location.js:180 | ||||
| msgid "Location Disabled" | ||||
| msgstr "Plassering slått av" | ||||
|  | ||||
| #: ../js/ui/status/location.js:219 | ||||
| #: ../js/ui/status/location.js:181 | ||||
| msgid "Enable" | ||||
| msgstr "Slå på" | ||||
|  | ||||
| #: ../js/ui/status/location.js:426 | ||||
| msgid "Deny Access" | ||||
| msgstr "Nekt tilgang" | ||||
|  | ||||
| #: ../js/ui/status/location.js:429 | ||||
| msgid "Grant Access" | ||||
| msgstr "Gi tilgang" | ||||
|  | ||||
| #. Translators: %s is an application name | ||||
| #: ../js/ui/status/location.js:435 | ||||
| #, javascript-format | ||||
| msgid "Give %s access to your location?" | ||||
| msgstr "Gi %s tilgang til din plassering?" | ||||
|  | ||||
| #: ../js/ui/status/location.js:437 | ||||
| msgid "Location access can be changed at any time from the privacy settings." | ||||
| msgstr "Tilgang til plassering kan endres når som helst fra innstillinger for personvern." | ||||
|  | ||||
| #: ../js/ui/status/network.js:101 | ||||
| msgid "<unknown>" | ||||
| msgstr "<ukjent>" | ||||
| @@ -1524,27 +1473,27 @@ msgstr "%d %%" | ||||
| msgid "Airplane Mode On" | ||||
| msgstr "Flymodus er slått på" | ||||
|  | ||||
| #: ../js/ui/status/system.js:348 | ||||
| #: ../js/ui/status/system.js:343 | ||||
| msgid "Switch User" | ||||
| msgstr "Bytt bruker" | ||||
|  | ||||
| #: ../js/ui/status/system.js:353 | ||||
| #: ../js/ui/status/system.js:348 | ||||
| msgid "Log Out" | ||||
| msgstr "Logg ut" | ||||
|  | ||||
| #: ../js/ui/status/system.js:358 | ||||
| #: ../js/ui/status/system.js:353 | ||||
| msgid "Account Settings" | ||||
| msgstr "Innstillinger for konto" | ||||
|  | ||||
| #: ../js/ui/status/system.js:375 | ||||
| #: ../js/ui/status/system.js:370 | ||||
| msgid "Orientation Lock" | ||||
| msgstr "Lås for orientering" | ||||
|  | ||||
| #: ../js/ui/status/system.js:383 | ||||
| #: ../js/ui/status/system.js:378 | ||||
| msgid "Suspend" | ||||
| msgstr "Hvilemodus" | ||||
|  | ||||
| #: ../js/ui/status/system.js:386 | ||||
| #: ../js/ui/status/system.js:381 | ||||
| msgid "Power Off" | ||||
| msgstr "Slå av" | ||||
|  | ||||
| @@ -1556,6 +1505,10 @@ msgstr "Volum endret" | ||||
| msgid "Volume" | ||||
| msgstr "Volum" | ||||
|  | ||||
| #: ../js/ui/status/volume.js:213 | ||||
| msgid "Microphone" | ||||
| msgstr "Mikrofon" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:67 | ||||
| msgid "Log in as another user" | ||||
| msgstr "Logg inn som en annen bruker" | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user