Compare commits
	
		
			159 Commits
		
	
	
		
			wip/gdbus-
			...
			wip/grab-h
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					64bacc6286 | ||
| 
						 | 
					50fec9e1f8 | ||
| 
						 | 
					b03f7564e3 | ||
| 
						 | 
					ef9006fa65 | ||
| 
						 | 
					485d16ca4e | ||
| 
						 | 
					1e40264ee4 | ||
| 
						 | 
					ae22bde368 | ||
| 
						 | 
					32502af652 | ||
| 
						 | 
					7d693cbd17 | ||
| 
						 | 
					d86e57a8d9 | ||
| 
						 | 
					75985ae0ce | ||
| 
						 | 
					7ee897ead5 | ||
| 
						 | 
					7c371392da | ||
| 
						 | 
					ab549f763d | ||
| 
						 | 
					ea25331a55 | ||
| 
						 | 
					c6bc1526fa | ||
| 
						 | 
					871ae3f9b2 | ||
| 
						 | 
					8ebbf442cd | ||
| 
						 | 
					b936f094d1 | ||
| 
						 | 
					165265f4fb | ||
| 
						 | 
					ca73017100 | ||
| 
						 | 
					123fb350ce | ||
| 
						 | 
					1a27d7dfc0 | ||
| 
						 | 
					b0c6d44515 | ||
| 
						 | 
					6092e01428 | ||
| 
						 | 
					e20ff5ae45 | ||
| 
						 | 
					621a0d70e2 | ||
| 
						 | 
					855b238ec5 | ||
| 
						 | 
					96f44e1959 | ||
| 
						 | 
					242dc8cddd | ||
| 
						 | 
					b8a2004872 | ||
| 
						 | 
					63f08bf2c2 | ||
| 
						 | 
					4734a9ac18 | ||
| 
						 | 
					81cd1e6c40 | ||
| 
						 | 
					0b9cdea7d2 | ||
| 
						 | 
					f63fceb2ea | ||
| 
						 | 
					f0f7165ab6 | ||
| 
						 | 
					2511f60d39 | ||
| 
						 | 
					c0f868dd56 | ||
| 
						 | 
					a112bfdaa2 | ||
| 
						 | 
					4535a70f08 | ||
| 
						 | 
					b59529e579 | ||
| 
						 | 
					393c23820a | ||
| 
						 | 
					e6a3958e45 | ||
| 
						 | 
					59a7fdd2c9 | ||
| 
						 | 
					c3cab28c9b | ||
| 
						 | 
					4c55a6f436 | ||
| 
						 | 
					c10e4c3117 | ||
| 
						 | 
					3b70094151 | ||
| 
						 | 
					a370697385 | ||
| 
						 | 
					8a7c0313f6 | ||
| 
						 | 
					00201f7e6c | ||
| 
						 | 
					5e3111bad8 | ||
| 
						 | 
					a327c10c60 | ||
| 
						 | 
					938bc07e3c | ||
| 
						 | 
					d053d45a6d | ||
| 
						 | 
					5200da6eec | ||
| 
						 | 
					b0523860d9 | ||
| 
						 | 
					1a1215527f | ||
| 
						 | 
					360c018c9e | ||
| 
						 | 
					7bed964ab2 | ||
| 
						 | 
					989d0a5682 | ||
| 
						 | 
					b121c25184 | ||
| 
						 | 
					e0d127b3e4 | ||
| 
						 | 
					a0c56c74e1 | ||
| 
						 | 
					f4b61a7f24 | ||
| 
						 | 
					b2400fb883 | ||
| 
						 | 
					f25832d1b6 | ||
| 
						 | 
					cf363171aa | ||
| 
						 | 
					38c8569d16 | ||
| 
						 | 
					9791d15f39 | ||
| 
						 | 
					80e7f5832b | ||
| 
						 | 
					6e46ddaad3 | ||
| 
						 | 
					8499e4aab2 | ||
| 
						 | 
					5eae1851a1 | ||
| 
						 | 
					c48a246ccb | ||
| 
						 | 
					f084011a61 | ||
| 
						 | 
					bd40cf194c | ||
| 
						 | 
					2434af7e8a | ||
| 
						 | 
					ced7fa9f01 | ||
| 
						 | 
					28b559e812 | ||
| 
						 | 
					76d776245b | ||
| 
						 | 
					0d9f70492e | ||
| 
						 | 
					b58f502dd6 | ||
| 
						 | 
					5f367248c5 | ||
| 
						 | 
					c2065cc3e2 | ||
| 
						 | 
					034408971d | ||
| 
						 | 
					490206b5b2 | ||
| 
						 | 
					d8540819af | ||
| 
						 | 
					d1a9aec526 | ||
| 
						 | 
					e4b681a5a5 | ||
| 
						 | 
					52036871d1 | ||
| 
						 | 
					4fc6a804f5 | ||
| 
						 | 
					08d2ca300a | ||
| 
						 | 
					dc2ec0a8f9 | ||
| 
						 | 
					2cfed952bb | ||
| 
						 | 
					a7da137778 | ||
| 
						 | 
					5ae2f87ce9 | ||
| 
						 | 
					c4f6619fbd | ||
| 
						 | 
					65edbc1424 | ||
| 
						 | 
					1f2d7fa28f | ||
| 
						 | 
					2407a0c4e2 | ||
| 
						 | 
					7f8bfcc939 | ||
| 
						 | 
					fae4cb9e56 | ||
| 
						 | 
					063bbb02f2 | ||
| 
						 | 
					15e1470c50 | ||
| 
						 | 
					f602993aa9 | ||
| 
						 | 
					271508c0a8 | ||
| 
						 | 
					50f96d1c9c | ||
| 
						 | 
					809544800b | ||
| 
						 | 
					e757b06987 | ||
| 
						 | 
					6f2da1baf1 | ||
| 
						 | 
					f30dcad8a7 | ||
| 
						 | 
					7dc235511e | ||
| 
						 | 
					644c210fe2 | ||
| 
						 | 
					68e8f98671 | ||
| 
						 | 
					1228db6ac1 | ||
| 
						 | 
					86596749fa | ||
| 
						 | 
					76229a3601 | ||
| 
						 | 
					95abdeb919 | ||
| 
						 | 
					df0151d338 | ||
| 
						 | 
					ee2f12fe81 | ||
| 
						 | 
					10c104529f | ||
| 
						 | 
					cbc8ec6508 | ||
| 
						 | 
					8e7758e280 | ||
| 
						 | 
					9aefbd189c | ||
| 
						 | 
					b9d50584d8 | ||
| 
						 | 
					e5f7390c09 | ||
| 
						 | 
					797b1ff8bb | ||
| 
						 | 
					09b738045c | ||
| 
						 | 
					4fd690333a | ||
| 
						 | 
					5ef5e25a7f | ||
| 
						 | 
					87e8770cbc | ||
| 
						 | 
					cac9d120be | ||
| 
						 | 
					1ae0fadbf4 | ||
| 
						 | 
					65497e089a | ||
| 
						 | 
					2d763bd033 | ||
| 
						 | 
					4ebf396cf5 | ||
| 
						 | 
					6faa50d496 | ||
| 
						 | 
					6fcd6298c8 | ||
| 
						 | 
					5c16be5dbb | ||
| 
						 | 
					e3abb6f178 | ||
| 
						 | 
					70736be4eb | ||
| 
						 | 
					1c3e7330f3 | ||
| 
						 | 
					6e4c89b310 | ||
| 
						 | 
					73b4a0ef5f | ||
| 
						 | 
					d88002c4ed | ||
| 
						 | 
					025c63c045 | ||
| 
						 | 
					b189cbd46e | ||
| 
						 | 
					a21ddb5914 | ||
| 
						 | 
					e04a4c3923 | ||
| 
						 | 
					ae0821e07b | ||
| 
						 | 
					a508bece36 | ||
| 
						 | 
					2c9969a8f4 | ||
| 
						 | 
					dd9fc91f6f | ||
| 
						 | 
					39d9838cc1 | ||
| 
						 | 
					1397c7c624 | ||
| 
						 | 
					c09fcba94f | ||
| 
						 | 
					c77b38fc4f | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -45,6 +45,7 @@ intltool-merge.in
 | 
			
		||||
intltool-update.in
 | 
			
		||||
libtool
 | 
			
		||||
m4/
 | 
			
		||||
man/gnome-shell.1
 | 
			
		||||
omf.make
 | 
			
		||||
po/*.gmo
 | 
			
		||||
po/gnome-shell.pot
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,11 @@
 | 
			
		||||
# Point to our macro directory and pick up user flags from the environment
 | 
			
		||||
ACLOCAL_AMFLAGS  = -I m4 ${ACLOCAL_FLAGS}
 | 
			
		||||
 | 
			
		||||
SUBDIRS = data js src browser-plugin tests po man docs
 | 
			
		||||
SUBDIRS = data js src browser-plugin tests po docs
 | 
			
		||||
 | 
			
		||||
if ENABLE_MAN
 | 
			
		||||
SUBDIRS += man
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST =		\
 | 
			
		||||
	.project	\
 | 
			
		||||
@@ -21,4 +25,4 @@ distcheck-hook:
 | 
			
		||||
	@echo "Checking disted files against files in git"
 | 
			
		||||
	@$(srcdir)/tools/check-for-missing.py $(srcdir) $(distdir) $(DIST_EXCLUDE)
 | 
			
		||||
 | 
			
		||||
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
 | 
			
		||||
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-man
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										63
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										63
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,3 +1,66 @@
 | 
			
		||||
3.7.2
 | 
			
		||||
=====
 | 
			
		||||
* Enforce RTL in he for messages that might end up as LTR [Florian; #686630]
 | 
			
		||||
* gdm: Move logo into the panel [Florian; #685852]
 | 
			
		||||
* Hide notifications when closed button is clicked [Jasper, Florian; #682237]
 | 
			
		||||
* Tweak screenShield animations [Rui; #686745]
 | 
			
		||||
* Restore Fittsability of summary items in message tray [Florian; #686474]
 | 
			
		||||
* Save screencasts as recent item [Ray; #680647]
 | 
			
		||||
* overview: Resize window captions on content change [Giovanni, Alex; #620874]
 | 
			
		||||
* App search: Match GenericName too [Matthias; #687121]
 | 
			
		||||
* runDialog: Better match style of other modal dialogs [Florian, Allan; #687127]
 | 
			
		||||
* Improve the button insensitive style [Stéphane; #687110]
 | 
			
		||||
* network: Don't use a global switch for all VPN connections [Giovanni; #682929]
 | 
			
		||||
* appMenu: Update on icon theme changes [Florian; #687224]
 | 
			
		||||
* Show 'Log out' in more situations [Matthias; #686736]
 | 
			
		||||
* Add a setting to force the 'Log out' menuitem [Matthias; #686057]
 | 
			
		||||
* overview: Improve styling of search box [Stéphane; #686479]
 | 
			
		||||
* Implement 'disable-user-list' in login screen [Ray; #660660]
 | 
			
		||||
* Fix auto-scroll to bottom in chat notifications [Sjoerd; #686571]
 | 
			
		||||
* Show feedback notifications when user is busy [Stéphane; #662900]
 | 
			
		||||
* Disable login button when there is no input [Stéphane; #687112]
 | 
			
		||||
* Use non-linear overview shade for background [Giovanni, Pierre-Eric; #669798]
 | 
			
		||||
* Reduce blocking in compositor thread [Simon, Jasper; #687465]
 | 
			
		||||
* network: new country-specific type to gather providers [Aleksander; #687356]
 | 
			
		||||
* Update man page [Matthias; #680601]
 | 
			
		||||
* st-entry: Change the pointer cursor on enter/leave events [Thomas; #687130]
 | 
			
		||||
* screenShield: Blur and desaturate the background [Giovanni, Cosimo; #682536]
 | 
			
		||||
* Change height of chat notifications to have more context [Carlos; #665255]
 | 
			
		||||
* screenShield: Account for motion velocity when hiding [Giovanni; #682537]
 | 
			
		||||
* screenShield: hide the cursor while the lock screen is on [Giovanni; #682535]
 | 
			
		||||
* Support remote search provider settings [Cosimo; #687491]
 | 
			
		||||
* unlockDialog: Improve label of confirmation button [Stéphane; #687656]
 | 
			
		||||
* userMenu: Rename "System Settings" item to "Settings" [Elad; #687738]
 | 
			
		||||
* messageTray: Add keybinding to focus current notification [Stéphane; #652082]
 | 
			
		||||
* Remove shell-screen-grabber [Neil; #685915]
 | 
			
		||||
* main: Stop using Metacity's keybinding files [Florian; #687672]
 | 
			
		||||
* Bluetooth: Remove ObexFTP functionality [Bastien; #688160]
 | 
			
		||||
* a11y: Also set WM theme when HighContrast is switched on [Cosimo; #688256]
 | 
			
		||||
* network: Rework multiple NIC support [Giovanni; #677142]
 | 
			
		||||
* Rework keybindings to allow selective blocking/processing [Florian; #688202]
 | 
			
		||||
* recorder: Show indicator on primary monitor [Adel; #688470]
 | 
			
		||||
* recorder: Set frame duration to fix broken video headers [Adel; #688487]
 | 
			
		||||
* Misc. bugfixes and cleanups [Florian, Jasper, Giovanni, Matthew, Stéphane,
 | 
			
		||||
  Allan, Daiki, Owen, Alejandro, Jean-François, Cosimo, Sebastian, Adel, Alban;
 | 
			
		||||
  #686484, #686728, #686805, #686574, #686763, #682428, #687132, #685239,
 | 
			
		||||
  #687189, #687226, #658091, #670687, #687457, #687242, #687287, #687020,
 | 
			
		||||
  #686583, #661194, #687491, #657315, #687958, #683986, #688089, #687708,
 | 
			
		||||
  #686530, #684810, #688181, #688475, #688557, #688507, #638351]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Elad Alfassa, Matthew Barnes, Alban Browaeys, Giovanni Campagna,
 | 
			
		||||
  Cosimo Cecchi, Matthias Clasen, Allan Day, Stéphane Démurget,
 | 
			
		||||
  Jean-François Fortin Tam, Adel Gadllah, Alex Hultman, Sebastian Keller,
 | 
			
		||||
  Rui Matos, Simon McVittie, Aleksander Morgado, Florian Müllner,
 | 
			
		||||
  Bastien Nocera, Pierre-Eric Pelloux-Prayer, Alejandro Piñeiro, Neil Roberts,
 | 
			
		||||
  Sjoerd Simons, Carlos Soriano Sánchez, Jasper St. Pierre, Ray Strode,
 | 
			
		||||
  Owen Taylor, Daiki Ueno, Thomas Wood
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Dušan Kazik [sk], Pavol Klačanský [sk], Piotr Drąg [pl], Yuri Myasoedov [ru],
 | 
			
		||||
  Marek Černocký [cs], Kjartan Maraas [nb], Wolfgang Stöggl [de],
 | 
			
		||||
  Yaron Shahrabani [he], Fran Diéguez [gl], Mattias Põldaru [et]
 | 
			
		||||
 | 
			
		||||
3.7.1
 | 
			
		||||
=====
 | 
			
		||||
* Add shortcut to open application view directly [Jeremy; #685738]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								configure.ac
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
AC_PREREQ(2.63)
 | 
			
		||||
AC_INIT([gnome-shell],[3.7.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
 | 
			
		||||
AC_INIT([gnome-shell],[3.7.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
 | 
			
		||||
 | 
			
		||||
AC_CONFIG_HEADERS([config.h])
 | 
			
		||||
AC_CONFIG_SRCDIR([src/shell-global.c])
 | 
			
		||||
@@ -36,6 +36,8 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
 | 
			
		||||
 | 
			
		||||
PKG_PROG_PKG_CONFIG([0.22])
 | 
			
		||||
 | 
			
		||||
AC_PATH_PROG([XSLTPROC], [xsltproc])
 | 
			
		||||
 | 
			
		||||
GLIB_GSETTINGS
 | 
			
		||||
 | 
			
		||||
# Get a value to substitute into gnome-shell.in
 | 
			
		||||
@@ -63,7 +65,7 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
 | 
			
		||||
CLUTTER_MIN_VERSION=1.11.11
 | 
			
		||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
 | 
			
		||||
GJS_MIN_VERSION=1.33.2
 | 
			
		||||
MUTTER_MIN_VERSION=3.7.1
 | 
			
		||||
MUTTER_MIN_VERSION=3.7.2
 | 
			
		||||
GTK_MIN_VERSION=3.3.9
 | 
			
		||||
GIO_MIN_VERSION=2.35.0
 | 
			
		||||
LIBECAL_MIN_VERSION=3.5.3
 | 
			
		||||
@@ -76,6 +78,7 @@ STARTUP_NOTIFICATION_MIN_VERSION=0.11
 | 
			
		||||
GCR_MIN_VERSION=3.3.90
 | 
			
		||||
GNOME_DESKTOP_REQUIRED_VERSION=3.7.1
 | 
			
		||||
GNOME_MENUS_REQUIRED_VERSION=3.5.3
 | 
			
		||||
NETWORKMANAGER_MIN_VERSION=0.9.7
 | 
			
		||||
 | 
			
		||||
# Collect more than 20 libraries for a prize!
 | 
			
		||||
PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
 | 
			
		||||
@@ -96,8 +99,9 @@ PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
 | 
			
		||||
                               telepathy-glib >= $TELEPATHY_GLIB_MIN_VERSION
 | 
			
		||||
                               telepathy-logger-0.2 >= $TELEPATHY_LOGGER_MIN_VERSION
 | 
			
		||||
                               polkit-agent-1 >= $POLKIT_MIN_VERSION xfixes
 | 
			
		||||
                               libnm-glib libnm-util gnome-keyring-1
 | 
			
		||||
                               gcr-3 >= $GCR_MIN_VERSION)
 | 
			
		||||
                               libnm-glib libnm-util >= $NETWORKMANAGER_MIN_VERSION
 | 
			
		||||
                               libnm-gtk >= $NETWORKMANAGER_MIN_VERSION
 | 
			
		||||
                               gnome-keyring-1 gcr-3 >= $GCR_MIN_VERSION)
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
 | 
			
		||||
 | 
			
		||||
@@ -110,19 +114,11 @@ AC_SUBST([GNOME_KEYBINDINGS_KEYSDIR])
 | 
			
		||||
 | 
			
		||||
GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION])
 | 
			
		||||
 | 
			
		||||
saved_CFLAGS=$CFLAGS
 | 
			
		||||
saved_LIBS=$LIBS
 | 
			
		||||
CFLAGS=$GNOME_SHELL_CFLAGS
 | 
			
		||||
LIBS=$GNOME_SHELL_LIBS
 | 
			
		||||
AC_CHECK_FUNCS(JS_NewGlobalObject XFixesCreatePointerBarrier)
 | 
			
		||||
CFLAGS=$saved_CFLAGS
 | 
			
		||||
LIBS=$saved_LIBS
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
 | 
			
		||||
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
 | 
			
		||||
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
 | 
			
		||||
PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0)
 | 
			
		||||
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.5.4)
 | 
			
		||||
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.2)
 | 
			
		||||
 | 
			
		||||
AC_MSG_CHECKING([for bluetooth support])
 | 
			
		||||
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
 | 
			
		||||
@@ -207,6 +203,18 @@ AC_SUBST(TYPELIBDIR)
 | 
			
		||||
 | 
			
		||||
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
 | 
			
		||||
 | 
			
		||||
AC_ARG_ENABLE(man,
 | 
			
		||||
              [AS_HELP_STRING([--enable-man],
 | 
			
		||||
                              [generate man pages [default=yes]])],,
 | 
			
		||||
              enable_man=yes)
 | 
			
		||||
if test "$enable_man" != no; then
 | 
			
		||||
  AC_PATH_PROG([XSLTPROC], [xsltproc])
 | 
			
		||||
  if test -z "$XSLTPROC"; then
 | 
			
		||||
    AC_MSG_ERROR([xsltproc is required for --enable-man])
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no)
 | 
			
		||||
 | 
			
		||||
# Stay command-line compatible with the gnome-common configure option. Here
 | 
			
		||||
# minimum/yes/maximum are the same, however.
 | 
			
		||||
AC_ARG_ENABLE(compile_warnings,
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,9 @@
 | 
			
		||||
	<KeyListEntry name="toggle-message-tray"
 | 
			
		||||
                      _description="Show the message tray"/>
 | 
			
		||||
 | 
			
		||||
	<KeyListEntry name="focus-active-notification"
 | 
			
		||||
                      _description="Focus the active notification"/>
 | 
			
		||||
 | 
			
		||||
	<KeyListEntry name="toggle-application-view"
 | 
			
		||||
                      _description="Show all applications"/>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,11 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
 | 
			
		||||
        menuitem in single-user, single-session situations.
 | 
			
		||||
      </_description>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="show-full-name" type="b">
 | 
			
		||||
      <default>true</default>
 | 
			
		||||
      <_summary>Show full name in the user menu</_summary>
 | 
			
		||||
      <_description>Whether the users full name is shown in the user menu or not.</_description>
 | 
			
		||||
    </key>
 | 
			
		||||
    <child name="calendar" schema="org.gnome.shell.calendar"/>
 | 
			
		||||
    <child name="recorder" schema="org.gnome.shell.recorder"/>
 | 
			
		||||
    <child name="keybindings" schema="org.gnome.shell.keybindings"/>
 | 
			
		||||
@@ -106,6 +111,13 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
 | 
			
		||||
        Keybinding to toggle the visibility of the message tray.
 | 
			
		||||
      </_description>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="focus-active-notification" type="as">
 | 
			
		||||
      <default>["<Super>n"]</default>
 | 
			
		||||
      <_summary>Keybinding to focus the active notification</_summary>
 | 
			
		||||
      <_description>
 | 
			
		||||
        Keybinding to focus the active notification.
 | 
			
		||||
      </_description>
 | 
			
		||||
    </key>
 | 
			
		||||
    <key name="toggle-recording" type="as">
 | 
			
		||||
      <default><![CDATA[['<Control><Shift><Alt>r']]]></default>
 | 
			
		||||
      <_summary>Keybinding to toggle the screen recorder</_summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -405,11 +405,13 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    padding: 0 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-prompt-entry:insensitive {
 | 
			
		||||
    color: rgba(0,0,0,0.7);
 | 
			
		||||
    border: 2px solid #565656;
 | 
			
		||||
    background-gradient-start: rgb(200,200,200);
 | 
			
		||||
    background-gradient-end: rgb(210,210,210);
 | 
			
		||||
.modal-dialog StEntry:insensitive {
 | 
			
		||||
    border-color: #666666;
 | 
			
		||||
    color: #9f9f9f;
 | 
			
		||||
    border: 2px solid #9f9f9f;
 | 
			
		||||
    background-gradient-direction: none;
 | 
			
		||||
    background-color: rgba(102, 102, 102, 0.15);
 | 
			
		||||
    box-shadow: inset 0 0 rgba(0,0,0,1.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Panel */
 | 
			
		||||
@@ -418,6 +420,18 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    background-color: black;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    height: 1.86em;
 | 
			
		||||
    transition-duration: 250;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#panel.lock-screen {
 | 
			
		||||
    height: 2em;
 | 
			
		||||
    background-color: rgba(0,0,0,0.3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#panel.unlock-screen,
 | 
			
		||||
#panel.login-screen {
 | 
			
		||||
    height: 2em;
 | 
			
		||||
    background-color: transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#panelLeft, #panelCenter {
 | 
			
		||||
@@ -453,6 +467,13 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    -panel-corner-border-color: rgba(255,255,255,0.8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.panel-corner.lock-screen,
 | 
			
		||||
.panel-corner.unlock-screen,
 | 
			
		||||
.panel-corner.login-screen {
 | 
			
		||||
    -panel-corner-background-color: transparent;
 | 
			
		||||
    -panel-corner-border-color: transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#appMenu {
 | 
			
		||||
    spacing: 4px;
 | 
			
		||||
}
 | 
			
		||||
@@ -485,6 +506,24 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    transition-duration: 100;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#panel.unlock-screen .panel-button,
 | 
			
		||||
#panel.lock-screen .panel-button,
 | 
			
		||||
#panel.login-screen .panel-button {
 | 
			
		||||
    color: #e6e6e6;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#panel.unlock-screen .panel-button:hover,
 | 
			
		||||
#panel.lock-screen .panel-button:hover,
 | 
			
		||||
#panel.login-screen .panel-button:hover,
 | 
			
		||||
#panel.unlock-screen .panel-button:active,
 | 
			
		||||
#panel.lock-screen .panel-button:active,
 | 
			
		||||
#panel.login-screen .panel-button:active,
 | 
			
		||||
#panel.unlock-screen .panel-button:focus,
 | 
			
		||||
#panel.lock-screen .panel-button:focus,
 | 
			
		||||
#panel.login-screen .panel-button:focus {
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.panel-button:hover {
 | 
			
		||||
    color: white;
 | 
			
		||||
    text-shadow: black 0px 2px 2px;
 | 
			
		||||
@@ -615,6 +654,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    border-radius: 8px;
 | 
			
		||||
    padding: 4px 12px;
 | 
			
		||||
    -shell-caption-spacing: 12px;
 | 
			
		||||
    border: 2px solid rgba(0, 0, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.window-close, .notification-close {
 | 
			
		||||
@@ -625,7 +665,16 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.window-close {
 | 
			
		||||
    -shell-close-overlap: 20px;
 | 
			
		||||
    -shell-close-overlap: 16px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.window-caption:hover {
 | 
			
		||||
    border: 2px solid rgba(255, 255, 255, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.window-clone-border {
 | 
			
		||||
    border: 4px solid rgba(255, 255, 255, 0.5);
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.notification-close {
 | 
			
		||||
@@ -1222,6 +1271,12 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    outline: 1px solid rgba(128, 128, 128, 0.3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.no-messages-label {
 | 
			
		||||
    font-family: cantarell, sans-serif;
 | 
			
		||||
    font-size: 11pt;
 | 
			
		||||
    color: #999999;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.notification {
 | 
			
		||||
    border-radius: 10px 10px 0px 0px;
 | 
			
		||||
    background: rgba(0,0,0,0.8);
 | 
			
		||||
@@ -1255,7 +1310,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.summary-boxpointer {
 | 
			
		||||
    -arrow-border-radius: 8px;
 | 
			
		||||
    -arrow-border-radius: 15px;
 | 
			
		||||
    -arrow-background-color: rgba(0,0,0,0.8);
 | 
			
		||||
    -arrow-base: 36px;
 | 
			
		||||
    -arrow-rise: 18px;
 | 
			
		||||
@@ -1276,8 +1331,8 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
 | 
			
		||||
.summary-notification-stack-scrollview {
 | 
			
		||||
    max-height: 18em;
 | 
			
		||||
    padding-top: 6px;
 | 
			
		||||
    padding-bottom: 6px;
 | 
			
		||||
    padding-top: 8px;
 | 
			
		||||
    padding-bottom: 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.summary-notification-stack-scrollview:ltr {
 | 
			
		||||
@@ -1432,6 +1487,10 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    padding-right: 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-notification-scrollview{
 | 
			
		||||
	max-height: 22em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.subscription-message {
 | 
			
		||||
    font-style: italic;
 | 
			
		||||
}
 | 
			
		||||
@@ -2125,7 +2184,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    text-align: left;
 | 
			
		||||
    padding-left: 15px;
 | 
			
		||||
    text-shadow: black 4px 4px 3px 0px;
 | 
			
		||||
    text-shadow: black 0px 4px 3px 0px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog-prompt-layout {
 | 
			
		||||
@@ -2191,6 +2250,10 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    height: .75em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog .modal-dialog-button-box {
 | 
			
		||||
    spacing: 3px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.login-dialog .modal-dialog-button {
 | 
			
		||||
    border-radius: 5px;
 | 
			
		||||
    padding: 3px 18px;
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,7 @@ const GdmUtil = imports.gdm.util;
 | 
			
		||||
const Lightbox = imports.ui.lightbox;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
const Panel = imports.ui.panel;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const UserMenu = imports.ui.userMenu;
 | 
			
		||||
@@ -48,6 +49,10 @@ const _SCROLL_ANIMATION_TIME = 0.5;
 | 
			
		||||
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
 | 
			
		||||
const _LOGO_ICON_HEIGHT = 16;
 | 
			
		||||
 | 
			
		||||
const WORK_SPINNER_ICON_SIZE = 24;
 | 
			
		||||
const WORK_SPINNER_ANIMATION_DELAY = 1.0;
 | 
			
		||||
const WORK_SPINNER_ANIMATION_TIME = 0.3;
 | 
			
		||||
 | 
			
		||||
let _loginDialog = null;
 | 
			
		||||
 | 
			
		||||
function _smoothlyResizeActor(actor, width, height) {
 | 
			
		||||
@@ -604,6 +609,14 @@ const SessionList = new Lang.Class({
 | 
			
		||||
            this.close();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateSensitivity: function(sensitive) {
 | 
			
		||||
        this._button.reactive = sensitive;
 | 
			
		||||
        this._button.can_focus = sensitive;
 | 
			
		||||
 | 
			
		||||
        for (let id in this._items)
 | 
			
		||||
            this._items[id].actor.reactive = sensitive;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setActiveSession: function(sessionId) {
 | 
			
		||||
         if (sessionId == this._activeSessionId)
 | 
			
		||||
             return;
 | 
			
		||||
@@ -660,6 +673,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        this.parent({ shellReactive: true,
 | 
			
		||||
                      styleClass: 'login-dialog',
 | 
			
		||||
                      parentActor: parentActor,
 | 
			
		||||
                      keybindingMode: Main.KeybindingMode.LOGIN_SCREEN,
 | 
			
		||||
                      shouldFadeIn: false });
 | 
			
		||||
        this.connect('destroy',
 | 
			
		||||
                     Lang.bind(this, this._onDestroy));
 | 
			
		||||
@@ -684,9 +698,11 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        this._userVerifier = new GdmUtil.ShellUserVerifier(this._greeterClient);
 | 
			
		||||
        this._userVerifier.connect('ask-question', Lang.bind(this, this._askQuestion));
 | 
			
		||||
        this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage));
 | 
			
		||||
        this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
 | 
			
		||||
        this._userVerifier.connect('verification-failed', Lang.bind(this, this._verificationFailed));
 | 
			
		||||
        this._userVerifier.connect('reset', Lang.bind(this, this._reset));
 | 
			
		||||
        this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
 | 
			
		||||
        this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
 | 
			
		||||
        this._verifyingUser = false;
 | 
			
		||||
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
 | 
			
		||||
 | 
			
		||||
@@ -694,6 +710,8 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
                               Lang.bind(this, this._updateBanner));
 | 
			
		||||
        this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_TEXT_KEY,
 | 
			
		||||
                               Lang.bind(this, this._updateBanner));
 | 
			
		||||
        this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY,
 | 
			
		||||
                               Lang.bind(this, this._updateDisableUserList));
 | 
			
		||||
 | 
			
		||||
        this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
 | 
			
		||||
                                           text: '' });
 | 
			
		||||
@@ -701,7 +719,8 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        this._updateBanner();
 | 
			
		||||
 | 
			
		||||
        this._titleLabel = new St.Label({ style_class: 'login-dialog-title',
 | 
			
		||||
                                          text: C_("title", "Sign In") });
 | 
			
		||||
                                          text: C_("title", "Sign In"),
 | 
			
		||||
                                          visible: false });
 | 
			
		||||
 | 
			
		||||
        this.contentLayout.add(this._titleLabel,
 | 
			
		||||
                              { y_fill: false,
 | 
			
		||||
@@ -731,6 +750,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
                              x_align: St.Align.START });
 | 
			
		||||
        this._promptEntry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
 | 
			
		||||
                                           can_focus: true });
 | 
			
		||||
        this._promptEntryTextChangedId = 0;
 | 
			
		||||
        this._promptBox.add(this._promptEntry,
 | 
			
		||||
                            { expand: true,
 | 
			
		||||
                              x_fill: true,
 | 
			
		||||
@@ -744,6 +764,9 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        this._promptLoginHint.hide();
 | 
			
		||||
        this._promptBox.add(this._promptLoginHint);
 | 
			
		||||
 | 
			
		||||
        this._signInButton = null;
 | 
			
		||||
        this._workSpinner = null;
 | 
			
		||||
 | 
			
		||||
        this._sessionList = new SessionList();
 | 
			
		||||
        this._sessionList.connect('session-activated',
 | 
			
		||||
                                  Lang.bind(this, function(list, sessionId) {
 | 
			
		||||
@@ -769,7 +792,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
                                                x_align: St.Align.START,
 | 
			
		||||
                                                x_fill: true });
 | 
			
		||||
 | 
			
		||||
        this._notListedButton.connect('clicked', Lang.bind(this, this._onNotListedClicked));
 | 
			
		||||
        this._notListedButton.connect('clicked', Lang.bind(this, this._hideUserListAndLogIn));
 | 
			
		||||
 | 
			
		||||
        this.contentLayout.add(this._notListedButton,
 | 
			
		||||
                               { expand: false,
 | 
			
		||||
@@ -795,6 +818,21 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
   },
 | 
			
		||||
 | 
			
		||||
    _updateDisableUserList: function() {
 | 
			
		||||
        let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY);
 | 
			
		||||
 | 
			
		||||
        // If this is the first time around, set initial focus
 | 
			
		||||
        if (this._disableUserList == undefined && disableUserList)
 | 
			
		||||
            this.setInitialKeyFocus(this._promptEntry);
 | 
			
		||||
 | 
			
		||||
        if (disableUserList != this._disableUserList) {
 | 
			
		||||
            this._disableUserList = disableUserList;
 | 
			
		||||
 | 
			
		||||
            if (!this._verifyingUser)
 | 
			
		||||
                this._reset();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateBanner: function() {
 | 
			
		||||
        let enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY);
 | 
			
		||||
        let text = this._settings.get_string(GdmUtil.BANNER_MESSAGE_TEXT_KEY);
 | 
			
		||||
@@ -807,31 +845,23 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onReset: function(client, serviceName) {
 | 
			
		||||
    _reset: function() {
 | 
			
		||||
        this._updateSensitivity(true);
 | 
			
		||||
        this._promptMessage.hide();
 | 
			
		||||
 | 
			
		||||
        let tasks = [this._hidePrompt,
 | 
			
		||||
 | 
			
		||||
                     new Batch.ConcurrentBatch(this, [this._fadeInTitleLabel,
 | 
			
		||||
                                                      this._fadeInNotListedButton]),
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         this._sessionList.close();
 | 
			
		||||
                         this._promptLoginHint.hide();
 | 
			
		||||
                         this._userList.actor.show();
 | 
			
		||||
                         this._userList.actor.opacity = 255;
 | 
			
		||||
                         return this._userList.showItems();
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         this._userList.actor.reactive = true;
 | 
			
		||||
                         this._userList.actor.grab_key_focus();
 | 
			
		||||
                     }];
 | 
			
		||||
 | 
			
		||||
        this._user = null;
 | 
			
		||||
        this._verifyingUser = false;
 | 
			
		||||
 | 
			
		||||
        let batch = new Batch.ConsecutiveBatch(this, tasks);
 | 
			
		||||
        batch.run();
 | 
			
		||||
        if (this._disableUserList)
 | 
			
		||||
            this._hideUserListAndLogIn();
 | 
			
		||||
        else
 | 
			
		||||
            this._showUserList();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _verificationFailed: function() {
 | 
			
		||||
        this._promptEntry.text = '';
 | 
			
		||||
 | 
			
		||||
        this._updateSensitivity(true);
 | 
			
		||||
        this._setWorking(false);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDefaultSessionChanged: function(client, sessionId) {
 | 
			
		||||
@@ -886,6 +916,9 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
                         if (this._user && this._user.is_logged_in())
 | 
			
		||||
                             return null;
 | 
			
		||||
 | 
			
		||||
                         if (!this._verifyingUser)
 | 
			
		||||
                             return null;
 | 
			
		||||
 | 
			
		||||
                         return GdmUtil.fadeInActor(this._sessionList.actor);
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
@@ -898,24 +931,15 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        return batch.run();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showPrompt: function() {
 | 
			
		||||
    _showPrompt: function(forSecret) {
 | 
			
		||||
        let hold = new Batch.Hold();
 | 
			
		||||
 | 
			
		||||
        let buttons = [{ action: Lang.bind(this, this.cancel),
 | 
			
		||||
                         label: _("Cancel"),
 | 
			
		||||
                         key: Clutter.Escape },
 | 
			
		||||
                       { action: Lang.bind(this, function() {
 | 
			
		||||
                                     hold.release();
 | 
			
		||||
                                 }),
 | 
			
		||||
                         label: C_("button", "Sign In"),
 | 
			
		||||
                         default: true }];
 | 
			
		||||
 | 
			
		||||
        let tasks = [function() {
 | 
			
		||||
                         return this._fadeInPrompt();
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         this.setButtons(buttons);
 | 
			
		||||
                         this._prepareDialog(forSecret, hold);
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     hold];
 | 
			
		||||
@@ -925,17 +949,86 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        return batch.run();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _prepareDialog: function(forSecret, hold) {
 | 
			
		||||
        this._workSpinner = new Panel.AnimatedIcon('process-working.svg', WORK_SPINNER_ICON_SIZE);
 | 
			
		||||
        this._workSpinner.actor.opacity = 0;
 | 
			
		||||
        this._workSpinner.actor.show();
 | 
			
		||||
 | 
			
		||||
        this.buttonLayout.visible = true;
 | 
			
		||||
        this.clearButtons();
 | 
			
		||||
 | 
			
		||||
        if (!this._disableUserList || this._verifyingUser)
 | 
			
		||||
            this.addButton({ action: Lang.bind(this, this.cancel),
 | 
			
		||||
                             label: _("Cancel"),
 | 
			
		||||
                             key: Clutter.Escape },
 | 
			
		||||
                           { expand: true,
 | 
			
		||||
                             x_fill: false,
 | 
			
		||||
                             y_fill: false,
 | 
			
		||||
                             x_align: St.Align.START,
 | 
			
		||||
                             y_align: St.Align.MIDDLE });
 | 
			
		||||
        this.buttonLayout.add(this._workSpinner.actor,
 | 
			
		||||
                              { expand: false,
 | 
			
		||||
                                x_fill: false,
 | 
			
		||||
                                y_fill: false,
 | 
			
		||||
                                x_align: St.Align.END,
 | 
			
		||||
                                y_align: St.Align.MIDDLE });
 | 
			
		||||
        this._signInButton = this.addButton({ action: Lang.bind(this, function() {
 | 
			
		||||
                                                          hold.release();
 | 
			
		||||
                                                      }),
 | 
			
		||||
                                              label: forSecret ? C_("button", "Sign In") : _("Next"),
 | 
			
		||||
                                              default: true },
 | 
			
		||||
                                            { expand: false,
 | 
			
		||||
                                              x_fill: false,
 | 
			
		||||
                                              y_fill: false,
 | 
			
		||||
                                              x_align: St.Align.END,
 | 
			
		||||
                                              y_align: St.Align.MIDDLE });
 | 
			
		||||
 | 
			
		||||
        this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0);
 | 
			
		||||
 | 
			
		||||
        this._promptEntryTextChangedId =
 | 
			
		||||
            this._promptEntry.clutter_text.connect('text-changed',
 | 
			
		||||
                                                    Lang.bind(this, function() {
 | 
			
		||||
                                                        this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0);
 | 
			
		||||
                                                    }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateSensitivity: function(sensitive) {
 | 
			
		||||
        this._promptEntry.reactive = sensitive;
 | 
			
		||||
        this._promptEntry.clutter_text.editable = sensitive;
 | 
			
		||||
        this._sessionList.updateSensitivity(sensitive);
 | 
			
		||||
        this._updateSignInButtonSensitivity(sensitive);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateSignInButtonSensitivity: function(sensitive) {
 | 
			
		||||
        if (this._signInButton) {
 | 
			
		||||
            this._signInButton.reactive = sensitive;
 | 
			
		||||
            this._signInButton.can_focus = sensitive;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hidePrompt: function() {
 | 
			
		||||
        this.setButtons([]);
 | 
			
		||||
 | 
			
		||||
        if (this._promptEntryTextChangedId > 0) {
 | 
			
		||||
            this._promptEntry.clutter_text.disconnect(this._promptEntryTextChangedId);
 | 
			
		||||
            this._promptEntryTextChangedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let tasks = [function() {
 | 
			
		||||
                         this._setWorking(false);
 | 
			
		||||
 | 
			
		||||
                         return GdmUtil.fadeOutActor(this._promptBox);
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         this._promptLoginHint.hide();
 | 
			
		||||
                         this._promptEntry.reactive = true;
 | 
			
		||||
 | 
			
		||||
                         this._updateSensitivity(true);
 | 
			
		||||
                         this._promptEntry.set_text('');
 | 
			
		||||
 | 
			
		||||
                         this.clearButtons();
 | 
			
		||||
                         this._workSpinner = null;
 | 
			
		||||
                         this._signInButton = null;
 | 
			
		||||
                     }];
 | 
			
		||||
 | 
			
		||||
        let batch = new Batch.ConsecutiveBatch(this, tasks);
 | 
			
		||||
@@ -943,18 +1036,63 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        return batch.run();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setWorking: function(working) {
 | 
			
		||||
        if (!this._workSpinner)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (working) {
 | 
			
		||||
            this._workSpinner.play();
 | 
			
		||||
            Tweener.addTween(this._workSpinner.actor,
 | 
			
		||||
                             { opacity: 255,
 | 
			
		||||
                               delay: WORK_SPINNER_ANIMATION_DELAY,
 | 
			
		||||
                               time: WORK_SPINNER_ANIMATION_TIME,
 | 
			
		||||
                               transition: 'linear'
 | 
			
		||||
                             });
 | 
			
		||||
        } else {
 | 
			
		||||
            Tweener.addTween(this._workSpinner.actor,
 | 
			
		||||
                             { opacity: 0,
 | 
			
		||||
                               time: WORK_SPINNER_ANIMATION_TIME,
 | 
			
		||||
                               transition: 'linear',
 | 
			
		||||
                               onCompleteScope: this,
 | 
			
		||||
                               onComplete: function() {
 | 
			
		||||
                                   this._workSpinner.stop();
 | 
			
		||||
                               }
 | 
			
		||||
                             });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _askQuestion: function(verifier, serviceName, question, passwordChar) {
 | 
			
		||||
        this._promptLabel.set_text(question);
 | 
			
		||||
 | 
			
		||||
        this._promptEntry.set_text('');
 | 
			
		||||
        this._promptEntry.clutter_text.set_password_char(passwordChar);
 | 
			
		||||
 | 
			
		||||
        let tasks = [function() {
 | 
			
		||||
                         return this._showPrompt(!!passwordChar);
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         let text = this._promptEntry.get_text();
 | 
			
		||||
                         this._updateSensitivity(false);
 | 
			
		||||
                         this._setWorking(true);
 | 
			
		||||
                         this._userVerifier.answerQuery(serviceName, text);
 | 
			
		||||
                     }];
 | 
			
		||||
 | 
			
		||||
        let batch = new Batch.ConsecutiveBatch(this, tasks);
 | 
			
		||||
        return batch.run();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _askForUsernameAndLogIn: function() {
 | 
			
		||||
        this._promptLabel.set_text(_("Username: "));
 | 
			
		||||
        this._promptEntry.set_text('');
 | 
			
		||||
        this._promptEntry.clutter_text.set_password_char('');
 | 
			
		||||
 | 
			
		||||
        let tasks = [this._showPrompt,
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         let _text = this._promptEntry.get_text();
 | 
			
		||||
                         let userName = this._promptEntry.get_text();
 | 
			
		||||
                         this._promptEntry.reactive = false;
 | 
			
		||||
                         this._userVerifier.answerQuery(serviceName, _text);
 | 
			
		||||
                         return this._beginVerificationForUser(userName);
 | 
			
		||||
                     }];
 | 
			
		||||
 | 
			
		||||
        let batch = new Batch.ConsecutiveBatch(this, tasks);
 | 
			
		||||
@@ -1089,7 +1227,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
                             }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onNotListedClicked: function() {
 | 
			
		||||
    _hideUserListAndLogIn: function() {
 | 
			
		||||
        let tasks = [function() {
 | 
			
		||||
                         return this._userList.hideItems();
 | 
			
		||||
                     },
 | 
			
		||||
@@ -1106,10 +1244,30 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
                                                      this._fadeOutNotListedButton]),
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         let hold = new Batch.Hold();
 | 
			
		||||
                         return this._askForUsernameAndLogIn();
 | 
			
		||||
                     }];
 | 
			
		||||
 | 
			
		||||
                         this._userVerifier.begin(null, hold);
 | 
			
		||||
                         return hold;
 | 
			
		||||
        let batch = new Batch.ConsecutiveBatch(this, tasks);
 | 
			
		||||
        batch.run();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showUserList: function() {
 | 
			
		||||
        let tasks = [this._hidePrompt,
 | 
			
		||||
 | 
			
		||||
                     new Batch.ConcurrentBatch(this, [this._fadeInTitleLabel,
 | 
			
		||||
                                                      this._fadeInNotListedButton]),
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         this._sessionList.close();
 | 
			
		||||
                         this._promptLoginHint.hide();
 | 
			
		||||
                         this._userList.actor.show();
 | 
			
		||||
                         this._userList.actor.opacity = 255;
 | 
			
		||||
                         return this._userList.showItems();
 | 
			
		||||
                     },
 | 
			
		||||
 | 
			
		||||
                     function() {
 | 
			
		||||
                         this._userList.actor.reactive = true;
 | 
			
		||||
                         this._userList.actor.grab_key_focus();
 | 
			
		||||
                     }];
 | 
			
		||||
 | 
			
		||||
        let batch = new Batch.ConsecutiveBatch(this, tasks);
 | 
			
		||||
@@ -1144,6 +1302,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        let hold = new Batch.Hold();
 | 
			
		||||
 | 
			
		||||
        this._userVerifier.begin(userName, hold);
 | 
			
		||||
        this._verifyingUser = true;
 | 
			
		||||
        return hold;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -1196,6 +1355,8 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
            this._userList.addUser(users[i]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._updateDisableUserList();
 | 
			
		||||
 | 
			
		||||
        this._userManager.connect('user-added',
 | 
			
		||||
                                  Lang.bind(this, function(userManager, user) {
 | 
			
		||||
                                      this._userList.addUser(user);
 | 
			
		||||
@@ -1219,7 +1380,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
    _onOpened: function() {
 | 
			
		||||
        Main.ctrlAltTabManager.addGroup(this.dialogLayout,
 | 
			
		||||
                                        _("Login Window"),
 | 
			
		||||
                                        'dialog-password',
 | 
			
		||||
                                        'dialog-password-symbolic',
 | 
			
		||||
                                        { sortGroup: CtrlAltTab.SortGroup.MIDDLE });
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
@@ -1227,6 +1388,6 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
    close: function() {
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        Main.ctrlAltTabManager.removeGroup(this._group);
 | 
			
		||||
        Main.ctrlAltTabManager.removeGroup(this.dialogLayout);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ const BANNER_MESSAGE_TEXT_KEY = 'banner-message-text';
 | 
			
		||||
const ALLOWED_FAILURES_KEY = 'allowed-failures';
 | 
			
		||||
 | 
			
		||||
const LOGO_KEY = 'logo';
 | 
			
		||||
const DISABLE_USER_LIST_KEY = 'disable-user-list';
 | 
			
		||||
 | 
			
		||||
function fadeInActor(actor) {
 | 
			
		||||
    if (actor.opacity == 255 && actor.visible)
 | 
			
		||||
 
 | 
			
		||||
@@ -46,8 +46,70 @@ let _providersTable;
 | 
			
		||||
function _getProvidersTable() {
 | 
			
		||||
    if (_providersTable)
 | 
			
		||||
        return _providersTable;
 | 
			
		||||
    let [providers, countryCodes] = Shell.mobile_providers_parse();
 | 
			
		||||
    return _providersTable = providers;
 | 
			
		||||
    return _providersTable = Shell.mobile_providers_parse(null,null);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function findProviderForMCCMNC(table, needle) {
 | 
			
		||||
    let needlemcc = needle.substring(0, 3);
 | 
			
		||||
    let needlemnc = needle.substring(3, needle.length);
 | 
			
		||||
 | 
			
		||||
    let name2, name3;
 | 
			
		||||
    for (let iter in table) {
 | 
			
		||||
        let country = table[iter];
 | 
			
		||||
        let providers = country.get_providers();
 | 
			
		||||
 | 
			
		||||
        // Search through each country's providers
 | 
			
		||||
        for (let i = 0; i < providers.length; i++) {
 | 
			
		||||
            let provider = providers[i];
 | 
			
		||||
 | 
			
		||||
            // Search through MCC/MNC list
 | 
			
		||||
            let list = provider.get_gsm_mcc_mnc();
 | 
			
		||||
            for (let j = 0; j < list.length; j++) {
 | 
			
		||||
                let mccmnc = list[j];
 | 
			
		||||
 | 
			
		||||
                // Match both 2-digit and 3-digit MNC; prefer a
 | 
			
		||||
                // 3-digit match if found, otherwise a 2-digit one.
 | 
			
		||||
                if (mccmnc.mcc != needlemcc)
 | 
			
		||||
                    continue;  // MCC was wrong
 | 
			
		||||
 | 
			
		||||
                if (!name3 && needle.length == 6 && needlemnc == mccmnc.mnc)
 | 
			
		||||
                    name3 = provider.name;
 | 
			
		||||
 | 
			
		||||
                if (!name2 && needlemnc.substring(0, 2) == mccmnc.mnc.substring(0, 2))
 | 
			
		||||
                    name2 = provider.name;
 | 
			
		||||
 | 
			
		||||
                if (name2 && name3)
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return name3 || name2 || null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function findProviderForSid(table, sid) {
 | 
			
		||||
    if (sid == 0)
 | 
			
		||||
        return null;
 | 
			
		||||
 | 
			
		||||
    // Search through each country
 | 
			
		||||
    for (let iter in table) {
 | 
			
		||||
        let country = table[iter];
 | 
			
		||||
        let providers = country.get_providers();
 | 
			
		||||
 | 
			
		||||
        // Search through each country's providers
 | 
			
		||||
        for (let i = 0; i < providers.length; i++) {
 | 
			
		||||
            let provider = providers[i];
 | 
			
		||||
            let cdma_sid = provider.get_cdma_sid();
 | 
			
		||||
 | 
			
		||||
            // Search through CDMA SID list
 | 
			
		||||
            for (let j = 0; j < cdma_sid.length; j++) {
 | 
			
		||||
                if (cdma_sid[j] == sid)
 | 
			
		||||
                    return provider.name;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ModemGsm = new Lang.Class({
 | 
			
		||||
@@ -91,64 +153,29 @@ const ModemGsm = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findOperatorName: function(name, opCode) {
 | 
			
		||||
        if (name.length != 0 && (name.length > 6 || name.length < 5)) {
 | 
			
		||||
            // this looks like a valid name, i.e. not an MCCMNC (that some
 | 
			
		||||
            // devices return when not yet connected
 | 
			
		||||
            return name;
 | 
			
		||||
        }
 | 
			
		||||
        if (isNaN(parseInt(name))) {
 | 
			
		||||
            // name is definitely not a MCCMNC, so it may be a name
 | 
			
		||||
            // after all; return that
 | 
			
		||||
            return name;
 | 
			
		||||
        if (name) {
 | 
			
		||||
            if (name && name.length != 0 && (name.length > 6 || name.length < 5)) {
 | 
			
		||||
                // this looks like a valid name, i.e. not an MCCMNC (that some
 | 
			
		||||
                // devices return when not yet connected
 | 
			
		||||
                return name;
 | 
			
		||||
            }
 | 
			
		||||
            if (isNaN(parseInt(name))) {
 | 
			
		||||
                // name is definitely not a MCCMNC, so it may be a name
 | 
			
		||||
                // after all; return that
 | 
			
		||||
                return name;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let needle;
 | 
			
		||||
        if (name.length == 0 && opCode)
 | 
			
		||||
        if ((name == null || name.length == 0) && opCode)
 | 
			
		||||
            needle = opCode;
 | 
			
		||||
        else if (name.length == 6 || name.length == 5)
 | 
			
		||||
            needle = name;
 | 
			
		||||
        else // nothing to search
 | 
			
		||||
            return null;
 | 
			
		||||
 | 
			
		||||
        return this._findProviderForMCCMNC(needle);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findProviderForMCCMNC: function(needle) {
 | 
			
		||||
        let table = _getProvidersTable();
 | 
			
		||||
        let needlemcc = needle.substring(0, 3);
 | 
			
		||||
        let needlemnc = needle.substring(3, needle.length);
 | 
			
		||||
 | 
			
		||||
        let name2, name3;
 | 
			
		||||
        for (let iter in table) {
 | 
			
		||||
            let providers = table[iter];
 | 
			
		||||
 | 
			
		||||
            // Search through each country's providers
 | 
			
		||||
            for (let i = 0; i < providers.length; i++) {
 | 
			
		||||
                let provider = providers[i];
 | 
			
		||||
 | 
			
		||||
                // Search through MCC/MNC list
 | 
			
		||||
                let list = provider.get_gsm_mcc_mnc();
 | 
			
		||||
                for (let j = 0; j < list.length; j++) {
 | 
			
		||||
                    let mccmnc = list[j];
 | 
			
		||||
 | 
			
		||||
                    // Match both 2-digit and 3-digit MNC; prefer a
 | 
			
		||||
                    // 3-digit match if found, otherwise a 2-digit one.
 | 
			
		||||
                    if (mccmnc.mcc != needlemcc)
 | 
			
		||||
                        continue;  // MCC was wrong
 | 
			
		||||
 | 
			
		||||
                    if (!name3 && needle.length == 6 && needlemnc == mccmnc.mnc)
 | 
			
		||||
                        name3 = provider.name;
 | 
			
		||||
 | 
			
		||||
                    if (!name2 && needlemnc.substring(0, 2) == mccmnc.mnc.substring(0, 2))
 | 
			
		||||
                        name2 = provider.name;
 | 
			
		||||
 | 
			
		||||
                    if (name2 && name3)
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return name3 || name2 || null;
 | 
			
		||||
        return findProviderForMCCMNC(table, needle);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ModemGsm.prototype);
 | 
			
		||||
@@ -189,39 +216,14 @@ const ModemCdma = new Lang.Class({
 | 
			
		||||
                this.operator_name = null;
 | 
			
		||||
            } else {
 | 
			
		||||
                let [bandClass, band, id] = result;
 | 
			
		||||
                if (name.length > 0)
 | 
			
		||||
                    this.operator_name = this._findProviderForSid(id);
 | 
			
		||||
                else
 | 
			
		||||
                if (name.length > 0) {
 | 
			
		||||
                    let table = _getProvidersTable();
 | 
			
		||||
                    this.operator_name = findProviderForSid(table, id);
 | 
			
		||||
                } else
 | 
			
		||||
                    this.operator_name = null;
 | 
			
		||||
            }
 | 
			
		||||
            this.emit('notify::operator-name');
 | 
			
		||||
        }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findProviderForSid: function(sid) {
 | 
			
		||||
        if (sid == 0)
 | 
			
		||||
            return null;
 | 
			
		||||
 | 
			
		||||
        let table = _getProvidersTable();
 | 
			
		||||
 | 
			
		||||
        // Search through each country
 | 
			
		||||
        for (let iter in table) {
 | 
			
		||||
            let providers = table[iter];
 | 
			
		||||
 | 
			
		||||
            // Search through each country's providers
 | 
			
		||||
            for (let i = 0; i < providers.length; i++) {
 | 
			
		||||
                let provider = providers[i];
 | 
			
		||||
                let cdma_sid = provider.get_cdma_sid();
 | 
			
		||||
 | 
			
		||||
                // Search through CDMA SID list
 | 
			
		||||
                for (let j = 0; j < cdma_sid.length; j++) {
 | 
			
		||||
                    if (cdma_sid[j] == sid)
 | 
			
		||||
                        return provider.name;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ModemCdma.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -159,86 +159,6 @@ function killall(processName) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This was ported from network-manager-applet
 | 
			
		||||
// Copyright 2007 - 2011 Red Hat, Inc.
 | 
			
		||||
// Author: Dan Williams <dcbw@redhat.com>
 | 
			
		||||
 | 
			
		||||
const _IGNORED_WORDS = [
 | 
			
		||||
        'Semiconductor',
 | 
			
		||||
        'Components',
 | 
			
		||||
        'Corporation',
 | 
			
		||||
        'Communications',
 | 
			
		||||
        'Company',
 | 
			
		||||
        'Corp.',
 | 
			
		||||
        'Corp',
 | 
			
		||||
        'Co.',
 | 
			
		||||
        'Inc.',
 | 
			
		||||
        'Inc',
 | 
			
		||||
        'Incorporated',
 | 
			
		||||
        'Ltd.',
 | 
			
		||||
        'Limited.',
 | 
			
		||||
        'Intel',
 | 
			
		||||
        'chipset',
 | 
			
		||||
        'adapter',
 | 
			
		||||
        '[hex]',
 | 
			
		||||
        'NDIS',
 | 
			
		||||
        'Module'
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const _IGNORED_PHRASES = [
 | 
			
		||||
        'Multiprotocol MAC/baseband processor',
 | 
			
		||||
        'Wireless LAN Controller',
 | 
			
		||||
        'Wireless LAN Adapter',
 | 
			
		||||
        'Wireless Adapter',
 | 
			
		||||
        'Network Connection',
 | 
			
		||||
        'Wireless Cardbus Adapter',
 | 
			
		||||
        'Wireless CardBus Adapter',
 | 
			
		||||
        '54 Mbps Wireless PC Card',
 | 
			
		||||
        'Wireless PC Card',
 | 
			
		||||
        'Wireless PC',
 | 
			
		||||
        'PC Card with XJACK(r) Antenna',
 | 
			
		||||
        'Wireless cardbus',
 | 
			
		||||
        'Wireless LAN PC Card',
 | 
			
		||||
        'Technology Group Ltd.',
 | 
			
		||||
        'Communication S.p.A.',
 | 
			
		||||
        'Business Mobile Networks BV',
 | 
			
		||||
        'Mobile Broadband Minicard Composite Device',
 | 
			
		||||
        'Mobile Communications AB',
 | 
			
		||||
        '(PC-Suite Mode)'
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
function fixupPCIDescription(desc) {
 | 
			
		||||
    desc = desc.replace(/[_,]/, ' ');
 | 
			
		||||
 | 
			
		||||
    /* Attempt to shorten ID by ignoring certain phrases */
 | 
			
		||||
    for (let i = 0; i < _IGNORED_PHRASES.length; i++) {
 | 
			
		||||
        let item = _IGNORED_PHRASES[i];
 | 
			
		||||
        let pos = desc.indexOf(item);
 | 
			
		||||
        if (pos != -1) {
 | 
			
		||||
            let before = desc.substring(0, pos);
 | 
			
		||||
            let after = desc.substring(pos + item.length, desc.length);
 | 
			
		||||
            desc = before + after;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Attmept to shorten ID by ignoring certain individual words */
 | 
			
		||||
    let words = desc.split(' ');
 | 
			
		||||
    let out = [ ];
 | 
			
		||||
    for (let i = 0; i < words.length; i++) {
 | 
			
		||||
        let item = words[i];
 | 
			
		||||
 | 
			
		||||
        // skip empty items (that come out from consecutive spaces)
 | 
			
		||||
        if (item.length == 0)
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        if (_IGNORED_WORDS.indexOf(item) == -1) {
 | 
			
		||||
            out.push(item);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return out.join(' ');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// lowerBound:
 | 
			
		||||
// @array: an array or array-like object, already sorted
 | 
			
		||||
//         according to @cmp
 | 
			
		||||
 
 | 
			
		||||
@@ -172,7 +172,7 @@ const AltTabPopup = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        if (!Main.pushModal(this.actor)) {
 | 
			
		||||
            // Probably someone else has a pointer grab, try again with keyboard only
 | 
			
		||||
            if (!Main.pushModal(this.actor, global.get_current_time(), Meta.ModalOptions.POINTER_ALREADY_GRABBED)) {
 | 
			
		||||
            if (!Main.pushModal(this.actor, { options: Meta.ModalOptions.POINTER_ALREADY_GRABBED })) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -48,18 +48,16 @@ const AlphabeticalView = new Lang.Class({
 | 
			
		||||
                                         style_class: 'vfade' });
 | 
			
		||||
        this.actor.add_actor(box);
 | 
			
		||||
        this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
 | 
			
		||||
        this.actor.connect('notify::mapped', Lang.bind(this,
 | 
			
		||||
            function() {
 | 
			
		||||
                if (!this.actor.mapped)
 | 
			
		||||
                    return;
 | 
			
		||||
        let action = new Clutter.PanAction({ interpolate: true });
 | 
			
		||||
        action.connect('pan', Lang.bind(this, this._onPan));
 | 
			
		||||
        this.actor.add_action(action);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
                let adjustment = this.actor.vscroll.adjustment;
 | 
			
		||||
                let direction = Overview.SwipeScrollDirection.VERTICAL;
 | 
			
		||||
                Main.overview.setScrollAdjustment(adjustment, direction);
 | 
			
		||||
 | 
			
		||||
                // Reset scroll on mapping
 | 
			
		||||
                adjustment.value = 0;
 | 
			
		||||
            }));
 | 
			
		||||
    _onPan: function(action) {
 | 
			
		||||
        let [dist, dx, dy] = action.get_motion_delta(0);
 | 
			
		||||
        let adjustment = this.actor.vscroll.adjustment;
 | 
			
		||||
        adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    removeAll: function() {
 | 
			
		||||
@@ -216,6 +214,16 @@ const ViewByCategories = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addCategory: function(name, index, dir) {
 | 
			
		||||
        let apps;
 | 
			
		||||
 | 
			
		||||
        if (dir != null) {
 | 
			
		||||
            apps = [];
 | 
			
		||||
            this._loadCategory(dir, apps);
 | 
			
		||||
 | 
			
		||||
            if (apps.length == 0)
 | 
			
		||||
                return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let button = new St.Button({ label: GLib.markup_escape_text (name, -1),
 | 
			
		||||
                                     style_class: 'app-filter',
 | 
			
		||||
                                     x_align: St.Align.START,
 | 
			
		||||
@@ -225,12 +233,9 @@ const ViewByCategories = new Lang.Class({
 | 
			
		||||
            this._selectCategory(index);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        var apps;
 | 
			
		||||
        if (dir == null) {
 | 
			
		||||
            this._allCategoryButton = button;
 | 
			
		||||
        } else {
 | 
			
		||||
            apps = [];
 | 
			
		||||
            this._loadCategory(dir, apps);
 | 
			
		||||
            this._categories.push({ apps: apps,
 | 
			
		||||
                                    name: name,
 | 
			
		||||
                                    button: button });
 | 
			
		||||
@@ -479,7 +484,6 @@ const AppWellIcon = new Lang.Class({
 | 
			
		||||
                                                Lang.bind(this,
 | 
			
		||||
                                                          this._onStateChanged));
 | 
			
		||||
        this._onStateChanged();
 | 
			
		||||
        this.isMenuUp = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDestroy: function() {
 | 
			
		||||
@@ -561,7 +565,8 @@ const AppWellIcon = new Lang.Class({
 | 
			
		||||
            this._menuManager.addMenu(this._menu);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.isMenuUp = true;
 | 
			
		||||
        this.emit('menu-state-changed', true);
 | 
			
		||||
 | 
			
		||||
        this.actor.set_hover(true);
 | 
			
		||||
        this._menu.popup();
 | 
			
		||||
 | 
			
		||||
@@ -578,7 +583,7 @@ const AppWellIcon = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _onMenuPoppedDown: function() {
 | 
			
		||||
        this.actor.sync_hover();
 | 
			
		||||
        this.isMenuUp = false;
 | 
			
		||||
        this.emit('menu-state-changed', false);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onActivate: function (event) {
 | 
			
		||||
 
 | 
			
		||||
@@ -84,9 +84,12 @@ const AppFavorites = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        let app = Shell.AppSystem.get_default().lookup_app(appId);
 | 
			
		||||
 | 
			
		||||
        Main.overview.setMessage(_("%s has been added to your favorites.").format(app.get_name()), Lang.bind(this, function () {
 | 
			
		||||
            this._removeFavorite(appId);
 | 
			
		||||
        }));
 | 
			
		||||
        Main.overview.setMessage(_("%s has been added to your favorites.").format(app.get_name()),
 | 
			
		||||
                                 { forFeedback: true,
 | 
			
		||||
                                   undoCallback: Lang.bind(this, function () {
 | 
			
		||||
                                                               this._removeFavorite(appId);
 | 
			
		||||
                                                           })
 | 
			
		||||
                                 });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addFavorite: function(appId) {
 | 
			
		||||
@@ -116,9 +119,11 @@ const AppFavorites = new Lang.Class({
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        Main.overview.setMessage(_("%s has been removed from your favorites.").format(app.get_name()),
 | 
			
		||||
                                 Lang.bind(this, function () {
 | 
			
		||||
            this._addFavorite(appId, pos);
 | 
			
		||||
        }));
 | 
			
		||||
                                 { forFeedback: true,
 | 
			
		||||
                                   undoCallback: Lang.bind(this, function () {
 | 
			
		||||
                                                               this._addFavorite(appId, pos);
 | 
			
		||||
                                                           })
 | 
			
		||||
                                 });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(AppFavorites.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -598,7 +598,7 @@ const NetworkAgent = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    enable: function() {
 | 
			
		||||
        this._native.register();
 | 
			
		||||
        this._native.auto_register = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    disable: function() {
 | 
			
		||||
@@ -612,6 +612,7 @@ const NetworkAgent = new Lang.Class({
 | 
			
		||||
            this._vpnRequests[requestId].cancel(true);
 | 
			
		||||
        this._vpnRequests = { };
 | 
			
		||||
 | 
			
		||||
        this._native.auto_register = false;
 | 
			
		||||
        this._native.unregister();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ const AuthenticationDialog = new Lang.Class({
 | 
			
		||||
        let messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
 | 
			
		||||
                                            vertical: true });
 | 
			
		||||
        mainContentBox.add(messageBox,
 | 
			
		||||
                           { y_align: St.Align.START });
 | 
			
		||||
                           { expand: true, y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this._subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline',
 | 
			
		||||
                                            text: _("Authentication Required") });
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
@@ -16,13 +17,16 @@ const Recorder = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    enable: function() {
 | 
			
		||||
        global.display.add_keybinding('toggle-recording',
 | 
			
		||||
                                      this._bindingSettings,
 | 
			
		||||
                                      Meta.KeyBindingFlags.NONE, Lang.bind(this, this._toggleRecorder));
 | 
			
		||||
        Main.wm.addKeybinding('toggle-recording',
 | 
			
		||||
                              this._bindingSettings,
 | 
			
		||||
                              Meta.KeyBindingFlags.NONE,
 | 
			
		||||
                              Main.KeybindingMode.NORMAL |
 | 
			
		||||
                              Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                              Lang.bind(this, this._toggleRecorder));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    disable: function() {
 | 
			
		||||
        global.display.remove_keybinding('toggle-recording');
 | 
			
		||||
        Main.wm.removeKeybinding('toggle-recording');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _ensureRecorder: function() {
 | 
			
		||||
 
 | 
			
		||||
@@ -383,25 +383,12 @@ const TelepathyClient = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Display notification to ask user to accept/reject request */
 | 
			
		||||
        let source = this._ensureSubscriptionSource();
 | 
			
		||||
        let source = this._ensureAppSource();
 | 
			
		||||
 | 
			
		||||
        let notif = new SubscriptionRequestNotification(source, contact);
 | 
			
		||||
        source.notify(notif);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _ensureSubscriptionSource: function() {
 | 
			
		||||
        if (this._subscriptionSource == null) {
 | 
			
		||||
            this._subscriptionSource = new MessageTray.Source(_("Subscription request"),
 | 
			
		||||
                                                              'gtk-dialog-question');
 | 
			
		||||
            Main.messageTray.add(this._subscriptionSource);
 | 
			
		||||
            this._subscriptionSource.connect('destroy', Lang.bind(this, function () {
 | 
			
		||||
                this._subscriptionSource = null;
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this._subscriptionSource;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _accountConnectionStatusNotifyCb: function(account) {
 | 
			
		||||
        let connectionError = account.connection_error;
 | 
			
		||||
 | 
			
		||||
@@ -415,7 +402,7 @@ const TelepathyClient = new Lang.Class({
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        /* Display notification that account failed to connect */
 | 
			
		||||
        let source = this._ensureAccountSource();
 | 
			
		||||
        let source = this._ensureAppSource();
 | 
			
		||||
 | 
			
		||||
        notif = new AccountNotification(source, account, connectionError);
 | 
			
		||||
        this._accountNotifications[account.get_object_path()] = notif;
 | 
			
		||||
@@ -425,17 +412,16 @@ const TelepathyClient = new Lang.Class({
 | 
			
		||||
        source.notify(notif);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _ensureAccountSource: function() {
 | 
			
		||||
        if (this._accountSource == null) {
 | 
			
		||||
            this._accountSource = new MessageTray.Source(_("Connection error"),
 | 
			
		||||
                                                         'gtk-dialog-error');
 | 
			
		||||
            Main.messageTray.add(this._accountSource);
 | 
			
		||||
            this._accountSource.connect('destroy', Lang.bind(this, function () {
 | 
			
		||||
                this._accountSource = null;
 | 
			
		||||
    _ensureAppSource: function() {
 | 
			
		||||
        if (this._appSource == null) {
 | 
			
		||||
            this._appSource = new MessageTray.Source(_("Chat"), 'empathy');
 | 
			
		||||
            Main.messageTray.add(this._appSource);
 | 
			
		||||
            this._appSource.connect('destroy', Lang.bind(this, function () {
 | 
			
		||||
                this._appSource = null;
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this._accountSource;
 | 
			
		||||
        return this._appSource;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@@ -771,16 +757,19 @@ const ChatNotification = new Lang.Class({
 | 
			
		||||
            this.emit('unfocused');
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this._oldMaxScrollAdjustment = 0;
 | 
			
		||||
        this._createScrollArea();
 | 
			
		||||
        this._lastGroup = null;
 | 
			
		||||
        this._lastGroupActor = null;
 | 
			
		||||
 | 
			
		||||
        // Keep track of the bottom position for the current adjustment and
 | 
			
		||||
        // force a scroll to the bottom if things change while we were at the
 | 
			
		||||
        // bottom
 | 
			
		||||
        this._oldMaxScrollValue = this._scrollArea.vscroll.adjustment.value;
 | 
			
		||||
        this._scrollArea.add_style_class_name('chat-notification-scrollview');
 | 
			
		||||
        this._scrollArea.vscroll.adjustment.connect('changed', Lang.bind(this, function(adjustment) {
 | 
			
		||||
            let currentValue = adjustment.value + adjustment.page_size;
 | 
			
		||||
            if (currentValue == this._oldMaxScrollAdjustment)
 | 
			
		||||
            if (adjustment.value == this._oldMaxScrollValue)
 | 
			
		||||
                this.scrollTo(St.Side.BOTTOM);
 | 
			
		||||
            this._oldMaxScrollAdjustment = adjustment.upper;
 | 
			
		||||
            this._oldMaxScrollValue = Math.max(adjustment.lower, adjustment.upper - adjustment.page_size);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this._inputHistory = new History.HistoryManager({ entry: this._responseEntry.clutter_text });
 | 
			
		||||
@@ -1133,7 +1122,7 @@ const AudioVideoNotification = new Lang.Class({
 | 
			
		||||
        this.parent(source, title, null, { customContent: true });
 | 
			
		||||
        this.setResident(true);
 | 
			
		||||
 | 
			
		||||
        this.addButton('reject', _("Reject"));
 | 
			
		||||
        this.addButton('reject', _("Decline"));
 | 
			
		||||
        /* translators: this is a button label (verb), not a noun */
 | 
			
		||||
        this.addButton('answer', _("Answer"));
 | 
			
		||||
 | 
			
		||||
@@ -1350,26 +1339,16 @@ const AccountNotification = new Lang.Class({
 | 
			
		||||
        this.parent(source,
 | 
			
		||||
                    /* translators: argument is the account name, like
 | 
			
		||||
                     * name@jabber.org for example. */
 | 
			
		||||
                    _("Connection to %s failed").format(account.get_display_name()),
 | 
			
		||||
                    null, { customContent: true });
 | 
			
		||||
 | 
			
		||||
        this._label = new St.Label();
 | 
			
		||||
        this.addActor(this._label);
 | 
			
		||||
        this._updateMessage(connectionError);
 | 
			
		||||
                    _("Unable to connect to %s").format(account.get_display_name()),
 | 
			
		||||
                    this._getMessage(connectionError));
 | 
			
		||||
 | 
			
		||||
        this._account = account;
 | 
			
		||||
 | 
			
		||||
        this.addButton('reconnect', _("Reconnect"));
 | 
			
		||||
        this.addButton('edit', _("Edit account"));
 | 
			
		||||
        this.addButton('view', _("View account"));
 | 
			
		||||
 | 
			
		||||
        this.connect('action-invoked', Lang.bind(this, function(self, action) {
 | 
			
		||||
            switch (action) {
 | 
			
		||||
            case 'reconnect':
 | 
			
		||||
                // If it fails again, a new notification should pop up with the
 | 
			
		||||
                // new error.
 | 
			
		||||
                account.reconnect_async(null);
 | 
			
		||||
                break;
 | 
			
		||||
            case 'edit':
 | 
			
		||||
            case 'view':
 | 
			
		||||
                let cmd = '/usr/bin/empathy-accounts'
 | 
			
		||||
                        + ' --select-account=%s'
 | 
			
		||||
                        .format(account.get_path_suffix());
 | 
			
		||||
@@ -1395,19 +1374,19 @@ const AccountNotification = new Lang.Class({
 | 
			
		||||
                if (status == Tp.ConnectionStatus.CONNECTED) {
 | 
			
		||||
                    this.destroy();
 | 
			
		||||
                } else if (status == Tp.ConnectionStatus.DISCONNECTED) {
 | 
			
		||||
                    this._updateMessage(account.connection_error);
 | 
			
		||||
                    this.update(this.title, this._getMessage(account.connection_error));
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateMessage: function(connectionError) {
 | 
			
		||||
    _getMessage: function(connectionError) {
 | 
			
		||||
        let message;
 | 
			
		||||
        if (connectionError in _connectionErrorMessages) {
 | 
			
		||||
            message = _connectionErrorMessages[connectionError];
 | 
			
		||||
        } else {
 | 
			
		||||
            message = _("Unknown reason");
 | 
			
		||||
        }
 | 
			
		||||
        this._label.set_text(message);
 | 
			
		||||
        return message;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
 
 | 
			
		||||
@@ -23,8 +23,7 @@ const DASH_ITEM_HOVER_TIMEOUT = 300;
 | 
			
		||||
 | 
			
		||||
function getAppFromSource(source) {
 | 
			
		||||
    if (source instanceof AppDisplay.AppWellIcon) {
 | 
			
		||||
        let appSystem = Shell.AppSystem.get_default();
 | 
			
		||||
        return appSystem.lookup_app(source.getId());
 | 
			
		||||
        return source.app;
 | 
			
		||||
    } else if (source.metaWindow) {
 | 
			
		||||
        let tracker = Shell.WindowTracker.get_default();
 | 
			
		||||
        return tracker.get_window_app(source.metaWindow);
 | 
			
		||||
@@ -142,6 +141,7 @@ const DashItemContainer = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    setLabelText: function(text) {
 | 
			
		||||
        this._labelText = text;
 | 
			
		||||
        this.child.accessible_name = text;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hideLabel: function () {
 | 
			
		||||
@@ -259,7 +259,6 @@ const ShowAppsIcon = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this.setChild(this.toggleButton);
 | 
			
		||||
        this.setDragApp(null);
 | 
			
		||||
        this.toggleButton.label_actor = this.label;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createIcon: function(size) {
 | 
			
		||||
@@ -492,32 +491,51 @@ const Dash = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createAppItem: function(app) {
 | 
			
		||||
        let display = new AppDisplay.AppWellIcon(app,
 | 
			
		||||
        let appIcon = new AppDisplay.AppWellIcon(app,
 | 
			
		||||
                                                 { setSizeManually: true,
 | 
			
		||||
                                                   showLabel: false });
 | 
			
		||||
        display._draggable.connect('drag-begin',
 | 
			
		||||
        appIcon._draggable.connect('drag-begin',
 | 
			
		||||
                                   Lang.bind(this, function() {
 | 
			
		||||
                                       display.actor.opacity = 50;
 | 
			
		||||
                                       appIcon.actor.opacity = 50;
 | 
			
		||||
                                   }));
 | 
			
		||||
        display._draggable.connect('drag-end',
 | 
			
		||||
        appIcon._draggable.connect('drag-end',
 | 
			
		||||
                                   Lang.bind(this, function() {
 | 
			
		||||
                                       display.actor.opacity = 255;
 | 
			
		||||
                                       appIcon.actor.opacity = 255;
 | 
			
		||||
                                   }));
 | 
			
		||||
        appIcon.connect('menu-state-changed',
 | 
			
		||||
                        Lang.bind(this, function(appIcon, opened) {
 | 
			
		||||
                            this._itemMenuStateChanged(item, opened);
 | 
			
		||||
                        }));
 | 
			
		||||
 | 
			
		||||
        let item = new DashItemContainer();
 | 
			
		||||
        item.setChild(display.actor);
 | 
			
		||||
        item.setChild(appIcon.actor);
 | 
			
		||||
 | 
			
		||||
        // Override default AppWellIcon label_actor, now the
 | 
			
		||||
        // accessible_name is set at DashItemContainer.setLabelText
 | 
			
		||||
        appIcon.actor.label_actor = null;
 | 
			
		||||
        item.setLabelText(app.get_name());
 | 
			
		||||
        // Override default AppWellIcon label_actor
 | 
			
		||||
        display.actor.label_actor = item.label;
 | 
			
		||||
        display.icon.setIconSize(this.iconSize);
 | 
			
		||||
 | 
			
		||||
        appIcon.icon.setIconSize(this.iconSize);
 | 
			
		||||
        this._hookUpLabel(item);
 | 
			
		||||
 | 
			
		||||
        return item;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _itemMenuStateChanged: function(item, opened) {
 | 
			
		||||
        // When the menu closes, it calls sync_hover, which means
 | 
			
		||||
        // that the notify::hover handler does everything we need to.
 | 
			
		||||
        if (opened) {
 | 
			
		||||
            if (this._showLabelTimeoutId > 0) {
 | 
			
		||||
                Mainloop.source_remove(this._showLabelTimeoutId);
 | 
			
		||||
                this._showLabelTimeoutId = 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            item.hideLabel();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onHover: function (item) {
 | 
			
		||||
        if (item.child.get_hover() && !item.child._delegate.isMenuUp) {
 | 
			
		||||
        if (item.child.get_hover()) {
 | 
			
		||||
            if (this._showLabelTimeoutId == 0) {
 | 
			
		||||
                let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT;
 | 
			
		||||
                this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
 | 
			
		||||
@@ -619,8 +637,10 @@ const Dash = new Lang.Class({
 | 
			
		||||
            icon.setIconSize(this.iconSize);
 | 
			
		||||
 | 
			
		||||
            // Don't animate the icon size change when the overview
 | 
			
		||||
            // is not visible or when initially filling the dash
 | 
			
		||||
            if (!Main.overview.visible || !this._shownInitially)
 | 
			
		||||
            // is transitioning, not visible or when initially filling
 | 
			
		||||
            // the dash
 | 
			
		||||
            if (!Main.overview.visible || Main.overview.animationInProgress ||
 | 
			
		||||
                !this._shownInitially)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            let [targetWidth, targetHeight] = icon.icon.get_size();
 | 
			
		||||
@@ -744,8 +764,9 @@ const Dash = new Lang.Class({
 | 
			
		||||
        for (let i = 0; i < removedActors.length; i++) {
 | 
			
		||||
            let item = removedActors[i]._delegate;
 | 
			
		||||
 | 
			
		||||
            // Don't animate item removal when the overview is hidden
 | 
			
		||||
            if (Main.overview.visible)
 | 
			
		||||
            // Don't animate item removal when the overview is transitioning
 | 
			
		||||
            // or hidden
 | 
			
		||||
            if (Main.overview.visible && !Main.overview.animationInProgress)
 | 
			
		||||
                item.animateOutAndDestroy();
 | 
			
		||||
            else
 | 
			
		||||
                item.destroy();
 | 
			
		||||
@@ -760,8 +781,9 @@ const Dash = new Lang.Class({
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Don't animate item addition when the overview is hidden
 | 
			
		||||
        if (!Main.overview.visible)
 | 
			
		||||
        // Don't animate item addition when the overview is transitioning
 | 
			
		||||
        // or hidden
 | 
			
		||||
        if (!Main.overview.visible || Main.overview.animationInProgress)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < addedItems.length; i++)
 | 
			
		||||
 
 | 
			
		||||
@@ -126,11 +126,7 @@ function logExtensionError(uuid, error) {
 | 
			
		||||
 | 
			
		||||
    let message = '' + error;
 | 
			
		||||
 | 
			
		||||
    if (error.state)
 | 
			
		||||
        extension.state = error.state;
 | 
			
		||||
    else
 | 
			
		||||
        extension.state = ExtensionState.ERROR;
 | 
			
		||||
 | 
			
		||||
    extension.state = ExtensionState.ERROR;
 | 
			
		||||
    if (!extension.errors)
 | 
			
		||||
        extension.errors = [];
 | 
			
		||||
 | 
			
		||||
@@ -145,18 +141,16 @@ function loadExtension(extension) {
 | 
			
		||||
    extension.state = ExtensionState.ERROR;
 | 
			
		||||
 | 
			
		||||
    if (ExtensionUtils.isOutOfDate(extension)) {
 | 
			
		||||
        let error = new Error('extension is not compatible with current GNOME Shell and/or GJS version');
 | 
			
		||||
        error.state = ExtensionState.OUT_OF_DATE;
 | 
			
		||||
        throw error;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let enabled = enabledExtensions.indexOf(extension.uuid) != -1;
 | 
			
		||||
    if (enabled) {
 | 
			
		||||
        initExtension(extension.uuid);
 | 
			
		||||
        if (extension.state == ExtensionState.DISABLED)
 | 
			
		||||
            enableExtension(extension.uuid);
 | 
			
		||||
        extension.state = ExtensionState.OUT_OF_DATE;
 | 
			
		||||
    } else {
 | 
			
		||||
        extension.state = ExtensionState.INITIALIZED;
 | 
			
		||||
        let enabled = enabledExtensions.indexOf(extension.uuid) != -1;
 | 
			
		||||
        if (enabled) {
 | 
			
		||||
            initExtension(extension.uuid);
 | 
			
		||||
            if (extension.state == ExtensionState.DISABLED)
 | 
			
		||||
                enableExtension(extension.uuid);
 | 
			
		||||
        } else {
 | 
			
		||||
            extension.state = ExtensionState.INITIALIZED;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _signals.emit('extension-state-changed', extension);
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ function _navigateActor(actor) {
 | 
			
		||||
 | 
			
		||||
// GrabHelper:
 | 
			
		||||
// @owner: the actor that owns the GrabHelper
 | 
			
		||||
// @params: optional parameters to pass to Main.pushModal()
 | 
			
		||||
//
 | 
			
		||||
// Creates a new GrabHelper object, for dealing with keyboard and pointer grabs
 | 
			
		||||
// associated with a set of actors.
 | 
			
		||||
@@ -34,14 +35,14 @@ function _navigateActor(actor) {
 | 
			
		||||
const GrabHelper = new Lang.Class({
 | 
			
		||||
    Name: 'GrabHelper',
 | 
			
		||||
 | 
			
		||||
    _init: function(owner) {
 | 
			
		||||
    _init: function(owner, params) {
 | 
			
		||||
        this._owner = owner;
 | 
			
		||||
        this._modalParams = params;
 | 
			
		||||
 | 
			
		||||
        this._grabStack = [];
 | 
			
		||||
 | 
			
		||||
        this._actors = [];
 | 
			
		||||
        this._capturedEventId = 0;
 | 
			
		||||
        this._eventId = 0;
 | 
			
		||||
        this._keyFocusNotifyId = 0;
 | 
			
		||||
        this._focusWindowChangedId = 0;
 | 
			
		||||
        this._ignoreRelease = false;
 | 
			
		||||
@@ -75,10 +76,25 @@ const GrabHelper = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _actorInGrabStack: function(actor) {
 | 
			
		||||
        while (actor) {
 | 
			
		||||
            for (let i = 0; i < this._grabStack.length; i++) {
 | 
			
		||||
                let grab = this._grabStack[i];
 | 
			
		||||
                if (grab.actor == actor)
 | 
			
		||||
                    return i;
 | 
			
		||||
            }
 | 
			
		||||
            actor = actor.get_parent();
 | 
			
		||||
        }
 | 
			
		||||
        return -1;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _isWithinGrabbedActor: function(actor) {
 | 
			
		||||
       let currentActor = this.currentGrab.actor;
 | 
			
		||||
        while (actor) {
 | 
			
		||||
            if (this._actors.indexOf(actor) != -1)
 | 
			
		||||
                return true;
 | 
			
		||||
            if (actor == currentActor)
 | 
			
		||||
                return true;
 | 
			
		||||
            actor = actor.get_parent();
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
@@ -88,6 +104,14 @@ const GrabHelper = new Lang.Class({
 | 
			
		||||
        return this._grabStack[this._grabStack.length - 1] || {};
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get grabbed() {
 | 
			
		||||
        return this._grabStack.length > 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get grabStack() {
 | 
			
		||||
        return this._grabStack;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findStackIndex: function(actor) {
 | 
			
		||||
        if (!actor)
 | 
			
		||||
            return -1;
 | 
			
		||||
@@ -165,11 +189,10 @@ const GrabHelper = new Lang.Class({
 | 
			
		||||
    _takeModalGrab: function() {
 | 
			
		||||
        let firstGrab = (this._modalCount == 0);
 | 
			
		||||
        if (firstGrab) {
 | 
			
		||||
            if (!Main.pushModal(this._owner))
 | 
			
		||||
            if (!Main.pushModal(this._owner, this._modalParams))
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
 | 
			
		||||
            this._eventId = global.stage.connect('event', Lang.bind(this, this._onEvent));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._modalCount++;
 | 
			
		||||
@@ -186,11 +209,6 @@ const GrabHelper = new Lang.Class({
 | 
			
		||||
            this._capturedEventId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._eventId > 0) {
 | 
			
		||||
            global.stage.disconnect(this._eventId);
 | 
			
		||||
            this._eventId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Main.popModal(this._owner);
 | 
			
		||||
        global.sync_pointer();
 | 
			
		||||
    },
 | 
			
		||||
@@ -321,27 +339,22 @@ const GrabHelper = new Lang.Class({
 | 
			
		||||
        if (Main.keyboard.shouldTakeEvent(event))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (button) {
 | 
			
		||||
            // If we have a press event, ignore the next event,
 | 
			
		||||
            // which should be a release event.
 | 
			
		||||
            if (press)
 | 
			
		||||
                this._ignoreRelease = true;
 | 
			
		||||
            this.ungrab({ actor: this._grabStack[0].actor });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this._modalCount > 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // We catch 'event' rather than 'key-press-event' so that we get
 | 
			
		||||
    // a chance to run before the overview's own Escape check
 | 
			
		||||
    _onEvent: function(actor, event) {
 | 
			
		||||
        if (event.type() == Clutter.EventType.KEY_PRESS &&
 | 
			
		||||
        if (type == Clutter.EventType.KEY_PRESS &&
 | 
			
		||||
            event.get_key_symbol() == Clutter.KEY_Escape) {
 | 
			
		||||
            this.ungrab();
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
        if (button) {
 | 
			
		||||
            // If we have a press event, ignore the next event,
 | 
			
		||||
            // which should be a release event.
 | 
			
		||||
            if (press)
 | 
			
		||||
                this._ignoreRelease = true;
 | 
			
		||||
            let i = this._actorInGrabStack(event.get_source()) + 1;
 | 
			
		||||
            this.ungrab({ actor: this._grabStack[i].actor });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this._modalCount > 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyFocusChanged: function() {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,25 +20,6 @@ const KEYBOARD_TYPE = 'keyboard-type';
 | 
			
		||||
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
 | 
			
		||||
const SHOW_KEYBOARD = 'screen-keyboard-enabled';
 | 
			
		||||
 | 
			
		||||
// Key constants taken from Antler
 | 
			
		||||
// FIXME: ought to be moved into libcaribou
 | 
			
		||||
const PRETTY_KEYS = {
 | 
			
		||||
    'BackSpace': '\u232b',
 | 
			
		||||
    'space': ' ',
 | 
			
		||||
    'Return': '\u23ce',
 | 
			
		||||
    'Caribou_Prefs': '\u2328',
 | 
			
		||||
    'Caribou_ShiftUp': '\u2b06',
 | 
			
		||||
    'Caribou_ShiftDown': '\u2b07',
 | 
			
		||||
    'Caribou_Emoticons': '\u263a',
 | 
			
		||||
    'Caribou_Symbols': '123',
 | 
			
		||||
    'Caribou_Symbols_More': '{#*',
 | 
			
		||||
    'Caribou_Alpha': 'Abc',
 | 
			
		||||
    'Tab': 'Tab',
 | 
			
		||||
    'Escape': 'Esc',
 | 
			
		||||
    'Control_L': 'Ctrl',
 | 
			
		||||
    'Alt_L': 'Alt'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const CaribouKeyboardIface = <interface name='org.gnome.Caribou.Keyboard'>
 | 
			
		||||
<method name='Show'>
 | 
			
		||||
    <arg type='u' direction='in' />
 | 
			
		||||
@@ -98,17 +79,7 @@ const Key = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _makeKey: function () {
 | 
			
		||||
        let label = this._key.name;
 | 
			
		||||
 | 
			
		||||
        if (label.length > 1) {
 | 
			
		||||
            let pretty = PRETTY_KEYS[label];
 | 
			
		||||
            if (pretty)
 | 
			
		||||
                label = pretty;
 | 
			
		||||
            else
 | 
			
		||||
                label = this._getUnichar(this._key);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        label = GLib.markup_escape_text(label, -1);
 | 
			
		||||
        let label = GLib.markup_escape_text(this._key.label, -1);
 | 
			
		||||
        let button = new St.Button ({ label: label,
 | 
			
		||||
                                      style_class: 'keyboard-key' });
 | 
			
		||||
 | 
			
		||||
@@ -280,7 +251,7 @@ const Keyboard = new Lang.Class({
 | 
			
		||||
        this._focusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
 | 
			
		||||
 | 
			
		||||
        if (show)
 | 
			
		||||
            this.show();
 | 
			
		||||
            this.show(Main.layoutManager.focusIndex);
 | 
			
		||||
        else
 | 
			
		||||
            this._createSource();
 | 
			
		||||
    },
 | 
			
		||||
@@ -404,7 +375,7 @@ const Keyboard = new Lang.Class({
 | 
			
		||||
        if (!this._enableKeyboard)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let monitor = Main.layoutManager.bottomMonitor;
 | 
			
		||||
        let monitor = Main.layoutManager.keyboardMonitor;
 | 
			
		||||
        let maxHeight = monitor.height / 3;
 | 
			
		||||
        this.actor.width = monitor.width;
 | 
			
		||||
 | 
			
		||||
@@ -491,9 +462,9 @@ const Keyboard = new Lang.Class({
 | 
			
		||||
               actor._extended_keys || actor.extended_key;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show: function () {
 | 
			
		||||
    show: function (monitor) {
 | 
			
		||||
        Main.layoutManager.keyboardIndex = monitor;
 | 
			
		||||
        this._redraw();
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.showKeyboard();
 | 
			
		||||
        this._destroySource();
 | 
			
		||||
    },
 | 
			
		||||
@@ -541,7 +512,7 @@ const Keyboard = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        if (timestamp != Clutter.CURRENT_TIME)
 | 
			
		||||
            this._timestamp = timestamp;
 | 
			
		||||
        this.show();
 | 
			
		||||
        this.show(Main.layoutManager.focusIndex);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    Hide: function(timestamp) {
 | 
			
		||||
@@ -595,6 +566,7 @@ const KeyboardSource = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    open: function() {
 | 
			
		||||
        this._keyboard.show();
 | 
			
		||||
        // Show the OSK below the message tray
 | 
			
		||||
        this._keyboard.show(Main.layoutManager.bottomIndex);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										247
									
								
								js/ui/layout.js
									
									
									
									
									
								
							
							
						
						
									
										247
									
								
								js/ui/layout.js
									
									
									
									
									
								
							@@ -19,6 +19,12 @@ const STARTUP_ANIMATION_TIME = 0.2;
 | 
			
		||||
const KEYBOARD_ANIMATION_TIME = 0.5;
 | 
			
		||||
const PLYMOUTH_TRANSITION_TIME = 1;
 | 
			
		||||
 | 
			
		||||
const MESSAGE_TRAY_PRESSURE_THRESHOLD = 200;
 | 
			
		||||
// The maximium amount that the user is allowed to travel
 | 
			
		||||
// perpendicular to the barrier before we release the accumulated
 | 
			
		||||
// pressure.
 | 
			
		||||
const MESSAGE_TRAY_MAX_SKIRT = 100;
 | 
			
		||||
 | 
			
		||||
const MonitorConstraint = new Lang.Class({
 | 
			
		||||
    Name: 'MonitorConstraint',
 | 
			
		||||
    Extends: Clutter.Constraint,
 | 
			
		||||
@@ -103,11 +109,12 @@ const LayoutManager = new Lang.Class({
 | 
			
		||||
        this.monitors = [];
 | 
			
		||||
        this.primaryMonitor = null;
 | 
			
		||||
        this.primaryIndex = -1;
 | 
			
		||||
        this._keyboardIndex = -1;
 | 
			
		||||
        this._hotCorners = [];
 | 
			
		||||
        this._background = null;
 | 
			
		||||
        this._leftPanelBarrier = 0;
 | 
			
		||||
        this._rightPanelBarrier = 0;
 | 
			
		||||
        this._trayBarrier = 0;
 | 
			
		||||
        this._leftPanelBarrier = null;
 | 
			
		||||
        this._rightPanelBarrier = null;
 | 
			
		||||
        this._trayBarrier = null;
 | 
			
		||||
 | 
			
		||||
        this._chrome = new Chrome(this);
 | 
			
		||||
 | 
			
		||||
@@ -242,9 +249,8 @@ const LayoutManager = new Lang.Class({
 | 
			
		||||
        this.panelBox.set_position(this.primaryMonitor.x, this.primaryMonitor.y);
 | 
			
		||||
        this.panelBox.set_size(this.primaryMonitor.width, -1);
 | 
			
		||||
 | 
			
		||||
        this.keyboardBox.set_position(this.bottomMonitor.x,
 | 
			
		||||
                                      this.bottomMonitor.y + this.bottomMonitor.height);
 | 
			
		||||
        this.keyboardBox.set_size(this.bottomMonitor.width, -1);
 | 
			
		||||
        if (this.keyboardIndex < 0)
 | 
			
		||||
            this.keyboardIndex = this.primaryIndex;
 | 
			
		||||
 | 
			
		||||
        this.trayBox.set_position(this.bottomMonitor.x,
 | 
			
		||||
                                  this.bottomMonitor.y + this.bottomMonitor.height);
 | 
			
		||||
@@ -259,40 +265,50 @@ const LayoutManager = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updatePanelBarriers: function() {
 | 
			
		||||
        if (this._leftPanelBarrier)
 | 
			
		||||
            global.destroy_pointer_barrier(this._leftPanelBarrier);
 | 
			
		||||
        if (this._rightPanelBarrier)
 | 
			
		||||
            global.destroy_pointer_barrier(this._rightPanelBarrier);
 | 
			
		||||
        if (this._leftPanelBarrier) {
 | 
			
		||||
            this._leftPanelBarrier.destroy();
 | 
			
		||||
            this._leftPanelBarrier = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._rightPanelBarrier) {
 | 
			
		||||
            this._rightPanelBarrier.destroy();
 | 
			
		||||
            this._rightPanelBarrier = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.panelBox.height) {
 | 
			
		||||
            let primary = this.primaryMonitor;
 | 
			
		||||
            this._leftPanelBarrier =
 | 
			
		||||
                global.create_pointer_barrier(primary.x, primary.y,
 | 
			
		||||
                                              primary.x, primary.y + this.panelBox.height,
 | 
			
		||||
                                              1 /* BarrierPositiveX */);
 | 
			
		||||
            this._rightPanelBarrier =
 | 
			
		||||
                global.create_pointer_barrier(primary.x + primary.width, primary.y,
 | 
			
		||||
                                              primary.x + primary.width, primary.y + this.panelBox.height,
 | 
			
		||||
                                              4 /* BarrierNegativeX */);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._leftPanelBarrier = 0;
 | 
			
		||||
            this._rightPanelBarrier = 0;
 | 
			
		||||
 | 
			
		||||
            this._leftPanelBarrier  = new Meta.Barrier({ display: global.display,
 | 
			
		||||
                                                         x1: primary.x, y1: primary.y,
 | 
			
		||||
                                                         x2: primary.x, y2: primary.y + this.panelBox.height,
 | 
			
		||||
                                                         directions: Meta.BarrierDirection.POSITIVE_X });
 | 
			
		||||
            this._rightPanelBarrier = new Meta.Barrier({ display: global.display,
 | 
			
		||||
                                                         x1: primary.x + primary.width, y1: primary.y,
 | 
			
		||||
                                                         x2: primary.x + primary.width, y2: primary.y + this.panelBox.height,
 | 
			
		||||
                                                         directions: Meta.BarrierDirection.NEGATIVE_X });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateTrayBarrier: function() {
 | 
			
		||||
        let monitor = this.bottomMonitor;
 | 
			
		||||
 | 
			
		||||
        if (this._trayBarrier)
 | 
			
		||||
            global.destroy_pointer_barrier(this._trayBarrier);
 | 
			
		||||
        if (this._trayBarrier) {
 | 
			
		||||
            this._trayBarrier.destroy();
 | 
			
		||||
            this._trayBarrier = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (Main.messageTray) {
 | 
			
		||||
            this._trayBarrier =
 | 
			
		||||
                global.create_pointer_barrier(monitor.x + monitor.width, monitor.y + monitor.height - Main.messageTray.actor.height,
 | 
			
		||||
                                              monitor.x + monitor.width, monitor.y + monitor.height,
 | 
			
		||||
                                              4 /* BarrierNegativeX */);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._trayBarrier = 0;
 | 
			
		||||
            this._trayBarrier = new Meta.Barrier({ display: global.display,
 | 
			
		||||
                                                   x1: monitor.x, x2: monitor.x + monitor.width,
 | 
			
		||||
                                                   y1: monitor.y + monitor.height - 1, y2: monitor.y + monitor.height - 1,
 | 
			
		||||
                                                   directions: Meta.BarrierDirection.NEGATIVE_Y });
 | 
			
		||||
 | 
			
		||||
            this._trayPressure = new PressureBarrier(this._trayBarrier,
 | 
			
		||||
                                                     MESSAGE_TRAY_PRESSURE_THRESHOLD,
 | 
			
		||||
                                                     MESSAGE_TRAY_MAX_SKIRT);
 | 
			
		||||
            this._trayPressure.connect('trigger', function() {
 | 
			
		||||
                Main.messageTray.openTray();
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -323,6 +339,42 @@ const LayoutManager = new Lang.Class({
 | 
			
		||||
        return this.monitors[index];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get keyboardMonitor() {
 | 
			
		||||
        return this.monitors[this.keyboardIndex];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get focusIndex() {
 | 
			
		||||
        let i = Main.layoutManager.primaryIndex;
 | 
			
		||||
 | 
			
		||||
        if (global.stage_input_mode == Shell.StageInputMode.FOCUSED ||
 | 
			
		||||
            global.stage_input_mode == Shell.StageInputMode.FULLSCREEN) {
 | 
			
		||||
            let focusActor = global.stage.key_focus;
 | 
			
		||||
            if (focusActor)
 | 
			
		||||
                i = this._chrome.findIndexForActor(focusActor);
 | 
			
		||||
        } else {
 | 
			
		||||
            let focusWindow = global.display.focus_window;
 | 
			
		||||
            if (focusWindow)
 | 
			
		||||
                i = this._chrome.findIndexForWindow(focusWindow.get_compositor_private());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return i;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get focusMonitor() {
 | 
			
		||||
        return this.monitors[this.focusIndex];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    set keyboardIndex(v) {
 | 
			
		||||
        this._keyboardIndex = v;
 | 
			
		||||
        this.keyboardBox.set_position(this.keyboardMonitor.x,
 | 
			
		||||
                                      this.keyboardMonitor.y + this.keyboardMonitor.height);
 | 
			
		||||
        this.keyboardBox.set_size(this.keyboardMonitor.width, -1);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get keyboardIndex() {
 | 
			
		||||
        return this._keyboardIndex;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _startupAnimation: function() {
 | 
			
		||||
        this.panelBox.anchor_y = this.panelBox.height;
 | 
			
		||||
 | 
			
		||||
@@ -381,11 +433,14 @@ const LayoutManager = new Lang.Class({
 | 
			
		||||
                           onComplete: this._showKeyboardComplete,
 | 
			
		||||
                           onCompleteScope: this
 | 
			
		||||
                         });
 | 
			
		||||
        Tweener.addTween(this.trayBox,
 | 
			
		||||
                         { anchor_y: this.keyboardBox.height,
 | 
			
		||||
                           time: KEYBOARD_ANIMATION_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad'
 | 
			
		||||
                         });
 | 
			
		||||
 | 
			
		||||
        if (this.keyboardIndex == this.bottomIndex) {
 | 
			
		||||
            Tweener.addTween(this.trayBox,
 | 
			
		||||
                             { anchor_y: this.keyboardBox.height,
 | 
			
		||||
                               time: KEYBOARD_ANIMATION_TIME,
 | 
			
		||||
                               transition: 'easeOutQuad'
 | 
			
		||||
                             });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.emit('keyboard-visible-changed', true);
 | 
			
		||||
    },
 | 
			
		||||
@@ -397,7 +452,8 @@ const LayoutManager = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._keyboardHeightNotifyId = this.keyboardBox.connect('notify::height', Lang.bind(this, function () {
 | 
			
		||||
            this.keyboardBox.anchor_y = this.keyboardBox.height;
 | 
			
		||||
            this.trayBox.anchor_y = this.keyboardBox.height;
 | 
			
		||||
            if (this.keyboardIndex == this.bottomIndex)
 | 
			
		||||
                this.trayBox.anchor_y = this.keyboardBox.height;
 | 
			
		||||
        }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -413,11 +469,14 @@ const LayoutManager = new Lang.Class({
 | 
			
		||||
                           onComplete: this._hideKeyboardComplete,
 | 
			
		||||
                           onCompleteScope: this
 | 
			
		||||
                         });
 | 
			
		||||
        Tweener.addTween(this.trayBox,
 | 
			
		||||
                         { anchor_y: 0,
 | 
			
		||||
                           time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad'
 | 
			
		||||
                         });
 | 
			
		||||
 | 
			
		||||
        if (this.keyboardIndex == this.bottomIndex) {
 | 
			
		||||
            Tweener.addTween(this.trayBox,
 | 
			
		||||
                             { anchor_y: 0,
 | 
			
		||||
                               time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
 | 
			
		||||
                               transition: 'easeOutQuad'
 | 
			
		||||
                             });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.emit('keyboard-visible-changed', false);
 | 
			
		||||
    },
 | 
			
		||||
@@ -481,7 +540,7 @@ const LayoutManager = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    findMonitorForActor: function(actor) {
 | 
			
		||||
        return this._chrome.findMonitorForActor(actor);
 | 
			
		||||
        return this.monitors[this._chrome.findIndexForActor(actor)];
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(LayoutManager.prototype);
 | 
			
		||||
@@ -830,6 +889,7 @@ const Chrome = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _relayout: function() {
 | 
			
		||||
        this._monitors = this._layoutManager.monitors;
 | 
			
		||||
        this._primaryIndex = this._layoutManager.primaryIndex;
 | 
			
		||||
        this._primaryMonitor = this._layoutManager.primaryMonitor;
 | 
			
		||||
 | 
			
		||||
        this._updateFullscreen();
 | 
			
		||||
@@ -845,32 +905,47 @@ const Chrome = new Lang.Class({
 | 
			
		||||
            let monitor = this._monitors[i];
 | 
			
		||||
            if (cx >= monitor.x && cx < monitor.x + monitor.width &&
 | 
			
		||||
                cy >= monitor.y && cy < monitor.y + monitor.height)
 | 
			
		||||
                return monitor;
 | 
			
		||||
                return i;
 | 
			
		||||
        }
 | 
			
		||||
        // If the center is not on a monitor, return the first overlapping monitor
 | 
			
		||||
        for (let i = 0; i < this._monitors.length; i++) {
 | 
			
		||||
            let monitor = this._monitors[i];
 | 
			
		||||
            if (x + w > monitor.x && x < monitor.x + monitor.width &&
 | 
			
		||||
                y + h > monitor.y && y < monitor.y + monitor.height)
 | 
			
		||||
                return monitor;
 | 
			
		||||
                return i;
 | 
			
		||||
        }
 | 
			
		||||
        // otherwise on no monitor
 | 
			
		||||
        return null;
 | 
			
		||||
        return -1;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findMonitorForWindow: function(window) {
 | 
			
		||||
        return this._findMonitorForRect(window.x, window.y, window.width, window.height);
 | 
			
		||||
    findIndexForWindow: function(window) {
 | 
			
		||||
        let i = this._findMonitorForRect(window.x, window.y, window.width, window.height);
 | 
			
		||||
        if (i >= 0)
 | 
			
		||||
            return i;
 | 
			
		||||
        return this._primaryIndex; // Not on any monitor, pretend its on the primary
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // This call guarantees that we return some monitor to simplify usage of it
 | 
			
		||||
    // In practice all tracked actors should be visible on some monitor anyway
 | 
			
		||||
    findMonitorForActor: function(actor) {
 | 
			
		||||
    findIndexForActor: function(actor) {
 | 
			
		||||
        let [x, y] = actor.get_transformed_position();
 | 
			
		||||
        let [w, h] = actor.get_transformed_size();
 | 
			
		||||
        let monitor = this._findMonitorForRect(x, y, w, h);
 | 
			
		||||
        if (monitor)
 | 
			
		||||
            return monitor;
 | 
			
		||||
        return this._primaryMonitor; // Not on any monitor, pretend its on the primary
 | 
			
		||||
        let i = this._findMonitorForRect(x, y, w, h);
 | 
			
		||||
        if (i >= 0)
 | 
			
		||||
            return i;
 | 
			
		||||
        return this._primaryIndex; // Not on any monitor, pretend its on the primary
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    findMonitorForWindow: function(window) {
 | 
			
		||||
        let i = this._findMonitorForRect(window.x, window.y, window.width, window.height);
 | 
			
		||||
        if (i >= 0)
 | 
			
		||||
            return this._monitors[i];
 | 
			
		||||
        else
 | 
			
		||||
            return null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    findMonitorForActor: function(actor) {
 | 
			
		||||
        return this._monitors[this.findIndexForActor(actor)];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _queueUpdateRegions: function() {
 | 
			
		||||
@@ -918,7 +993,7 @@ const Chrome = new Lang.Class({
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            if (layer == Meta.StackLayer.FULLSCREEN) {
 | 
			
		||||
                let monitor = this._findMonitorForWindow(window);
 | 
			
		||||
                let monitor = this.findMonitorForWindow(window);
 | 
			
		||||
                if (monitor)
 | 
			
		||||
                    monitor.inFullscreen = true;
 | 
			
		||||
            }
 | 
			
		||||
@@ -935,7 +1010,7 @@ const Chrome = new Lang.Class({
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Or whether it is monitor sized
 | 
			
		||||
                let monitor = this._findMonitorForWindow(window);
 | 
			
		||||
                let monitor = this.findMonitorForWindow(window);
 | 
			
		||||
                if (monitor &&
 | 
			
		||||
                    window.x <= monitor.x &&
 | 
			
		||||
                    window.x + window.width >= monitor.x + monitor.width &&
 | 
			
		||||
@@ -1086,5 +1161,69 @@ const Chrome = new Lang.Class({
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Signals.addSignalMethods(Chrome.prototype);
 | 
			
		||||
 | 
			
		||||
const PressureBarrier = new Lang.Class({
 | 
			
		||||
    Name: 'TrayPressure',
 | 
			
		||||
 | 
			
		||||
    _init: function(barrier, pressureThreshold, perpThreshold) {
 | 
			
		||||
        this._barrier = barrier;
 | 
			
		||||
        this._pressureThreshold = pressureThreshold;
 | 
			
		||||
        this._perpThreshold = perpThreshold;
 | 
			
		||||
        this._getVelocityAndPerp = this._makeGetVelocityAndPerp(barrier);
 | 
			
		||||
 | 
			
		||||
        this._reset(0);
 | 
			
		||||
 | 
			
		||||
        this._barrierHitId = this._barrier.connect('hit', Lang.bind(this, this._onBarrierHit));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        this._barrier.disconnect(this._barrierHitId);
 | 
			
		||||
        this._barrier = null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _reset: function(eventId) {
 | 
			
		||||
        this._currentEventId = eventId;
 | 
			
		||||
        this._currentPressure = 0;
 | 
			
		||||
        this._perpAccumulator = 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _makeGetVelocityAndPerp: function(barrier) {
 | 
			
		||||
        if (barrier.y1 === barrier.y2) {
 | 
			
		||||
            return function(event) {
 | 
			
		||||
                return [Math.abs(event.dy), event.dx];
 | 
			
		||||
            };
 | 
			
		||||
        } else {
 | 
			
		||||
            return function(event) {
 | 
			
		||||
                return [Math.abs(event.dx), event.dy];
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onBarrierHit: function(barrier, event) {
 | 
			
		||||
        // Event IDs are incremented every time the user stops
 | 
			
		||||
        // hitting the barrier. So, if the event ID switches,
 | 
			
		||||
        // reset the current state, and start over.
 | 
			
		||||
        if (this._currentEventId != event.event_id) {
 | 
			
		||||
            this._reset(event.event_id);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let [velocity, perp] = this._getVelocityAndPerp(event);
 | 
			
		||||
        this._perpAccumulator += perp;
 | 
			
		||||
 | 
			
		||||
        // If the user travels too far in the direction perpendicular
 | 
			
		||||
        // to the barrier, start over from scratch -- the user is simply
 | 
			
		||||
        // trying to skirt along the barrier.
 | 
			
		||||
        if (Math.abs(this._perpAccumulator) >= this._perpThreshold) {
 | 
			
		||||
            this._reset(0);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._currentPressure += velocity;
 | 
			
		||||
        if (this._currentPressure >= this._pressureThreshold) {
 | 
			
		||||
            this.emit('trigger');
 | 
			
		||||
            this._reset(0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(PressureBarrier.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -1129,7 +1129,7 @@ const LookingGlass = new Lang.Class({
 | 
			
		||||
        if (this._open)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (!Main.pushModal(this._entry))
 | 
			
		||||
        if (!Main.pushModal(this._entry, { keybindingMode: Main.KeybindingMode.LOOKING_GLASS }))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._notebook.selectIndex(0);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										138
									
								
								js/ui/main.js
									
									
									
									
									
								
							
							
						
						
									
										138
									
								
								js/ui/main.js
									
									
									
									
									
								
							@@ -20,6 +20,7 @@ const Keyboard = imports.ui.keyboard;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
const Overview = imports.ui.overview;
 | 
			
		||||
const Panel = imports.ui.panel;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const RunDialog = imports.ui.runDialog;
 | 
			
		||||
const Layout = imports.ui.layout;
 | 
			
		||||
const LookingGlass = imports.ui.lookingGlass;
 | 
			
		||||
@@ -39,6 +40,18 @@ const Util = imports.misc.util;
 | 
			
		||||
const OVERRIDES_SCHEMA = 'org.gnome.shell.overrides';
 | 
			
		||||
const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
 | 
			
		||||
 | 
			
		||||
const KeybindingMode = {
 | 
			
		||||
    NONE:          0,       // block all keybindings
 | 
			
		||||
    NORMAL:        1 << 0,  // window mode
 | 
			
		||||
    OVERVIEW:      1 << 1,
 | 
			
		||||
    LOCK_SCREEN:   1 << 2,
 | 
			
		||||
    UNLOCK_SCREEN: 1 << 3,
 | 
			
		||||
    LOGIN_SCREEN:  1 << 4,
 | 
			
		||||
    MESSAGE_TRAY:  1 << 5,
 | 
			
		||||
    SYSTEM_MODAL:  1 << 6,
 | 
			
		||||
    LOOKING_GLASS: 1 << 7
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
let componentManager = null;
 | 
			
		||||
let panel = null;
 | 
			
		||||
let overview = null;
 | 
			
		||||
@@ -55,6 +68,7 @@ let shellDBusService = null;
 | 
			
		||||
let shellMountOpDBusService = null;
 | 
			
		||||
let screenSaverDBus = null;
 | 
			
		||||
let modalCount = 0;
 | 
			
		||||
let keybindingMode = KeybindingMode.NORMAL;
 | 
			
		||||
let modalActorFocusStack = [];
 | 
			
		||||
let uiGroup = null;
 | 
			
		||||
let magnifier = null;
 | 
			
		||||
@@ -69,7 +83,17 @@ let _overridesSettings = null;
 | 
			
		||||
let background = null;
 | 
			
		||||
 | 
			
		||||
function _sessionUpdated() {
 | 
			
		||||
    Meta.keybindings_set_custom_handler('panel-run-dialog', sessionMode.hasRunDialog ? openRunDialog : null);
 | 
			
		||||
    wm.setCustomKeybindingHandler('panel-main-menu',
 | 
			
		||||
                                  KeybindingMode.NORMAL |
 | 
			
		||||
                                  KeybindingMode.OVERVIEW,
 | 
			
		||||
                                  sessionMode.hasOverview ? Lang.bind(overview, overview.toggle) : null);
 | 
			
		||||
    wm.allowKeybinding('overlay-key', KeybindingMode.NORMAL |
 | 
			
		||||
                                      KeybindingMode.OVERVIEW);
 | 
			
		||||
 | 
			
		||||
    wm.setCustomKeybindingHandler('panel-run-dialog',
 | 
			
		||||
                                  KeybindingMode.NORMAL |
 | 
			
		||||
                                  KeybindingMode.OVERVIEW,
 | 
			
		||||
                                  sessionMode.hasRunDialog ? openRunDialog : null);
 | 
			
		||||
    if (sessionMode.isGreeter)
 | 
			
		||||
        screenShield.showDialog();
 | 
			
		||||
}
 | 
			
		||||
@@ -155,9 +179,7 @@ function start() {
 | 
			
		||||
 | 
			
		||||
    global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
 | 
			
		||||
                                            false, -1, 1);
 | 
			
		||||
    Meta.keybindings_set_custom_handler('panel-main-menu', Lang.bind(overview, overview.toggle));
 | 
			
		||||
    global.display.connect('overlay-key', Lang.bind(overview, overview.toggle));
 | 
			
		||||
 | 
			
		||||
    sessionMode.connect('update', _sessionUpdated);
 | 
			
		||||
    _sessionUpdated();
 | 
			
		||||
 | 
			
		||||
@@ -167,8 +189,6 @@ function start() {
 | 
			
		||||
 | 
			
		||||
    _startDate = new Date();
 | 
			
		||||
 | 
			
		||||
    global.stage.connect('captured-event', _globalKeyPressHandler);
 | 
			
		||||
 | 
			
		||||
    log('GNOME Shell started at ' + _startDate);
 | 
			
		||||
 | 
			
		||||
    let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
 | 
			
		||||
@@ -465,80 +485,6 @@ function getWindowActorsForWorkspace(workspaceIndex) {
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This function encapsulates hacks to make certain global keybindings
 | 
			
		||||
// work even when we are in one of our modes where global keybindings
 | 
			
		||||
// are disabled with a global grab. (When there is a global grab, then
 | 
			
		||||
// all key events will be delivered to the stage, so ::captured-event
 | 
			
		||||
// on the stage can be used for global keybindings.)
 | 
			
		||||
function _globalKeyPressHandler(actor, event) {
 | 
			
		||||
    if (modalCount == 0)
 | 
			
		||||
        return false;
 | 
			
		||||
    if (event.type() != Clutter.EventType.KEY_PRESS)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    if (!sessionMode.allowKeybindingsWhenModal) {
 | 
			
		||||
        if (modalCount > (overview.visible ? 1 : 0))
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let symbol = event.get_key_symbol();
 | 
			
		||||
    let keyCode = event.get_key_code();
 | 
			
		||||
    let ignoredModifiers = global.display.get_ignored_modifier_mask();
 | 
			
		||||
    let modifierState = event.get_state() & ~ignoredModifiers;
 | 
			
		||||
 | 
			
		||||
    // This relies on the fact that Clutter.ModifierType is the same as Gdk.ModifierType
 | 
			
		||||
    let action = global.display.get_keybinding_action(keyCode, modifierState);
 | 
			
		||||
 | 
			
		||||
    if (action == Meta.KeyBindingAction.SWITCH_PANELS) {
 | 
			
		||||
        ctrlAltTabManager.popup(modifierState & Clutter.ModifierType.SHIFT_MASK,
 | 
			
		||||
                                modifierState);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    switch (action) {
 | 
			
		||||
        // left/right would effectively act as synonyms for up/down if we enabled them;
 | 
			
		||||
        // but that could be considered confusing; we also disable them in the main view.
 | 
			
		||||
        //
 | 
			
		||||
        // case Meta.KeyBindingAction.WORKSPACE_LEFT:
 | 
			
		||||
        //  if (!sessionMode.hasWorkspaces)
 | 
			
		||||
        //      return false;
 | 
			
		||||
        //
 | 
			
		||||
        //     wm.actionMoveWorkspaceLeft();
 | 
			
		||||
        //     return true;
 | 
			
		||||
        // case Meta.KeyBindingAction.WORKSPACE_RIGHT:
 | 
			
		||||
        //  if (!sessionMode.hasWorkspaces)
 | 
			
		||||
        //      return false;
 | 
			
		||||
        //
 | 
			
		||||
        //     wm.actionMoveWorkspaceRight();
 | 
			
		||||
        //     return true;
 | 
			
		||||
        case Meta.KeyBindingAction.WORKSPACE_UP:
 | 
			
		||||
            if (!sessionMode.hasWorkspaces)
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            wm.actionMoveWorkspace(Meta.MotionDirection.UP);
 | 
			
		||||
            return true;
 | 
			
		||||
        case Meta.KeyBindingAction.WORKSPACE_DOWN:
 | 
			
		||||
            if (!sessionMode.hasWorkspaces)
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            wm.actionMoveWorkspace(Meta.MotionDirection.DOWN);
 | 
			
		||||
            return true;
 | 
			
		||||
        case Meta.KeyBindingAction.PANEL_RUN_DIALOG:
 | 
			
		||||
        case Meta.KeyBindingAction.COMMAND_2:
 | 
			
		||||
            if (!sessionMode.hasRunDialog)
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            openRunDialog();
 | 
			
		||||
            return true;
 | 
			
		||||
        case Meta.KeyBindingAction.PANEL_MAIN_MENU:
 | 
			
		||||
        case Meta.KeyBindingAction.OVERLAY_KEY:
 | 
			
		||||
            overview.hide();
 | 
			
		||||
            return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _findModal(actor) {
 | 
			
		||||
    for (let i = 0; i < modalActorFocusStack.length; i++) {
 | 
			
		||||
        if (modalActorFocusStack[i].actor == actor)
 | 
			
		||||
@@ -554,7 +500,7 @@ function isInModalStack(actor) {
 | 
			
		||||
/**
 | 
			
		||||
 * pushModal:
 | 
			
		||||
 * @actor: #ClutterActor which will be given keyboard focus
 | 
			
		||||
 * @timestamp: optional timestamp
 | 
			
		||||
 * @params: optional parameters
 | 
			
		||||
 *
 | 
			
		||||
 * Ensure we are in a mode where all keyboard and mouse input goes to
 | 
			
		||||
 * the stage, and focus @actor. Multiple calls to this function act in
 | 
			
		||||
@@ -565,21 +511,27 @@ function isInModalStack(actor) {
 | 
			
		||||
 * modal stack returns to this actor, reset the focus to the actor
 | 
			
		||||
 * which was focused at the time pushModal() was invoked.
 | 
			
		||||
 *
 | 
			
		||||
 * @timestamp is optionally used to associate the call with a specific user
 | 
			
		||||
 * initiated event.  If not provided then the value of
 | 
			
		||||
 * global.get_current_time() is assumed.
 | 
			
		||||
 * @params may be used to provide the following parameters:
 | 
			
		||||
 *  - timestamp: used to associate the call with a specific user initiated
 | 
			
		||||
 *               event.  If not provided then the value of
 | 
			
		||||
 *               global.get_current_time() is assumed.
 | 
			
		||||
 *
 | 
			
		||||
 * @options: optional Meta.ModalOptions flags to indicate that the
 | 
			
		||||
 *           pointer is alrady grabbed
 | 
			
		||||
 *  - options: Meta.ModalOptions flags to indicate that the pointer is
 | 
			
		||||
 *             already grabbed
 | 
			
		||||
 *
 | 
			
		||||
 *  - keybindingMode: used to set the current Main.KeybindingMode to filter
 | 
			
		||||
 *                    global keybindings; the default of NONE will filter
 | 
			
		||||
 *                    out all keybindings
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: true iff we successfully acquired a grab or already had one
 | 
			
		||||
 */
 | 
			
		||||
function pushModal(actor, timestamp, options) {
 | 
			
		||||
    if (timestamp == undefined)
 | 
			
		||||
        timestamp = global.get_current_time();
 | 
			
		||||
function pushModal(actor, params) {
 | 
			
		||||
    params = Params.parse(params, { timestamp: global.get_current_time(),
 | 
			
		||||
                                    options: 0,
 | 
			
		||||
                                    keybindingMode: KeybindingMode.NONE });
 | 
			
		||||
 | 
			
		||||
    if (modalCount == 0) {
 | 
			
		||||
        if (!global.begin_modal(timestamp, options ? options : 0)) {
 | 
			
		||||
        if (!global.begin_modal(params.timestamp, params.options)) {
 | 
			
		||||
            log('pushModal: invocation of begin_modal failed');
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
@@ -606,8 +558,10 @@ function pushModal(actor, timestamp, options) {
 | 
			
		||||
    modalActorFocusStack.push({ actor: actor,
 | 
			
		||||
                                focus: curFocus,
 | 
			
		||||
                                destroyId: actorDestroyId,
 | 
			
		||||
                                focusDestroyId: curFocusDestroyId });
 | 
			
		||||
                                focusDestroyId: curFocusDestroyId,
 | 
			
		||||
                                keybindingMode: keybindingMode });
 | 
			
		||||
 | 
			
		||||
    keybindingMode = params.keybindingMode;
 | 
			
		||||
    global.stage.set_key_focus(actor);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
@@ -634,6 +588,7 @@ function popModal(actor, timestamp) {
 | 
			
		||||
        global.stage.set_key_focus(null);
 | 
			
		||||
        global.end_modal(timestamp);
 | 
			
		||||
        global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
 | 
			
		||||
        keybindingMode = KeybindingMode.NORMAL;
 | 
			
		||||
 | 
			
		||||
        throw new Error('incorrect pop');
 | 
			
		||||
    }
 | 
			
		||||
@@ -646,6 +601,7 @@ function popModal(actor, timestamp) {
 | 
			
		||||
    if (focusIndex == modalActorFocusStack.length - 1) {
 | 
			
		||||
        if (record.focus)
 | 
			
		||||
            record.focus.disconnect(record.focusDestroyId);
 | 
			
		||||
        keybindingMode = record.keybindingMode;
 | 
			
		||||
        global.stage.set_key_focus(record.focus);
 | 
			
		||||
    } else {
 | 
			
		||||
        let t = modalActorFocusStack[modalActorFocusStack.length - 1];
 | 
			
		||||
@@ -655,6 +611,7 @@ function popModal(actor, timestamp) {
 | 
			
		||||
        for (let i = modalActorFocusStack.length - 1; i > focusIndex; i--) {
 | 
			
		||||
            modalActorFocusStack[i].focus = modalActorFocusStack[i - 1].focus;
 | 
			
		||||
            modalActorFocusStack[i].focusDestroyId = modalActorFocusStack[i - 1].focusDestroyId;
 | 
			
		||||
            modalActorFocusStack[i].keybindingMode = modalActorFocusStack[i - 1].keybindingMode;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    modalActorFocusStack.splice(focusIndex, 1);
 | 
			
		||||
@@ -665,6 +622,7 @@ function popModal(actor, timestamp) {
 | 
			
		||||
    global.end_modal(timestamp);
 | 
			
		||||
    global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
 | 
			
		||||
    Meta.enable_unredirect_for_screen(global.screen);
 | 
			
		||||
    keybindingMode = KeybindingMode.NORMAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function createLookingGlass() {
 | 
			
		||||
 
 | 
			
		||||
@@ -40,11 +40,6 @@ const LONGER_HIDE_TIMEOUT = 0.6;
 | 
			
		||||
// range from the point where it left the tray.
 | 
			
		||||
const MOUSE_LEFT_ACTOR_THRESHOLD = 20;
 | 
			
		||||
 | 
			
		||||
// Time the user needs to leave the mouse on the bottom pixel row to open the tray
 | 
			
		||||
const TRAY_DWELL_TIME = 1000; // ms
 | 
			
		||||
// Time resolution when tracking the mouse to catch the open tray dwell
 | 
			
		||||
const TRAY_DWELL_CHECK_INTERVAL = 100; // ms
 | 
			
		||||
 | 
			
		||||
const IDLE_TIME = 1000;
 | 
			
		||||
 | 
			
		||||
const State = {
 | 
			
		||||
@@ -314,6 +309,7 @@ const Notification = new Lang.Class({
 | 
			
		||||
        this.resident = false;
 | 
			
		||||
        // 'transient' is a reserved keyword in JS, so we have to use an alternate variable name
 | 
			
		||||
        this.isTransient = false;
 | 
			
		||||
        this.forFeedback = false;
 | 
			
		||||
        this.expanded = false;
 | 
			
		||||
        this.focused = false;
 | 
			
		||||
        this.acknowledged = false;
 | 
			
		||||
@@ -713,6 +709,10 @@ const Notification = new Lang.Class({
 | 
			
		||||
        this.isTransient = isTransient;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setForFeedback: function(forFeedback) {
 | 
			
		||||
        this.forFeedback = forFeedback;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setUseActionIcons: function(useIcons) {
 | 
			
		||||
        this._useActionIcons = useIcons;
 | 
			
		||||
    },
 | 
			
		||||
@@ -1389,6 +1389,8 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
                                                   y_expand: true,
 | 
			
		||||
                                                   x_expand: true,
 | 
			
		||||
                                                   layout_manager: new Clutter.BinLayout() });
 | 
			
		||||
        this._notificationWidget.connect('key-release-event', Lang.bind(this, this._onNotificationKeyRelease));
 | 
			
		||||
 | 
			
		||||
        this.actor.add_actor(this._notificationWidget);
 | 
			
		||||
 | 
			
		||||
        this._notificationBin = new St.Bin({ y_expand: true });
 | 
			
		||||
@@ -1434,11 +1436,10 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
        this._clickedSummaryItem = null;
 | 
			
		||||
        this._clickedSummaryItemMouseButton = -1;
 | 
			
		||||
        this._clickedSummaryItemAllocationChangedId = 0;
 | 
			
		||||
        this._pointerBarrier = 0;
 | 
			
		||||
 | 
			
		||||
        this._closeButton = makeCloseButton();
 | 
			
		||||
        this._closeButton.hide();
 | 
			
		||||
        this._closeButton.connect('clicked', Lang.bind(this, this._onCloseClicked));
 | 
			
		||||
        this._closeButton.connect('clicked', Lang.bind(this, this._closeNotification));
 | 
			
		||||
        this._notificationWidget.add_actor(this._closeButton);
 | 
			
		||||
 | 
			
		||||
        this._idleMonitorBecameActiveId = 0;
 | 
			
		||||
@@ -1446,7 +1447,8 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this.idleMonitor = new GnomeDesktop.IdleMonitor();
 | 
			
		||||
 | 
			
		||||
        this._grabHelper = new GrabHelper.GrabHelper(this.actor);
 | 
			
		||||
        this._grabHelper = new GrabHelper.GrabHelper(this.actor,
 | 
			
		||||
                                                     { keybindingMode: Main.KeybindingMode.MESSAGE_TRAY });
 | 
			
		||||
        this._grabHelper.addActor(this._summaryBoxPointer.actor);
 | 
			
		||||
        this._grabHelper.addActor(this.actor);
 | 
			
		||||
        if (Main.panel.statusArea.activities)
 | 
			
		||||
@@ -1463,6 +1465,7 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
        this._pointerInTray = false;
 | 
			
		||||
        this._pointerInKeyboard = false;
 | 
			
		||||
        this._keyboardVisible = false;
 | 
			
		||||
        this._keyboardUnderMessageTray = false;
 | 
			
		||||
        this._summaryState = State.HIDDEN;
 | 
			
		||||
        this._pointerInSummary = false;
 | 
			
		||||
        this._notificationClosed = false;
 | 
			
		||||
@@ -1510,86 +1513,73 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
 | 
			
		||||
 | 
			
		||||
        global.display.add_keybinding('toggle-message-tray',
 | 
			
		||||
                                      new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
 | 
			
		||||
                                      Meta.KeyBindingFlags.NONE,
 | 
			
		||||
                                      Lang.bind(this, this.toggleAndNavigate));
 | 
			
		||||
        Main.wm.addKeybinding('toggle-message-tray',
 | 
			
		||||
                              new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
 | 
			
		||||
                              Meta.KeyBindingFlags.NONE,
 | 
			
		||||
                              Main.KeybindingMode.NORMAL |
 | 
			
		||||
                              Main.KeybindingMode.MESSAGE_TRAY |
 | 
			
		||||
                              Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                              Lang.bind(this, this.toggleAndNavigate));
 | 
			
		||||
        Main.wm.addKeybinding('focus-active-notification',
 | 
			
		||||
                              new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
 | 
			
		||||
                              Meta.KeyBindingFlags.NONE,
 | 
			
		||||
                              Main.KeybindingMode.NORMAL |
 | 
			
		||||
                              Main.KeybindingMode.MESSAGE_TRAY |
 | 
			
		||||
                              Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                              Lang.bind(this, this._expandActiveNotification));
 | 
			
		||||
 | 
			
		||||
        this._summaryItems = [];
 | 
			
		||||
        this._chatSummaryItemsCount = 0;
 | 
			
		||||
 | 
			
		||||
        let pointerWatcher = PointerWatcher.getPointerWatcher();
 | 
			
		||||
        pointerWatcher.addWatch(TRAY_DWELL_CHECK_INTERVAL, Lang.bind(this, this._checkTrayDwell));
 | 
			
		||||
        this._trayDwellTimeoutId = 0;
 | 
			
		||||
        this._trayDwelling = false;
 | 
			
		||||
        this._trayDwellUserTime = 0;
 | 
			
		||||
 | 
			
		||||
        this._sessionUpdated();
 | 
			
		||||
        this._updateNoMessagesLabel();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateNoMessagesLabel: function() {
 | 
			
		||||
        if (this._summaryItems.length == 0 && !this._noMessages) {
 | 
			
		||||
            this._noMessages = new St.Label({ text: _("No Messages"),
 | 
			
		||||
                                              style_class: 'no-messages-label',
 | 
			
		||||
                                              x_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
                                              x_expand: true,
 | 
			
		||||
                                              y_align: Clutter.ActorAlign.CENTER,
 | 
			
		||||
                                              y_expand: true });
 | 
			
		||||
            this.actor.add_actor(this._noMessages);
 | 
			
		||||
        } else if (this._summaryItems.length > 0 && this._noMessages) {
 | 
			
		||||
            this._noMessages.destroy();
 | 
			
		||||
            this._noMessages = null;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _sessionUpdated: function() {
 | 
			
		||||
        if (Main.sessionMode.isLocked || Main.sessionMode.isGreeter)
 | 
			
		||||
            Main.ctrlAltTabManager.removeGroup(this._summary);
 | 
			
		||||
        else
 | 
			
		||||
            Main.ctrlAltTabManager.addGroup(this._summary, _("Message Tray"), 'start-here-symbolic',
 | 
			
		||||
            Main.ctrlAltTabManager.addGroup(this._summary, _("Message Tray"), 'user-available-symbolic',
 | 
			
		||||
                                            { focusCallback: Lang.bind(this, this.toggleAndNavigate),
 | 
			
		||||
                                              sortGroup: CtrlAltTab.SortGroup.BOTTOM });
 | 
			
		||||
        this._updateState();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _checkTrayDwell: function(x, y) {
 | 
			
		||||
        let monitor = Main.layoutManager.bottomMonitor;
 | 
			
		||||
        let shouldDwell = (x >= monitor.x && x <= monitor.x + monitor.width &&
 | 
			
		||||
                           y == monitor.y + monitor.height - 1);
 | 
			
		||||
        if (shouldDwell) {
 | 
			
		||||
            // We only set up dwell timeout when the user is not hovering over the tray
 | 
			
		||||
            // (!this.actor.hover). This avoids bringing up the message tray after the
 | 
			
		||||
            // user clicks on a notification with the pointer on the bottom pixel
 | 
			
		||||
            // of the monitor. The _trayDwelling variable is used so that we only try to
 | 
			
		||||
            // fire off one tray dwell - if it fails (because, say, the user has the mouse down),
 | 
			
		||||
            // we don't try again until the user moves the mouse up and down again.
 | 
			
		||||
            if (!this._trayDwelling && !this.actor.hover && this._trayDwellTimeoutId == 0) {
 | 
			
		||||
                // Save the interaction timestamp so we can detect user input
 | 
			
		||||
                let focusWindow = global.display.focus_window;
 | 
			
		||||
                this._trayDwellUserTime = focusWindow ? focusWindow.user_time : 0;
 | 
			
		||||
 | 
			
		||||
                this._trayDwellTimeoutId = Mainloop.timeout_add(TRAY_DWELL_TIME,
 | 
			
		||||
                                                                Lang.bind(this, this._trayDwellTimeout));
 | 
			
		||||
            }
 | 
			
		||||
            this._trayDwelling = true;
 | 
			
		||||
        } else {
 | 
			
		||||
            this._cancelTrayDwell();
 | 
			
		||||
            this._trayDwelling = false;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _cancelTrayDwell: function() {
 | 
			
		||||
        if (this._trayDwellTimeoutId != 0) {
 | 
			
		||||
            Mainloop.source_remove(this._trayDwellTimeoutId);
 | 
			
		||||
            this._trayDwellTimeoutId = 0;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _trayDwellTimeout: function() {
 | 
			
		||||
        if (Main.modalCount > 0)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        // If the user interacted with the focus window since we started the tray
 | 
			
		||||
        // dwell (by clicking or typing), don't activate the message tray
 | 
			
		||||
        let focusWindow = global.display.focus_window;
 | 
			
		||||
        let currentUserTime = focusWindow ? focusWindow.user_time : 0;
 | 
			
		||||
        if (currentUserTime != this._trayDwellUserTime)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        this._trayDwellTimeoutId = 0;
 | 
			
		||||
 | 
			
		||||
    openTray: function() {
 | 
			
		||||
        this._traySummoned = true;
 | 
			
		||||
        this._updateState();
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onCloseClicked: function() {
 | 
			
		||||
    _onNotificationKeyRelease: function(actor, event) {
 | 
			
		||||
        let ignoredModifiers = global.display.get_ignored_modifier_mask();
 | 
			
		||||
        let modifierState = event.get_state() & ~ignoredModifiers;
 | 
			
		||||
 | 
			
		||||
        if (event.get_key_symbol() == Clutter.KEY_Escape && modifierState == 0) {
 | 
			
		||||
            this._closeNotification();
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _closeNotification: function() {
 | 
			
		||||
        if (this._notificationState == State.SHOWN) {
 | 
			
		||||
            this._closeButton.hide();
 | 
			
		||||
            this._notificationClosed = true;
 | 
			
		||||
@@ -1657,6 +1647,8 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
        Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { this._updateState(); return false; }));
 | 
			
		||||
 | 
			
		||||
        this.emit('summary-item-added', summaryItem);
 | 
			
		||||
 | 
			
		||||
        this._updateNoMessagesLabel();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getSummaryItems: function() {
 | 
			
		||||
@@ -1689,6 +1681,8 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        summaryItemToRemove.actor.destroy();
 | 
			
		||||
 | 
			
		||||
        this._updateNoMessagesLabel();
 | 
			
		||||
 | 
			
		||||
        if (needUpdate)
 | 
			
		||||
            this._updateState();
 | 
			
		||||
    },
 | 
			
		||||
@@ -1798,9 +1792,6 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _onTrayHoverChanged: function() {
 | 
			
		||||
        if (this.actor.hover) {
 | 
			
		||||
            // No dwell inside notifications at the bottom of the screen
 | 
			
		||||
            this._cancelTrayDwell();
 | 
			
		||||
 | 
			
		||||
            // Don't do anything if the one pixel area at the bottom is hovered over while the tray is hidden.
 | 
			
		||||
            if (this._trayState == State.HIDDEN && this._notificationState == State.HIDDEN)
 | 
			
		||||
                return;
 | 
			
		||||
@@ -1874,12 +1865,15 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyboardVisibleChanged: function(layoutManager, keyboardVisible) {
 | 
			
		||||
        if (this._keyboardVisible == keyboardVisible)
 | 
			
		||||
        let keyboardUnderMessageTray = layoutManager.keyboardIndex == layoutManager.bottomIndex;
 | 
			
		||||
        if (this._keyboardVisible == keyboardVisible &&
 | 
			
		||||
            this._keyboardUnderMesssageTray == keyboardUnderMessageTray)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._keyboardVisible = keyboardVisible;
 | 
			
		||||
        this._keyboardUnderMessageTray = keyboardUnderMessageTray;
 | 
			
		||||
 | 
			
		||||
        if (keyboardVisible)
 | 
			
		||||
        if (keyboardVisible && keyboardUnderMessageTray)
 | 
			
		||||
            this.actor.add_style_pseudo_class('keyboard');
 | 
			
		||||
        else
 | 
			
		||||
            this.actor.remove_style_pseudo_class('keyboard');
 | 
			
		||||
@@ -1949,8 +1943,9 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
        // Notifications
 | 
			
		||||
        let notificationQueue = this._notificationQueue;
 | 
			
		||||
        let notificationUrgent = notificationQueue.length > 0 && notificationQueue[0].urgency == Urgency.CRITICAL;
 | 
			
		||||
        let notificationForFeedback = notificationQueue.length > 0 && notificationQueue[0].forFeedback;
 | 
			
		||||
        let notificationsLimited = this._busy || this._inFullscreen;
 | 
			
		||||
        let notificationsPending = notificationQueue.length > 0 && (!notificationsLimited || notificationUrgent) && Main.sessionMode.hasNotifications;
 | 
			
		||||
        let notificationsPending = notificationQueue.length > 0 && (!notificationsLimited || notificationUrgent || notificationForFeedback) && Main.sessionMode.hasNotifications;
 | 
			
		||||
        let nextNotification = notificationQueue.length > 0 ? notificationQueue[0] : null;
 | 
			
		||||
        let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved;
 | 
			
		||||
        let notificationExpanded = this._notification && this._notification.expanded;
 | 
			
		||||
@@ -1982,8 +1977,7 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
        let summaryPinned = this._pointerInTray || summarySummoned || this._locked;
 | 
			
		||||
        let summaryHovered = this._pointerInTray || this._pointerInSummary;
 | 
			
		||||
 | 
			
		||||
        let notificationsVisible = (this._notificationState == State.SHOWING ||
 | 
			
		||||
                                    this._notificationState == State.SHOWN);
 | 
			
		||||
        let notificationsVisible = this._notificationState != State.HIDDEN;
 | 
			
		||||
        let notificationsDone = !notificationsVisible && !notificationsPending;
 | 
			
		||||
 | 
			
		||||
        let summaryOptionalInOverview = this._overviewVisible && !this._locked && !summaryHovered;
 | 
			
		||||
@@ -2036,12 +2030,12 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
                                     this._desktopCloneState == State.SHOWN);
 | 
			
		||||
        let desktopCloneShouldBeVisible = (trayShouldBeVisible &&
 | 
			
		||||
                                           !this._overviewVisible &&
 | 
			
		||||
                                           !this._keyboardVisible);
 | 
			
		||||
                                           (!this._keyboardVisible || !this._keyboardUnderMessageTray));
 | 
			
		||||
 | 
			
		||||
        if (!desktopCloneIsVisible && desktopCloneShouldBeVisible) {
 | 
			
		||||
            this._showDesktopClone();
 | 
			
		||||
        } else if (desktopCloneIsVisible && !desktopCloneShouldBeVisible) {
 | 
			
		||||
            this._hideDesktopClone (this._keyboardVisible);
 | 
			
		||||
            this._hideDesktopClone (this._keyboardVisible && this._keyboardUnderMessageTray);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -2054,6 +2048,8 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
        params.onCompleteScope = this;
 | 
			
		||||
        params.onCompleteParams = [statevar, value, onComplete, onCompleteScope, onCompleteParams];
 | 
			
		||||
 | 
			
		||||
        // Remove other tweens that could mess with the state machine
 | 
			
		||||
        Tweener.removeTweens(actor);
 | 
			
		||||
        Tweener.addTween(actor, params);
 | 
			
		||||
 | 
			
		||||
        let valuing = (value == State.SHOWN) ? State.SHOWING : State.HIDING;
 | 
			
		||||
@@ -2286,6 +2282,18 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hideNotification: function() {
 | 
			
		||||
        // HACK!
 | 
			
		||||
        // There seems to be a reentrancy issue in calling .ungrab() here,
 | 
			
		||||
        // which causes _updateState to be called before _notificationState
 | 
			
		||||
        // becomes HIDING. That hides the notification again, nullifying the
 | 
			
		||||
        // object but not setting _notificationState (and that's the weird part)
 | 
			
		||||
        // As then _notificationState is stuck into SHOWN but _notification
 | 
			
		||||
        // is null, every new _updateState fails and the message tray is
 | 
			
		||||
        // lost forever.
 | 
			
		||||
        //
 | 
			
		||||
        // See more at https://bugzilla.gnome.org/show_bug.cgi?id=683986
 | 
			
		||||
        this._notificationState = State.HIDING;
 | 
			
		||||
 | 
			
		||||
        this._grabHelper.ungrab({ actor: this._notification.actor });
 | 
			
		||||
 | 
			
		||||
        if (this._idleMonitorBecameActiveId) {
 | 
			
		||||
@@ -2299,6 +2307,7 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._notificationRemoved) {
 | 
			
		||||
            Tweener.removeTweens(this._notificationWidget);
 | 
			
		||||
            this._notificationWidget.y = this.actor.height;
 | 
			
		||||
            this._notificationWidget.opacity = 0;
 | 
			
		||||
            this._notificationState = State.HIDDEN;
 | 
			
		||||
@@ -2332,6 +2341,13 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
            notification.destroy(NotificationDestroyedReason.EXPIRED);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _expandActiveNotification: function() {
 | 
			
		||||
        if (!this._notification)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._expandNotification(false);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _expandNotification: function(autoExpanding) {
 | 
			
		||||
        // Don't grab focus in notifications that are auto-expanded.
 | 
			
		||||
        if (!autoExpanding)
 | 
			
		||||
@@ -2355,8 +2371,11 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
        if (this._notificationWidget.y < expandedY) {
 | 
			
		||||
            this._notificationWidget.y = expandedY;
 | 
			
		||||
        } else if (this._notification.y != expandedY) {
 | 
			
		||||
            // Tween also opacity here, to override a possible tween that's
 | 
			
		||||
            // currently hiding the notification.
 | 
			
		||||
            this._tween(this._notificationWidget, '_notificationState', State.SHOWN,
 | 
			
		||||
                        { y: expandedY,
 | 
			
		||||
                          opacity: 255,
 | 
			
		||||
                          time: ANIMATION_TIME,
 | 
			
		||||
                          transition: 'easeOutQuad'
 | 
			
		||||
                        });
 | 
			
		||||
@@ -2415,6 +2434,7 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
            this._summaryBoxPointerItem.prepareNotificationStackForShowing();
 | 
			
		||||
        } else if (this._clickedSummaryItemMouseButton == 3) {
 | 
			
		||||
            this._summaryBoxPointer.bin.child = this._clickedSummaryItem.rightClickMenu;
 | 
			
		||||
            this._summaryBoxPointerCloseClickedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._grabHelper.grab({ actor: this._summaryBoxPointer.bin.child,
 | 
			
		||||
@@ -2521,8 +2541,10 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
        this._summaryBoxPointer.bin.child = null;
 | 
			
		||||
        this._summaryBoxPointerItem.disconnect(this._summaryBoxPointerContentUpdatedId);
 | 
			
		||||
        this._summaryBoxPointerContentUpdatedId = 0;
 | 
			
		||||
        this._summaryBoxPointerItem.closeButton.disconnect(this._summaryBoxPointerCloseClickedId);
 | 
			
		||||
        this._summaryBoxPointerCloseClickedId = 0;
 | 
			
		||||
        if (this._summaryBoxPointerCloseClickedId != 0) {
 | 
			
		||||
            this._summaryBoxPointerItem.closeButton.disconnect(this._summaryBoxPointerCloseClickedId);
 | 
			
		||||
            this._summaryBoxPointerCloseClickedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        this._summaryBoxPointerItem.source.disconnect(this._sourceDoneDisplayingId);
 | 
			
		||||
        this._summaryBoxPointerDoneDisplayingId = 0;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -37,10 +37,12 @@ const ModalDialog = new Lang.Class({
 | 
			
		||||
        params = Params.parse(params, { shellReactive: false,
 | 
			
		||||
                                        styleClass: null,
 | 
			
		||||
                                        parentActor: Main.uiGroup,
 | 
			
		||||
                                        keybindingMode: Main.KeybindingMode.SYSTEM_MODAL,
 | 
			
		||||
                                        shouldFadeIn: true });
 | 
			
		||||
 | 
			
		||||
        this.state = State.CLOSED;
 | 
			
		||||
        this._hasModal = false;
 | 
			
		||||
        this._keybindingMode = params.keybindingMode;
 | 
			
		||||
        this._shellReactive = params.shellReactive;
 | 
			
		||||
        this._shouldFadeIn = params.shouldFadeIn;
 | 
			
		||||
 | 
			
		||||
@@ -56,7 +58,7 @@ const ModalDialog = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._group.connect('destroy', Lang.bind(this, this._onGroupDestroy));
 | 
			
		||||
 | 
			
		||||
        this._actionKeys = {};
 | 
			
		||||
        this._buttonKeys = {};
 | 
			
		||||
        this._group.connect('key-release-event', Lang.bind(this, this._onKeyReleaseEvent));
 | 
			
		||||
 | 
			
		||||
        this._backgroundBin = new St.Bin();
 | 
			
		||||
@@ -93,10 +95,10 @@ const ModalDialog = new Lang.Class({
 | 
			
		||||
                                x_align: St.Align.MIDDLE,
 | 
			
		||||
                                y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this._buttonLayout = new St.BoxLayout({ style_class: 'modal-dialog-button-box',
 | 
			
		||||
        this.buttonLayout = new St.BoxLayout({ style_class: 'modal-dialog-button-box',
 | 
			
		||||
                                                visible:     false,
 | 
			
		||||
                                                vertical:    false });
 | 
			
		||||
        this.dialogLayout.add(this._buttonLayout,
 | 
			
		||||
        this.dialogLayout.add(this.buttonLayout,
 | 
			
		||||
                              { expand:  true,
 | 
			
		||||
                                x_align: St.Align.MIDDLE,
 | 
			
		||||
                                y_align: St.Align.END });
 | 
			
		||||
@@ -111,35 +113,17 @@ const ModalDialog = new Lang.Class({
 | 
			
		||||
        this._group.destroy();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setActionKey: function(key, action) {
 | 
			
		||||
        this._actionKeys[key] = action;
 | 
			
		||||
    clearButtons: function() {
 | 
			
		||||
        this.buttonLayout.destroy_all_children();
 | 
			
		||||
        this._buttonKeys = {};
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setButtons: function(buttons) {
 | 
			
		||||
        this._buttonLayout.destroy_all_children();
 | 
			
		||||
        this._actionKeys = {};
 | 
			
		||||
 | 
			
		||||
        this._buttonLayout.visible = (buttons.length > 0);
 | 
			
		||||
        this.clearButtons();
 | 
			
		||||
        this.buttonLayout.visible = (buttons.length > 0);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < buttons.length; i++) {
 | 
			
		||||
            let buttonInfo = buttons[i];
 | 
			
		||||
            let label = buttonInfo['label'];
 | 
			
		||||
            let action = buttonInfo['action'];
 | 
			
		||||
            let key = buttonInfo['key'];
 | 
			
		||||
            let isDefault = buttonInfo['default'];
 | 
			
		||||
 | 
			
		||||
            if (isDefault && !key) {
 | 
			
		||||
                this._actionKeys[Clutter.KEY_KP_Enter] = action;
 | 
			
		||||
                this._actionKeys[Clutter.KEY_ISO_Enter] = action;
 | 
			
		||||
                key = Clutter.KEY_Return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            buttonInfo.button = new St.Button({ style_class: 'modal-dialog-button',
 | 
			
		||||
                                                reactive:    true,
 | 
			
		||||
                                                can_focus:   true,
 | 
			
		||||
                                                label:       label });
 | 
			
		||||
            if (isDefault)
 | 
			
		||||
                buttonInfo.button.add_style_pseudo_class('default');
 | 
			
		||||
 | 
			
		||||
            let x_alignment;
 | 
			
		||||
            if (buttons.length == 1)
 | 
			
		||||
@@ -151,29 +135,62 @@ const ModalDialog = new Lang.Class({
 | 
			
		||||
            else
 | 
			
		||||
                x_alignment = St.Align.MIDDLE;
 | 
			
		||||
 | 
			
		||||
            if (!this._initialKeyFocusDestroyId)
 | 
			
		||||
                this._initialKeyFocus = buttonInfo.button;
 | 
			
		||||
            this._buttonLayout.add(buttonInfo.button,
 | 
			
		||||
                                   { expand: true,
 | 
			
		||||
                                     x_fill: false,
 | 
			
		||||
                                     y_fill: false,
 | 
			
		||||
                                     x_align: x_alignment,
 | 
			
		||||
                                     y_align: St.Align.MIDDLE });
 | 
			
		||||
 | 
			
		||||
            buttonInfo.button.connect('clicked', action);
 | 
			
		||||
 | 
			
		||||
            if (key)
 | 
			
		||||
                this._actionKeys[key] = action;
 | 
			
		||||
            this.addButton(buttonInfo, { expand: true,
 | 
			
		||||
                                         x_fill: false,
 | 
			
		||||
                                         y_fill: false,
 | 
			
		||||
                                         x_align: x_alignment,
 | 
			
		||||
                                         y_align: St.Align.MIDDLE });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
        this.emit('buttons-set');
 | 
			
		||||
    addButton: function(buttonInfo, layoutInfo) {
 | 
			
		||||
        let label = buttonInfo['label'];
 | 
			
		||||
        let action = buttonInfo['action'];
 | 
			
		||||
        let key = buttonInfo['key'];
 | 
			
		||||
        let isDefault = buttonInfo['default'];
 | 
			
		||||
 | 
			
		||||
        let keys;
 | 
			
		||||
 | 
			
		||||
        if (key)
 | 
			
		||||
            keys = [key];
 | 
			
		||||
        else if (isDefault)
 | 
			
		||||
            keys = [Clutter.KEY_Return, Clutter.KEY_KP_Enter, Clutter.KEY_ISO_Enter];
 | 
			
		||||
        else
 | 
			
		||||
            keys = [];
 | 
			
		||||
 | 
			
		||||
        let button = new St.Button({ style_class: 'modal-dialog-button',
 | 
			
		||||
                                     reactive:    true,
 | 
			
		||||
                                     can_focus:   true,
 | 
			
		||||
                                     label:       label });
 | 
			
		||||
        button.connect('clicked', action);
 | 
			
		||||
 | 
			
		||||
        buttonInfo['button'] = button;
 | 
			
		||||
 | 
			
		||||
        if (isDefault)
 | 
			
		||||
            button.add_style_pseudo_class('default');
 | 
			
		||||
 | 
			
		||||
        if (!this._initialKeyFocusDestroyId)
 | 
			
		||||
            this._initialKeyFocus = button;
 | 
			
		||||
 | 
			
		||||
        for (let i in keys)
 | 
			
		||||
            this._buttonKeys[keys[i]] = buttonInfo;
 | 
			
		||||
 | 
			
		||||
        this.buttonLayout.add(button, layoutInfo);
 | 
			
		||||
 | 
			
		||||
        return button;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyReleaseEvent: function(object, event) {
 | 
			
		||||
        let symbol = event.get_key_symbol();
 | 
			
		||||
        let action = this._actionKeys[symbol];
 | 
			
		||||
        let buttonInfo = this._buttonKeys[symbol];
 | 
			
		||||
 | 
			
		||||
        if (action) {
 | 
			
		||||
        if (!buttonInfo)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        let button = buttonInfo['button'];
 | 
			
		||||
        let action = buttonInfo['action'];
 | 
			
		||||
 | 
			
		||||
        if (action && button.reactive) {
 | 
			
		||||
            action();
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
@@ -226,7 +243,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);
 | 
			
		||||
@@ -276,7 +293,8 @@ const ModalDialog = new Lang.Class({
 | 
			
		||||
    pushModal: function (timestamp) {
 | 
			
		||||
        if (this._hasModal)
 | 
			
		||||
            return true;
 | 
			
		||||
        if (!Main.pushModal(this._group, timestamp))
 | 
			
		||||
        if (!Main.pushModal(this._group, { timestamp: timestamp,
 | 
			
		||||
                                           keybindingMode: this._keybindingMode }))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        this._hasModal = true;
 | 
			
		||||
 
 | 
			
		||||
@@ -28,17 +28,23 @@ const DASH_MAX_WIDTH = 96;
 | 
			
		||||
 | 
			
		||||
const DND_WINDOW_SWITCH_TIMEOUT = 1250;
 | 
			
		||||
 | 
			
		||||
const SwipeScrollDirection = {
 | 
			
		||||
    NONE: 0,
 | 
			
		||||
    HORIZONTAL: 1,
 | 
			
		||||
    VERTICAL: 2
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const SwipeScrollResult = {
 | 
			
		||||
    CANCEL: 0,
 | 
			
		||||
    SWIPE: 1,
 | 
			
		||||
    CLICK: 2
 | 
			
		||||
};
 | 
			
		||||
const GLSL_DIM_EFFECT_DECLARATIONS = '';
 | 
			
		||||
const GLSL_DIM_EFFECT_CODE = '\
 | 
			
		||||
   vec2 dist = cogl_tex_coord_in[0].xy - vec2(0.5, 0.5); \
 | 
			
		||||
   float elipse_radius = 0.5; \
 | 
			
		||||
   /* from https://bugzilla.gnome.org/show_bug.cgi?id=669798: \
 | 
			
		||||
      the alpha on the gradient goes from 165 at its darkest to 98 at its most transparent. */ \
 | 
			
		||||
   float y = 165.0 / 255.0; \
 | 
			
		||||
   float x = 98.0 / 255.0; \
 | 
			
		||||
   /* interpolate darkening value, based on distance from screen center */ \
 | 
			
		||||
   float val = min(length(dist), elipse_radius); \
 | 
			
		||||
   float a = mix(x, y, val / elipse_radius); \
 | 
			
		||||
   /* dim_factor varies from [1.0 -> 0.5] when overview is showing \
 | 
			
		||||
      We use it to smooth value, then we clamp it to valid color interval */ \
 | 
			
		||||
   a = clamp(a - cogl_color_in.r + 0.5, 0.0, 1.0); \
 | 
			
		||||
   /* We\'re blending between: color and black color (obviously omitted in the equation) */ \
 | 
			
		||||
   cogl_color_out.xyz = cogl_color_out.xyz * (1.0 - a); \
 | 
			
		||||
   cogl_color_out.a = 1.0;';
 | 
			
		||||
 | 
			
		||||
const ShellInfo = new Lang.Class({
 | 
			
		||||
    Name: 'ShellInfo',
 | 
			
		||||
@@ -57,7 +63,14 @@ const ShellInfo = new Lang.Class({
 | 
			
		||||
            this._source.destroy();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setMessage: function(text, undoCallback, undoLabel) {
 | 
			
		||||
    setMessage: function(text, options) {
 | 
			
		||||
        options = Params.parse(options, { undoCallback: null,
 | 
			
		||||
                                          forFeedback: false
 | 
			
		||||
                                        });
 | 
			
		||||
 | 
			
		||||
        let undoCallback = options.undoCallback;
 | 
			
		||||
        let forFeedback = options.forFeedback;
 | 
			
		||||
 | 
			
		||||
        if (this._source == null) {
 | 
			
		||||
            this._source = new MessageTray.SystemNotificationSource();
 | 
			
		||||
            this._source.connect('destroy', Lang.bind(this,
 | 
			
		||||
@@ -71,6 +84,7 @@ const ShellInfo = new Lang.Class({
 | 
			
		||||
        if (this._source.notifications.length == 0) {
 | 
			
		||||
            notification = new MessageTray.Notification(this._source, text, null);
 | 
			
		||||
            notification.setTransient(true);
 | 
			
		||||
            notification.setForFeedback(forFeedback);
 | 
			
		||||
        } else {
 | 
			
		||||
            notification = this._source.notifications[0];
 | 
			
		||||
            notification.update(text, null, { clear: true });
 | 
			
		||||
@@ -78,10 +92,8 @@ const ShellInfo = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._undoCallback = undoCallback;
 | 
			
		||||
        if (undoCallback) {
 | 
			
		||||
            notification.addButton('system-undo',
 | 
			
		||||
                                   undoLabel ? undoLabel : _("Undo"));
 | 
			
		||||
            notification.connect('action-invoked',
 | 
			
		||||
                                 Lang.bind(this, this._onUndoClicked));
 | 
			
		||||
            notification.addButton('system-undo', _("Undo"));
 | 
			
		||||
            notification.connect('action-invoked', Lang.bind(this, this._onUndoClicked));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._source.notify(notification);
 | 
			
		||||
@@ -113,6 +125,10 @@ const Overview = new Lang.Class({
 | 
			
		||||
        // scenes which allows us to show the background with different
 | 
			
		||||
        // rendering options without duplicating the texture data.
 | 
			
		||||
        this._background = Meta.BackgroundActor.new_for_screen(global.screen);
 | 
			
		||||
        this._background.add_glsl_snippet(Meta.SnippetHook.FRAGMENT,
 | 
			
		||||
                                          GLSL_DIM_EFFECT_DECLARATIONS,
 | 
			
		||||
                                          GLSL_DIM_EFFECT_CODE,
 | 
			
		||||
                                          false);
 | 
			
		||||
        this._background.hide();
 | 
			
		||||
        global.overlay_group.add_actor(this._background);
 | 
			
		||||
 | 
			
		||||
@@ -137,8 +153,6 @@ const Overview = new Lang.Class({
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
        this._scrollDirection = SwipeScrollDirection.NONE;
 | 
			
		||||
        this._scrollAdjustment = null;
 | 
			
		||||
        this._capturedEventId = 0;
 | 
			
		||||
        this._buttonPressId = 0;
 | 
			
		||||
 | 
			
		||||
@@ -233,11 +247,16 @@ const Overview = new Lang.Class({
 | 
			
		||||
        this._viewSelector.removeSearchProvider(provider);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setMessage: function(text, undoCallback, undoLabel) {
 | 
			
		||||
    //
 | 
			
		||||
    // options:
 | 
			
		||||
    //  - undoCallback (function): the callback to be called if undo support is needed
 | 
			
		||||
    //  - forFeedback (boolean): whether the message is for direct feedback of a user action
 | 
			
		||||
    //
 | 
			
		||||
    setMessage: function(text, options) {
 | 
			
		||||
        if (this.isDummy)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._shellInfo.setMessage(text, undoCallback, undoLabel);
 | 
			
		||||
        this._shellInfo.setMessage(text, options);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDragBegin: function() {
 | 
			
		||||
@@ -308,159 +327,11 @@ const Overview = new Lang.Class({
 | 
			
		||||
        return DND.DragMotionResult.CONTINUE;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setScrollAdjustment: function(adjustment, direction) {
 | 
			
		||||
    addAction: function(action) {
 | 
			
		||||
        if (this.isDummy)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._scrollAdjustment = adjustment;
 | 
			
		||||
        if (this._scrollAdjustment == null)
 | 
			
		||||
            this._scrollDirection = SwipeScrollDirection.NONE;
 | 
			
		||||
        else
 | 
			
		||||
            this._scrollDirection = direction;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onButtonPress: function(actor, event) {
 | 
			
		||||
        if (this._scrollDirection == SwipeScrollDirection.NONE
 | 
			
		||||
            || event.get_button() != 1)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let [stageX, stageY] = event.get_coords();
 | 
			
		||||
        this._dragStartX = this._dragX = stageX;
 | 
			
		||||
        this._dragStartY = this._dragY = stageY;
 | 
			
		||||
        this._dragStartValue = this._scrollAdjustment.value;
 | 
			
		||||
        this._lastMotionTime = -1; // used to track "stopping" while swipe-scrolling
 | 
			
		||||
        this._capturedEventId = global.stage.connect('captured-event',
 | 
			
		||||
            Lang.bind(this, this._onCapturedEvent));
 | 
			
		||||
        this.emit('swipe-scroll-begin');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onCapturedEvent: function(actor, event) {
 | 
			
		||||
        let stageX, stageY;
 | 
			
		||||
        let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
 | 
			
		||||
 | 
			
		||||
        switch(event.type()) {
 | 
			
		||||
            case Clutter.EventType.BUTTON_RELEASE:
 | 
			
		||||
                [stageX, stageY] = event.get_coords();
 | 
			
		||||
 | 
			
		||||
                // default to snapping back to the original value
 | 
			
		||||
                let newValue = this._dragStartValue;
 | 
			
		||||
 | 
			
		||||
                let minValue = this._scrollAdjustment.lower;
 | 
			
		||||
                let maxValue = this._scrollAdjustment.upper - this._scrollAdjustment.page_size;
 | 
			
		||||
 | 
			
		||||
                let direction;
 | 
			
		||||
                if (this._scrollDirection == SwipeScrollDirection.HORIZONTAL) {
 | 
			
		||||
                    direction = stageX > this._dragStartX ? -1 : 1;
 | 
			
		||||
                    if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
                        direction *= -1;
 | 
			
		||||
                } else {
 | 
			
		||||
                    direction = stageY > this._dragStartY ? -1 : 1;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // We default to scroll a full page size; both the first
 | 
			
		||||
                // and the last page may be smaller though, so we need to
 | 
			
		||||
                // adjust difference in those cases.
 | 
			
		||||
                let difference = direction * this._scrollAdjustment.page_size;
 | 
			
		||||
                if (this._dragStartValue + difference > maxValue)
 | 
			
		||||
                    difference = maxValue - this._dragStartValue;
 | 
			
		||||
                else if (this._dragStartValue + difference < minValue)
 | 
			
		||||
                    difference = minValue - this._dragStartValue;
 | 
			
		||||
 | 
			
		||||
                // If the user has moved more than half the scroll
 | 
			
		||||
                // difference, we want to "settle" to the new value
 | 
			
		||||
                // even if the user stops dragging rather "throws" by
 | 
			
		||||
                // releasing during the drag.
 | 
			
		||||
                let distance = this._dragStartValue - this._scrollAdjustment.value;
 | 
			
		||||
                let noStop = Math.abs(distance / difference) > 0.5;
 | 
			
		||||
 | 
			
		||||
                // We detect if the user is stopped by comparing the
 | 
			
		||||
                // timestamp of the button release with the timestamp of
 | 
			
		||||
                // the last motion. Experimentally, a difference of 0 or 1
 | 
			
		||||
                // millisecond indicates that the mouse is in motion, a
 | 
			
		||||
                // larger difference indicates that the mouse is stopped.
 | 
			
		||||
                if ((this._lastMotionTime > 0 &&
 | 
			
		||||
                     this._lastMotionTime > event.get_time() - 2) ||
 | 
			
		||||
                    noStop) {
 | 
			
		||||
                    if (this._dragStartValue + difference >= minValue &&
 | 
			
		||||
                        this._dragStartValue + difference <= maxValue)
 | 
			
		||||
                        newValue += difference;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let result;
 | 
			
		||||
 | 
			
		||||
                // See if the user has moved the mouse enough to trigger
 | 
			
		||||
                // a drag
 | 
			
		||||
                if (Math.abs(stageX - this._dragStartX) < threshold &&
 | 
			
		||||
                    Math.abs(stageY - this._dragStartY) < threshold) {
 | 
			
		||||
                    // no motion? It's a click!
 | 
			
		||||
                    result = SwipeScrollResult.CLICK;
 | 
			
		||||
                    this.emit('swipe-scroll-end', result);
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (newValue == this._dragStartValue)
 | 
			
		||||
                        result = SwipeScrollResult.CANCEL;
 | 
			
		||||
                    else
 | 
			
		||||
                        result = SwipeScrollResult.SWIPE;
 | 
			
		||||
 | 
			
		||||
                    // The event capture handler is disconnected
 | 
			
		||||
                    // while scrolling to the final position, so
 | 
			
		||||
                    // to avoid undesired prelights we raise
 | 
			
		||||
                    // the cover pane.
 | 
			
		||||
                    this._coverPane.raise_top();
 | 
			
		||||
                    this._coverPane.show();
 | 
			
		||||
 | 
			
		||||
                    Tweener.addTween(this._scrollAdjustment,
 | 
			
		||||
                                     { value: newValue,
 | 
			
		||||
                                       time: ANIMATION_TIME,
 | 
			
		||||
                                       transition: 'easeOutQuad',
 | 
			
		||||
                                       onCompleteScope: this,
 | 
			
		||||
                                       onComplete: function() {
 | 
			
		||||
                                          this._coverPane.hide();
 | 
			
		||||
                                          this.emit('swipe-scroll-end',
 | 
			
		||||
                                                    result);
 | 
			
		||||
                                       }
 | 
			
		||||
                                     });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                global.stage.disconnect(this._capturedEventId);
 | 
			
		||||
                this._capturedEventId = 0;
 | 
			
		||||
 | 
			
		||||
                return result != SwipeScrollResult.CLICK;
 | 
			
		||||
 | 
			
		||||
            case Clutter.EventType.MOTION:
 | 
			
		||||
                [stageX, stageY] = event.get_coords();
 | 
			
		||||
                let dx = this._dragX - stageX;
 | 
			
		||||
                let dy = this._dragY - stageY;
 | 
			
		||||
                let primary = Main.layoutManager.primaryMonitor;
 | 
			
		||||
 | 
			
		||||
                this._dragX = stageX;
 | 
			
		||||
                this._dragY = stageY;
 | 
			
		||||
                this._lastMotionTime = event.get_time();
 | 
			
		||||
 | 
			
		||||
                // See if the user has moved the mouse enough to trigger
 | 
			
		||||
                // a drag
 | 
			
		||||
                if (Math.abs(stageX - this._dragStartX) < threshold &&
 | 
			
		||||
                    Math.abs(stageY - this._dragStartY) < threshold)
 | 
			
		||||
                    return true;
 | 
			
		||||
 | 
			
		||||
                if (this._scrollDirection == SwipeScrollDirection.HORIZONTAL) {
 | 
			
		||||
                    if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
                        this._scrollAdjustment.value -= (dx / primary.width) * this._scrollAdjustment.page_size;
 | 
			
		||||
                    else
 | 
			
		||||
                        this._scrollAdjustment.value += (dx / primary.width) * this._scrollAdjustment.page_size;
 | 
			
		||||
                } else {
 | 
			
		||||
                    this._scrollAdjustment.value += (dy / primary.height) * this._scrollAdjustment.page_size;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return true;
 | 
			
		||||
 | 
			
		||||
            // Block enter/leave events to avoid prelights
 | 
			
		||||
            // during swipe-scroll
 | 
			
		||||
            case Clutter.EventType.ENTER:
 | 
			
		||||
            case Clutter.EventType.LEAVE:
 | 
			
		||||
                return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
        this._group.add_action(action);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getDesktopClone: function() {
 | 
			
		||||
@@ -558,14 +429,11 @@ const Overview = new Lang.Class({
 | 
			
		||||
        if (this._shown)
 | 
			
		||||
            return;
 | 
			
		||||
        // Do this manually instead of using _syncInputMode, to handle failure
 | 
			
		||||
        if (!Main.pushModal(this._group))
 | 
			
		||||
        if (!Main.pushModal(this._group, { keybindingMode: Main.KeybindingMode.OVERVIEW }))
 | 
			
		||||
            return;
 | 
			
		||||
        this._modal = true;
 | 
			
		||||
        this._animateVisible();
 | 
			
		||||
        this._shown = true;
 | 
			
		||||
 | 
			
		||||
        this._buttonPressId = this._group.connect('button-press-event',
 | 
			
		||||
            Lang.bind(this, this._onButtonPress));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    fadeInDesktop: function() {
 | 
			
		||||
@@ -622,7 +490,7 @@ const Overview = new Lang.Class({
 | 
			
		||||
                         });
 | 
			
		||||
 | 
			
		||||
        Tweener.addTween(this._background,
 | 
			
		||||
                         { dim_factor: 0.4,
 | 
			
		||||
                         { dim_factor: 0.8,
 | 
			
		||||
                           time: ANIMATION_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad'
 | 
			
		||||
                         });
 | 
			
		||||
@@ -665,10 +533,6 @@ const Overview = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._shown = false;
 | 
			
		||||
        this._syncInputMode();
 | 
			
		||||
 | 
			
		||||
        if (this._buttonPressId > 0)
 | 
			
		||||
            this._group.disconnect(this._buttonPressId);
 | 
			
		||||
        this._buttonPressId = 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // hideTemporarily:
 | 
			
		||||
@@ -709,7 +573,8 @@ const Overview = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        if (this._shown) {
 | 
			
		||||
            if (!this._modal) {
 | 
			
		||||
                if (Main.pushModal(this._group))
 | 
			
		||||
                if (Main.pushModal(this._group,
 | 
			
		||||
                                   { keybindingMode: Main.KeybindingMode.OVERVIEW }))
 | 
			
		||||
                    this._modal = true;
 | 
			
		||||
                else
 | 
			
		||||
                    this.hide();
 | 
			
		||||
 
 | 
			
		||||
@@ -82,26 +82,34 @@ const AnimatedIcon = new Lang.Class({
 | 
			
		||||
    _init: function(name, size) {
 | 
			
		||||
        this.actor = new St.Bin({ visible: false });
 | 
			
		||||
        this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
 | 
			
		||||
        this.actor.connect('notify::visible', Lang.bind(this, this._onVisibleNotify));
 | 
			
		||||
 | 
			
		||||
        this._isLoaded = false;
 | 
			
		||||
        this._isPlaying = false;
 | 
			
		||||
        this._timeoutId = 0;
 | 
			
		||||
        this._frame = 0;
 | 
			
		||||
        this._animations = St.TextureCache.get_default().load_sliced_image (global.datadir + '/theme/' + name, size, size);
 | 
			
		||||
        this._animations = St.TextureCache.get_default().load_sliced_image (global.datadir + '/theme/' + name, size, size,
 | 
			
		||||
                                                                            Lang.bind(this, this._animationsLoaded));
 | 
			
		||||
        this.actor.set_child(this._animations);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _disconnectTimeout: function() {
 | 
			
		||||
    play: function() {
 | 
			
		||||
        if (this._isLoaded && this._timeoutId == 0) {
 | 
			
		||||
            if (this._frame == 0)
 | 
			
		||||
                this._showFrame(0);
 | 
			
		||||
 | 
			
		||||
            this._timeoutId = Mainloop.timeout_add(ANIMATED_ICON_UPDATE_TIMEOUT, Lang.bind(this, this._update));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._isPlaying = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    stop: function() {
 | 
			
		||||
        if (this._timeoutId > 0) {
 | 
			
		||||
            Mainloop.source_remove(this._timeoutId);
 | 
			
		||||
            this._timeoutId = 0;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onVisibleNotify: function() {
 | 
			
		||||
        if (this.actor.visible)
 | 
			
		||||
            this._timeoutId = Mainloop.timeout_add(ANIMATED_ICON_UPDATE_TIMEOUT, Lang.bind(this, this._update));
 | 
			
		||||
        else
 | 
			
		||||
            this._disconnectTimeout();
 | 
			
		||||
        this._isPlaying = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showFrame: function(frame) {
 | 
			
		||||
@@ -121,8 +129,17 @@ const AnimatedIcon = new Lang.Class({
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _animationsLoaded: function() {
 | 
			
		||||
        this._isLoaded = true;
 | 
			
		||||
 | 
			
		||||
        if (this._isPlaying) {
 | 
			
		||||
            this._showFrame(0);
 | 
			
		||||
            this._timeoutId = Mainloop.timeout_add(ANIMATED_ICON_UPDATE_TIMEOUT, Lang.bind(this, this._update));
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDestroy: function() {
 | 
			
		||||
        this._disconnectTimeout();
 | 
			
		||||
        this.stop();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@@ -367,6 +384,7 @@ const AppMenuButton = new Lang.Class({
 | 
			
		||||
                           transition: "easeOutQuad",
 | 
			
		||||
                           onCompleteScope: this,
 | 
			
		||||
                           onComplete: function() {
 | 
			
		||||
                               this._spinner.stop();
 | 
			
		||||
                               this._spinner.actor.opacity = 255;
 | 
			
		||||
                               this._spinner.actor.hide();
 | 
			
		||||
                           }
 | 
			
		||||
@@ -376,6 +394,7 @@ const AppMenuButton = new Lang.Class({
 | 
			
		||||
    startAnimation: function() {
 | 
			
		||||
        this._stop = false;
 | 
			
		||||
        this.actor.reactive = false;
 | 
			
		||||
        this._spinner.play();
 | 
			
		||||
        this._spinner.actor.show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -863,10 +882,13 @@ const PanelCorner = new Lang.Class({
 | 
			
		||||
        let backgroundColor = node.get_color('-panel-corner-background-color');
 | 
			
		||||
        let borderColor = node.get_color('-panel-corner-border-color');
 | 
			
		||||
 | 
			
		||||
        let noOverlap = borderColor.alpha == 0;
 | 
			
		||||
        let offsetY = noOverlap ? borderWidth : 0;
 | 
			
		||||
 | 
			
		||||
        let cr = this.actor.get_context();
 | 
			
		||||
        cr.setOperator(Cairo.Operator.SOURCE);
 | 
			
		||||
 | 
			
		||||
        cr.moveTo(0, 0);
 | 
			
		||||
        cr.moveTo(0, offsetY);
 | 
			
		||||
        if (this._side == St.Side.LEFT)
 | 
			
		||||
            cr.arc(cornerRadius,
 | 
			
		||||
                   borderWidth + cornerRadius,
 | 
			
		||||
@@ -875,7 +897,7 @@ const PanelCorner = new Lang.Class({
 | 
			
		||||
            cr.arc(0,
 | 
			
		||||
                   borderWidth + cornerRadius,
 | 
			
		||||
                   cornerRadius, 3 * Math.PI / 2, 2 * Math.PI);
 | 
			
		||||
        cr.lineTo(cornerRadius, 0);
 | 
			
		||||
        cr.lineTo(cornerRadius, offsetY);
 | 
			
		||||
        cr.closePath();
 | 
			
		||||
 | 
			
		||||
        let savedPath = cr.copyPath();
 | 
			
		||||
@@ -885,6 +907,9 @@ const PanelCorner = new Lang.Class({
 | 
			
		||||
        Clutter.cairo_set_source_color(cr, over);
 | 
			
		||||
        cr.fill();
 | 
			
		||||
 | 
			
		||||
        if (noOverlap)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let offset = borderWidth;
 | 
			
		||||
        Clutter.cairo_set_source_color(cr, backgroundColor);
 | 
			
		||||
 | 
			
		||||
@@ -939,14 +964,9 @@ const Panel = new Lang.Class({
 | 
			
		||||
                                                  reactive: true });
 | 
			
		||||
        this.actor._delegate = this;
 | 
			
		||||
 | 
			
		||||
        this.statusArea = {};
 | 
			
		||||
        this._sessionStyle = null;
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('shown', Lang.bind(this, function () {
 | 
			
		||||
            this.actor.add_style_class_name('in-overview');
 | 
			
		||||
        }));
 | 
			
		||||
        Main.overview.connect('hiding', Lang.bind(this, function () {
 | 
			
		||||
            this.actor.remove_style_class_name('in-overview');
 | 
			
		||||
        }));
 | 
			
		||||
        this.statusArea = {};
 | 
			
		||||
 | 
			
		||||
        this.menuManager = new PopupMenu.PopupMenuManager(this);
 | 
			
		||||
 | 
			
		||||
@@ -976,7 +996,7 @@ const Panel = new Lang.Class({
 | 
			
		||||
        this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.panelBox.add(this.actor);
 | 
			
		||||
        Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'start-here-symbolic',
 | 
			
		||||
        Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'emblem-system-symbolic',
 | 
			
		||||
                                        { sortGroup: CtrlAltTab.SortGroup.TOP });
 | 
			
		||||
 | 
			
		||||
        Main.sessionMode.connect('updated', Lang.bind(this, this._updatePanel));
 | 
			
		||||
@@ -1133,6 +1153,13 @@ const Panel = new Lang.Class({
 | 
			
		||||
        this._updateBox(panel.left, this._leftBox);
 | 
			
		||||
        this._updateBox(panel.center, this._centerBox);
 | 
			
		||||
        this._updateBox(panel.right, this._rightBox);
 | 
			
		||||
 | 
			
		||||
        if (this._sessionStyle)
 | 
			
		||||
            this._removeStyleClassName(this._sessionStyle);
 | 
			
		||||
 | 
			
		||||
        this._sessionStyle = Main.sessionMode.panelStyle;
 | 
			
		||||
        if (this._sessionStyle)
 | 
			
		||||
            this._addStyleClassName(this._sessionStyle);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _initBox: function(elements, box) {
 | 
			
		||||
@@ -1221,5 +1248,17 @@ const Panel = new Lang.Class({
 | 
			
		||||
        this.statusArea[role] = indicator;
 | 
			
		||||
        this._addToPanelBox(role, indicator, position, boxContainer);
 | 
			
		||||
        return indicator;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addStyleClassName: function(className) {
 | 
			
		||||
        this.actor.add_style_class_name(className);
 | 
			
		||||
        this._rightCorner.actor.add_style_class_name(className);
 | 
			
		||||
        this._leftCorner.actor.add_style_class_name(className);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _removeStyleClassName: function(className) {
 | 
			
		||||
        this.actor.remove_style_class_name(className);
 | 
			
		||||
        this._rightCorner.actor.remove_style_class_name(className);
 | 
			
		||||
        this._leftCorner.actor.remove_style_class_name(className);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@ const St = imports.gi.St;
 | 
			
		||||
const Atk = imports.gi.Atk;
 | 
			
		||||
 | 
			
		||||
const BoxPointer = imports.ui.boxpointer;
 | 
			
		||||
const GrabHelper = imports.ui.grabHelper;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
@@ -658,14 +659,23 @@ const PopupSliderMenuItem = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _onScrollEvent: function (actor, event) {
 | 
			
		||||
        let direction = event.get_scroll_direction();
 | 
			
		||||
        let delta;
 | 
			
		||||
 | 
			
		||||
        if (event.is_pointer_emulated())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (direction == Clutter.ScrollDirection.DOWN) {
 | 
			
		||||
            this._value = Math.max(0, this._value - SLIDER_SCROLL_STEP);
 | 
			
		||||
        }
 | 
			
		||||
        else if (direction == Clutter.ScrollDirection.UP) {
 | 
			
		||||
            this._value = Math.min(1, this._value + SLIDER_SCROLL_STEP);
 | 
			
		||||
            delta = -SLIDER_SCROLL_STEP;
 | 
			
		||||
        } else if (direction == Clutter.ScrollDirection.UP) {
 | 
			
		||||
            delta = +SLIDER_SCROLL_STEP;
 | 
			
		||||
        } else if (direction == Clutter.ScrollDirection.SMOOTH) {
 | 
			
		||||
            let [dx, dy] = event.get_scroll_delta();
 | 
			
		||||
            // Even though the slider is horizontal, use dy to match
 | 
			
		||||
            // the UP/DOWN above.
 | 
			
		||||
            delta = -dy / 10;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._value = Math.min(Math.max(0, this._value + delta), 1);
 | 
			
		||||
        this._slider.queue_repaint();
 | 
			
		||||
        this.emit('value-changed', this._value);
 | 
			
		||||
    },
 | 
			
		||||
@@ -1204,7 +1214,6 @@ const PopupMenu = new Lang.Class({
 | 
			
		||||
        this.actor = this._boxPointer.actor;
 | 
			
		||||
        this.actor._delegate = this;
 | 
			
		||||
        this.actor.style_class = 'popup-menu-boxpointer';
 | 
			
		||||
        this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
 | 
			
		||||
 | 
			
		||||
        this._boxWrapper = new Shell.GenericContainer();
 | 
			
		||||
        this._boxWrapper.connect('get-preferred-width', Lang.bind(this, this._boxGetPreferredWidth));
 | 
			
		||||
@@ -1234,15 +1243,6 @@ const PopupMenu = new Lang.Class({
 | 
			
		||||
        this.box.allocate(box, flags);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyPressEvent: function(actor, event) {
 | 
			
		||||
        if (event.get_key_symbol() == Clutter.Escape) {
 | 
			
		||||
            this.close(BoxPointer.PopupAnimation.FULL);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setArrowOrigin: function(origin) {
 | 
			
		||||
        this._boxPointer.setArrowOrigin(origin);
 | 
			
		||||
    },
 | 
			
		||||
@@ -1537,7 +1537,6 @@ const PopupComboMenu = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this.actor = this.box;
 | 
			
		||||
        this.actor._delegate = this;
 | 
			
		||||
        this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
 | 
			
		||||
        this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
 | 
			
		||||
        sourceActor.connect('style-changed',
 | 
			
		||||
                            Lang.bind(this, this._onSourceActorStyleChanged));
 | 
			
		||||
@@ -1545,15 +1544,6 @@ const PopupComboMenu = new Lang.Class({
 | 
			
		||||
        global.focus_manager.add_group(this.actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyPressEvent: function(actor, event) {
 | 
			
		||||
        if (event.get_key_symbol() == Clutter.Escape) {
 | 
			
		||||
            this.close(BoxPointer.PopupAnimation.FULL);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyFocusIn: function(actor) {
 | 
			
		||||
        let items = this._getMenuItems();
 | 
			
		||||
        let activeItem = items[this._activeItemPos];
 | 
			
		||||
@@ -2044,17 +2034,8 @@ const PopupMenuManager = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _init: function(owner) {
 | 
			
		||||
        this._owner = owner;
 | 
			
		||||
        this.grabbed = false;
 | 
			
		||||
 | 
			
		||||
        this._eventCaptureId = 0;
 | 
			
		||||
        this._enterEventId = 0;
 | 
			
		||||
        this._leaveEventId = 0;
 | 
			
		||||
        this._keyFocusNotifyId = 0;
 | 
			
		||||
        this._activeMenu = null;
 | 
			
		||||
        this._grabHelper = new GrabHelper.GrabHelper(owner.actor);
 | 
			
		||||
        this._menus = [];
 | 
			
		||||
        this._menuStack = [];
 | 
			
		||||
        this._preGrabInputMode = null;
 | 
			
		||||
        this._grabbedFromKeynav = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addMenu: function(menu, position) {
 | 
			
		||||
@@ -2073,6 +2054,8 @@ const PopupMenuManager = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        let source = menu.sourceActor;
 | 
			
		||||
        if (source) {
 | 
			
		||||
            if (!menu.blockSourceEvents)
 | 
			
		||||
                this._grabHelper.addActor(source);
 | 
			
		||||
            menudata.enterId = source.connect('enter-event', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
 | 
			
		||||
            menudata.focusInId = source.connect('key-focus-in', Lang.bind(this, function() { this._onMenuSourceEnter(menu); }));
 | 
			
		||||
        }
 | 
			
		||||
@@ -2085,7 +2068,7 @@ const PopupMenuManager = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    removeMenu: function(menu) {
 | 
			
		||||
        if (menu == this._activeMenu)
 | 
			
		||||
            this._closeMenu();
 | 
			
		||||
            this._closeMenu(menu);
 | 
			
		||||
 | 
			
		||||
        let position = this._findMenu(menu);
 | 
			
		||||
        if (position == -1) // not a menu we manage
 | 
			
		||||
@@ -2102,79 +2085,25 @@ const PopupMenuManager = new Lang.Class({
 | 
			
		||||
        if (menudata.focusInId)
 | 
			
		||||
            menu.sourceActor.disconnect(menudata.focusInId);
 | 
			
		||||
 | 
			
		||||
        if (menu.sourceActor)
 | 
			
		||||
            this._grabHelper.removeActor(menu.sourceActor);
 | 
			
		||||
        this._menus.splice(position, 1);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _grab: function() {
 | 
			
		||||
        Main.pushModal(this._owner.actor);
 | 
			
		||||
 | 
			
		||||
        this._eventCaptureId = global.stage.connect('captured-event', Lang.bind(this, this._onEventCapture));
 | 
			
		||||
        // captured-event doesn't see enter/leave events
 | 
			
		||||
        this._enterEventId = global.stage.connect('enter-event', Lang.bind(this, this._onEventCapture));
 | 
			
		||||
        this._leaveEventId = global.stage.connect('leave-event', Lang.bind(this, this._onEventCapture));
 | 
			
		||||
        this._keyFocusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
 | 
			
		||||
 | 
			
		||||
        this.grabbed = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _ungrab: function() {
 | 
			
		||||
        global.stage.disconnect(this._eventCaptureId);
 | 
			
		||||
        this._eventCaptureId = 0;
 | 
			
		||||
        global.stage.disconnect(this._enterEventId);
 | 
			
		||||
        this._enterEventId = 0;
 | 
			
		||||
        global.stage.disconnect(this._leaveEventId);
 | 
			
		||||
        this._leaveEventId = 0;
 | 
			
		||||
        global.stage.disconnect(this._keyFocusNotifyId);
 | 
			
		||||
        this._keyFocusNotifyId = 0;
 | 
			
		||||
 | 
			
		||||
        this.grabbed = false;
 | 
			
		||||
        Main.popModal(this._owner.actor);
 | 
			
		||||
    get activeMenu() {
 | 
			
		||||
        let actor = this._grabHelper.currentGrab.actor;
 | 
			
		||||
        if (actor)
 | 
			
		||||
            return actor._delegate;
 | 
			
		||||
        else
 | 
			
		||||
            return null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onMenuOpenState: function(menu, open) {
 | 
			
		||||
        if (open) {
 | 
			
		||||
            if (this._activeMenu && this._activeMenu.isChildMenu(menu)) {
 | 
			
		||||
                this._menuStack.push(this._activeMenu);
 | 
			
		||||
                menu.actor.grab_key_focus();
 | 
			
		||||
            }
 | 
			
		||||
            this._activeMenu = menu;
 | 
			
		||||
            this._grabHelper.grab({ actor: menu.actor, modal: true,
 | 
			
		||||
                                    onUngrab: Lang.bind(this, this._closeMenu, menu) });
 | 
			
		||||
        } else {
 | 
			
		||||
            if (this._menuStack.length > 0) {
 | 
			
		||||
                this._activeMenu = this._menuStack.pop();
 | 
			
		||||
                if (menu.sourceActor)
 | 
			
		||||
                    menu.sourceActor.grab_key_focus();
 | 
			
		||||
                this._didPop = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check what the focus was before calling pushModal/popModal
 | 
			
		||||
        let focus = global.stage.key_focus;
 | 
			
		||||
        let hadFocus = focus && this._activeMenuContains(focus);
 | 
			
		||||
 | 
			
		||||
        if (open) {
 | 
			
		||||
            if (!this.grabbed) {
 | 
			
		||||
                this._preGrabInputMode = global.stage_input_mode;
 | 
			
		||||
                this._grabbedFromKeynav = hadFocus;
 | 
			
		||||
                this._grab();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (hadFocus)
 | 
			
		||||
                focus.grab_key_focus();
 | 
			
		||||
            else
 | 
			
		||||
                menu.actor.grab_key_focus();
 | 
			
		||||
        } else if (menu == this._activeMenu) {
 | 
			
		||||
            if (this.grabbed)
 | 
			
		||||
                this._ungrab();
 | 
			
		||||
            this._activeMenu = null;
 | 
			
		||||
 | 
			
		||||
            if (this._grabbedFromKeynav) {
 | 
			
		||||
                if (this._preGrabInputMode == Shell.StageInputMode.FOCUSED)
 | 
			
		||||
                    global.stage_input_mode = Shell.StageInputMode.FOCUSED;
 | 
			
		||||
                if (hadFocus && menu.sourceActor)
 | 
			
		||||
                    menu.sourceActor.grab_key_focus();
 | 
			
		||||
                else if (focus)
 | 
			
		||||
                    focus.grab_key_focus();
 | 
			
		||||
            }
 | 
			
		||||
            this._grabHelper.ungrab({ actor: menu.actor });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -2186,87 +2115,37 @@ const PopupMenuManager = new Lang.Class({
 | 
			
		||||
        this.removeMenu(childMenu);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // change the currently-open menu without dropping grab
 | 
			
		||||
    _changeMenu: function(newMenu) {
 | 
			
		||||
        if (this._activeMenu) {
 | 
			
		||||
            // _onOpenMenuState will drop the grab if it sees
 | 
			
		||||
            // this._activeMenu being closed; so clear _activeMenu
 | 
			
		||||
            // before closing it to keep that from happening
 | 
			
		||||
            let oldMenu = this._activeMenu;
 | 
			
		||||
            this._activeMenu = null;
 | 
			
		||||
            for (let i = this._menuStack.length - 1; i >= 0; i--)
 | 
			
		||||
                this._menuStack[i].close(BoxPointer.PopupAnimation.FADE);
 | 
			
		||||
            oldMenu.close(BoxPointer.PopupAnimation.FADE);
 | 
			
		||||
            newMenu.open(BoxPointer.PopupAnimation.FADE);
 | 
			
		||||
        } else
 | 
			
		||||
            newMenu.open(BoxPointer.PopupAnimation.FULL);
 | 
			
		||||
        if (this.activeMenu) {
 | 
			
		||||
            this._closeMenu(this.activeMenu);
 | 
			
		||||
            newMenu.open(false);
 | 
			
		||||
        } else {
 | 
			
		||||
            newMenu.open(true);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onMenuSourceEnter: function(menu) {
 | 
			
		||||
        if (!this.grabbed || menu == this._activeMenu)
 | 
			
		||||
        if (!this._grabHelper.grabbed)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (this._activeMenu && this._activeMenu.isChildMenu(menu))
 | 
			
		||||
        if (this._grabHelper.isActorGrabbed(menu.actor))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (this._menuStack.indexOf(menu) != -1)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (this._menuStack.length > 0 && this._menuStack[0].isChildMenu(menu))
 | 
			
		||||
        let isChildMenu = this._grabHelper.grabStack.some(function(grab) {
 | 
			
		||||
            let existingMenu = grab.actor._delegate;
 | 
			
		||||
            return existingMenu.isChildMenu(menu);
 | 
			
		||||
        });
 | 
			
		||||
        if (isChildMenu)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        this._changeMenu(menu);
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyFocusChanged: function() {
 | 
			
		||||
        if (!this.grabbed || !this._activeMenu)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let focus = global.stage.key_focus;
 | 
			
		||||
        if (focus) {
 | 
			
		||||
            if (this._activeMenuContains(focus))
 | 
			
		||||
                return;
 | 
			
		||||
            if (this._menuStack.length > 0)
 | 
			
		||||
                return;
 | 
			
		||||
            if (focus._delegate && focus._delegate.menu &&
 | 
			
		||||
                this._findMenu(focus._delegate.menu) != -1)
 | 
			
		||||
                return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._closeMenu();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onMenuDestroy: function(menu) {
 | 
			
		||||
        this.removeMenu(menu);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _activeMenuContains: function(actor) {
 | 
			
		||||
        return this._activeMenu != null
 | 
			
		||||
                && (this._activeMenu.actor.contains(actor) ||
 | 
			
		||||
                    (this._activeMenu.sourceActor && this._activeMenu.sourceActor.contains(actor)));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _eventIsOnActiveMenu: function(event) {
 | 
			
		||||
        return this._activeMenuContains(event.get_source());
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _shouldBlockEvent: function(event) {
 | 
			
		||||
        let src = event.get_source();
 | 
			
		||||
 | 
			
		||||
        if (this._activeMenu != null && this._activeMenu.actor.contains(src))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._menus.length; i++) {
 | 
			
		||||
            let menu = this._menus[i].menu;
 | 
			
		||||
            if (menu.sourceActor && !menu.blockSourceEvents && menu.sourceActor.contains(src)) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findMenu: function(item) {
 | 
			
		||||
        for (let i = 0; i < this._menus.length; i++) {
 | 
			
		||||
            let menudata = this._menus[i];
 | 
			
		||||
@@ -2276,41 +2155,7 @@ const PopupMenuManager = new Lang.Class({
 | 
			
		||||
        return -1;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onEventCapture: function(actor, event) {
 | 
			
		||||
        if (!this.grabbed)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (this._owner.menuEventFilter &&
 | 
			
		||||
            this._owner.menuEventFilter(event))
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        if (this._didPop) {
 | 
			
		||||
            this._didPop = false;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let activeMenuContains = this._eventIsOnActiveMenu(event);
 | 
			
		||||
        let eventType = event.type();
 | 
			
		||||
 | 
			
		||||
        if (eventType == Clutter.EventType.BUTTON_RELEASE) {
 | 
			
		||||
            if (activeMenuContains) {
 | 
			
		||||
                return false;
 | 
			
		||||
            } else {
 | 
			
		||||
                this._closeMenu();
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (eventType == Clutter.EventType.BUTTON_PRESS && !activeMenuContains) {
 | 
			
		||||
            this._closeMenu();
 | 
			
		||||
            return true;
 | 
			
		||||
        } else if (!this._shouldBlockEvent(event)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _closeMenu: function() {
 | 
			
		||||
        if (this._activeMenu != null)
 | 
			
		||||
            this._activeMenu.close(BoxPointer.PopupAnimation.FULL);
 | 
			
		||||
    _closeMenu: function(menu) {
 | 
			
		||||
        menu.close(BoxPointer.PopupAnimation.FULL);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -31,20 +31,37 @@ const SearchProviderIface = <interface name="org.gnome.Shell.SearchProvider">
 | 
			
		||||
 | 
			
		||||
var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function loadRemoteSearchProviders(addProviderCallback) {
 | 
			
		||||
    let loadState = { loadedProviders: [],
 | 
			
		||||
                      objectPaths: {},
 | 
			
		||||
                      numLoading: 0,
 | 
			
		||||
                      addProviderCallback: addProviderCallback };
 | 
			
		||||
 | 
			
		||||
    let dataDirs = GLib.get_system_data_dirs();
 | 
			
		||||
    let loadedProviders = {};
 | 
			
		||||
    for (let i = 0; i < dataDirs.length; i++) {
 | 
			
		||||
        let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', 'search-providers']);
 | 
			
		||||
        let dir = Gio.file_new_for_path(path);
 | 
			
		||||
        if (!dir.query_exists(null))
 | 
			
		||||
            continue;
 | 
			
		||||
        loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallback);
 | 
			
		||||
 | 
			
		||||
        dir.query_info_async('standard:type', Gio.FileQueryInfoFlags.NONE,
 | 
			
		||||
            GLib.PRIORITY_DEFAULT, null,
 | 
			
		||||
                function(object, res) {
 | 
			
		||||
                    let exists = false;
 | 
			
		||||
                    try {
 | 
			
		||||
                        object.query_info_finish(res);
 | 
			
		||||
                        exists = true;
 | 
			
		||||
                    } catch (e) {
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (!exists)
 | 
			
		||||
                        return;
 | 
			
		||||
 | 
			
		||||
                    loadState.numLoading++;
 | 
			
		||||
                    loadRemoteSearchProvidersFromDir(dir, loadState);
 | 
			
		||||
                });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallback) {
 | 
			
		||||
function loadRemoteSearchProvidersFromDir(dir, loadState) {
 | 
			
		||||
    let dirPath = dir.get_path();
 | 
			
		||||
    FileUtils.listDirAsync(dir, Lang.bind(this, function(files) {
 | 
			
		||||
        for (let i = 0; i < files.length; i++) {
 | 
			
		||||
@@ -60,13 +77,13 @@ function loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallb
 | 
			
		||||
            if (!keyfile.has_group(KEY_FILE_GROUP))
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            let remoteProvider, title;
 | 
			
		||||
            let remoteProvider;
 | 
			
		||||
            try {
 | 
			
		||||
                let group = KEY_FILE_GROUP;
 | 
			
		||||
                let busName = keyfile.get_string(group, 'BusName');
 | 
			
		||||
                let objectPath = keyfile.get_string(group, 'ObjectPath');
 | 
			
		||||
 | 
			
		||||
                if (loadedProviders[objectPath])
 | 
			
		||||
                if (loadState.objectPaths[objectPath])
 | 
			
		||||
                    continue;
 | 
			
		||||
 | 
			
		||||
                let appInfo = null;
 | 
			
		||||
@@ -74,46 +91,93 @@ function loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallb
 | 
			
		||||
                    let desktopId = keyfile.get_string(group, 'DesktopId');
 | 
			
		||||
                    appInfo = Gio.DesktopAppInfo.new(desktopId);
 | 
			
		||||
                } catch (e) {
 | 
			
		||||
                    log('Ignoring search provider ' + path + ': missing DesktopId');
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let icon;
 | 
			
		||||
                if (appInfo) {
 | 
			
		||||
                    icon = appInfo.get_icon();
 | 
			
		||||
                    title = appInfo.get_name();
 | 
			
		||||
                } else {
 | 
			
		||||
                    let iconName = keyfile.get_string(group, 'Icon');
 | 
			
		||||
                    icon = new Gio.ThemedIcon({ name: iconName });
 | 
			
		||||
                    title = keyfile.get_locale_string(group, 'Title', null);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                remoteProvider = new RemoteSearchProvider(title,
 | 
			
		||||
                                                          icon,
 | 
			
		||||
                remoteProvider = new RemoteSearchProvider(appInfo,
 | 
			
		||||
                                                          busName,
 | 
			
		||||
                                                          objectPath);
 | 
			
		||||
                loadedProviders[objectPath] = remoteProvider;
 | 
			
		||||
                loadState.objectPaths[objectPath] = remoteProvider;
 | 
			
		||||
                loadState.loadedProviders.push(remoteProvider);
 | 
			
		||||
            } catch(e) {
 | 
			
		||||
                log('Failed to add search provider "%s": %s'.format(title, e.toString()));
 | 
			
		||||
                log('Failed to add search provider %s: %s'.format(path, e.toString()));
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            addProviderCallback(remoteProvider);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        remoteProvidersDirLoaded(loadState);
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function remoteProvidersDirLoaded(loadState) {
 | 
			
		||||
    loadState.numLoading--;
 | 
			
		||||
    if (loadState.numLoading > 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    let searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
 | 
			
		||||
    let sortOrder = searchSettings.get_strv('sort-order');
 | 
			
		||||
    let numSorted = sortOrder.length;
 | 
			
		||||
 | 
			
		||||
    loadState.loadedProviders.sort(
 | 
			
		||||
        function(providerA, providerB) {
 | 
			
		||||
            let idxA, idxB;
 | 
			
		||||
            let appIdA, appIdB;
 | 
			
		||||
 | 
			
		||||
            appIdA = providerA.appInfo.get_id();
 | 
			
		||||
            appIdB = providerB.appInfo.get_id();
 | 
			
		||||
 | 
			
		||||
            idxA = sortOrder.indexOf(appIdA);
 | 
			
		||||
            idxB = sortOrder.indexOf(appIdB);
 | 
			
		||||
 | 
			
		||||
            // if no provider is found in the order, use alphabetical order
 | 
			
		||||
            if ((idxA == -1) && (idxB == -1))
 | 
			
		||||
                return GLib.utf8_collate(providerA.title, providerB.title);
 | 
			
		||||
 | 
			
		||||
            if (numSorted > 1) {
 | 
			
		||||
                // if providerA is the last, it goes after everything
 | 
			
		||||
                if ((idxA + 1) == numSorted)
 | 
			
		||||
                    return 1;
 | 
			
		||||
                // if providerB is the last, it goes after everything
 | 
			
		||||
                else if ((idxB + 1) == numSorted)
 | 
			
		||||
                    return -1;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // if providerA isn't found, it's sorted after providerB
 | 
			
		||||
            if (idxA == -1)
 | 
			
		||||
                return 1;
 | 
			
		||||
 | 
			
		||||
            // if providerB isn't found, it's sorted after providerA
 | 
			
		||||
            if (idxB == -1)
 | 
			
		||||
                return -1;
 | 
			
		||||
 | 
			
		||||
            // finally, if both providers are found, return their order in the list
 | 
			
		||||
            return (idxA - idxB);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    loadState.loadedProviders.forEach(
 | 
			
		||||
        function(provider) {
 | 
			
		||||
            loadState.addProviderCallback(provider);
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const RemoteSearchProvider = new Lang.Class({
 | 
			
		||||
    Name: 'RemoteSearchProvider',
 | 
			
		||||
    Extends: Search.SearchProvider,
 | 
			
		||||
 | 
			
		||||
    _init: function(title, icon, dbusName, dbusPath) {
 | 
			
		||||
    _init: function(appInfo, dbusName, dbusPath) {
 | 
			
		||||
        this._proxy = new SearchProviderProxy(Gio.DBus.session,
 | 
			
		||||
                                              dbusName, dbusPath);
 | 
			
		||||
            dbusName, dbusPath, Lang.bind(this, this._onProxyConstructed));
 | 
			
		||||
 | 
			
		||||
        this.parent(title.toUpperCase());
 | 
			
		||||
        this.parent(appInfo.get_name().toUpperCase(), appInfo, true);
 | 
			
		||||
        this._cancellable = new Gio.Cancellable();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onProxyConstructed: function(proxy) {
 | 
			
		||||
        // Do nothing
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createIcon: function(size, meta) {
 | 
			
		||||
        if (meta['gicon']) {
 | 
			
		||||
            return new St.Icon({ gicon: Gio.icon_new_for_string(meta['gicon']),
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,38 @@ const SUMMARY_ICON_SIZE = 48;
 | 
			
		||||
const STANDARD_FADE_TIME = 10;
 | 
			
		||||
const SHORT_FADE_TIME = 0.3;
 | 
			
		||||
 | 
			
		||||
function sample(offx, offy) {
 | 
			
		||||
    return 'texel += texture2D (sampler, tex_coord.st + pixel_step * ' +
 | 
			
		||||
        'vec2 (' + offx + ',' + offy + '));\n'
 | 
			
		||||
}
 | 
			
		||||
const GLSL_BLUR_EFFECT_DECLARATIONS = ' \
 | 
			
		||||
uniform vec2 pixel_step;\n \
 | 
			
		||||
uniform float desaturation;\n \
 | 
			
		||||
vec4 apply_blur(in sampler2D sampler, in vec2 tex_coord) {\n \
 | 
			
		||||
  vec4 texel;\n \
 | 
			
		||||
  texel = texture2D (sampler, tex_coord.st);\n'
 | 
			
		||||
  + sample(-1.0, -1.0)
 | 
			
		||||
  + sample( 0.0, -1.0)
 | 
			
		||||
  + sample(+1.0, -1.0)
 | 
			
		||||
  + sample(-1.0,  0.0)
 | 
			
		||||
  + sample(+1.0,  0.0)
 | 
			
		||||
  + sample(-1.0, +1.0)
 | 
			
		||||
  + sample( 0.0, +1.0)
 | 
			
		||||
  + sample(+1.0, +1.0) + ' \
 | 
			
		||||
   texel /= 9.0;\n \
 | 
			
		||||
   return texel;\n \
 | 
			
		||||
}\n \
 | 
			
		||||
vec3 desaturate (const vec3 color)\n \
 | 
			
		||||
{\n \
 | 
			
		||||
   const vec3 gray_conv = vec3 (0.299, 0.587, 0.114);\n \
 | 
			
		||||
   vec3 gray = vec3 (dot (gray_conv, color));\n \
 | 
			
		||||
   return vec3 (mix (color.rgb, gray, desaturation));\n \
 | 
			
		||||
}';
 | 
			
		||||
const GLSL_BLUR_EFFECT_CODE = ' \
 | 
			
		||||
cogl_texel = apply_blur(cogl_sampler, cogl_tex_coord.st);\n \
 | 
			
		||||
cogl_texel.rgb = desaturate(cogl_texel.rgb);\n';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const Clock = new Lang.Class({
 | 
			
		||||
    Name: 'ScreenShieldClock',
 | 
			
		||||
 | 
			
		||||
@@ -335,6 +367,10 @@ const Arrow = new Lang.Class({
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function clamp(value, min, max) {
 | 
			
		||||
    return Math.max(min, Math.min(max, value));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * To test screen shield, make sure to kill gnome-screensaver.
 | 
			
		||||
 *
 | 
			
		||||
@@ -362,13 +398,25 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
                                      Lang.bind(this, this._onLockScreenKeyRelease));
 | 
			
		||||
        this._lockScreenGroup.connect('scroll-event',
 | 
			
		||||
                                      Lang.bind(this, this._onLockScreenScroll));
 | 
			
		||||
        Main.ctrlAltTabManager.addGroup(this._lockScreenGroup, _("Lock"), 'changes-prevent-symbolic');
 | 
			
		||||
 | 
			
		||||
        this._lockScreenContents = new St.Widget({ layout_manager: new Clutter.BinLayout(),
 | 
			
		||||
                                                   name: 'lockScreenContents' });
 | 
			
		||||
        this._lockScreenContents.add_constraint(new Layout.MonitorConstraint({ primary: true }));
 | 
			
		||||
 | 
			
		||||
        let backgroundActor = Meta.BackgroundActor.new_for_screen(global.screen);
 | 
			
		||||
        backgroundActor.add_glsl_snippet(Meta.SnippetHook.TEXTURE_LOOKUP,
 | 
			
		||||
                                         GLSL_BLUR_EFFECT_DECLARATIONS,
 | 
			
		||||
                                         GLSL_BLUR_EFFECT_CODE,
 | 
			
		||||
                                         true);
 | 
			
		||||
        backgroundActor.set_uniform_float('desaturation',
 | 
			
		||||
                                          1, 1, [0.6]);
 | 
			
		||||
        backgroundActor.connect('notify::size', function(actor) {
 | 
			
		||||
            actor.set_uniform_float('pixel_step', 2, 1, [1/actor.width, 1/actor.height]);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._background = new St.Bin({ style_class: 'screen-shield-background',
 | 
			
		||||
                                        child: Meta.BackgroundActor.new_for_screen(global.screen) });
 | 
			
		||||
                                        child: backgroundActor });
 | 
			
		||||
        this._lockScreenGroup.add_actor(this._background);
 | 
			
		||||
        this._lockScreenGroup.add_actor(this._lockScreenContents);
 | 
			
		||||
 | 
			
		||||
@@ -387,14 +435,11 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
        this._lockScreenContents.add_actor(this._arrowContainer);
 | 
			
		||||
 | 
			
		||||
        let dragArea = new Clutter.Rect({ origin: new Clutter.Point({ x: 0, y: -global.screen_height, }),
 | 
			
		||||
                                          size: new Clutter.Size({ width: global.screen_width,
 | 
			
		||||
                                                                   height: global.screen_height }) });
 | 
			
		||||
        let action = new Clutter.DragAction({ drag_axis: Clutter.DragAxis.Y_AXIS,
 | 
			
		||||
                                              drag_area: dragArea });
 | 
			
		||||
        action.connect('drag-begin', Lang.bind(this, this._onDragBegin));
 | 
			
		||||
        action.connect('drag-end', Lang.bind(this, this._onDragEnd));
 | 
			
		||||
        this._lockScreenGroup.add_action(action);
 | 
			
		||||
        this._dragAction = new Clutter.GestureAction();
 | 
			
		||||
        this._dragAction.connect('gesture-begin', Lang.bind(this, this._onDragBegin));
 | 
			
		||||
        this._dragAction.connect('gesture-progress', Lang.bind(this, this._onDragMotion));
 | 
			
		||||
        this._dragAction.connect('gesture-end', Lang.bind(this, this._onDragEnd));
 | 
			
		||||
        this._lockScreenGroup.add_action(this._dragAction);
 | 
			
		||||
 | 
			
		||||
        this._lockDialogGroup = new St.Widget({ x_expand: true,
 | 
			
		||||
                                                y_expand: true,
 | 
			
		||||
@@ -436,6 +481,8 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
                                               { inhibitEvents: true,
 | 
			
		||||
                                                 fadeInTime: STANDARD_FADE_TIME,
 | 
			
		||||
                                                 fadeFactor: 1 });
 | 
			
		||||
 | 
			
		||||
        this.idleMonitor = new GnomeDesktop.IdleMonitor();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onLockScreenKeyRelease: function(actor, event) {
 | 
			
		||||
@@ -455,8 +502,8 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
        if (symbol == Clutter.KEY_Escape ||
 | 
			
		||||
            symbol == Clutter.KEY_Return ||
 | 
			
		||||
            symbol == Clutter.KEY_KP_Enter) {
 | 
			
		||||
            this._ensureUnlockDialog(true);
 | 
			
		||||
            this._hideLockScreen(true);
 | 
			
		||||
            this._ensureUnlockDialog(true, true);
 | 
			
		||||
            this._hideLockScreen(true, 0);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -478,8 +525,8 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        // 7 standard scrolls to lift up
 | 
			
		||||
        if (this._lockScreenScrollCounter > 35) {
 | 
			
		||||
            this._ensureUnlockDialog(false);
 | 
			
		||||
            this._hideLockScreen(true);
 | 
			
		||||
            this._ensureUnlockDialog(false, true);
 | 
			
		||||
            this._hideLockScreen(true, 0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
@@ -510,13 +557,29 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
    _onDragBegin: function() {
 | 
			
		||||
        Tweener.removeTweens(this._lockScreenGroup);
 | 
			
		||||
        this._lockScreenState = MessageTray.State.HIDING;
 | 
			
		||||
        this._ensureUnlockDialog(false);
 | 
			
		||||
        this._ensureUnlockDialog(false, false);
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDragMotion: function() {
 | 
			
		||||
	let [origX, origY] = this._dragAction.get_press_coords(0);
 | 
			
		||||
	let [currentX, currentY] = this._dragAction.get_motion_coords(0);
 | 
			
		||||
 | 
			
		||||
	let newY = currentY - origY;
 | 
			
		||||
	newY = clamp(newY, -global.stage.height, 0);
 | 
			
		||||
 | 
			
		||||
	this._lockScreenGroup.y = newY;
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDragEnd: function(action, actor, eventX, eventY, modifiers) {
 | 
			
		||||
        if (this._lockScreenGroup.y < -(ARROW_DRAG_THRESHOLD * global.stage.height)) {
 | 
			
		||||
            // Complete motion automatically
 | 
			
		||||
            this._hideLockScreen(true);
 | 
			
		||||
	    let [velocity, velocityX, velocityY] = this._dragAction.get_velocity(0);
 | 
			
		||||
	    this._hideLockScreen(true, -velocityY);
 | 
			
		||||
            this._ensureUnlockDialog(false, true);
 | 
			
		||||
        } else {
 | 
			
		||||
            // restore the lock screen to its original place
 | 
			
		||||
            // try to use the same speed as the normal animation
 | 
			
		||||
@@ -545,35 +608,43 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onStatusChanged: function(status) {
 | 
			
		||||
        if (status == GnomeSession.PresenceStatus.IDLE) {
 | 
			
		||||
            if (this._dialog) {
 | 
			
		||||
                this._dialog.cancel();
 | 
			
		||||
                if (!this._isGreeter) {
 | 
			
		||||
                    this._dialog = null;
 | 
			
		||||
        if (status != GnomeSession.PresenceStatus.IDLE)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (this._dialog) {
 | 
			
		||||
            this._dialog.cancel();
 | 
			
		||||
            if (!this._isGreeter) {
 | 
			
		||||
                this._dialog = null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!this._isModal) {
 | 
			
		||||
            Main.pushModal(this.actor, { keybindingMode: Main.KeybindingMode.LOCK_SCREEN });
 | 
			
		||||
            this._isModal = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!this._isActive) {
 | 
			
		||||
            this._lightbox.show();
 | 
			
		||||
 | 
			
		||||
            if (this._activationTime == 0)
 | 
			
		||||
                this._activationTime = GLib.get_monotonic_time();
 | 
			
		||||
 | 
			
		||||
            this._becameActiveId = this.idleMonitor.connect('became-active', Lang.bind(this, function() {
 | 
			
		||||
                this.idleMonitor.disconnect(this._becameActiveId);
 | 
			
		||||
 | 
			
		||||
                let lightboxWasShown = this._lightbox.shown;
 | 
			
		||||
                this._lightbox.hide();
 | 
			
		||||
 | 
			
		||||
                let shouldLock = lightboxWasShown && this._settings.get_boolean(LOCK_ENABLED_KEY);
 | 
			
		||||
                if (shouldLock || this._isLocked) {
 | 
			
		||||
                    this.lock(false);
 | 
			
		||||
                } else if (this._isActive) {
 | 
			
		||||
                    this.unlock();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
            if (!this._isModal) {
 | 
			
		||||
                Main.pushModal(this.actor);
 | 
			
		||||
                this._isModal = true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!this._isActive) {
 | 
			
		||||
                this._lightbox.show();
 | 
			
		||||
 | 
			
		||||
                if (this._activationTime == 0)
 | 
			
		||||
                    this._activationTime = GLib.get_monotonic_time();
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            let lightboxWasShown = this._lightbox.shown;
 | 
			
		||||
            this._lightbox.hide();
 | 
			
		||||
 | 
			
		||||
            let shouldLock = lightboxWasShown && this._settings.get_boolean(LOCK_ENABLED_KEY);
 | 
			
		||||
            if (shouldLock || this._isActive) {
 | 
			
		||||
                this.lock(false);
 | 
			
		||||
            } else if (this._isModal) {
 | 
			
		||||
                this.unlock();
 | 
			
		||||
            }
 | 
			
		||||
            this._isActive = true;
 | 
			
		||||
            this.emit('lock-status-changed');
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -591,8 +662,8 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
        this._isGreeter = Main.sessionMode.isGreeter;
 | 
			
		||||
        this._ensureUnlockDialog(true);
 | 
			
		||||
        this._hideLockScreen(false);
 | 
			
		||||
        this._ensureUnlockDialog(true, true);
 | 
			
		||||
        this._hideLockScreen(false, 0);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _bumpLockScreen: function() {
 | 
			
		||||
@@ -610,14 +681,21 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
                         });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hideLockScreen: function(animate) {
 | 
			
		||||
    _hideLockScreen: function(animate, velocity) {
 | 
			
		||||
        this._lockScreenState = MessageTray.State.HIDING;
 | 
			
		||||
 | 
			
		||||
        if (animate) {
 | 
			
		||||
            // Tween the lock screen out of screen
 | 
			
		||||
            // try to use the same speed regardless of original position
 | 
			
		||||
            // if velocity is not specified (i.e. we come here from pressing ESC),
 | 
			
		||||
            // use the same speed regardless of original position
 | 
			
		||||
            // if velocity is specified, it's in pixels per milliseconds
 | 
			
		||||
            let h = global.stage.height;
 | 
			
		||||
            let time = CURTAIN_SLIDE_TIME * (h + this._lockScreenGroup.y) / h;
 | 
			
		||||
            let delta = (h + this._lockScreenGroup.y);
 | 
			
		||||
            let min_velocity = global.stage.height / (CURTAIN_SLIDE_TIME * 1000);
 | 
			
		||||
 | 
			
		||||
            velocity = Math.max(min_velocity, velocity);
 | 
			
		||||
            let time = (delta / velocity) / 1000;
 | 
			
		||||
 | 
			
		||||
            Tweener.removeTweens(this._lockScreenGroup);
 | 
			
		||||
            Tweener.addTween(this._lockScreenGroup,
 | 
			
		||||
                             { y: -h,
 | 
			
		||||
@@ -634,20 +712,24 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
            this._lockScreenGroup.hide();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        global.stage.show_cursor();
 | 
			
		||||
 | 
			
		||||
        if (Main.sessionMode.currentMode == 'lock-screen')
 | 
			
		||||
            Main.sessionMode.popMode('lock-screen');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _ensureUnlockDialog: function(onPrimary) {
 | 
			
		||||
    _ensureUnlockDialog: function(onPrimary, allowCancel) {
 | 
			
		||||
        if (!this._dialog) {
 | 
			
		||||
            let constructor = Main.sessionMode.unlockDialog;
 | 
			
		||||
            this._dialog = new constructor(this._lockDialogGroup);
 | 
			
		||||
            if (!this._dialog) {
 | 
			
		||||
            if (!constructor) {
 | 
			
		||||
                // This session mode has no locking capabilities
 | 
			
		||||
                this.unlock();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this._dialog = new constructor(this._lockDialogGroup);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            let time = global.get_current_time();
 | 
			
		||||
            this._dialog.connect('loaded', Lang.bind(this, function() {
 | 
			
		||||
                if (!this._dialog.open(time, onPrimary)) {
 | 
			
		||||
@@ -659,6 +741,8 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
            this._dialog.connect('failed', Lang.bind(this, this._onUnlockFailed));
 | 
			
		||||
            this._dialog.connect('unlocked', Lang.bind(this, this._onUnlockSucceded));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._dialog.allowCancel = allowCancel;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onUnlockFailed: function() {
 | 
			
		||||
@@ -722,6 +806,16 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
        this._arrowAnimationId = Mainloop.timeout_add(6000, Lang.bind(this, this._animateArrows));
 | 
			
		||||
        this._animateArrows();
 | 
			
		||||
 | 
			
		||||
        let motionId = global.stage.connect('captured-event', function(stage, event) {
 | 
			
		||||
            if (event.type() == Clutter.EventType.MOTION) {
 | 
			
		||||
                global.stage.show_cursor();
 | 
			
		||||
                global.stage.disconnect(motionId);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        });
 | 
			
		||||
        global.stage.hide_cursor();
 | 
			
		||||
 | 
			
		||||
        this._lockScreenState = MessageTray.State.SHOWN;
 | 
			
		||||
        this._lockScreenGroup.fixed_position_set = false;
 | 
			
		||||
        this._lockScreenScrollCounter = 0;
 | 
			
		||||
@@ -830,12 +924,13 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._activationTime = 0;
 | 
			
		||||
        this._isActive = false;
 | 
			
		||||
        this._isLocked = false;
 | 
			
		||||
        this.emit('lock-status-changed');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    lock: function(animate) {
 | 
			
		||||
        if (!this._isModal) {
 | 
			
		||||
            Main.pushModal(this.actor);
 | 
			
		||||
            Main.pushModal(this.actor, { keybindingMode: Main.KeybindingMode.LOCK_SCREEN });
 | 
			
		||||
            this._isModal = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -854,6 +949,7 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
        this._resetLockScreen(animate, animate);
 | 
			
		||||
 | 
			
		||||
        this._isActive = true;
 | 
			
		||||
        this._isLocked = true;
 | 
			
		||||
        this.emit('lock-status-changed');
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,8 @@ const Util = imports.misc.util;
 | 
			
		||||
const FileUtils = imports.misc.fileUtils;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
 | 
			
		||||
const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
 | 
			
		||||
 | 
			
		||||
// Not currently referenced by the search API, but
 | 
			
		||||
// this enumeration can be useful for provider
 | 
			
		||||
// implementations.
 | 
			
		||||
@@ -74,9 +76,11 @@ const SearchResultDisplay = new Lang.Class({
 | 
			
		||||
const SearchProvider = new Lang.Class({
 | 
			
		||||
    Name: 'SearchProvider',
 | 
			
		||||
 | 
			
		||||
    _init: function(title) {
 | 
			
		||||
    _init: function(title, appInfo, isRemoteProvider) {
 | 
			
		||||
        this.title = title;
 | 
			
		||||
        this.appInfo = appInfo;
 | 
			
		||||
        this.searchSystem = null;
 | 
			
		||||
        this.isRemoteProvider = !!isRemoteProvider;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -172,12 +176,16 @@ const SearchSystem = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._providers = [];
 | 
			
		||||
        this._remoteProviders = [];
 | 
			
		||||
        this.reset();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    registerProvider: function (provider) {
 | 
			
		||||
        provider.searchSystem = this;
 | 
			
		||||
        this._providers.push(provider);
 | 
			
		||||
 | 
			
		||||
        if (provider.isRemoteProvider)
 | 
			
		||||
            this._remoteProviders.push(provider);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    unregisterProvider: function (provider) {
 | 
			
		||||
@@ -186,12 +194,20 @@ const SearchSystem = new Lang.Class({
 | 
			
		||||
            return;
 | 
			
		||||
        provider.searchSystem = null;
 | 
			
		||||
        this._providers.splice(index, 1);
 | 
			
		||||
 | 
			
		||||
        let remoteIndex = this._remoteProviders.indexOf(provider);
 | 
			
		||||
        if (remoteIndex != -1)
 | 
			
		||||
            this._remoteProviders.splice(index, 1);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getProviders: function() {
 | 
			
		||||
        return this._providers;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getRemoteProviders: function() {
 | 
			
		||||
        return this._remoteProviders;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getTerms: function() {
 | 
			
		||||
        return this._previousTerms;
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -194,15 +194,9 @@ const SearchResults = new Lang.Class({
 | 
			
		||||
                                     expand: true,
 | 
			
		||||
                                     x_align: St.Align.START,
 | 
			
		||||
                                     y_align: St.Align.START });
 | 
			
		||||
        this.actor.connect('notify::mapped', Lang.bind(this,
 | 
			
		||||
            function() {
 | 
			
		||||
                if (!this.actor.mapped)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                let adjustment = scrollView.vscroll.adjustment;
 | 
			
		||||
                let direction = Overview.SwipeScrollDirection.VERTICAL;
 | 
			
		||||
                Main.overview.setScrollAdjustment(adjustment, direction);
 | 
			
		||||
            }));
 | 
			
		||||
        let action = new Clutter.PanAction({ interpolate: true });
 | 
			
		||||
        action.connect('pan', Lang.bind(this, this._onPan));
 | 
			
		||||
        this.actor.add_action(action);
 | 
			
		||||
 | 
			
		||||
        this._statusText = new St.Label({ style_class: 'search-statustext' });
 | 
			
		||||
        this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
 | 
			
		||||
@@ -219,6 +213,13 @@ const SearchResults = new Lang.Class({
 | 
			
		||||
        this._defaultResult = null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onPan: function(action) {
 | 
			
		||||
        let [dist, dx, dy] = action.get_motion_delta(0);
 | 
			
		||||
        let adjustment = this.actor.vscroll.adjustment;
 | 
			
		||||
        adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createProviderMeta: function(provider) {
 | 
			
		||||
        let providerBox = new St.BoxLayout({ style_class: 'search-section',
 | 
			
		||||
                                             vertical: true });
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,6 @@ const _modes = {
 | 
			
		||||
        showCalendarEvents: false,
 | 
			
		||||
        allowSettings: false,
 | 
			
		||||
        allowExtensions: false,
 | 
			
		||||
        allowKeybindingsWhenModal: false,
 | 
			
		||||
        hasRunDialog: false,
 | 
			
		||||
        hasWorkspaces: false,
 | 
			
		||||
        hasWindows: false,
 | 
			
		||||
@@ -29,10 +28,10 @@ const _modes = {
 | 
			
		||||
            center: [],
 | 
			
		||||
            right: []
 | 
			
		||||
        },
 | 
			
		||||
        panelStyle: null
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    'gdm': {
 | 
			
		||||
        allowKeybindingsWhenModal: true,
 | 
			
		||||
        hasNotifications: true,
 | 
			
		||||
        isGreeter: true,
 | 
			
		||||
        isPrimary: true,
 | 
			
		||||
@@ -43,7 +42,8 @@ const _modes = {
 | 
			
		||||
            center: ['dateMenu'],
 | 
			
		||||
            right: ['a11y', 'display', 'keyboard',
 | 
			
		||||
                    'volume', 'battery', 'powerMenu']
 | 
			
		||||
        }
 | 
			
		||||
        },
 | 
			
		||||
        panelStyle: 'login-screen'
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    'lock-screen': {
 | 
			
		||||
@@ -56,6 +56,7 @@ const _modes = {
 | 
			
		||||
            center: [],
 | 
			
		||||
            right: ['lockScreen']
 | 
			
		||||
        },
 | 
			
		||||
        panelStyle: 'lock-screen'
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    'unlock-dialog': {
 | 
			
		||||
@@ -67,6 +68,7 @@ const _modes = {
 | 
			
		||||
            center: [],
 | 
			
		||||
            right: ['a11y', 'keyboard', 'lockScreen']
 | 
			
		||||
        },
 | 
			
		||||
        panelStyle: 'unlock-screen'
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    'initial-setup': {
 | 
			
		||||
 
 | 
			
		||||
@@ -111,7 +111,7 @@ const GnomeShell = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onScreenshotComplete: function(obj, result, area, flash, invocation) {
 | 
			
		||||
        if (flash) {
 | 
			
		||||
        if (flash && result) {
 | 
			
		||||
            let flashspot = new Flashspot.Flashspot(area);
 | 
			
		||||
            flashspot.fire();
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@ const KEY_VISUAL_BELL      = 'visual-bell';
 | 
			
		||||
const DESKTOP_INTERFACE_SCHEMA = 'org.gnome.desktop.interface';
 | 
			
		||||
const KEY_GTK_THEME      = 'gtk-theme';
 | 
			
		||||
const KEY_ICON_THEME     = 'icon-theme';
 | 
			
		||||
const KEY_WM_THEME       = 'theme';
 | 
			
		||||
const KEY_TEXT_SCALING_FACTOR = 'text-scaling-factor';
 | 
			
		||||
 | 
			
		||||
const HIGH_CONTRAST_THEME = 'HighContrast';
 | 
			
		||||
@@ -101,28 +102,35 @@ const ATIndicator = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _buildHCItem: function() {
 | 
			
		||||
        let settings = new Gio.Settings({ schema: DESKTOP_INTERFACE_SCHEMA });
 | 
			
		||||
        let gtkTheme = settings.get_string(KEY_GTK_THEME);
 | 
			
		||||
        let iconTheme = settings.get_string(KEY_ICON_THEME);
 | 
			
		||||
        let interfaceSettings = new Gio.Settings({ schema: DESKTOP_INTERFACE_SCHEMA });
 | 
			
		||||
        let wmSettings = new Gio.Settings({ schema: WM_SCHEMA });
 | 
			
		||||
        let gtkTheme = interfaceSettings.get_string(KEY_GTK_THEME);
 | 
			
		||||
        let iconTheme = interfaceSettings.get_string(KEY_ICON_THEME);
 | 
			
		||||
        let wmTheme = wmSettings.get_string(KEY_WM_THEME);
 | 
			
		||||
        let hasHC = (gtkTheme == HIGH_CONTRAST_THEME);
 | 
			
		||||
        let highContrast = this._buildItemExtended(
 | 
			
		||||
            _("High Contrast"),
 | 
			
		||||
            hasHC,
 | 
			
		||||
            settings.is_writable(KEY_GTK_THEME) && settings.is_writable(KEY_ICON_THEME),
 | 
			
		||||
            interfaceSettings.is_writable(KEY_GTK_THEME) &&
 | 
			
		||||
            interfaceSettings.is_writable(KEY_ICON_THEME) &&
 | 
			
		||||
            wmSettings.is_writable(KEY_WM_THEME),
 | 
			
		||||
            function (enabled) {
 | 
			
		||||
                if (enabled) {
 | 
			
		||||
                    settings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
 | 
			
		||||
                    settings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
 | 
			
		||||
                    interfaceSettings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
 | 
			
		||||
                    interfaceSettings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
 | 
			
		||||
                    wmSettings.set_string(KEY_WM_THEME, HIGH_CONTRAST_THEME);
 | 
			
		||||
                } else if(!hasHC) {
 | 
			
		||||
                    settings.set_string(KEY_GTK_THEME, gtkTheme);
 | 
			
		||||
                    settings.set_string(KEY_ICON_THEME, iconTheme);
 | 
			
		||||
                    interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme);
 | 
			
		||||
                    interfaceSettings.set_string(KEY_ICON_THEME, iconTheme);
 | 
			
		||||
                    wmSettings.set_string(KEY_WM_THEME, wmTheme);
 | 
			
		||||
                } else {
 | 
			
		||||
                    settings.reset(KEY_GTK_THEME);
 | 
			
		||||
                    settings.reset(KEY_ICON_THEME);
 | 
			
		||||
                    interfaceSettings.reset(KEY_GTK_THEME);
 | 
			
		||||
                    interfaceSettings.reset(KEY_ICON_THEME);
 | 
			
		||||
                    wmSettings.reset(KEY_WM_THEME);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        settings.connect('changed::' + KEY_GTK_THEME, function() {
 | 
			
		||||
            let value = settings.get_string(KEY_GTK_THEME);
 | 
			
		||||
        interfaceSettings.connect('changed::' + KEY_GTK_THEME, function() {
 | 
			
		||||
            let value = interfaceSettings.get_string(KEY_GTK_THEME);
 | 
			
		||||
            if (value == HIGH_CONTRAST_THEME) {
 | 
			
		||||
                highContrast.setToggleState(true);
 | 
			
		||||
            } else {
 | 
			
		||||
@@ -130,11 +138,16 @@ const ATIndicator = new Lang.Class({
 | 
			
		||||
                gtkTheme = value;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        settings.connect('changed::' + KEY_ICON_THEME, function() {
 | 
			
		||||
            let value = settings.get_string(KEY_ICON_THEME);
 | 
			
		||||
        interfaceSettings.connect('changed::' + KEY_ICON_THEME, function() {
 | 
			
		||||
            let value = interfaceSettings.get_string(KEY_ICON_THEME);
 | 
			
		||||
            if (value != HIGH_CONTRAST_THEME)
 | 
			
		||||
                iconTheme = value;
 | 
			
		||||
        });
 | 
			
		||||
        wmSettings.connect('changed::' + KEY_WM_THEME, function() {
 | 
			
		||||
            let value = wmSettings.get_string(KEY_WM_THEME);
 | 
			
		||||
            if (value != HIGH_CONTRAST_THEME)
 | 
			
		||||
                wmTheme = value;
 | 
			
		||||
        });
 | 
			
		||||
        return highContrast;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -239,22 +239,6 @@ const Indicator = new Lang.Class({
 | 
			
		||||
                this._applet.send_to_address(device.bdaddr, device.alias);
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
        if (device.capabilities & GnomeBluetoothApplet.Capabilities.OBEX_FILE_TRANSFER) {
 | 
			
		||||
            item.menu.addAction(_("Browse Files..."), Lang.bind(this, function(event) {
 | 
			
		||||
                this._applet.browse_address(device.bdaddr, event.get_time(),
 | 
			
		||||
                    Lang.bind(this, function(applet, result) {
 | 
			
		||||
                        try {
 | 
			
		||||
                            applet.browse_address_finish(result);
 | 
			
		||||
                        } catch (e) {
 | 
			
		||||
                            this._ensureSource();
 | 
			
		||||
                            this._source.notify(new MessageTray.Notification(this._source,
 | 
			
		||||
                                 _("Bluetooth"),
 | 
			
		||||
                                 _("Error browsing device"),
 | 
			
		||||
                                 { body: _("The requested device cannot be browsed, error is '%s'").format(e) }));
 | 
			
		||||
                        }
 | 
			
		||||
                    }));
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        switch (device.type) {
 | 
			
		||||
        case GnomeBluetoothApplet.Type.KEYBOARD:
 | 
			
		||||
@@ -369,6 +353,7 @@ const ConfirmNotification = new Lang.Class({
 | 
			
		||||
    _init: function(source, applet, device_path, name, long_name, pin) {
 | 
			
		||||
        this.parent(source,
 | 
			
		||||
                    _("Bluetooth"),
 | 
			
		||||
                    /* Translators: argument is the device short name */
 | 
			
		||||
                    _("Pairing confirmation for %s").format(name),
 | 
			
		||||
                    { customContent: true });
 | 
			
		||||
        this.setResident(true);
 | 
			
		||||
@@ -378,6 +363,7 @@ const ConfirmNotification = new Lang.Class({
 | 
			
		||||
        this.addBody(_("Device %s wants to pair with this computer").format(long_name));
 | 
			
		||||
        this.addBody(_("Please confirm whether the PIN '%06d' matches the one on the device.").format(pin));
 | 
			
		||||
 | 
			
		||||
        /* Translators: this is the verb, not the noun */
 | 
			
		||||
        this.addButton('matches', _("Matches"));
 | 
			
		||||
        this.addButton('does-not-match', _("Does not match"));
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ const Gio = imports.gi.Gio;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const NetworkManager = imports.gi.NetworkManager;
 | 
			
		||||
const NMClient = imports.gi.NMClient;
 | 
			
		||||
const NMGtk = imports.gi.NMGtk;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
@@ -139,46 +140,6 @@ const NMNetworkMenuItem = new Lang.Class({
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const NMWiredSectionTitleMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'NMWiredSectionTitleMenuItem',
 | 
			
		||||
    Extends: PopupMenu.PopupSwitchMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function(label, params) {
 | 
			
		||||
        params = params || { };
 | 
			
		||||
        params.style_class = 'popup-subtitle-menu-item';
 | 
			
		||||
        this.parent(label, false, params);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateForDevice: function(device) {
 | 
			
		||||
        if (device) {
 | 
			
		||||
            this._device = device;
 | 
			
		||||
            this.setStatus(device.getStatusLabel());
 | 
			
		||||
            this.setToggleState(device.connected);
 | 
			
		||||
        } else
 | 
			
		||||
            this.setStatus('');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    activate: function(event) {
 | 
			
		||||
        this.parent(event);
 | 
			
		||||
 | 
			
		||||
        if (!this._device) {
 | 
			
		||||
            log('Section title activated when there is more than one device, should be non reactive');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let newState = this._switch.state;
 | 
			
		||||
 | 
			
		||||
        let ok;
 | 
			
		||||
        if (newState)
 | 
			
		||||
            ok = this._device.activate();
 | 
			
		||||
        else
 | 
			
		||||
            ok = this._device.deactivate();
 | 
			
		||||
 | 
			
		||||
        if (!ok)
 | 
			
		||||
            this._switch.setToggleState(false);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const NMWirelessSectionTitleMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'NMWirelessSectionTitleMenuItem',
 | 
			
		||||
    Extends: PopupMenu.PopupSwitchMenuItem,
 | 
			
		||||
@@ -351,7 +312,7 @@ const NMDevice = new Lang.Class({
 | 
			
		||||
        this._autoConnectionItem = null;
 | 
			
		||||
        this._overflowItem = null;
 | 
			
		||||
 | 
			
		||||
        this.statusItem = new PopupMenu.PopupSwitchMenuItem(this._getDescription(), this.connected, { style_class: 'popup-subtitle-menu-item' });
 | 
			
		||||
        this.statusItem = new PopupMenu.PopupSwitchMenuItem('', this.connected, { style_class: 'popup-subtitle-menu-item' });
 | 
			
		||||
        this._statusChanged = this.statusItem.connect('toggled', Lang.bind(this, function(item, state) {
 | 
			
		||||
            let ok;
 | 
			
		||||
            if (state)
 | 
			
		||||
@@ -512,6 +473,10 @@ const NMDevice = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    syncDescription: function() {
 | 
			
		||||
        this.statusItem.label.text = this.device._description;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // protected
 | 
			
		||||
    _createAutomaticConnection: function() {
 | 
			
		||||
        throw new TypeError('Invoking pure virtual function NMDevice.createAutomaticConnection');
 | 
			
		||||
@@ -639,25 +604,6 @@ const NMDevice = new Lang.Class({
 | 
			
		||||
        this.statusItem.setStatus(this.getStatusLabel());
 | 
			
		||||
 | 
			
		||||
        this.emit('state-changed');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getDescription: function() {
 | 
			
		||||
        let dev_product = this.device.get_product();
 | 
			
		||||
        let dev_vendor = this.device.get_vendor();
 | 
			
		||||
        if (!dev_product || !dev_vendor)
 | 
			
		||||
	    return '';
 | 
			
		||||
 | 
			
		||||
        let product = Util.fixupPCIDescription(dev_product);
 | 
			
		||||
        let vendor = Util.fixupPCIDescription(dev_vendor);
 | 
			
		||||
        let out = '';
 | 
			
		||||
 | 
			
		||||
        // Another quick hack; if all of the fixed up vendor string
 | 
			
		||||
        // is found in product, ignore the vendor.
 | 
			
		||||
        if (product.indexOf(vendor) == -1)
 | 
			
		||||
            out += vendor + ' ';
 | 
			
		||||
        out += product;
 | 
			
		||||
 | 
			
		||||
        return out;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@@ -867,10 +813,6 @@ const NMDeviceBluetooth = new Lang.Class({
 | 
			
		||||
        this._clearSection();
 | 
			
		||||
        this._queueCreateSection();
 | 
			
		||||
        this._updateStatusItem();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getDescription: function() {
 | 
			
		||||
        return this.device.name || _("Bluetooth");
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@@ -1651,15 +1593,14 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
        this._mobileUpdateId = 0;
 | 
			
		||||
        this._mobileUpdateDevice = null;
 | 
			
		||||
 | 
			
		||||
        this._nmDevices = [];
 | 
			
		||||
        this._devices = { };
 | 
			
		||||
 | 
			
		||||
        this._devices.wired = {
 | 
			
		||||
            section: new PopupMenu.PopupMenuSection(),
 | 
			
		||||
            devices: [ ],
 | 
			
		||||
            item: new NMWiredSectionTitleMenuItem(_("Wired"))
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this._devices.wired.section.addMenuItem(this._devices.wired.item);
 | 
			
		||||
        this._devices.wired.section.actor.hide();
 | 
			
		||||
        this.menu.addMenuItem(this._devices.wired.section);
 | 
			
		||||
        this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
 | 
			
		||||
@@ -1667,7 +1608,7 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
        this._devices.wireless = {
 | 
			
		||||
            section: new PopupMenu.PopupMenuSection(),
 | 
			
		||||
            devices: [ ],
 | 
			
		||||
            item: this._makeToggleItem('wireless', _("Wireless"))
 | 
			
		||||
            item: this._makeToggleItem('wireless', _("Wi-Fi"))
 | 
			
		||||
        };
 | 
			
		||||
        this._devices.wireless.section.addMenuItem(this._devices.wireless.item);
 | 
			
		||||
        this._devices.wireless.section.actor.hide();
 | 
			
		||||
@@ -1677,9 +1618,7 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
        this._devices.wwan = {
 | 
			
		||||
            section: new PopupMenu.PopupMenuSection(),
 | 
			
		||||
            devices: [ ],
 | 
			
		||||
            item: this._makeToggleItem('wwan', _("Mobile broadband"))
 | 
			
		||||
        };
 | 
			
		||||
        this._devices.wwan.section.addMenuItem(this._devices.wwan.item);
 | 
			
		||||
        this._devices.wwan.section.actor.hide();
 | 
			
		||||
        this.menu.addMenuItem(this._devices.wwan.section);
 | 
			
		||||
        this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
 | 
			
		||||
@@ -1762,16 +1701,23 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
            section.actor.hide();
 | 
			
		||||
        else {
 | 
			
		||||
            section.actor.show();
 | 
			
		||||
            if (devices.length == 1) {
 | 
			
		||||
                let dev = devices[0];
 | 
			
		||||
                dev.statusItem.actor.hide();
 | 
			
		||||
                item.updateForDevice(dev);
 | 
			
		||||
            } else {
 | 
			
		||||
                devices.forEach(function(dev) {
 | 
			
		||||
                    dev.statusItem.actor.show();
 | 
			
		||||
                });
 | 
			
		||||
                // remove status text from the section title item
 | 
			
		||||
                item.updateForDevice(null);
 | 
			
		||||
 | 
			
		||||
            // Sync the relation between the section title
 | 
			
		||||
            // item (the one with the airplane mode switch)
 | 
			
		||||
            // and the individual device switches
 | 
			
		||||
            if (item) {
 | 
			
		||||
                if (devices.length == 1) {
 | 
			
		||||
                    let dev = devices[0];
 | 
			
		||||
                    dev.statusItem.actor.hide();
 | 
			
		||||
                    item.updateForDevice(dev);
 | 
			
		||||
                } else {
 | 
			
		||||
                    devices.forEach(function(dev) {
 | 
			
		||||
                        dev.statusItem.actor.show();
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                    // remove status text from the section title item
 | 
			
		||||
                    item.updateForDevice(null);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
@@ -1779,8 +1725,9 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
    _readDevices: function() {
 | 
			
		||||
        let devices = this._client.get_devices() || [ ];
 | 
			
		||||
        for (let i = 0; i < devices.length; ++i) {
 | 
			
		||||
            this._deviceAdded(this._client, devices[i]);
 | 
			
		||||
            this._deviceAdded(this._client, devices[i], true);
 | 
			
		||||
        }
 | 
			
		||||
        this._syncDeviceNames();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _notifyForDevice: function(device, iconName, title, text, urgency) {
 | 
			
		||||
@@ -1828,7 +1775,18 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
        return wrapper;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _deviceAdded: function(client, device) {
 | 
			
		||||
    _syncDeviceNames: function() {
 | 
			
		||||
        let names = NMGtk.utils_disambiguate_device_names(this._nmDevices);
 | 
			
		||||
        for (let i = 0; i < this._nmDevices.length; i++) {
 | 
			
		||||
            let device = this._nmDevices[i];
 | 
			
		||||
            if (device._description != names[i]) {
 | 
			
		||||
                device._description = names[i];
 | 
			
		||||
                device._delegate.syncDescription();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _deviceAdded: function(client, device, skipSyncDeviceNames) {
 | 
			
		||||
        if (device._delegate) {
 | 
			
		||||
            // already seen, not adding again
 | 
			
		||||
            return;
 | 
			
		||||
@@ -1839,10 +1797,14 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
            let section = this._devices[wrapper.category].section;
 | 
			
		||||
            let devices = this._devices[wrapper.category].devices;
 | 
			
		||||
 | 
			
		||||
            section.addMenuItem(wrapper.section, 1);
 | 
			
		||||
            section.addMenuItem(wrapper.statusItem, 1);
 | 
			
		||||
            section.addMenuItem(wrapper.statusItem);
 | 
			
		||||
            section.addMenuItem(wrapper.section);
 | 
			
		||||
            devices.push(wrapper);
 | 
			
		||||
 | 
			
		||||
            this._nmDevices.push(device);
 | 
			
		||||
            if (!skipSyncDeviceNames)
 | 
			
		||||
                this._syncDeviceNames();
 | 
			
		||||
 | 
			
		||||
            this._syncSectionTitle(wrapper.category);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
@@ -1860,6 +1822,10 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
        let pos = devices.indexOf(wrapper);
 | 
			
		||||
        devices.splice(pos, 1);
 | 
			
		||||
 | 
			
		||||
        pos = this._nmDevices.indexOf(device);
 | 
			
		||||
        this._nmDevices.splice(pos, 1);
 | 
			
		||||
        this._syncDeviceNames();
 | 
			
		||||
 | 
			
		||||
        this._syncSectionTitle(wrapper.category)
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -96,7 +96,7 @@ const Indicator = new Lang.Class({
 | 
			
		||||
                    let minutes = time % 60;
 | 
			
		||||
                    let hours = Math.floor(time / 60);
 | 
			
		||||
                    let timestring;
 | 
			
		||||
                    if (time > 60) {
 | 
			
		||||
                    if (time >= 60) {
 | 
			
		||||
                        if (minutes == 0) {
 | 
			
		||||
                            timestring = ngettext("%d hour remaining", "%d hours remaining", hours).format(hours);
 | 
			
		||||
                        } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -66,24 +66,32 @@ const VolumeMenu = new Lang.Class({
 | 
			
		||||
        this._onControlStateChanged();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    scroll: function(direction) {
 | 
			
		||||
    scroll: function(event) {
 | 
			
		||||
        let direction = event.get_scroll_direction();
 | 
			
		||||
        let currentVolume = this._output.volume;
 | 
			
		||||
        let delta;
 | 
			
		||||
 | 
			
		||||
        if (event.is_pointer_emulated())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (direction == Clutter.ScrollDirection.DOWN) {
 | 
			
		||||
            let prev_muted = this._output.is_muted;
 | 
			
		||||
            this._output.volume = Math.max(0, currentVolume - this._volumeMax * VOLUME_ADJUSTMENT_STEP);
 | 
			
		||||
            if (this._output.volume < 1) {
 | 
			
		||||
                this._output.volume = 0;
 | 
			
		||||
                if (!prev_muted)
 | 
			
		||||
                    this._output.change_is_muted(true);
 | 
			
		||||
            }
 | 
			
		||||
            this._output.push_volume();
 | 
			
		||||
            delta = -VOLUME_ADJUSTMENT_STEP;
 | 
			
		||||
        } else if (direction == Clutter.ScrollDirection.UP) {
 | 
			
		||||
            delta = +VOLUME_ADJUSTMENT_STEP;
 | 
			
		||||
        } else if (direction == Clutter.ScrollDirection.SMOOTH) {
 | 
			
		||||
            let [dx, dy] = event.get_scroll_delta();
 | 
			
		||||
            // Use the same math as in the slider.
 | 
			
		||||
            delta = -dy / 10;
 | 
			
		||||
        }
 | 
			
		||||
        else if (direction == Clutter.ScrollDirection.UP) {
 | 
			
		||||
            this._output.volume = Math.min(this._volumeMax, currentVolume + this._volumeMax * VOLUME_ADJUSTMENT_STEP);
 | 
			
		||||
            this._output.change_is_muted(false);
 | 
			
		||||
            this._output.push_volume();
 | 
			
		||||
 | 
			
		||||
        let prev_muted = this._output.is_muted;
 | 
			
		||||
        this._output.volume = Math.max(0, currentVolume + this._volumeMax * delta);
 | 
			
		||||
        if (this._output.volume < 1) {
 | 
			
		||||
            this._output.volume = 0;
 | 
			
		||||
            if (!prev_muted)
 | 
			
		||||
                this._output.change_is_muted(true);
 | 
			
		||||
        }
 | 
			
		||||
        this._output.push_volume();
 | 
			
		||||
 | 
			
		||||
        this._notifyVolumeChange();
 | 
			
		||||
    },
 | 
			
		||||
@@ -242,6 +250,6 @@ const Indicator = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onScrollEvent: function(actor, event) {
 | 
			
		||||
        this._volumeMenu.scroll(event.get_scroll_direction());
 | 
			
		||||
        this._volumeMenu.scroll(event);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -14,12 +14,14 @@ const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const ModalDialog = imports.ui.modalDialog;
 | 
			
		||||
const Panel = imports.ui.panel;
 | 
			
		||||
const ShellEntry = imports.ui.shellEntry;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
const UserMenu = imports.ui.userMenu;
 | 
			
		||||
 | 
			
		||||
const Batch = imports.gdm.batch;
 | 
			
		||||
const GdmUtil = imports.gdm.util;
 | 
			
		||||
const LoginDialog = imports.gdm.loginDialog;
 | 
			
		||||
 | 
			
		||||
// The timeout before going back automatically to the lock screen (in seconds)
 | 
			
		||||
const IDLE_TIMEOUT = 2 * 60;
 | 
			
		||||
@@ -113,6 +115,7 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
    _init: function(parentActor) {
 | 
			
		||||
        this.parent({ shellReactive: true,
 | 
			
		||||
                      styleClass: 'login-dialog',
 | 
			
		||||
                      keybindingMode: Main.KeybindingMode.UNLOCK_SCREEN,
 | 
			
		||||
                      parentActor: parentActor
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
@@ -150,7 +153,9 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
        this._promptEntry.clutter_text.set_password_char('\u25cf');
 | 
			
		||||
        ShellEntry.addContextMenu(this._promptEntry, { isPassword: true });
 | 
			
		||||
        this.setInitialKeyFocus(this._promptEntry);
 | 
			
		||||
        this._promptEntry.clutter_text.connect('activate', Lang.bind(this, this._doUnlock));
 | 
			
		||||
        this._promptEntry.clutter_text.connect('text-changed', Lang.bind(this, function() {
 | 
			
		||||
            this._updateOkButtonSensitivity(this._promptEntry.text.length > 0);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this._promptLayout.add(this._promptEntry,
 | 
			
		||||
                               { expand: true,
 | 
			
		||||
@@ -165,15 +170,34 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
        this._promptLoginHint.hide();
 | 
			
		||||
        this.contentLayout.add_actor(this._promptLoginHint);
 | 
			
		||||
 | 
			
		||||
        let cancelButton = { label: _("Cancel"),
 | 
			
		||||
                             action: Lang.bind(this, this._escape),
 | 
			
		||||
                             key: Clutter.KEY_Escape };
 | 
			
		||||
        this._okButton = { label: _("Unlock"),
 | 
			
		||||
                           action: Lang.bind(this, this._doUnlock),
 | 
			
		||||
                           default: true };
 | 
			
		||||
        this.setButtons([cancelButton, this._okButton]);
 | 
			
		||||
        this._workSpinner = new Panel.AnimatedIcon('process-working.svg', LoginDialog.WORK_SPINNER_ICON_SIZE);
 | 
			
		||||
        this._workSpinner.actor.opacity = 0;
 | 
			
		||||
        this._workSpinner.actor.show();
 | 
			
		||||
 | 
			
		||||
        this._updateSensitivity(true);
 | 
			
		||||
        this.allowCancel = false;
 | 
			
		||||
        this.buttonLayout.visible = true;
 | 
			
		||||
        this.addButton({ label: _("Cancel"),
 | 
			
		||||
                         action: Lang.bind(this, this._escape),
 | 
			
		||||
                         key: Clutter.KEY_Escape },
 | 
			
		||||
                       { expand: true,
 | 
			
		||||
                         x_fill: false,
 | 
			
		||||
                         y_fill: false,
 | 
			
		||||
                         x_align: St.Align.START,
 | 
			
		||||
                         y_align: St.Align.MIDDLE });
 | 
			
		||||
        this.buttonLayout.add(this._workSpinner.actor,
 | 
			
		||||
                              { expand: false,
 | 
			
		||||
                                x_fill: false,
 | 
			
		||||
                                y_fill: false,
 | 
			
		||||
                                x_align: St.Align.END,
 | 
			
		||||
                                y_align: St.Align.MIDDLE });
 | 
			
		||||
        this._okButton = this.addButton({ label: _("Unlock"),
 | 
			
		||||
                                          action: Lang.bind(this, this._doUnlock),
 | 
			
		||||
                                          default: true },
 | 
			
		||||
                                        { expand: false,
 | 
			
		||||
                                          x_fill: false,
 | 
			
		||||
                                          y_fill: false,
 | 
			
		||||
                                          x_align: St.Align.END,
 | 
			
		||||
                                          y_align: St.Align.MIDDLE });
 | 
			
		||||
 | 
			
		||||
        let otherUserLabel = new St.Label({ text: _("Log in as another user"),
 | 
			
		||||
                                            style_class: 'login-dialog-not-listed-label' });
 | 
			
		||||
@@ -188,6 +212,8 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
                              { x_align: St.Align.START,
 | 
			
		||||
                                x_fill: false });
 | 
			
		||||
 | 
			
		||||
        this._updateSensitivity(true);
 | 
			
		||||
 | 
			
		||||
        let batch = new Batch.Hold();
 | 
			
		||||
        this._userVerifier.begin(this._userName, batch);
 | 
			
		||||
 | 
			
		||||
@@ -196,6 +222,8 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
            return false;
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        Main.ctrlAltTabManager.addGroup(this.dialogLayout, _("Unlock Window"), 'dialog-password-symbolic');
 | 
			
		||||
 | 
			
		||||
        this._idleMonitor = new GnomeDesktop.IdleMonitor();
 | 
			
		||||
        this._idleWatchId = this._idleMonitor.add_watch(IDLE_TIMEOUT * 1000, Lang.bind(this, this._escape));
 | 
			
		||||
    },
 | 
			
		||||
@@ -203,8 +231,36 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
    _updateSensitivity: function(sensitive) {
 | 
			
		||||
        this._promptEntry.reactive = sensitive;
 | 
			
		||||
        this._promptEntry.clutter_text.editable = sensitive;
 | 
			
		||||
        this._okButton.button.reactive = sensitive;
 | 
			
		||||
        this._okButton.button.can_focus = sensitive;
 | 
			
		||||
        this._updateOkButtonSensitivity(sensitive && this._promptEntry.text.length > 0);
 | 
			
		||||
        this._otherUserButton.reactive = sensitive;
 | 
			
		||||
        this._otherUserButton.can_focus = sensitive;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateOkButtonSensitivity: function(sensitive) {
 | 
			
		||||
        this._okButton.reactive = sensitive;
 | 
			
		||||
        this._okButton.can_focus = sensitive;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setWorking: function(working) {
 | 
			
		||||
        if (working) {
 | 
			
		||||
            this._workSpinner.play();
 | 
			
		||||
            Tweener.addTween(this._workSpinner.actor,
 | 
			
		||||
                             { opacity: 255,
 | 
			
		||||
                               delay: LoginDialog.WORK_SPINNER_ANIMATION_DELAY,
 | 
			
		||||
                               time: LoginDialog.WORK_SPINNER_ANIMATION_TIME,
 | 
			
		||||
                               transition: 'linear'
 | 
			
		||||
                             });
 | 
			
		||||
        } else {
 | 
			
		||||
            Tweener.addTween(this._workSpinner.actor,
 | 
			
		||||
                             { opacity: 0,
 | 
			
		||||
                               time: LoginDialog.WORK_SPINNER_ANIMATION_TIME,
 | 
			
		||||
                               transition: 'linear',
 | 
			
		||||
                               onCompleteScope: this,
 | 
			
		||||
                               onComplete: function() {
 | 
			
		||||
                                   this._workSpinner.stop();
 | 
			
		||||
                               }
 | 
			
		||||
                             });
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showMessage: function(userVerifier, message, styleClass) {
 | 
			
		||||
@@ -237,6 +293,7 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._currentQuery = serviceName;
 | 
			
		||||
        this._updateSensitivity(true);
 | 
			
		||||
        this._setWorking(false);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showLoginHint: function(verifier, message) {
 | 
			
		||||
@@ -255,6 +312,7 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
            // the actual reply to GDM will be sent as soon as asked
 | 
			
		||||
            this._firstQuestionAnswer = this._promptEntry.text;
 | 
			
		||||
            this._updateSensitivity(false);
 | 
			
		||||
            this._setWorking(true);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -265,6 +323,7 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
        this._currentQuery = null;
 | 
			
		||||
 | 
			
		||||
        this._updateSensitivity(false);
 | 
			
		||||
        this._setWorking(true);
 | 
			
		||||
 | 
			
		||||
        this._userVerifier.answerQuery(query, this._promptEntry.text);
 | 
			
		||||
    },
 | 
			
		||||
@@ -287,11 +346,14 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
        this._promptEntry.menu.isPassword = true;
 | 
			
		||||
 | 
			
		||||
        this._updateSensitivity(false);
 | 
			
		||||
        this._setWorking(false);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _escape: function() {
 | 
			
		||||
        this._userVerifier.cancel();
 | 
			
		||||
        this.emit('failed');
 | 
			
		||||
        if (this.allowCancel) {
 | 
			
		||||
            this._userVerifier.cancel();
 | 
			
		||||
            this.emit('failed');
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _otherUserClicked: function(button, event) {
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@ const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen';
 | 
			
		||||
const DISABLE_LOG_OUT_KEY = 'disable-log-out';
 | 
			
		||||
const LOCK_ENABLED_KEY = 'lock-enabled';
 | 
			
		||||
const ALWAYS_SHOW_LOG_OUT_KEY = 'always-show-log-out';
 | 
			
		||||
const SHOW_FULL_NAME_KEY = 'show-full-name';
 | 
			
		||||
 | 
			
		||||
const DIALOG_ICON_SIZE = 64;
 | 
			
		||||
 | 
			
		||||
@@ -550,9 +551,12 @@ const UserMenuButton = new Lang.Class({
 | 
			
		||||
                                       Lang.bind(this, this._updateSwitchUser));
 | 
			
		||||
        this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
 | 
			
		||||
                                       Lang.bind(this, this._updateLogout));
 | 
			
		||||
 | 
			
		||||
        this._lockdownSettings.connect('changed::' + DISABLE_LOCK_SCREEN_KEY,
 | 
			
		||||
                                       Lang.bind(this, this._updateLockScreen));
 | 
			
		||||
        this._screenSaverSettings.connect('changed::' + SHOW_FULL_NAME_KEY,
 | 
			
		||||
                                           Lang.bind(this, this._updateUserName));
 | 
			
		||||
        global.settings.connect('changed::' + SHOW_FULL_NAME_KEY,
 | 
			
		||||
                                Lang.bind(this, this._updateUserName));
 | 
			
		||||
        this._updateSwitchUser();
 | 
			
		||||
        this._updateLogout();
 | 
			
		||||
        this._updateLockScreen();
 | 
			
		||||
@@ -597,7 +601,10 @@ const UserMenuButton = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateUserName: function() {
 | 
			
		||||
        if (this._user.is_loaded)
 | 
			
		||||
        let settings = global.settings;
 | 
			
		||||
        if (Main.sessionMode.isLocked)
 | 
			
		||||
            settings = this._screenSaverSettings;
 | 
			
		||||
        if (this._user.is_loaded && settings.get_boolean(SHOW_FULL_NAME_KEY))
 | 
			
		||||
            this._name.set_text(this._user.get_real_name());
 | 
			
		||||
        else
 | 
			
		||||
            this._name.set_text("");
 | 
			
		||||
@@ -752,7 +759,7 @@ const UserMenuButton = new Lang.Class({
 | 
			
		||||
        item = new PopupMenu.PopupSeparatorMenuItem();
 | 
			
		||||
        this.menu.addMenuItem(item);
 | 
			
		||||
 | 
			
		||||
        item = new PopupMenu.PopupMenuItem(_("System Settings"));
 | 
			
		||||
        item = new PopupMenu.PopupMenuItem(_("Settings"));
 | 
			
		||||
        item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
 | 
			
		||||
        this.menu.addMenuItem(item);
 | 
			
		||||
        this._systemSettings = item;
 | 
			
		||||
 
 | 
			
		||||
@@ -84,16 +84,21 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
 | 
			
		||||
        this._workspacesPage = this._addPage(this._workspacesDisplay.actor, null,
 | 
			
		||||
                                             _("Windows"), 'text-x-generic-symbolic');
 | 
			
		||||
                                             _("Windows"), 'emblem-documents-symbolic');
 | 
			
		||||
 | 
			
		||||
        this._appDisplay = new AppDisplay.AllAppDisplay();
 | 
			
		||||
        this._appsPage = this._addPage(this._appDisplay.actor, null,
 | 
			
		||||
                                       _("Applications"), 'system-run-symbolic');
 | 
			
		||||
                                       _("Applications"), 'view-grid-symbolic');
 | 
			
		||||
 | 
			
		||||
        this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
 | 
			
		||||
        this._searchPage = this._addPage(this._searchResults.actor, this._entry,
 | 
			
		||||
                                         _("Search"), 'edit-find-symbolic');
 | 
			
		||||
 | 
			
		||||
        this._searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
 | 
			
		||||
        this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
 | 
			
		||||
        this._searchSettings.connect('changed::disable-external', Lang.bind(this, this._reloadRemoteProviders));
 | 
			
		||||
        this._searchSettings.connect('changed::sort-order', Lang.bind(this, this._reloadRemoteProviders));
 | 
			
		||||
 | 
			
		||||
        // Default search providers
 | 
			
		||||
        // Wanda comes obviously first
 | 
			
		||||
        this.addSearchProvider(new Wanda.WandaSearchProvider());
 | 
			
		||||
@@ -144,15 +149,17 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
        this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
 | 
			
		||||
                                                            coordinate: Clutter.BindCoordinate.HEIGHT });
 | 
			
		||||
 | 
			
		||||
        global.display.add_keybinding('toggle-application-view',
 | 
			
		||||
                                      new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
 | 
			
		||||
                                      Meta.KeyBindingFlags.NONE,
 | 
			
		||||
                                      Lang.bind(this, this._showWithAppsPage));
 | 
			
		||||
        Main.wm.addKeybinding('toggle-application-view',
 | 
			
		||||
                              new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
 | 
			
		||||
                              Meta.KeyBindingFlags.NONE,
 | 
			
		||||
                              Main.KeybindingMode.NORMAL |
 | 
			
		||||
                              Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                              Lang.bind(this, this._toggleAppsPage));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showWithAppsPage: function() {
 | 
			
		||||
    _toggleAppsPage: function() {
 | 
			
		||||
        Main.overview.show();
 | 
			
		||||
        this._showAppsButton.set_checked(true);
 | 
			
		||||
        this._showAppsButton.checked = !this._showAppsButton.checked;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show: function() {
 | 
			
		||||
@@ -196,7 +203,7 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
                                                  })
 | 
			
		||||
                                            });;
 | 
			
		||||
        this._pageArea.add_actor(page);
 | 
			
		||||
        return page
 | 
			
		||||
        return page;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showPage: function(page) {
 | 
			
		||||
@@ -204,18 +211,19 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if(this._activePage) {
 | 
			
		||||
            let oldPage = this._activePage;
 | 
			
		||||
            Tweener.addTween(this._activePage,
 | 
			
		||||
                             { opacity: 0,
 | 
			
		||||
                               time: 0.1,
 | 
			
		||||
                               transition: 'easeOutQuad',
 | 
			
		||||
                               onComplete: Lang.bind(this,
 | 
			
		||||
                                   function() {
 | 
			
		||||
                                       this._activePage.hide();
 | 
			
		||||
                                       this._activePage = page;
 | 
			
		||||
                                       oldPage.hide();
 | 
			
		||||
                                   })
 | 
			
		||||
                             });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._activePage = page;
 | 
			
		||||
        page.show();
 | 
			
		||||
        Tweener.addTween(page,
 | 
			
		||||
                         { opacity: 255,
 | 
			
		||||
@@ -433,7 +441,32 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
        this._showPage(this._searchPage);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _shouldUseSearchProvider: function(provider) {
 | 
			
		||||
        // the disable-external GSetting only affects remote providers
 | 
			
		||||
        if (!provider.isRemoteProvider)
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        if (this._searchSettings.get_boolean('disable-external'))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        let appId = provider.appInfo.get_id();
 | 
			
		||||
        let disable = this._searchSettings.get_strv('disabled');
 | 
			
		||||
        return disable.indexOf(appId) == -1;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _reloadRemoteProviders: function() {
 | 
			
		||||
        // removeSearchProvider() modifies the provider list we iterate on,
 | 
			
		||||
        // so make a copy first
 | 
			
		||||
        let remoteProviders = this._searchSystem.getRemoteProviders().slice(0);
 | 
			
		||||
 | 
			
		||||
        remoteProviders.forEach(Lang.bind(this, this.removeSearchProvider));
 | 
			
		||||
        RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addSearchProvider: function(provider) {
 | 
			
		||||
        if (!this._shouldUseSearchProvider(provider))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._searchSystem.registerProvider(provider);
 | 
			
		||||
        this._searchResults.createProviderMeta(provider);
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,8 @@ const WindowAttentionHandler = new Lang.Class({
 | 
			
		||||
        let [title, banner] = this._getTitleAndBanner(app, window);
 | 
			
		||||
 | 
			
		||||
        let notification = new MessageTray.Notification(source, title, banner);
 | 
			
		||||
        notification.setForFeedback(true);
 | 
			
		||||
 | 
			
		||||
        source.notify(notification);
 | 
			
		||||
 | 
			
		||||
        source.signalIDs.push(window.connect('notify::title', Lang.bind(this, function() {
 | 
			
		||||
 
 | 
			
		||||
@@ -83,6 +83,8 @@ const WindowManager = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._animationBlockCount = 0;
 | 
			
		||||
 | 
			
		||||
        this._allowedKeybindings = {};
 | 
			
		||||
 | 
			
		||||
        this._switchData = null;
 | 
			
		||||
        this._shellwm.connect('kill-switch-workspace', Lang.bind(this, this._switchWorkspaceDone));
 | 
			
		||||
        this._shellwm.connect('kill-window-effects', Lang.bind(this, function (shellwm, actor) {
 | 
			
		||||
@@ -99,38 +101,66 @@ const WindowManager = new Lang.Class({
 | 
			
		||||
        this._shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow));
 | 
			
		||||
        this._shellwm.connect('map', Lang.bind(this, this._mapWindow));
 | 
			
		||||
        this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
 | 
			
		||||
        this._shellwm.connect('filter-keybinding', Lang.bind(this, this._filterKeybinding));
 | 
			
		||||
 | 
			
		||||
        this._workspaceSwitcherPopup = null;
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-to-workspace-left',
 | 
			
		||||
                                            Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-to-workspace-right',
 | 
			
		||||
                                            Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-to-workspace-up',
 | 
			
		||||
                                            Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-to-workspace-down',
 | 
			
		||||
                                            Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('move-to-workspace-left',
 | 
			
		||||
                                            Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('move-to-workspace-right',
 | 
			
		||||
                                            Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('move-to-workspace-up',
 | 
			
		||||
                                            Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('move-to-workspace-down',
 | 
			
		||||
                                            Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-windows',
 | 
			
		||||
                                            Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-group',
 | 
			
		||||
                                            Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-windows-backward',
 | 
			
		||||
                                            Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-group-backward',
 | 
			
		||||
                                            Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        Meta.keybindings_set_custom_handler('switch-panels',
 | 
			
		||||
                                            Lang.bind(this, this._startA11ySwitcher));
 | 
			
		||||
        global.display.add_keybinding('open-application-menu',
 | 
			
		||||
                                      new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
 | 
			
		||||
                                      Meta.KeyBindingFlags.NONE,
 | 
			
		||||
                                      Lang.bind(this, this._openAppMenu));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-to-workspace-left',
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-to-workspace-right',
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-to-workspace-up',
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-to-workspace-down',
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('move-to-workspace-left',
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('move-to-workspace-right',
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('move-to-workspace-up',
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('move-to-workspace-down',
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-windows',
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL,
 | 
			
		||||
                                        Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-group',
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL,
 | 
			
		||||
                                        Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-windows-backward',
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL,
 | 
			
		||||
                                        Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-group-backward',
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL,
 | 
			
		||||
                                        Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-panels',
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW |
 | 
			
		||||
                                        Main.KeybindingMode.LOCK_SCREEN |
 | 
			
		||||
                                        Main.KeybindingMode.UNLOCK_SCREEN |
 | 
			
		||||
                                        Main.KeybindingMode.LOGIN_SCREEN,
 | 
			
		||||
                                        Lang.bind(this, this._startA11ySwitcher));
 | 
			
		||||
 | 
			
		||||
        this.addKeybinding('open-application-menu',
 | 
			
		||||
                           new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
 | 
			
		||||
                           Meta.KeyBindingFlags.NONE,
 | 
			
		||||
                           Main.KeybindingMode.NORMAL,
 | 
			
		||||
                           Lang.bind(this, this._openAppMenu));
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('showing', Lang.bind(this, function() {
 | 
			
		||||
            for (let i = 0; i < this._dimmedWindows.length; i++)
 | 
			
		||||
@@ -142,6 +172,25 @@ const WindowManager = new Lang.Class({
 | 
			
		||||
        }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setCustomKeybindingHandler: function(name, modes, handler) {
 | 
			
		||||
        if (Meta.keybindings_set_custom_handler(name, handler))
 | 
			
		||||
            this.allowKeybinding(name, modes);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addKeybinding: function(name, settings, flags, modes, handler) {
 | 
			
		||||
        if (global.display.add_keybinding(name, settings, flags, handler))
 | 
			
		||||
            this.allowKeybinding(name, modes);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    removeKeybinding: function(name) {
 | 
			
		||||
        if (global.display.remove_keybinding(name))
 | 
			
		||||
            this.allowKeybinding(name, Main.KeybindingMode.NONE);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    allowKeybinding: function(name, modes) {
 | 
			
		||||
        this._allowedKeybindings[name] = modes;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    blockAnimations: function() {
 | 
			
		||||
        this._animationBlockCount++;
 | 
			
		||||
    },
 | 
			
		||||
@@ -424,6 +473,21 @@ const WindowManager = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _filterKeybinding: function(shellwm, binding) {
 | 
			
		||||
        if (Main.keybindingMode == Main.KeybindingMode.NONE)
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        // There's little sense in implementing a keybinding in mutter and
 | 
			
		||||
        // not having it work in NORMAL mode; handle this case generically
 | 
			
		||||
        // so we don't have to explicitly allow all builtin keybindings in
 | 
			
		||||
        // NORMAL mode.
 | 
			
		||||
        if (Main.keybindingMode == Main.KeybindingMode.NORMAL &&
 | 
			
		||||
            binding.is_builtin())
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        return !(this._allowedKeybindings[binding.get_name()] & Main.keybindingMode);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _switchWorkspace : function(shellwm, from, to, direction) {
 | 
			
		||||
        if (!this._shouldAnimate()) {
 | 
			
		||||
            shellwm.completed_switch_workspace();
 | 
			
		||||
 
 | 
			
		||||
@@ -265,23 +265,37 @@ const WindowClone = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _onScroll : function (actor, event) {
 | 
			
		||||
        let direction = event.get_scroll_direction();
 | 
			
		||||
        if (direction == Clutter.ScrollDirection.UP) {
 | 
			
		||||
        let delta;
 | 
			
		||||
 | 
			
		||||
        if (event.is_pointer_emulated())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (direction == Clutter.ScrollDirection.DOWN) {
 | 
			
		||||
            delta = -SCROLL_SCALE_AMOUNT;
 | 
			
		||||
        } else if (direction == Clutter.ScrollDirection.UP) {
 | 
			
		||||
            delta = +SCROLL_SCALE_AMOUNT;
 | 
			
		||||
        } else if (direction == Clutter.ScrollDirection.SMOOTH) {
 | 
			
		||||
            let [dx, dy] = event.get_scroll_delta();
 | 
			
		||||
            delta = -dy * 10;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (delta > 0) {
 | 
			
		||||
            if (this._zoomStep == undefined)
 | 
			
		||||
                this._zoomStart();
 | 
			
		||||
            if (this._zoomStep < 100) {
 | 
			
		||||
                this._zoomStep += SCROLL_SCALE_AMOUNT;
 | 
			
		||||
                this._zoomStep += delta;
 | 
			
		||||
                this._zoomStep = Math.min(100, this._zoomStep);
 | 
			
		||||
                this._zoomUpdate();
 | 
			
		||||
            }
 | 
			
		||||
        } else if (direction == Clutter.ScrollDirection.DOWN) {
 | 
			
		||||
        } else if (delta < 0) {
 | 
			
		||||
            if (this._zoomStep > 0) {
 | 
			
		||||
                this._zoomStep -= SCROLL_SCALE_AMOUNT;
 | 
			
		||||
                this._zoomStep += delta;
 | 
			
		||||
                this._zoomStep = Math.max(0, this._zoomStep);
 | 
			
		||||
                this._zoomUpdate();
 | 
			
		||||
            }
 | 
			
		||||
            if (this._zoomStep <= 0.0)
 | 
			
		||||
                this._zoomEnd();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _zoomUpdate : function () {
 | 
			
		||||
@@ -445,6 +459,9 @@ const WindowOverlay = new Lang.Class({
 | 
			
		||||
        this._parentActor = parentActor;
 | 
			
		||||
        this._hidden = false;
 | 
			
		||||
 | 
			
		||||
        this.borderSize = 0;
 | 
			
		||||
        this.border = new St.Bin({ style_class: 'window-clone-border' });
 | 
			
		||||
 | 
			
		||||
        let title = new St.Label({ style_class: 'window-caption',
 | 
			
		||||
                                   text: metaWindow.title });
 | 
			
		||||
        title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
 | 
			
		||||
@@ -482,11 +499,13 @@ const WindowOverlay = new Lang.Class({
 | 
			
		||||
        this.closeButton = button;
 | 
			
		||||
 | 
			
		||||
        parentActor.add_actor(this.title);
 | 
			
		||||
        parentActor.add_actor(this.border);
 | 
			
		||||
        parentActor.add_actor(this.closeButton);
 | 
			
		||||
        title.connect('style-changed',
 | 
			
		||||
                      Lang.bind(this, this._onStyleChanged));
 | 
			
		||||
        button.connect('style-changed',
 | 
			
		||||
                       Lang.bind(this, this._onStyleChanged));
 | 
			
		||||
        this.border.connect('style-changed', Lang.bind(this, this._onStyleChanged));
 | 
			
		||||
        // force a style change if we are already on a stage - otherwise
 | 
			
		||||
        // the signal will be emitted normally when we are added
 | 
			
		||||
        if (parentActor.get_stage())
 | 
			
		||||
@@ -495,15 +514,17 @@ const WindowOverlay = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    hide: function() {
 | 
			
		||||
        this._hidden = true;
 | 
			
		||||
        this.closeButton.hide();
 | 
			
		||||
        this.title.hide();
 | 
			
		||||
 | 
			
		||||
        this.hideCloseButton();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show: function() {
 | 
			
		||||
        this._hidden = false;
 | 
			
		||||
        if (this._windowClone.actor.has_pointer)
 | 
			
		||||
            this.closeButton.show();
 | 
			
		||||
 | 
			
		||||
        this.title.show();
 | 
			
		||||
        if (this._windowClone.actor.has_pointer)
 | 
			
		||||
            this._animateVisible();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    fadeIn: function() {
 | 
			
		||||
@@ -520,10 +541,14 @@ const WindowOverlay = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    chromeHeights: function () {
 | 
			
		||||
        return [this.closeButton.height - this.closeButton._overlap,
 | 
			
		||||
        return [Math.max(this.borderSize, this.closeButton.height - this.closeButton._overlap),
 | 
			
		||||
                this.title.height + this.title._spacing];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    chromeWidths: function () {
 | 
			
		||||
        return [this.borderSize, this.borderSize];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _repositionSelf: function() {
 | 
			
		||||
        let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
 | 
			
		||||
        this.updatePositions(cloneX, cloneY, cloneWidth, cloneHeight, false);
 | 
			
		||||
@@ -578,16 +603,32 @@ const WindowOverlay = new Lang.Class({
 | 
			
		||||
            title.width = titleWidth;
 | 
			
		||||
            title.set_position(Math.floor(titleX), Math.floor(titleY));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let borderX = cloneX - this.borderSize;
 | 
			
		||||
        let borderY = cloneY - this.borderSize;
 | 
			
		||||
        let borderWidth = cloneWidth + 2 * this.borderSize;
 | 
			
		||||
        let borderHeight = cloneHeight + 2 * this.borderSize;
 | 
			
		||||
 | 
			
		||||
        if (animate) {
 | 
			
		||||
            this._animateOverlayActor(this.border, borderX, borderY,
 | 
			
		||||
                                      borderWidth, borderHeight);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.border.set_position(borderX, borderY);
 | 
			
		||||
            this.border.set_size(borderWidth, borderHeight);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _animateOverlayActor: function(actor, x, y, width) {
 | 
			
		||||
        Tweener.addTween(actor,
 | 
			
		||||
                         { x: x,
 | 
			
		||||
                           y: y,
 | 
			
		||||
                           width: width,
 | 
			
		||||
                           time: Overview.ANIMATION_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad'
 | 
			
		||||
                         });
 | 
			
		||||
    _animateOverlayActor: function(actor, x, y, width, height) {
 | 
			
		||||
        let params = { x: x,
 | 
			
		||||
                       y: y,
 | 
			
		||||
                       width: width,
 | 
			
		||||
                       time: Overview.ANIMATION_TIME,
 | 
			
		||||
                       transition: 'easeOutQuad' };
 | 
			
		||||
 | 
			
		||||
        if (height !== undefined)
 | 
			
		||||
            params.height = height;
 | 
			
		||||
 | 
			
		||||
        Tweener.addTween(actor, params);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _closeWindow: function(actor) {
 | 
			
		||||
@@ -630,6 +671,43 @@ const WindowOverlay = new Lang.Class({
 | 
			
		||||
        this._windowClone.metaWindow.disconnect(this._updateCaptionId);
 | 
			
		||||
        this.title.destroy();
 | 
			
		||||
        this.closeButton.destroy();
 | 
			
		||||
        this.border.destroy();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _animateVisible: function() {
 | 
			
		||||
        this._parentActor.raise_top();
 | 
			
		||||
 | 
			
		||||
        this.closeButton.show();
 | 
			
		||||
        this.closeButton.opacity = 0;
 | 
			
		||||
        Tweener.addTween(this.closeButton,
 | 
			
		||||
                         { opacity: 255,
 | 
			
		||||
                           time: CLOSE_BUTTON_FADE_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad' });
 | 
			
		||||
 | 
			
		||||
        this.border.show();
 | 
			
		||||
        this.border.opacity = 0;
 | 
			
		||||
        Tweener.addTween(this.border,
 | 
			
		||||
                         { opacity: 255,
 | 
			
		||||
                           time: CLOSE_BUTTON_FADE_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad' });
 | 
			
		||||
 | 
			
		||||
        this.title.add_style_pseudo_class('hover');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _animateInvisible: function() {
 | 
			
		||||
        this.closeButton.opacity = 255;
 | 
			
		||||
        Tweener.addTween(this.closeButton,
 | 
			
		||||
                         { opacity: 0,
 | 
			
		||||
                           time: CLOSE_BUTTON_FADE_TIME,
 | 
			
		||||
                           transition: 'easeInQuad' });
 | 
			
		||||
 | 
			
		||||
        this.border.opacity = 255;
 | 
			
		||||
        Tweener.addTween(this.border,
 | 
			
		||||
                         { opacity: 0,
 | 
			
		||||
                           time: CLOSE_BUTTON_FADE_TIME,
 | 
			
		||||
                           transition: 'easeInQuad' });
 | 
			
		||||
 | 
			
		||||
        this.title.remove_style_pseudo_class('hover');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onEnter: function() {
 | 
			
		||||
@@ -639,8 +717,8 @@ const WindowOverlay = new Lang.Class({
 | 
			
		||||
        // are shown again
 | 
			
		||||
        if (this._hidden)
 | 
			
		||||
            return;
 | 
			
		||||
        this._parentActor.raise_top();
 | 
			
		||||
        this.closeButton.show();
 | 
			
		||||
 | 
			
		||||
        this._animateVisible();
 | 
			
		||||
        this.emit('show-close-button');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -651,9 +729,10 @@ const WindowOverlay = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _idleToggleCloseButton: function() {
 | 
			
		||||
        this._idleToggleCloseId = 0;
 | 
			
		||||
 | 
			
		||||
        if (!this._windowClone.actor.has_pointer &&
 | 
			
		||||
            !this.closeButton.has_pointer)
 | 
			
		||||
            this.closeButton.hide();
 | 
			
		||||
            this._animateInvisible();
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
@@ -664,6 +743,8 @@ const WindowOverlay = new Lang.Class({
 | 
			
		||||
            this._idleToggleCloseId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        this.closeButton.hide();
 | 
			
		||||
        this.border.hide();
 | 
			
		||||
        this.title.remove_style_pseudo_class('hover');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onStyleChanged: function() {
 | 
			
		||||
@@ -673,6 +754,9 @@ const WindowOverlay = new Lang.Class({
 | 
			
		||||
        let closeNode = this.closeButton.get_theme_node();
 | 
			
		||||
        this.closeButton._overlap = closeNode.get_length('-shell-close-overlap');
 | 
			
		||||
 | 
			
		||||
        let borderNode = this.border.get_theme_node();
 | 
			
		||||
        this.borderSize = borderNode.get_border_width(St.Side.TOP);
 | 
			
		||||
 | 
			
		||||
        this._parentActor.queue_relayout();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -1623,20 +1707,25 @@ const Workspace = new Lang.Class({
 | 
			
		||||
            return [];
 | 
			
		||||
 | 
			
		||||
        let closeButtonHeight, captionHeight;
 | 
			
		||||
        let leftBorder, rightBorder;
 | 
			
		||||
        if (this._windowOverlays.length) {
 | 
			
		||||
            // All of the overlays have the same chrome sizes,
 | 
			
		||||
            // so just pick the first one.
 | 
			
		||||
            let overlay = this._windowOverlays[0];
 | 
			
		||||
            [closeButtonHeight, captionHeight] = overlay.chromeHeights();
 | 
			
		||||
            [leftBorder, rightBorder] = overlay.chromeWidths();
 | 
			
		||||
        } else {
 | 
			
		||||
            [closeButtonHeight, captionHeight] = [0, 0];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        rowSpacing += captionHeight;
 | 
			
		||||
        columnSpacing += rightBorder;
 | 
			
		||||
 | 
			
		||||
        let area = { x: this._x, y: this._y, width: this._width, height: this._height };
 | 
			
		||||
        area.y += closeButtonHeight;
 | 
			
		||||
        area.height -= closeButtonHeight;
 | 
			
		||||
        area.x += leftBorder;
 | 
			
		||||
        area.width -= leftBorder;
 | 
			
		||||
 | 
			
		||||
        if (!this._currentLayout)
 | 
			
		||||
            this._currentLayout = this._computeLayout(windows, area, rowSpacing, columnSpacing, captionHeight);
 | 
			
		||||
 
 | 
			
		||||
@@ -205,11 +205,11 @@ const WorkspacesView = new Lang.Class({
 | 
			
		||||
            this._workspaces[w].positionWindows(Workspace.WindowPositionFlags.ANIMATE);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _scrollToActive: function(showAnimation) {
 | 
			
		||||
    _scrollToActive: function() {
 | 
			
		||||
        let active = global.screen.get_active_workspace_index();
 | 
			
		||||
 | 
			
		||||
        this._updateWorkspaceActors(showAnimation);
 | 
			
		||||
        this._updateScrollAdjustment(active, showAnimation);
 | 
			
		||||
        this._updateWorkspaceActors(true);
 | 
			
		||||
        this._updateScrollAdjustment(active);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Update workspace actors parameters
 | 
			
		||||
@@ -267,26 +267,21 @@ const WorkspacesView = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateScrollAdjustment: function(index, showAnimation) {
 | 
			
		||||
    _updateScrollAdjustment: function(index) {
 | 
			
		||||
        if (this._scrolling)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._animatingScroll = true;
 | 
			
		||||
 | 
			
		||||
        if (showAnimation) {
 | 
			
		||||
            Tweener.addTween(this.scrollAdjustment, {
 | 
			
		||||
               value: index,
 | 
			
		||||
               time: WORKSPACE_SWITCH_TIME,
 | 
			
		||||
               transition: 'easeOutQuad',
 | 
			
		||||
               onComplete: Lang.bind(this,
 | 
			
		||||
                   function() {
 | 
			
		||||
                       this._animatingScroll = false;
 | 
			
		||||
                   })
 | 
			
		||||
            });
 | 
			
		||||
        } else {
 | 
			
		||||
            this.scrollAdjustment.value = index;
 | 
			
		||||
            this._animatingScroll = false;
 | 
			
		||||
        }
 | 
			
		||||
        Tweener.addTween(this.scrollAdjustment, {
 | 
			
		||||
            value: index,
 | 
			
		||||
            time: WORKSPACE_SWITCH_TIME,
 | 
			
		||||
            transition: 'easeOutQuad',
 | 
			
		||||
            onComplete: Lang.bind(this,
 | 
			
		||||
                                  function() {
 | 
			
		||||
                                      this._animatingScroll = false;
 | 
			
		||||
                                  })
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces) {
 | 
			
		||||
@@ -313,7 +308,7 @@ const WorkspacesView = new Lang.Class({
 | 
			
		||||
        if (this._scrolling)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._scrollToActive(true);
 | 
			
		||||
        this._scrollToActive();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDestroy: function() {
 | 
			
		||||
@@ -387,24 +382,11 @@ const WorkspacesView = new Lang.Class({
 | 
			
		||||
        this._scrolling = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    endSwipeScroll: function(result) {
 | 
			
		||||
    endSwipeScroll: function() {
 | 
			
		||||
        this._scrolling = false;
 | 
			
		||||
 | 
			
		||||
        if (result == Overview.SwipeScrollResult.CLICK) {
 | 
			
		||||
            let [x, y, mod] = global.get_pointer();
 | 
			
		||||
            let actor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
 | 
			
		||||
                                                      x, y);
 | 
			
		||||
 | 
			
		||||
            // 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 active = global.screen.get_active_workspace_index();
 | 
			
		||||
            if (this._workspaces[active].isEmpty() &&
 | 
			
		||||
                this.actor.contains(actor))
 | 
			
		||||
                Main.overview.hide();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Make sure title captions etc are shown as necessary
 | 
			
		||||
        this._scrollToActive();
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -456,9 +438,23 @@ const WorkspacesDisplay = new Lang.Class({
 | 
			
		||||
        this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
 | 
			
		||||
        this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
 | 
			
		||||
        this.actor.connect('allocate', Lang.bind(this, this._allocate));
 | 
			
		||||
        this.actor.connect('notify::mapped', Lang.bind(this, this._setupSwipeScrolling));
 | 
			
		||||
        this.actor.connect('parent-set', Lang.bind(this, this._parentSet));
 | 
			
		||||
        this.actor.set_clip_to_allocation(true);
 | 
			
		||||
        let action = new Clutter.PanAction();
 | 
			
		||||
        action.connect('pan', Lang.bind(this, this._onPan));
 | 
			
		||||
        action.connect('gesture-begin', Lang.bind(this, function() {
 | 
			
		||||
            for (let i = 0; i < this._workspacesViews.length; i++)
 | 
			
		||||
                this._workspacesViews[i].startSwipeScroll();
 | 
			
		||||
            return true;
 | 
			
		||||
        }));
 | 
			
		||||
        action.connect('gesture-end', Lang.bind(this, function() {
 | 
			
		||||
            for (let i = 0; i < this._workspacesViews.length; i++)
 | 
			
		||||
                this._workspacesViews[i].endSwipeScroll();
 | 
			
		||||
        }));
 | 
			
		||||
        Main.overview.addAction(action);
 | 
			
		||||
        this.actor.connect('notify::mapped', Lang.bind(this, function() {
 | 
			
		||||
            action.enabled = this.actor.mapped;
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        let controls = new St.Bin({ style_class: 'workspace-controls',
 | 
			
		||||
                                    request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT,
 | 
			
		||||
@@ -531,6 +527,13 @@ const WorkspacesDisplay = new Lang.Class({
 | 
			
		||||
            Lang.bind(this, this._updateSwitcherVisibility));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onPan: function(action) {
 | 
			
		||||
        let [dist, dx, dy] = action.get_motion_delta(0);
 | 
			
		||||
        let adjustment = this._scrollAdjustment;
 | 
			
		||||
        adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateSwitcherVisibility: function() {
 | 
			
		||||
        this._thumbnailsBox.actor.visible =
 | 
			
		||||
            this._settings.get_boolean('dynamic-workspaces') ||
 | 
			
		||||
@@ -640,33 +643,6 @@ const WorkspacesDisplay = new Lang.Class({
 | 
			
		||||
            }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setupSwipeScrolling: function() {
 | 
			
		||||
        if (this._swipeScrollBeginId)
 | 
			
		||||
            Main.overview.disconnect(this._swipeScrollBeginId);
 | 
			
		||||
        this._swipeScrollBeginId = 0;
 | 
			
		||||
 | 
			
		||||
        if (this._swipeScrollEndId)
 | 
			
		||||
            Main.overview.disconnect(this._swipeScrollEndId);
 | 
			
		||||
        this._swipeScrollEndId = 0;
 | 
			
		||||
 | 
			
		||||
        if (!this.actor.mapped)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let direction = Overview.SwipeScrollDirection.VERTICAL;
 | 
			
		||||
        Main.overview.setScrollAdjustment(this._scrollAdjustment,
 | 
			
		||||
                                          direction);
 | 
			
		||||
        this._swipeScrollBeginId = Main.overview.connect('swipe-scroll-begin',
 | 
			
		||||
            Lang.bind(this, function() {
 | 
			
		||||
                for (let i = 0; i < this._workspacesViews.length; i++)
 | 
			
		||||
                    this._workspacesViews[i].startSwipeScroll();
 | 
			
		||||
            }));
 | 
			
		||||
        this._swipeScrollEndId = Main.overview.connect('swipe-scroll-end',
 | 
			
		||||
           Lang.bind(this, function(overview, result) {
 | 
			
		||||
                for (let i = 0; i < this._workspacesViews.length; i++)
 | 
			
		||||
                    this._workspacesViews[i].endSwipeScroll(result);
 | 
			
		||||
           }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _workspacesOnlyOnPrimaryChanged: function() {
 | 
			
		||||
        this._workspacesOnlyOnPrimary = this._settings.get_boolean('workspaces-only-on-primary');
 | 
			
		||||
 | 
			
		||||
@@ -706,7 +682,6 @@ const WorkspacesDisplay = new Lang.Class({
 | 
			
		||||
                this._scrollAdjustment = view.scrollAdjustment;
 | 
			
		||||
                this._scrollAdjustment.connect('notify::value',
 | 
			
		||||
                                               Lang.bind(this, this._scrollValueChanged));
 | 
			
		||||
                this._setupSwipeScrolling();
 | 
			
		||||
            }
 | 
			
		||||
            this._workspacesViews.push(view);
 | 
			
		||||
        }
 | 
			
		||||
@@ -863,8 +838,9 @@ const WorkspacesDisplay = new Lang.Class({
 | 
			
		||||
        let clipX = rtl ? x + controlsVisible : x;
 | 
			
		||||
        let clipY = y + (fullHeight - clipHeight) / 2;
 | 
			
		||||
 | 
			
		||||
        let overviewSpacing = Main.overview._spacing;
 | 
			
		||||
        let widthAdjust = this._zoomOut ? controlsNatural : controlsVisible;
 | 
			
		||||
        widthAdjust += Main.overview._spacing;
 | 
			
		||||
        widthAdjust += overviewSpacing;
 | 
			
		||||
        width -= widthAdjust;
 | 
			
		||||
        if (rtl)
 | 
			
		||||
            x += widthAdjust;
 | 
			
		||||
@@ -882,10 +858,10 @@ const WorkspacesDisplay = new Lang.Class({
 | 
			
		||||
                                                     monitors[i].y,
 | 
			
		||||
                                                     monitors[i].width,
 | 
			
		||||
                                                     monitors[i].height);
 | 
			
		||||
                this._workspacesViews[m].setGeometry(monitors[i].x,
 | 
			
		||||
                                                     monitors[i].y,
 | 
			
		||||
                                                     monitors[i].width,
 | 
			
		||||
                                                     monitors[i].height);
 | 
			
		||||
                this._workspacesViews[m].setGeometry(monitors[i].x + overviewSpacing/2,
 | 
			
		||||
                                                     monitors[i].y + overviewSpacing/2,
 | 
			
		||||
                                                     monitors[i].width - overviewSpacing,
 | 
			
		||||
                                                     monitors[i].height - overviewSpacing);
 | 
			
		||||
                m++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +1,19 @@
 | 
			
		||||
dist_man_MANS = gnome-shell.1
 | 
			
		||||
XSLTPROC_FLAGS = \
 | 
			
		||||
        --nonet \
 | 
			
		||||
        --stringparam man.output.quietly 1 \
 | 
			
		||||
        --stringparam funcsynopsis.style ansi \
 | 
			
		||||
        --stringparam man.th.extra1.suppress 1 \
 | 
			
		||||
        --stringparam man.authors.section.enabled 0 \
 | 
			
		||||
        --stringparam man.copyright.section.enabled 0
 | 
			
		||||
 | 
			
		||||
.xml.1:
 | 
			
		||||
	$(AM_V_GEN) $(XSLTPROC) $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
 | 
			
		||||
 | 
			
		||||
man_MANS = \
 | 
			
		||||
	gnome-shell.1
 | 
			
		||||
 | 
			
		||||
xml_files = $(man_MANS:.1=.xml)
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST = $(xml_files)
 | 
			
		||||
 | 
			
		||||
DISTCLEANFILES = $(man_MANS)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,94 +0,0 @@
 | 
			
		||||
.\" Copyright (c) 2009, Marcelo Jorge Vieira (metal) <metal@alucinados.com>
 | 
			
		||||
.\"
 | 
			
		||||
.\" This is free documentation; you can redistribute it and/or
 | 
			
		||||
.\" modify it under the terms of the GNU General Public License as
 | 
			
		||||
.\" published by the Free Software Foundation; either version 2 of
 | 
			
		||||
.\" the License, or (at your option) any later version.
 | 
			
		||||
.\"
 | 
			
		||||
.\" The GNU General Public License's references to "object code"
 | 
			
		||||
.\" and "executables" are to be interpreted as the output of any
 | 
			
		||||
.\" document formatting or typesetting system, including
 | 
			
		||||
.\" intermediate and printed output.
 | 
			
		||||
.\"
 | 
			
		||||
.\" This manual is distributed in the hope that it will be useful,
 | 
			
		||||
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
.\" GNU General Public License for more details.
 | 
			
		||||
.\"
 | 
			
		||||
.\" You should have received a copy of the GNU General Public
 | 
			
		||||
.\" License along with this manual; if not, write to the Free
 | 
			
		||||
.\" Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 | 
			
		||||
.\" Boston, MA  02111-1301  USA.
 | 
			
		||||
.TH GNOME-SHELL 1
 | 
			
		||||
.SH NAME
 | 
			
		||||
gnome-shell \- Graphical shell for the GNOME desktop
 | 
			
		||||
 | 
			
		||||
.SH SYNOPSIS
 | 
			
		||||
.B gnome-shell [options]
 | 
			
		||||
 | 
			
		||||
.SH DESCRIPTION
 | 
			
		||||
GNOME Shell provides core user interface functions for the GNOME 3
 | 
			
		||||
desktop, like switching to windows and launching applications. GNOME
 | 
			
		||||
Shell takes advantage of the capabilities of modern graphics hardware
 | 
			
		||||
and introduces innovative user interface concepts to provide a
 | 
			
		||||
visually attractive and easy to use experience.
 | 
			
		||||
 | 
			
		||||
.SH OPTIONS
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B \-\-replace
 | 
			
		||||
Replace the running window manager
 | 
			
		||||
.br
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B \-\-sm-disable
 | 
			
		||||
Disable connection to the session manager
 | 
			
		||||
.br
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B \-\-sm-client-id=ID
 | 
			
		||||
Specify session management ID
 | 
			
		||||
.br
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B \-\-sm-save-file=FILE
 | 
			
		||||
Initialize session from savefile
 | 
			
		||||
.br
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B \-\-screen=SCREEN
 | 
			
		||||
X screen to use
 | 
			
		||||
.br
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B \-d, \-\-display=DISPLAY
 | 
			
		||||
X display to use
 | 
			
		||||
.br
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B \-\-sync
 | 
			
		||||
Make X calls synchronous
 | 
			
		||||
.br
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B \-\-version
 | 
			
		||||
Print version and exit
 | 
			
		||||
.br
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B \-\-help
 | 
			
		||||
Display help and exit
 | 
			
		||||
.br
 | 
			
		||||
 | 
			
		||||
.SH BUGS
 | 
			
		||||
The bug tracker can be reached by visiting the website
 | 
			
		||||
\fIhttps://bugzilla.gnome.org/buglist.cgi?product=gnome-shell\fR
 | 
			
		||||
 | 
			
		||||
Before sending a bug report, please verify that you have the latest
 | 
			
		||||
version of gnome-shell. Many bugs (major and minor) are fixed at each
 | 
			
		||||
release, and if yours is out of date, the problem may already have
 | 
			
		||||
been solved.
 | 
			
		||||
 | 
			
		||||
.SH ADDITIONAL INFORMATION
 | 
			
		||||
 | 
			
		||||
For further information, visit the website \fIhttp://live.gnome.org/GnomeShell\fR
 | 
			
		||||
							
								
								
									
										159
									
								
								man/gnome-shell.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								man/gnome-shell.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,159 @@
 | 
			
		||||
<?xml version='1.0'?>
 | 
			
		||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
 | 
			
		||||
        "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
 | 
			
		||||
 | 
			
		||||
<refentry id="gnome-shell">
 | 
			
		||||
 | 
			
		||||
        <refentryinfo>
 | 
			
		||||
                <title>gnome-shell</title>
 | 
			
		||||
                <productname>gnome-shell</productname>
 | 
			
		||||
 | 
			
		||||
                <authorgroup>
 | 
			
		||||
                        <author>
 | 
			
		||||
                                <contrib>wrote the original gnome-shell man page</contrib>
 | 
			
		||||
                                <firstname>Marcelo Jorge</firstname>
 | 
			
		||||
                                <surname>Vieira</surname>
 | 
			
		||||
                                <email>metal@alucinados.com</email>
 | 
			
		||||
                        </author>
 | 
			
		||||
                </authorgroup>
 | 
			
		||||
 | 
			
		||||
        </refentryinfo>
 | 
			
		||||
 | 
			
		||||
        <refmeta>
 | 
			
		||||
                <refentrytitle>gnome-shell</refentrytitle>
 | 
			
		||||
                <manvolnum>1</manvolnum>
 | 
			
		||||
        </refmeta>
 | 
			
		||||
 | 
			
		||||
        <refnamediv>
 | 
			
		||||
                <refname>gnome-shell</refname>
 | 
			
		||||
                <refpurpose>Graphical shell for the GNOME desktop</refpurpose>
 | 
			
		||||
        </refnamediv>
 | 
			
		||||
 | 
			
		||||
        <refsynopsisdiv>
 | 
			
		||||
                <cmdsynopsis>
 | 
			
		||||
                        <command>gnome-shell <arg choice="opt" rep="repeat">OPTION</arg></command>
 | 
			
		||||
                </cmdsynopsis>
 | 
			
		||||
        </refsynopsisdiv>
 | 
			
		||||
 | 
			
		||||
        <refsect1>
 | 
			
		||||
                <title>Description</title>
 | 
			
		||||
 | 
			
		||||
                <para>GNOME shell provides core user
 | 
			
		||||
                interface functions for the GNOME 3 desktop, like switching
 | 
			
		||||
                to windows and launching applications. GNOME shell takes
 | 
			
		||||
                advantage of the capabilities of modern graphics hardware
 | 
			
		||||
                and introduces innovative user interface concepts to provide
 | 
			
		||||
                a visually attractive and easy to use experience.</para>
 | 
			
		||||
 | 
			
		||||
                <para>gnome-shell is a required component of
 | 
			
		||||
                the GNOME desktop, i.e. it is listed in the
 | 
			
		||||
                RequiredComponents field of
 | 
			
		||||
                <filename>/usr/share/gnome-session/sessions/gnome.session</filename>.
 | 
			
		||||
                It is started in the window manager phase of the session.
 | 
			
		||||
                </para>
 | 
			
		||||
 | 
			
		||||
        </refsect1>
 | 
			
		||||
 | 
			
		||||
        <refsect1>
 | 
			
		||||
                <title>Options</title>
 | 
			
		||||
 | 
			
		||||
                <variablelist>
 | 
			
		||||
 | 
			
		||||
                        <varlistentry>
 | 
			
		||||
                                <term><option>-r</option>, <option>--replace</option></term>
 | 
			
		||||
 | 
			
		||||
                                <listitem><para>Replace the running window manager</para></listitem>
 | 
			
		||||
                        </varlistentry>
 | 
			
		||||
 | 
			
		||||
                        <varlistentry>
 | 
			
		||||
                                <term><option>--sm-disable</option></term>
 | 
			
		||||
 | 
			
		||||
                                <listitem><para>Disable connection to the session manager</para></listitem>
 | 
			
		||||
                        </varlistentry>
 | 
			
		||||
 | 
			
		||||
                        <varlistentry>
 | 
			
		||||
                                <term><option>--sm-client-id=<replaceable>ID</replaceable></option></term>
 | 
			
		||||
 | 
			
		||||
                                <listitem><para>Specify session management <replaceable>ID</replaceable></para></listitem>
 | 
			
		||||
                        </varlistentry>
 | 
			
		||||
 | 
			
		||||
                        <varlistentry>
 | 
			
		||||
                                <term><option>--sm-save-file=<replaceable>FILE</replaceable></option></term>
 | 
			
		||||
 | 
			
		||||
                                <listitem><para>Initialize session from <replaceable>FILE</replaceable></para></listitem>
 | 
			
		||||
                        </varlistentry>
 | 
			
		||||
 | 
			
		||||
                        <varlistentry>
 | 
			
		||||
                                <term><option>--screen=<replaceable>SCREEN</replaceable></option></term>
 | 
			
		||||
 | 
			
		||||
                                <listitem><para>X screen to use</para></listitem>
 | 
			
		||||
                        </varlistentry>
 | 
			
		||||
 | 
			
		||||
                        <varlistentry>
 | 
			
		||||
                                <term><option>-d</option>, <option>--display=<replaceable>DISPLAY</replaceable></option></term>
 | 
			
		||||
 | 
			
		||||
                                <listitem><para>X Display to use</para></listitem>
 | 
			
		||||
                        </varlistentry>
 | 
			
		||||
 | 
			
		||||
                        <varlistentry>
 | 
			
		||||
                                <term><option>--sync</option></term>
 | 
			
		||||
 | 
			
		||||
                                <listitem><para>Make X calls synchronous</para></listitem>
 | 
			
		||||
                        </varlistentry>
 | 
			
		||||
 | 
			
		||||
                        <varlistentry>
 | 
			
		||||
                                <term><option>--version</option></term>
 | 
			
		||||
 | 
			
		||||
                                <listitem><para>Print version and exit</para></listitem>
 | 
			
		||||
                        </varlistentry>
 | 
			
		||||
 | 
			
		||||
                        <varlistentry>
 | 
			
		||||
                                <term><option>--help</option></term>
 | 
			
		||||
 | 
			
		||||
                                <listitem><para>Display help and exit</para></listitem>
 | 
			
		||||
                        </varlistentry>
 | 
			
		||||
 | 
			
		||||
                        <varlistentry>
 | 
			
		||||
                                <term><option>--mode=<replaceable>MODE</replaceable></option></term>
 | 
			
		||||
 | 
			
		||||
                                <listitem><para>Use a specific mode, e.g. "gdm" for login screen</para></listitem>
 | 
			
		||||
                        </varlistentry>
 | 
			
		||||
 | 
			
		||||
                        <varlistentry>
 | 
			
		||||
                                <term><option>--list-modes</option></term>
 | 
			
		||||
 | 
			
		||||
                                <listitem><para>List possible modes and exit</para></listitem>
 | 
			
		||||
                        </varlistentry>
 | 
			
		||||
 | 
			
		||||
                </variablelist>
 | 
			
		||||
 | 
			
		||||
        </refsect1>
 | 
			
		||||
 | 
			
		||||
        <refsect1>
 | 
			
		||||
                <title>Files</title>
 | 
			
		||||
 | 
			
		||||
                <para>
 | 
			
		||||
                        <filename>/usr/share/gnome-session/sessions/gnome.session</filename>,
 | 
			
		||||
                        <filename>/usr/share/applications/gnome-shell.desktop</filename>.</para>
 | 
			
		||||
        </refsect1>
 | 
			
		||||
 | 
			
		||||
        <refsect1>
 | 
			
		||||
                <title>Bugs</title>
 | 
			
		||||
 | 
			
		||||
                <para>The bug tracker can be reached by visiting the
 | 
			
		||||
                website <ulink url="https://bugzilla.gnome.org/buglist.cgi?product=gnome-shell">https://bugzilla.gnome.org/buglist.cgi?product=gnome-shell</ulink>.
 | 
			
		||||
                Before sending a bug report, please verify that you have
 | 
			
		||||
                the latest version of gnome-shell. Many bugs (major and
 | 
			
		||||
                minor) are fixed at each release, and if yours is out of
 | 
			
		||||
                date, the problem may already have been solved.</para>
 | 
			
		||||
 | 
			
		||||
        </refsect1>
 | 
			
		||||
 | 
			
		||||
        <refsect1>
 | 
			
		||||
                <title>Additional Information</title>
 | 
			
		||||
 | 
			
		||||
                <para>For further information, visit the website
 | 
			
		||||
                <ulink url="http://live.gnome.org/GnomeShell">http://live.gnome.org/GnomeShell</ulink>.</para>
 | 
			
		||||
        </refsect1>
 | 
			
		||||
 | 
			
		||||
</refentry>
 | 
			
		||||
							
								
								
									
										194
									
								
								po/de.po
									
									
									
									
									
								
							
							
						
						
									
										194
									
								
								po/de.po
									
									
									
									
									
								
							@@ -19,9 +19,9 @@ msgstr ""
 | 
			
		||||
"Project-Id-Version: gnome-shell master\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
 | 
			
		||||
"shell&keywords=I18N+L10N&component=general\n"
 | 
			
		||||
"POT-Creation-Date: 2012-10-14 16:48+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2012-10-10 23:10+0100\n"
 | 
			
		||||
"Last-Translator: Tobias Endrigkeit <tobiasendrigkeit@googlemail.com>\n"
 | 
			
		||||
"POT-Creation-Date: 2012-11-06 04:39+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2012-11-06 20:04+0100\n"
 | 
			
		||||
"Last-Translator: Wolfgang Stoeggl <c72578@yahoo.de>\n"
 | 
			
		||||
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
 | 
			
		||||
"Language: \n"
 | 
			
		||||
"MIME-Version: 1.0\n"
 | 
			
		||||
@@ -148,56 +148,68 @@ msgstr ""
 | 
			
		||||
"Aufzählung entnommen."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:13
 | 
			
		||||
msgid "Always show the 'Log out' menuitem in the user menu."
 | 
			
		||||
msgstr "Den Menüeintrag »Abmelden« immer im Benutzermenü anzeigen."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:14
 | 
			
		||||
msgid ""
 | 
			
		||||
"This key overrides the automatic hiding of the 'Log out' menuitem in single-"
 | 
			
		||||
"user, single-session situations."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Dieser Schlüssel überschreibt das automatische Verbergen des Menüeintrags "
 | 
			
		||||
"»Abmelden« in Einzelbenutzer, Einzelsitzungssituationen."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
 | 
			
		||||
msgid "Show the week date in the calendar"
 | 
			
		||||
msgstr "Wochentag im Kalender anzeigen"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:14
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16
 | 
			
		||||
msgid "If true, display the ISO week date in the calendar."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Wenn dieser Wert gesetzt ist, wird der ISO-Wochentag im Kalender angezeigt."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17
 | 
			
		||||
msgid "Keybinding to open the application menu"
 | 
			
		||||
msgstr "Tastenkombination zum Öffnen des Anwendungsmenüs"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
 | 
			
		||||
msgid "Keybinding to open the application menu."
 | 
			
		||||
msgstr "Tastenkombination zum Öffnen des Anwendungsmenüs."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
 | 
			
		||||
msgid "Keybinding to toggle the visibility of the message tray"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Tastenkombination zum Umschalten der Sichtbarkeit des Benachrichtigungsfeldes"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20
 | 
			
		||||
msgid "Keybinding to toggle the visibility of the message tray."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Tastenkombination zum Umschalten der Sichtbarkeit des "
 | 
			
		||||
"Benachrichtigungsfeldes."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21
 | 
			
		||||
msgid "Keybinding to toggle the screen recorder"
 | 
			
		||||
msgstr "Tastenkombination zum Umschalten des Bildschirmaufzeichners"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22
 | 
			
		||||
msgid "Keybinding to start/stop the builtin screen recorder."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Tastenkombination zum Starten/Entfernen des eingebauten "
 | 
			
		||||
"Bildschirmaufzeichners."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
 | 
			
		||||
msgid "Which keyboard to use"
 | 
			
		||||
msgstr "Zu verwendende Tastatur"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24
 | 
			
		||||
msgid "The type of keyboard to use."
 | 
			
		||||
msgstr "Der Typ der zu verwendenden Tastatur"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
 | 
			
		||||
msgid "Framerate used for recording screencasts."
 | 
			
		||||
msgstr "Bildwiederholungsrate zur Aufnahme von Screencasts"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26
 | 
			
		||||
msgid ""
 | 
			
		||||
"The framerate of the resulting screencast recordered by GNOME Shell's "
 | 
			
		||||
"screencast recorder in frames-per-second."
 | 
			
		||||
@@ -206,11 +218,11 @@ msgstr ""
 | 
			
		||||
"der GNOME-Shell aufgezeichnet werden soll, in Einzelbildern pro Sekunde."
 | 
			
		||||
 | 
			
		||||
# hmm Enkodieren oder Kodieren?
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
 | 
			
		||||
msgid "The gstreamer pipeline used to encode the screencast"
 | 
			
		||||
msgstr "Die GStreamer-Weiterleitung zur Enkodierung des Screencasts"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
 | 
			
		||||
#, no-c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
 | 
			
		||||
@@ -238,11 +250,11 @@ msgstr ""
 | 
			
		||||
"aufzeichnet. %T wird als Platzhalter für die vermutete optimale Thread-"
 | 
			
		||||
"Anzahl auf dem System verwendet."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30
 | 
			
		||||
msgid "File extension used for storing the screencast"
 | 
			
		||||
msgstr "Die Dateiendung zum Speichern des Screencast"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31
 | 
			
		||||
msgid ""
 | 
			
		||||
"The filename for recorded screencasts will be a unique filename based on the "
 | 
			
		||||
"current date, and use this extension. It should be changed when recording to "
 | 
			
		||||
@@ -303,8 +315,8 @@ msgstr "Anmeldefenster"
 | 
			
		||||
msgid "Power"
 | 
			
		||||
msgstr "Ausschalten"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/powerMenu.js:89 ../js/ui/userMenu.js:660 ../js/ui/userMenu.js:664
 | 
			
		||||
#: ../js/ui/userMenu.js:775
 | 
			
		||||
#: ../js/gdm/powerMenu.js:89 ../js/ui/userMenu.js:664 ../js/ui/userMenu.js:668
 | 
			
		||||
#: ../js/ui/userMenu.js:779
 | 
			
		||||
msgid "Suspend"
 | 
			
		||||
msgstr "Bereitschaft"
 | 
			
		||||
 | 
			
		||||
@@ -312,8 +324,8 @@ msgstr "Bereitschaft"
 | 
			
		||||
msgid "Restart"
 | 
			
		||||
msgstr "Neu starten"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/powerMenu.js:99 ../js/ui/userMenu.js:662 ../js/ui/userMenu.js:664
 | 
			
		||||
#: ../js/ui/userMenu.js:774
 | 
			
		||||
#: ../js/gdm/powerMenu.js:99 ../js/ui/userMenu.js:666 ../js/ui/userMenu.js:668
 | 
			
		||||
#: ../js/ui/userMenu.js:778
 | 
			
		||||
msgid "Power Off"
 | 
			
		||||
msgstr "Ausschalten"
 | 
			
		||||
 | 
			
		||||
@@ -698,35 +710,35 @@ msgstr "Stumm"
 | 
			
		||||
#. Translators: this is a time format string followed by a date.
 | 
			
		||||
#. If applicable, replace %X with a strftime format valid for your
 | 
			
		||||
#. locale, without seconds.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:948
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:952
 | 
			
		||||
#, no-c-format
 | 
			
		||||
msgid "Sent at <b>%X</b> on <b>%A</b>"
 | 
			
		||||
msgstr "Gesendet am <b>%A</b> um <b>%X</b> "
 | 
			
		||||
 | 
			
		||||
#. Translators: this is a time format in the style of "Wednesday, May 25",
 | 
			
		||||
#. shown when you get a chat message in the same year.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:954
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:958
 | 
			
		||||
#, no-c-format
 | 
			
		||||
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
 | 
			
		||||
msgstr "Gesendet am <b>%A</b>, <b>%d. %B</b>"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
 | 
			
		||||
#. shown when you get a chat message in a different year.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:959
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:963
 | 
			
		||||
#, no-c-format
 | 
			
		||||
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
 | 
			
		||||
msgstr "Gesendet am <b>%A</b>, <b>%d. %B</b> %Y"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is the other person changing their old IM name to their new
 | 
			
		||||
#. IM name.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:988
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:992
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s is now known as %s"
 | 
			
		||||
msgstr "%s heißt jetzt %s"
 | 
			
		||||
 | 
			
		||||
#. translators: argument is a room name like
 | 
			
		||||
#. * room@jabber.org for example.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1088
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1092
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Invitation to %s"
 | 
			
		||||
msgstr "Einladung zum Betreten von %s"
 | 
			
		||||
@@ -734,42 +746,42 @@ msgstr "Einladung zum Betreten von %s"
 | 
			
		||||
#. translators: first argument is the name of a contact and the second
 | 
			
		||||
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
 | 
			
		||||
#. * for example.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1096
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1100
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s is inviting you to join %s"
 | 
			
		||||
msgstr "%s lädt Sie ein, %s beizutreten"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1098
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1177
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1240
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1102
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1181
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1244
 | 
			
		||||
msgid "Decline"
 | 
			
		||||
msgstr "Ablehnen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1099
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1178
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1241
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1103
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1182
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1245
 | 
			
		||||
msgid "Accept"
 | 
			
		||||
msgstr "Annehmen"
 | 
			
		||||
 | 
			
		||||
#. translators: argument is a contact name like Alice for example.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1129
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1133
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Video call from %s"
 | 
			
		||||
msgstr "Video-Anruf von %s"
 | 
			
		||||
 | 
			
		||||
#. translators: argument is a contact name like Alice for example.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1132
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1136
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Call from %s"
 | 
			
		||||
msgstr "Anruf von %s"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1137
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1141
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:346
 | 
			
		||||
msgid "Reject"
 | 
			
		||||
msgstr "Abweisen"
 | 
			
		||||
 | 
			
		||||
#. translators: this is a button label (verb), not a noun
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1139
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1143
 | 
			
		||||
msgid "Answer"
 | 
			
		||||
msgstr "Antworten"
 | 
			
		||||
 | 
			
		||||
@@ -778,113 +790,113 @@ msgstr "Antworten"
 | 
			
		||||
#. * file name. The string will be something
 | 
			
		||||
#. * like: "Alice is sending you test.ogg"
 | 
			
		||||
#.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1171
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1175
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s is sending you %s"
 | 
			
		||||
msgstr "%s sendet Ihnen %s"
 | 
			
		||||
 | 
			
		||||
#. To translators: The parameter is the contact's alias
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1206
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1210
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s would like permission to see when you are online"
 | 
			
		||||
msgstr "%s bittet um das Recht, Ihre Online-Verfügbarkeit sehen zu dürfen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1298
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1302
 | 
			
		||||
msgid "Network error"
 | 
			
		||||
msgstr "Netzwerkfehler"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1300
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1304
 | 
			
		||||
msgid "Authentication failed"
 | 
			
		||||
msgstr "Legitimierung fehlgeschlagen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1302
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1306
 | 
			
		||||
msgid "Encryption error"
 | 
			
		||||
msgstr "Verschlüsselungsfehler"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1304
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1308
 | 
			
		||||
msgid "Certificate not provided"
 | 
			
		||||
msgstr "Zertifikat wurde nicht bereitgestellt"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1306
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1310
 | 
			
		||||
msgid "Certificate untrusted"
 | 
			
		||||
msgstr "Zertifikat nicht vertrauenswürdig"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1308
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1312
 | 
			
		||||
msgid "Certificate expired"
 | 
			
		||||
msgstr "Zertifikat abgelaufen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1310
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1314
 | 
			
		||||
msgid "Certificate not activated"
 | 
			
		||||
msgstr "Zertifikat nicht aktiviert"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1312
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1316
 | 
			
		||||
msgid "Certificate hostname mismatch"
 | 
			
		||||
msgstr "Rechnername des Zertifikats stimmt nicht überein"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1314
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1318
 | 
			
		||||
msgid "Certificate fingerprint mismatch"
 | 
			
		||||
msgstr "Fingerabdruck des Zertifikats stimmt nicht überein"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1316
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1320
 | 
			
		||||
msgid "Certificate self-signed"
 | 
			
		||||
msgstr "Selbstsigniertes Zertifikat"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1318
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1322
 | 
			
		||||
msgid "Status is set to offline"
 | 
			
		||||
msgstr "Der Status ist auf »Abgemeldet« gesetzt"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1320
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1324
 | 
			
		||||
msgid "Encryption is not available"
 | 
			
		||||
msgstr "Verschlüsselung ist nicht verfügbar"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1322
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1326
 | 
			
		||||
msgid "Certificate is invalid"
 | 
			
		||||
msgstr "Zertifikat ist ungültig"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1324
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1328
 | 
			
		||||
msgid "Connection has been refused"
 | 
			
		||||
msgstr "Verbindungsaufbau wurde verweigert"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1326
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1330
 | 
			
		||||
msgid "Connection can't be established"
 | 
			
		||||
msgstr "Verbindung kann nicht hergestellt werden"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1328
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1332
 | 
			
		||||
msgid "Connection has been lost"
 | 
			
		||||
msgstr "Verbindung wurde unterbrochen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1330
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1334
 | 
			
		||||
msgid "This account is already connected to the server"
 | 
			
		||||
msgstr "Dieses Konto ist bereits mit dem Server verbunden"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1332
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1336
 | 
			
		||||
msgid ""
 | 
			
		||||
"Connection has been replaced by a new connection using the same resource"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Die Verbindung wurde durch eine neue Verbindung mit der gleichen Ressource "
 | 
			
		||||
"ersetzt"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1334
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1338
 | 
			
		||||
msgid "The account already exists on the server"
 | 
			
		||||
msgstr "Dieses Konto ist bereits auf dem Server vorhanden"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1336
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1340
 | 
			
		||||
msgid "Server is currently too busy to handle the connection"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Der Server ist derzeit überlastet und kann die Verbindung nicht annehmen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1338
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1342
 | 
			
		||||
msgid "Certificate has been revoked"
 | 
			
		||||
msgstr "Zertifikat wurde zurückgezogen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1340
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1344
 | 
			
		||||
msgid ""
 | 
			
		||||
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Das Zertifikat verwendet einen unsicheren Chiffrier-Algorithmus oder ist "
 | 
			
		||||
"kryptografisch schwach"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1342
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1346
 | 
			
		||||
msgid ""
 | 
			
		||||
"The length of the server certificate, or the depth of the server certificate "
 | 
			
		||||
"chain, exceed the limits imposed by the cryptography library"
 | 
			
		||||
@@ -893,26 +905,26 @@ msgstr ""
 | 
			
		||||
"überschreiten die durch die kryptografische Bibliothek gegebenen "
 | 
			
		||||
"Beschränkungen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1344
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1348
 | 
			
		||||
msgid "Internal error"
 | 
			
		||||
msgstr "Interner Fehler"
 | 
			
		||||
 | 
			
		||||
#. translators: argument is the account name, like
 | 
			
		||||
#. * name@jabber.org for example.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1354
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1358
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Connection to %s failed"
 | 
			
		||||
msgstr "Verbindung zu %s ist fehlgeschlagen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1363
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1367
 | 
			
		||||
msgid "Reconnect"
 | 
			
		||||
msgstr "Erneut verbinden"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1364
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1368
 | 
			
		||||
msgid "Edit account"
 | 
			
		||||
msgstr "Konto bearbeiten"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1409
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1413
 | 
			
		||||
msgid "Unknown reason"
 | 
			
		||||
msgstr "Unbekannter Grund"
 | 
			
		||||
 | 
			
		||||
@@ -1095,23 +1107,23 @@ msgstr "Quelle zeigen"
 | 
			
		||||
msgid "Web Page"
 | 
			
		||||
msgstr "Webseite"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:1081
 | 
			
		||||
#: ../js/ui/messageTray.js:1084
 | 
			
		||||
msgid "Open"
 | 
			
		||||
msgstr "Öffnen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:1088
 | 
			
		||||
#: ../js/ui/messageTray.js:1091
 | 
			
		||||
msgid "Remove"
 | 
			
		||||
msgstr "Entfernen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:1540
 | 
			
		||||
#: ../js/ui/messageTray.js:1543
 | 
			
		||||
msgid "Message Tray"
 | 
			
		||||
msgstr "Benachrichtigungsfeld"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:2547
 | 
			
		||||
#: ../js/ui/messageTray.js:2549
 | 
			
		||||
msgid "System Information"
 | 
			
		||||
msgstr "Systeminformationen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/notificationDaemon.js:506 ../src/shell-app.c:373
 | 
			
		||||
#: ../js/ui/notificationDaemon.js:506 ../src/shell-app.c:374
 | 
			
		||||
msgctxt "program"
 | 
			
		||||
msgid "Unknown"
 | 
			
		||||
msgstr "Unbekannt"
 | 
			
		||||
@@ -1171,18 +1183,18 @@ msgstr "Bitte geben Sie einen Befehl ein:"
 | 
			
		||||
# %B - ausgeschriebener Name des Monats, abhängig von der gesetzten Umgebung
 | 
			
		||||
#. Translators: This is a time format for a date in
 | 
			
		||||
#. long format
 | 
			
		||||
#: ../js/ui/screenShield.js:79
 | 
			
		||||
#: ../js/ui/screenShield.js:80
 | 
			
		||||
msgid "%A, %B %d"
 | 
			
		||||
msgstr "%A, %d. %B"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/screenShield.js:143
 | 
			
		||||
#: ../js/ui/screenShield.js:144
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%d new message"
 | 
			
		||||
msgid_plural "%d new messages"
 | 
			
		||||
msgstr[0] "%d neue Nachricht"
 | 
			
		||||
msgstr[1] "%d neue Nachrichten"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/screenShield.js:145
 | 
			
		||||
#: ../js/ui/screenShield.js:146
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%d new notification"
 | 
			
		||||
msgid_plural "%d new notifications"
 | 
			
		||||
@@ -1638,59 +1650,59 @@ msgstr "Mikrofon"
 | 
			
		||||
msgid "Log in as another user"
 | 
			
		||||
msgstr "Als anderer Benutzer anmelden"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:180
 | 
			
		||||
#: ../js/ui/userMenu.js:181
 | 
			
		||||
msgid "Available"
 | 
			
		||||
msgstr "Verfügbar"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:183
 | 
			
		||||
#: ../js/ui/userMenu.js:184
 | 
			
		||||
msgid "Busy"
 | 
			
		||||
msgstr "Beschäftigt"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:186
 | 
			
		||||
#: ../js/ui/userMenu.js:187
 | 
			
		||||
msgid "Invisible"
 | 
			
		||||
msgstr "Unsichtbar"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:189
 | 
			
		||||
#: ../js/ui/userMenu.js:190
 | 
			
		||||
msgid "Away"
 | 
			
		||||
msgstr "Abwesend"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:192
 | 
			
		||||
#: ../js/ui/userMenu.js:193
 | 
			
		||||
msgid "Idle"
 | 
			
		||||
msgstr "Untätig"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:195
 | 
			
		||||
#: ../js/ui/userMenu.js:196
 | 
			
		||||
msgid "Unavailable"
 | 
			
		||||
msgstr "Nicht verfügbar"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:740
 | 
			
		||||
#: ../js/ui/userMenu.js:744
 | 
			
		||||
msgid "Notifications"
 | 
			
		||||
msgstr "Benachrichtigungen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:748
 | 
			
		||||
#: ../js/ui/userMenu.js:752
 | 
			
		||||
msgid "System Settings"
 | 
			
		||||
msgstr "Systemeinstellungen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:756
 | 
			
		||||
#: ../js/ui/userMenu.js:760
 | 
			
		||||
msgid "Switch User"
 | 
			
		||||
msgstr "Benutzer wechseln"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:761
 | 
			
		||||
#: ../js/ui/userMenu.js:765
 | 
			
		||||
msgid "Log Out"
 | 
			
		||||
msgstr "Abmelden"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:766
 | 
			
		||||
#: ../js/ui/userMenu.js:770
 | 
			
		||||
msgid "Lock"
 | 
			
		||||
msgstr "Sperren"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:781
 | 
			
		||||
#: ../js/ui/userMenu.js:785
 | 
			
		||||
msgid "Install Updates & Restart"
 | 
			
		||||
msgstr "Aktualisierungen installieren und neustarten"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:799
 | 
			
		||||
#: ../js/ui/userMenu.js:803
 | 
			
		||||
msgid "Your chat status will be set to busy"
 | 
			
		||||
msgstr "Ihr Anwesenheitsstatus wird auf »Beschäftigt« gesetzt"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:800
 | 
			
		||||
#: ../js/ui/userMenu.js:804
 | 
			
		||||
msgid ""
 | 
			
		||||
"Notifications are now disabled, including chat messages. Your online status "
 | 
			
		||||
"has been adjusted to let others know that you might not see their messages."
 | 
			
		||||
@@ -1777,7 +1789,7 @@ msgstr ""
 | 
			
		||||
msgid "List possible modes"
 | 
			
		||||
msgstr "Die möglichen Modi auflisten"
 | 
			
		||||
 | 
			
		||||
#: ../src/shell-app.c:621
 | 
			
		||||
#: ../src/shell-app.c:622
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Failed to launch '%s'"
 | 
			
		||||
msgstr "»%s« konnte nicht gestartet werden"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										158
									
								
								po/et.po
									
									
									
									
									
								
							
							
						
						
									
										158
									
								
								po/et.po
									
									
									
									
									
								
							@@ -13,8 +13,8 @@ msgstr ""
 | 
			
		||||
"Project-Id-Version: gnome-shell MASTER\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
 | 
			
		||||
"shell&keywords=I18N+L10N&component=general\n"
 | 
			
		||||
"POT-Creation-Date: 2012-09-22 22:24+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2012-09-23 08:48+0300\n"
 | 
			
		||||
"POT-Creation-Date: 2012-11-16 18:27+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2012-11-16 20:40+0300\n"
 | 
			
		||||
"Last-Translator: Mattias Põldaru <mahfiaz@gmail.com>\n"
 | 
			
		||||
"Language-Team: Estonian <>\n"
 | 
			
		||||
"Language: et\n"
 | 
			
		||||
@@ -37,6 +37,15 @@ msgstr "Arvuti"
 | 
			
		||||
msgid "Show the message tray"
 | 
			
		||||
msgstr "Teateala näitamine"
 | 
			
		||||
 | 
			
		||||
msgid "Focus the active notification"
 | 
			
		||||
msgstr "Aktiivse märguande fokuseerimine"
 | 
			
		||||
 | 
			
		||||
msgid "Show all applications"
 | 
			
		||||
msgstr "Kõigi rakenduste kuvamine"
 | 
			
		||||
 | 
			
		||||
msgid "Open the application menu"
 | 
			
		||||
msgstr "Rakenduste menüü avamine"
 | 
			
		||||
 | 
			
		||||
msgid "GNOME Shell"
 | 
			
		||||
msgstr "GNOME Shell"
 | 
			
		||||
 | 
			
		||||
@@ -116,6 +125,16 @@ msgstr ""
 | 
			
		||||
"Kasutatakse kasutaja poolt viimati vahetult määratud kiirsuhtluse oleku "
 | 
			
		||||
"salvestamiseks. See väärtus pärineb GsmPresenceStatus nummerdusest."
 | 
			
		||||
 | 
			
		||||
msgid "Always show the 'Log out' menuitem in the user menu."
 | 
			
		||||
msgstr "Kasutajamenüüs näidatakse alati 'Logi välja' menüükirjet."
 | 
			
		||||
 | 
			
		||||
msgid ""
 | 
			
		||||
"This key overrides the automatic hiding of the 'Log out' menuitem in single-"
 | 
			
		||||
"user, single-session situations."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"See võti keelab automaatse 'Logi välja' menüükirje peitmise, kui arvutis on "
 | 
			
		||||
"üks kasutaja ning avatud üks seanss."
 | 
			
		||||
 | 
			
		||||
msgid "Show the week date in the calendar"
 | 
			
		||||
msgstr "Kalendris näidatakse kuupäeva nädalavormingus"
 | 
			
		||||
 | 
			
		||||
@@ -128,12 +147,25 @@ msgstr "Rakenduste menüü avamise kiirklahv"
 | 
			
		||||
msgid "Keybinding to open the application menu."
 | 
			
		||||
msgstr "Kiirklahv  rakenduste menüü avamiseks."
 | 
			
		||||
 | 
			
		||||
msgid "Keybinding to open the \"Show Applications\" view"
 | 
			
		||||
msgstr "\"Rakenduste vaate\" avamise kiirklahv"
 | 
			
		||||
 | 
			
		||||
msgid ""
 | 
			
		||||
"Keybinding to open the \"Show Applications\" view of the Activities Overview."
 | 
			
		||||
msgstr "\"Rakenduste vaate\" avamise kiirklahv tegevuste ülevaates."
 | 
			
		||||
 | 
			
		||||
msgid "Keybinding to toggle the visibility of the message tray"
 | 
			
		||||
msgstr "Teateala nähtavuse muutmise kiirklahv"
 | 
			
		||||
 | 
			
		||||
msgid "Keybinding to toggle the visibility of the message tray."
 | 
			
		||||
msgstr "Kiirklahv teateala nähtavuse muutmiseks."
 | 
			
		||||
 | 
			
		||||
msgid "Keybinding to focus the active notification"
 | 
			
		||||
msgstr "Aktiivse teate fokuseerimise kiirklahv"
 | 
			
		||||
 | 
			
		||||
msgid "Keybinding to focus the active notification."
 | 
			
		||||
msgstr "Aktiivse teate fokuseerimise kiirklahv."
 | 
			
		||||
 | 
			
		||||
msgid "Keybinding to toggle the screen recorder"
 | 
			
		||||
msgstr "Erkaanilindistaja lülitamise kiirklahv"
 | 
			
		||||
 | 
			
		||||
@@ -195,6 +227,34 @@ msgstr ""
 | 
			
		||||
"konteinervormingusse salvestades tuleks ka sellele vormingule vastav laiend "
 | 
			
		||||
"määrata."
 | 
			
		||||
 | 
			
		||||
msgid "Attach modal dialog to the parent window"
 | 
			
		||||
msgstr "Modaaldialoog kuulub vanemakna juurde"
 | 
			
		||||
 | 
			
		||||
msgid ""
 | 
			
		||||
"This key overrides the key in org.gnome.mutter when running GNOME Shell."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"See võti on ülimuslik võtme org.gnome.mutter suhtes, kui kasutatakse GNOME "
 | 
			
		||||
"Shelli."
 | 
			
		||||
 | 
			
		||||
msgid "Arrangement of buttons on the titlebar"
 | 
			
		||||
msgstr "Nuppude järjekord tiitliribal"
 | 
			
		||||
 | 
			
		||||
msgid ""
 | 
			
		||||
"This key overrides the key in org.gnome.desktop.wm.preferences when running "
 | 
			
		||||
"GNOME Shell."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"See võti on ülimuslik võtme org.gnome.desktop.wm.preferences suhtes, kui "
 | 
			
		||||
"kasutatakse GNOME Shelli."
 | 
			
		||||
 | 
			
		||||
msgid "Enable edge tiling when dropping windows on screen edges"
 | 
			
		||||
msgstr "Akende lohistamisel ekraani serva lubatakse serva paigutamine"
 | 
			
		||||
 | 
			
		||||
msgid "Workspaces are managed dynamically"
 | 
			
		||||
msgstr "Tööalasid hallatakse dünaamiliselt"
 | 
			
		||||
 | 
			
		||||
msgid "Workspaces only on primary monitor"
 | 
			
		||||
msgstr "Tööalad peamisel monitoril"
 | 
			
		||||
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "There was an error loading the preferences dialog for %s:"
 | 
			
		||||
msgstr "%s jaoks eelistuste dialoogi laadimisel esines viga:"
 | 
			
		||||
@@ -225,9 +285,22 @@ msgctxt "button"
 | 
			
		||||
msgid "Sign In"
 | 
			
		||||
msgstr "Logi sisse"
 | 
			
		||||
 | 
			
		||||
msgid "Next"
 | 
			
		||||
msgstr "Järgmine"
 | 
			
		||||
 | 
			
		||||
#. TTLS and PEAP are actually much more complicated, but this complication
 | 
			
		||||
#. is not visible here since we only care about phase2 authentication
 | 
			
		||||
#. (and don't even care of which one)
 | 
			
		||||
msgid "Username: "
 | 
			
		||||
msgstr "Kasutajanimi: "
 | 
			
		||||
 | 
			
		||||
msgid "Login Window"
 | 
			
		||||
msgstr "Sisselogimisaken"
 | 
			
		||||
 | 
			
		||||
#. Translators: accessible name of the power menu in the login screen
 | 
			
		||||
msgid "Power"
 | 
			
		||||
msgstr "Vool"
 | 
			
		||||
 | 
			
		||||
msgid "Suspend"
 | 
			
		||||
msgstr "Uinak"
 | 
			
		||||
 | 
			
		||||
@@ -437,12 +510,6 @@ msgstr "Parool: "
 | 
			
		||||
msgid "Key: "
 | 
			
		||||
msgstr "Võti: "
 | 
			
		||||
 | 
			
		||||
#. TTLS and PEAP are actually much more complicated, but this complication
 | 
			
		||||
#. is not visible here since we only care about phase2 authentication
 | 
			
		||||
#. (and don't even care of which one)
 | 
			
		||||
msgid "Username: "
 | 
			
		||||
msgstr "Kasutajanimi: "
 | 
			
		||||
 | 
			
		||||
msgid "Identity: "
 | 
			
		||||
msgstr "Identiteet: "
 | 
			
		||||
 | 
			
		||||
@@ -533,24 +600,27 @@ msgstr "Heli peale"
 | 
			
		||||
msgid "Mute"
 | 
			
		||||
msgstr "Heli maha"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is a time format string followed by a date.
 | 
			
		||||
#. If applicable, replace %X with a strftime format valid for your
 | 
			
		||||
#. locale, without seconds.
 | 
			
		||||
#. Translators: this is a time format string followed by the word "Yesterday". i.e. "14:30 on Yesterday"
 | 
			
		||||
#, no-c-format
 | 
			
		||||
msgid "Sent at <b>%X</b> on <b>%A</b>"
 | 
			
		||||
msgstr "Saadetud: <b>%A</b>, <b>%X</b>"
 | 
			
		||||
msgid "<b>%H:%M</b> on Yesterday"
 | 
			
		||||
msgstr "Eile <b>%H:%M</b>"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is a time format in the style of "Wednesday, May 25",
 | 
			
		||||
#. shown when you get a chat message in the same year.
 | 
			
		||||
#. Translators: this is a time format string followed by a week day name. i.e. "14:30 on Monday
 | 
			
		||||
#, no-c-format
 | 
			
		||||
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
 | 
			
		||||
msgstr "Saadeti <b>%A</b>, <b>%B %d</b>"
 | 
			
		||||
msgid "<b>%H:%M</b> on <b>%A</b>"
 | 
			
		||||
msgstr "<b>%H:%M</b>, <b>%A</b>"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
 | 
			
		||||
#. shown when you get a chat message in a different year.
 | 
			
		||||
#. Translators: this is a time format in the style of "14:30 on Wednesday, May 25",
 | 
			
		||||
#. shown when you get a chat message in the same year
 | 
			
		||||
#, no-c-format
 | 
			
		||||
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
 | 
			
		||||
msgstr "Saadeti <b>%A</b>, <b>%B %d</b>, %Y"
 | 
			
		||||
msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>"
 | 
			
		||||
msgstr "<b>%H:%M</b>, <b>%A</b>, <b>%d. %B</b>"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is a time format in the style of "14:30 on Wednesday, May 25, 2012",
 | 
			
		||||
#. shown when you get a chat message in a different year
 | 
			
		||||
#, no-c-format
 | 
			
		||||
msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>, %Y"
 | 
			
		||||
msgstr "<b>%H:%M</b>, <b>%A</b>, <b>%d. %B</b> %Y"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is the other person changing their old IM name to their new
 | 
			
		||||
#. IM name.
 | 
			
		||||
@@ -587,9 +657,6 @@ msgstr "%s tahab alustada videokõnet"
 | 
			
		||||
msgid "Call from %s"
 | 
			
		||||
msgstr "%s helistab"
 | 
			
		||||
 | 
			
		||||
msgid "Reject"
 | 
			
		||||
msgstr "Lükka tagasi"
 | 
			
		||||
 | 
			
		||||
#. translators: this is a button label (verb), not a noun
 | 
			
		||||
msgid "Answer"
 | 
			
		||||
msgstr "Vasta"
 | 
			
		||||
@@ -897,8 +964,11 @@ msgstr "Ülemine riba"
 | 
			
		||||
msgid "toggle-switch-us"
 | 
			
		||||
msgstr "toggle-switch-intl"
 | 
			
		||||
 | 
			
		||||
msgid "Please enter a command:"
 | 
			
		||||
msgstr "Palun sisesta käsk:"
 | 
			
		||||
msgid "Enter a Command"
 | 
			
		||||
msgstr "Palun sisesta käsk"
 | 
			
		||||
 | 
			
		||||
msgid "Close"
 | 
			
		||||
msgstr "Sulge"
 | 
			
		||||
 | 
			
		||||
#. Translators: This is a time format for a date in
 | 
			
		||||
#. long format
 | 
			
		||||
@@ -1011,16 +1081,6 @@ msgstr "ühendumine..."
 | 
			
		||||
msgid "Send Files..."
 | 
			
		||||
msgstr "Failide saatmine..."
 | 
			
		||||
 | 
			
		||||
msgid "Browse Files..."
 | 
			
		||||
msgstr "Failide sirvimine..."
 | 
			
		||||
 | 
			
		||||
msgid "Error browsing device"
 | 
			
		||||
msgstr "Viga seadme sirvimisel"
 | 
			
		||||
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "The requested device cannot be browsed, error is '%s'"
 | 
			
		||||
msgstr "Küsitud seadet pole võimalik sirvida, viga on '%s'"
 | 
			
		||||
 | 
			
		||||
msgid "Keyboard Settings"
 | 
			
		||||
msgstr "Klaviatuurisätted"
 | 
			
		||||
 | 
			
		||||
@@ -1044,6 +1104,9 @@ msgstr "Luba alati"
 | 
			
		||||
msgid "Grant this time only"
 | 
			
		||||
msgstr "Luba ainult seekord"
 | 
			
		||||
 | 
			
		||||
msgid "Reject"
 | 
			
		||||
msgstr "Lükka tagasi"
 | 
			
		||||
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Pairing confirmation for %s"
 | 
			
		||||
msgstr "Paardumise kinnitus seadmele %s"
 | 
			
		||||
@@ -1154,9 +1217,6 @@ msgstr "Juhtmeta"
 | 
			
		||||
msgid "Mobile broadband"
 | 
			
		||||
msgstr "Mobiiliühendus"
 | 
			
		||||
 | 
			
		||||
msgid "VPN Connections"
 | 
			
		||||
msgstr "VPN-ühendused"
 | 
			
		||||
 | 
			
		||||
msgid "Network Settings"
 | 
			
		||||
msgstr "Võrgusätted"
 | 
			
		||||
 | 
			
		||||
@@ -1274,20 +1334,17 @@ msgstr "Eemal"
 | 
			
		||||
msgid "Idle"
 | 
			
		||||
msgstr "Jõude"
 | 
			
		||||
 | 
			
		||||
msgid "Unavailable"
 | 
			
		||||
msgstr "Pole saadaval"
 | 
			
		||||
 | 
			
		||||
msgid "Switch User"
 | 
			
		||||
msgstr "Vaheta kasutajat"
 | 
			
		||||
 | 
			
		||||
msgid "Switch Session"
 | 
			
		||||
msgstr "Vaheta seanssi"
 | 
			
		||||
msgid "Offline"
 | 
			
		||||
msgstr "Ühendamata"
 | 
			
		||||
 | 
			
		||||
msgid "Notifications"
 | 
			
		||||
msgstr "Märguanded"
 | 
			
		||||
 | 
			
		||||
msgid "System Settings"
 | 
			
		||||
msgstr "Süsteemi sätted"
 | 
			
		||||
msgid "Settings"
 | 
			
		||||
msgstr "Sätted"
 | 
			
		||||
 | 
			
		||||
msgid "Switch User"
 | 
			
		||||
msgstr "Vaheta kasutajat"
 | 
			
		||||
 | 
			
		||||
msgid "Log Out"
 | 
			
		||||
msgstr "Logi välja"
 | 
			
		||||
@@ -1404,9 +1461,6 @@ msgstr "Kasutaja katkestas autentimisdialoogi"
 | 
			
		||||
#~ msgid "If true, display date in the clock, in addition to time."
 | 
			
		||||
#~ msgstr "Kui määratud, siis kuvatakse kellaaja kõrval ka kuupäeva."
 | 
			
		||||
 | 
			
		||||
#~ msgid "Offline"
 | 
			
		||||
#~ msgstr "Ühendamata"
 | 
			
		||||
 | 
			
		||||
#~ msgid "CONTACTS"
 | 
			
		||||
#~ msgstr "KONTAKTID"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										111
									
								
								po/ml.po
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								po/ml.po
									
									
									
									
									
								
							@@ -11,15 +11,15 @@ msgstr ""
 | 
			
		||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug."
 | 
			
		||||
"cgi?product=gnome-shell&keywords=I18N+L10N&component=general\n"
 | 
			
		||||
"POT-Creation-Date: 2012-09-20 16:11+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2012-09-20 22:56+0000\n"
 | 
			
		||||
"Last-Translator: Ani Peter <apeter@redhat.com>\n"
 | 
			
		||||
"PO-Revision-Date: 2012-11-26 15:02+0530\n"
 | 
			
		||||
"Last-Translator: Ani Peter <peter.ani@gmail.com>\n"
 | 
			
		||||
"Language-Team: Malayalam <discuss@lists.smc.org.in>\n"
 | 
			
		||||
"Language: ml\n"
 | 
			
		||||
"MIME-Version: 1.0\n"
 | 
			
		||||
"Content-Type: text/plain; charset=UTF-8\n"
 | 
			
		||||
"Content-Transfer-Encoding: 8bit\n"
 | 
			
		||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
 | 
			
		||||
"X-Generator: Lokalize 1.0\n"
 | 
			
		||||
"X-Generator: Lokalize 1.5\n"
 | 
			
		||||
"X-DamnedLies-Scope: partial\n"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-gnome-shell-screenshot.xml.in.h:1
 | 
			
		||||
@@ -61,7 +61,8 @@ msgstr "ഗ്നോം ഷെല് എക്സ്റ്റെന്ഷ
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:1
 | 
			
		||||
msgid "Enable internal tools useful for developers and testers from Alt-F2"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Alt-F2-ല് ഡവലപ്പര്മാര്ക്കും ടെസ്റ്റേര്സിനും പ്രയോജനകരമായ ആന്തരിക പ്രയോഗങ്ങള് പ്രവര്ത്തന "
 | 
			
		||||
"Alt-F2-ല് ഡവലപ്പര്മാര്ക്കും ടെസ്റ്റേര്സിനും പ്രയോജനകരമായ ആന്തരിക "
 | 
			
		||||
"പ്രയോഗങ്ങള് പ്രവര്ത്തന "
 | 
			
		||||
"സജ്ജമാക്കുന്നു"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:2
 | 
			
		||||
@@ -69,7 +70,8 @@ msgid ""
 | 
			
		||||
"Allows access to internal debugging and monitoring tools using the Alt-F2 "
 | 
			
		||||
"dialog."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Alt-F2 ഡയലോഗ് ഉപയോഗിച്ചു് ആന്തരിക ഡീബഗ്ഗിലേക്കും നീരീക്ഷണ പ്രയോഗങ്ങളിലേക്കും പ്രവേശനം "
 | 
			
		||||
"Alt-F2 ഡയലോഗ് ഉപയോഗിച്ചു് ആന്തരിക ഡീബഗ്ഗിലേക്കും നീരീക്ഷണ പ്രയോഗങ്ങളിലേക്കും "
 | 
			
		||||
"പ്രവേശനം "
 | 
			
		||||
"അനുവദിയ്ക്കുക."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:3
 | 
			
		||||
@@ -83,14 +85,19 @@ msgid ""
 | 
			
		||||
"list. You can also manipulate this list with the EnableExtension and "
 | 
			
		||||
"DisableExtension DBus methods on org.gnome.Shell."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"ഗ്നോം ഷെല് എക്സ്റ്റെന്ഷനുകള്ക്കു് ഒരു യുയുഐഡി വിശേഷതയുണ്ടു്; ലഭ്യമാക്കേണ്ട എക്സ്റ്റെന്ഷനുകള് ഈ കീ പട്ടിക "
 | 
			
		||||
"ലഭ്യമാക്കുന്നു. ലഭ്യമാക്കേണ്ട ഏതു് എക്സ്റ്റെന്ഷനും ഈ പട്ടികയിലുണ്ടാവണം. org.gnome.Shell-ല് "
 | 
			
		||||
"നിങ്ങള്ക്കു് EnableExtension, DisableExtension എന്നീ ഡീബസ് രീതികളിലൂടെ ഈ പട്ടിക "
 | 
			
		||||
"ഗ്നോം ഷെല് എക്സ്റ്റെന്ഷനുകള്ക്കു് ഒരു യുയുഐഡി വിശേഷതയുണ്ടു്; ലഭ്യമാക്കേണ്ട "
 | 
			
		||||
"എക്സ്റ്റെന്ഷനുകള് ഈ കീ പട്ടിക "
 | 
			
		||||
"ലഭ്യമാക്കുന്നു. ലഭ്യമാക്കേണ്ട ഏതു് എക്സ്റ്റെന്ഷനും ഈ പട്ടികയിലുണ്ടാവണം. "
 | 
			
		||||
"org.gnome.Shell-ല് "
 | 
			
		||||
"നിങ്ങള്ക്കു് EnableExtension, DisableExtension എന്നീ ഡീബസ് രീതികളിലൂടെ ഈ "
 | 
			
		||||
"പട്ടിക "
 | 
			
		||||
"കൈകാര്യം ചെയ്യുവാനും സാധിയ്ക്കുന്നു."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:5
 | 
			
		||||
msgid "Whether to collect stats about applications usage"
 | 
			
		||||
msgstr "പ്രയോഗങ്ങളുടെ ഉപയോഗത്തെപ്പറ്റിയുള്ള സ്ഥിതിവിവരക്കണക്കുകള് ശേഖരിയ്ക്കണമോ എന്നു്"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"പ്രയോഗങ്ങളുടെ ഉപയോഗത്തെപ്പറ്റിയുള്ള സ്ഥിതിവിവരക്കണക്കുകള് ശേഖരിയ്ക്കണമോ "
 | 
			
		||||
"എന്നു്"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:6
 | 
			
		||||
msgid ""
 | 
			
		||||
@@ -99,9 +106,12 @@ msgid ""
 | 
			
		||||
"want to disable this for privacy reasons. Please note that doing so won't "
 | 
			
		||||
"remove already saved data."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"ഏറ്റവും കൂടുതല് തവണ ഉപയോഗിയ്ക്കുന്ന പ്രയോഗങ്ങള് ലഭ്യമാക്കുന്നതിനായി ഷെല് സാധാരണയായി സജീവമായ "
 | 
			
		||||
"പ്രയോഗങ്ങളെ നിരീക്ഷിയ്ക്കുന്നു. (ഉദാഹരണത്തിനു്, ലോഞ്ചേര്സ്). ഈ ഡേറ്റാ സ്വകാര്യമായി "
 | 
			
		||||
"സൂക്ഷിയ്ക്കുന്നെങ്കിലും, ചില കാരണങ്ങളാല് ഇതു് പ്രവര്ത്തന രഹിതമാക്കേണ്ടതുണ്ടു്. ഇങ്ങനെ ചെയ്യുന്നതു് "
 | 
			
		||||
"ഏറ്റവും കൂടുതല് തവണ ഉപയോഗിയ്ക്കുന്ന പ്രയോഗങ്ങള് ലഭ്യമാക്കുന്നതിനായി ഷെല് "
 | 
			
		||||
"സാധാരണയായി സജീവമായ "
 | 
			
		||||
"പ്രയോഗങ്ങളെ നിരീക്ഷിയ്ക്കുന്നു. (ഉദാഹരണത്തിനു്, ലോഞ്ചേര്സ്). ഈ ഡേറ്റാ "
 | 
			
		||||
"സ്വകാര്യമായി "
 | 
			
		||||
"സൂക്ഷിയ്ക്കുന്നെങ്കിലും, ചില കാരണങ്ങളാല് ഇതു് പ്രവര്ത്തന "
 | 
			
		||||
"രഹിതമാക്കേണ്ടതുണ്ടു്. ഇങ്ങനെ ചെയ്യുന്നതു് "
 | 
			
		||||
"നിങ്ങള് സൂക്ഷിച്ച ഡേറ്റയെ ബാധിയ്ക്കുന്നതല്ല."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:7
 | 
			
		||||
@@ -112,7 +122,8 @@ msgstr "ഇഷ്ടമുള്ള പ്രയോഗങ്ങള്ക്
 | 
			
		||||
msgid ""
 | 
			
		||||
"The applications corresponding to these identifiers will be displayed in the "
 | 
			
		||||
"favorites area."
 | 
			
		||||
msgstr "ഈ ഐഡന്റിഫയറുകള്ക്കുള്ള പ്രയോഗങ്ങള് ഉചിതമായ സ്ഥലങ്ങളില് കാണിയ്ക്കുന്നു."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"ഈ ഐഡന്റിഫയറുകള്ക്കുള്ള പ്രയോഗങ്ങള് ഉചിതമായ സ്ഥലങ്ങളില് കാണിയ്ക്കുന്നു."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:9
 | 
			
		||||
msgid "History for command (Alt-F2) dialog"
 | 
			
		||||
@@ -127,7 +138,8 @@ msgid ""
 | 
			
		||||
"Internally used to store the last IM presence explicitly set by the user. "
 | 
			
		||||
"The value here is from the TpConnectionPresenceType enumeration."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"ഉപയോക്താവു് സജ്ജമാക്കിയ അവസാന ഐഎം ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് ഉപയോഗിയ്ക്കുന്നു. മൂല്യം "
 | 
			
		||||
"ഉപയോക്താവു് സജ്ജമാക്കിയ അവസാന ഐഎം ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് "
 | 
			
		||||
"ഉപയോഗിയ്ക്കുന്നു. മൂല്യം "
 | 
			
		||||
"TpConnectionPresenceType തരത്തിലുള്ളതാകുന്നു."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:12
 | 
			
		||||
@@ -135,7 +147,8 @@ msgid ""
 | 
			
		||||
"Internally used to store the last session presence status for the user. The "
 | 
			
		||||
"value here is from the GsmPresenceStatus enumeration."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"ഉപയോക്താവിനുള്ള അവസാന സെഷന് അവസ്ഥ ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് ഉപയോഗിയ്ക്കുന്നു. മൂല്യം "
 | 
			
		||||
"ഉപയോക്താവിനുള്ള അവസാന സെഷന് അവസ്ഥ ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് "
 | 
			
		||||
"ഉപയോഗിയ്ക്കുന്നു. മൂല്യം "
 | 
			
		||||
"GsmPresenceStatus തരത്തിലുള്ളതാകുന്നു."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:13
 | 
			
		||||
@@ -168,7 +181,9 @@ msgstr "സ്ക്രീന് റിക്കോര്ഡര് ട
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20
 | 
			
		||||
msgid "Keybinding to start/stop the builtin screen recorder."
 | 
			
		||||
msgstr "ബിള്ട്ടിന് സ്ക്രീന് റിക്കോര്ഡര് തുടങ്ങുവാന്/നിര്ത്തുന്നതിനുള്ള കീക്കൂട്ടം."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"ബിള്ട്ടിന് സ്ക്രീന് റിക്കോര്ഡര് തുടങ്ങുവാന്/നിര്ത്തുന്നതിനുള്ള "
 | 
			
		||||
"കീക്കൂട്ടം."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21
 | 
			
		||||
msgid "Which keyboard to use"
 | 
			
		||||
@@ -187,7 +202,8 @@ msgid ""
 | 
			
		||||
"The framerate of the resulting screencast recordered by GNOME Shell's "
 | 
			
		||||
"screencast recorder in frames-per-second."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"ഗ്നോം ഷെല്ലിന്റെ സ്ക്രീന്കാസ്റ്റ് റിക്കോര്ഡര് റീക്കോര്ഡ് ചെയ്തിട്ടുള്ള സ്ക്രീന്കാസ്റ്റിന്റെ "
 | 
			
		||||
"ഗ്നോം ഷെല്ലിന്റെ സ്ക്രീന്കാസ്റ്റ് റിക്കോര്ഡര് റീക്കോര്ഡ് ചെയ്തിട്ടുള്ള "
 | 
			
		||||
"സ്ക്രീന്കാസ്റ്റിന്റെ "
 | 
			
		||||
"ഫ്രെയിംറേറ്റ്, ഒരു സെക്കന്ഡില് ഒരു ഫ്രെയിം."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
 | 
			
		||||
@@ -219,9 +235,12 @@ msgid ""
 | 
			
		||||
"threads=%T ! queue ! webmmux' and records to WEBM using the VP8 codec. %T is "
 | 
			
		||||
"used as a placeholder for a guess at the optimal thread count on the system."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"റിക്കോര്ഡിങുകള് എന്കോഡ് ചെയ്യുന്നതിനായി GStreamer പൈപ്പ് ലൈന് ഉപയോഗിയ്ക്കുന്നു. "
 | 
			
		||||
"gst-launch-നുള്ള സിന്റാക്സ് ഉപയോഗിയ്ക്കുന്നു. കാലിയായി സജ്ജമാക്കുമ്പോള് കാലിയാകുന്നു."
 | 
			
		||||
"ഇതു് നിലവില് 'vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 "
 | 
			
		||||
"റിക്കോര്ഡിങുകള് എന്കോഡ് ചെയ്യുന്നതിനായി GStreamer പൈപ്പ് ലൈന് "
 | 
			
		||||
"ഉപയോഗിയ്ക്കുന്നു. "
 | 
			
		||||
"gst-launch-നുള്ള സിന്റാക്സ് ഉപയോഗിയ്ക്കുന്നു. കാലിയായി സജ്ജമാക്കുമ്പോള് "
 | 
			
		||||
"കാലിയാകുന്നു."
 | 
			
		||||
"ഇതു് നിലവില് 'vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 "
 | 
			
		||||
"deadline=1000000 "
 | 
			
		||||
"threads=%T ! queue ! webmmux' ആകുന്നുസ WEBM VP8 കോഡ് ഉപയോഗിച്ചു് റിക്കോര്ഡ് "
 | 
			
		||||
"ചെയ്യുന്നു."
 | 
			
		||||
 | 
			
		||||
@@ -235,8 +254,10 @@ msgid ""
 | 
			
		||||
"current date, and use this extension. It should be changed when recording to "
 | 
			
		||||
"a different container format."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"റിക്കോര്ഡ് ചെയ്ത സ്ക്രീന്കാസ്റ്റുകള്ക്കുള്ള ഫയല്നാമം നിലവിലുള്ള തീയതി, എക്സ്റ്റെന്ഷന് എന്നിവ "
 | 
			
		||||
"അനുസരിച്ചാകുന്നു. മറ്റൊരു ശൈലിയിലേക്കു് റിക്കോര്ഡ് ചെയ്യുമ്പോള് ഇതു് മാറ്റണം."
 | 
			
		||||
"റിക്കോര്ഡ് ചെയ്ത സ്ക്രീന്കാസ്റ്റുകള്ക്കുള്ള ഫയല്നാമം നിലവിലുള്ള തീയതി, "
 | 
			
		||||
"എക്സ്റ്റെന്ഷന് എന്നിവ "
 | 
			
		||||
"അനുസരിച്ചാകുന്നു. മറ്റൊരു ശൈലിയിലേക്കു് റിക്കോര്ഡ് ചെയ്യുമ്പോള് ഇതു് "
 | 
			
		||||
"മാറ്റണം."
 | 
			
		||||
 | 
			
		||||
#: ../js/extensionPrefs/main.js:124
 | 
			
		||||
#, c-format
 | 
			
		||||
@@ -249,7 +270,9 @@ msgstr "എക്സ്റ്റെന്ഷന്"
 | 
			
		||||
 | 
			
		||||
#: ../js/extensionPrefs/main.js:188
 | 
			
		||||
msgid "Select an extension to configure using the combobox above."
 | 
			
		||||
msgstr "മുകളിലുള്ള കോമ്പോ ബോക്സ് ഉപയോഗിച്ചു് ക്രമീകരിയ്ക്കുന്നതിനുള്ളൊരു എക്സ്റ്റെന്ഷന് തെരഞ്ഞെടുക്കുക."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"മുകളിലുള്ള കോമ്പോ ബോക്സ് ഉപയോഗിച്ചു് ക്രമീകരിയ്ക്കുന്നതിനുള്ളൊരു "
 | 
			
		||||
"എക്സ്റ്റെന്ഷന് തെരഞ്ഞെടുക്കുക."
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/loginDialog.js:526
 | 
			
		||||
msgid "Session..."
 | 
			
		||||
@@ -578,7 +601,8 @@ msgid ""
 | 
			
		||||
"Passwords or encryption keys are required to access the wireless network "
 | 
			
		||||
"'%s'."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"വയര്ലെസ് നെറ്റ്വര്ക്ക് '%s'-ലേക്ക് പ്രവേശിക്കുന്നതിനായി രഹസ്യവാക്കുകള് അല്ലെങ്കില് എന്ക്രിപ്ഷന് കീകള് "
 | 
			
		||||
"വയര്ലെസ് നെറ്റ്വര്ക്ക് '%s'-ലേക്ക് പ്രവേശിക്കുന്നതിനായി രഹസ്യവാക്കുകള് "
 | 
			
		||||
"അല്ലെങ്കില് എന്ക്രിപ്ഷന് കീകള് "
 | 
			
		||||
"ആവശ്യമുണ്ടു്."
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/networkAgent.js:314
 | 
			
		||||
@@ -764,7 +788,8 @@ msgstr "%s നിങ്ങള്ക്കു് %s അയച്ചിരി
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1206
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s would like permission to see when you are online"
 | 
			
		||||
msgstr "നിങ്ങള് ഓണ്ലൈന് ആകുമ്പോള് കാണുന്നതിനുള്ള അനുമതി %s-നു് ആവശ്യമുണ്ടു്"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"നിങ്ങള് ഓണ്ലൈന് ആകുമ്പോള് കാണുന്നതിനുള്ള അനുമതി %s-നു് ആവശ്യമുണ്ടു്"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1298
 | 
			
		||||
msgid "Network error"
 | 
			
		||||
@@ -835,8 +860,11 @@ msgid "This account is already connected to the server"
 | 
			
		||||
msgstr "ഈ അക്കൌണ്ട് നിലവില് സര്വറിലേക്കു് കണക്ട് ചെയ്തിരിയ്ക്കുന്നു"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1332
 | 
			
		||||
msgid "Connection has been replaced by a new connection using the same resource"
 | 
			
		||||
msgstr "അതേ ശ്രോതസ്സ് ഉപയോഗിച്ചു് ഒരു പുതിയ കണക്ഷന് ഉപയോഗിച്ചു് ഈ കണക്ഷന് മാറ്റിസ്ഥാപിയ്ക്കുന്നു"
 | 
			
		||||
msgid ""
 | 
			
		||||
"Connection has been replaced by a new connection using the same resource"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"അതേ ശ്രോതസ്സ് ഉപയോഗിച്ചു് ഒരു പുതിയ കണക്ഷന് ഉപയോഗിച്ചു് ഈ കണക്ഷന് "
 | 
			
		||||
"മാറ്റിസ്ഥാപിയ്ക്കുന്നു"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1334
 | 
			
		||||
msgid "The account already exists on the server"
 | 
			
		||||
@@ -851,15 +879,19 @@ msgid "Certificate has been revoked"
 | 
			
		||||
msgstr "സമ്മതപത്രം വീണ്ടും ആവശ്യപ്പെട്ടിരിയ്ക്കുന്നു"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1340
 | 
			
		||||
msgid "Certificate uses an insecure cipher algorithm or is cryptographically weak"
 | 
			
		||||
msgstr "സമ്മതപത്രം സുരക്ഷിതമല്ലാത്തൊരു സിഫര് ആല്ഗോരിഥം ഉപയോഗിയ്ക്കുന്നു അല്ലെങ്കില് ഉചിതമല്ല"
 | 
			
		||||
msgid ""
 | 
			
		||||
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"സമ്മതപത്രം സുരക്ഷിതമല്ലാത്തൊരു സിഫര് ആല്ഗോരിഥം ഉപയോഗിയ്ക്കുന്നു "
 | 
			
		||||
"അല്ലെങ്കില് ഉചിതമല്ല"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1342
 | 
			
		||||
msgid ""
 | 
			
		||||
"The length of the server certificate, or the depth of the server certificate "
 | 
			
		||||
"chain, exceed the limits imposed by the cryptography library"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"സര്വറിന്റെ സമ്മതപത്രത്തിന്റെ വ്യാപ്തി, അല്ലെങ്കില് സര്വര് സമ്മതപത്ര ചെയിന്റെ വ്യാപ്തി, എന്നിവ "
 | 
			
		||||
"സര്വറിന്റെ സമ്മതപത്രത്തിന്റെ വ്യാപ്തി, അല്ലെങ്കില് സര്വര് സമ്മതപത്ര "
 | 
			
		||||
"ചെയിന്റെ വ്യാപ്തി, എന്നിവ "
 | 
			
		||||
"പരിധിയില് കൂടുന്നു"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1344
 | 
			
		||||
@@ -918,7 +950,8 @@ msgstr "പുറത്ത് കടക്കുക"
 | 
			
		||||
#: ../js/ui/endSessionDialog.js:63
 | 
			
		||||
msgid "Click Log Out to quit these applications and log out of the system."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പുറത്തു കടക്കുക ക്ലിക്ക് ചെയ്തു് സിസ്റ്റത്തില് നിന്നും "
 | 
			
		||||
"ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പുറത്തു കടക്കുക ക്ലിക്ക് "
 | 
			
		||||
"ചെയ്തു് സിസ്റ്റത്തില് നിന്നും "
 | 
			
		||||
"പുറത്തു് കടക്കുക."
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/endSessionDialog.js:65
 | 
			
		||||
@@ -952,7 +985,8 @@ msgstr "നിര്ത്തുക"
 | 
			
		||||
#: ../js/ui/endSessionDialog.js:82
 | 
			
		||||
msgid "Click Power Off to quit these applications and power off the system."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പവര് ഓഫ് ചെയ്യുക ക്ലിക്ക് ചെയ്തു സിസ്റ്റിന്റെ പവര് "
 | 
			
		||||
"ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പവര് ഓഫ് ചെയ്യുക ക്ലിക്ക് "
 | 
			
		||||
"ചെയ്തു സിസ്റ്റിന്റെ പവര് "
 | 
			
		||||
"ഓഫ് ചെയ്യുക."
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/endSessionDialog.js:84
 | 
			
		||||
@@ -983,7 +1017,8 @@ msgstr "പുനരാരംഭിക്കുക"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/endSessionDialog.js:99
 | 
			
		||||
msgid "Click Restart to quit these applications and restart the system."
 | 
			
		||||
msgstr "ഈ പ്രയോഗങ്ങള് നിറുത്തി സിസ്റ്റം പുനരാരംഭിക്കുവാന് പുനരാരംഭിക്കൂ അമര്ത്തുക"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"ഈ പ്രയോഗങ്ങള് നിറുത്തി സിസ്റ്റം പുനരാരംഭിക്കുവാന് പുനരാരംഭിക്കൂ അമര്ത്തുക"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/endSessionDialog.js:101
 | 
			
		||||
#, c-format
 | 
			
		||||
@@ -1003,7 +1038,9 @@ msgstr "ഇന്സ്റ്റോള്"
 | 
			
		||||
#: ../js/ui/extensionDownloader.js:204
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Download and install '%s' from extensions.gnome.org?"
 | 
			
		||||
msgstr "extensions.gnome.org ഇല് നിന്നും '%s' ഡൗണ്ലോട് ചെയ്ത് ഇന്സ്റ്റോള് ചെയ്യേണമോ?"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"extensions.gnome.org ഇല് നിന്നും '%s' ഡൗണ്ലോട് ചെയ്ത് ഇന്സ്റ്റോള് "
 | 
			
		||||
"ചെയ്യേണമോ?"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/keyboard.js:327
 | 
			
		||||
msgid "tray"
 | 
			
		||||
@@ -1660,8 +1697,10 @@ msgid ""
 | 
			
		||||
"Notifications are now disabled, including chat messages. Your online status "
 | 
			
		||||
"has been adjusted to let others know that you might not see their messages."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"ചാറ്റ് സന്ദേശങ്ങള് എന്ന പോലെ അറിയിപ്പുകള് പ്രവര്ത്തന രഹിതമാക്കുന്നു. മറ്റുള്ളവരുടെ ചാറ്റ് സന്ദേശങ്ങള് "
 | 
			
		||||
"നിങ്ങള്ക്കു് കാണുവാന് സാധ്യമല്ല എന്നു് നിങ്ങളുടെ ഓണ്ലൈന് അവസ്ഥയില് വ്യക്തമാക്കുന്നു."
 | 
			
		||||
"ചാറ്റ് സന്ദേശങ്ങള് എന്ന പോലെ അറിയിപ്പുകള് പ്രവര്ത്തന രഹിതമാക്കുന്നു. "
 | 
			
		||||
"മറ്റുള്ളവരുടെ ചാറ്റ് സന്ദേശങ്ങള് "
 | 
			
		||||
"നിങ്ങള്ക്കു് കാണുവാന് സാധ്യമല്ല എന്നു് നിങ്ങളുടെ ഓണ്ലൈന് അവസ്ഥയില് "
 | 
			
		||||
"വ്യക്തമാക്കുന്നു."
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/viewSelector.js:85
 | 
			
		||||
msgid "Windows"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										419
									
								
								po/nb.po
									
									
									
									
									
								
							
							
						
						
									
										419
									
								
								po/nb.po
									
									
									
									
									
								
							@@ -6,10 +6,10 @@
 | 
			
		||||
# Torstein Adolf Winterseth <kvikende@fsfe.org>, 2010.
 | 
			
		||||
msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: gnome-shell 3.5.x\n"
 | 
			
		||||
"Project-Id-Version: gnome-shell 3.7.x\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: \n"
 | 
			
		||||
"POT-Creation-Date: 2012-10-11 20:24+0200\n"
 | 
			
		||||
"PO-Revision-Date: 2012-10-11 20:25+0200\n"
 | 
			
		||||
"POT-Creation-Date: 2012-11-05 19:06+0100\n"
 | 
			
		||||
"PO-Revision-Date: 2012-11-05 19:10+0100\n"
 | 
			
		||||
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
 | 
			
		||||
"Language-Team: Norwegian bokmål <i18n-nb@lister.ping.uio.no>\n"
 | 
			
		||||
"Language: \n"
 | 
			
		||||
@@ -34,6 +34,14 @@ msgstr "System"
 | 
			
		||||
msgid "Show the message tray"
 | 
			
		||||
msgstr "Vis meldingstrau"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-gnome-shell-system.xml.in.h:3
 | 
			
		||||
msgid "Show all applications"
 | 
			
		||||
msgstr "Vis alle programmer"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-gnome-shell-system.xml.in.h:4
 | 
			
		||||
msgid "Open the application menu"
 | 
			
		||||
msgstr "Åpne programmenyen"
 | 
			
		||||
 | 
			
		||||
#: ../data/gnome-shell.desktop.in.in.h:1
 | 
			
		||||
msgid "GNOME Shell"
 | 
			
		||||
msgstr "GNOME Shell"
 | 
			
		||||
@@ -128,50 +136,71 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:13
 | 
			
		||||
msgid "Always show the 'Log out' menuitem in the user menu."
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:14
 | 
			
		||||
msgid ""
 | 
			
		||||
"This key overrides the automatic hiding of the 'Log out' menuitem in single-"
 | 
			
		||||
"user, single-session situations."
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
 | 
			
		||||
msgid "Show the week date in the calendar"
 | 
			
		||||
msgstr "Vis dato for uken i kalender"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:14
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16
 | 
			
		||||
msgid "If true, display the ISO week date in the calendar."
 | 
			
		||||
msgstr "Viser ISO-ukedato i kalenderen hvis «true»."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17
 | 
			
		||||
msgid "Keybinding to open the application menu"
 | 
			
		||||
msgstr "Tastaturbinding som åpner programmenyen"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
 | 
			
		||||
msgid "Keybinding to open the application menu."
 | 
			
		||||
msgstr "Tastaturbinding som åpner programmenyen."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
 | 
			
		||||
#, fuzzy
 | 
			
		||||
msgid "Keybinding to open the \"Show Applications\" view"
 | 
			
		||||
msgstr "Tastaturbinding som åpner programmenyen"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20
 | 
			
		||||
#, fuzzy
 | 
			
		||||
msgid ""
 | 
			
		||||
"Keybinding to open the \"Show Applications\" view of the Activities Overview."
 | 
			
		||||
msgstr "Tastaturbinding som åpner programmenyen."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21
 | 
			
		||||
msgid "Keybinding to toggle the visibility of the message tray"
 | 
			
		||||
msgstr "Tastaturbinding som slår av/på synlighet for meldingstrau"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22
 | 
			
		||||
msgid "Keybinding to toggle the visibility of the message tray."
 | 
			
		||||
msgstr "Tastaturbinding som slår av/på synlighet for meldingstrauet."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
 | 
			
		||||
msgid "Keybinding to toggle the screen recorder"
 | 
			
		||||
msgstr "Tastaturbinding som slår av/på skjermopptak"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24
 | 
			
		||||
msgid "Keybinding to start/stop the builtin screen recorder."
 | 
			
		||||
msgstr "Tastaturbinding som starter/stopper innebygget opptak av skjerm."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
 | 
			
		||||
msgid "Which keyboard to use"
 | 
			
		||||
msgstr "Tastatur som skal brukes"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26
 | 
			
		||||
msgid "The type of keyboard to use."
 | 
			
		||||
msgstr "Type tastatur som skal brukes."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
 | 
			
		||||
msgid "Framerate used for recording screencasts."
 | 
			
		||||
msgstr "Bildefrekvens i bruk ved lagring av skjermvideoer."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28
 | 
			
		||||
msgid ""
 | 
			
		||||
"The framerate of the resulting screencast recordered by GNOME Shell's "
 | 
			
		||||
"screencast recorder in frames-per-second."
 | 
			
		||||
@@ -179,11 +208,11 @@ msgstr ""
 | 
			
		||||
"Bildefrekvensen i den ferdige skjermvideoen tatt opp med GNOME Shells "
 | 
			
		||||
"skjermvideoopptaker i bilder per sekund."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
 | 
			
		||||
msgid "The gstreamer pipeline used to encode the screencast"
 | 
			
		||||
msgstr "Gstreamer-kommandokø brukt til å kode skjermvideoen"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31
 | 
			
		||||
#, fuzzy, no-c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
 | 
			
		||||
@@ -200,11 +229,11 @@ msgstr ""
 | 
			
		||||
"Setter GStreamer-rør som brukes til å kode opptak. Den følger syntaksen som "
 | 
			
		||||
"brukes for gst-launch. Røret må ha en..."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:32
 | 
			
		||||
msgid "File extension used for storing the screencast"
 | 
			
		||||
msgstr "Filendelse i bruk ved lagring av skjermvideo"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:33
 | 
			
		||||
msgid ""
 | 
			
		||||
"The filename for recorded screencasts will be a unique filename based on the "
 | 
			
		||||
"current date, and use this extension. It should be changed when recording to "
 | 
			
		||||
@@ -214,6 +243,37 @@ msgstr ""
 | 
			
		||||
"og bruke denne filendelsen. Den bør endres når du gjør opptak til et nytt "
 | 
			
		||||
"oppbevaringsformat."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:34
 | 
			
		||||
msgid "Attach modal dialog to the parent window"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:35
 | 
			
		||||
msgid ""
 | 
			
		||||
"This key overrides the key in org.gnome.mutter when running GNOME Shell."
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:36
 | 
			
		||||
msgid "Arrangement of buttons on the titlebar"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:37
 | 
			
		||||
msgid ""
 | 
			
		||||
"This key overrides the key in org.gnome.desktop.wm.preferences when running "
 | 
			
		||||
"GNOME Shell."
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:38
 | 
			
		||||
msgid "Enable edge tiling when dropping windows on screen edges"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:39
 | 
			
		||||
msgid "Workspaces are managed dynamically"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:40
 | 
			
		||||
msgid "Workspaces only on primary monitor"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: ../js/extensionPrefs/main.js:124
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "There was an error loading the preferences dialog for %s:"
 | 
			
		||||
@@ -227,11 +287,11 @@ msgstr "Utvidelse"
 | 
			
		||||
msgid "Select an extension to configure using the combobox above."
 | 
			
		||||
msgstr "Velg en utvidelse som skal konfigureres med komboboksen over."
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/loginDialog.js:529
 | 
			
		||||
#: ../js/gdm/loginDialog.js:560
 | 
			
		||||
msgid "Session..."
 | 
			
		||||
msgstr "Økt …"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/loginDialog.js:677
 | 
			
		||||
#: ../js/gdm/loginDialog.js:704
 | 
			
		||||
msgctxt "title"
 | 
			
		||||
msgid "Sign In"
 | 
			
		||||
msgstr "Logg inn"
 | 
			
		||||
@@ -239,56 +299,56 @@ msgstr "Logg inn"
 | 
			
		||||
#. translators: this message is shown below the user list on the
 | 
			
		||||
#. login screen. It can be activated to reveal an entry for
 | 
			
		||||
#. manually entering the username.
 | 
			
		||||
#: ../js/gdm/loginDialog.js:736
 | 
			
		||||
#: ../js/gdm/loginDialog.js:764
 | 
			
		||||
msgid "Not listed?"
 | 
			
		||||
msgstr "Ikke listet?"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/loginDialog.js:889 ../js/ui/components/networkAgent.js:137
 | 
			
		||||
#: ../js/gdm/loginDialog.js:906 ../js/ui/components/networkAgent.js:137
 | 
			
		||||
#: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:373
 | 
			
		||||
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:396
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:427 ../js/ui/unlockDialog.js:166
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:427 ../js/ui/unlockDialog.js:171
 | 
			
		||||
msgid "Cancel"
 | 
			
		||||
msgstr "Avbryt"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/loginDialog.js:894
 | 
			
		||||
#: ../js/gdm/loginDialog.js:911
 | 
			
		||||
msgctxt "button"
 | 
			
		||||
msgid "Sign In"
 | 
			
		||||
msgstr "Logg inn"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/loginDialog.js:1215
 | 
			
		||||
#: ../js/gdm/loginDialog.js:1237
 | 
			
		||||
msgid "Login Window"
 | 
			
		||||
msgstr "Innloggingsvindu"
 | 
			
		||||
 | 
			
		||||
#. Translators: accessible name of the power menu in the login screen
 | 
			
		||||
#: ../js/gdm/powerMenu.js:35
 | 
			
		||||
#: ../js/gdm/powerMenu.js:36
 | 
			
		||||
msgid "Power"
 | 
			
		||||
msgstr "Strøm"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/powerMenu.js:89 ../js/ui/userMenu.js:660 ../js/ui/userMenu.js:664
 | 
			
		||||
#: ../js/ui/userMenu.js:775
 | 
			
		||||
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:667 ../js/ui/userMenu.js:671
 | 
			
		||||
#: ../js/ui/userMenu.js:782
 | 
			
		||||
msgid "Suspend"
 | 
			
		||||
msgstr "Hvilemodus"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/powerMenu.js:94
 | 
			
		||||
#: ../js/gdm/powerMenu.js:98
 | 
			
		||||
msgid "Restart"
 | 
			
		||||
msgstr "Start på nytt"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/powerMenu.js:99 ../js/ui/userMenu.js:662 ../js/ui/userMenu.js:664
 | 
			
		||||
#: ../js/ui/userMenu.js:774
 | 
			
		||||
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:669
 | 
			
		||||
#: ../js/ui/userMenu.js:671 ../js/ui/userMenu.js:781
 | 
			
		||||
msgid "Power Off"
 | 
			
		||||
msgstr "Slå av"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/util.js:148
 | 
			
		||||
#: ../js/gdm/util.js:151
 | 
			
		||||
msgid "Authentication error"
 | 
			
		||||
msgstr "Autentiseringsfeil"
 | 
			
		||||
 | 
			
		||||
#. Translators: this message is shown below the password entry field
 | 
			
		||||
#. to indicate the user can swipe their finger instead
 | 
			
		||||
#: ../js/gdm/util.js:265
 | 
			
		||||
#: ../js/gdm/util.js:268
 | 
			
		||||
msgid "(or swipe finger)"
 | 
			
		||||
msgstr "(eller dra finger)"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/util.js:290
 | 
			
		||||
#: ../js/gdm/util.js:293
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "(e.g., user or %s)"
 | 
			
		||||
msgstr "(f.eks. bruker eller %s)"
 | 
			
		||||
@@ -338,7 +398,7 @@ msgstr "Legg til i favoritter"
 | 
			
		||||
msgid "%s has been added to your favorites."
 | 
			
		||||
msgstr "%s ble lagt til i dine favoritter."
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/appFavorites.js:118
 | 
			
		||||
#: ../js/ui/appFavorites.js:121
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s has been removed from your favorites."
 | 
			
		||||
msgstr "%s ble fjernet fra dine favoritter."
 | 
			
		||||
@@ -457,48 +517,48 @@ msgid "S"
 | 
			
		||||
msgstr "Lø"
 | 
			
		||||
 | 
			
		||||
#. Translators: Text to show if there are no events
 | 
			
		||||
#: ../js/ui/calendar.js:699
 | 
			
		||||
#: ../js/ui/calendar.js:700
 | 
			
		||||
msgid "Nothing Scheduled"
 | 
			
		||||
msgstr "Ingenting planlagt"
 | 
			
		||||
 | 
			
		||||
#. Translators: Shown on calendar heading when selected day occurs on current year
 | 
			
		||||
#: ../js/ui/calendar.js:715
 | 
			
		||||
#: ../js/ui/calendar.js:716
 | 
			
		||||
msgctxt "calendar heading"
 | 
			
		||||
msgid "%A, %B %d"
 | 
			
		||||
msgstr "%A %B %d"
 | 
			
		||||
 | 
			
		||||
#. Translators: Shown on calendar heading when selected day occurs on different year
 | 
			
		||||
#: ../js/ui/calendar.js:718
 | 
			
		||||
#: ../js/ui/calendar.js:719
 | 
			
		||||
msgctxt "calendar heading"
 | 
			
		||||
msgid "%A, %B %d, %Y"
 | 
			
		||||
msgstr "%A %B %d, %Y"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/calendar.js:728
 | 
			
		||||
#: ../js/ui/calendar.js:729
 | 
			
		||||
msgid "Today"
 | 
			
		||||
msgstr "I dag"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/calendar.js:732
 | 
			
		||||
#: ../js/ui/calendar.js:733
 | 
			
		||||
msgid "Tomorrow"
 | 
			
		||||
msgstr "I morgen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/calendar.js:743
 | 
			
		||||
#: ../js/ui/calendar.js:744
 | 
			
		||||
msgid "This week"
 | 
			
		||||
msgstr "Denne uken"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/calendar.js:751
 | 
			
		||||
#: ../js/ui/calendar.js:752
 | 
			
		||||
msgid "Next week"
 | 
			
		||||
msgstr "Neste uke"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/autorunManager.js:297
 | 
			
		||||
#: ../js/ui/components/autorunManager.js:295
 | 
			
		||||
msgid "Removable Devices"
 | 
			
		||||
msgstr "Avtagbare enheter"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/autorunManager.js:594
 | 
			
		||||
#: ../js/ui/components/autorunManager.js:591
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Open with %s"
 | 
			
		||||
msgstr "Åpne med %s"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/autorunManager.js:620
 | 
			
		||||
#: ../js/ui/components/autorunManager.js:617
 | 
			
		||||
msgid "Eject"
 | 
			
		||||
msgstr "Løs ut"
 | 
			
		||||
 | 
			
		||||
@@ -652,38 +712,42 @@ msgstr "Fjern demping"
 | 
			
		||||
msgid "Mute"
 | 
			
		||||
msgstr "Demp"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is a time format string followed by a date.
 | 
			
		||||
#. If applicable, replace %X with a strftime format valid for your
 | 
			
		||||
#. locale, without seconds.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:948
 | 
			
		||||
#. Translators: this is a time format string followed by the word "Yesterday". i.e. "14:30 on Yesterday"
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:945
 | 
			
		||||
#, no-c-format
 | 
			
		||||
msgid "Sent at <b>%X</b> on <b>%A</b>"
 | 
			
		||||
msgstr "Sendt <b>%X</b> på <b>%A</b>"
 | 
			
		||||
msgid "<b>%H:%M</b> on Yesterday"
 | 
			
		||||
msgstr "<b>%H.%M</b> i går"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is a time format in the style of "Wednesday, May 25",
 | 
			
		||||
#. shown when you get a chat message in the same year.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:954
 | 
			
		||||
#. Translators: this is a time format string followed by a week day name. i.e. "14:30 on Monday
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:951
 | 
			
		||||
#, no-c-format
 | 
			
		||||
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
 | 
			
		||||
msgstr "Sendt  <b>%A</b>, <b>%B %d</b>"
 | 
			
		||||
msgid "<b>%H:%M</b> on <b>%A</b>"
 | 
			
		||||
msgstr "<b>%H.%M</b> på <b>%A</b>"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
 | 
			
		||||
#. shown when you get a chat message in a different year.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:959
 | 
			
		||||
#. Translators: this is a time format in the style of "14:30 on Wednesday, May 25",
 | 
			
		||||
#. shown when you get a chat message in the same year
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:957
 | 
			
		||||
#, no-c-format
 | 
			
		||||
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
 | 
			
		||||
msgstr "Sendt <b>%A</b>, <b>%B %d</b>, %Y"
 | 
			
		||||
msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>"
 | 
			
		||||
msgstr "<b>%H.%M</b>, <b>%A</b>, <b>%B</b> <b>%d</b>"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is a time format in the style of "14:30 on Wednesday, May 25, 2012",
 | 
			
		||||
#. shown when you get a chat message in a different year
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:962
 | 
			
		||||
#, no-c-format
 | 
			
		||||
msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>, %Y"
 | 
			
		||||
msgstr "<b>%H.%M</b>, <b>%A</b>, <b>%B</b> <b>%d</b>, %Y"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is the other person changing their old IM name to their new
 | 
			
		||||
#. IM name.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:988
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:990
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s is now known as %s"
 | 
			
		||||
msgstr "%s er nå kjent som %s"
 | 
			
		||||
 | 
			
		||||
#. translators: argument is a room name like
 | 
			
		||||
#. * room@jabber.org for example.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1088
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1089
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Invitation to %s"
 | 
			
		||||
msgstr "Invitasjon til %s"
 | 
			
		||||
@@ -691,42 +755,42 @@ msgstr "Invitasjon til %s"
 | 
			
		||||
#. translators: first argument is the name of a contact and the second
 | 
			
		||||
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
 | 
			
		||||
#. * for example.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1096
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1097
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s is inviting you to join %s"
 | 
			
		||||
msgstr "%s inviterer deg til å bli med i %s"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1098
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1177
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1240
 | 
			
		||||
msgid "Decline"
 | 
			
		||||
msgstr "Avslå"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1099
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1178
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1241
 | 
			
		||||
msgid "Decline"
 | 
			
		||||
msgstr "Avslå"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1100
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1179
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1242
 | 
			
		||||
msgid "Accept"
 | 
			
		||||
msgstr "Godta"
 | 
			
		||||
 | 
			
		||||
#. translators: argument is a contact name like Alice for example.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1129
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1130
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Video call from %s"
 | 
			
		||||
msgstr "Videosamtale fra %s"
 | 
			
		||||
 | 
			
		||||
#. translators: argument is a contact name like Alice for example.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1132
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1133
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Call from %s"
 | 
			
		||||
msgstr "Samtale fra %s"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1137
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1138
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:346
 | 
			
		||||
msgid "Reject"
 | 
			
		||||
msgstr "Avvis"
 | 
			
		||||
 | 
			
		||||
#. translators: this is a button label (verb), not a noun
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1139
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1140
 | 
			
		||||
msgid "Answer"
 | 
			
		||||
msgstr "Svar"
 | 
			
		||||
 | 
			
		||||
@@ -735,110 +799,110 @@ msgstr "Svar"
 | 
			
		||||
#. * file name. The string will be something
 | 
			
		||||
#. * like: "Alice is sending you test.ogg"
 | 
			
		||||
#.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1171
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1172
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s is sending you %s"
 | 
			
		||||
msgstr "%s sender deg %s"
 | 
			
		||||
 | 
			
		||||
#. To translators: The parameter is the contact's alias
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1206
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1207
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s would like permission to see when you are online"
 | 
			
		||||
msgstr "%s vil ha rettigheter til å se når du er tilkoblet"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1298
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1299
 | 
			
		||||
msgid "Network error"
 | 
			
		||||
msgstr "Nettverksfeil"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1300
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1301
 | 
			
		||||
msgid "Authentication failed"
 | 
			
		||||
msgstr "Autentisering feilet"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1302
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1303
 | 
			
		||||
msgid "Encryption error"
 | 
			
		||||
msgstr "Feil ved kryptering"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1304
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1305
 | 
			
		||||
msgid "Certificate not provided"
 | 
			
		||||
msgstr "Sertifikat ikke oppgitt"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1306
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1307
 | 
			
		||||
msgid "Certificate untrusted"
 | 
			
		||||
msgstr "Stoler ikke på sertifikatet"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1308
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1309
 | 
			
		||||
msgid "Certificate expired"
 | 
			
		||||
msgstr "Sertifikatet er utløpt"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1310
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1311
 | 
			
		||||
msgid "Certificate not activated"
 | 
			
		||||
msgstr "Sertifikatet er ikke aktivert"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1312
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1313
 | 
			
		||||
msgid "Certificate hostname mismatch"
 | 
			
		||||
msgstr "Feil vertsnavn for sertifikat"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1314
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1315
 | 
			
		||||
msgid "Certificate fingerprint mismatch"
 | 
			
		||||
msgstr "Feil fingeravtrykk for sertifikat"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1316
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1317
 | 
			
		||||
msgid "Certificate self-signed"
 | 
			
		||||
msgstr "Sertifikatet er selvsignert"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1318
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1319
 | 
			
		||||
msgid "Status is set to offline"
 | 
			
		||||
msgstr "Status er satt til frakoblet"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1320
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1321
 | 
			
		||||
msgid "Encryption is not available"
 | 
			
		||||
msgstr "Kryptering er ikke tilgjengelig"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1322
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1323
 | 
			
		||||
msgid "Certificate is invalid"
 | 
			
		||||
msgstr "Sertifikatet er ugyldig"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1324
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1325
 | 
			
		||||
msgid "Connection has been refused"
 | 
			
		||||
msgstr "Tilkobling ble nektet"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1326
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1327
 | 
			
		||||
msgid "Connection can't be established"
 | 
			
		||||
msgstr "Tilkobling kan ikke etableres"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1328
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1329
 | 
			
		||||
msgid "Connection has been lost"
 | 
			
		||||
msgstr "Tilkobling tapt"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1330
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1331
 | 
			
		||||
msgid "This account is already connected to the server"
 | 
			
		||||
msgstr "Denne kontoen er allerede koblet til tjeneren"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1332
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1333
 | 
			
		||||
msgid ""
 | 
			
		||||
"Connection has been replaced by a new connection using the same resource"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Tilkoblingen har blitt erstattet av en ny tilkobling som bruker samme ressurs"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1334
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1335
 | 
			
		||||
msgid "The account already exists on the server"
 | 
			
		||||
msgstr "Kontoen eksisterer allerede på tjeneren"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1336
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1337
 | 
			
		||||
msgid "Server is currently too busy to handle the connection"
 | 
			
		||||
msgstr "Tjener er for opptatt til å håndtere tilkoblingen"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1338
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1339
 | 
			
		||||
msgid "Certificate has been revoked"
 | 
			
		||||
msgstr "Sertifikatet er tilbaketrukket"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1340
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1341
 | 
			
		||||
msgid ""
 | 
			
		||||
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Sertifikatet bruker en usikker sifferalgoritme eller er krytografisk svakt"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1342
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1343
 | 
			
		||||
msgid ""
 | 
			
		||||
"The length of the server certificate, or the depth of the server certificate "
 | 
			
		||||
"chain, exceed the limits imposed by the cryptography library"
 | 
			
		||||
@@ -846,26 +910,26 @@ msgstr ""
 | 
			
		||||
"Lengden eller dybden på tjenersertifikatet oversteg grensen som er satt i "
 | 
			
		||||
"kryptografibiblioteket"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1344
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1345
 | 
			
		||||
msgid "Internal error"
 | 
			
		||||
msgstr "Intern feil"
 | 
			
		||||
 | 
			
		||||
#. translators: argument is the account name, like
 | 
			
		||||
#. * name@jabber.org for example.
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1354
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1355
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Connection to %s failed"
 | 
			
		||||
msgstr "Tilkobling til %s feilet"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1363
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1364
 | 
			
		||||
msgid "Reconnect"
 | 
			
		||||
msgstr "Koble til på nytt"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1364
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1365
 | 
			
		||||
msgid "Edit account"
 | 
			
		||||
msgstr "Rediger konto"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1409
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1410
 | 
			
		||||
msgid "Unknown reason"
 | 
			
		||||
msgstr "Ukjent årsak"
 | 
			
		||||
 | 
			
		||||
@@ -884,7 +948,7 @@ msgstr "Åpne kalender"
 | 
			
		||||
#. Translators: This is the date format to use when the calendar popup is
 | 
			
		||||
#. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
 | 
			
		||||
#.
 | 
			
		||||
#: ../js/ui/dateMenu.js:190
 | 
			
		||||
#: ../js/ui/dateMenu.js:201
 | 
			
		||||
msgid "%A %B %e, %Y"
 | 
			
		||||
msgstr "%a %e %B, %Y"
 | 
			
		||||
 | 
			
		||||
@@ -989,11 +1053,11 @@ msgstr "Installer"
 | 
			
		||||
msgid "Download and install '%s' from extensions.gnome.org?"
 | 
			
		||||
msgstr "Last ned og installer «%s» fra extensions.gnome.org?"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/keyboard.js:337
 | 
			
		||||
#: ../js/ui/keyboard.js:308
 | 
			
		||||
msgid "tray"
 | 
			
		||||
msgstr "varslingsområde"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/keyboard.js:584 ../js/ui/status/keyboard.js:195
 | 
			
		||||
#: ../js/ui/keyboard.js:555 ../js/ui/status/keyboard.js:195
 | 
			
		||||
#: ../js/ui/status/power.js:205
 | 
			
		||||
msgid "Keyboard"
 | 
			
		||||
msgstr "Tastatur"
 | 
			
		||||
@@ -1046,32 +1110,32 @@ msgstr "Vis kildekode"
 | 
			
		||||
msgid "Web Page"
 | 
			
		||||
msgstr "Nettside"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:1081
 | 
			
		||||
#: ../js/ui/messageTray.js:1088
 | 
			
		||||
msgid "Open"
 | 
			
		||||
msgstr "Åpne"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:1088
 | 
			
		||||
#: ../js/ui/messageTray.js:1095
 | 
			
		||||
msgid "Remove"
 | 
			
		||||
msgstr "Fjern"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:1540
 | 
			
		||||
#: ../js/ui/messageTray.js:1539
 | 
			
		||||
msgid "Message Tray"
 | 
			
		||||
msgstr "Meldingstrau"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:2547
 | 
			
		||||
#: ../js/ui/messageTray.js:2563
 | 
			
		||||
msgid "System Information"
 | 
			
		||||
msgstr "Systeminformasjon"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/notificationDaemon.js:506 ../src/shell-app.c:373
 | 
			
		||||
#: ../js/ui/notificationDaemon.js:504 ../src/shell-app.c:374
 | 
			
		||||
msgctxt "program"
 | 
			
		||||
msgid "Unknown"
 | 
			
		||||
msgstr "Ukjent"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/overview.js:82
 | 
			
		||||
#: ../js/ui/overview.js:89
 | 
			
		||||
msgid "Undo"
 | 
			
		||||
msgstr "Angre"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/overview.js:127
 | 
			
		||||
#: ../js/ui/overview.js:133
 | 
			
		||||
msgid "Overview"
 | 
			
		||||
msgstr "Oversikt"
 | 
			
		||||
 | 
			
		||||
@@ -1079,27 +1143,27 @@ msgstr "Oversikt"
 | 
			
		||||
#. in the search entry when no search is
 | 
			
		||||
#. active; it should not exceed ~30
 | 
			
		||||
#. characters.
 | 
			
		||||
#: ../js/ui/overview.js:201
 | 
			
		||||
#: ../js/ui/overview.js:207
 | 
			
		||||
msgid "Type to search..."
 | 
			
		||||
msgstr "Skriv for å søke …"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is the name of the dock/favorites area on
 | 
			
		||||
#. the left of the overview
 | 
			
		||||
#: ../js/ui/overview.js:222
 | 
			
		||||
#: ../js/ui/overview.js:228
 | 
			
		||||
msgid "Dash"
 | 
			
		||||
msgstr "Favoritter"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/panel.js:567
 | 
			
		||||
#: ../js/ui/panel.js:581
 | 
			
		||||
msgid "Quit"
 | 
			
		||||
msgstr "Avslutt"
 | 
			
		||||
 | 
			
		||||
#. Translators: If there is no suitable word for "Activities"
 | 
			
		||||
#. in your language, you can use the word for "Overview".
 | 
			
		||||
#: ../js/ui/panel.js:599
 | 
			
		||||
#: ../js/ui/panel.js:613
 | 
			
		||||
msgid "Activities"
 | 
			
		||||
msgstr "Aktiviteter"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/panel.js:965
 | 
			
		||||
#: ../js/ui/panel.js:980
 | 
			
		||||
msgid "Top Bar"
 | 
			
		||||
msgstr "Topp-panel"
 | 
			
		||||
 | 
			
		||||
@@ -1113,23 +1177,27 @@ msgid "toggle-switch-us"
 | 
			
		||||
msgstr "toggle-switch-intl"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/runDialog.js:205
 | 
			
		||||
msgid "Please enter a command:"
 | 
			
		||||
msgstr "Oppgi en kommando:"
 | 
			
		||||
msgid "Enter a Command"
 | 
			
		||||
msgstr "Oppgi en kommando"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/runDialog.js:241
 | 
			
		||||
msgid "Close"
 | 
			
		||||
msgstr "Lukk"
 | 
			
		||||
 | 
			
		||||
#. Translators: This is a time format for a date in
 | 
			
		||||
#. long format
 | 
			
		||||
#: ../js/ui/screenShield.js:79
 | 
			
		||||
#: ../js/ui/screenShield.js:80
 | 
			
		||||
msgid "%A, %B %d"
 | 
			
		||||
msgstr "%A, %B %d"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/screenShield.js:143
 | 
			
		||||
#: ../js/ui/screenShield.js:144
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%d new message"
 | 
			
		||||
msgid_plural "%d new messages"
 | 
			
		||||
msgstr[0] "%d ny melding"
 | 
			
		||||
msgstr[1] "%d nye meldinger"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/screenShield.js:145
 | 
			
		||||
#: ../js/ui/screenShield.js:146
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%d new notification"
 | 
			
		||||
msgid_plural "%d new notifications"
 | 
			
		||||
@@ -1168,7 +1236,7 @@ msgstr "Passord"
 | 
			
		||||
msgid "Remember Password"
 | 
			
		||||
msgstr "Husk passord"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/shellMountOperation.js:400 ../js/ui/unlockDialog.js:169
 | 
			
		||||
#: ../js/ui/shellMountOperation.js:400 ../js/ui/unlockDialog.js:174
 | 
			
		||||
msgid "Unlock"
 | 
			
		||||
msgstr "Lås opp"
 | 
			
		||||
 | 
			
		||||
@@ -1223,7 +1291,7 @@ msgstr "Stor tekst"
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:27 ../js/ui/status/bluetooth.js:31
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:251 ../js/ui/status/bluetooth.js:304
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:335 ../js/ui/status/bluetooth.js:371
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:400 ../js/ui/status/network.js:867
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:400 ../js/ui/status/network.js:873
 | 
			
		||||
msgid "Bluetooth"
 | 
			
		||||
msgstr "Bluetooth"
 | 
			
		||||
 | 
			
		||||
@@ -1252,12 +1320,12 @@ msgstr "maskinvare slått av"
 | 
			
		||||
msgid "Connection"
 | 
			
		||||
msgstr "Tilkobling"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:207 ../js/ui/status/network.js:458
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:207 ../js/ui/status/network.js:475
 | 
			
		||||
msgid "disconnecting..."
 | 
			
		||||
msgstr "kobler fra …"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:220 ../js/ui/status/network.js:464
 | 
			
		||||
#: ../js/ui/status/network.js:934
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:220 ../js/ui/status/network.js:481
 | 
			
		||||
#: ../js/ui/status/network.js:1507
 | 
			
		||||
msgid "connecting..."
 | 
			
		||||
msgstr "kobler til …"
 | 
			
		||||
 | 
			
		||||
@@ -1367,109 +1435,106 @@ msgstr "slått av"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is for network devices that are physically present but are not
 | 
			
		||||
#. under NetworkManager's control (and thus cannot be used in the menu)
 | 
			
		||||
#: ../js/ui/status/network.js:456
 | 
			
		||||
#: ../js/ui/status/network.js:473
 | 
			
		||||
msgid "unmanaged"
 | 
			
		||||
msgstr "ikke håndtert"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is for network connections that require some kind of key or password
 | 
			
		||||
#: ../js/ui/status/network.js:467 ../js/ui/status/network.js:937
 | 
			
		||||
#: ../js/ui/status/network.js:484 ../js/ui/status/network.js:1510
 | 
			
		||||
msgid "authentication required"
 | 
			
		||||
msgstr "autentisering kreves"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is for devices that require some kind of firmware or kernel
 | 
			
		||||
#. module, which is missing
 | 
			
		||||
#: ../js/ui/status/network.js:477
 | 
			
		||||
#: ../js/ui/status/network.js:494
 | 
			
		||||
msgid "firmware missing"
 | 
			
		||||
msgstr "fastvare mangler"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is for wired network devices that are physically disconnected
 | 
			
		||||
#: ../js/ui/status/network.js:484
 | 
			
		||||
#: ../js/ui/status/network.js:501
 | 
			
		||||
msgid "cable unplugged"
 | 
			
		||||
msgstr "kabel koblet fra"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is for a network device that cannot be activated (for example it
 | 
			
		||||
#. is disabled by rfkill, or it has no coverage
 | 
			
		||||
#: ../js/ui/status/network.js:489
 | 
			
		||||
#: ../js/ui/status/network.js:506
 | 
			
		||||
msgid "unavailable"
 | 
			
		||||
msgstr "ikke tilgjengelig"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:491 ../js/ui/status/network.js:939
 | 
			
		||||
#: ../js/ui/status/network.js:508 ../js/ui/status/network.js:1512
 | 
			
		||||
msgid "connection failed"
 | 
			
		||||
msgstr "tilkobling feilet"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:552 ../js/ui/status/network.js:1529
 | 
			
		||||
#: ../js/ui/status/network.js:560 ../js/ui/status/network.js:1446
 | 
			
		||||
#: ../js/ui/status/network.js:1588
 | 
			
		||||
msgid "More..."
 | 
			
		||||
msgstr "Mer …"
 | 
			
		||||
 | 
			
		||||
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
 | 
			
		||||
#. and we cannot access its settings (including the name)
 | 
			
		||||
#: ../js/ui/status/network.js:588 ../js/ui/status/network.js:1459
 | 
			
		||||
#: ../js/ui/status/network.js:596 ../js/ui/status/network.js:1376
 | 
			
		||||
msgid "Connected (private)"
 | 
			
		||||
msgstr "Tilkoblet (privat)"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:663
 | 
			
		||||
#: ../js/ui/status/network.js:669
 | 
			
		||||
msgid "Auto Ethernet"
 | 
			
		||||
msgstr "Automatisk Ethernet"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:721
 | 
			
		||||
#: ../js/ui/status/network.js:727
 | 
			
		||||
msgid "Auto broadband"
 | 
			
		||||
msgstr "Automatisk bredbånd"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:724
 | 
			
		||||
#: ../js/ui/status/network.js:730
 | 
			
		||||
msgid "Auto dial-up"
 | 
			
		||||
msgstr "Automatisk oppringt"
 | 
			
		||||
 | 
			
		||||
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
 | 
			
		||||
#: ../js/ui/status/network.js:853 ../js/ui/status/network.js:1476
 | 
			
		||||
#: ../js/ui/status/network.js:859 ../js/ui/status/network.js:1393
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Auto %s"
 | 
			
		||||
msgstr "Automatisk %s"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:855
 | 
			
		||||
#: ../js/ui/status/network.js:861
 | 
			
		||||
msgid "Auto bluetooth"
 | 
			
		||||
msgstr "Automatisk Bluetooth"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1478
 | 
			
		||||
#: ../js/ui/status/network.js:1395
 | 
			
		||||
msgid "Auto wireless"
 | 
			
		||||
msgstr "Automatisk trådløst"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1575
 | 
			
		||||
#: ../js/ui/status/network.js:1637
 | 
			
		||||
msgid "Enable networking"
 | 
			
		||||
msgstr "Slå på nettverk"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1597
 | 
			
		||||
#: ../js/ui/status/network.js:1659
 | 
			
		||||
msgid "Wired"
 | 
			
		||||
msgstr "Kablet"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1608
 | 
			
		||||
#: ../js/ui/status/network.js:1670
 | 
			
		||||
msgid "Wireless"
 | 
			
		||||
msgstr "Trådløst"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1618
 | 
			
		||||
#: ../js/ui/status/network.js:1680
 | 
			
		||||
msgid "Mobile broadband"
 | 
			
		||||
msgstr "Mobilt bredbånd"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1628
 | 
			
		||||
msgid "VPN Connections"
 | 
			
		||||
msgstr "VPN-tilkoblinger"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1635
 | 
			
		||||
#: ../js/ui/status/network.js:1691
 | 
			
		||||
msgid "Network Settings"
 | 
			
		||||
msgstr "Innstillinger for nettverk"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1679
 | 
			
		||||
#: ../js/ui/status/network.js:1735
 | 
			
		||||
msgid "Network Manager"
 | 
			
		||||
msgstr "Nettverkshåndtering"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1769
 | 
			
		||||
#: ../js/ui/status/network.js:1809
 | 
			
		||||
msgid "Connection failed"
 | 
			
		||||
msgstr "Tilkobling feilet"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1770
 | 
			
		||||
#: ../js/ui/status/network.js:1810
 | 
			
		||||
msgid "Activation of network connection failed"
 | 
			
		||||
msgstr "Aktivering av nettverkstilkobling feilet"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:2065
 | 
			
		||||
#: ../js/ui/status/network.js:2108
 | 
			
		||||
msgid "Networking is disabled"
 | 
			
		||||
msgstr "Nettverk er slått av"
 | 
			
		||||
 | 
			
		||||
@@ -1579,63 +1644,63 @@ msgstr "Volum"
 | 
			
		||||
msgid "Microphone"
 | 
			
		||||
msgstr "Mikrofon"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/unlockDialog.js:176
 | 
			
		||||
#: ../js/ui/unlockDialog.js:181
 | 
			
		||||
msgid "Log in as another user"
 | 
			
		||||
msgstr "Logg inn som en annen bruker"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:180
 | 
			
		||||
#: ../js/ui/userMenu.js:176
 | 
			
		||||
msgid "Available"
 | 
			
		||||
msgstr "Tilgjengelig"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:183
 | 
			
		||||
#: ../js/ui/userMenu.js:179
 | 
			
		||||
msgid "Busy"
 | 
			
		||||
msgstr "Opptatt"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:186
 | 
			
		||||
#: ../js/ui/userMenu.js:182
 | 
			
		||||
msgid "Invisible"
 | 
			
		||||
msgstr "Usynlig"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:189
 | 
			
		||||
#: ../js/ui/userMenu.js:185
 | 
			
		||||
msgid "Away"
 | 
			
		||||
msgstr "Borte"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:192
 | 
			
		||||
#: ../js/ui/userMenu.js:188
 | 
			
		||||
msgid "Idle"
 | 
			
		||||
msgstr "Ledig"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:195
 | 
			
		||||
msgid "Unavailable"
 | 
			
		||||
msgstr "Ikke tilgjengelig"
 | 
			
		||||
#: ../js/ui/userMenu.js:191
 | 
			
		||||
msgid "Offline"
 | 
			
		||||
msgstr "Frakoblet"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:740
 | 
			
		||||
#: ../js/ui/userMenu.js:747
 | 
			
		||||
msgid "Notifications"
 | 
			
		||||
msgstr "Varslinger"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:748
 | 
			
		||||
#: ../js/ui/userMenu.js:755
 | 
			
		||||
msgid "System Settings"
 | 
			
		||||
msgstr "Systeminnstillinger"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:756
 | 
			
		||||
#: ../js/ui/userMenu.js:763
 | 
			
		||||
msgid "Switch User"
 | 
			
		||||
msgstr "Bytt bruker"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:761
 | 
			
		||||
#: ../js/ui/userMenu.js:768
 | 
			
		||||
msgid "Log Out"
 | 
			
		||||
msgstr "Logg ut"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:766
 | 
			
		||||
#: ../js/ui/userMenu.js:773
 | 
			
		||||
msgid "Lock"
 | 
			
		||||
msgstr "Lås"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:781
 | 
			
		||||
#: ../js/ui/userMenu.js:788
 | 
			
		||||
msgid "Install Updates & Restart"
 | 
			
		||||
msgstr "Installer oppdateringer og start på nytt"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:799
 | 
			
		||||
#: ../js/ui/userMenu.js:806
 | 
			
		||||
msgid "Your chat status will be set to busy"
 | 
			
		||||
msgstr "Din pratestatus vil bli satt til opptatt"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:800
 | 
			
		||||
#: ../js/ui/userMenu.js:807
 | 
			
		||||
msgid ""
 | 
			
		||||
"Notifications are now disabled, including chat messages. Your online status "
 | 
			
		||||
"has been adjusted to let others know that you might not see their messages."
 | 
			
		||||
@@ -1644,15 +1709,15 @@ msgstr ""
 | 
			
		||||
"tilkoblingsstatus er justert for å la andre vite at du kanskje ikke ser "
 | 
			
		||||
"deres meldinger."
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/viewSelector.js:85
 | 
			
		||||
#: ../js/ui/viewSelector.js:87
 | 
			
		||||
msgid "Windows"
 | 
			
		||||
msgstr "Vinduer"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/viewSelector.js:89
 | 
			
		||||
#: ../js/ui/viewSelector.js:91
 | 
			
		||||
msgid "Applications"
 | 
			
		||||
msgstr "Programmer"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/viewSelector.js:93
 | 
			
		||||
#: ../js/ui/viewSelector.js:95
 | 
			
		||||
msgid "Search"
 | 
			
		||||
msgstr "Søk"
 | 
			
		||||
 | 
			
		||||
@@ -1721,7 +1786,7 @@ msgstr "Bruk spesifikt modus, f.eks «gdm» for innloggingsskjerm"
 | 
			
		||||
msgid "List possible modes"
 | 
			
		||||
msgstr "Vis mulige modi"
 | 
			
		||||
 | 
			
		||||
#: ../src/shell-app.c:621
 | 
			
		||||
#: ../src/shell-app.c:622
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Failed to launch '%s'"
 | 
			
		||||
msgstr "Klarte ikke å starte «%s»"
 | 
			
		||||
 
 | 
			
		||||
@@ -119,7 +119,6 @@ shell_public_headers_h =		\
 | 
			
		||||
	shell-network-agent.h		\
 | 
			
		||||
	shell-perf-log.h		\
 | 
			
		||||
	shell-screenshot.h		\
 | 
			
		||||
	shell-screen-grabber.h		\
 | 
			
		||||
	shell-slicer.h			\
 | 
			
		||||
	shell-stack.h			\
 | 
			
		||||
	shell-tp-client.h		\
 | 
			
		||||
@@ -167,7 +166,6 @@ libgnome_shell_la_SOURCES =		\
 | 
			
		||||
	shell-polkit-authentication-agent.h	\
 | 
			
		||||
	shell-polkit-authentication-agent.c	\
 | 
			
		||||
	shell-screenshot.c		\
 | 
			
		||||
	shell-screen-grabber.c		\
 | 
			
		||||
	shell-secure-text-buffer.c	\
 | 
			
		||||
	shell-secure-text-buffer.h	\
 | 
			
		||||
	shell-slicer.c			\
 | 
			
		||||
@@ -232,8 +230,6 @@ test_recorder_LDADD = $(TEST_SHELL_RECORDER_LIBS)
 | 
			
		||||
 | 
			
		||||
test_recorder_SOURCES =     \
 | 
			
		||||
	$(shell_recorder_sources) $(shell_recorder_private_sources) \
 | 
			
		||||
	shell-screen-grabber.c	\
 | 
			
		||||
	shell-screen-grabber.h	\
 | 
			
		||||
	test-recorder.c
 | 
			
		||||
endif BUILD_RECORDER
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1035,8 +1035,6 @@ main (int    argc,
 | 
			
		||||
  name_owner_id = 0;
 | 
			
		||||
  stdin_channel = NULL;
 | 
			
		||||
 | 
			
		||||
  g_type_init ();
 | 
			
		||||
 | 
			
		||||
  introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
 | 
			
		||||
  g_assert (introspection_data != NULL);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ def show_version(option, opt_str, value, parser):
 | 
			
		||||
def wait_for_dbus_name(wait_name):
 | 
			
		||||
    loop = GLib.MainLoop()
 | 
			
		||||
 | 
			
		||||
    def on_name_appeared(connection, name, name_owner, *args):
 | 
			
		||||
    def on_name_appeared(connection, name, new_owner, *args):
 | 
			
		||||
        if not (name == wait_name and new_owner != ''):
 | 
			
		||||
            return
 | 
			
		||||
        loop.quit()
 | 
			
		||||
@@ -60,13 +60,18 @@ def start_perf_helper():
 | 
			
		||||
    wait_for_dbus_name (PERF_HELPER_NAME)
 | 
			
		||||
 | 
			
		||||
def stop_perf_helper():
 | 
			
		||||
    proxy = Gio.DBusProxy(g_bus_type=Gio.BusType.SESSION,
 | 
			
		||||
                          g_name=PERF_HELPER_NAME,
 | 
			
		||||
                          g_interface=PERF_HELPER_IFACE,
 | 
			
		||||
                          g_object_path=PERF_HELPER_PATH)
 | 
			
		||||
    bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
 | 
			
		||||
 | 
			
		||||
    proxy = Gio.DBusProxy.new_sync(bus,
 | 
			
		||||
                                   Gio.DBusProxyFlags.NONE,
 | 
			
		||||
                                   None,
 | 
			
		||||
                                   PERF_HELPER_NAME,
 | 
			
		||||
                                   PERF_HELPER_PATH,
 | 
			
		||||
                                   PERF_HELPER_IFACE,
 | 
			
		||||
                                   None)
 | 
			
		||||
    proxy.Exit()
 | 
			
		||||
 | 
			
		||||
def start_shell(extra_args, perf_output=None):
 | 
			
		||||
def start_shell(perf_output=None):
 | 
			
		||||
    # Set up environment
 | 
			
		||||
    env = dict(os.environ)
 | 
			
		||||
    env['SHELL_PERF_MODULE'] = options.perf
 | 
			
		||||
@@ -76,19 +81,21 @@ def start_shell(extra_args, perf_output=None):
 | 
			
		||||
        env['SHELL_PERF_OUTPUT'] = perf_output
 | 
			
		||||
 | 
			
		||||
    self_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
 | 
			
		||||
    args = []
 | 
			
		||||
    args.append(os.path.join(self_dir, 'gnome-shell'))
 | 
			
		||||
    # pass on any additional arguments
 | 
			
		||||
    args += extra_args
 | 
			
		||||
 | 
			
		||||
    if options.replace:
 | 
			
		||||
        args.append('--replace')
 | 
			
		||||
 | 
			
		||||
    return subprocess.Popen(args, env=env)
 | 
			
		||||
 | 
			
		||||
def run_shell(args, perf_output=None):
 | 
			
		||||
def run_shell(perf_output=None):
 | 
			
		||||
    # we do no additional supervision of gnome-shell,
 | 
			
		||||
    # beyond that of wait
 | 
			
		||||
    # in particular, we don't kill the shell upon
 | 
			
		||||
    # receving a KeyboardInterrupt, as we expect to be
 | 
			
		||||
    # in the same process group
 | 
			
		||||
    shell = start_shell(extra_args, perf_output=perf_output)
 | 
			
		||||
    shell = start_shell(perf_output=perf_output)
 | 
			
		||||
    shell.wait()
 | 
			
		||||
    return shell.returncode == 0
 | 
			
		||||
 | 
			
		||||
@@ -173,7 +180,7 @@ def upload_performance_report(report_text):
 | 
			
		||||
        print "Performance report upload failed with status %d" % response.status
 | 
			
		||||
        print response.read()
 | 
			
		||||
 | 
			
		||||
def run_performance_test(args):
 | 
			
		||||
def run_performance_test():
 | 
			
		||||
    iters = options.perf_iters
 | 
			
		||||
    if options.perf_warmup:
 | 
			
		||||
        iters += 1
 | 
			
		||||
@@ -192,7 +199,7 @@ def run_performance_test(args):
 | 
			
		||||
        # Run the performance test and collect the output as JSON
 | 
			
		||||
        normal_exit = False
 | 
			
		||||
        try:
 | 
			
		||||
            normal_exit = run_shell(args, perf_output=output_file)
 | 
			
		||||
            normal_exit = run_shell(perf_output=output_file)
 | 
			
		||||
        except:
 | 
			
		||||
            stop_perf_helper()
 | 
			
		||||
            raise
 | 
			
		||||
@@ -288,7 +295,8 @@ def run_performance_test(args):
 | 
			
		||||
 | 
			
		||||
parser = optparse.OptionParser()
 | 
			
		||||
parser.add_option("", "--perf", metavar="PERF_MODULE",
 | 
			
		||||
		  help="Specify the name of a performance module to run")
 | 
			
		||||
		  help="Specify the name of a performance module to run",
 | 
			
		||||
                  default="core")
 | 
			
		||||
parser.add_option("", "--perf-iters", type="int", metavar="ITERS",
 | 
			
		||||
		  help="Numbers of iterations of performance module to run",
 | 
			
		||||
                  default=1)
 | 
			
		||||
@@ -301,9 +309,16 @@ parser.add_option("", "--perf-upload", action="store_true",
 | 
			
		||||
parser.add_option("", "--version", action="callback", callback=show_version,
 | 
			
		||||
                  help="Display version and exit")
 | 
			
		||||
 | 
			
		||||
parser.add_option("-r", "--replace", action="store_true",
 | 
			
		||||
                  help="Replace the running window manager")
 | 
			
		||||
 | 
			
		||||
options, args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
normal_exit = run_performance_test(args)
 | 
			
		||||
if args:
 | 
			
		||||
    parser.print_usage()
 | 
			
		||||
    sys.exit(1)
 | 
			
		||||
 | 
			
		||||
normal_exit = run_performance_test()
 | 
			
		||||
if normal_exit:
 | 
			
		||||
    sys.exit(0)
 | 
			
		||||
else:
 | 
			
		||||
 
 | 
			
		||||
@@ -72,6 +72,9 @@ static void gnome_shell_plugin_kill_switch_workspace (MetaPlugin      *plugin);
 | 
			
		||||
 | 
			
		||||
static gboolean              gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
 | 
			
		||||
                                                               XEvent     *event);
 | 
			
		||||
 | 
			
		||||
static gboolean              gnome_shell_plugin_keybinding_filter (MetaPlugin *plugin,
 | 
			
		||||
                                                                   MetaKeyBinding *binding);
 | 
			
		||||
static const MetaPluginInfo *gnome_shell_plugin_plugin_info   (MetaPlugin *plugin);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -126,8 +129,9 @@ gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
 | 
			
		||||
  plugin_class->kill_window_effects   = gnome_shell_plugin_kill_window_effects;
 | 
			
		||||
  plugin_class->kill_switch_workspace = gnome_shell_plugin_kill_switch_workspace;
 | 
			
		||||
 | 
			
		||||
  plugin_class->xevent_filter    = gnome_shell_plugin_xevent_filter;
 | 
			
		||||
  plugin_class->plugin_info      = gnome_shell_plugin_plugin_info;
 | 
			
		||||
  plugin_class->xevent_filter     = gnome_shell_plugin_xevent_filter;
 | 
			
		||||
  plugin_class->keybinding_filter = gnome_shell_plugin_keybinding_filter;
 | 
			
		||||
  plugin_class->plugin_info       = gnome_shell_plugin_plugin_info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -337,6 +341,13 @@ gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
 | 
			
		||||
  return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
gnome_shell_plugin_keybinding_filter (MetaPlugin     *plugin,
 | 
			
		||||
                                      MetaKeyBinding *binding)
 | 
			
		||||
{
 | 
			
		||||
  return _shell_wm_filter_keybinding (get_shell_wm (), binding);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const
 | 
			
		||||
MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ extern GType gnome_shell_plugin_get_type (void);
 | 
			
		||||
#define OVERRIDES_SCHEMA "org.gnome.shell.overrides"
 | 
			
		||||
 | 
			
		||||
#define WM_NAME "GNOME Shell"
 | 
			
		||||
#define GNOME_WM_KEYBINDINGS "Metacity,Mutter,GNOME Shell"
 | 
			
		||||
#define GNOME_WM_KEYBINDINGS "Mutter,GNOME Shell"
 | 
			
		||||
 | 
			
		||||
static gboolean is_gdm_mode = FALSE;
 | 
			
		||||
static char *session_mode = NULL;
 | 
			
		||||
 
 | 
			
		||||
@@ -1007,54 +1007,6 @@ shell_global_end_modal (ShellGlobal *global,
 | 
			
		||||
  meta_plugin_end_modal (global->plugin, timestamp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_global_create_pointer_barrier:
 | 
			
		||||
 * @global: a #ShellGlobal
 | 
			
		||||
 * @x1: left X coordinate
 | 
			
		||||
 * @y1: top Y coordinate
 | 
			
		||||
 * @x2: right X coordinate
 | 
			
		||||
 * @y2: bottom Y coordinate
 | 
			
		||||
 * @directions: The directions we're allowed to pass through
 | 
			
		||||
 *
 | 
			
		||||
 * If supported by X creates a pointer barrier.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: value you can pass to shell_global_destroy_pointer_barrier()
 | 
			
		||||
 */
 | 
			
		||||
guint32
 | 
			
		||||
shell_global_create_pointer_barrier (ShellGlobal *global,
 | 
			
		||||
                                     int x1, int y1, int x2, int y2,
 | 
			
		||||
                                     int directions)
 | 
			
		||||
{
 | 
			
		||||
#if HAVE_XFIXESCREATEPOINTERBARRIER
 | 
			
		||||
  return (guint32)
 | 
			
		||||
    XFixesCreatePointerBarrier (global->xdisplay,
 | 
			
		||||
                                DefaultRootWindow (global->xdisplay),
 | 
			
		||||
                                x1, y1,
 | 
			
		||||
                                x2, y2,
 | 
			
		||||
                                directions,
 | 
			
		||||
                                0, NULL);
 | 
			
		||||
#else
 | 
			
		||||
  return 0;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_global_destroy_pointer_barrier:
 | 
			
		||||
 * @global: a #ShellGlobal
 | 
			
		||||
 * @barrier: a pointer barrier
 | 
			
		||||
 *
 | 
			
		||||
 * Destroys the @barrier created by shell_global_create_pointer_barrier().
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
shell_global_destroy_pointer_barrier (ShellGlobal *global, guint32 barrier)
 | 
			
		||||
{
 | 
			
		||||
#if HAVE_XFIXESCREATEPOINTERBARRIER
 | 
			
		||||
  g_return_if_fail (barrier > 0);
 | 
			
		||||
 | 
			
		||||
  XFixesDestroyPointerBarrier (global->xdisplay, (PointerBarrier)barrier);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Code to close all file descriptors before we exec; copied from gspawn.c in GLib.
 | 
			
		||||
 *
 | 
			
		||||
 * Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering
 | 
			
		||||
 
 | 
			
		||||
@@ -70,15 +70,6 @@ void    shell_global_set_cursor              (ShellGlobal         *global,
 | 
			
		||||
                                              ShellCursor          type);
 | 
			
		||||
void    shell_global_unset_cursor            (ShellGlobal         *global);
 | 
			
		||||
 | 
			
		||||
guint32 shell_global_create_pointer_barrier  (ShellGlobal         *global,
 | 
			
		||||
                                              int                  x1,
 | 
			
		||||
                                              int                  y1,
 | 
			
		||||
                                              int                  x2,
 | 
			
		||||
                                              int                  y2,
 | 
			
		||||
                                              int                  directions);
 | 
			
		||||
void    shell_global_destroy_pointer_barrier (ShellGlobal         *global,
 | 
			
		||||
                                              guint32              barrier);
 | 
			
		||||
 | 
			
		||||
void    shell_global_get_pointer             (ShellGlobal         *global,
 | 
			
		||||
                                              int                 *x,
 | 
			
		||||
                                              int                 *y,
 | 
			
		||||
 
 | 
			
		||||
@@ -37,10 +37,11 @@
 | 
			
		||||
 | 
			
		||||
#define ISO_3166_COUNTRY_CODES DATADIR "/zoneinfo/iso3166.tab"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static ShellCountryMobileProvider *country_mobile_provider_new (const char *country_code,
 | 
			
		||||
                                                                const gchar *country_name);
 | 
			
		||||
 | 
			
		||||
static GHashTable *
 | 
			
		||||
read_country_codes (void)
 | 
			
		||||
read_country_codes (const gchar *country_codes)
 | 
			
		||||
{
 | 
			
		||||
    GHashTable *table;
 | 
			
		||||
    GIOChannel *channel;
 | 
			
		||||
@@ -48,18 +49,21 @@ read_country_codes (void)
 | 
			
		||||
    GError *error = NULL;
 | 
			
		||||
    GIOStatus status;
 | 
			
		||||
 | 
			
		||||
    channel = g_io_channel_new_file (ISO_3166_COUNTRY_CODES, "r", &error);
 | 
			
		||||
    channel = g_io_channel_new_file (country_codes, "r", &error);
 | 
			
		||||
    if (!channel) {
 | 
			
		||||
        if (error) {
 | 
			
		||||
            g_warning ("Could not read " ISO_3166_COUNTRY_CODES ": %s", error->message);
 | 
			
		||||
            g_warning ("Could not read %s: %s", country_codes, error->message);
 | 
			
		||||
            g_error_free (error);
 | 
			
		||||
        } else
 | 
			
		||||
            g_warning ("Could not read " ISO_3166_COUNTRY_CODES ": Unknown error");
 | 
			
		||||
            g_warning ("Could not read %s: Unknown error", country_codes);
 | 
			
		||||
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 | 
			
		||||
    table = g_hash_table_new_full (g_str_hash,
 | 
			
		||||
                                   g_str_equal,
 | 
			
		||||
                                   g_free,
 | 
			
		||||
                                   (GDestroyNotify)shell_country_mobile_provider_unref);
 | 
			
		||||
    buffer = g_string_sized_new (32);
 | 
			
		||||
 | 
			
		||||
    status = G_IO_STATUS_NORMAL;
 | 
			
		||||
@@ -69,6 +73,7 @@ read_country_codes (void)
 | 
			
		||||
        switch (status) {
 | 
			
		||||
        case G_IO_STATUS_NORMAL:
 | 
			
		||||
            if (buffer->str[0] != '#') {
 | 
			
		||||
                ShellCountryMobileProvider *country_provider;
 | 
			
		||||
                char **pieces;
 | 
			
		||||
 | 
			
		||||
                pieces = g_strsplit (buffer->str, "\t", 2);
 | 
			
		||||
@@ -80,7 +85,8 @@ read_country_codes (void)
 | 
			
		||||
                    pieces[1] = g_strdup (_("United Kingdom"));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                g_hash_table_insert (table, pieces[0], pieces[1]);
 | 
			
		||||
                country_provider = country_mobile_provider_new (pieces[0], pieces[1]);
 | 
			
		||||
                g_hash_table_insert (table, pieces[0], country_provider);
 | 
			
		||||
                g_free (pieces);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -117,7 +123,6 @@ typedef enum {
 | 
			
		||||
} MobileContextState;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    GHashTable *country_codes;
 | 
			
		||||
    GHashTable *table;
 | 
			
		||||
 | 
			
		||||
    char *current_country;
 | 
			
		||||
@@ -276,6 +281,86 @@ shell_mobile_provider_get_type (void)
 | 
			
		||||
    return type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ShellCountryMobileProvider *
 | 
			
		||||
country_mobile_provider_new (const char *country_code,
 | 
			
		||||
                             const gchar *country_name)
 | 
			
		||||
{
 | 
			
		||||
    ShellCountryMobileProvider *country_provider;
 | 
			
		||||
 | 
			
		||||
    country_provider = g_slice_new0 (ShellCountryMobileProvider);
 | 
			
		||||
    country_provider->refs = 1;
 | 
			
		||||
    country_provider->country_code = g_strdup (country_code);
 | 
			
		||||
    country_provider->country_name = g_strdup (country_name);
 | 
			
		||||
    return country_provider;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ShellCountryMobileProvider *
 | 
			
		||||
shell_country_mobile_provider_ref (ShellCountryMobileProvider *country_provider)
 | 
			
		||||
{
 | 
			
		||||
    country_provider->refs++;
 | 
			
		||||
 | 
			
		||||
    return country_provider;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
shell_country_mobile_provider_unref (ShellCountryMobileProvider *country_provider)
 | 
			
		||||
{
 | 
			
		||||
    if (--country_provider->refs == 0) {
 | 
			
		||||
        g_free (country_provider->country_code);
 | 
			
		||||
        g_free (country_provider->country_name);
 | 
			
		||||
        g_slist_free_full (country_provider->providers,
 | 
			
		||||
                           (GDestroyNotify) shell_mobile_provider_unref);
 | 
			
		||||
        g_slice_free (ShellCountryMobileProvider, country_provider);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_country_mobile_provider_get_country_code:
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (transfer none): the code of the country.
 | 
			
		||||
 */
 | 
			
		||||
const gchar *
 | 
			
		||||
shell_country_mobile_provider_get_country_code (ShellCountryMobileProvider *country_provider)
 | 
			
		||||
{
 | 
			
		||||
    return country_provider->country_code;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_country_mobile_provider_get_country_name:
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (transfer none): the name of the country.
 | 
			
		||||
 */
 | 
			
		||||
const gchar *
 | 
			
		||||
shell_country_mobile_provider_get_country_name (ShellCountryMobileProvider *country_provider)
 | 
			
		||||
{
 | 
			
		||||
    return country_provider->country_name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_country_mobile_provider_get_providers:
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (element-type Shell.MobileProvider) (transfer none): the
 | 
			
		||||
 *   list of #ShellMobileProvider this country exposes.
 | 
			
		||||
 */
 | 
			
		||||
GSList *
 | 
			
		||||
shell_country_mobile_provider_get_providers (ShellCountryMobileProvider *country_provider)
 | 
			
		||||
{
 | 
			
		||||
    return country_provider->providers;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
shell_country_mobile_provider_get_type (void)
 | 
			
		||||
{
 | 
			
		||||
    static GType type = 0;
 | 
			
		||||
 | 
			
		||||
    if (G_UNLIKELY (type == 0)) {
 | 
			
		||||
        type = g_boxed_type_register_static ("ShellCountryMobileProvider",
 | 
			
		||||
                                             (GBoxedCopyFunc) shell_country_mobile_provider_ref,
 | 
			
		||||
                                             (GBoxedFreeFunc) shell_country_mobile_provider_unref);
 | 
			
		||||
    }
 | 
			
		||||
    return type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
provider_list_free (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
@@ -310,15 +395,17 @@ parser_toplevel_start (MobileParser *parser,
 | 
			
		||||
        for (i = 0; attribute_names && attribute_names[i]; i++) {
 | 
			
		||||
            if (!strcmp (attribute_names[i], "code")) {
 | 
			
		||||
                char *country_code;
 | 
			
		||||
                char *country;
 | 
			
		||||
                ShellCountryMobileProvider *country_provider;
 | 
			
		||||
 | 
			
		||||
                country_code = g_ascii_strup (attribute_values[i], -1);
 | 
			
		||||
                country = g_hash_table_lookup (parser->country_codes, country_code);
 | 
			
		||||
                if (country) {
 | 
			
		||||
                    parser->current_country = g_strdup (country);
 | 
			
		||||
                    g_free (country_code);
 | 
			
		||||
                } else
 | 
			
		||||
                    parser->current_country = country_code;
 | 
			
		||||
                country_provider = g_hash_table_lookup (parser->table, country_code);
 | 
			
		||||
                /* Ensure we have a country provider for this country code */
 | 
			
		||||
                if (!country_provider) {
 | 
			
		||||
                    g_warning ("%s: adding providers for unknown country '%s'", __func__, country_code);
 | 
			
		||||
                    country_provider = country_mobile_provider_new (country_code, NULL);
 | 
			
		||||
                    g_hash_table_insert (parser->table, country_code, country_provider);
 | 
			
		||||
                }
 | 
			
		||||
                parser->current_country = country_code;
 | 
			
		||||
 | 
			
		||||
                parser->state = PARSER_COUNTRY;
 | 
			
		||||
                break;
 | 
			
		||||
@@ -455,7 +542,13 @@ parser_country_end (MobileParser *parser,
 | 
			
		||||
                    const char *name)
 | 
			
		||||
{
 | 
			
		||||
    if (!strcmp (name, "country")) {
 | 
			
		||||
        g_hash_table_insert (parser->table, parser->current_country, parser->current_providers);
 | 
			
		||||
        ShellCountryMobileProvider *country_provider;
 | 
			
		||||
 | 
			
		||||
        country_provider = g_hash_table_lookup (parser->table, parser->current_country);
 | 
			
		||||
        if (country_provider)
 | 
			
		||||
            /* Store providers for this country */
 | 
			
		||||
            country_provider->providers = parser->current_providers;
 | 
			
		||||
 | 
			
		||||
        parser->current_country = NULL;
 | 
			
		||||
        parser->current_providers = NULL;
 | 
			
		||||
        parser->text_buffer = NULL;
 | 
			
		||||
@@ -616,15 +709,16 @@ static const GMarkupParser mobile_parser = {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_mobile_providers_parse:
 | 
			
		||||
 * @out_ccs: (out) (allow-none): (element-type utf8 utf8): a #GHashTable containing
 | 
			
		||||
 *   country codes
 | 
			
		||||
 * @country_codes: (allow-none) File with the list of country codes.
 | 
			
		||||
 * @service_providers: (allow-none) File with the list of service providers.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (element-type utf8 GList) (transfer container): a
 | 
			
		||||
 *   hash table where keys are country names #gchar, values are a #GSList
 | 
			
		||||
 *   of #ShellMobileProvider. Everything is destroyed with g_hash_table_destroy().
 | 
			
		||||
*/
 | 
			
		||||
 * Returns: (element-type utf8 Shell.CountryMobileProvider) (transfer full): a
 | 
			
		||||
 *   hash table where keys are country names #gchar and values are #ShellCountryMobileProvider.
 | 
			
		||||
 *   Everything is destroyed with g_hash_table_destroy().
 | 
			
		||||
 */
 | 
			
		||||
GHashTable *
 | 
			
		||||
shell_mobile_providers_parse (GHashTable **out_ccs)
 | 
			
		||||
shell_mobile_providers_parse (const gchar *country_codes,
 | 
			
		||||
                              const gchar *service_providers)
 | 
			
		||||
{
 | 
			
		||||
    GMarkupParseContext *ctx;
 | 
			
		||||
    GIOChannel *channel;
 | 
			
		||||
@@ -634,24 +728,29 @@ shell_mobile_providers_parse (GHashTable **out_ccs)
 | 
			
		||||
    GIOStatus status;
 | 
			
		||||
    gsize len = 0;
 | 
			
		||||
 | 
			
		||||
    /* Use default paths if none given */
 | 
			
		||||
    if (!country_codes)
 | 
			
		||||
        country_codes = ISO_3166_COUNTRY_CODES;
 | 
			
		||||
    if (!service_providers)
 | 
			
		||||
        service_providers = MOBILE_BROADBAND_PROVIDER_INFO;
 | 
			
		||||
 | 
			
		||||
    memset (&parser, 0, sizeof (MobileParser));
 | 
			
		||||
 | 
			
		||||
    parser.country_codes = read_country_codes ();
 | 
			
		||||
    if (!parser.country_codes)
 | 
			
		||||
    parser.table = read_country_codes (country_codes);
 | 
			
		||||
    if (!parser.table)
 | 
			
		||||
        goto out;
 | 
			
		||||
 | 
			
		||||
    channel = g_io_channel_new_file (MOBILE_BROADBAND_PROVIDER_INFO, "r", &error);
 | 
			
		||||
    channel = g_io_channel_new_file (service_providers, "r", &error);
 | 
			
		||||
    if (!channel) {
 | 
			
		||||
        if (error) {
 | 
			
		||||
            g_warning ("Could not read " MOBILE_BROADBAND_PROVIDER_INFO ": %s", error->message);
 | 
			
		||||
            g_warning ("Could not read %s: %s", service_providers, error->message);
 | 
			
		||||
            g_error_free (error);
 | 
			
		||||
        } else
 | 
			
		||||
            g_warning ("Could not read " MOBILE_BROADBAND_PROVIDER_INFO ": Unknown error");
 | 
			
		||||
            g_warning ("Could not read %s: Unknown error", service_providers);
 | 
			
		||||
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    parser.table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, provider_list_free);
 | 
			
		||||
    parser.state = PARSER_TOPLEVEL;
 | 
			
		||||
 | 
			
		||||
    ctx = g_markup_parse_context_new (&mobile_parser, 0, &parser, NULL);
 | 
			
		||||
@@ -696,13 +795,7 @@ shell_mobile_providers_parse (GHashTable **out_ccs)
 | 
			
		||||
    g_free (parser.current_country);
 | 
			
		||||
    g_free (parser.text_buffer);
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
    if (parser.country_codes) {
 | 
			
		||||
        if (out_ccs)
 | 
			
		||||
            *out_ccs = parser.country_codes;
 | 
			
		||||
        else
 | 
			
		||||
            g_hash_table_destroy (parser.country_codes);
 | 
			
		||||
    }
 | 
			
		||||
out:
 | 
			
		||||
 | 
			
		||||
    return parser.table;
 | 
			
		||||
}
 | 
			
		||||
@@ -744,12 +837,17 @@ dump_gsm (ShellMobileAccessMethod *method)
 | 
			
		||||
static void
 | 
			
		||||
dump_country (gpointer key, gpointer value, gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    GSList *citer, *miter;
 | 
			
		||||
    GSList *miter, *citer;
 | 
			
		||||
    ShellCountryMobileProvider *country_provider = value;
 | 
			
		||||
 | 
			
		||||
    for (citer = value; citer; citer = g_slist_next (citer)) {
 | 
			
		||||
    g_print ("Country: %s (%s)\n",
 | 
			
		||||
             country_provider->country_code,
 | 
			
		||||
             country_provider->country_name);
 | 
			
		||||
 | 
			
		||||
    for (citer = country_provider->providers; citer; citer = g_slist_next (citer)) {
 | 
			
		||||
        ShellMobileProvider *provider = citer->data;
 | 
			
		||||
 | 
			
		||||
        g_print ("Provider: %s (%s)\n", provider->name, (const char *) key);
 | 
			
		||||
        g_print ("    Provider: %s (%s)\n", provider->name, (const char *) key);
 | 
			
		||||
        for (miter = provider->methods; miter; miter = g_slist_next (miter)) {
 | 
			
		||||
            ShellMobileAccessMethod *method = miter->data;
 | 
			
		||||
            GSList *liter;
 | 
			
		||||
@@ -779,10 +877,10 @@ dump_country (gpointer key, gpointer value, gpointer user_data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
shell_mobile_providers_dump (GHashTable *providers)
 | 
			
		||||
shell_mobile_providers_dump (GHashTable *country_providers)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (providers != NULL);
 | 
			
		||||
    g_hash_table_foreach (providers, dump_country, NULL);
 | 
			
		||||
    g_return_if_fail (country_providers != NULL);
 | 
			
		||||
    g_hash_table_foreach (country_providers, dump_country, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* All the following don't exist in nm-applet, because C doesn't need
 | 
			
		||||
 
 | 
			
		||||
@@ -76,10 +76,19 @@ typedef struct {
 | 
			
		||||
    gint refs;
 | 
			
		||||
} ShellMobileProvider;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    char *country_code;
 | 
			
		||||
    char *country_name;
 | 
			
		||||
    GSList *providers;
 | 
			
		||||
 | 
			
		||||
    gint refs;
 | 
			
		||||
} ShellCountryMobileProvider;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
GType shell_gsm_mcc_mnc_get_type (void); /* added in porting */
 | 
			
		||||
GType shell_mobile_provider_get_type (void);
 | 
			
		||||
GType shell_mobile_access_method_get_type (void);
 | 
			
		||||
GType shell_mobile_provider_get_type (void);
 | 
			
		||||
GType shell_country_mobile_provider_get_type (void);
 | 
			
		||||
 | 
			
		||||
ShellMobileProvider *shell_mobile_provider_ref   (ShellMobileProvider *provider);
 | 
			
		||||
void                 shell_mobile_provider_unref (ShellMobileProvider *provider);
 | 
			
		||||
@@ -89,8 +98,14 @@ GSList *             shell_mobile_provider_get_cdma_sid (ShellMobileProvider *pr
 | 
			
		||||
ShellMobileAccessMethod *shell_mobile_access_method_ref   (ShellMobileAccessMethod *method);
 | 
			
		||||
void                     shell_mobile_access_method_unref (ShellMobileAccessMethod *method);
 | 
			
		||||
 | 
			
		||||
GHashTable *shell_mobile_providers_parse (GHashTable **out_ccs);
 | 
			
		||||
ShellCountryMobileProvider *shell_country_mobile_provider_ref              (ShellCountryMobileProvider *country_provider);
 | 
			
		||||
void                        shell_country_mobile_provider_unref            (ShellCountryMobileProvider *country_provider);
 | 
			
		||||
const gchar                *shell_country_mobile_provider_get_country_code (ShellCountryMobileProvider *country_provider);
 | 
			
		||||
const gchar                *shell_country_mobile_provider_get_country_name (ShellCountryMobileProvider *country_provider);
 | 
			
		||||
GSList                     *shell_country_mobile_provider_get_providers    (ShellCountryMobileProvider *country_provider);
 | 
			
		||||
 | 
			
		||||
void shell_mobile_providers_dump (GHashTable *providers);
 | 
			
		||||
GHashTable *shell_mobile_providers_parse (const gchar *country_codes,
 | 
			
		||||
                                          const gchar *service_providers);
 | 
			
		||||
void        shell_mobile_providers_dump  (GHashTable *country_providers);
 | 
			
		||||
 | 
			
		||||
#endif /* SHELL_MOBILE_PROVIDERS_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,9 @@ struct _ShellRecorderSrc
 | 
			
		||||
  GMutex mutex_data;
 | 
			
		||||
  GMutex *mutex;
 | 
			
		||||
 | 
			
		||||
  GstClock *clock;
 | 
			
		||||
  GstClockTime last_frame_time;
 | 
			
		||||
 | 
			
		||||
  GstCaps *caps;
 | 
			
		||||
  GAsyncQueue *queue;
 | 
			
		||||
  gboolean closed;
 | 
			
		||||
@@ -41,6 +44,10 @@ static void
 | 
			
		||||
shell_recorder_src_init (ShellRecorderSrc      *src)
 | 
			
		||||
{
 | 
			
		||||
  gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
 | 
			
		||||
  gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
 | 
			
		||||
 | 
			
		||||
  src->clock = gst_system_clock_obtain ();
 | 
			
		||||
  src->last_frame_time = 0;
 | 
			
		||||
 | 
			
		||||
  src->queue = g_async_queue_new ();
 | 
			
		||||
  src->mutex = &src->mutex_data;
 | 
			
		||||
@@ -89,6 +96,10 @@ shell_recorder_src_create (GstPushSrc  *push_src,
 | 
			
		||||
    return GST_FLOW_EOS;
 | 
			
		||||
 | 
			
		||||
  buffer = g_async_queue_pop (src->queue);
 | 
			
		||||
 | 
			
		||||
  if (src->last_frame_time == 0)
 | 
			
		||||
    src->last_frame_time = gst_clock_get_time (GST_CLOCK (src->clock));
 | 
			
		||||
 | 
			
		||||
  if (buffer == RECORDER_QUEUE_END)
 | 
			
		||||
    {
 | 
			
		||||
      /* Returning UNEXPECTED here will cause a EOS message to be sent */
 | 
			
		||||
@@ -100,6 +111,9 @@ shell_recorder_src_create (GstPushSrc  *push_src,
 | 
			
		||||
					 - (int)(gst_buffer_get_size(buffer) / 1024));
 | 
			
		||||
 | 
			
		||||
  *buffer_out = buffer;
 | 
			
		||||
  GST_BUFFER_DURATION(*buffer_out) = GST_CLOCK_DIFF (src->last_frame_time, gst_clock_get_time (GST_CLOCK (src->clock)));
 | 
			
		||||
 | 
			
		||||
  src->last_frame_time = gst_clock_get_time (GST_CLOCK (src->clock));
 | 
			
		||||
 | 
			
		||||
  return GST_FLOW_OK;
 | 
			
		||||
}
 | 
			
		||||
@@ -141,6 +155,8 @@ shell_recorder_src_finalize (GObject *object)
 | 
			
		||||
 | 
			
		||||
  g_mutex_clear (src->mutex);
 | 
			
		||||
 | 
			
		||||
  gst_object_unref (src->clock);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (shell_recorder_src_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,10 +12,10 @@
 | 
			
		||||
#include <gst/gst.h>
 | 
			
		||||
 | 
			
		||||
#include <gtk/gtk.h>
 | 
			
		||||
#include <gdk/gdk.h>
 | 
			
		||||
 | 
			
		||||
#include "shell-recorder-src.h"
 | 
			
		||||
#include "shell-recorder.h"
 | 
			
		||||
#include "shell-screen-grabber.h"
 | 
			
		||||
 | 
			
		||||
#include <clutter/x11/clutter-x11.h>
 | 
			
		||||
#include <X11/extensions/Xfixes.h>
 | 
			
		||||
@@ -48,7 +48,7 @@ struct _ShellRecorder {
 | 
			
		||||
  int stage_width;
 | 
			
		||||
  int stage_height;
 | 
			
		||||
 | 
			
		||||
  ShellScreenGrabber *grabber;
 | 
			
		||||
  GdkScreen *gdk_screen;
 | 
			
		||||
 | 
			
		||||
  gboolean have_pointer;
 | 
			
		||||
  int pointer_x;
 | 
			
		||||
@@ -259,11 +259,11 @@ shell_recorder_init (ShellRecorder *recorder)
 | 
			
		||||
 | 
			
		||||
  shell_recorder_src_register ();
 | 
			
		||||
 | 
			
		||||
  recorder->gdk_screen = gdk_screen_get_default ();
 | 
			
		||||
 | 
			
		||||
  recorder->recording_icon = create_recording_icon ();
 | 
			
		||||
  recorder->memory_target = get_memory_target();
 | 
			
		||||
 | 
			
		||||
  recorder->grabber = shell_screen_grabber_new ();
 | 
			
		||||
 | 
			
		||||
  recorder->state = RECORDER_STATE_CLOSED;
 | 
			
		||||
  recorder->framerate = DEFAULT_FRAMES_PER_SECOND;
 | 
			
		||||
}
 | 
			
		||||
@@ -283,8 +283,6 @@ shell_recorder_finalize (GObject  *object)
 | 
			
		||||
  recorder_set_pipeline (recorder, NULL);
 | 
			
		||||
  recorder_set_file_template (recorder, NULL);
 | 
			
		||||
 | 
			
		||||
  g_object_unref (recorder->grabber);
 | 
			
		||||
 | 
			
		||||
  cogl_handle_unref (recorder->recording_icon);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (shell_recorder_parent_class)->finalize (object);
 | 
			
		||||
@@ -462,6 +460,12 @@ static void
 | 
			
		||||
recorder_draw_buffer_meter (ShellRecorder *recorder)
 | 
			
		||||
{
 | 
			
		||||
  int fill_level;
 | 
			
		||||
  GdkRectangle primary_monitor;
 | 
			
		||||
  float rects[16];
 | 
			
		||||
 | 
			
		||||
  gdk_screen_get_monitor_geometry (recorder->gdk_screen,
 | 
			
		||||
                                   gdk_screen_get_primary_monitor (recorder->gdk_screen),
 | 
			
		||||
                                   &primary_monitor);
 | 
			
		||||
 | 
			
		||||
  recorder_update_memory_used (recorder, FALSE);
 | 
			
		||||
 | 
			
		||||
@@ -476,14 +480,27 @@ recorder_draw_buffer_meter (ShellRecorder *recorder)
 | 
			
		||||
  fill_level = MIN (60, (recorder->memory_used * 60) / recorder->memory_target);
 | 
			
		||||
 | 
			
		||||
  /* A hollow rectangle filled from the left to fill_level */
 | 
			
		||||
  cogl_rectangle (recorder->stage_width - 64, recorder->stage_height - 10,
 | 
			
		||||
                  recorder->stage_width - 2,  recorder->stage_height - 9);
 | 
			
		||||
  cogl_rectangle (recorder->stage_width - 64, recorder->stage_height - 9,
 | 
			
		||||
                  recorder->stage_width - (63 - fill_level), recorder->stage_height - 3);
 | 
			
		||||
  cogl_rectangle (recorder->stage_width - 3,  recorder->stage_height - 9,
 | 
			
		||||
                  recorder->stage_width - 2,  recorder->stage_height - 3);
 | 
			
		||||
  cogl_rectangle (recorder->stage_width - 64, recorder->stage_height - 3,
 | 
			
		||||
                  recorder->stage_width - 2,  recorder->stage_height - 2);
 | 
			
		||||
  rects[0] = primary_monitor.x + primary_monitor.width - 64;
 | 
			
		||||
  rects[1] = primary_monitor.y + primary_monitor.height - 10;
 | 
			
		||||
  rects[2] = primary_monitor.x + primary_monitor.width - 2;
 | 
			
		||||
  rects[3] = primary_monitor.y + primary_monitor.height - 9;
 | 
			
		||||
 | 
			
		||||
  rects[4] = primary_monitor.x + primary_monitor.width - 64;
 | 
			
		||||
  rects[5] = primary_monitor.y + primary_monitor.height - 9;
 | 
			
		||||
  rects[6] = primary_monitor.x + primary_monitor.width - (63 - fill_level);
 | 
			
		||||
  rects[7] = primary_monitor.y + primary_monitor.height - 3;
 | 
			
		||||
 | 
			
		||||
  rects[8] = primary_monitor.x + primary_monitor.width - 3;
 | 
			
		||||
  rects[9] = primary_monitor.y + primary_monitor.height - 9;
 | 
			
		||||
  rects[10] = primary_monitor.x + primary_monitor.width - 2;
 | 
			
		||||
  rects[11] = primary_monitor.y + primary_monitor.height - 3;
 | 
			
		||||
 | 
			
		||||
  rects[12] = primary_monitor.x + primary_monitor.width - 64;
 | 
			
		||||
  rects[13] = primary_monitor.y + primary_monitor.height - 3;
 | 
			
		||||
  rects[14] = primary_monitor.x + primary_monitor.width - 2;
 | 
			
		||||
  rects[15] = primary_monitor.y + primary_monitor.height - 2;
 | 
			
		||||
 | 
			
		||||
  cogl_rectangles (rects, 4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* We want to time-stamp each frame based on the actual time it was
 | 
			
		||||
@@ -533,8 +550,13 @@ recorder_record_frame (ShellRecorder *recorder)
 | 
			
		||||
 | 
			
		||||
  size = recorder->stage_width * recorder->stage_height * 4;
 | 
			
		||||
 | 
			
		||||
  data = shell_screen_grabber_grab (recorder->grabber,
 | 
			
		||||
                                    0, 0, recorder->stage_width, recorder->stage_height);
 | 
			
		||||
  data = g_malloc (recorder->stage_width * 4 * recorder->stage_height);
 | 
			
		||||
  cogl_read_pixels (0, 0, /* x/y */
 | 
			
		||||
                    recorder->stage_width,
 | 
			
		||||
                    recorder->stage_height,
 | 
			
		||||
                    COGL_READ_PIXELS_COLOR_BUFFER,
 | 
			
		||||
                    CLUTTER_CAIRO_FORMAT_ARGB32,
 | 
			
		||||
                    data);
 | 
			
		||||
 | 
			
		||||
  buffer = gst_buffer_new();
 | 
			
		||||
  gst_buffer_insert_memory (buffer, -1,
 | 
			
		||||
@@ -562,12 +584,17 @@ recorder_on_stage_paint (ClutterActor  *actor,
 | 
			
		||||
{
 | 
			
		||||
  if (recorder->state == RECORDER_STATE_RECORDING)
 | 
			
		||||
    {
 | 
			
		||||
      GdkRectangle primary_monitor;
 | 
			
		||||
 | 
			
		||||
      gdk_screen_get_monitor_geometry (recorder->gdk_screen,
 | 
			
		||||
                                       gdk_screen_get_primary_monitor (recorder->gdk_screen),
 | 
			
		||||
                                       &primary_monitor);
 | 
			
		||||
      if (!recorder->only_paint)
 | 
			
		||||
        recorder_record_frame (recorder);
 | 
			
		||||
 | 
			
		||||
      cogl_set_source_texture (recorder->recording_icon);
 | 
			
		||||
      cogl_rectangle (recorder->stage_width - 32, recorder->stage_height - 42,
 | 
			
		||||
                      recorder->stage_width,      recorder->stage_height - 10);
 | 
			
		||||
      cogl_rectangle (primary_monitor.x + primary_monitor.width - 32, primary_monitor.y + primary_monitor.height - 42,
 | 
			
		||||
                      primary_monitor.x + primary_monitor.width,      primary_monitor.y + primary_monitor.height - 10);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (recorder->state == RECORDER_STATE_RECORDING || recorder->memory_used != 0)
 | 
			
		||||
@@ -1703,9 +1730,6 @@ shell_recorder_close (ShellRecorder *recorder)
 | 
			
		||||
      recorder->repaint_hook_id = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  recorder_remove_redraw_timeout (recorder);
 | 
			
		||||
  recorder_close_pipeline (recorder);
 | 
			
		||||
 | 
			
		||||
  recorder->state = RECORDER_STATE_CLOSED;
 | 
			
		||||
 | 
			
		||||
  /* Release the refcount we took when we started recording */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,210 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <cogl/cogl.h>
 | 
			
		||||
#include <GL/gl.h>
 | 
			
		||||
#include <GL/glx.h>
 | 
			
		||||
#include <GL/glext.h>
 | 
			
		||||
 | 
			
		||||
#include "shell-screen-grabber.h"
 | 
			
		||||
 | 
			
		||||
PFNGLBINDBUFFERARBPROC pf_glBindBufferARB;
 | 
			
		||||
PFNGLBUFFERDATAARBPROC pf_glBufferDataARB;
 | 
			
		||||
PFNGLDELETEBUFFERSARBPROC pf_glDeleteBuffersARB;
 | 
			
		||||
PFNGLGENBUFFERSARBPROC pf_glGenBuffersARB;
 | 
			
		||||
PFNGLMAPBUFFERARBPROC pf_glMapBufferARB;
 | 
			
		||||
PFNGLUNMAPBUFFERARBPROC pf_glUnmapBufferARB;
 | 
			
		||||
 | 
			
		||||
struct _ShellScreenGrabberClass
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _ShellScreenGrabber
 | 
			
		||||
{
 | 
			
		||||
  GObject parent_instance;
 | 
			
		||||
 | 
			
		||||
  int have_pixel_buffers;
 | 
			
		||||
  int have_pack_invert;
 | 
			
		||||
  int width, height;
 | 
			
		||||
  GLuint pixel_buffer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE(ShellScreenGrabber, shell_screen_grabber, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_screen_grabber_finalize (GObject *gobject)
 | 
			
		||||
{
 | 
			
		||||
  ShellScreenGrabber *grabber = SHELL_SCREEN_GRABBER (gobject);
 | 
			
		||||
 | 
			
		||||
  if (grabber->pixel_buffer != 0)
 | 
			
		||||
    pf_glDeleteBuffersARB (1, &grabber->pixel_buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_screen_grabber_class_init (ShellScreenGrabberClass *grabber_class)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *gobject_class = G_OBJECT_CLASS (grabber_class);
 | 
			
		||||
 | 
			
		||||
  gobject_class->finalize = shell_screen_grabber_finalize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_screen_grabber_init (ShellScreenGrabber *grabber)
 | 
			
		||||
{
 | 
			
		||||
  grabber->have_pixel_buffers = -1;
 | 
			
		||||
  grabber->width = -1;
 | 
			
		||||
  grabber->height= -1;
 | 
			
		||||
  grabber->pixel_buffer = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ShellScreenGrabber *
 | 
			
		||||
shell_screen_grabber_new  (void)
 | 
			
		||||
{
 | 
			
		||||
  return g_object_new (SHELL_TYPE_SCREEN_GRABBER, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_screen_grabber_grab:
 | 
			
		||||
 * x: X coordinate of the rectangle to grab
 | 
			
		||||
 * y: Y coordinate of the rectangle to grab
 | 
			
		||||
 * width: width of the rectangle to grab
 | 
			
		||||
 * height: heigth of the rectangle to grab
 | 
			
		||||
 *
 | 
			
		||||
 * Grabs pixel data from a portion of the screen.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: buffer holding the grabbed data. The data is stored as 32-bit
 | 
			
		||||
 *  words with native-endian xRGB pixels (i.e., the same as CAIRO_FORMAT_RGB24)
 | 
			
		||||
 *  with no padding on the rows. So, the size of the buffer is width * height * 4
 | 
			
		||||
 *  bytes. Free with g_free().
 | 
			
		||||
 **/
 | 
			
		||||
guchar *
 | 
			
		||||
shell_screen_grabber_grab (ShellScreenGrabber *grabber,
 | 
			
		||||
                           int                 x,
 | 
			
		||||
                           int                 y,
 | 
			
		||||
                           int                 width,
 | 
			
		||||
                           int                 height)
 | 
			
		||||
{
 | 
			
		||||
  guchar *data;
 | 
			
		||||
  gsize row_bytes;
 | 
			
		||||
  gsize data_size;
 | 
			
		||||
 | 
			
		||||
  row_bytes = width * 4;
 | 
			
		||||
  data_size = row_bytes * height;
 | 
			
		||||
  data = g_malloc (data_size);
 | 
			
		||||
 | 
			
		||||
  if (grabber->have_pixel_buffers == -1)
 | 
			
		||||
    {
 | 
			
		||||
      const GLubyte* extensions = glGetString (GL_EXTENSIONS);
 | 
			
		||||
      grabber->have_pixel_buffers = strstr ((const char *)extensions, "GL_EXT_pixel_buffer_object") != NULL;
 | 
			
		||||
      grabber->have_pack_invert = strstr ((const char *)extensions, "GL_MESA_pack_invert") != NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (grabber->have_pixel_buffers)
 | 
			
		||||
    {
 | 
			
		||||
      GLubyte *mapped_data;
 | 
			
		||||
      GLint old_swap_bytes, old_lsb_first, old_row_length, old_skip_pixels, old_skip_rows, old_alignment;
 | 
			
		||||
      GLint old_pack_invert = GL_FALSE;
 | 
			
		||||
      GLint vp_size[4];
 | 
			
		||||
      guchar *src_row, *dest_row;
 | 
			
		||||
      int i;
 | 
			
		||||
 | 
			
		||||
      cogl_flush ();
 | 
			
		||||
 | 
			
		||||
      if (pf_glBindBufferARB == NULL)
 | 
			
		||||
        {
 | 
			
		||||
          pf_glBindBufferARB = (PFNGLBINDBUFFERARBPROC) cogl_get_proc_address ("glBindBufferARB");
 | 
			
		||||
          pf_glBufferDataARB = (PFNGLBUFFERDATAARBPROC) cogl_get_proc_address ("glBufferDataARB");
 | 
			
		||||
          pf_glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) cogl_get_proc_address ("glDeleteBuffersARB");
 | 
			
		||||
          pf_glGenBuffersARB = (PFNGLGENBUFFERSARBPROC) cogl_get_proc_address ("glGenBuffersARB");
 | 
			
		||||
          pf_glMapBufferARB = (PFNGLMAPBUFFERARBPROC) cogl_get_proc_address ("glMapBufferARB");
 | 
			
		||||
          pf_glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC) cogl_get_proc_address ("glUnmapBufferARB");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      glGetIntegerv (GL_PACK_SWAP_BYTES, &old_swap_bytes);
 | 
			
		||||
      glGetIntegerv (GL_PACK_LSB_FIRST, &old_lsb_first);
 | 
			
		||||
      glGetIntegerv (GL_PACK_ROW_LENGTH, &old_row_length);
 | 
			
		||||
      glGetIntegerv (GL_PACK_SKIP_PIXELS, &old_skip_pixels);
 | 
			
		||||
      glGetIntegerv (GL_PACK_SKIP_ROWS, &old_skip_rows);
 | 
			
		||||
      glGetIntegerv (GL_PACK_ALIGNMENT, &old_alignment);
 | 
			
		||||
 | 
			
		||||
      glPixelStorei (GL_PACK_SWAP_BYTES, GL_FALSE);
 | 
			
		||||
      glPixelStorei (GL_PACK_LSB_FIRST, GL_FALSE);
 | 
			
		||||
      glPixelStorei (GL_PACK_ROW_LENGTH, 0);
 | 
			
		||||
      glPixelStorei (GL_PACK_SKIP_PIXELS, 0);
 | 
			
		||||
      glPixelStorei (GL_PACK_SKIP_ROWS, 0);
 | 
			
		||||
      glPixelStorei (GL_PACK_ALIGNMENT, 1);
 | 
			
		||||
 | 
			
		||||
      if (grabber->have_pack_invert)
 | 
			
		||||
        {
 | 
			
		||||
          glGetIntegerv (GL_PACK_INVERT_MESA, &old_pack_invert);
 | 
			
		||||
          glPixelStorei (GL_PACK_INVERT_MESA, GL_FALSE);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (grabber->pixel_buffer != 0 &&
 | 
			
		||||
          (grabber->width != width ||
 | 
			
		||||
           grabber->height != height))
 | 
			
		||||
        {
 | 
			
		||||
          pf_glDeleteBuffersARB (1, &grabber->pixel_buffer);
 | 
			
		||||
          grabber->pixel_buffer = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (grabber->pixel_buffer == 0)
 | 
			
		||||
        {
 | 
			
		||||
          pf_glGenBuffersARB (1, &grabber->pixel_buffer);
 | 
			
		||||
 | 
			
		||||
          pf_glBindBufferARB (GL_PIXEL_PACK_BUFFER_ARB, grabber->pixel_buffer);
 | 
			
		||||
          pf_glBufferDataARB (GL_PIXEL_PACK_BUFFER_ARB, data_size, 0, GL_STREAM_READ_ARB);
 | 
			
		||||
 | 
			
		||||
          grabber->width = width;
 | 
			
		||||
          grabber->height = height;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          pf_glBindBufferARB (GL_PIXEL_PACK_BUFFER_ARB, grabber->pixel_buffer);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      /* In OpenGL, (x,y) specifies the bottom-left corner rather than the
 | 
			
		||||
       * top-left */
 | 
			
		||||
      glGetIntegerv (GL_VIEWPORT, vp_size);
 | 
			
		||||
      y = vp_size[3] - (y + height);
 | 
			
		||||
      glReadPixels (x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
 | 
			
		||||
 | 
			
		||||
      mapped_data = pf_glMapBufferARB (GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
 | 
			
		||||
 | 
			
		||||
      src_row = mapped_data + (height - 1) * row_bytes;
 | 
			
		||||
      dest_row = data;
 | 
			
		||||
 | 
			
		||||
      for (i = 0; i < height; i++)
 | 
			
		||||
        {
 | 
			
		||||
          memcpy (dest_row, src_row, row_bytes);
 | 
			
		||||
          src_row -= row_bytes;
 | 
			
		||||
          dest_row += row_bytes;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      pf_glUnmapBufferARB (GL_PIXEL_PACK_BUFFER_ARB);
 | 
			
		||||
      pf_glBindBufferARB (GL_PIXEL_PACK_BUFFER_ARB, 0);
 | 
			
		||||
 | 
			
		||||
      glPixelStorei (GL_PACK_SWAP_BYTES, old_swap_bytes);
 | 
			
		||||
      glPixelStorei (GL_PACK_LSB_FIRST, old_lsb_first);
 | 
			
		||||
      glPixelStorei (GL_PACK_ROW_LENGTH, old_row_length);
 | 
			
		||||
      glPixelStorei (GL_PACK_SKIP_PIXELS, old_skip_pixels);
 | 
			
		||||
      glPixelStorei (GL_PACK_SKIP_ROWS, old_skip_rows);
 | 
			
		||||
      glPixelStorei (GL_PACK_ALIGNMENT, old_alignment);
 | 
			
		||||
 | 
			
		||||
      if (grabber->have_pack_invert)
 | 
			
		||||
        glPixelStorei (GL_PACK_INVERT_MESA, old_pack_invert);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      cogl_read_pixels (x, y,
 | 
			
		||||
                        width, height,
 | 
			
		||||
                        COGL_READ_PIXELS_COLOR_BUFFER,
 | 
			
		||||
                        CLUTTER_CAIRO_FORMAT_ARGB32,
 | 
			
		||||
                        data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return data;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,44 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
#ifndef __SHELL_SCREEN_GRABBER_H__
 | 
			
		||||
#define __SHELL_SCREEN_GRABBER_H__
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:shell-screen-grabber
 | 
			
		||||
 * @short_description: Grab pixel data from the screen
 | 
			
		||||
 *
 | 
			
		||||
 * The #ShellScreenGrabber object is used to download previous drawn
 | 
			
		||||
 * content to the screen. It internally uses pixel-buffer objects if
 | 
			
		||||
 * available, otherwise falls back to cogl_read_pixels().
 | 
			
		||||
 *
 | 
			
		||||
 * If you are repeatedly grabbing images of the same size from the
 | 
			
		||||
 * screen, it makes sense to create one #ShellScreenGrabber and keep
 | 
			
		||||
 * it around. Otherwise, it's fine to simply create one as needed and
 | 
			
		||||
 * then get rid of it.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef struct _ShellScreenGrabber      ShellScreenGrabber;
 | 
			
		||||
typedef struct _ShellScreenGrabberClass ShellScreenGrabberClass;
 | 
			
		||||
 | 
			
		||||
#define SHELL_TYPE_SCREEN_GRABBER              (shell_screen_grabber_get_type ())
 | 
			
		||||
#define SHELL_SCREEN_GRABBER(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), SHELL_TYPE_SCREEN_GRABBER, ShellScreenGrabber))
 | 
			
		||||
#define SHELL_SCREEN_GRABBER_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_SCREEN_GRABBER, ShellScreenGrabberClass))
 | 
			
		||||
#define SHELL_IS_SCREEN_GRABBER(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), SHELL_TYPE_SCREEN_GRABBER))
 | 
			
		||||
#define SHELL_IS_SCREEN_GRABBER_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_SCREEN_GRABBER))
 | 
			
		||||
#define SHELL_SCREEN_GRABBER_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_SCREEN_GRABBER, ShellScreenGrabberClass))
 | 
			
		||||
 | 
			
		||||
GType shell_screen_grabber_get_type (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
ShellScreenGrabber *shell_screen_grabber_new  (void);
 | 
			
		||||
guchar *            shell_screen_grabber_grab (ShellScreenGrabber *grabber,
 | 
			
		||||
                                               int                 x,
 | 
			
		||||
                                               int                 y,
 | 
			
		||||
                                               int                 width,
 | 
			
		||||
                                               int                 height);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* __SHELL_SCREEN_GRABBER_H__ */
 | 
			
		||||
@@ -1,5 +1,8 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
#define COGL_ENABLE_EXPERIMENTAL_API
 | 
			
		||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
 | 
			
		||||
 | 
			
		||||
#include <X11/extensions/Xfixes.h>
 | 
			
		||||
#include <clutter/x11/clutter-x11.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
@@ -10,7 +13,6 @@
 | 
			
		||||
#include <meta/meta-shaped-texture.h>
 | 
			
		||||
 | 
			
		||||
#include "shell-global.h"
 | 
			
		||||
#include "shell-screen-grabber.h"
 | 
			
		||||
#include "shell-screenshot.h"
 | 
			
		||||
 | 
			
		||||
struct _ShellScreenshotClass
 | 
			
		||||
@@ -90,18 +92,33 @@ do_grab_screenshot (_screenshot_data *screenshot_data,
 | 
			
		||||
                    int               width,
 | 
			
		||||
                    int               height)
 | 
			
		||||
{
 | 
			
		||||
  ShellScreenGrabber *grabber;
 | 
			
		||||
  static const cairo_user_data_key_t key;
 | 
			
		||||
  CoglBitmap *bitmap;
 | 
			
		||||
  ClutterBackend *backend;
 | 
			
		||||
  CoglContext *context;
 | 
			
		||||
  int stride;
 | 
			
		||||
  guchar *data;
 | 
			
		||||
 | 
			
		||||
  grabber = shell_screen_grabber_new ();
 | 
			
		||||
  data = shell_screen_grabber_grab (grabber, x, y, width, height);
 | 
			
		||||
  g_object_unref (grabber);
 | 
			
		||||
  backend = clutter_get_default_backend ();
 | 
			
		||||
  context = clutter_backend_get_cogl_context (backend);
 | 
			
		||||
 | 
			
		||||
  screenshot_data->image = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_RGB24,
 | 
			
		||||
                                                               width, height, width * 4);
 | 
			
		||||
  cairo_surface_set_user_data (screenshot_data->image, &key,
 | 
			
		||||
                               data, (cairo_destroy_func_t)g_free);
 | 
			
		||||
  screenshot_data->image = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
 | 
			
		||||
                                                       width, height);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  data = cairo_image_surface_get_data (screenshot_data->image);
 | 
			
		||||
  stride = cairo_image_surface_get_stride (screenshot_data->image);
 | 
			
		||||
 | 
			
		||||
  bitmap = cogl_bitmap_new_for_data (context,
 | 
			
		||||
                                     width,
 | 
			
		||||
                                     height,
 | 
			
		||||
                                     CLUTTER_CAIRO_FORMAT_ARGB32,
 | 
			
		||||
                                     stride,
 | 
			
		||||
                                     data);
 | 
			
		||||
  cogl_framebuffer_read_pixels_into_bitmap (cogl_get_draw_framebuffer (),
 | 
			
		||||
                                            x, y,
 | 
			
		||||
                                            COGL_READ_PIXELS_COLOR_BUFFER,
 | 
			
		||||
                                            bitmap);
 | 
			
		||||
  cogl_object_unref (bitmap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,9 @@ void _shell_wm_kill_window_effects   (ShellWM             *wm,
 | 
			
		||||
                                      MetaWindowActor     *actor);
 | 
			
		||||
void _shell_wm_kill_switch_workspace (ShellWM             *wm);
 | 
			
		||||
 | 
			
		||||
gboolean _shell_wm_filter_keybinding (ShellWM             *wm,
 | 
			
		||||
                                      MetaKeyBinding      *binding);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* __SHELL_WM_PRIVATE_H__ */
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ enum
 | 
			
		||||
  SWITCH_WORKSPACE,
 | 
			
		||||
  KILL_SWITCH_WORKSPACE,
 | 
			
		||||
  KILL_WINDOW_EFFECTS,
 | 
			
		||||
  FILTER_KEYBINDING,
 | 
			
		||||
 | 
			
		||||
  LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
@@ -115,6 +116,14 @@ shell_wm_class_init (ShellWMClass *klass)
 | 
			
		||||
          NULL, NULL, NULL,
 | 
			
		||||
		  G_TYPE_NONE, 1,
 | 
			
		||||
		  META_TYPE_WINDOW_ACTOR);
 | 
			
		||||
  shell_wm_signals[FILTER_KEYBINDING] =
 | 
			
		||||
    g_signal_new ("filter-keybinding",
 | 
			
		||||
                  G_TYPE_FROM_CLASS (klass),
 | 
			
		||||
                  G_SIGNAL_RUN_LAST,
 | 
			
		||||
                  0,
 | 
			
		||||
                  g_signal_accumulator_true_handled, NULL, NULL,
 | 
			
		||||
                  G_TYPE_BOOLEAN, 1,
 | 
			
		||||
                  META_TYPE_KEY_BINDING);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -267,6 +276,17 @@ _shell_wm_destroy (ShellWM         *wm,
 | 
			
		||||
  g_signal_emit (wm, shell_wm_signals[DESTROY], 0, actor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
_shell_wm_filter_keybinding (ShellWM             *wm,
 | 
			
		||||
                             MetaKeyBinding      *binding)
 | 
			
		||||
{
 | 
			
		||||
  gboolean rv;
 | 
			
		||||
 | 
			
		||||
  g_signal_emit (wm, shell_wm_signals[FILTER_KEYBINDING], 0, binding, &rv);
 | 
			
		||||
 | 
			
		||||
  return rv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_wm_new:
 | 
			
		||||
 * @plugin: the #MetaPlugin
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,10 @@
 | 
			
		||||
#include "st-clipboard.h"
 | 
			
		||||
#include "st-private.h"
 | 
			
		||||
 | 
			
		||||
#include <clutter/x11/clutter-x11.h>
 | 
			
		||||
#include <X11/Xlib.h>
 | 
			
		||||
#include <X11/cursorfont.h>
 | 
			
		||||
 | 
			
		||||
#include "st-widget-accessible.h"
 | 
			
		||||
 | 
			
		||||
#define HAS_FOCUS(actor) (clutter_actor_get_stage (actor) && clutter_stage_get_key_focus ((ClutterStage *) clutter_actor_get_stage (actor)) == actor)
 | 
			
		||||
@@ -613,6 +617,38 @@ st_entry_key_focus_in (ClutterActor *actor)
 | 
			
		||||
  clutter_actor_grab_key_focus (priv->entry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
st_entry_set_cursor (StEntry  *entry,
 | 
			
		||||
                     gboolean  use_ibeam)
 | 
			
		||||
{
 | 
			
		||||
  Display *dpy;
 | 
			
		||||
  ClutterActor *stage, *actor = CLUTTER_ACTOR (entry);
 | 
			
		||||
  Window wid;
 | 
			
		||||
  static Cursor ibeam = None;
 | 
			
		||||
 | 
			
		||||
  dpy = clutter_x11_get_default_display ();
 | 
			
		||||
  stage = clutter_actor_get_stage (actor);
 | 
			
		||||
  wid = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
 | 
			
		||||
 | 
			
		||||
  if (ibeam == None)
 | 
			
		||||
    ibeam = XCreateFontCursor (dpy, XC_xterm);
 | 
			
		||||
 | 
			
		||||
  if (use_ibeam)
 | 
			
		||||
    XDefineCursor (dpy, wid, ibeam);
 | 
			
		||||
  else
 | 
			
		||||
    XUndefineCursor (dpy, wid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
st_entry_crossing_event (ClutterActor         *actor,
 | 
			
		||||
                         ClutterCrossingEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  if (event->source == ST_ENTRY (actor)->priv->entry && event->related != NULL)
 | 
			
		||||
    st_entry_set_cursor (ST_ENTRY (actor), (event->type == CLUTTER_ENTER));
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
st_entry_class_init (StEntryClass *klass)
 | 
			
		||||
{
 | 
			
		||||
@@ -635,6 +671,9 @@ st_entry_class_init (StEntryClass *klass)
 | 
			
		||||
  actor_class->key_press_event = st_entry_key_press_event;
 | 
			
		||||
  actor_class->key_focus_in = st_entry_key_focus_in;
 | 
			
		||||
 | 
			
		||||
  actor_class->enter_event = st_entry_crossing_event;
 | 
			
		||||
  actor_class->leave_event = st_entry_crossing_event;
 | 
			
		||||
 | 
			
		||||
  widget_class->style_changed = st_entry_style_changed;
 | 
			
		||||
  widget_class->navigate_focus = st_entry_navigate_focus;
 | 
			
		||||
  widget_class->get_accessible_type = st_entry_accessible_get_type;
 | 
			
		||||
 
 | 
			
		||||
@@ -665,6 +665,45 @@ st_scroll_view_allocate (ClutterActor          *actor,
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
adjust_with_delta (StAdjustment *adj,
 | 
			
		||||
                   gdouble       delta)
 | 
			
		||||
{
 | 
			
		||||
  gdouble new_value, page_size, scroll_unit;
 | 
			
		||||
 | 
			
		||||
  g_object_get (adj,
 | 
			
		||||
                "page-size", &page_size,
 | 
			
		||||
                NULL);
 | 
			
		||||
  scroll_unit = pow (page_size, 2.0 / 3.0);
 | 
			
		||||
 | 
			
		||||
  new_value = st_adjustment_get_value (adj) + delta * scroll_unit;
 | 
			
		||||
  st_adjustment_set_value (adj, new_value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
adjust_with_direction (StAdjustment           *adj,
 | 
			
		||||
                       ClutterScrollDirection  direction)
 | 
			
		||||
{
 | 
			
		||||
  gdouble delta;
 | 
			
		||||
 | 
			
		||||
  switch (direction)
 | 
			
		||||
    {
 | 
			
		||||
    case CLUTTER_SCROLL_UP:
 | 
			
		||||
    case CLUTTER_SCROLL_LEFT:
 | 
			
		||||
      delta = -1.0;
 | 
			
		||||
      break;
 | 
			
		||||
    case CLUTTER_SCROLL_RIGHT:
 | 
			
		||||
    case CLUTTER_SCROLL_DOWN:
 | 
			
		||||
      delta = 1.0;
 | 
			
		||||
      break;
 | 
			
		||||
    case CLUTTER_SCROLL_SMOOTH:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  adjust_with_delta (adj, delta);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
st_scroll_view_style_changed (StWidget *widget)
 | 
			
		||||
{
 | 
			
		||||
@@ -687,57 +726,32 @@ st_scroll_view_scroll_event (ClutterActor       *self,
 | 
			
		||||
                             ClutterScrollEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  StScrollViewPrivate *priv = ST_SCROLL_VIEW (self)->priv;
 | 
			
		||||
  gdouble value, step, hvalue, vvalue, delta_x, delta_y;
 | 
			
		||||
 | 
			
		||||
  /* don't handle scroll events if requested not to */
 | 
			
		||||
  if (!priv->mouse_scroll)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  switch (event->direction)
 | 
			
		||||
    {
 | 
			
		||||
    case CLUTTER_SCROLL_SMOOTH:
 | 
			
		||||
      clutter_event_get_scroll_delta ((ClutterEvent *)event,
 | 
			
		||||
                                      &delta_x, &delta_y);
 | 
			
		||||
      g_object_get (priv->hadjustment,
 | 
			
		||||
                    "value", &hvalue,
 | 
			
		||||
                    NULL);
 | 
			
		||||
      g_object_get (priv->vadjustment,
 | 
			
		||||
                    "value", &vvalue,
 | 
			
		||||
                    NULL);
 | 
			
		||||
      break;
 | 
			
		||||
    case CLUTTER_SCROLL_UP:
 | 
			
		||||
    case CLUTTER_SCROLL_DOWN:
 | 
			
		||||
      g_object_get (priv->vadjustment,
 | 
			
		||||
                    "step-increment", &step,
 | 
			
		||||
                    "value", &value,
 | 
			
		||||
                    NULL);
 | 
			
		||||
      break;
 | 
			
		||||
    case CLUTTER_SCROLL_LEFT:
 | 
			
		||||
    case CLUTTER_SCROLL_RIGHT:
 | 
			
		||||
      g_object_get (priv->hadjustment,
 | 
			
		||||
                    "step-increment", &step,
 | 
			
		||||
                    "value", &value,
 | 
			
		||||
                    NULL);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  /* throw away this garbage event. we want smooth scrolling. */
 | 
			
		||||
  if (clutter_event_is_pointer_emulated ((ClutterEvent *) event))
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  switch (event->direction)
 | 
			
		||||
    {
 | 
			
		||||
    case CLUTTER_SCROLL_SMOOTH:
 | 
			
		||||
      st_adjustment_set_value (priv->hadjustment, hvalue + delta_x);
 | 
			
		||||
      st_adjustment_set_value (priv->vadjustment, vvalue + delta_y);
 | 
			
		||||
      {
 | 
			
		||||
        gdouble delta_x, delta_y;
 | 
			
		||||
        clutter_event_get_scroll_delta ((ClutterEvent *)event, &delta_x, &delta_y);
 | 
			
		||||
        adjust_with_delta (priv->hadjustment, delta_x);
 | 
			
		||||
        adjust_with_delta (priv->vadjustment, delta_y);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case CLUTTER_SCROLL_UP:
 | 
			
		||||
      st_adjustment_set_value (priv->vadjustment, value - step);
 | 
			
		||||
      break;
 | 
			
		||||
    case CLUTTER_SCROLL_DOWN:
 | 
			
		||||
      st_adjustment_set_value (priv->vadjustment, value + step);
 | 
			
		||||
      adjust_with_direction (priv->vadjustment, event->direction);
 | 
			
		||||
      break;
 | 
			
		||||
    case CLUTTER_SCROLL_LEFT:
 | 
			
		||||
      st_adjustment_set_value (priv->hadjustment, value - step);
 | 
			
		||||
      break;
 | 
			
		||||
    case CLUTTER_SCROLL_RIGHT:
 | 
			
		||||
      st_adjustment_set_value (priv->hadjustment, value + step);
 | 
			
		||||
      adjust_with_direction (priv->hadjustment, event->direction);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1073,6 +1073,8 @@ typedef struct {
 | 
			
		||||
  gchar *path;
 | 
			
		||||
  gint   grid_width, grid_height;
 | 
			
		||||
  ClutterActor *actor;
 | 
			
		||||
  GFunc load_callback;
 | 
			
		||||
  gpointer load_callback_data;
 | 
			
		||||
} AsyncImageData;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -1089,6 +1091,7 @@ on_sliced_image_loaded (GObject *source_object,
 | 
			
		||||
                        GAsyncResult *res,
 | 
			
		||||
                        gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  GObject *cache = source_object;
 | 
			
		||||
  AsyncImageData *data = (AsyncImageData *)user_data;
 | 
			
		||||
  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
 | 
			
		||||
  GList *list;
 | 
			
		||||
@@ -1102,6 +1105,9 @@ on_sliced_image_loaded (GObject *source_object,
 | 
			
		||||
      clutter_actor_hide (actor);
 | 
			
		||||
      clutter_actor_add_child (data->actor, actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (data->load_callback != NULL)
 | 
			
		||||
    data->load_callback (cache, data->load_callback_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -1156,6 +1162,8 @@ load_sliced_image (GSimpleAsyncResult *result,
 | 
			
		||||
 * @path: Path to a filename
 | 
			
		||||
 * @grid_width: Width in pixels
 | 
			
		||||
 * @grid_height: Height in pixels
 | 
			
		||||
 * @load_callback: (scope async) (allow-none): Function called when the image is loaded, or %NULL
 | 
			
		||||
 * @user_data: Data to pass to the load callback
 | 
			
		||||
 *
 | 
			
		||||
 * This function reads a single image file which contains multiple images internally.
 | 
			
		||||
 * The image file will be divided using @grid_width and @grid_height;
 | 
			
		||||
@@ -1165,10 +1173,12 @@ load_sliced_image (GSimpleAsyncResult *result,
 | 
			
		||||
 * Returns: (transfer none): A new #ClutterActor
 | 
			
		||||
 */
 | 
			
		||||
ClutterActor *
 | 
			
		||||
st_texture_cache_load_sliced_image (StTextureCache    *cache,
 | 
			
		||||
                                    const gchar       *path,
 | 
			
		||||
                                    gint               grid_width,
 | 
			
		||||
                                    gint               grid_height)
 | 
			
		||||
st_texture_cache_load_sliced_image (StTextureCache *cache,
 | 
			
		||||
                                    const gchar    *path,
 | 
			
		||||
                                    gint            grid_width,
 | 
			
		||||
                                    gint            grid_height,
 | 
			
		||||
                                    GFunc           load_callback,
 | 
			
		||||
                                    gpointer        user_data)
 | 
			
		||||
{
 | 
			
		||||
  AsyncImageData *data;
 | 
			
		||||
  GSimpleAsyncResult *result;
 | 
			
		||||
@@ -1179,6 +1189,8 @@ st_texture_cache_load_sliced_image (StTextureCache    *cache,
 | 
			
		||||
  data->grid_height = grid_height;
 | 
			
		||||
  data->path = g_strdup (path);
 | 
			
		||||
  data->actor = actor;
 | 
			
		||||
  data->load_callback = load_callback;
 | 
			
		||||
  data->load_callback_data = user_data;
 | 
			
		||||
  g_object_ref (G_OBJECT (actor));
 | 
			
		||||
 | 
			
		||||
  result = g_simple_async_result_new (G_OBJECT (cache), on_sliced_image_loaded, data, st_texture_cache_load_sliced_image);
 | 
			
		||||
 
 | 
			
		||||
@@ -69,10 +69,12 @@ GType st_texture_cache_get_type (void) G_GNUC_CONST;
 | 
			
		||||
StTextureCache* st_texture_cache_get_default (void);
 | 
			
		||||
 | 
			
		||||
ClutterActor *
 | 
			
		||||
st_texture_cache_load_sliced_image (StTextureCache    *cache,
 | 
			
		||||
                                    const gchar       *path,
 | 
			
		||||
                                    gint               grid_width,
 | 
			
		||||
                                    gint               grid_height);
 | 
			
		||||
st_texture_cache_load_sliced_image (StTextureCache *cache,
 | 
			
		||||
                                    const gchar    *path,
 | 
			
		||||
                                    gint            grid_width,
 | 
			
		||||
                                    gint            grid_height,
 | 
			
		||||
                                    GFunc           load_callback,
 | 
			
		||||
                                    gpointer        user_data);
 | 
			
		||||
 | 
			
		||||
ClutterActor *st_texture_cache_bind_pixbuf_property (StTextureCache    *cache,
 | 
			
		||||
                                                     GObject           *object,
 | 
			
		||||
 
 | 
			
		||||
@@ -31,6 +31,9 @@ struct _StThemeContext {
 | 
			
		||||
  PangoFontDescription *font;
 | 
			
		||||
  StThemeNode *root_node;
 | 
			
		||||
  StTheme *theme;
 | 
			
		||||
 | 
			
		||||
  /* set of StThemeNode */
 | 
			
		||||
  GHashTable *nodes;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _StThemeContextClass {
 | 
			
		||||
@@ -66,6 +69,8 @@ st_theme_context_finalize (GObject *object)
 | 
			
		||||
                                        (gpointer) st_theme_context_changed,
 | 
			
		||||
                                        context);
 | 
			
		||||
 | 
			
		||||
  if (context->nodes)
 | 
			
		||||
    g_hash_table_unref (context->nodes);
 | 
			
		||||
  if (context->root_node)
 | 
			
		||||
    g_object_unref (context->root_node);
 | 
			
		||||
  if (context->theme)
 | 
			
		||||
@@ -105,6 +110,10 @@ st_theme_context_init (StThemeContext *context)
 | 
			
		||||
                            "resolution-changed",
 | 
			
		||||
                            G_CALLBACK (st_theme_context_changed),
 | 
			
		||||
                            context);
 | 
			
		||||
 | 
			
		||||
  context->nodes = g_hash_table_new_full ((GHashFunc) st_theme_node_hash,
 | 
			
		||||
                                          (GEqualFunc) st_theme_node_equal,
 | 
			
		||||
                                          g_object_unref, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -146,6 +155,7 @@ st_theme_context_changed (StThemeContext *context)
 | 
			
		||||
{
 | 
			
		||||
  StThemeNode *old_root = context->root_node;
 | 
			
		||||
  context->root_node = NULL;
 | 
			
		||||
  g_hash_table_remove_all (context->nodes);
 | 
			
		||||
 | 
			
		||||
  emit_changed (context);
 | 
			
		||||
 | 
			
		||||
@@ -299,3 +309,27 @@ st_theme_context_get_root_node (StThemeContext *context)
 | 
			
		||||
 | 
			
		||||
  return context->root_node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * st_theme_context_intern_node:
 | 
			
		||||
 * @context: a #StThemeContext
 | 
			
		||||
 * @node: a #StThemeNode
 | 
			
		||||
 *
 | 
			
		||||
 * Return an existing node matching @node, or if that isn't possible,
 | 
			
		||||
 * @node itself.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: (transfer none): a node with the same properties as @node
 | 
			
		||||
 */
 | 
			
		||||
StThemeNode *
 | 
			
		||||
st_theme_context_intern_node (StThemeContext *context,
 | 
			
		||||
                              StThemeNode    *node)
 | 
			
		||||
{
 | 
			
		||||
  StThemeNode *mine = g_hash_table_lookup (context->nodes, node);
 | 
			
		||||
 | 
			
		||||
  /* this might be node or not - it doesn't actually matter */
 | 
			
		||||
  if (mine != NULL)
 | 
			
		||||
    return mine;
 | 
			
		||||
 | 
			
		||||
  g_hash_table_add (context->nodes, g_object_ref (node));
 | 
			
		||||
  return node;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -62,6 +62,9 @@ const PangoFontDescription *st_theme_context_get_font       (StThemeContext
 | 
			
		||||
 | 
			
		||||
StThemeNode *               st_theme_context_get_root_node  (StThemeContext             *context);
 | 
			
		||||
 | 
			
		||||
StThemeNode *               st_theme_context_intern_node    (StThemeContext             *context,
 | 
			
		||||
                                                             StThemeNode                *node);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* __ST_THEME_CONTEXT_H__ */
 | 
			
		||||
 
 | 
			
		||||
@@ -1553,7 +1553,7 @@ st_theme_node_paint_borders (StThemeNode           *node,
 | 
			
		||||
    {
 | 
			
		||||
      ClutterColor effective_border;
 | 
			
		||||
      gboolean skip_corner_1, skip_corner_2;
 | 
			
		||||
      float x1, y1, x2, y2;
 | 
			
		||||
      float rects[16];
 | 
			
		||||
 | 
			
		||||
      over (&border_color, &node->background_color, &effective_border);
 | 
			
		||||
      alpha = paint_opacity * effective_border.alpha / 255;
 | 
			
		||||
@@ -1569,46 +1569,44 @@ st_theme_node_paint_borders (StThemeNode           *node,
 | 
			
		||||
          skip_corner_1 = border_radius[ST_CORNER_TOPLEFT] > 0;
 | 
			
		||||
          skip_corner_2 = border_radius[ST_CORNER_TOPRIGHT] > 0;
 | 
			
		||||
 | 
			
		||||
          x1 = skip_corner_1 ? max_width_radius[ST_CORNER_TOPLEFT] : 0;
 | 
			
		||||
          y1 = 0;
 | 
			
		||||
          x2 = skip_corner_2 ? width - max_width_radius[ST_CORNER_TOPRIGHT] : width;
 | 
			
		||||
          y2 = border_width[ST_SIDE_TOP];
 | 
			
		||||
          cogl_rectangle (x1, y1, x2, y2);
 | 
			
		||||
          rects[0] = skip_corner_1 ? max_width_radius[ST_CORNER_TOPLEFT] : 0;
 | 
			
		||||
          rects[1] = 0;
 | 
			
		||||
          rects[2] = skip_corner_2 ? width - max_width_radius[ST_CORNER_TOPRIGHT] : width;
 | 
			
		||||
          rects[3] = border_width[ST_SIDE_TOP];
 | 
			
		||||
 | 
			
		||||
          /* EAST */
 | 
			
		||||
          skip_corner_1 = border_radius[ST_CORNER_TOPRIGHT] > 0;
 | 
			
		||||
          skip_corner_2 = border_radius[ST_CORNER_BOTTOMRIGHT] > 0;
 | 
			
		||||
 | 
			
		||||
          x1 = width - border_width[ST_SIDE_RIGHT];
 | 
			
		||||
          y1 = skip_corner_1 ? max_width_radius[ST_CORNER_TOPRIGHT]
 | 
			
		||||
          rects[4] = width - border_width[ST_SIDE_RIGHT];
 | 
			
		||||
          rects[5] = skip_corner_1 ? max_width_radius[ST_CORNER_TOPRIGHT]
 | 
			
		||||
                             : border_width[ST_SIDE_TOP];
 | 
			
		||||
          x2 = width;
 | 
			
		||||
          y2 = skip_corner_2 ? height - max_width_radius[ST_CORNER_BOTTOMRIGHT]
 | 
			
		||||
          rects[6] = width;
 | 
			
		||||
          rects[7] = skip_corner_2 ? height - max_width_radius[ST_CORNER_BOTTOMRIGHT]
 | 
			
		||||
                             : height - border_width[ST_SIDE_BOTTOM];
 | 
			
		||||
          cogl_rectangle (x1, y1, x2, y2);
 | 
			
		||||
 | 
			
		||||
          /* SOUTH */
 | 
			
		||||
          skip_corner_1 = border_radius[ST_CORNER_BOTTOMLEFT] > 0;
 | 
			
		||||
          skip_corner_2 = border_radius[ST_CORNER_BOTTOMRIGHT] > 0;
 | 
			
		||||
 | 
			
		||||
          x1 = skip_corner_1 ? max_width_radius[ST_CORNER_BOTTOMLEFT] : 0;
 | 
			
		||||
          y1 = height - border_width[ST_SIDE_BOTTOM];
 | 
			
		||||
          x2 = skip_corner_2 ? width - max_width_radius[ST_CORNER_BOTTOMRIGHT]
 | 
			
		||||
          rects[8] = skip_corner_1 ? max_width_radius[ST_CORNER_BOTTOMLEFT] : 0;
 | 
			
		||||
          rects[9] = height - border_width[ST_SIDE_BOTTOM];
 | 
			
		||||
          rects[10] = skip_corner_2 ? width - max_width_radius[ST_CORNER_BOTTOMRIGHT]
 | 
			
		||||
                             : width;
 | 
			
		||||
          y2 = height;
 | 
			
		||||
          cogl_rectangle (x1, y1, x2, y2);
 | 
			
		||||
          rects[11] = height;
 | 
			
		||||
 | 
			
		||||
          /* WEST */
 | 
			
		||||
          skip_corner_1 = border_radius[ST_CORNER_TOPLEFT] > 0;
 | 
			
		||||
          skip_corner_2 = border_radius[ST_CORNER_BOTTOMLEFT] > 0;
 | 
			
		||||
 | 
			
		||||
          x1 = 0;
 | 
			
		||||
          y1 = skip_corner_1 ? max_width_radius[ST_CORNER_TOPLEFT]
 | 
			
		||||
          rects[12] = 0;
 | 
			
		||||
          rects[13] = skip_corner_1 ? max_width_radius[ST_CORNER_TOPLEFT]
 | 
			
		||||
                             : border_width[ST_SIDE_TOP];
 | 
			
		||||
          x2 = border_width[ST_SIDE_LEFT];
 | 
			
		||||
          y2 = skip_corner_2 ? height - max_width_radius[ST_CORNER_BOTTOMLEFT]
 | 
			
		||||
          rects[14] = border_width[ST_SIDE_LEFT];
 | 
			
		||||
          rects[15] = skip_corner_2 ? height - max_width_radius[ST_CORNER_BOTTOMLEFT]
 | 
			
		||||
                             : height - border_width[ST_SIDE_BOTTOM];
 | 
			
		||||
          cogl_rectangle (x1, y1, x2, y2);
 | 
			
		||||
 | 
			
		||||
          cogl_rectangles (rects, 4);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1875,6 +1873,7 @@ st_theme_node_paint_outline (StThemeNode           *node,
 | 
			
		||||
{
 | 
			
		||||
  float width, height;
 | 
			
		||||
  int outline_width;
 | 
			
		||||
  float rects[16];
 | 
			
		||||
  ClutterColor outline_color, effective_outline;
 | 
			
		||||
 | 
			
		||||
  width = box->x2 - box->x1;
 | 
			
		||||
@@ -1899,20 +1898,30 @@ st_theme_node_paint_outline (StThemeNode           *node,
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  /* NORTH */
 | 
			
		||||
  cogl_rectangle (-outline_width, -outline_width,
 | 
			
		||||
                  width + outline_width, 0);
 | 
			
		||||
  rects[0] = -outline_width;
 | 
			
		||||
  rects[1] = -outline_width;
 | 
			
		||||
  rects[2] = width + outline_width;
 | 
			
		||||
  rects[3] = 0;
 | 
			
		||||
 | 
			
		||||
  /* EAST */
 | 
			
		||||
  cogl_rectangle (width, 0,
 | 
			
		||||
                  width + outline_width, height);
 | 
			
		||||
  rects[4] = width;
 | 
			
		||||
  rects[5] = 0;
 | 
			
		||||
  rects[6] = width + outline_width;
 | 
			
		||||
  rects[7] = height;
 | 
			
		||||
 | 
			
		||||
  /* SOUTH */
 | 
			
		||||
  cogl_rectangle (-outline_width, height,
 | 
			
		||||
                  width + outline_width, height + outline_width);
 | 
			
		||||
  rects[8] = -outline_width;
 | 
			
		||||
  rects[9] = height;
 | 
			
		||||
  rects[10] = width + outline_width;
 | 
			
		||||
  rects[11] = height + outline_width;
 | 
			
		||||
 | 
			
		||||
  /* WEST */
 | 
			
		||||
  cogl_rectangle (-outline_width, 0,
 | 
			
		||||
                  0, height);
 | 
			
		||||
  rects[12] = -outline_width;
 | 
			
		||||
  rects[13] = 0;
 | 
			
		||||
  rects[14] = 0;
 | 
			
		||||
  rects[15] = height;
 | 
			
		||||
 | 
			
		||||
  cogl_rectangles (rects, 4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -2060,6 +2069,9 @@ st_theme_node_copy_cached_paint_state (StThemeNode *node,
 | 
			
		||||
  g_return_if_fail (ST_IS_THEME_NODE (node));
 | 
			
		||||
  g_return_if_fail (ST_IS_THEME_NODE (other));
 | 
			
		||||
 | 
			
		||||
  if (node == other)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* Check omitted for speed: */
 | 
			
		||||
  /* g_return_if_fail (st_theme_node_paint_equal (node, other)); */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -77,8 +77,8 @@ struct _StThemeNode {
 | 
			
		||||
 | 
			
		||||
  GType element_type;
 | 
			
		||||
  char *element_id;
 | 
			
		||||
  char *element_class;
 | 
			
		||||
  char *pseudo_class;
 | 
			
		||||
  GStrv element_classes;
 | 
			
		||||
  GStrv pseudo_classes;
 | 
			
		||||
  char *inline_style;
 | 
			
		||||
 | 
			
		||||
  CRDeclaration **properties;
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,6 @@ struct _StThemeNodeTransitionPrivate {
 | 
			
		||||
 | 
			
		||||
  CoglHandle material;
 | 
			
		||||
 | 
			
		||||
  ClutterAlpha    *alpha;
 | 
			
		||||
  ClutterTimeline *timeline;
 | 
			
		||||
 | 
			
		||||
  guint timeline_completed_id;
 | 
			
		||||
@@ -91,7 +90,6 @@ st_theme_node_transition_new (StThemeNode *from_node,
 | 
			
		||||
  transition->priv->old_theme_node = g_object_ref (from_node);
 | 
			
		||||
  transition->priv->new_theme_node = g_object_ref (to_node);
 | 
			
		||||
 | 
			
		||||
  transition->priv->alpha = clutter_alpha_new ();
 | 
			
		||||
  transition->priv->timeline = clutter_timeline_new (duration);
 | 
			
		||||
 | 
			
		||||
  transition->priv->timeline_completed_id =
 | 
			
		||||
@@ -101,9 +99,7 @@ st_theme_node_transition_new (StThemeNode *from_node,
 | 
			
		||||
    g_signal_connect (transition->priv->timeline, "new-frame",
 | 
			
		||||
                      G_CALLBACK (on_timeline_new_frame), transition);
 | 
			
		||||
 | 
			
		||||
  clutter_alpha_set_mode (transition->priv->alpha, CLUTTER_EASE_IN_OUT_QUAD);
 | 
			
		||||
  clutter_alpha_set_timeline (transition->priv->alpha,
 | 
			
		||||
                              transition->priv->timeline);
 | 
			
		||||
  clutter_timeline_set_progress_mode (transition->priv->timeline, CLUTTER_EASE_IN_OUT_QUAD);
 | 
			
		||||
 | 
			
		||||
  clutter_timeline_start (transition->priv->timeline);
 | 
			
		||||
 | 
			
		||||
@@ -334,7 +330,7 @@ st_theme_node_transition_paint (StThemeNodeTransition *transition,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  cogl_color_set_from_4f (&constant, 0., 0., 0.,
 | 
			
		||||
                          clutter_alpha_get_alpha (priv->alpha));
 | 
			
		||||
                          clutter_timeline_get_progress (priv->timeline));
 | 
			
		||||
  cogl_material_set_layer_combine_constant (priv->material, 1, &constant);
 | 
			
		||||
 | 
			
		||||
  cogl_material_set_color4ub (priv->material,
 | 
			
		||||
@@ -412,12 +408,6 @@ st_theme_node_transition_dispose (GObject *object)
 | 
			
		||||
  priv->timeline_completed_id = 0;
 | 
			
		||||
  priv->timeline_new_frame_id = 0;
 | 
			
		||||
 | 
			
		||||
  if (priv->alpha)
 | 
			
		||||
    {
 | 
			
		||||
      g_object_unref (priv->alpha);
 | 
			
		||||
      priv->alpha = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (st_theme_node_transition_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -436,8 +426,6 @@ st_theme_node_transition_init (StThemeNodeTransition *transition)
 | 
			
		||||
  transition->priv->new_offscreen = NULL;
 | 
			
		||||
 | 
			
		||||
  transition->priv->needs_setup = TRUE;
 | 
			
		||||
 | 
			
		||||
  transition->priv->alpha = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
@@ -96,8 +96,8 @@ st_theme_node_finalize (GObject *object)
 | 
			
		||||
  StThemeNode *node = ST_THEME_NODE (object);
 | 
			
		||||
 | 
			
		||||
  g_free (node->element_id);
 | 
			
		||||
  g_free (node->element_class);
 | 
			
		||||
  g_free (node->pseudo_class);
 | 
			
		||||
  g_strfreev (node->element_classes);
 | 
			
		||||
  g_strfreev (node->pseudo_classes);
 | 
			
		||||
  g_free (node->inline_style);
 | 
			
		||||
 | 
			
		||||
  if (node->properties)
 | 
			
		||||
@@ -145,6 +145,33 @@ st_theme_node_finalize (GObject *object)
 | 
			
		||||
  G_OBJECT_CLASS (st_theme_node_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GStrv
 | 
			
		||||
split_on_whitespace (const gchar *s)
 | 
			
		||||
{
 | 
			
		||||
  gchar *cur;
 | 
			
		||||
  gchar *l;
 | 
			
		||||
  gchar *temp;
 | 
			
		||||
  GPtrArray *arr;
 | 
			
		||||
 | 
			
		||||
  if (s == NULL)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  arr = g_ptr_array_new ();
 | 
			
		||||
  l = g_strdup (s);
 | 
			
		||||
 | 
			
		||||
  cur = strtok_r (l, " \t\f\r\n", &temp);
 | 
			
		||||
 | 
			
		||||
  while (cur != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_ptr_array_add (arr, g_strdup (cur));
 | 
			
		||||
      cur = strtok_r (NULL, " \t\f\r\n", &temp);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_free (l);
 | 
			
		||||
  g_ptr_array_add (arr, NULL);
 | 
			
		||||
  return (GStrv) g_ptr_array_free (arr, FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * st_theme_node_new:
 | 
			
		||||
 * @context: the context representing global state for this themed tree
 | 
			
		||||
@@ -201,8 +228,8 @@ st_theme_node_new (StThemeContext    *context,
 | 
			
		||||
 | 
			
		||||
  node->element_type = element_type;
 | 
			
		||||
  node->element_id = g_strdup (element_id);
 | 
			
		||||
  node->element_class = g_strdup (element_class);
 | 
			
		||||
  node->pseudo_class = g_strdup (pseudo_class);
 | 
			
		||||
  node->element_classes = split_on_whitespace (element_class);
 | 
			
		||||
  node->pseudo_classes = split_on_whitespace (pseudo_class);
 | 
			
		||||
  node->inline_style = g_strdup (inline_style);
 | 
			
		||||
 | 
			
		||||
  return node;
 | 
			
		||||
@@ -257,20 +284,30 @@ st_theme_node_get_element_id (StThemeNode *node)
 | 
			
		||||
  return node->element_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *
 | 
			
		||||
st_theme_node_get_element_class (StThemeNode *node)
 | 
			
		||||
/**
 | 
			
		||||
 * st_theme_node_get_element_classes:
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (transfer none): the element's classes
 | 
			
		||||
 */
 | 
			
		||||
GStrv
 | 
			
		||||
st_theme_node_get_element_classes (StThemeNode *node)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (ST_IS_THEME_NODE (node), NULL);
 | 
			
		||||
 | 
			
		||||
  return node->element_class;
 | 
			
		||||
  return node->element_classes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *
 | 
			
		||||
st_theme_node_get_pseudo_class (StThemeNode *node)
 | 
			
		||||
/**
 | 
			
		||||
 * st_theme_node_get_pseudo_classes:
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (transfer none): the element's pseudo-classes
 | 
			
		||||
 */
 | 
			
		||||
GStrv
 | 
			
		||||
st_theme_node_get_pseudo_classes (StThemeNode *node)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (ST_IS_THEME_NODE (node), NULL);
 | 
			
		||||
 | 
			
		||||
  return node->pseudo_class;
 | 
			
		||||
  return node->pseudo_classes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -304,16 +341,91 @@ gboolean
 | 
			
		||||
st_theme_node_equal (StThemeNode *node_a, StThemeNode *node_b)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (ST_IS_THEME_NODE (node_a), FALSE);
 | 
			
		||||
 | 
			
		||||
  if (node_a == node_b)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (ST_IS_THEME_NODE (node_b), FALSE);
 | 
			
		||||
 | 
			
		||||
  return node_a->parent_node == node_b->parent_node &&
 | 
			
		||||
         node_a->context == node_b->context &&
 | 
			
		||||
         node_a->theme == node_b->theme &&
 | 
			
		||||
         node_a->element_type == node_b->element_type &&
 | 
			
		||||
         !g_strcmp0 (node_a->element_id, node_b->element_id) &&
 | 
			
		||||
         !g_strcmp0 (node_a->element_class, node_b->element_class) &&
 | 
			
		||||
         !g_strcmp0 (node_a->pseudo_class, node_b->pseudo_class) &&
 | 
			
		||||
         !g_strcmp0 (node_a->inline_style, node_b->inline_style);
 | 
			
		||||
  if (node_a->parent_node != node_b->parent_node ||
 | 
			
		||||
      node_a->context != node_b->context ||
 | 
			
		||||
      node_a->theme != node_b->theme ||
 | 
			
		||||
      node_a->element_type != node_b->element_type ||
 | 
			
		||||
      g_strcmp0 (node_a->element_id, node_b->element_id) ||
 | 
			
		||||
      g_strcmp0 (node_a->inline_style, node_b->inline_style))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if ((node_a->element_classes == NULL) != (node_b->element_classes == NULL))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if ((node_a->pseudo_classes == NULL) != (node_b->pseudo_classes == NULL))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (node_a->element_classes != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      int i;
 | 
			
		||||
 | 
			
		||||
      for (i = 0; ; i++)
 | 
			
		||||
        {
 | 
			
		||||
          if (g_strcmp0 (node_a->element_classes[i],
 | 
			
		||||
                         node_b->element_classes[i]))
 | 
			
		||||
            return FALSE;
 | 
			
		||||
 | 
			
		||||
          if (node_a->element_classes[i] == NULL)
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (node_a->pseudo_classes != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      int i;
 | 
			
		||||
 | 
			
		||||
      for (i = 0; ; i++)
 | 
			
		||||
        {
 | 
			
		||||
          if (g_strcmp0 (node_a->pseudo_classes[i],
 | 
			
		||||
                         node_b->pseudo_classes[i]))
 | 
			
		||||
            return FALSE;
 | 
			
		||||
 | 
			
		||||
          if (node_a->pseudo_classes[i] == NULL)
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
guint
 | 
			
		||||
st_theme_node_hash (StThemeNode *node)
 | 
			
		||||
{
 | 
			
		||||
  guint hash = GPOINTER_TO_UINT (node->parent_node);
 | 
			
		||||
 | 
			
		||||
  hash = hash * 33 + GPOINTER_TO_UINT (node->context);
 | 
			
		||||
  hash = hash * 33 + GPOINTER_TO_UINT (node->theme);
 | 
			
		||||
  hash = hash * 33 + ((guint) node->element_type);
 | 
			
		||||
 | 
			
		||||
  if (node->element_id != NULL)
 | 
			
		||||
    hash = hash * 33 + g_str_hash (node->element_id);
 | 
			
		||||
 | 
			
		||||
  if (node->inline_style != NULL)
 | 
			
		||||
    hash = hash * 33 + g_str_hash (node->inline_style);
 | 
			
		||||
 | 
			
		||||
  if (node->element_classes != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      gchar **it;
 | 
			
		||||
 | 
			
		||||
      for (it = node->element_classes; *it != NULL; it++)
 | 
			
		||||
        hash = hash * 33 + g_str_hash (*it) + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (node->pseudo_classes != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      gchar **it;
 | 
			
		||||
 | 
			
		||||
      for (it = node->pseudo_classes; *it != NULL; it++)
 | 
			
		||||
        hash = hash * 33 + g_str_hash (*it) + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return hash;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -3440,6 +3552,10 @@ st_theme_node_geometry_equal (StThemeNode *node,
 | 
			
		||||
  StSide side;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (ST_IS_THEME_NODE (node), FALSE);
 | 
			
		||||
 | 
			
		||||
  if (node == other)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (ST_IS_THEME_NODE (other), FALSE);
 | 
			
		||||
 | 
			
		||||
  _st_theme_node_ensure_geometry (node);
 | 
			
		||||
@@ -3484,6 +3600,10 @@ st_theme_node_paint_equal (StThemeNode *node,
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (ST_IS_THEME_NODE (node), FALSE);
 | 
			
		||||
 | 
			
		||||
  if (node == other)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (ST_IS_THEME_NODE (other), FALSE);
 | 
			
		||||
 | 
			
		||||
  _st_theme_node_ensure_background (node);
 | 
			
		||||
 
 | 
			
		||||
@@ -110,11 +110,12 @@ StThemeNode *st_theme_node_get_parent (StThemeNode *node);
 | 
			
		||||
StTheme *st_theme_node_get_theme (StThemeNode *node);
 | 
			
		||||
 | 
			
		||||
gboolean    st_theme_node_equal (StThemeNode *node_a, StThemeNode *node_b);
 | 
			
		||||
guint       st_theme_node_hash  (StThemeNode *node);
 | 
			
		||||
 | 
			
		||||
GType       st_theme_node_get_element_type  (StThemeNode *node);
 | 
			
		||||
const char *st_theme_node_get_element_id    (StThemeNode *node);
 | 
			
		||||
const char *st_theme_node_get_element_class (StThemeNode *node);
 | 
			
		||||
const char *st_theme_node_get_pseudo_class  (StThemeNode *node);
 | 
			
		||||
GStrv       st_theme_node_get_element_classes (StThemeNode *node);
 | 
			
		||||
GStrv       st_theme_node_get_pseudo_classes (StThemeNode *node);
 | 
			
		||||
 | 
			
		||||
/* Generic getters ... these are not cached so are less efficient. The other
 | 
			
		||||
 * reason for adding the more specific version is that we can handle the
 | 
			
		||||
 
 | 
			
		||||
@@ -448,25 +448,17 @@ st_theme_new (const char       *application_stylesheet,
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
string_in_list (GString    *stryng,
 | 
			
		||||
                const char *list)
 | 
			
		||||
                GStrv       list)
 | 
			
		||||
{
 | 
			
		||||
  const char *cur;
 | 
			
		||||
  gchar **it;
 | 
			
		||||
 | 
			
		||||
  for (cur = list; *cur;)
 | 
			
		||||
  if (list == NULL)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  for (it = list; *it != NULL; it++)
 | 
			
		||||
    {
 | 
			
		||||
      while (*cur && cr_utils_is_white_space (*cur))
 | 
			
		||||
        cur++;
 | 
			
		||||
 | 
			
		||||
      if (strncmp (cur, stryng->str, stryng->len) == 0)
 | 
			
		||||
        {
 | 
			
		||||
          cur +=  stryng->len;
 | 
			
		||||
          if ((!*cur) || cr_utils_is_white_space (*cur))
 | 
			
		||||
            return TRUE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      /*  skip to next whitespace character  */
 | 
			
		||||
      while (*cur && !cr_utils_is_white_space (*cur))
 | 
			
		||||
        cur++;
 | 
			
		||||
      if (!strqcmp (*it, stryng->str, stryng->len))
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
@@ -477,7 +469,7 @@ pseudo_class_add_sel_matches_style (StTheme         *a_this,
 | 
			
		||||
                                    CRAdditionalSel *a_add_sel,
 | 
			
		||||
                                    StThemeNode     *a_node)
 | 
			
		||||
{
 | 
			
		||||
  const char *node_pseudo_class;
 | 
			
		||||
  GStrv node_pseudo_classes;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (a_this
 | 
			
		||||
                        && a_add_sel
 | 
			
		||||
@@ -487,12 +479,10 @@ pseudo_class_add_sel_matches_style (StTheme         *a_this,
 | 
			
		||||
                        && a_add_sel->content.pseudo->name->stryng->str
 | 
			
		||||
                        && a_node, FALSE);
 | 
			
		||||
 | 
			
		||||
  node_pseudo_class = st_theme_node_get_pseudo_class (a_node);
 | 
			
		||||
  node_pseudo_classes = st_theme_node_get_pseudo_classes (a_node);
 | 
			
		||||
 | 
			
		||||
  if (node_pseudo_class == NULL)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  return string_in_list (a_add_sel->content.pseudo->name->stryng, node_pseudo_class);
 | 
			
		||||
  return string_in_list (a_add_sel->content.pseudo->name->stryng,
 | 
			
		||||
                         node_pseudo_classes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -507,7 +497,7 @@ static gboolean
 | 
			
		||||
class_add_sel_matches_style (CRAdditionalSel *a_add_sel,
 | 
			
		||||
                             StThemeNode     *a_node)
 | 
			
		||||
{
 | 
			
		||||
  const char *element_class;
 | 
			
		||||
  GStrv element_classes;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (a_add_sel
 | 
			
		||||
                        && a_add_sel->type == CLASS_ADD_SELECTOR
 | 
			
		||||
@@ -516,11 +506,10 @@ class_add_sel_matches_style (CRAdditionalSel *a_add_sel,
 | 
			
		||||
                        && a_add_sel->content.class_name->stryng->str
 | 
			
		||||
                        && a_node, FALSE);
 | 
			
		||||
 | 
			
		||||
  element_class = st_theme_node_get_element_class (a_node);
 | 
			
		||||
  if (element_class == NULL)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  element_classes = st_theme_node_get_element_classes (a_node);
 | 
			
		||||
 | 
			
		||||
  return string_in_list (a_add_sel->content.class_name->stryng, element_class);
 | 
			
		||||
  return string_in_list (a_add_sel->content.class_name->stryng,
 | 
			
		||||
                         element_classes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -589,6 +589,8 @@ st_widget_get_theme_node (StWidget *widget)
 | 
			
		||||
 | 
			
		||||
  if (priv->theme_node == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      StThemeContext *context;
 | 
			
		||||
      StThemeNode *tmp_node;
 | 
			
		||||
      StThemeNode *parent_node = NULL;
 | 
			
		||||
      ClutterStage *stage = NULL;
 | 
			
		||||
      ClutterActor *parent;
 | 
			
		||||
@@ -629,16 +631,20 @@ st_widget_get_theme_node (StWidget *widget)
 | 
			
		||||
      else
 | 
			
		||||
        pseudo_class = direction_pseudo_class;
 | 
			
		||||
 | 
			
		||||
      priv->theme_node = st_theme_node_new (st_theme_context_get_for_stage (stage),
 | 
			
		||||
                                            parent_node, priv->theme,
 | 
			
		||||
                                            G_OBJECT_TYPE (widget),
 | 
			
		||||
                                            clutter_actor_get_name (CLUTTER_ACTOR (widget)),
 | 
			
		||||
                                            priv->style_class,
 | 
			
		||||
                                            pseudo_class,
 | 
			
		||||
                                            priv->inline_style);
 | 
			
		||||
      context = st_theme_context_get_for_stage (stage);
 | 
			
		||||
      tmp_node = st_theme_node_new (context, parent_node, priv->theme,
 | 
			
		||||
                                    G_OBJECT_TYPE (widget),
 | 
			
		||||
                                    clutter_actor_get_name (CLUTTER_ACTOR (widget)),
 | 
			
		||||
                                    priv->style_class,
 | 
			
		||||
                                    pseudo_class,
 | 
			
		||||
                                    priv->inline_style);
 | 
			
		||||
 | 
			
		||||
      if (pseudo_class != direction_pseudo_class)
 | 
			
		||||
        g_free (pseudo_class);
 | 
			
		||||
 | 
			
		||||
      priv->theme_node = g_object_ref (st_theme_context_intern_node (context,
 | 
			
		||||
                                                                     tmp_node));
 | 
			
		||||
      g_object_unref (tmp_node);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return priv->theme_node;
 | 
			
		||||
@@ -1526,6 +1532,12 @@ st_widget_recompute_style (StWidget    *widget,
 | 
			
		||||
  int transition_duration;
 | 
			
		||||
  gboolean paint_equal;
 | 
			
		||||
 | 
			
		||||
  if (new_theme_node == old_theme_node)
 | 
			
		||||
    {
 | 
			
		||||
      widget->priv->is_style_dirty = FALSE;
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!old_theme_node ||
 | 
			
		||||
      !st_theme_node_geometry_equal (old_theme_node, new_theme_node))
 | 
			
		||||
    clutter_actor_queue_relayout ((ClutterActor *) widget);
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ on_stage_realized (ClutterActor *stage,
 | 
			
		||||
                   gpointer      data)
 | 
			
		||||
{
 | 
			
		||||
  recorder = shell_recorder_new (CLUTTER_STAGE (stage));
 | 
			
		||||
  shell_recorder_set_file_template (recorder, "test-recorder.ogg");
 | 
			
		||||
  shell_recorder_set_file_template (recorder, "test-recorder.webm");
 | 
			
		||||
  shell_recorder_record (recorder);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ TEST_JS =					\
 | 
			
		||||
	interactive/scrolling.js		\
 | 
			
		||||
	interactive/scroll-view-sizing.js	\
 | 
			
		||||
	interactive/table.js			\
 | 
			
		||||
	interactive/test-title.js		\
 | 
			
		||||
	interactive/transitions.js		\
 | 
			
		||||
	testcommon/100-200.svg			\
 | 
			
		||||
	testcommon/200-100.svg			\
 | 
			
		||||
@@ -25,11 +26,14 @@ TEST_JS =					\
 | 
			
		||||
	testcommon/border-image.png		\
 | 
			
		||||
	testcommon/face-plain.png		\
 | 
			
		||||
	testcommon/ui.js                        \
 | 
			
		||||
	testcommon/iso3166-test.tab             \
 | 
			
		||||
	testcommon/serviceproviders-test.xml    \
 | 
			
		||||
	unit/format.js				\
 | 
			
		||||
	unit/insertSorted.js			\
 | 
			
		||||
	unit/markup.js				\
 | 
			
		||||
	unit/jsParse.js				\
 | 
			
		||||
	unit/url.js
 | 
			
		||||
	unit/url.js                             \
 | 
			
		||||
	unit/mobileProviders.js
 | 
			
		||||
EXTRA_DIST += $(TEST_JS)
 | 
			
		||||
 | 
			
		||||
TEST_MISC =					\
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								tests/testcommon/iso3166-test.tab
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tests/testcommon/iso3166-test.tab
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
# Test country list
 | 
			
		||||
ES	Spain
 | 
			
		||||
US	United States
 | 
			
		||||
							
								
								
									
										44
									
								
								tests/testcommon/serviceproviders-test.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								tests/testcommon/serviceproviders-test.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
 | 
			
		||||
<!-- -*- Mode: XML; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- -->
 | 
			
		||||
 | 
			
		||||
<!DOCTYPE serviceproviders SYSTEM "serviceproviders.2.dtd">
 | 
			
		||||
 | 
			
		||||
<serviceproviders format="2.0">
 | 
			
		||||
 | 
			
		||||
  <!-- United States -->
 | 
			
		||||
  <country code="us">
 | 
			
		||||
    <provider>
 | 
			
		||||
      <name>AT&T</name>
 | 
			
		||||
      <gsm>
 | 
			
		||||
	<network-id mcc="310" mnc="038"/>
 | 
			
		||||
	<network-id mcc="310" mnc="090"/>
 | 
			
		||||
	<network-id mcc="310" mnc="150"/>
 | 
			
		||||
      </gsm>
 | 
			
		||||
    </provider>
 | 
			
		||||
    <provider>
 | 
			
		||||
      <name>Verizon</name>
 | 
			
		||||
      <gsm>
 | 
			
		||||
	<network-id mcc="310" mnc="995"/>
 | 
			
		||||
	<network-id mcc="311" mnc="480"/>
 | 
			
		||||
      </gsm>
 | 
			
		||||
      <cdma>
 | 
			
		||||
	<sid value="2"/>
 | 
			
		||||
	<sid value="4"/>
 | 
			
		||||
	<sid value="5"/>
 | 
			
		||||
      </cdma>
 | 
			
		||||
    </provider>
 | 
			
		||||
  </country>
 | 
			
		||||
 | 
			
		||||
  <!-- Spain -->
 | 
			
		||||
  <country code="es">
 | 
			
		||||
    <provider>
 | 
			
		||||
      <name>Movistar (Telefónica)</name>
 | 
			
		||||
      <gsm>
 | 
			
		||||
	<network-id mcc="214" mnc="05"/>
 | 
			
		||||
	<network-id mcc="214" mnc="07"/>
 | 
			
		||||
      </gsm>
 | 
			
		||||
    </provider>
 | 
			
		||||
  </country>
 | 
			
		||||
 | 
			
		||||
</serviceproviders>
 | 
			
		||||
							
								
								
									
										78
									
								
								tests/unit/mobileProviders.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								tests/unit/mobileProviders.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const JsUnit = imports.jsUnit;
 | 
			
		||||
const ModemManager = imports.misc.modemManager;
 | 
			
		||||
const Environment = imports.ui.environment;
 | 
			
		||||
 | 
			
		||||
Environment.init();
 | 
			
		||||
 | 
			
		||||
// Load test providers table
 | 
			
		||||
let countrycodesPath = GLib.getenv("GNOME_SHELL_TESTSDIR") + "/testcommon/iso3166-test.tab";
 | 
			
		||||
let serviceprovidersPath = GLib.getenv("GNOME_SHELL_TESTSDIR") + "/testcommon/serviceproviders-test.xml";
 | 
			
		||||
let providersTable = Shell.mobile_providers_parse(countrycodesPath, serviceprovidersPath);
 | 
			
		||||
 | 
			
		||||
function assertCountryFound(country_code, expected_country_name) {
 | 
			
		||||
    let country = providersTable[country_code];
 | 
			
		||||
    JsUnit.assertNotUndefined(country);
 | 
			
		||||
    JsUnit.assertEquals(country.get_country_name(), expected_country_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function assertCountryNotFound(country_code) {
 | 
			
		||||
    let country = providersTable[country_code];
 | 
			
		||||
    JsUnit.assertUndefined(country);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function assertProviderFoundForMCCMNC(mccmnc, expected_provider_name) {
 | 
			
		||||
    let provider_name = ModemManager.findProviderForMCCMNC(providersTable, mccmnc);
 | 
			
		||||
    JsUnit.assertEquals(provider_name, expected_provider_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function assertProviderNotFoundForMCCMNC(mccmnc) {
 | 
			
		||||
    let provider_name = ModemManager.findProviderForMCCMNC(providersTable, mccmnc);
 | 
			
		||||
    JsUnit.assertNull(provider_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function assertProviderFoundForSid(sid, expected_provider_name) {
 | 
			
		||||
    let provider_name = ModemManager.findProviderForSid(providersTable, sid);
 | 
			
		||||
    JsUnit.assertEquals(provider_name, expected_provider_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function assertProviderNotFoundForSid(sid) {
 | 
			
		||||
    let provider_name = ModemManager.findProviderForSid(providersTable, sid);
 | 
			
		||||
    JsUnit.assertNull(provider_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TEST:
 | 
			
		||||
// * Both 'US' and 'ES' country info should be loaded
 | 
			
		||||
assertCountryFound("ES", "Spain");
 | 
			
		||||
assertCountryFound("US", "United States");
 | 
			
		||||
 | 
			
		||||
// TEST:
 | 
			
		||||
// * Country info for 'FR' not given
 | 
			
		||||
assertCountryNotFound("FR");
 | 
			
		||||
 | 
			
		||||
// TEST:
 | 
			
		||||
// * Ensure operator names are found for the given MCC/MNC codes
 | 
			
		||||
assertProviderFoundForMCCMNC("21405", "Movistar (Telefónica)");
 | 
			
		||||
assertProviderFoundForMCCMNC("21407", "Movistar (Telefónica)");
 | 
			
		||||
assertProviderFoundForMCCMNC("310038", "AT&T");
 | 
			
		||||
assertProviderFoundForMCCMNC("310090", "AT&T");
 | 
			
		||||
assertProviderFoundForMCCMNC("310150", "AT&T");
 | 
			
		||||
assertProviderFoundForMCCMNC("310995", "Verizon");
 | 
			
		||||
assertProviderFoundForMCCMNC("311480", "Verizon");
 | 
			
		||||
 | 
			
		||||
// TEST:
 | 
			
		||||
// * Ensure NULL is given for unexpected MCC/MNC codes
 | 
			
		||||
assertProviderNotFoundForMCCMNC("12345");
 | 
			
		||||
 | 
			
		||||
// TEST:
 | 
			
		||||
// * Ensure operator names are found for the given SID codes
 | 
			
		||||
assertProviderFoundForSid(2, "Verizon");
 | 
			
		||||
assertProviderFoundForSid(4, "Verizon");
 | 
			
		||||
assertProviderFoundForSid(5, "Verizon");
 | 
			
		||||
 | 
			
		||||
// TEST:
 | 
			
		||||
// * Ensure NULL is given for unexpected SID codes
 | 
			
		||||
assertProviderNotFoundForSid(1);
 | 
			
		||||
		Reference in New Issue
	
	Block a user