Compare commits
	
		
			2 Commits
		
	
	
		
			wip/gcampa
			...
			3.7.3.1-br
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					7d598b7725 | ||
| 
						 | 
					9f890982b2 | 
							
								
								
									
										51
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,53 +1,6 @@
 | 
			
		||||
3.7.4.1
 | 
			
		||||
3.7.3.1
 | 
			
		||||
=======
 | 
			
		||||
* userMenu: Use show-full-name-in-top-bar setting [Bastien; #689561]
 | 
			
		||||
* dateMenu: Add "Open Clocks" entry [Mathieu; #644390]
 | 
			
		||||
* screenshot: Immediately show the flash spot [Jasper; #691875]
 | 
			
		||||
* Misc. bug fixes [Rico, Jeremy]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jeremy Bicha, Mathieu Bridon, Bastien Nocera, Jasper St. Pierre,
 | 
			
		||||
  Rico Tzschichholz
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Ihar Hrachyshka [be]
 | 
			
		||||
 | 
			
		||||
3.7.4
 | 
			
		||||
=====
 | 
			
		||||
* Make menu separators crisp [Giovanni, Allan; #641745]
 | 
			
		||||
* power: Update for new D-Bus name [Bastien; #690506]
 | 
			
		||||
* Add smooth scrolling support [Jasper; #687573]
 | 
			
		||||
* Tweak notification layout [Allan; #688506]
 | 
			
		||||
* Ping the active window when using the app menu [Giovanni; #684340]
 | 
			
		||||
* Make password entries insensitive after submission [Jasper; #690594, #690895]
 | 
			
		||||
* Honor lock-delay GSettings key [Giovanni, Matthias; #690766, #691170]
 | 
			
		||||
* Use text/calendar preferred app as the calendar app [Giovanni; #690767]
 | 
			
		||||
* lookingGlass: Move to an inspect() function [Jasper; #690726]
 | 
			
		||||
* Make OSK animation quicker, snappier [Rui; #688642]
 | 
			
		||||
* Allow to close chat notifications with Escape [Jasper; #690897]
 | 
			
		||||
* Honor org.gnome.desktop.screensaver.user-switch-enabled [Giovanni; #691042]
 | 
			
		||||
* Add a SelectArea() DBus method [Cosimo; #687954]
 | 
			
		||||
* Support non-absolute paths when saving screenshots [Cosimo; #688004]
 | 
			
		||||
* OSK: Fix extended keys popups [Rui; #674955]
 | 
			
		||||
* Don't hide or show the keyboard immediately [Rui; #688646]
 | 
			
		||||
* Improve padding in power menu [Giovanni; #689297]
 | 
			
		||||
* Add per-window input source switching [Rui; #691414]
 | 
			
		||||
* Misc bug fixes and cleanups [Rico, Jasper, Giovanni, Rui, Florian, Dan;
 | 
			
		||||
  #690608, #690589, #690539, #687081, #690667, #690665, #690666, #685856,
 | 
			
		||||
  #690858, #690895, #680414, #690965, #691019, #690590, #681376, #690180,
 | 
			
		||||
  #685513, #689263, #691553, #691720, #691743, #691750]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Giovanni Campagna, Cosimo Cecchi, Matthias Clasen, Allan Day, Rui Matos,
 | 
			
		||||
  Florian Müllner, Bastien Nocera, Jasper St. Pierre, Rico Tzschichholz,
 | 
			
		||||
  Dan Winship
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Matej Urbančič [sl], Kjartan Maraas [nb], Mattias Põldaru [et],
 | 
			
		||||
  Yaron Shahrabani [he], Aurimas Černius [lt], Khaled Hosny [ar],
 | 
			
		||||
  Fran Diéguez [gl], Daniel Mustieles [es], Piotr Drąg [pl], Balázs Úr [hu],
 | 
			
		||||
  Baurzhan Muftakhidinov [kk], Tobias Endrigkeit [de], Dušan Kazik [sk],
 | 
			
		||||
  Aron Xu [zh_CN], Gheyret Kenji [ug]
 | 
			
		||||
* Revert 490206b to not depend on NMGTK-0.9.7, which hasn't been released yet
 | 
			
		||||
 | 
			
		||||
3.7.3
 | 
			
		||||
=====
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										93
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										93
									
								
								configure.ac
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
AC_PREREQ(2.63)
 | 
			
		||||
AC_INIT([gnome-shell],[3.7.4.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
 | 
			
		||||
AC_INIT([gnome-shell],[3.7.3.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
 | 
			
		||||
 | 
			
		||||
AC_CONFIG_HEADERS([config.h])
 | 
			
		||||
AC_CONFIG_SRCDIR([src/shell-global.c])
 | 
			
		||||
@@ -16,6 +16,8 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
 | 
			
		||||
 | 
			
		||||
# Checks for programs.
 | 
			
		||||
AC_PROG_CC
 | 
			
		||||
# Needed for per-target cflags, like in gnomeshell-taskpanel
 | 
			
		||||
AM_PROG_CC_C_O
 | 
			
		||||
 | 
			
		||||
# Initialize libtool
 | 
			
		||||
LT_PREREQ([2.2.6])
 | 
			
		||||
@@ -60,14 +62,15 @@ fi
 | 
			
		||||
 | 
			
		||||
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
 | 
			
		||||
 | 
			
		||||
CLUTTER_MIN_VERSION=1.13.4
 | 
			
		||||
CLUTTER_MIN_VERSION=1.11.11
 | 
			
		||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
 | 
			
		||||
GJS_MIN_VERSION=1.35.4
 | 
			
		||||
MUTTER_MIN_VERSION=3.7.4
 | 
			
		||||
GJS_MIN_VERSION=1.33.2
 | 
			
		||||
MUTTER_MIN_VERSION=3.7.3
 | 
			
		||||
GTK_MIN_VERSION=3.3.9
 | 
			
		||||
GIO_MIN_VERSION=2.35.0
 | 
			
		||||
LIBECAL_MIN_VERSION=3.5.3
 | 
			
		||||
LIBEDATASERVER_MIN_VERSION=3.5.3
 | 
			
		||||
LIBEDATASERVERUI_MIN_VERSION=3.5.3
 | 
			
		||||
TELEPATHY_GLIB_MIN_VERSION=0.17.5
 | 
			
		||||
TELEPATHY_LOGGER_MIN_VERSION=0.2.4
 | 
			
		||||
POLKIT_MIN_VERSION=0.100
 | 
			
		||||
@@ -75,7 +78,6 @@ 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.6
 | 
			
		||||
PULSE_MIN_VERS=2.0
 | 
			
		||||
 | 
			
		||||
# Collect more than 20 libraries for a prize!
 | 
			
		||||
@@ -93,22 +95,37 @@ PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
 | 
			
		||||
			       clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
 | 
			
		||||
                               libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_MIN_VERSION
 | 
			
		||||
                               gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION
 | 
			
		||||
			       libcanberra libcanberra-gtk3
 | 
			
		||||
			       libcanberra
 | 
			
		||||
                               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 >= $NETWORKMANAGER_MIN_VERSION
 | 
			
		||||
                               libnm-gtk >= $NETWORKMANAGER_MIN_VERSION
 | 
			
		||||
                               gnome-keyring-1 gcr-3 >= $GCR_MIN_VERSION)
 | 
			
		||||
                               libnm-glib libnm-util gnome-keyring-1
 | 
			
		||||
                               gcr-3 >= $GCR_MIN_VERSION)
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0)
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(BROWSER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION json-glib-1.0 >= 0.13.2)
 | 
			
		||||
 | 
			
		||||
GNOME_KEYBINDINGS_KEYSDIR=`$PKG_CONFIG --variable keysdir gnome-keybindings`
 | 
			
		||||
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(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
 | 
			
		||||
PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0)
 | 
			
		||||
PKG_CHECK_MODULES(BROWSER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION json-glib-1.0 >= 0.13.2)
 | 
			
		||||
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
 | 
			
		||||
PKG_CHECK_MODULES(GVC, libpulse >= $PULSE_MIN_VERS libpulse-mainloop-glib gobject-2.0)
 | 
			
		||||
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.4)
 | 
			
		||||
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.2.2)
 | 
			
		||||
 | 
			
		||||
AC_MSG_CHECKING([for bluetooth support])
 | 
			
		||||
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
 | 
			
		||||
@@ -155,19 +172,6 @@ if test "x$use_systemd" = "xyes"; then
 | 
			
		||||
        AC_DEFINE(WITH_SYSTEMD, 1, [systemd support])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
GNOME_KEYBINDINGS_KEYSDIR=`$PKG_CONFIG --variable keysdir gnome-keybindings`
 | 
			
		||||
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(XFixesCreatePointerBarrier)
 | 
			
		||||
CFLAGS=$saved_CFLAGS
 | 
			
		||||
LIBS=$saved_LIBS
 | 
			
		||||
 | 
			
		||||
MUTTER_GIR_DIR=`$PKG_CONFIG --variable=girdir libmutter`
 | 
			
		||||
MUTTER_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter`
 | 
			
		||||
AC_SUBST(MUTTER_GIR_DIR)
 | 
			
		||||
@@ -193,6 +197,16 @@ fi
 | 
			
		||||
 | 
			
		||||
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
 | 
			
		||||
AM_PATH_GLIB_2_0()
 | 
			
		||||
G_IR_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
 | 
			
		||||
AC_SUBST(G_IR_SCANNER)
 | 
			
		||||
G_IR_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
 | 
			
		||||
AC_SUBST(G_IR_COMPILER)
 | 
			
		||||
G_IR_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
 | 
			
		||||
AC_SUBST(G_IR_GENERATE)
 | 
			
		||||
GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
 | 
			
		||||
AC_SUBST(GIRDIR)
 | 
			
		||||
TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
 | 
			
		||||
AC_SUBST(TYPELIBDIR)
 | 
			
		||||
 | 
			
		||||
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
 | 
			
		||||
 | 
			
		||||
@@ -208,7 +222,32 @@ if test "$enable_man" != no; then
 | 
			
		||||
fi
 | 
			
		||||
AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no)
 | 
			
		||||
 | 
			
		||||
GNOME_COMPILE_WARNINGS([error])
 | 
			
		||||
# Stay command-line compatible with the gnome-common configure option. Here
 | 
			
		||||
# minimum/yes/maximum are the same, however.
 | 
			
		||||
AC_ARG_ENABLE(compile_warnings,
 | 
			
		||||
  AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),,
 | 
			
		||||
  enable_compile_warnings=error)
 | 
			
		||||
 | 
			
		||||
changequote(,)dnl
 | 
			
		||||
if test "$enable_compile_warnings" != no ; then
 | 
			
		||||
  if test "x$GCC" = "xyes"; then
 | 
			
		||||
    case " $CFLAGS " in
 | 
			
		||||
    *[\ \	]-Wall[\ \	]*) ;;
 | 
			
		||||
    *) CFLAGS="$CFLAGS -Wall" ;;
 | 
			
		||||
    esac
 | 
			
		||||
    case " $CFLAGS " in
 | 
			
		||||
    *[\ \	]-Wmissing-prototypes[\ \	]*) ;;
 | 
			
		||||
    *) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
 | 
			
		||||
    esac
 | 
			
		||||
    if test "$enable_compile_warnings" = error ; then
 | 
			
		||||
      case " $CFLAGS " in
 | 
			
		||||
      *[\ \	]-Werror[\ \	]*) ;;
 | 
			
		||||
      *) CFLAGS="$CFLAGS -Werror -Wno-error=deprecated-declarations" ;;
 | 
			
		||||
      esac
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
changequote([,])dnl
 | 
			
		||||
 | 
			
		||||
AC_ARG_ENABLE(jhbuild-wrapper-script,
 | 
			
		||||
  AS_HELP_STRING([--enable-jhbuild-wrapper-script],[Make "gnome-shell" script work for jhbuild]),,enable_jhbuild_wrapper_script=no)
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,6 @@ desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
 | 
			
		||||
 | 
			
		||||
introspectiondir = $(datadir)/dbus-1/interfaces
 | 
			
		||||
introspection_DATA =				\
 | 
			
		||||
	org.gnome.Shell.Screenshot.xml		\
 | 
			
		||||
	org.gnome.ShellSearchProvider.xml	\
 | 
			
		||||
	org.gnome.ShellSearchProvider2.xml
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,128 +0,0 @@
 | 
			
		||||
<!DOCTYPE node PUBLIC
 | 
			
		||||
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
 | 
			
		||||
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
 | 
			
		||||
<node>
 | 
			
		||||
 | 
			
		||||
  <!--
 | 
			
		||||
      org.gnome.Shell.Screenshot:
 | 
			
		||||
      @short_description: Screenshot interface
 | 
			
		||||
 | 
			
		||||
      The interface used to capture pictures of the screen contents.
 | 
			
		||||
  -->
 | 
			
		||||
  <interface name="org.gnome.Shell.Screenshot">
 | 
			
		||||
 | 
			
		||||
    <!--
 | 
			
		||||
        Screenshot:
 | 
			
		||||
        @filename: The filename for the screenshot
 | 
			
		||||
        @include_cursor: Whether to include the cursor image or not
 | 
			
		||||
        @flash: Whether to flash the screen or not
 | 
			
		||||
        @success: whether the screenshot was captured
 | 
			
		||||
        @filename_used: the file where the screenshot was saved
 | 
			
		||||
 | 
			
		||||
        Takes a screenshot of the whole screen and saves it
 | 
			
		||||
        in @filename as png image, it returns a boolean
 | 
			
		||||
        indicating whether the operation was successful or not.
 | 
			
		||||
        @filename can either be an absolute path or a basename, in
 | 
			
		||||
        which case the screenshot will be saved in the $XDG_PICTURES_DIR
 | 
			
		||||
        or the home directory if it doesn't exist. The filename used
 | 
			
		||||
        to save the screenshot will be returned in @filename_used.
 | 
			
		||||
    -->
 | 
			
		||||
    <method name="Screenshot">
 | 
			
		||||
      <arg type="b" direction="in" name="include_cursor"/>
 | 
			
		||||
      <arg type="b" direction="in" name="flash"/>
 | 
			
		||||
      <arg type="s" direction="in" name="filename"/>
 | 
			
		||||
      <arg type="b" direction="out" name="success"/>
 | 
			
		||||
      <arg type="s" direction="out" name="filename_used"/>
 | 
			
		||||
    </method>
 | 
			
		||||
 | 
			
		||||
    <!--
 | 
			
		||||
        ScreenshotWindow:
 | 
			
		||||
        @include_frame: Whether to include the frame or not
 | 
			
		||||
        @include_cursor: Whether to include the cursor image or not
 | 
			
		||||
        @flash: Whether to flash the window area or not
 | 
			
		||||
        @filename: The filename for the screenshot
 | 
			
		||||
        @success: whether the screenshot was captured
 | 
			
		||||
        @filename_used: the file where the screenshot was saved
 | 
			
		||||
 | 
			
		||||
        Takes a screenshot of the focused window (optionally omitting the frame)
 | 
			
		||||
        and saves it in @filename as png image, it returns a boolean
 | 
			
		||||
        indicating whether the operation was successful or not.
 | 
			
		||||
        @filename can either be an absolute path or a basename, in
 | 
			
		||||
        which case the screenshot will be saved in the $XDG_PICTURES_DIR
 | 
			
		||||
        or the home directory if it doesn't exist. The filename used
 | 
			
		||||
        to save the screenshot will be returned in @filename_used.
 | 
			
		||||
    -->
 | 
			
		||||
    <method name="ScreenshotWindow">
 | 
			
		||||
      <arg type="b" direction="in" name="include_frame"/>
 | 
			
		||||
      <arg type="b" direction="in" name="include_cursor"/>
 | 
			
		||||
      <arg type="b" direction="in" name="flash"/>
 | 
			
		||||
      <arg type="s" direction="in" name="filename"/>
 | 
			
		||||
      <arg type="b" direction="out" name="success"/>
 | 
			
		||||
      <arg type="s" direction="out" name="filename_used"/>
 | 
			
		||||
    </method>
 | 
			
		||||
 | 
			
		||||
    <!--
 | 
			
		||||
        ScreenshotArea:
 | 
			
		||||
        @x: the X coordinate of the area to capture
 | 
			
		||||
        @y: the Y coordinate of the area to capture
 | 
			
		||||
        @width: the width of the area to capture
 | 
			
		||||
        @height: the height of the area to capture
 | 
			
		||||
        @flash: whether to flash the area or not
 | 
			
		||||
        @filename: the filename for the screenshot
 | 
			
		||||
        @success: whether the screenshot was captured
 | 
			
		||||
        @filename_used: the file where the screenshot was saved
 | 
			
		||||
 | 
			
		||||
        Takes a screenshot of the passed in area and saves it
 | 
			
		||||
        in @filename as png image, it returns a boolean
 | 
			
		||||
        indicating whether the operation was successful or not.
 | 
			
		||||
        @filename can either be an absolute path or a basename, in
 | 
			
		||||
        which case the screenshot will be saved in the $XDG_PICTURES_DIR
 | 
			
		||||
        or the home directory if it doesn't exist. The filename used
 | 
			
		||||
        to save the screenshot will be returned in @filename_used.
 | 
			
		||||
    -->
 | 
			
		||||
    <method name="ScreenshotArea">
 | 
			
		||||
      <arg type="i" direction="in" name="x"/>
 | 
			
		||||
      <arg type="i" direction="in" name="y"/>
 | 
			
		||||
      <arg type="i" direction="in" name="width"/>
 | 
			
		||||
      <arg type="i" direction="in" name="height"/>
 | 
			
		||||
      <arg type="b" direction="in" name="flash"/>
 | 
			
		||||
      <arg type="s" direction="in" name="filename"/>
 | 
			
		||||
      <arg type="b" direction="out" name="success"/>
 | 
			
		||||
      <arg type="s" direction="out" name="filename_used"/>
 | 
			
		||||
    </method>
 | 
			
		||||
 | 
			
		||||
    <!--
 | 
			
		||||
        FlashArea:
 | 
			
		||||
        @x: the X coordinate of the area to flash
 | 
			
		||||
        @y: the Y coordinate of the area to flash
 | 
			
		||||
        @width: the width of the area to flash
 | 
			
		||||
        @height: the height of the area to flash
 | 
			
		||||
 | 
			
		||||
        Renders a flash spot effect in the specified rectangle of the screen.
 | 
			
		||||
    -->
 | 
			
		||||
    <method name="FlashArea">
 | 
			
		||||
      <arg type="i" direction="in" name="x"/>
 | 
			
		||||
      <arg type="i" direction="in" name="y"/>
 | 
			
		||||
      <arg type="i" direction="in" name="width"/>
 | 
			
		||||
      <arg type="i" direction="in" name="height"/>
 | 
			
		||||
    </method>
 | 
			
		||||
 | 
			
		||||
    <!--
 | 
			
		||||
        SelectArea:
 | 
			
		||||
        @x: the X coordinate of the selected area
 | 
			
		||||
        @y: the Y coordinate of the selected area
 | 
			
		||||
        @width: the width of the selected area
 | 
			
		||||
        @height: the height of the selected area
 | 
			
		||||
 | 
			
		||||
        Interactively allows the user to select a rectangular area of
 | 
			
		||||
        the screen, and returns its coordinates.
 | 
			
		||||
    -->
 | 
			
		||||
    <method name="SelectArea">
 | 
			
		||||
      <arg type="i" direction="out" name="x"/>
 | 
			
		||||
      <arg type="i" direction="out" name="y"/>
 | 
			
		||||
      <arg type="i" direction="out" name="width"/>
 | 
			
		||||
      <arg type="i" direction="out" name="height"/>
 | 
			
		||||
    </method>
 | 
			
		||||
 | 
			
		||||
  </interface>
 | 
			
		||||
</node>
 | 
			
		||||
@@ -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>
 | 
			
		||||
    <key name="remember-mount-password" type="b">
 | 
			
		||||
      <default>false</default>
 | 
			
		||||
      <_summary>Whether to remember password for mounting encrypted or remote filesystems</_summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -206,12 +206,11 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popup-separator-menu-item {
 | 
			
		||||
    -gradient-height: 1px;
 | 
			
		||||
    -gradient-start: rgba(255,255,255,0.0);
 | 
			
		||||
    -gradient-end: rgba(255,255,255,0.3);
 | 
			
		||||
    -margin-horizontal: 24px;
 | 
			
		||||
    height: 1px;
 | 
			
		||||
    padding: 8px 0px;
 | 
			
		||||
    -gradient-height: 2px;
 | 
			
		||||
    -gradient-start: rgba(8,8,8,0);
 | 
			
		||||
    -gradient-end: #333333;
 | 
			
		||||
    -margin-horizontal: 1.5em;
 | 
			
		||||
    height: 1em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popup-alternating-menu-item:alternate {
 | 
			
		||||
@@ -252,10 +251,6 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    icon-size: 1.09em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.popup-battery-percentage {
 | 
			
		||||
    padding-left: 24px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Switches */
 | 
			
		||||
.toggle-switch {
 | 
			
		||||
    width: 65px;
 | 
			
		||||
@@ -292,17 +287,13 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
.hotplug-notification-item,
 | 
			
		||||
.hotplug-resident-eject-button,
 | 
			
		||||
.modal-dialog-button {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    border: 1px solid #8b8b8b;
 | 
			
		||||
    background-gradient-direction: vertical;
 | 
			
		||||
    background-gradient-start: rgba(255, 255, 255, 0.2);
 | 
			
		||||
    background-gradient-end: rgba(255, 255, 255, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dash-search-button,
 | 
			
		||||
.modal-dialog-button {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dash-search-button:hover,
 | 
			
		||||
.notification-button:hover,
 | 
			
		||||
.notification-icon-button:hover,
 | 
			
		||||
@@ -363,7 +354,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    background-gradient-start: rgba(5,5,6,0.1);
 | 
			
		||||
    background-gradient-end: rgba(254,254,254,0.1);
 | 
			
		||||
    background-gradient-direction: vertical;
 | 
			
		||||
    transition-duration: 300ms;
 | 
			
		||||
    transition-duration: 300;
 | 
			
		||||
    box-shadow: inset 0px 2px 4px rgba(0,0,0,0.6);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -398,7 +389,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    color: rgb(64, 64, 64);
 | 
			
		||||
    caret-color: rgb(64, 64, 64);
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    transition-duration: 0ms;
 | 
			
		||||
    transition-duration: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.notification StEntry,
 | 
			
		||||
@@ -429,7 +420,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    background-color: black;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    height: 1.86em;
 | 
			
		||||
    transition-duration: 250ms;
 | 
			
		||||
    transition-duration: 250;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#panel.lock-screen {
 | 
			
		||||
@@ -512,7 +503,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    -minimum-hpadding: 6px;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    color: #ccc;
 | 
			
		||||
    transition-duration: 100ms;
 | 
			
		||||
    transition-duration: 100;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#panel.unlock-screen .panel-button,
 | 
			
		||||
@@ -727,10 +718,6 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    -vertical-spacing: 32px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.window-picker.external-monitor {
 | 
			
		||||
    padding: 32px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Dash */
 | 
			
		||||
 | 
			
		||||
#dash {
 | 
			
		||||
@@ -755,6 +742,10 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    height: 24px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#viewSelector {
 | 
			
		||||
    spacing: 1em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Search Box */
 | 
			
		||||
 | 
			
		||||
#searchEntry {
 | 
			
		||||
@@ -779,10 +770,6 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    spacing: 18px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#searchResultsBin {
 | 
			
		||||
    max-width: 1000px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#searchResultsContent {
 | 
			
		||||
    padding-right: 20px;
 | 
			
		||||
    spacing: 16px;
 | 
			
		||||
@@ -930,7 +917,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
    padding: 3px;
 | 
			
		||||
    border: 1px rgba(0,0,0,0);
 | 
			
		||||
    transition-duration: 100ms;
 | 
			
		||||
    transition-duration: 100;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -947,7 +934,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
.grid-search-result:hover .overview-icon {
 | 
			
		||||
    background-color: rgba(255,255,255,0.1);
 | 
			
		||||
    text-shadow: black 0px 2px 2px;
 | 
			
		||||
    transition-duration: 100ms;
 | 
			
		||||
    transition-duration: 100;
 | 
			
		||||
    color:white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -963,20 +950,19 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.show-apps:checked > .overview-icon,
 | 
			
		||||
.show-apps:active > .overview-icon {
 | 
			
		||||
.show-apps:checked > .overview-icon {
 | 
			
		||||
    background-gradient-start: rgba(255, 255, 255, .05);
 | 
			
		||||
    background-gradient-end: rgba(255, 255, 255, .15);
 | 
			
		||||
    background-gradient-direction: vertical;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
    box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 1);
 | 
			
		||||
    transition-duration: 100ms;
 | 
			
		||||
    transition-duration: 100;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.show-apps:checked .show-apps-icon,
 | 
			
		||||
.show-apps:focus .show-apps-icon {
 | 
			
		||||
    color: white;
 | 
			
		||||
    transition-duration: 100ms;
 | 
			
		||||
    transition-duration: 100;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.app-well-app:focus > .overview-icon,
 | 
			
		||||
@@ -1015,7 +1001,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    -minimum-hpadding: 6px;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    color: #ccc;
 | 
			
		||||
    transition-duration: 100ms;
 | 
			
		||||
    transition-duration: 100;
 | 
			
		||||
    padding-left: .3em;
 | 
			
		||||
    padding-right: .3em;
 | 
			
		||||
}
 | 
			
		||||
@@ -1318,7 +1304,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
#message-tray {
 | 
			
		||||
    background: #2e3436 url(message-tray-background.png);
 | 
			
		||||
    background-repeat: repeat;
 | 
			
		||||
    height: 72px;
 | 
			
		||||
    transition-duration: 250;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#message-tray:keyboard {
 | 
			
		||||
@@ -1345,7 +1331,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
    border-radius: 10px 10px 0px 0px;
 | 
			
		||||
    background: rgba(0,0,0,0.9);
 | 
			
		||||
    padding: 8px 8px 4px 8px;
 | 
			
		||||
    spacing-rows: 4px;
 | 
			
		||||
    spacing-rows: 10px;
 | 
			
		||||
    spacing-columns: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1425,7 +1411,6 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.notification-actions {
 | 
			
		||||
    padding-top: 18px;
 | 
			
		||||
    spacing: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1588,7 +1573,7 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
.summary-source {
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
    padding: 0 6px 0 6px;
 | 
			
		||||
    transition-duration: 100ms;
 | 
			
		||||
    transition-duration: 100;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.summary-source-counter {
 | 
			
		||||
@@ -2417,7 +2402,6 @@ StScrollBar StButton#vhandle:active {
 | 
			
		||||
 | 
			
		||||
.screen-shield-notifications-box {
 | 
			
		||||
    spacing: 18px;
 | 
			
		||||
    max-width: 34em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.screen-shield-notification-source {
 | 
			
		||||
 
 | 
			
		||||
@@ -88,18 +88,11 @@ doc-gen-org.gnome.Shell.SearchProvider2.xml: $(top_srcdir)/data/org.gnome.ShellS
 | 
			
		||||
	--generate-docbook doc-gen				\
 | 
			
		||||
	$(top_srcdir)/data/org.gnome.ShellSearchProvider2.xml
 | 
			
		||||
 | 
			
		||||
doc-gen-org.gnome.Shell.Screenshot.xml: $(top_srcdir)/data/org.gnome.Shell.Screenshot.xml
 | 
			
		||||
	gdbus-codegen 						\
 | 
			
		||||
	--interface-prefix org.gnome.Shell.Screenshot.		\
 | 
			
		||||
	--generate-docbook doc-gen				\
 | 
			
		||||
	$(top_srcdir)/data/org.gnome.Shell.Screenshot.xml
 | 
			
		||||
 | 
			
		||||
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
 | 
			
		||||
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
 | 
			
		||||
content_files= \
 | 
			
		||||
	doc-gen-org.gnome.Shell.SearchProvider.xml	\
 | 
			
		||||
	doc-gen-org.gnome.Shell.SearchProvider2.xml	\
 | 
			
		||||
	doc-gen-org.gnome.Shell.Screenshot.xml
 | 
			
		||||
	doc-gen-org.gnome.Shell.SearchProvider2.xml
 | 
			
		||||
 | 
			
		||||
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
 | 
			
		||||
# These files must be listed here *and* in content_files
 | 
			
		||||
 
 | 
			
		||||
@@ -66,11 +66,4 @@ its dependencies to build from tarballs.</description>
 | 
			
		||||
      <gnome:userid>fmuellner</gnome:userid>
 | 
			
		||||
    </foaf:Person>
 | 
			
		||||
  </maintainer>
 | 
			
		||||
  <maintainer>
 | 
			
		||||
    <foaf:Person>
 | 
			
		||||
      <foaf:name>Ray Strode</foaf:name>
 | 
			
		||||
      <foaf:mbox rdf:resource="mailto:halfline@gmail.com" />
 | 
			
		||||
      <gnome:userid>halfline</gnome:userid>
 | 
			
		||||
    </foaf:Person>
 | 
			
		||||
  </maintainer>
 | 
			
		||||
</Project>
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,6 @@ nobase_dist_js_DATA = 	\
 | 
			
		||||
	misc/extensionUtils.js	\
 | 
			
		||||
	misc/fileUtils.js	\
 | 
			
		||||
	misc/gnomeSession.js	\
 | 
			
		||||
	misc/hash.js		\
 | 
			
		||||
	misc/history.js		\
 | 
			
		||||
	misc/jsParse.js		\
 | 
			
		||||
	misc/loginManager.js	\
 | 
			
		||||
@@ -50,6 +49,7 @@ nobase_dist_js_DATA = 	\
 | 
			
		||||
	ui/extensionSystem.js	\
 | 
			
		||||
	ui/extensionDownloader.js \
 | 
			
		||||
	ui/environment.js	\
 | 
			
		||||
	ui/flashspot.js		\
 | 
			
		||||
	ui/ibusCandidatePopup.js\
 | 
			
		||||
	ui/grabHelper.js	\
 | 
			
		||||
	ui/iconGrid.js		\
 | 
			
		||||
@@ -74,7 +74,6 @@ nobase_dist_js_DATA = 	\
 | 
			
		||||
	ui/popupMenu.js		\
 | 
			
		||||
	ui/remoteSearch.js	\
 | 
			
		||||
	ui/runDialog.js		\
 | 
			
		||||
	ui/screenshot.js	\
 | 
			
		||||
        ui/screenShield.js	\
 | 
			
		||||
	ui/scripting.js		\
 | 
			
		||||
	ui/search.js		\
 | 
			
		||||
 
 | 
			
		||||
@@ -128,7 +128,6 @@ const UserListItem = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        let layout = new St.BoxLayout({ vertical: false });
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
 | 
			
		||||
                                     button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                     can_focus: true,
 | 
			
		||||
                                     child: layout,
 | 
			
		||||
                                     reactive: true,
 | 
			
		||||
@@ -493,7 +492,6 @@ const SessionListItem = new Lang.Class({
 | 
			
		||||
        this.id = id;
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Button({ style_class: 'login-dialog-session-list-item',
 | 
			
		||||
                                     button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                     can_focus: true,
 | 
			
		||||
                                     reactive: true,
 | 
			
		||||
                                     x_fill: true,
 | 
			
		||||
@@ -534,7 +532,6 @@ const SessionListItem = new Lang.Class({
 | 
			
		||||
                          color.alpha / 255);
 | 
			
		||||
        cr.arc(width / 2, height / 2, width / 3, 0, 2 * Math.PI);
 | 
			
		||||
        cr.fill();
 | 
			
		||||
        cr.$dispose();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onClicked: function() {
 | 
			
		||||
@@ -554,7 +551,6 @@ const SessionList = new Lang.Class({
 | 
			
		||||
        this.actor.child = this._box;
 | 
			
		||||
 | 
			
		||||
        this._button = new St.Button({ style_class: 'login-dialog-session-list-button',
 | 
			
		||||
                                       button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                       can_focus: true,
 | 
			
		||||
                                       x_fill: true,
 | 
			
		||||
                                       y_fill: true });
 | 
			
		||||
@@ -677,7 +673,7 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        this.parent({ shellReactive: true,
 | 
			
		||||
                      styleClass: 'login-dialog',
 | 
			
		||||
                      parentActor: parentActor,
 | 
			
		||||
                      keybindingMode: Shell.KeyBindingMode.LOGIN_SCREEN,
 | 
			
		||||
                      keybindingMode: Main.KeybindingMode.LOGIN_SCREEN,
 | 
			
		||||
                      shouldFadeIn: false });
 | 
			
		||||
        this.connect('destroy',
 | 
			
		||||
                     Lang.bind(this, this._onDestroy));
 | 
			
		||||
@@ -790,7 +786,6 @@ const LoginDialog = new Lang.Class({
 | 
			
		||||
        let notListedLabel = new St.Label({ text: _("Not listed?"),
 | 
			
		||||
                                            style_class: 'login-dialog-not-listed-label' });
 | 
			
		||||
        this._notListedButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
 | 
			
		||||
                                                button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                                can_focus: true,
 | 
			
		||||
                                                child: notListedLabel,
 | 
			
		||||
                                                reactive: true,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										141
									
								
								js/misc/hash.js
									
									
									
									
									
								
							
							
						
						
									
										141
									
								
								js/misc/hash.js
									
									
									
									
									
								
							@@ -1,141 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const System = imports.system;
 | 
			
		||||
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
 | 
			
		||||
// This is an implementation of EcmaScript SameValue algorithm,
 | 
			
		||||
// which returns true if two values are not observably distinguishable.
 | 
			
		||||
// It was taken from http://wiki.ecmascript.org/doku.php?id=harmony:egal
 | 
			
		||||
//
 | 
			
		||||
// In the future, we may want to use the 'is' operator instead.
 | 
			
		||||
function _sameValue(x, y) {
 | 
			
		||||
    if (x === y) {
 | 
			
		||||
        // 0 === -0, but they are not identical
 | 
			
		||||
        return x !== 0 || 1 / x === 1 / y;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // NaN !== NaN, but they are identical.
 | 
			
		||||
    // NaNs are the only non-reflexive value, i.e., if x !== x,
 | 
			
		||||
    // then x is a NaN.
 | 
			
		||||
    // isNaN is broken: it converts its argument to number, so
 | 
			
		||||
    // isNaN("foo") => true
 | 
			
		||||
    return x !== x && y !== y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const _hashers = {
 | 
			
		||||
    object: function(o) { return o ? System.addressOf(o) : 'null'; },
 | 
			
		||||
    function: function(f) { return System.addressOf(f); },
 | 
			
		||||
    string: function(s) { return s; },
 | 
			
		||||
    number: function(n) { return String(n); },
 | 
			
		||||
    undefined: function() { return 'undefined'; },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Map is meant to be similar in usage to ES6 Map, which is
 | 
			
		||||
   described at http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets,
 | 
			
		||||
   without requiring more than ES5 + Gjs extensions.
 | 
			
		||||
 | 
			
		||||
   Known differences from other implementations:
 | 
			
		||||
   Polyfills around the web usually implement HashMaps for
 | 
			
		||||
   primitive values and reversed WeakMaps for object keys,
 | 
			
		||||
   but we want real maps with real O(1) semantics in all cases,
 | 
			
		||||
   and the easiest way is to have different hashers for different
 | 
			
		||||
   types.
 | 
			
		||||
 | 
			
		||||
   Known differences from the ES6 specification:
 | 
			
		||||
   - Map is a Lang.Class, not a ES6 class, so inheritance,
 | 
			
		||||
     prototype, sealing, etc. work differently.
 | 
			
		||||
   - items(), keys() and values() don't return iterators,
 | 
			
		||||
     they return actual arrays, so they incur a full copy everytime
 | 
			
		||||
     they're called, and they don't see changes if you mutate
 | 
			
		||||
     the table while iterating
 | 
			
		||||
     (admittedly, the ES6 spec is a bit unclear on this, and
 | 
			
		||||
     the reference code would just blow up)
 | 
			
		||||
*/
 | 
			
		||||
const Map = new Lang.Class({
 | 
			
		||||
    Name: 'Map',
 | 
			
		||||
 | 
			
		||||
    _init: function(iterable) {
 | 
			
		||||
        this._pool = { };
 | 
			
		||||
 | 
			
		||||
        if (iterable) {
 | 
			
		||||
            for (let i = 0; i < iterable.length; i++) {
 | 
			
		||||
                let [key, value] = iterable[i];
 | 
			
		||||
                this.set(key, value);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hashKey: function(key) {
 | 
			
		||||
        let type = typeof(key);
 | 
			
		||||
        return type + ':' + _hashers[type](key);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _internalGet: function(key) {
 | 
			
		||||
        let hash = this._hashKey(key);
 | 
			
		||||
        let node = this._pool[hash];
 | 
			
		||||
 | 
			
		||||
        if (node && _sameValue(node.key, key))
 | 
			
		||||
            return [true, node.value];
 | 
			
		||||
        else
 | 
			
		||||
            return [false, null];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get: function(key) {
 | 
			
		||||
        return this._internalGet(key)[1];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    has: function(key) {
 | 
			
		||||
        return this._internalGet(key)[0];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    set: function(key, value) {
 | 
			
		||||
        let hash = this._hashKey(key);
 | 
			
		||||
        let node = this._pool[hash];
 | 
			
		||||
 | 
			
		||||
        if (node) {
 | 
			
		||||
            node.key = key;
 | 
			
		||||
            node.value = value;
 | 
			
		||||
        } else {
 | 
			
		||||
            this._pool[hash] = { key: key, value: value };
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    delete: function(key) {
 | 
			
		||||
        let hash = this._hashKey(key);
 | 
			
		||||
        let node = this._pool[hash];
 | 
			
		||||
 | 
			
		||||
        if (node && _sameValue(node.key, key)) {
 | 
			
		||||
            delete this._pool[hash];
 | 
			
		||||
            return [node.key, node.value];
 | 
			
		||||
        } else {
 | 
			
		||||
            return [null, null];
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    keys: function() {
 | 
			
		||||
        let pool = this._pool;
 | 
			
		||||
        return Object.getOwnPropertyNames(pool).map(function(hash) {
 | 
			
		||||
            return pool[hash].key;
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    values: function() {
 | 
			
		||||
        let pool = this._pool;
 | 
			
		||||
        return Object.getOwnPropertyNames(pool).map(function(hash) {
 | 
			
		||||
            return pool[hash].value;
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    items: function() {
 | 
			
		||||
        let pool = this._pool;
 | 
			
		||||
        return Object.getOwnPropertyNames(pool).map(function(hash) {
 | 
			
		||||
            return [pool[hash].key, pool[hash].value];
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    size: function() {
 | 
			
		||||
        return Object.getOwnPropertyNames(this._pool).length;
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
@@ -159,6 +159,86 @@ 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
 | 
			
		||||
 
 | 
			
		||||
@@ -153,7 +153,6 @@ const ViewByCategories = new Lang.Class({
 | 
			
		||||
                                                   y_fill: false,
 | 
			
		||||
                                                   style_class: 'vfade' });
 | 
			
		||||
        this._categoryScroll.add_actor(this._categoryBox);
 | 
			
		||||
        this._categoryScroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
 | 
			
		||||
        this.actor.add(this._view.actor, { expand: true, x_fill: true, y_fill: true });
 | 
			
		||||
        this.actor.add(this._categoryScroll, { expand: false, y_fill: false, y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -220,8 +220,25 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
        this.bin.allocate(childBox, flags);
 | 
			
		||||
 | 
			
		||||
        if (this._sourceActor && this._sourceActor.mapped) {
 | 
			
		||||
            this._reposition();
 | 
			
		||||
            this._updateFlip();
 | 
			
		||||
            this._reposition(this._sourceActor, this._arrowAlignment);
 | 
			
		||||
 | 
			
		||||
            if (this._shouldFlip()) {
 | 
			
		||||
                switch (this._arrowSide) {
 | 
			
		||||
                case St.Side.TOP:
 | 
			
		||||
                    this._arrowSide = St.Side.BOTTOM;
 | 
			
		||||
                    break;
 | 
			
		||||
                case St.Side.BOTTOM:
 | 
			
		||||
                    this._arrowSide = St.Side.TOP;
 | 
			
		||||
                    break;
 | 
			
		||||
                case St.Side.LEFT:
 | 
			
		||||
                    this._arrowSide = St.Side.RIGHT;
 | 
			
		||||
                    break;
 | 
			
		||||
                case St.Side.RIGHT:
 | 
			
		||||
                    this._arrowSide = St.Side.LEFT;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                this._reposition(this._sourceActor, this._arrowAlignment);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -388,11 +405,11 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
            cr.setLineWidth(borderWidth);
 | 
			
		||||
            cr.stroke();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        cr.$dispose();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setPosition: function(sourceActor, alignment) {
 | 
			
		||||
        this._arrowSide = this._userArrowSide;
 | 
			
		||||
 | 
			
		||||
        // We need to show it now to force an allocation,
 | 
			
		||||
        // so that we can query the correct size.
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
@@ -400,8 +417,7 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
        this._sourceActor = sourceActor;
 | 
			
		||||
        this._arrowAlignment = alignment;
 | 
			
		||||
 | 
			
		||||
        this._reposition();
 | 
			
		||||
        this._updateFlip();
 | 
			
		||||
        this._reposition(sourceActor, alignment);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setSourceAlignment: function(alignment) {
 | 
			
		||||
@@ -413,10 +429,7 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
        this.setPosition(this._sourceActor, this._arrowAlignment);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _reposition: function() {
 | 
			
		||||
        let sourceActor = this._sourceActor;
 | 
			
		||||
        let alignment = this._arrowAlignment;
 | 
			
		||||
 | 
			
		||||
    _reposition: function(sourceActor, alignment) {
 | 
			
		||||
        // Position correctly relative to the sourceActor
 | 
			
		||||
        let sourceNode = sourceActor.get_theme_node();
 | 
			
		||||
        let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box());
 | 
			
		||||
@@ -540,7 +553,7 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
    _shiftActor : function() {
 | 
			
		||||
        // Since the position of the BoxPointer depends on the allocated size
 | 
			
		||||
        // of the BoxPointer and the position of the source actor, trying
 | 
			
		||||
        // to position the BoxPointer via the x/y properties will result in
 | 
			
		||||
        // to position the BoxPoiner via the x/y properties will result in
 | 
			
		||||
        // allocation loops and warnings. Instead we do the positioning via
 | 
			
		||||
        // the anchor point, which is independent of allocation, and leave
 | 
			
		||||
        // x == y == 0.
 | 
			
		||||
@@ -548,47 +561,37 @@ const BoxPointer = new Lang.Class({
 | 
			
		||||
                                    -(this._yPosition + this._yOffset));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _calculateArrowSide: function(arrowSide) {
 | 
			
		||||
    _shouldFlip: function() {
 | 
			
		||||
        let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
 | 
			
		||||
        let [minWidth, minHeight, boxWidth, boxHeight] = this._container.get_preferred_size();
 | 
			
		||||
        let boxAllocation = Shell.util_get_transformed_allocation(this.actor);
 | 
			
		||||
        let boxWidth = boxAllocation.x2 - boxAllocation.x1;
 | 
			
		||||
        let boxHeight = boxAllocation.y2 - boxAllocation.y1;
 | 
			
		||||
        let monitor = Main.layoutManager.findMonitorForActor(this.actor);
 | 
			
		||||
 | 
			
		||||
        switch (arrowSide) {
 | 
			
		||||
        switch (this._arrowSide) {
 | 
			
		||||
        case St.Side.TOP:
 | 
			
		||||
            if (sourceAllocation.y2 + boxHeight > monitor.y + monitor.height &&
 | 
			
		||||
            if (boxAllocation.y2 > monitor.y + monitor.height &&
 | 
			
		||||
                boxHeight < sourceAllocation.y1 - monitor.y)
 | 
			
		||||
                return St.Side.BOTTOM;
 | 
			
		||||
                return true;
 | 
			
		||||
            break;
 | 
			
		||||
        case St.Side.BOTTOM:
 | 
			
		||||
            if (sourceAllocation.y1 - boxHeight < monitor.y &&
 | 
			
		||||
            if (boxAllocation.y1 < monitor.y &&
 | 
			
		||||
                boxHeight < monitor.y + monitor.height - sourceAllocation.y2)
 | 
			
		||||
                return St.Side.TOP;
 | 
			
		||||
                return true;
 | 
			
		||||
            break;
 | 
			
		||||
        case St.Side.LEFT:
 | 
			
		||||
            if (sourceAllocation.y2 + boxWidth > monitor.x + monitor.width &&
 | 
			
		||||
            if (boxAllocation.x2 > monitor.x + monitor.width &&
 | 
			
		||||
                boxWidth < sourceAllocation.x1 - monitor.x)
 | 
			
		||||
                return St.Side.RIGHT;
 | 
			
		||||
                return true;
 | 
			
		||||
            break;
 | 
			
		||||
        case St.Side.RIGHT:
 | 
			
		||||
            if (sourceAllocation.y1 - boxWidth < monitor.x &&
 | 
			
		||||
            if (boxAllocation.x1 < monitor.x &&
 | 
			
		||||
                boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
 | 
			
		||||
                return St.Side.LEFT;
 | 
			
		||||
                return true;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return arrowSide;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateFlip: function() {
 | 
			
		||||
        let arrowSide = this._calculateArrowSide(this._userArrowSide);
 | 
			
		||||
        if (this._arrowSide != arrowSide) {
 | 
			
		||||
            this._arrowSide = arrowSide;
 | 
			
		||||
            this._reposition();
 | 
			
		||||
            Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
 | 
			
		||||
                this._container.queue_relayout();
 | 
			
		||||
                return false;
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    set xOffset(offset) {
 | 
			
		||||
 
 | 
			
		||||
@@ -88,9 +88,7 @@ const AutomountManager = new Lang.Class({
 | 
			
		||||
        if (!this._loginManager.sessionActive)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        global.play_theme_sound(0, 'device-added-media',
 | 
			
		||||
                                _("External drive connected"),
 | 
			
		||||
                                null);
 | 
			
		||||
        global.play_theme_sound(0, 'device-added-media');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDriveDisconnected: function() {
 | 
			
		||||
@@ -99,9 +97,7 @@ const AutomountManager = new Lang.Class({
 | 
			
		||||
        if (!this._loginManager.sessionActive)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        global.play_theme_sound(0, 'device-removed-media',
 | 
			
		||||
                                _("External drive disconnected"),
 | 
			
		||||
                                null);
 | 
			
		||||
        global.play_theme_sound(0, 'device-removed-media');        
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onDriveEjectButton: function(monitor, drive) {
 | 
			
		||||
 
 | 
			
		||||
@@ -293,6 +293,7 @@ const AutorunResidentSource = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _init: function(manager) {
 | 
			
		||||
        this.parent(_("Removable Devices"), 'media-removable');
 | 
			
		||||
        this.showInLockScreen = false;
 | 
			
		||||
 | 
			
		||||
        this._mounts = [];
 | 
			
		||||
 | 
			
		||||
@@ -300,10 +301,6 @@ const AutorunResidentSource = new Lang.Class({
 | 
			
		||||
        this._notification = new AutorunResidentNotification(this._manager, this);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createPolicy: function() {
 | 
			
		||||
        return new MessageTray.NotificationPolicy({ showInLockScreen: false });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    buildRightClickMenu: function() {
 | 
			
		||||
        return null;
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -60,14 +60,18 @@ const KeyringDialog = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._controlTable = null;
 | 
			
		||||
 | 
			
		||||
        let buttons = [{ label: '',
 | 
			
		||||
                         action: Lang.bind(this, this._onCancelButton),
 | 
			
		||||
                         key:    Clutter.Escape
 | 
			
		||||
                       },
 | 
			
		||||
                       { label: '',
 | 
			
		||||
                         action: Lang.bind(this, this._onContinueButton),
 | 
			
		||||
                         default: true
 | 
			
		||||
                       }]
 | 
			
		||||
 | 
			
		||||
        this._cancelButton = this.addButton({ label: '',
 | 
			
		||||
                                              action: Lang.bind(this, this._onCancelButton),
 | 
			
		||||
                                              key: Clutter.Escape });
 | 
			
		||||
        this._continueButton = this.addButton({ label: '',
 | 
			
		||||
                                                action: Lang.bind(this, this._onContinueButton),
 | 
			
		||||
                                                default: true },
 | 
			
		||||
                                              { expand: true, x_fill: false, x_align: St.Align.END });
 | 
			
		||||
        this.setButtons(buttons);
 | 
			
		||||
        this._cancelButton = buttons[0].button;
 | 
			
		||||
        this._continueButton = buttons[1].button;
 | 
			
		||||
 | 
			
		||||
        this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
@@ -142,14 +146,6 @@ const KeyringDialog = new Lang.Class({
 | 
			
		||||
        this._messageBox.add(table, { x_fill: true, y_fill: true });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateSensitivity: function(sensitive) {
 | 
			
		||||
        this._passwordEntry.reactive = sensitive;
 | 
			
		||||
        this._passwordEntry.clutter_text.editable = sensitive;
 | 
			
		||||
 | 
			
		||||
        this._continueButton.can_focus = sensitive;
 | 
			
		||||
        this._continueButton.reactive = sensitive;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _ensureOpen: function() {
 | 
			
		||||
        // NOTE: ModalDialog.open() is safe to call if the dialog is
 | 
			
		||||
        // already open - it just returns true without side-effects
 | 
			
		||||
@@ -171,14 +167,12 @@ const KeyringDialog = new Lang.Class({
 | 
			
		||||
    _onShowPassword: function(prompt) {
 | 
			
		||||
        this._buildControlTable();
 | 
			
		||||
        this._ensureOpen();
 | 
			
		||||
        this._updateSensitivity(true);
 | 
			
		||||
        this._passwordEntry.grab_key_focus();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onShowConfirm: function(prompt) {
 | 
			
		||||
        this._buildControlTable();
 | 
			
		||||
        this._ensureOpen();
 | 
			
		||||
        this._updateSensitivity(true);
 | 
			
		||||
        this._continueButton.grab_key_focus();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -198,7 +192,6 @@ const KeyringDialog = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onContinueButton: function() {
 | 
			
		||||
        this._updateSensitivity(false);
 | 
			
		||||
        this.prompt.complete();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -159,13 +159,14 @@ const AuthenticationDialog = new Lang.Class({
 | 
			
		||||
        messageBox.add(this._nullMessageLabel);
 | 
			
		||||
        this._nullMessageLabel.show();
 | 
			
		||||
 | 
			
		||||
        this._cancelButton = this.addButton({ label: _("Cancel"),
 | 
			
		||||
                                              action: Lang.bind(this, this.cancel),
 | 
			
		||||
                                              key: Clutter.Escape });
 | 
			
		||||
        this._okButton = this.addButton({ label:  _("Authenticate"),
 | 
			
		||||
                                          action: Lang.bind(this, this._onAuthenticateButtonPressed),
 | 
			
		||||
                                          default: true },
 | 
			
		||||
                                        { expand: true, x_fill: false, x_align: St.Align.END });
 | 
			
		||||
        this.setButtons([{ label: _("Cancel"),
 | 
			
		||||
                           action: Lang.bind(this, this.cancel),
 | 
			
		||||
                           key:    Clutter.Escape
 | 
			
		||||
                         },
 | 
			
		||||
                         { label:  _("Authenticate"),
 | 
			
		||||
                           action: Lang.bind(this, this._onAuthenticateButtonPressed),
 | 
			
		||||
                           default: true
 | 
			
		||||
                         }]);
 | 
			
		||||
 | 
			
		||||
        this._doneEmitted = false;
 | 
			
		||||
 | 
			
		||||
@@ -213,17 +214,8 @@ const AuthenticationDialog = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateSensitivity: function(sensitive) {
 | 
			
		||||
        this._passwordEntry.reactive = sensitive;
 | 
			
		||||
        this._passwordEntry.clutter_text.editable = sensitive;
 | 
			
		||||
 | 
			
		||||
        this._okButton.can_focus = sensitive;
 | 
			
		||||
        this._okButton.reactive = sensitive;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onEntryActivate: function() {
 | 
			
		||||
        let response = this._passwordEntry.get_text();
 | 
			
		||||
        this._updateSensitivity(false);
 | 
			
		||||
        this._session.response(response);
 | 
			
		||||
        // When the user responds, dismiss already shown info and
 | 
			
		||||
        // error texts (if any)
 | 
			
		||||
@@ -277,7 +269,6 @@ const AuthenticationDialog = new Lang.Class({
 | 
			
		||||
        this._passwordBox.show();
 | 
			
		||||
        this._passwordEntry.set_text('');
 | 
			
		||||
        this._passwordEntry.grab_key_focus();
 | 
			
		||||
        this._updateSensitivity(true);
 | 
			
		||||
        this._ensureOpen();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,8 @@ const Recorder = new Lang.Class({
 | 
			
		||||
        Main.wm.addKeybinding('toggle-recording',
 | 
			
		||||
                              this._bindingSettings,
 | 
			
		||||
                              Meta.KeyBindingFlags.NONE,
 | 
			
		||||
                              Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                              Shell.KeyBindingMode.OVERVIEW,
 | 
			
		||||
                              Main.KeybindingMode.NORMAL |
 | 
			
		||||
                              Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                              Lang.bind(this, this._toggleRecorder));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,6 @@ const Tp = imports.gi.TelepathyGLib;
 | 
			
		||||
const History = imports.misc.history;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
const NotificationDaemon = imports.ui.notificationDaemon;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
 | 
			
		||||
@@ -416,8 +415,6 @@ const TelepathyClient = new Lang.Class({
 | 
			
		||||
    _ensureAppSource: function() {
 | 
			
		||||
        if (this._appSource == null) {
 | 
			
		||||
            this._appSource = new MessageTray.Source(_("Chat"), 'empathy');
 | 
			
		||||
            this._appSource.policy = new NotificationDaemon.NotificationApplicationPolicy('empathy');
 | 
			
		||||
 | 
			
		||||
            Main.messageTray.add(this._appSource);
 | 
			
		||||
            this._appSource.connect('destroy', Lang.bind(this, function () {
 | 
			
		||||
                this._appSource = null;
 | 
			
		||||
@@ -487,10 +484,6 @@ const ChatSource = new Lang.Class({
 | 
			
		||||
        return rightClickMenu;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createPolicy: function() {
 | 
			
		||||
        return new NotificationDaemon.NotificationApplicationPolicy('empathy');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateAlias: function() {
 | 
			
		||||
        let oldAlias = this.title;
 | 
			
		||||
        let newAlias = this._contact.get_alias();
 | 
			
		||||
@@ -1055,10 +1048,6 @@ const ApproverSource = new Lang.Class({
 | 
			
		||||
        }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createPolicy: function() {
 | 
			
		||||
        return new NotificationDaemon.NotificationApplicationPolicy('empathy');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        if (this._invalidId != 0) {
 | 
			
		||||
            this._dispatchOp.disconnect(this._invalidId);
 | 
			
		||||
@@ -1357,8 +1346,9 @@ const AccountNotification = new Lang.Class({
 | 
			
		||||
        this.connect('action-invoked', Lang.bind(this, function(self, action) {
 | 
			
		||||
            switch (action) {
 | 
			
		||||
            case 'view':
 | 
			
		||||
                let cmd = 'empathy-accounts --select-account=' +
 | 
			
		||||
                          account.get_path_suffix();
 | 
			
		||||
                let cmd = '/usr/bin/empathy-accounts'
 | 
			
		||||
                        + ' --select-account=%s'
 | 
			
		||||
                        .format(account.get_path_suffix());
 | 
			
		||||
                let app_info = Gio.app_info_create_from_commandline(cmd, null, 0);
 | 
			
		||||
                app_info.launch([], global.create_app_launch_context());
 | 
			
		||||
                break;
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,6 @@ function _onVertSepRepaint (area)
 | 
			
		||||
    cr.setDash([1, 3], 1); // Hard-code for now
 | 
			
		||||
    cr.setLineWidth(stippleWidth);
 | 
			
		||||
    cr.stroke();
 | 
			
		||||
    cr.$dispose();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const DateMenuButton = new Lang.Class({
 | 
			
		||||
@@ -84,26 +83,12 @@ const DateMenuButton = new Lang.Class({
 | 
			
		||||
                               }));
 | 
			
		||||
        vbox.add(this._calendar.actor);
 | 
			
		||||
 | 
			
		||||
        let separator = new PopupMenu.PopupSeparatorMenuItem();
 | 
			
		||||
        separator.setColumnWidths(1);
 | 
			
		||||
        vbox.add(separator.actor, {y_align: St.Align.END, expand: true, y_fill: false});
 | 
			
		||||
 | 
			
		||||
        this._openCalendarItem = new PopupMenu.PopupMenuItem(_("Open Calendar"));
 | 
			
		||||
        this._openCalendarItem.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
 | 
			
		||||
        this._openCalendarItem.actor.can_focus = false;
 | 
			
		||||
        vbox.add(this._openCalendarItem.actor, {y_align: St.Align.END, expand: true, y_fill: false});
 | 
			
		||||
 | 
			
		||||
        this._openClocksItem = new PopupMenu.PopupMenuItem(_("Open Clocks"));
 | 
			
		||||
        this._openClocksItem.connect('activate', Lang.bind(this, this._onOpenClocksActivate));
 | 
			
		||||
        this._openClocksItem.actor.can_focus = false;
 | 
			
		||||
        vbox.add(this._openClocksItem.actor, {y_align: St.Align.END, expand: true, y_fill: false});
 | 
			
		||||
 | 
			
		||||
        Shell.AppSystem.get_default().connect('installed-changed',
 | 
			
		||||
                                              Lang.bind(this, this._appInstalledChanged));
 | 
			
		||||
        this._appInstalledChanged();
 | 
			
		||||
 | 
			
		||||
        item = this.menu.addSettingsAction(_("Date and Time Settings"), 'gnome-datetime-panel.desktop');
 | 
			
		||||
        if (item) {
 | 
			
		||||
            let separator = new PopupMenu.PopupSeparatorMenuItem();
 | 
			
		||||
            separator.setColumnWidths(1);
 | 
			
		||||
            vbox.add(separator.actor, {y_align: St.Align.END, expand: true, y_fill: false});
 | 
			
		||||
 | 
			
		||||
            item.actor.show_on_set_parent = false;
 | 
			
		||||
            item.actor.can_focus = false;
 | 
			
		||||
            item.actor.reparent(vbox);
 | 
			
		||||
@@ -123,6 +108,16 @@ const DateMenuButton = new Lang.Class({
 | 
			
		||||
        // Event list
 | 
			
		||||
        vbox.add(this._eventList.actor, { expand: true });
 | 
			
		||||
 | 
			
		||||
        this._openCalendarItem = new PopupMenu.PopupMenuItem(_("Open Calendar"));
 | 
			
		||||
        this._openCalendarItem.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
 | 
			
		||||
        this._openCalendarItem.actor.can_focus = false;
 | 
			
		||||
        vbox.add(this._openCalendarItem.actor, {y_align: St.Align.END, expand: true, y_fill: false});
 | 
			
		||||
 | 
			
		||||
        this._calendarSettings = new Gio.Settings({ schema: 'org.gnome.desktop.default-applications.office.calendar' });
 | 
			
		||||
        this._calendarSettings.connect('changed::exec',
 | 
			
		||||
                                       Lang.bind(this, this._calendarSettingsChanged));
 | 
			
		||||
        this._calendarSettingsChanged();
 | 
			
		||||
 | 
			
		||||
        // Whenever the menu is opened, select today
 | 
			
		||||
        this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {
 | 
			
		||||
            if (isOpen) {
 | 
			
		||||
@@ -156,9 +151,10 @@ const DateMenuButton = new Lang.Class({
 | 
			
		||||
        this._sessionUpdated();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _appInstalledChanged: function() {
 | 
			
		||||
        let app = Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop');
 | 
			
		||||
        this._openClocksItem.actor.visible = app !== null;
 | 
			
		||||
    _calendarSettingsChanged: function() {
 | 
			
		||||
        let exec = this._calendarSettings.get_string('exec');
 | 
			
		||||
        let fullExec = GLib.find_program_in_path(exec);
 | 
			
		||||
        this._openCalendarItem.actor.visible = fullExec != null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setEventsVisibility: function(visible) {
 | 
			
		||||
@@ -209,14 +205,24 @@ const DateMenuButton = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _onOpenCalendarActivate: function() {
 | 
			
		||||
        this.menu.close();
 | 
			
		||||
 | 
			
		||||
        let app = Gio.AppInfo.get_default_for_type('text/calendar', false);
 | 
			
		||||
        app.launch([], global.create_app_launch_context());
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onOpenClocksActivate: function() {
 | 
			
		||||
        this.menu.close();
 | 
			
		||||
        let app = Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop');
 | 
			
		||||
        app.activate();
 | 
			
		||||
        let tool = this._calendarSettings.get_string('exec');
 | 
			
		||||
        if (tool.length == 0 || tool.substr(0, 9) == 'evolution') {
 | 
			
		||||
            // TODO: pass the selected day
 | 
			
		||||
            let app = Shell.AppSystem.get_default().lookup_app('evolution-calendar.desktop');
 | 
			
		||||
            app.activate();
 | 
			
		||||
        } else {
 | 
			
		||||
            let needTerm = this._calendarSettings.get_boolean('needs-term');
 | 
			
		||||
            if (needTerm) {
 | 
			
		||||
                let terminalSettings = new Gio.Settings({ schema: 'org.gnome.desktop.default-applications.terminal' });
 | 
			
		||||
                let term = terminalSettings.get_string('exec');
 | 
			
		||||
                let arg = terminalSettings.get_string('exec-arg');
 | 
			
		||||
                if (arg != '')
 | 
			
		||||
                    Util.spawn([term, arg, tool]);
 | 
			
		||||
                else
 | 
			
		||||
                    Util.spawn([term, tool]);
 | 
			
		||||
            } else {
 | 
			
		||||
                Util.spawnCommandLine(tool)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										45
									
								
								js/ui/flashspot.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								js/ui/flashspot.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
 | 
			
		||||
const Lightbox = imports.ui.lightbox;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
 | 
			
		||||
const FLASHSPOT_ANIMATION_TIME = 0.25; // seconds
 | 
			
		||||
 | 
			
		||||
const Flashspot = new Lang.Class({
 | 
			
		||||
    Name: 'Flashspot',
 | 
			
		||||
    Extends: Lightbox.Lightbox,
 | 
			
		||||
 | 
			
		||||
    _init: function(area) {
 | 
			
		||||
        this.parent(Main.uiGroup, { inhibitEvents: true,
 | 
			
		||||
                                    width: area.width,
 | 
			
		||||
                                    height: area.height });
 | 
			
		||||
 | 
			
		||||
        this.actor.style_class = 'flashspot';
 | 
			
		||||
        this.actor.set_position(area.x, area.y);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    fire: function() {
 | 
			
		||||
        this.actor.opacity = 0;
 | 
			
		||||
        Tweener.addTween(this.actor,
 | 
			
		||||
                         { opacity: 255,
 | 
			
		||||
                           time: FLASHSPOT_ANIMATION_TIME,
 | 
			
		||||
                           transition: 'linear',
 | 
			
		||||
                           onComplete: Lang.bind(this, this._onFireShowComplete)
 | 
			
		||||
                         });
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onFireShowComplete: function() {
 | 
			
		||||
        Tweener.addTween(this.actor,
 | 
			
		||||
                         { opacity: 0,
 | 
			
		||||
                           time: FLASHSPOT_ANIMATION_TIME,
 | 
			
		||||
                           transition: 'linear',
 | 
			
		||||
                           onComplete: Lang.bind(this, function() {
 | 
			
		||||
                               this.destroy();
 | 
			
		||||
                           })
 | 
			
		||||
                         });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -183,9 +183,6 @@ const GrabHelper = new Lang.Class({
 | 
			
		||||
        else if (hadFocus || params.grabFocus)
 | 
			
		||||
            _navigateActor(newFocus);
 | 
			
		||||
 | 
			
		||||
        if ((params.grabFocus || params.modal) && !this._capturedEventId)
 | 
			
		||||
            this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
 | 
			
		||||
 | 
			
		||||
        this._grabStack.push(params);
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
@@ -195,6 +192,8 @@ const GrabHelper = new Lang.Class({
 | 
			
		||||
        if (firstGrab) {
 | 
			
		||||
            if (!Main.pushModal(this._owner, this._modalParams))
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._modalCount++;
 | 
			
		||||
@@ -206,6 +205,11 @@ const GrabHelper = new Lang.Class({
 | 
			
		||||
        if (this._modalCount > 0)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (this._capturedEventId > 0) {
 | 
			
		||||
            global.stage.disconnect(this._capturedEventId);
 | 
			
		||||
            this._capturedEventId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Main.popModal(this._owner);
 | 
			
		||||
        global.sync_pointer();
 | 
			
		||||
    },
 | 
			
		||||
@@ -304,11 +308,6 @@ const GrabHelper = new Lang.Class({
 | 
			
		||||
                this._releaseFocusGrab();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!this.grabbed && this._capturedEventId > 0) {
 | 
			
		||||
            global.stage.disconnect(this._capturedEventId);
 | 
			
		||||
            this._capturedEventId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (hadFocus) {
 | 
			
		||||
            let poppedGrab = poppedGrabs[0];
 | 
			
		||||
            _navigateActor(poppedGrab.savedFocus);
 | 
			
		||||
@@ -317,13 +316,6 @@ const GrabHelper = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _onCapturedEvent: function(actor, event) {
 | 
			
		||||
        let type = event.type();
 | 
			
		||||
 | 
			
		||||
        if (type == Clutter.EventType.KEY_PRESS &&
 | 
			
		||||
            event.get_key_symbol() == Clutter.KEY_Escape) {
 | 
			
		||||
            this.ungrab({ isUser: true });
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let press = type == Clutter.EventType.BUTTON_PRESS;
 | 
			
		||||
        let release = type == Clutter.EventType.BUTTON_RELEASE;
 | 
			
		||||
        let button = press || release;
 | 
			
		||||
@@ -336,6 +328,12 @@ const GrabHelper = new Lang.Class({
 | 
			
		||||
        if (!button && this._modalCount == 0)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (type == Clutter.EventType.KEY_PRESS &&
 | 
			
		||||
            event.get_key_symbol() == Clutter.KEY_Escape) {
 | 
			
		||||
            this.ungrab({ isUser: true });
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._isWithinGrabbedActor(event.get_source()))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,21 +2,18 @@
 | 
			
		||||
 | 
			
		||||
const Caribou = imports.gi.Caribou;
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const BoxPointer = imports.ui.boxpointer;
 | 
			
		||||
const Layout = imports.ui.layout;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
 | 
			
		||||
const KEYBOARD_REST_TIME = Layout.KEYBOARD_ANIMATION_TIME * 2 * 1000;
 | 
			
		||||
 | 
			
		||||
const KEYBOARD_SCHEMA = 'org.gnome.shell.keyboard';
 | 
			
		||||
const KEYBOARD_TYPE = 'keyboard-type';
 | 
			
		||||
 | 
			
		||||
@@ -59,7 +56,14 @@ const Key = new Lang.Class({
 | 
			
		||||
        if (this._key.name == 'Control_L' || this._key.name == 'Alt_L')
 | 
			
		||||
            this._key.latch = true;
 | 
			
		||||
 | 
			
		||||
        this._key.connect('key-pressed', Lang.bind(this, function ()
 | 
			
		||||
                                                   { this.actor.checked = true }));
 | 
			
		||||
        this._key.connect('key-released', Lang.bind(this, function ()
 | 
			
		||||
                                                    { this.actor.checked = false; }));
 | 
			
		||||
 | 
			
		||||
        if (this._extended_keys.length > 0) {
 | 
			
		||||
            this._grabbed = false;
 | 
			
		||||
            this._eventCaptureId = 0;
 | 
			
		||||
            this._key.connect('notify::show-subkeys', Lang.bind(this, this._onShowSubkeysChanged));
 | 
			
		||||
            this._boxPointer = new BoxPointer.BoxPointer(St.Side.BOTTOM,
 | 
			
		||||
                                                         { x_fill: true,
 | 
			
		||||
@@ -111,23 +115,52 @@ const Key = new Lang.Class({
 | 
			
		||||
        this._boxPointer.bin.add_actor(this._extended_keyboard);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get subkeys() {
 | 
			
		||||
        return this._boxPointer;
 | 
			
		||||
    _onEventCapture: function (actor, event) {
 | 
			
		||||
        let source = event.get_source();
 | 
			
		||||
        let type = event.type();
 | 
			
		||||
 | 
			
		||||
        if ((type == Clutter.EventType.BUTTON_PRESS ||
 | 
			
		||||
             type == Clutter.EventType.BUTTON_RELEASE) &&
 | 
			
		||||
            this._extended_keyboard.contains(source)) {
 | 
			
		||||
            source.extended_key.press();
 | 
			
		||||
            source.extended_key.release();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        if (type == Clutter.EventType.BUTTON_PRESS) {
 | 
			
		||||
            this._boxPointer.actor.hide();
 | 
			
		||||
            this._ungrab();
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _ungrab: function () {
 | 
			
		||||
        global.stage.disconnect(this._eventCaptureId);
 | 
			
		||||
        this._eventCaptureId = 0;
 | 
			
		||||
        this._grabbed = false;
 | 
			
		||||
        Main.popModal(this.actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onShowSubkeysChanged: function () {
 | 
			
		||||
        if (this._key.show_subkeys) {
 | 
			
		||||
            this.actor.fake_release();
 | 
			
		||||
            this._boxPointer.actor.raise_top();
 | 
			
		||||
            this._boxPointer.setPosition(this.actor, 0.5);
 | 
			
		||||
            this.emit('show-subkeys');
 | 
			
		||||
            this.actor.fake_release();
 | 
			
		||||
            this._boxPointer.show(BoxPointer.PopupAnimation.FULL);
 | 
			
		||||
            this.actor.set_hover(false);
 | 
			
		||||
            if (!this._grabbed) {
 | 
			
		||||
                 Main.pushModal(this.actor);
 | 
			
		||||
                 this._eventCaptureId = global.stage.connect('captured-event', Lang.bind(this, this._onEventCapture));
 | 
			
		||||
                 this._grabbed = true;
 | 
			
		||||
            }
 | 
			
		||||
            this._key.release();
 | 
			
		||||
        } else {
 | 
			
		||||
            this.emit('hide-subkeys');
 | 
			
		||||
            if (this._grabbed)
 | 
			
		||||
                this._ungrab();
 | 
			
		||||
            this._boxPointer.hide(BoxPointer.PopupAnimation.FULL);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Key.prototype);
 | 
			
		||||
 | 
			
		||||
const Keyboard = new Lang.Class({
 | 
			
		||||
    // HACK: we can't set Name, because it collides with Name dbus property
 | 
			
		||||
@@ -142,26 +175,16 @@ const Keyboard = new Lang.Class({
 | 
			
		||||
        this._focusInExtendedKeys = false;
 | 
			
		||||
 | 
			
		||||
        this._timestamp = global.display.get_current_time_roundtrip();
 | 
			
		||||
        Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._redraw));
 | 
			
		||||
 | 
			
		||||
        this._keyboardSettings = new Gio.Settings({ schema: KEYBOARD_SCHEMA });
 | 
			
		||||
        this._keyboardSettings.connect('changed', Lang.bind(this, this._settingsChanged));
 | 
			
		||||
        this._a11yApplicationsSettings = new Gio.Settings({ schema: A11Y_APPLICATIONS_SCHEMA });
 | 
			
		||||
        this._a11yApplicationsSettings.connect('changed', Lang.bind(this, this._settingsChanged));
 | 
			
		||||
        this._settingsChanged();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
        this._showIdleId = 0;
 | 
			
		||||
        this._subkeysBoxPointer = null;
 | 
			
		||||
        this._capturedEventId = 0;
 | 
			
		||||
        this._capturedPress = false;
 | 
			
		||||
 | 
			
		||||
        this._keyboardVisible = false;
 | 
			
		||||
        Main.layoutManager.connect('keyboard-visible-changed', Lang.bind(this, function(o, visible) {
 | 
			
		||||
            this._keyboardVisible = visible;
 | 
			
		||||
        }));
 | 
			
		||||
        this._keyboardRequested = false;
 | 
			
		||||
        this._keyboardRestingId = 0;
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._redraw));
 | 
			
		||||
    init: function () {
 | 
			
		||||
        this._redraw();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -250,14 +273,10 @@ const Keyboard = new Lang.Class({
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let time = global.get_current_time();
 | 
			
		||||
        if (!(focus instanceof Clutter.Text)) {
 | 
			
		||||
        if (focus instanceof Clutter.Text)
 | 
			
		||||
            this.Show(time);
 | 
			
		||||
        else
 | 
			
		||||
            this.Hide(time);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!this._showIdleId)
 | 
			
		||||
            this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE,
 | 
			
		||||
                                             Lang.bind(this, function() { this.Show(time); }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addKeys: function () {
 | 
			
		||||
@@ -312,19 +331,6 @@ const Keyboard = new Lang.Class({
 | 
			
		||||
        return trayButton;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onCapturedEvent: function(actor, event) {
 | 
			
		||||
        let type = event.type();
 | 
			
		||||
        let press = type == Clutter.EventType.BUTTON_PRESS;
 | 
			
		||||
        let release = type == Clutter.EventType.BUTTON_RELEASE;
 | 
			
		||||
 | 
			
		||||
        if (press)
 | 
			
		||||
            this._capturedPress = true;
 | 
			
		||||
        else if (release && this._capturedPress)
 | 
			
		||||
            this._hideSubkeys();
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addRows : function (keys, layout) {
 | 
			
		||||
        let keyboard_row = new St.BoxLayout();
 | 
			
		||||
        for (let i = 0; i < keys.length; ++i) {
 | 
			
		||||
@@ -347,19 +353,6 @@ const Keyboard = new Lang.Class({
 | 
			
		||||
                    // Add new key for hiding message tray
 | 
			
		||||
                    right_box.add(this._getTrayIcon());
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                button.connect('show-subkeys', Lang.bind(this, function() {
 | 
			
		||||
                    if (this._subkeysBoxPointer)
 | 
			
		||||
                        this._subkeysBoxPointer.hide(BoxPointer.PopupAnimation.FULL);
 | 
			
		||||
                    this._subkeysBoxPointer = button.subkeys;
 | 
			
		||||
                    this._subkeysBoxPointer.show(BoxPointer.PopupAnimation.FULL);
 | 
			
		||||
                    if (!this._capturedEventId)
 | 
			
		||||
                        this._capturedEventId = this.actor.connect('captured-event',
 | 
			
		||||
                                                                   Lang.bind(this, this._onCapturedEvent));
 | 
			
		||||
                }));
 | 
			
		||||
                button.connect('hide-subkeys', Lang.bind(this, function() {
 | 
			
		||||
                    this._hideSubkeys();
 | 
			
		||||
                }));
 | 
			
		||||
            }
 | 
			
		||||
            keyboard_row.add(left_box, { expand: true, x_fill: false, x_align: St.Align.START });
 | 
			
		||||
            keyboard_row.add(right_box, { expand: true, x_fill: false, x_align: St.Align.END });
 | 
			
		||||
@@ -469,37 +462,7 @@ const Keyboard = new Lang.Class({
 | 
			
		||||
               actor._extended_keys || actor.extended_key;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _clearKeyboardRestTimer: function() {
 | 
			
		||||
        if (!this._keyboardRestingId)
 | 
			
		||||
            return;
 | 
			
		||||
        GLib.source_remove(this._keyboardRestingId);
 | 
			
		||||
        this._keyboardRestingId = 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show: function (monitor) {
 | 
			
		||||
        this._keyboardRequested = true;
 | 
			
		||||
 | 
			
		||||
        if (this._keyboardVisible) {
 | 
			
		||||
            if (monitor != Main.layoutManager.keyboardIndex) {
 | 
			
		||||
                Main.layoutManager.keyboardIndex = monitor;
 | 
			
		||||
                this._redraw();
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._clearKeyboardRestTimer();
 | 
			
		||||
        this._keyboardRestingId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
 | 
			
		||||
                                                   KEYBOARD_REST_TIME,
 | 
			
		||||
                                                   Lang.bind(this, function() {
 | 
			
		||||
                                                       this._clearKeyboardRestTimer();
 | 
			
		||||
                                                       this._show(monitor);
 | 
			
		||||
                                                   }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _show: function(monitor) {
 | 
			
		||||
        if (!this._keyboardRequested)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        Main.layoutManager.keyboardIndex = monitor;
 | 
			
		||||
        this._redraw();
 | 
			
		||||
        Main.layoutManager.showKeyboard();
 | 
			
		||||
@@ -507,41 +470,10 @@ const Keyboard = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hide: function () {
 | 
			
		||||
        this._keyboardRequested = false;
 | 
			
		||||
 | 
			
		||||
        if (!this._keyboardVisible)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._clearKeyboardRestTimer();
 | 
			
		||||
        this._keyboardRestingId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
 | 
			
		||||
                                                   KEYBOARD_REST_TIME,
 | 
			
		||||
                                                   Lang.bind(this, function() {
 | 
			
		||||
                                                       this._clearKeyboardRestTimer();
 | 
			
		||||
                                                       this._hide();
 | 
			
		||||
                                                   }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hide: function() {
 | 
			
		||||
        if (this._keyboardRequested)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._hideSubkeys();
 | 
			
		||||
        Main.layoutManager.hideKeyboard();
 | 
			
		||||
        this._createSource();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hideSubkeys: function() {
 | 
			
		||||
        if (this._subkeysBoxPointer) {
 | 
			
		||||
            this._subkeysBoxPointer.hide(BoxPointer.PopupAnimation.FULL);
 | 
			
		||||
            this._subkeysBoxPointer = null;
 | 
			
		||||
        }
 | 
			
		||||
        if (this._capturedEventId) {
 | 
			
		||||
            this.actor.disconnect(this._capturedEventId);
 | 
			
		||||
            this._capturedEventId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        this._capturedPress = false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _moveTemporarily: function () {
 | 
			
		||||
        let currentWindow = global.screen.get_display().focus_window;
 | 
			
		||||
        let rect = currentWindow.get_outer_rect();
 | 
			
		||||
@@ -570,13 +502,6 @@ const Keyboard = new Lang.Class({
 | 
			
		||||
        return one - two;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _clearShowIdle: function() {
 | 
			
		||||
        if (!this._showIdleId)
 | 
			
		||||
            return;
 | 
			
		||||
        GLib.source_remove(this._showIdleId);
 | 
			
		||||
        this._showIdleId = 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // D-Bus methods
 | 
			
		||||
    Show: function(timestamp) {
 | 
			
		||||
        if (!this._enableKeyboard)
 | 
			
		||||
@@ -585,8 +510,6 @@ const Keyboard = new Lang.Class({
 | 
			
		||||
        if (this._compareTimestamp(timestamp, this._timestamp) < 0)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._clearShowIdle();
 | 
			
		||||
 | 
			
		||||
        if (timestamp != Clutter.CURRENT_TIME)
 | 
			
		||||
            this._timestamp = timestamp;
 | 
			
		||||
        this.show(Main.layoutManager.focusIndex);
 | 
			
		||||
@@ -599,8 +522,6 @@ const Keyboard = new Lang.Class({
 | 
			
		||||
        if (this._compareTimestamp(timestamp, this._timestamp) < 0)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._clearShowIdle();
 | 
			
		||||
 | 
			
		||||
        if (timestamp != Clutter.CURRENT_TIME)
 | 
			
		||||
            this._timestamp = timestamp;
 | 
			
		||||
        this.hide();
 | 
			
		||||
@@ -635,7 +556,11 @@ const KeyboardSource = new Lang.Class({
 | 
			
		||||
        this.keepTrayOnSummaryClick = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    handleSummaryClick: function(button) {
 | 
			
		||||
    handleSummaryClick: function() {
 | 
			
		||||
        let event = Clutter.get_current_event();
 | 
			
		||||
        if (event.type() != Clutter.EventType.BUTTON_RELEASE)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        this.open();
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1043
									
								
								js/ui/layout.js
									
									
									
									
									
								
							
							
						
						
									
										1043
									
								
								js/ui/layout.js
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -3,7 +3,6 @@
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
@@ -102,7 +101,6 @@ const Lightbox = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show: function() {
 | 
			
		||||
        Tweener.removeTweens(this.actor);
 | 
			
		||||
        if (this._fadeInTime) {
 | 
			
		||||
            this.shown = false;
 | 
			
		||||
            this.actor.opacity = 0;
 | 
			
		||||
@@ -112,20 +110,17 @@ const Lightbox = new Lang.Class({
 | 
			
		||||
                               transition: 'easeOutQuad',
 | 
			
		||||
                               onComplete: Lang.bind(this, function() {
 | 
			
		||||
                                   this.shown = true;
 | 
			
		||||
                                   this.emit('shown');
 | 
			
		||||
                               })
 | 
			
		||||
                             });
 | 
			
		||||
        } else {
 | 
			
		||||
            this.actor.opacity = 255 * this._fadeFactor;
 | 
			
		||||
            this.shown = true;
 | 
			
		||||
            this.emit('shown');
 | 
			
		||||
        }
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hide: function() {
 | 
			
		||||
        this.shown = false;
 | 
			
		||||
        Tweener.removeTweens(this.actor);
 | 
			
		||||
        if (this._fadeOutTime) {
 | 
			
		||||
            Tweener.addTween(this.actor,
 | 
			
		||||
                             { opacity: 0,
 | 
			
		||||
@@ -202,4 +197,3 @@ const Lightbox = new Lang.Class({
 | 
			
		||||
        this.highlight(null);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Lightbox.prototype);
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,6 @@ var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
 | 
			
		||||
                     * in the shell core code too. */
 | 
			
		||||
                    'const stage = global.stage; ' +
 | 
			
		||||
                    /* Special lookingGlass functions */
 | 
			
		||||
                    'const inspect = Lang.bind(Main.lookingGlass, Main.lookingGlass.inspect); ' +
 | 
			
		||||
                    'const it = Main.lookingGlass.getIt(); ' +
 | 
			
		||||
                    'const r = Lang.bind(Main.lookingGlass, Main.lookingGlass.getResult); ';
 | 
			
		||||
 | 
			
		||||
@@ -872,7 +871,8 @@ const LookingGlass = new Lang.Class({
 | 
			
		||||
        inspectIcon.connect('button-press-event', Lang.bind(this, function () {
 | 
			
		||||
            let inspector = new Inspector(this);
 | 
			
		||||
            inspector.connect('target', Lang.bind(this, function(i, target, stageX, stageY) {
 | 
			
		||||
                this._pushResult('inspect(' + Math.round(stageX) + ', ' + Math.round(stageY) + ')', target);
 | 
			
		||||
                this._pushResult('<inspect x:' + stageX + ' y:' + stageY + '>',
 | 
			
		||||
                                 target);
 | 
			
		||||
            }));
 | 
			
		||||
            inspector.connect('closed', Lang.bind(this, function() {
 | 
			
		||||
                this.actor.show();
 | 
			
		||||
@@ -1057,10 +1057,6 @@ const LookingGlass = new Lang.Class({
 | 
			
		||||
        this._entry.text = '';
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    inspect: function(x, y) {
 | 
			
		||||
        return global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getIt: function () {
 | 
			
		||||
        return this._it;
 | 
			
		||||
    },
 | 
			
		||||
@@ -1133,7 +1129,7 @@ const LookingGlass = new Lang.Class({
 | 
			
		||||
        if (this._open)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (!Main.pushModal(this._entry, { keybindingMode: Shell.KeyBindingMode.LOOKING_GLASS }))
 | 
			
		||||
        if (!Main.pushModal(this._entry, { keybindingMode: Main.KeybindingMode.LOOKING_GLASS }))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._notebook.selectIndex(0);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										127
									
								
								js/ui/main.js
									
									
									
									
									
								
							
							
						
						
									
										127
									
								
								js/ui/main.js
									
									
									
									
									
								
							@@ -38,6 +38,20 @@ const XdndHandler = imports.ui.xdndHandler;
 | 
			
		||||
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,
 | 
			
		||||
    ALL:           ~0,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
let componentManager = null;
 | 
			
		||||
let panel = null;
 | 
			
		||||
@@ -55,30 +69,31 @@ let shellDBusService = null;
 | 
			
		||||
let shellMountOpDBusService = null;
 | 
			
		||||
let screenSaverDBus = null;
 | 
			
		||||
let modalCount = 0;
 | 
			
		||||
let keybindingMode = Shell.KeyBindingMode.NORMAL;
 | 
			
		||||
let keybindingMode = KeybindingMode.NORMAL;
 | 
			
		||||
let modalActorFocusStack = [];
 | 
			
		||||
let uiGroup = null;
 | 
			
		||||
let magnifier = null;
 | 
			
		||||
let xdndHandler = null;
 | 
			
		||||
let keyboard = null;
 | 
			
		||||
let layoutManager = null;
 | 
			
		||||
let background = null;
 | 
			
		||||
let _startDate;
 | 
			
		||||
let _defaultCssStylesheet = null;
 | 
			
		||||
let _cssStylesheet = null;
 | 
			
		||||
let _overridesSettings = null;
 | 
			
		||||
 | 
			
		||||
let background = null;
 | 
			
		||||
 | 
			
		||||
function _sessionUpdated() {
 | 
			
		||||
    wm.setCustomKeybindingHandler('panel-main-menu',
 | 
			
		||||
                                  Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                                  Shell.KeyBindingMode.OVERVIEW,
 | 
			
		||||
                                  KeybindingMode.NORMAL |
 | 
			
		||||
                                  KeybindingMode.OVERVIEW,
 | 
			
		||||
                                  sessionMode.hasOverview ? Lang.bind(overview, overview.toggle) : null);
 | 
			
		||||
    wm.allowKeybinding('overlay-key', Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                                      Shell.KeyBindingMode.OVERVIEW);
 | 
			
		||||
    wm.allowKeybinding('overlay-key', KeybindingMode.NORMAL |
 | 
			
		||||
                                      KeybindingMode.OVERVIEW);
 | 
			
		||||
 | 
			
		||||
    wm.setCustomKeybindingHandler('panel-run-dialog',
 | 
			
		||||
                                  Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                                  Shell.KeyBindingMode.OVERVIEW,
 | 
			
		||||
                                  KeybindingMode.NORMAL |
 | 
			
		||||
                                  KeybindingMode.OVERVIEW,
 | 
			
		||||
                                  sessionMode.hasRunDialog ? openRunDialog : null);
 | 
			
		||||
    if (sessionMode.isGreeter)
 | 
			
		||||
        screenShield.showDialog();
 | 
			
		||||
@@ -111,17 +126,38 @@ function start() {
 | 
			
		||||
 | 
			
		||||
    tracker.connect('startup-sequence-changed', _queueCheckWorkspaces);
 | 
			
		||||
 | 
			
		||||
    // Setup the stage hierarchy early
 | 
			
		||||
    layoutManager = new Layout.LayoutManager();
 | 
			
		||||
    // For backward compatibility
 | 
			
		||||
    uiGroup = layoutManager.uiGroup;
 | 
			
		||||
 | 
			
		||||
    let backgroundActor = global.window_group.background;
 | 
			
		||||
    background = backgroundActor.settings;
 | 
			
		||||
    // The stage is always covered so Clutter doesn't need to clear it; however
 | 
			
		||||
    // the color is used as the default contents for the Mutter root background
 | 
			
		||||
    // actor so set it anyways.
 | 
			
		||||
    global.stage.color = DEFAULT_BACKGROUND_COLOR;
 | 
			
		||||
    global.stage.no_clear_hint = true;
 | 
			
		||||
 | 
			
		||||
    _defaultCssStylesheet = global.datadir + '/theme/gnome-shell.css';
 | 
			
		||||
    loadTheme();
 | 
			
		||||
 | 
			
		||||
    // Set up stage hierarchy to group all UI actors under one container.
 | 
			
		||||
    uiGroup = new Shell.GenericContainer({ name: 'uiGroup' });
 | 
			
		||||
    uiGroup.connect('allocate',
 | 
			
		||||
                    function (actor, box, flags) {
 | 
			
		||||
                        let children = uiGroup.get_children();
 | 
			
		||||
                        for (let i = 0; i < children.length; i++)
 | 
			
		||||
                            children[i].allocate_preferred_size(flags);
 | 
			
		||||
                    });
 | 
			
		||||
    uiGroup.connect('get-preferred-width',
 | 
			
		||||
                    function(actor, forHeight, alloc) {
 | 
			
		||||
                        let width = global.stage.width;
 | 
			
		||||
                        [alloc.min_size, alloc.natural_size] = [width, width];
 | 
			
		||||
                    });
 | 
			
		||||
    uiGroup.connect('get-preferred-height',
 | 
			
		||||
                    function(actor, forWidth, alloc) {
 | 
			
		||||
                        let height = global.stage.height;
 | 
			
		||||
                        [alloc.min_size, alloc.natural_size] = [height, height];
 | 
			
		||||
                    });
 | 
			
		||||
    global.window_group.reparent(uiGroup);
 | 
			
		||||
    global.overlay_group.reparent(uiGroup);
 | 
			
		||||
    global.stage.add_actor(uiGroup);
 | 
			
		||||
 | 
			
		||||
    layoutManager = new Layout.LayoutManager();
 | 
			
		||||
    xdndHandler = new XdndHandler.XdndHandler();
 | 
			
		||||
    ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
 | 
			
		||||
    overview = new Overview.Overview();
 | 
			
		||||
@@ -139,6 +175,7 @@ function start() {
 | 
			
		||||
    componentManager = new Components.ComponentManager();
 | 
			
		||||
 | 
			
		||||
    layoutManager.init();
 | 
			
		||||
    keyboard.init();
 | 
			
		||||
    overview.init();
 | 
			
		||||
 | 
			
		||||
    global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
 | 
			
		||||
@@ -175,14 +212,6 @@ function start() {
 | 
			
		||||
 | 
			
		||||
    ExtensionDownloader.init();
 | 
			
		||||
    ExtensionSystem.init();
 | 
			
		||||
 | 
			
		||||
    // Run the startup animation as soon as the mainloop is idle enough
 | 
			
		||||
    // This is necessary to have it smooth and without interruptions from
 | 
			
		||||
    // completed IO tasks
 | 
			
		||||
    GLib.idle_add(GLib.PRIORITY_LOW, function() {
 | 
			
		||||
        layoutManager.startupAnimation();
 | 
			
		||||
        return false;
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let _workspaces = [];
 | 
			
		||||
@@ -491,7 +520,7 @@ function isInModalStack(actor) {
 | 
			
		||||
 *  - options: Meta.ModalOptions flags to indicate that the pointer is
 | 
			
		||||
 *             already grabbed
 | 
			
		||||
 *
 | 
			
		||||
 *  - keybindingMode: used to set the current Shell.KeyBindingMode to filter
 | 
			
		||||
 *  - keybindingMode: used to set the current Main.KeybindingMode to filter
 | 
			
		||||
 *                    global keybindings; the default of NONE will filter
 | 
			
		||||
 *                    out all keybindings
 | 
			
		||||
 *
 | 
			
		||||
@@ -500,7 +529,7 @@ function isInModalStack(actor) {
 | 
			
		||||
function pushModal(actor, params) {
 | 
			
		||||
    params = Params.parse(params, { timestamp: global.get_current_time(),
 | 
			
		||||
                                    options: 0,
 | 
			
		||||
                                    keybindingMode: Shell.KeyBindingMode.NONE });
 | 
			
		||||
                                    keybindingMode: KeybindingMode.NONE });
 | 
			
		||||
 | 
			
		||||
    if (modalCount == 0) {
 | 
			
		||||
        if (!global.begin_modal(params.timestamp, params.options)) {
 | 
			
		||||
@@ -518,20 +547,19 @@ function pushModal(actor, params) {
 | 
			
		||||
        if (index >= 0)
 | 
			
		||||
            popModal(actor);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    let prevFocus = global.stage.get_key_focus();
 | 
			
		||||
    let prevFocusDestroyId;
 | 
			
		||||
    if (prevFocus != null) {
 | 
			
		||||
        prevFocusDestroyId = prevFocus.connect('destroy', function() {
 | 
			
		||||
    let curFocus = global.stage.get_key_focus();
 | 
			
		||||
    let curFocusDestroyId;
 | 
			
		||||
    if (curFocus != null) {
 | 
			
		||||
        curFocusDestroyId = curFocus.connect('destroy', function() {
 | 
			
		||||
            let index = _findModal(actor);
 | 
			
		||||
            if (index >= 0)
 | 
			
		||||
                modalActorFocusStack[index].prevFocus = null;
 | 
			
		||||
                modalActorFocusStack[index].actor = null;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    modalActorFocusStack.push({ actor: actor,
 | 
			
		||||
                                focus: curFocus,
 | 
			
		||||
                                destroyId: actorDestroyId,
 | 
			
		||||
                                prevFocus: prevFocus,
 | 
			
		||||
                                prevFocusDestroyId: prevFocusDestroyId,
 | 
			
		||||
                                focusDestroyId: curFocusDestroyId,
 | 
			
		||||
                                keybindingMode: keybindingMode });
 | 
			
		||||
 | 
			
		||||
    keybindingMode = params.keybindingMode;
 | 
			
		||||
@@ -561,7 +589,7 @@ function popModal(actor, timestamp) {
 | 
			
		||||
        global.stage.set_key_focus(null);
 | 
			
		||||
        global.end_modal(timestamp);
 | 
			
		||||
        global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
 | 
			
		||||
        keybindingMode = Shell.KeyBindingMode.NORMAL;
 | 
			
		||||
        keybindingMode = KeybindingMode.NORMAL;
 | 
			
		||||
 | 
			
		||||
        throw new Error('incorrect pop');
 | 
			
		||||
    }
 | 
			
		||||
@@ -572,33 +600,18 @@ function popModal(actor, timestamp) {
 | 
			
		||||
    record.actor.disconnect(record.destroyId);
 | 
			
		||||
 | 
			
		||||
    if (focusIndex == modalActorFocusStack.length - 1) {
 | 
			
		||||
        if (record.prevFocus)
 | 
			
		||||
            record.prevFocus.disconnect(record.prevFocusDestroyId);
 | 
			
		||||
        if (record.focus)
 | 
			
		||||
            record.focus.disconnect(record.focusDestroyId);
 | 
			
		||||
        keybindingMode = record.keybindingMode;
 | 
			
		||||
        global.stage.set_key_focus(record.prevFocus);
 | 
			
		||||
        global.stage.set_key_focus(record.focus);
 | 
			
		||||
    } else {
 | 
			
		||||
        // If we have:
 | 
			
		||||
        //     global.stage.set_focus(a);
 | 
			
		||||
        //     Main.pushModal(b);
 | 
			
		||||
        //     Main.pushModal(c);
 | 
			
		||||
        //     Main.pushModal(d);
 | 
			
		||||
        //
 | 
			
		||||
        // then we have the stack:
 | 
			
		||||
        //     [{ prevFocus: a, actor: b },
 | 
			
		||||
        //      { prevFocus: b, actor: c },
 | 
			
		||||
        //      { prevFocus: c, actor: d }]
 | 
			
		||||
        //
 | 
			
		||||
        // When actor c is destroyed/popped, if we only simply remove the
 | 
			
		||||
        // record, then the focus stack will be [a, c], rather than the correct
 | 
			
		||||
        // [a, b]. Shift the focus stack up before removing the record to ensure
 | 
			
		||||
        // that we get the correct result.
 | 
			
		||||
        let t = modalActorFocusStack[modalActorFocusStack.length - 1];
 | 
			
		||||
        if (t.prevFocus)
 | 
			
		||||
            t.prevFocus.disconnect(t.prevFocusDestroyId);
 | 
			
		||||
        if (t.focus)
 | 
			
		||||
            t.focus.disconnect(t.focusDestroyId);
 | 
			
		||||
        // Remove from the middle, shift the focus chain up
 | 
			
		||||
        for (let i = modalActorFocusStack.length - 1; i > focusIndex; i--) {
 | 
			
		||||
            modalActorFocusStack[i].prevFocus = modalActorFocusStack[i - 1].prevFocus;
 | 
			
		||||
            modalActorFocusStack[i].prevFocusDestroyId = modalActorFocusStack[i - 1].prevFocusDestroyId;
 | 
			
		||||
            modalActorFocusStack[i].focus = modalActorFocusStack[i - 1].focus;
 | 
			
		||||
            modalActorFocusStack[i].focusDestroyId = modalActorFocusStack[i - 1].focusDestroyId;
 | 
			
		||||
            modalActorFocusStack[i].keybindingMode = modalActorFocusStack[i - 1].keybindingMode;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -610,7 +623,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 = Shell.KeyBindingMode.NORMAL;
 | 
			
		||||
    keybindingMode = KeybindingMode.NORMAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function createLookingGlass() {
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,6 @@ const BoxPointer = imports.ui.boxpointer;
 | 
			
		||||
const CtrlAltTab = imports.ui.ctrlAltTab;
 | 
			
		||||
const GnomeSession = imports.misc.gnomeSession;
 | 
			
		||||
const GrabHelper = imports.ui.grabHelper;
 | 
			
		||||
const Hash = imports.misc.hash;
 | 
			
		||||
const Lightbox = imports.ui.lightbox;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const PointerWatcher = imports.ui.pointerWatcher;
 | 
			
		||||
@@ -244,36 +243,6 @@ function makeCloseButton() {
 | 
			
		||||
    return closeButton;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function strHasSuffix(string, suffix) {
 | 
			
		||||
    return string.substr(-suffix.length) == suffix;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NotificationPolicy:
 | 
			
		||||
// An object that holds all bits of configurable policy related to a notification
 | 
			
		||||
// source, such as whether to play sound or honour the critical bit.
 | 
			
		||||
//
 | 
			
		||||
// A notification without a policy object will inherit the default one.
 | 
			
		||||
const NotificationPolicy = new Lang.Class({
 | 
			
		||||
    Name: 'NotificationPolicy',
 | 
			
		||||
 | 
			
		||||
    _init: function(params) {
 | 
			
		||||
        params = Params.parse(params, { enable: true,
 | 
			
		||||
                                        enableSound: true,
 | 
			
		||||
                                        showBanners: true,
 | 
			
		||||
                                        forceExpanded: false,
 | 
			
		||||
                                        showInLockScreen: true,
 | 
			
		||||
                                        detailsInLockScreen: false
 | 
			
		||||
                                      });
 | 
			
		||||
        Lang.copyProperties(params, this);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Do nothing for the default policy. These methods are only useful for the
 | 
			
		||||
    // GSettings policy.
 | 
			
		||||
    store: function() { },
 | 
			
		||||
    destroy: function() { }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(NotificationPolicy.prototype);
 | 
			
		||||
 | 
			
		||||
// Notification:
 | 
			
		||||
// @source: the notification's Source
 | 
			
		||||
// @title: the title
 | 
			
		||||
@@ -345,7 +314,6 @@ 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.isMusic = false;
 | 
			
		||||
        this.forFeedback = false;
 | 
			
		||||
        this.expanded = false;
 | 
			
		||||
        this.focused = false;
 | 
			
		||||
@@ -353,8 +321,8 @@ const Notification = new Lang.Class({
 | 
			
		||||
        this._destroyed = false;
 | 
			
		||||
        this._useActionIcons = false;
 | 
			
		||||
        this._customContent = false;
 | 
			
		||||
        this.bannerBodyText = null;
 | 
			
		||||
        this.bannerBodyMarkup = false;
 | 
			
		||||
        this._bannerBodyText = null;
 | 
			
		||||
        this._bannerBodyMarkup = false;
 | 
			
		||||
        this._titleFitsInBannerMode = true;
 | 
			
		||||
        this._titleDirection = Clutter.TextDirection.DEFAULT;
 | 
			
		||||
        this._spacing = 0;
 | 
			
		||||
@@ -461,7 +429,7 @@ const Notification = new Lang.Class({
 | 
			
		||||
            this._actionArea = null;
 | 
			
		||||
            this._buttonBox = null;
 | 
			
		||||
        }
 | 
			
		||||
        if (params.clear)
 | 
			
		||||
        if (this._imageBin && params.clear)
 | 
			
		||||
            this.unsetImage();
 | 
			
		||||
 | 
			
		||||
        if (!this._scrollArea && !this._actionArea && !this._imageBin)
 | 
			
		||||
@@ -506,12 +474,12 @@ const Notification = new Lang.Class({
 | 
			
		||||
        // is done correctly automatically.
 | 
			
		||||
        this._table.set_text_direction(this._titleDirection);
 | 
			
		||||
 | 
			
		||||
        // Unless the notification has custom content, we save this.bannerBodyText
 | 
			
		||||
        // Unless the notification has custom content, we save this._bannerBodyText
 | 
			
		||||
        // to add it to the content of the notification if the notification is
 | 
			
		||||
        // expandable due to other elements in its content area or due to the banner
 | 
			
		||||
        // not fitting fully in the single-line mode.
 | 
			
		||||
        this.bannerBodyText = this._customContent ? null : banner;
 | 
			
		||||
        this.bannerBodyMarkup = params.bannerMarkup;
 | 
			
		||||
        this._bannerBodyText = this._customContent ? null : banner;
 | 
			
		||||
        this._bannerBodyMarkup = params.bannerMarkup;
 | 
			
		||||
 | 
			
		||||
        banner = banner ? banner.replace(/\n/g, '  ') : '';
 | 
			
		||||
 | 
			
		||||
@@ -519,7 +487,7 @@ const Notification = new Lang.Class({
 | 
			
		||||
        this._bannerLabel.queue_relayout();
 | 
			
		||||
 | 
			
		||||
        // Add the bannerBody now if we know for sure we'll need it
 | 
			
		||||
        if (this.bannerBodyText && this.bannerBodyText.indexOf('\n') > -1)
 | 
			
		||||
        if (this._bannerBodyText && this._bannerBodyText.indexOf('\n') > -1)
 | 
			
		||||
            this._addBannerBody();
 | 
			
		||||
 | 
			
		||||
        if (params.body)
 | 
			
		||||
@@ -543,8 +511,7 @@ const Notification = new Lang.Class({
 | 
			
		||||
        this._table.add_style_class_name('multi-line-notification');
 | 
			
		||||
        this._scrollArea = new St.ScrollView({ style_class: 'notification-scrollview',
 | 
			
		||||
                                               vscrollbar_policy: this._scrollPolicy,
 | 
			
		||||
                                               hscrollbar_policy: Gtk.PolicyType.NEVER,
 | 
			
		||||
                                               visible: this.expanded });
 | 
			
		||||
                                               hscrollbar_policy: Gtk.PolicyType.NEVER });
 | 
			
		||||
        this._table.add(this._scrollArea, { row: 1,
 | 
			
		||||
                                            col: 2 });
 | 
			
		||||
        this._updateLastColumnSettings();
 | 
			
		||||
@@ -585,10 +552,10 @@ const Notification = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addBannerBody: function() {
 | 
			
		||||
        if (this.bannerBodyText) {
 | 
			
		||||
            let text = this.bannerBodyText;
 | 
			
		||||
            this.bannerBodyText = null;
 | 
			
		||||
            this.addBody(text, this.bannerBodyMarkup);
 | 
			
		||||
        if (this._bannerBodyText) {
 | 
			
		||||
            let text = this._bannerBodyText;
 | 
			
		||||
            this._bannerBodyText = null;
 | 
			
		||||
            this.addBody(text, this._bannerBodyMarkup);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -620,7 +587,6 @@ const Notification = new Lang.Class({
 | 
			
		||||
            this._addBannerBody();
 | 
			
		||||
        }
 | 
			
		||||
        this._actionArea = actor;
 | 
			
		||||
        this._actionArea.visible = this.expanded;
 | 
			
		||||
 | 
			
		||||
        if (!props)
 | 
			
		||||
            props = {};
 | 
			
		||||
@@ -643,15 +609,11 @@ const Notification = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setImage: function(image) {
 | 
			
		||||
        this.unsetImage();
 | 
			
		||||
 | 
			
		||||
        if (!image)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._imageBin = new St.Bin({ opacity: 230,
 | 
			
		||||
                                      child: image,
 | 
			
		||||
                                      visible: this.expanded });
 | 
			
		||||
 | 
			
		||||
        if (this._imageBin)
 | 
			
		||||
            this.unsetImage();
 | 
			
		||||
        this._imageBin = new St.Bin();
 | 
			
		||||
        this._imageBin.child = image;
 | 
			
		||||
        this._imageBin.opacity = 230;
 | 
			
		||||
        this._table.add_style_class_name('multi-line-notification');
 | 
			
		||||
        this._table.add_style_class_name('notification-with-image');
 | 
			
		||||
        this._addBannerBody();
 | 
			
		||||
@@ -701,10 +663,9 @@ const Notification = new Lang.Class({
 | 
			
		||||
        let button = new St.Button({ can_focus: true });
 | 
			
		||||
        button._actionId = id;
 | 
			
		||||
 | 
			
		||||
        let iconName = strHasSuffix(id, '-symbolic') ? id : id + '-symbolic';
 | 
			
		||||
        if (this._useActionIcons && Gtk.IconTheme.get_default().has_icon(iconName)) {
 | 
			
		||||
        if (this._useActionIcons && Gtk.IconTheme.get_default().has_icon(id)) {
 | 
			
		||||
            button.add_style_class_name('notification-icon-button');
 | 
			
		||||
            button.child = new St.Icon({ icon_name: iconName });
 | 
			
		||||
            button.child = new St.Icon({ icon_name: id });
 | 
			
		||||
        } else {
 | 
			
		||||
            button.add_style_class_name('notification-button');
 | 
			
		||||
            button.label = label;
 | 
			
		||||
@@ -880,7 +841,7 @@ const Notification = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _canExpandContent: function() {
 | 
			
		||||
        return this.bannerBodyText ||
 | 
			
		||||
        return this._bannerBodyText ||
 | 
			
		||||
               (!this._titleFitsInBannerMode && !this._table.has_style_class_name('multi-line-notification'));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -893,14 +854,6 @@ const Notification = new Lang.Class({
 | 
			
		||||
        this.expanded = true;
 | 
			
		||||
        this.actor.remove_style_class_name('notification-unexpanded');
 | 
			
		||||
 | 
			
		||||
        // Show additional content that we keep hidden in banner mode
 | 
			
		||||
        if (this._imageBin)
 | 
			
		||||
            this._imageBin.show();
 | 
			
		||||
        if (this._actionArea)
 | 
			
		||||
            this._actionArea.show();
 | 
			
		||||
        if (this._scrollArea)
 | 
			
		||||
            this._scrollArea.show();
 | 
			
		||||
 | 
			
		||||
        // The banner is never shown when the title did not fit, so this
 | 
			
		||||
        // can be an if-else statement.
 | 
			
		||||
        if (!this._titleFitsInBannerMode) {
 | 
			
		||||
@@ -932,23 +885,12 @@ const Notification = new Lang.Class({
 | 
			
		||||
        if (this._destroyed)
 | 
			
		||||
            return;
 | 
			
		||||
        this.expanded = false;
 | 
			
		||||
 | 
			
		||||
        // Hide additional content that we keep hidden in banner mode
 | 
			
		||||
        if (this._imageBin)
 | 
			
		||||
            this._imageBin.hide();
 | 
			
		||||
        if (this._actionArea)
 | 
			
		||||
            this._actionArea.hide();
 | 
			
		||||
        if (this._scrollArea)
 | 
			
		||||
            this._scrollArea.hide();
 | 
			
		||||
 | 
			
		||||
        // Make sure we don't line wrap the title, and ellipsize it instead.
 | 
			
		||||
        this._titleLabel.clutter_text.line_wrap = false;
 | 
			
		||||
        this._titleLabel.clutter_text.ellipsize = Pango.EllipsizeMode.END;
 | 
			
		||||
 | 
			
		||||
        // Restore banner opacity in case the notification is shown in the
 | 
			
		||||
        // banner mode again on update.
 | 
			
		||||
        this._bannerLabel.opacity = 255;
 | 
			
		||||
 | 
			
		||||
        // Restore height requisition
 | 
			
		||||
        this.actor.add_style_class_name('notification-unexpanded');
 | 
			
		||||
        this.emit('collapsed');
 | 
			
		||||
@@ -1116,11 +1058,10 @@ const Source = new Lang.Class({
 | 
			
		||||
        this.isTransient = false;
 | 
			
		||||
        this.isChat = false;
 | 
			
		||||
        this.isMuted = false;
 | 
			
		||||
        this.showInLockScreen = true;
 | 
			
		||||
        this.keepTrayOnSummaryClick = false;
 | 
			
		||||
 | 
			
		||||
        this.notifications = [];
 | 
			
		||||
 | 
			
		||||
        this.policy = this._createPolicy();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get count() {
 | 
			
		||||
@@ -1139,10 +1080,6 @@ const Source = new Lang.Class({
 | 
			
		||||
        this.emit('count-updated');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createPolicy: function() {
 | 
			
		||||
        return new NotificationPolicy();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    buildRightClickMenu: function() {
 | 
			
		||||
        let item;
 | 
			
		||||
        let rightClickMenu = new St.BoxLayout({ name: 'summary-right-click-menu',
 | 
			
		||||
@@ -1232,13 +1169,11 @@ const Source = new Lang.Class({
 | 
			
		||||
    notify: function(notification) {
 | 
			
		||||
        notification.acknowledged = false;
 | 
			
		||||
        this.pushNotification(notification);
 | 
			
		||||
 | 
			
		||||
        if (!this.isMuted && this.policy.showBanners)
 | 
			
		||||
            this.emit('notify', notification);
 | 
			
		||||
        if (!this.isMuted)
 | 
			
		||||
             this.emit('notify', notification);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function(reason) {
 | 
			
		||||
        this.policy.destroy();
 | 
			
		||||
        this.emit('destroy', reason);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -1280,16 +1215,7 @@ const Source = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    hasResidentNotification: function() {
 | 
			
		||||
        return this.notifications.some(function(n) { return n.resident; });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getMusicNotification: function() {
 | 
			
		||||
        for (let i = 0; i < this.notifications.length; i++) {
 | 
			
		||||
            if (this.notifications[i].isMusic)
 | 
			
		||||
                return this.notifications[i];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    },
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(Source.prototype);
 | 
			
		||||
 | 
			
		||||
@@ -1343,14 +1269,6 @@ const SummaryItem = new Lang.Class({
 | 
			
		||||
            global.focus_manager.add_group(this.rightClickMenu);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        // remove the actor from the summary item so it doesn't get destroyed
 | 
			
		||||
        // with us
 | 
			
		||||
        this._sourceBox.remove_actor(this._sourceIcon);
 | 
			
		||||
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyPress: function(actor, event) {
 | 
			
		||||
        if (event.get_key_symbol() == Clutter.KEY_Up) {
 | 
			
		||||
            actor.emit('clicked', 1);
 | 
			
		||||
@@ -1535,7 +1453,7 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
        this.idleMonitor = new GnomeDesktop.IdleMonitor();
 | 
			
		||||
 | 
			
		||||
        this._grabHelper = new GrabHelper.GrabHelper(this.actor,
 | 
			
		||||
                                                     { keybindingMode: Shell.KeyBindingMode.MESSAGE_TRAY });
 | 
			
		||||
                                                     { keybindingMode: Main.KeybindingMode.MESSAGE_TRAY });
 | 
			
		||||
        this._grabHelper.addActor(this._summaryBoxPointer.actor);
 | 
			
		||||
        this._grabHelper.addActor(this.actor);
 | 
			
		||||
        if (Main.panel.statusArea.activities)
 | 
			
		||||
@@ -1595,6 +1513,7 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
            function() {
 | 
			
		||||
                this._overviewVisible = false;
 | 
			
		||||
                this._escapeTray();
 | 
			
		||||
                this.actor.remove_style_pseudo_class('overview');
 | 
			
		||||
                this._updateState();
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
@@ -1603,19 +1522,19 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
        Main.wm.addKeybinding('toggle-message-tray',
 | 
			
		||||
                              new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
 | 
			
		||||
                              Meta.KeyBindingFlags.NONE,
 | 
			
		||||
                              Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                              Shell.KeyBindingMode.MESSAGE_TRAY |
 | 
			
		||||
                              Shell.KeyBindingMode.OVERVIEW,
 | 
			
		||||
                              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,
 | 
			
		||||
                              Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                              Shell.KeyBindingMode.MESSAGE_TRAY |
 | 
			
		||||
                              Shell.KeyBindingMode.OVERVIEW,
 | 
			
		||||
                              Main.KeybindingMode.NORMAL |
 | 
			
		||||
                              Main.KeybindingMode.MESSAGE_TRAY |
 | 
			
		||||
                              Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                              Lang.bind(this, this._expandActiveNotification));
 | 
			
		||||
 | 
			
		||||
        this._sources = new Hash.Map();
 | 
			
		||||
        this._summaryItems = [];
 | 
			
		||||
        this._chatSummaryItemsCount = 0;
 | 
			
		||||
 | 
			
		||||
        let pointerWatcher = PointerWatcher.getPointerWatcher();
 | 
			
		||||
@@ -1625,19 +1544,22 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
        this._trayDwellUserTime = 0;
 | 
			
		||||
 | 
			
		||||
        this._sessionUpdated();
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
        this._updateNoMessagesLabel();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateNoMessagesLabel: function() {
 | 
			
		||||
        this._noMessages.visible = this._sources.size() == 0;
 | 
			
		||||
        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() {
 | 
			
		||||
@@ -1706,7 +1628,10 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onNotificationKeyRelease: function(actor, event) {
 | 
			
		||||
        if (event.get_key_symbol() == Clutter.KEY_Escape && event.get_state() == 0) {
 | 
			
		||||
        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;
 | 
			
		||||
        }
 | 
			
		||||
@@ -1724,7 +1649,15 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    contains: function(source) {
 | 
			
		||||
        return this._sources.has(source);
 | 
			
		||||
        return this._getIndexOfSummaryItemForSource(source) >= 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getIndexOfSummaryItemForSource: function(source) {
 | 
			
		||||
        for (let i = 0; i < this._summaryItems.length; i++) {
 | 
			
		||||
            if (this._summaryItems[i].source == source)
 | 
			
		||||
                return i;
 | 
			
		||||
        }
 | 
			
		||||
        return -1;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    add: function(source) {
 | 
			
		||||
@@ -1733,23 +1666,7 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Register that we got a notification for this source
 | 
			
		||||
        source.policy.store();
 | 
			
		||||
 | 
			
		||||
        source.policy.connect('enable-changed', Lang.bind(this, this._onSourceEnableChanged, source));
 | 
			
		||||
        source.policy.connect('policy-changed', Lang.bind(this, this._updateState));
 | 
			
		||||
        this._onSourceEnableChanged(source.policy, source);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addSource: function(source) {
 | 
			
		||||
        let obj = {
 | 
			
		||||
            source: source,
 | 
			
		||||
            summaryItem: new SummaryItem(source),
 | 
			
		||||
            notifyId: 0,
 | 
			
		||||
            destroyId: 0,
 | 
			
		||||
            mutedChangedId: 0
 | 
			
		||||
        };
 | 
			
		||||
        let summaryItem = obj.summaryItem;
 | 
			
		||||
        let summaryItem = new SummaryItem(source);
 | 
			
		||||
 | 
			
		||||
        if (source.isChat) {
 | 
			
		||||
            this._summary.insert_child_at_index(summaryItem.actor, 0);
 | 
			
		||||
@@ -1758,11 +1675,11 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
            this._summary.insert_child_at_index(summaryItem.actor, this._chatSummaryItemsCount);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._sources.set(source, obj);
 | 
			
		||||
        this._summaryItems.push(summaryItem);
 | 
			
		||||
 | 
			
		||||
        obj.notifyId = source.connect('notify', Lang.bind(this, this._onNotify));
 | 
			
		||||
        obj.destroyId = source.connect('destroy', Lang.bind(this, this._onSourceDestroy));
 | 
			
		||||
        obj.mutedChangedId = source.connect('muted-changed', Lang.bind(this,
 | 
			
		||||
        source.connect('notify', Lang.bind(this, this._onNotify));
 | 
			
		||||
 | 
			
		||||
        source.connect('muted-changed', Lang.bind(this,
 | 
			
		||||
            function () {
 | 
			
		||||
                if (source.isMuted)
 | 
			
		||||
                    this._notificationQueue = this._notificationQueue.filter(function(notification) {
 | 
			
		||||
@@ -1781,28 +1698,35 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
                this._onSummaryItemClicked(summaryItem, 3);
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
        source.connect('destroy', Lang.bind(this, this._onSourceDestroy));
 | 
			
		||||
 | 
			
		||||
        // We need to display the newly-added summary item, but if the
 | 
			
		||||
        // caller is about to post a notification, we want to show that
 | 
			
		||||
        // *first* and not show the summary item until after it hides.
 | 
			
		||||
        // So postpone calling _updateState() a tiny bit.
 | 
			
		||||
        Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { this._updateState(); return false; }));
 | 
			
		||||
 | 
			
		||||
        this.emit('source-added', source);
 | 
			
		||||
        this.emit('summary-item-added', summaryItem);
 | 
			
		||||
 | 
			
		||||
        this._updateNoMessagesLabel();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _removeSource: function(source) {
 | 
			
		||||
        let [, obj] = this._sources.delete(source);
 | 
			
		||||
        let summaryItem = obj.summaryItem;
 | 
			
		||||
    getSummaryItems: function() {
 | 
			
		||||
        return this._summaryItems;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onSourceDestroy: function(source) {
 | 
			
		||||
        let index = this._getIndexOfSummaryItemForSource(source);
 | 
			
		||||
        if (index == -1)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let summaryItemToRemove = this._summaryItems[index];
 | 
			
		||||
 | 
			
		||||
        this._summaryItems.splice(index, 1);
 | 
			
		||||
 | 
			
		||||
        if (source.isChat)
 | 
			
		||||
            this._chatSummaryItemsCount--;
 | 
			
		||||
 | 
			
		||||
        source.disconnect(obj.notifyId);
 | 
			
		||||
        source.disconnect(obj.destroyId);
 | 
			
		||||
        source.disconnect(obj.mutedChangedId);
 | 
			
		||||
 | 
			
		||||
        let needUpdate = false;
 | 
			
		||||
 | 
			
		||||
        if (this._notification && this._notification.source == source) {
 | 
			
		||||
@@ -1810,12 +1734,12 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
            this._notificationRemoved = true;
 | 
			
		||||
            needUpdate = true;
 | 
			
		||||
        }
 | 
			
		||||
        if (this._clickedSummaryItem == summaryItem) {
 | 
			
		||||
        if (this._clickedSummaryItem == summaryItemToRemove) {
 | 
			
		||||
            this._setClickedSummaryItem(null);
 | 
			
		||||
            needUpdate = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        summaryItem.destroy();
 | 
			
		||||
        summaryItemToRemove.actor.destroy();
 | 
			
		||||
 | 
			
		||||
        this._updateNoMessagesLabel();
 | 
			
		||||
 | 
			
		||||
@@ -1823,26 +1747,6 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
            this._updateState();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getSources: function() {
 | 
			
		||||
        return this._sources.keys();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onSourceEnableChanged: function(policy, source) {
 | 
			
		||||
        let wasEnabled = this.contains(source);
 | 
			
		||||
        let shouldBeEnabled = policy.enable;
 | 
			
		||||
 | 
			
		||||
        if (wasEnabled != shouldBeEnabled) {
 | 
			
		||||
            if (shouldBeEnabled)
 | 
			
		||||
                this._addSource(source);
 | 
			
		||||
            else
 | 
			
		||||
                this._removeSource(source);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onSourceDestroy: function(source) {
 | 
			
		||||
        this._removeSource(source);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onNotificationDestroy: function(notification) {
 | 
			
		||||
        if (this._notification == notification && (this._notificationState == State.SHOWN || this._notificationState == State.SHOWING)) {
 | 
			
		||||
            this._updateNotificationTimeout(0);
 | 
			
		||||
@@ -1928,7 +1832,7 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onSummaryItemClicked: function(summaryItem, button) {
 | 
			
		||||
        if (summaryItem.source.handleSummaryClick(button)) {
 | 
			
		||||
        if (summaryItem.source.handleSummaryClick()) {
 | 
			
		||||
            if (summaryItem.source.keepTrayOnSummaryClick)
 | 
			
		||||
                this._setClickedSummaryItem(null);
 | 
			
		||||
            else
 | 
			
		||||
@@ -2287,9 +2191,7 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
        this._tween(this.actor, '_trayState', State.HIDDEN,
 | 
			
		||||
                    { y: 0,
 | 
			
		||||
                      time: ANIMATION_TIME,
 | 
			
		||||
                      transition: 'easeOutQuad',
 | 
			
		||||
                      onComplete: this._onTrayHidden,
 | 
			
		||||
                      onCompleteScope: this
 | 
			
		||||
                      transition: 'easeOutQuad'
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
        // Note that we might have entered here without a grab,
 | 
			
		||||
@@ -2299,11 +2201,6 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
        this._lightbox.hide();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onTrayHidden: function() {
 | 
			
		||||
        if (!this._overviewVisible)
 | 
			
		||||
            this.actor.remove_style_pseudo_class('overview');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hideDesktopClone: function(now) {
 | 
			
		||||
        this._tween(this._desktopClone, '_desktopCloneState', State.HIDDEN,
 | 
			
		||||
                    { y: 0,
 | 
			
		||||
@@ -2340,7 +2237,7 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._notificationClickedId = this._notification.connect('done-displaying',
 | 
			
		||||
                                                                 Lang.bind(this, this._escapeTray));
 | 
			
		||||
        this._notificationUnfocusedId = this._notification.connect('unfocused', Lang.bind(this, function() {
 | 
			
		||||
        this._notification.connect('unfocused', Lang.bind(this, function() {
 | 
			
		||||
            this._updateState();
 | 
			
		||||
        }));
 | 
			
		||||
        this._notificationBin.child = this._notification.actor;
 | 
			
		||||
@@ -2369,10 +2266,8 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
    _updateShowingNotification: function() {
 | 
			
		||||
        this._notification.acknowledged = true;
 | 
			
		||||
 | 
			
		||||
        // We auto-expand notifications with CRITICAL urgency, or for which the relevant setting
 | 
			
		||||
        // is on in the control center.
 | 
			
		||||
        if (this._notification.urgency == Urgency.CRITICAL ||
 | 
			
		||||
            this._notification.source.policy.forceExpanded)
 | 
			
		||||
        // We auto-expand notifications with CRITICAL urgency.
 | 
			
		||||
        if (this._notification.urgency == Urgency.CRITICAL)
 | 
			
		||||
            this._expandNotification(true);
 | 
			
		||||
 | 
			
		||||
        // We tween all notifications to full opacity. This ensures that both new notifications and
 | 
			
		||||
@@ -2456,18 +2351,11 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
            this.idleMonitor.disconnect(this._idleMonitorBecameActiveId);
 | 
			
		||||
            this._idleMonitorBecameActiveId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._notificationExpandedId) {
 | 
			
		||||
            this._notification.disconnect(this._notificationExpandedId);
 | 
			
		||||
            this._notificationExpandedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (this._notificationClickedId) {
 | 
			
		||||
            this._notification.disconnect(this._notificationClickedId);
 | 
			
		||||
            this._notificationClickedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (this._notificationUnfocusedId) {
 | 
			
		||||
            this._notification.disconnect(this._notificationUnfocusedId);
 | 
			
		||||
            this._notificationUnfocusedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._notificationRemoved) {
 | 
			
		||||
            Tweener.removeTweens(this._notificationWidget);
 | 
			
		||||
@@ -2489,19 +2377,19 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hideNotificationCompleted: function() {
 | 
			
		||||
        this._notification.collapseCompleted();
 | 
			
		||||
 | 
			
		||||
        let notification = this._notification;
 | 
			
		||||
        this._notification = null;
 | 
			
		||||
        if (notification.isTransient)
 | 
			
		||||
            notification.destroy(NotificationDestroyedReason.EXPIRED);
 | 
			
		||||
 | 
			
		||||
        this._notificationRemoved = false;
 | 
			
		||||
        this._notificationWidget.hide();
 | 
			
		||||
        this._closeButton.hide();
 | 
			
		||||
        this._pointerInTray = false;
 | 
			
		||||
        this.actor.hover = false; // Clutter doesn't emit notify::hover when actors move
 | 
			
		||||
        this._notificationBin.child = null;
 | 
			
		||||
        this._notificationWidget.hide();
 | 
			
		||||
        this._notification.collapseCompleted();
 | 
			
		||||
        this._notification.disconnect(this._notificationClickedId);
 | 
			
		||||
        this._notificationClickedId = 0;
 | 
			
		||||
        let notification = this._notification;
 | 
			
		||||
        this._notification = null;
 | 
			
		||||
        if (notification.isTransient)
 | 
			
		||||
            notification.destroy(NotificationDestroyedReason.EXPIRED);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _expandActiveNotification: function() {
 | 
			
		||||
@@ -2689,20 +2577,6 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _onSummaryBoxPointerUngrabbed: function() {
 | 
			
		||||
        this._summaryBoxPointerState = State.HIDING;
 | 
			
		||||
 | 
			
		||||
        if (this._summaryBoxPointerContentUpdatedId) {
 | 
			
		||||
            this._summaryBoxPointerItem.disconnect(this._summaryBoxPointerContentUpdatedId);
 | 
			
		||||
            this._summaryBoxPointerContentUpdatedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (this._summaryBoxPointerCloseClickedId != 0) {
 | 
			
		||||
            this._summaryBoxPointerItem.closeButton.disconnect(this._summaryBoxPointerCloseClickedId);
 | 
			
		||||
            this._summaryBoxPointerCloseClickedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (this._sourceDoneDisplayingId) {
 | 
			
		||||
            this._summaryBoxPointerItem.source.disconnect(this._sourceDoneDisplayingId);
 | 
			
		||||
            this._sourceDoneDisplayingId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._unlock();
 | 
			
		||||
 | 
			
		||||
        if (this._summaryBoxPointerItem.source.notifications.length == 0) {
 | 
			
		||||
@@ -2725,6 +2599,14 @@ const MessageTray = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._summaryBoxPointerState = State.HIDDEN;
 | 
			
		||||
        this._summaryBoxPointer.bin.child = null;
 | 
			
		||||
        this._summaryBoxPointerItem.disconnect(this._summaryBoxPointerContentUpdatedId);
 | 
			
		||||
        this._summaryBoxPointerContentUpdatedId = 0;
 | 
			
		||||
        if (this._summaryBoxPointerCloseClickedId != 0) {
 | 
			
		||||
            this._summaryBoxPointerItem.closeButton.disconnect(this._summaryBoxPointerCloseClickedId);
 | 
			
		||||
            this._summaryBoxPointerCloseClickedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        this._summaryBoxPointerItem.source.disconnect(this._sourceDoneDisplayingId);
 | 
			
		||||
        this._summaryBoxPointerDoneDisplayingId = 0;
 | 
			
		||||
 | 
			
		||||
        let sourceNotificationStackDoneShowing = null;
 | 
			
		||||
        if (doneShowingNotificationStack) {
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ const ModalDialog = new Lang.Class({
 | 
			
		||||
        params = Params.parse(params, { shellReactive: false,
 | 
			
		||||
                                        styleClass: null,
 | 
			
		||||
                                        parentActor: Main.uiGroup,
 | 
			
		||||
                                        keybindingMode: Shell.KeyBindingMode.SYSTEM_MODAL,
 | 
			
		||||
                                        keybindingMode: Main.KeybindingMode.SYSTEM_MODAL,
 | 
			
		||||
                                        shouldFadeIn: true });
 | 
			
		||||
 | 
			
		||||
        this.state = State.CLOSED;
 | 
			
		||||
@@ -96,7 +96,8 @@ const ModalDialog = new Lang.Class({
 | 
			
		||||
                                y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this.buttonLayout = new St.BoxLayout({ style_class: 'modal-dialog-button-box',
 | 
			
		||||
                                               vertical: false });
 | 
			
		||||
                                                visible:     false,
 | 
			
		||||
                                                vertical:    false });
 | 
			
		||||
        this.dialogLayout.add(this.buttonLayout,
 | 
			
		||||
                              { expand:  true,
 | 
			
		||||
                                x_align: St.Align.MIDDLE,
 | 
			
		||||
@@ -119,6 +120,7 @@ const ModalDialog = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    setButtons: function(buttons) {
 | 
			
		||||
        this.clearButtons();
 | 
			
		||||
        this.buttonLayout.visible = (buttons.length > 0);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < buttons.length; i++) {
 | 
			
		||||
            let buttonInfo = buttons[i];
 | 
			
		||||
@@ -157,7 +159,6 @@ const ModalDialog = new Lang.Class({
 | 
			
		||||
            keys = [];
 | 
			
		||||
 | 
			
		||||
        let button = new St.Button({ style_class: 'modal-dialog-button',
 | 
			
		||||
                                     button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
 | 
			
		||||
                                     reactive:    true,
 | 
			
		||||
                                     can_focus:   true,
 | 
			
		||||
                                     label:       label });
 | 
			
		||||
 
 | 
			
		||||
@@ -103,126 +103,6 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
 | 
			
		||||
    'ibus-ui-gtk': 'keyboard'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const NotificationGenericPolicy = new Lang.Class({
 | 
			
		||||
    Name: 'NotificationGenericPolicy',
 | 
			
		||||
    Extends: MessageTray.NotificationPolicy,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        // Don't chain to parent, it would try setting
 | 
			
		||||
        // our properties to the defaults
 | 
			
		||||
 | 
			
		||||
        this.id = 'generic';
 | 
			
		||||
 | 
			
		||||
        this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' });
 | 
			
		||||
        this._masterSettings.connect('changed', Lang.bind(this, this._changed));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    store: function() { },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        this._masterSettings.run_dispose();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _changed: function(settings, key) {
 | 
			
		||||
        this.emit('policy-changed', key);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get enable() {
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get enableSound() {
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get showBanners() {
 | 
			
		||||
        return this._masterSettings.get_boolean('show-banners');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get forceExpanded() {
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get showInLockScreen() {
 | 
			
		||||
        return this._masterSettings.get_boolean('show-in-lock-screen');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get detailsInLockScreen() {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const NotificationApplicationPolicy = new Lang.Class({
 | 
			
		||||
    Name: 'NotificationApplicationPolicy',
 | 
			
		||||
    Extends: MessageTray.NotificationPolicy,
 | 
			
		||||
 | 
			
		||||
    _init: function(id) {
 | 
			
		||||
        // Don't chain to parent, it would try setting
 | 
			
		||||
        // our properties to the defaults
 | 
			
		||||
 | 
			
		||||
        this.id = id;
 | 
			
		||||
        this._canonicalId = this._canonicalizeId(id)
 | 
			
		||||
 | 
			
		||||
        this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' });
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications.application',
 | 
			
		||||
                                            path: '/org/gnome/desktop/notifications/application/' + this._canonicalId + '/' });
 | 
			
		||||
 | 
			
		||||
        this._masterSettings.connect('changed', Lang.bind(this, this._changed));
 | 
			
		||||
        this._settings.connect('changed', Lang.bind(this, this._changed));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    store: function() {
 | 
			
		||||
        this._settings.set_string('application-id', this.id + '.desktop');
 | 
			
		||||
 | 
			
		||||
        let apps = this._masterSettings.get_strv('application-children');
 | 
			
		||||
        if (apps.indexOf(this._canonicalId) < 0) {
 | 
			
		||||
            apps.push(this._canonicalId);
 | 
			
		||||
            this._masterSettings.set_strv('application-children', apps);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        this._masterSettings.run_dispose();
 | 
			
		||||
        this._settings.run_dispose();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _changed: function(settings, key) {
 | 
			
		||||
        this.emit('policy-changed', key);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _canonicalizeId: function(id) {
 | 
			
		||||
        // Keys are restricted to lowercase alphanumeric characters and dash,
 | 
			
		||||
        // and two dashes cannot be in succession
 | 
			
		||||
        return id.toLowerCase().replace(/[^a-z0-9\-]/g, '-').replace(/--+/g, '-');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get enable() {
 | 
			
		||||
        return this._settings.get_boolean('enable');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get enableSound() {
 | 
			
		||||
        return this._settings.get_boolean('enable-sound-alerts');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get showBanners() {
 | 
			
		||||
        return this._masterSettings.get_boolean('show-banners') &&
 | 
			
		||||
            this._settings.get_boolean('show-banners');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get forceExpanded() {
 | 
			
		||||
        return this._settings.get_boolean('force-expanded');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get showInLockScreen() {
 | 
			
		||||
        return this._masterSettings.get_boolean('show-in-lock-screen') &&
 | 
			
		||||
            this._settings.get_boolean('show-in-lock-screen');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get detailsInLockScreen() {
 | 
			
		||||
        return this._settings.get_boolean('details-in-lock-screen');
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const NotificationDaemon = new Lang.Class({
 | 
			
		||||
    Name: 'NotificationDaemon',
 | 
			
		||||
 | 
			
		||||
@@ -247,42 +127,42 @@ const NotificationDaemon = new Lang.Class({
 | 
			
		||||
        this._trayManager.manage_stage(global.stage, Main.messageTray.actor);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _imageForNotificationData: function(hints) {
 | 
			
		||||
        if (hints['image-data']) {
 | 
			
		||||
    _iconForNotificationData: function(icon, hints) {
 | 
			
		||||
        // If an icon is not specified, we use 'image-data' or 'image-path' hint for an icon
 | 
			
		||||
        // and don't show a large image. There are currently many applications that use
 | 
			
		||||
        // notify_notification_set_icon_from_pixbuf() from libnotify, which in turn sets
 | 
			
		||||
        // the 'image-data' hint. These applications don't typically pass in 'app_icon'
 | 
			
		||||
        // argument to Notify() and actually expect the pixbuf to be shown as an icon.
 | 
			
		||||
        // So the logic here does the right thing for this case. If both an icon and either
 | 
			
		||||
        // one of 'image-data' or 'image-path' are specified, we show both an icon and
 | 
			
		||||
        // a large image.
 | 
			
		||||
        if (icon) {
 | 
			
		||||
            if (icon.substr(0, 7) == 'file://')
 | 
			
		||||
                return new Gio.FileIcon({ file: Gio.File.new_for_uri(icon) });
 | 
			
		||||
            else if (icon[0] == '/') {
 | 
			
		||||
                return new Gio.FileIcon({ file: Gio.File.new_for_path(icon) });
 | 
			
		||||
            } else
 | 
			
		||||
                return new Gio.ThemedIcon({ name: icon });
 | 
			
		||||
        } else if (hints['image-data']) {
 | 
			
		||||
            let [width, height, rowStride, hasAlpha,
 | 
			
		||||
                 bitsPerSample, nChannels, data] = hints['image-data'];
 | 
			
		||||
            return Shell.util_create_pixbuf_from_data(data, GdkPixbuf.Colorspace.RGB, hasAlpha,
 | 
			
		||||
                                                      bitsPerSample, width, height, rowStride);
 | 
			
		||||
        } else if (hints['image-path']) {
 | 
			
		||||
            return new Gio.FileIcon({ file: Gio.File.new_for_path(hints['image-path']) });
 | 
			
		||||
        } else {
 | 
			
		||||
            let stockIcon;
 | 
			
		||||
            switch (hints.urgency) {
 | 
			
		||||
                case Urgency.LOW:
 | 
			
		||||
                case Urgency.NORMAL:
 | 
			
		||||
                    stockIcon = 'gtk-dialog-info';
 | 
			
		||||
                    break;
 | 
			
		||||
                case Urgency.CRITICAL:
 | 
			
		||||
                    stockIcon = 'gtk-dialog-error';
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            return new Gio.ThemedIcon({ name: stockIcon });
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _fallbackIconForNotificationData: function(hints) {
 | 
			
		||||
        let stockIcon;
 | 
			
		||||
        switch (hints.urgency) {
 | 
			
		||||
            case Urgency.LOW:
 | 
			
		||||
            case Urgency.NORMAL:
 | 
			
		||||
                stockIcon = 'gtk-dialog-info';
 | 
			
		||||
                break;
 | 
			
		||||
            case Urgency.CRITICAL:
 | 
			
		||||
                stockIcon = 'gtk-dialog-error';
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        return new Gio.ThemedIcon({ name: stockIcon });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _iconForNotificationData: function(icon) {
 | 
			
		||||
        if (icon) {
 | 
			
		||||
            if (icon.substr(0, 7) == 'file://')
 | 
			
		||||
                return new Gio.FileIcon({ file: Gio.File.new_for_uri(icon) });
 | 
			
		||||
            else if (icon[0] == '/')
 | 
			
		||||
                return new Gio.FileIcon({ file: Gio.File.new_for_path(icon) });
 | 
			
		||||
            else
 | 
			
		||||
                return new Gio.ThemedIcon({ name: icon });
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _lookupSource: function(title, pid, trayIcon) {
 | 
			
		||||
@@ -333,7 +213,7 @@ const NotificationDaemon = new Lang.Class({
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let source = new Source(title, pid, sender, trayIcon, ndata ? ndata.hints['desktop-entry'] : null);
 | 
			
		||||
        let source = new Source(title, pid, sender, trayIcon);
 | 
			
		||||
        source.setTransient(isForTransientNotification);
 | 
			
		||||
 | 
			
		||||
        if (!isForTransientNotification) {
 | 
			
		||||
@@ -475,8 +355,12 @@ const NotificationDaemon = new Lang.Class({
 | 
			
		||||
            [ndata.id, ndata.icon, ndata.summary, ndata.body,
 | 
			
		||||
             ndata.actions, ndata.hints, ndata.notification];
 | 
			
		||||
 | 
			
		||||
        let gicon = this._iconForNotificationData(icon, hints);
 | 
			
		||||
 | 
			
		||||
        if (notification == null) {
 | 
			
		||||
            notification = new MessageTray.Notification(source);
 | 
			
		||||
            notification = new MessageTray.Notification(source, summary, body,
 | 
			
		||||
                                                        { gicon: gicon,
 | 
			
		||||
                                                          bannerMarkup: true });
 | 
			
		||||
            ndata.notification = notification;
 | 
			
		||||
            notification.connect('destroy', Lang.bind(this,
 | 
			
		||||
                function(n, reason) {
 | 
			
		||||
@@ -499,36 +383,29 @@ const NotificationDaemon = new Lang.Class({
 | 
			
		||||
                function(n, actionId) {
 | 
			
		||||
                    this._emitActionInvoked(ndata.id, actionId);
 | 
			
		||||
                }));
 | 
			
		||||
        } else {
 | 
			
		||||
            notification.update(summary, body, { gicon: gicon,
 | 
			
		||||
                                                 bannerMarkup: true,
 | 
			
		||||
                                                 clear: true });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Mark music notifications so they can be shown in the screen shield
 | 
			
		||||
        notification.isMusic = (ndata.hints['category'] == 'x-gnome.music');
 | 
			
		||||
 | 
			
		||||
        let gicon = this._iconForNotificationData(icon, hints);
 | 
			
		||||
        let gimage = this._imageForNotificationData(hints);
 | 
			
		||||
 | 
			
		||||
        let image = null;
 | 
			
		||||
 | 
			
		||||
        // If an icon is not specified, we use 'image-data' or 'image-path' hint for an icon
 | 
			
		||||
        // and don't show a large image. There are currently many applications that use
 | 
			
		||||
        // notify_notification_set_icon_from_pixbuf() from libnotify, which in turn sets
 | 
			
		||||
        // the 'image-data' hint. These applications don't typically pass in 'app_icon'
 | 
			
		||||
        // argument to Notify() and actually expect the pixbuf to be shown as an icon.
 | 
			
		||||
        // So the logic here does the right thing for this case. If both an icon and either
 | 
			
		||||
        // one of 'image-data' or 'image-path' are specified, we show both an icon and
 | 
			
		||||
        // a large image.
 | 
			
		||||
        if (gicon && gimage)
 | 
			
		||||
            image = new St.Icon({ gicon: gimage,
 | 
			
		||||
                                  icon_size: notification.IMAGE_SIZE });
 | 
			
		||||
        else if (!gicon && gimage)
 | 
			
		||||
            gicon = gimage;
 | 
			
		||||
        else if (!gicon)
 | 
			
		||||
            gicon = this._fallbackIconForNotificationData(hints);
 | 
			
		||||
 | 
			
		||||
        notification.update(summary, body, { gicon: gicon,
 | 
			
		||||
                                             bannerMarkup: true,
 | 
			
		||||
                                             clear: true });
 | 
			
		||||
        notification.setImage(image);
 | 
			
		||||
        // We only display a large image if an icon is also specified.
 | 
			
		||||
        if (icon && (hints['image-data'] || hints['image-path'])) {
 | 
			
		||||
            let image = null;
 | 
			
		||||
            if (hints['image-data']) {
 | 
			
		||||
                let [width, height, rowStride, hasAlpha,
 | 
			
		||||
                 bitsPerSample, nChannels, data] = hints['image-data'];
 | 
			
		||||
                image = St.TextureCache.get_default().load_from_raw(data, hasAlpha,
 | 
			
		||||
                                                                    width, height, rowStride, notification.IMAGE_SIZE);
 | 
			
		||||
            } else if (hints['image-path']) {
 | 
			
		||||
                image = St.TextureCache.get_default().load_uri_async(GLib.filename_to_uri(hints['image-path'], null),
 | 
			
		||||
                                                                     notification.IMAGE_SIZE,
 | 
			
		||||
                                                                     notification.IMAGE_SIZE);
 | 
			
		||||
            }
 | 
			
		||||
            notification.setImage(image);
 | 
			
		||||
        } else {
 | 
			
		||||
            notification.unsetImage();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (actions.length) {
 | 
			
		||||
            notification.setUseActionIcons(hints['action-icons'] == true);
 | 
			
		||||
@@ -558,7 +435,7 @@ const NotificationDaemon = new Lang.Class({
 | 
			
		||||
        // of the 'transient' hint with hints['transient'] rather than hints.transient
 | 
			
		||||
        notification.setTransient(hints['transient'] == true);
 | 
			
		||||
 | 
			
		||||
        let sourceGIcon = source.useNotificationIcon ? gicon : null;
 | 
			
		||||
        let sourceGIcon = source.useNotificationIcon ? this._iconForNotificationData(icon, hints) : null;
 | 
			
		||||
        source.processNotification(notification, sourceGIcon);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -638,22 +515,12 @@ const Source = new Lang.Class({
 | 
			
		||||
    Name: 'NotificationDaemonSource',
 | 
			
		||||
    Extends: MessageTray.Source,
 | 
			
		||||
 | 
			
		||||
    _init: function(title, pid, sender, trayIcon, appId) {
 | 
			
		||||
        // Need to set the app before chaining up, so
 | 
			
		||||
        // methods called from the parent constructor can find it
 | 
			
		||||
        this.trayIcon = trayIcon;
 | 
			
		||||
        this.pid = pid;
 | 
			
		||||
        this.app = this._getApp(appId);
 | 
			
		||||
 | 
			
		||||
    _init: function(title, pid, sender, trayIcon) {
 | 
			
		||||
        this.parent(title);
 | 
			
		||||
 | 
			
		||||
        this.initialTitle = title;
 | 
			
		||||
 | 
			
		||||
        if (this.app)
 | 
			
		||||
            this.title = this.app.get_name();
 | 
			
		||||
        else
 | 
			
		||||
            this.useNotificationIcon = true;
 | 
			
		||||
 | 
			
		||||
        this.pid = pid;
 | 
			
		||||
        if (sender)
 | 
			
		||||
            this._nameWatcherId = Gio.DBus.session.watch_name(sender,
 | 
			
		||||
                                                              Gio.BusNameWatcherFlags.NONE,
 | 
			
		||||
@@ -662,19 +529,16 @@ const Source = new Lang.Class({
 | 
			
		||||
        else
 | 
			
		||||
            this._nameWatcherId = 0;
 | 
			
		||||
 | 
			
		||||
        if (this.trayIcon) {
 | 
			
		||||
            // Try again finding the app, using the WM_CLASS from the tray icon
 | 
			
		||||
            this._setSummaryIcon(this.trayIcon);
 | 
			
		||||
            this.useNotificationIcon = false;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
        this._setApp();
 | 
			
		||||
        if (this.app)
 | 
			
		||||
            this.title = this.app.get_name();
 | 
			
		||||
        else
 | 
			
		||||
            this.useNotificationIcon = true;
 | 
			
		||||
 | 
			
		||||
    _createPolicy: function() {
 | 
			
		||||
        if (this.app) {
 | 
			
		||||
            let id = this.app.get_id().replace(/\.desktop$/,'');
 | 
			
		||||
            return new NotificationApplicationPolicy(id);
 | 
			
		||||
        } else {
 | 
			
		||||
            return new NotificationGenericPolicy();
 | 
			
		||||
        this.trayIcon = trayIcon;
 | 
			
		||||
        if (this.trayIcon) {
 | 
			
		||||
           this._setSummaryIcon(this.trayIcon);
 | 
			
		||||
           this.useNotificationIcon = false;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -701,17 +565,19 @@ const Source = new Lang.Class({
 | 
			
		||||
            this.notify(notification);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    handleSummaryClick: function(button) {
 | 
			
		||||
    handleSummaryClick: function() {
 | 
			
		||||
        if (!this.trayIcon)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        let event = Clutter.get_current_event();
 | 
			
		||||
        if (event.type() != Clutter.EventType.BUTTON_RELEASE)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        // Left clicks are passed through only where there aren't unacknowledged
 | 
			
		||||
        // notifications, so it possible to open them in summary mode; right
 | 
			
		||||
        // clicks are always forwarded, as the right click menu is not useful for
 | 
			
		||||
        // tray icons
 | 
			
		||||
        if (button == 1 &&
 | 
			
		||||
        if (event.get_button() == 1 &&
 | 
			
		||||
            this.notifications.length > 0)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
@@ -724,7 +590,7 @@ const Source = new Lang.Class({
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getApp: function(appId) {
 | 
			
		||||
    _getApp: function() {
 | 
			
		||||
        let app;
 | 
			
		||||
 | 
			
		||||
        app = Shell.WindowTracker.get_default().get_app_from_pid(this.pid);
 | 
			
		||||
@@ -732,13 +598,7 @@ const Source = new Lang.Class({
 | 
			
		||||
            return app;
 | 
			
		||||
 | 
			
		||||
        if (this.trayIcon) {
 | 
			
		||||
            app = Shell.AppSystem.get_default().lookup_wmclass(this.trayIcon.wm_class);
 | 
			
		||||
            if (app != null)
 | 
			
		||||
                return app;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (appId) {
 | 
			
		||||
            app = Shell.AppSystem.get_default().lookup_app(appId + '.desktop');
 | 
			
		||||
            app = Shell.AppSystem.get_default().lookup_wmclass(this.trayIcon.wmclass);
 | 
			
		||||
            if (app != null)
 | 
			
		||||
                return app;
 | 
			
		||||
        }
 | 
			
		||||
@@ -746,11 +606,11 @@ const Source = new Lang.Class({
 | 
			
		||||
        return null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setApp: function(appId) {
 | 
			
		||||
    _setApp: function() {
 | 
			
		||||
        if (this.app)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this.app = this._getApp(appId);
 | 
			
		||||
        this.app = this._getApp();
 | 
			
		||||
        if (!this.app)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -122,8 +122,7 @@ const Overview = new Lang.Class({
 | 
			
		||||
        // one. Instances of this class share a single CoglTexture behind the
 | 
			
		||||
        // scenes which allows us to show the background with different
 | 
			
		||||
        // rendering options without duplicating the texture data.
 | 
			
		||||
        this._background = new Meta.BackgroundActor({ screen: global.screen,
 | 
			
		||||
                                                      settings: Main.background });
 | 
			
		||||
        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,
 | 
			
		||||
@@ -577,7 +576,7 @@ const Overview = new Lang.Class({
 | 
			
		||||
        if (this._shown) {
 | 
			
		||||
            if (!this._modal) {
 | 
			
		||||
                if (Main.pushModal(this._overview,
 | 
			
		||||
                                   { keybindingMode: Shell.KeyBindingMode.OVERVIEW }))
 | 
			
		||||
                                   { keybindingMode: Main.KeybindingMode.OVERVIEW }))
 | 
			
		||||
                    this._modal = true;
 | 
			
		||||
                else
 | 
			
		||||
                    this.hide();
 | 
			
		||||
 
 | 
			
		||||
@@ -315,7 +315,7 @@ const AppMenuButton = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show: function() {
 | 
			
		||||
        if (this._visible)
 | 
			
		||||
        if (this._visible || Main.screenShield.locked)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._visible = true;
 | 
			
		||||
@@ -598,11 +598,6 @@ const AppMenuButton = new Lang.Class({
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            menu = new PopupMenu.RemoteMenu(this.actor, this._targetApp.menu, this._targetApp.action_group);
 | 
			
		||||
            menu.connect('activate', Lang.bind(this, function() {
 | 
			
		||||
                let win = this._targetApp.get_windows()[0];
 | 
			
		||||
                win.check_alive(global.get_current_time());
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            if (this.menu.isDummyQuitMenu)
 | 
			
		||||
                return;
 | 
			
		||||
@@ -644,7 +639,7 @@ const ActivitiesButton = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this.actor.label_actor = this._label;
 | 
			
		||||
 | 
			
		||||
        this.hotCorner = new Layout.HotCorner(Main.layoutManager);
 | 
			
		||||
        this.hotCorner = new Layout.HotCorner();
 | 
			
		||||
        container.add_actor(this.hotCorner.actor);
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
 | 
			
		||||
@@ -751,9 +746,12 @@ const ActivitiesButton = new Lang.Class({
 | 
			
		||||
const PanelCorner = new Lang.Class({
 | 
			
		||||
    Name: 'PanelCorner',
 | 
			
		||||
 | 
			
		||||
    _init: function(side) {
 | 
			
		||||
    _init: function(box, side) {
 | 
			
		||||
        this._side = side;
 | 
			
		||||
 | 
			
		||||
        this._box = box;
 | 
			
		||||
        this._box.connect('style-changed', Lang.bind(this, this._boxStyleChanged));
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.DrawingArea({ style_class: 'panel-corner' });
 | 
			
		||||
        this.actor.connect('style-changed', Lang.bind(this, this._styleChanged));
 | 
			
		||||
        this.actor.connect('repaint', Lang.bind(this, this._repaint));
 | 
			
		||||
@@ -809,12 +807,12 @@ const PanelCorner = new Lang.Class({
 | 
			
		||||
        return children[index];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setStyleParent: function(box) {
 | 
			
		||||
    _boxStyleChanged: function() {
 | 
			
		||||
        let side = this._side;
 | 
			
		||||
 | 
			
		||||
        let rtlAwareContainer = box instanceof St.BoxLayout;
 | 
			
		||||
        let rtlAwareContainer = this._box instanceof St.BoxLayout;
 | 
			
		||||
        if (rtlAwareContainer &&
 | 
			
		||||
            box.get_text_direction() == Clutter.TextDirection.RTL) {
 | 
			
		||||
            this._box.get_text_direction() == Clutter.TextDirection.RTL) {
 | 
			
		||||
            if (this._side == St.Side.LEFT)
 | 
			
		||||
                side = St.Side.RIGHT;
 | 
			
		||||
            else if (this._side == St.Side.RIGHT)
 | 
			
		||||
@@ -823,9 +821,9 @@ const PanelCorner = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        let button;
 | 
			
		||||
        if (side == St.Side.LEFT)
 | 
			
		||||
            button = this._findLeftmostButton(box);
 | 
			
		||||
            button = this._findLeftmostButton(this._box);
 | 
			
		||||
        else if (side == St.Side.RIGHT)
 | 
			
		||||
            button = this._findRightmostButton(box);
 | 
			
		||||
            button = this._findRightmostButton(this._box);
 | 
			
		||||
 | 
			
		||||
        if (button) {
 | 
			
		||||
            if (this._button && this._buttonStyleChangedSignalId) {
 | 
			
		||||
@@ -852,7 +850,7 @@ const PanelCorner = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
            // The corner doesn't support theme transitions, so override
 | 
			
		||||
            // the .panel-button default
 | 
			
		||||
            button.style = 'transition-duration: 0ms';
 | 
			
		||||
            button.style = 'transition-duration: 0';
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -865,8 +863,8 @@ const PanelCorner = new Lang.Class({
 | 
			
		||||
        let backgroundColor = node.get_color('-panel-corner-background-color');
 | 
			
		||||
        let borderColor = node.get_color('-panel-corner-border-color');
 | 
			
		||||
 | 
			
		||||
        let overlap = borderColor.alpha != 0;
 | 
			
		||||
        let offsetY = overlap ? 0 : borderWidth;
 | 
			
		||||
        let noOverlap = borderColor.alpha == 0;
 | 
			
		||||
        let offsetY = noOverlap ? borderWidth : 0;
 | 
			
		||||
 | 
			
		||||
        let cr = this.actor.get_context();
 | 
			
		||||
        cr.setOperator(Cairo.Operator.SOURCE);
 | 
			
		||||
@@ -890,18 +888,17 @@ const PanelCorner = new Lang.Class({
 | 
			
		||||
        Clutter.cairo_set_source_color(cr, over);
 | 
			
		||||
        cr.fill();
 | 
			
		||||
 | 
			
		||||
        if (overlap) {
 | 
			
		||||
            let offset = borderWidth;
 | 
			
		||||
            Clutter.cairo_set_source_color(cr, backgroundColor);
 | 
			
		||||
        if (noOverlap)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
            cr.save();
 | 
			
		||||
            cr.translate(xOffsetDirection * offset, - offset);
 | 
			
		||||
            cr.appendPath(savedPath);
 | 
			
		||||
            cr.fill();
 | 
			
		||||
            cr.restore();
 | 
			
		||||
        }
 | 
			
		||||
        let offset = borderWidth;
 | 
			
		||||
        Clutter.cairo_set_source_color(cr, backgroundColor);
 | 
			
		||||
 | 
			
		||||
        cr.$dispose();
 | 
			
		||||
        cr.save();
 | 
			
		||||
        cr.translate(xOffsetDirection * offset, - offset);
 | 
			
		||||
        cr.appendPath(savedPath);
 | 
			
		||||
        cr.fill();
 | 
			
		||||
        cr.restore();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _styleChanged: function() {
 | 
			
		||||
@@ -961,10 +958,17 @@ const Panel = new Lang.Class({
 | 
			
		||||
        this._rightBox = new St.BoxLayout({ name: 'panelRight' });
 | 
			
		||||
        this.actor.add_actor(this._rightBox);
 | 
			
		||||
 | 
			
		||||
        this._leftCorner = new PanelCorner(St.Side.LEFT);
 | 
			
		||||
        if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
            this._leftCorner = new PanelCorner(this._rightBox, St.Side.LEFT);
 | 
			
		||||
        else
 | 
			
		||||
            this._leftCorner = new PanelCorner(this._leftBox, St.Side.LEFT);
 | 
			
		||||
 | 
			
		||||
        this.actor.add_actor(this._leftCorner.actor);
 | 
			
		||||
 | 
			
		||||
        this._rightCorner = new PanelCorner(St.Side.RIGHT);
 | 
			
		||||
        if (this.actor.get_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
            this._rightCorner = new PanelCorner(this._leftBox, St.Side.RIGHT);
 | 
			
		||||
        else
 | 
			
		||||
            this._rightCorner = new PanelCorner(this._rightBox, St.Side.RIGHT);
 | 
			
		||||
        this.actor.add_actor(this._rightCorner.actor);
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
 | 
			
		||||
@@ -1137,13 +1141,17 @@ const Panel = new Lang.Class({
 | 
			
		||||
        this._sessionStyle = Main.sessionMode.panelStyle;
 | 
			
		||||
        if (this._sessionStyle)
 | 
			
		||||
            this._addStyleClassName(this._sessionStyle);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
        if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) {
 | 
			
		||||
            this._leftCorner.setStyleParent(this._rightBox);
 | 
			
		||||
            this._rightCorner.setStyleParent(this._leftBox);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._leftCorner.setStyleParent(this._leftBox);
 | 
			
		||||
            this._rightCorner.setStyleParent(this._rightBox);
 | 
			
		||||
    _initBox: function(elements, box) {
 | 
			
		||||
        for (let i = 0; i < elements.length; i++) {
 | 
			
		||||
            let role = elements[i];
 | 
			
		||||
            let constructor = PANEL_ITEM_IMPLEMENTATIONS[role];
 | 
			
		||||
            if (!constructor) {
 | 
			
		||||
                // panel icon is not supported (can happen for
 | 
			
		||||
                // bluetooth or network)
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -244,21 +244,18 @@ const SystemStatusButton = new Lang.Class({
 | 
			
		||||
            this.setIcon(iconName);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get icons() {
 | 
			
		||||
        return this._box.get_children();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addIcon: function(gicon) {
 | 
			
		||||
        let icon = new St.Icon({ gicon: gicon,
 | 
			
		||||
                                 style_class: 'system-status-icon' });
 | 
			
		||||
        this._box.add_actor(icon);
 | 
			
		||||
 | 
			
		||||
        this.emit('icons-changed');
 | 
			
		||||
 | 
			
		||||
        return icon;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setIcon: function(iconName) {
 | 
			
		||||
        // Need to first add a NULL GIcon and then set icon_name, to ensure
 | 
			
		||||
        // compatibility with -symbolic fallbacks
 | 
			
		||||
 | 
			
		||||
        if (!this.mainIcon)
 | 
			
		||||
            this.mainIcon = this.addIcon(null);
 | 
			
		||||
        this.mainIcon.icon_name = iconName;
 | 
			
		||||
 
 | 
			
		||||
@@ -41,10 +41,10 @@ const PointerWatcher = new Lang.Class({
 | 
			
		||||
    Name: 'PointerWatcher',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._idleMonitor = new GnomeDesktop.IdleMonitor();
 | 
			
		||||
        this._idleMonitor.connect('became-active', Lang.bind(this, this._onIdleMonitorBecameActive));
 | 
			
		||||
        this._idleMonitor.add_watch(IDLE_TIME, Lang.bind(this, this._onIdleMonitorBecameIdle));
 | 
			
		||||
        this._idle = this._idleMonitor.get_idletime() > IDLE_TIME;
 | 
			
		||||
        let idleMonitor = new GnomeDesktop.IdleMonitor();
 | 
			
		||||
        idleMonitor.connect('became-active', Lang.bind(this, this._onIdleMonitorBecameActive));
 | 
			
		||||
        idleMonitor.add_watch(IDLE_TIME, Lang.bind(this, this._onIdleMonitorBecameIdle));
 | 
			
		||||
        this._idle = idleMonitor.get_idletime() > IDLE_TIME;
 | 
			
		||||
        this._watches = [];
 | 
			
		||||
        this.pointerX = null;
 | 
			
		||||
        this.pointerY = null;
 | 
			
		||||
 
 | 
			
		||||
@@ -207,7 +207,6 @@ const PopupBaseMenuItem = new Lang.Class({
 | 
			
		||||
            color.alpha / 255);
 | 
			
		||||
        cr.arc(width / 2, height / 2, width / 3, 0, 2 * Math.PI);
 | 
			
		||||
        cr.fill();
 | 
			
		||||
        cr.$dispose();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // This returns column widths in logical order (i.e. from the dot
 | 
			
		||||
@@ -605,7 +604,6 @@ const PopupSliderMenuItem = new Lang.Class({
 | 
			
		||||
            color.alpha / 255);
 | 
			
		||||
        cr.arc(handleX, handleY, handleRadius, 0, 2 * Math.PI);
 | 
			
		||||
        cr.fill();
 | 
			
		||||
        cr.$dispose();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _startDragging: function(actor, event) {
 | 
			
		||||
@@ -638,34 +636,20 @@ const PopupSliderMenuItem = new Lang.Class({
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    scroll: function(event) {
 | 
			
		||||
    _onScrollEvent: function (actor, event) {
 | 
			
		||||
        let direction = event.get_scroll_direction();
 | 
			
		||||
        let delta;
 | 
			
		||||
 | 
			
		||||
        if (event.is_pointer_emulated())
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (direction == Clutter.ScrollDirection.DOWN) {
 | 
			
		||||
            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.max(0, this._value - SLIDER_SCROLL_STEP);
 | 
			
		||||
        }
 | 
			
		||||
        else if (direction == Clutter.ScrollDirection.UP) {
 | 
			
		||||
            this._value = Math.min(1, this._value + SLIDER_SCROLL_STEP);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._value = Math.min(Math.max(0, this._value + delta), 1);
 | 
			
		||||
 | 
			
		||||
        this._slider.queue_repaint();
 | 
			
		||||
        this.emit('value-changed', this._value);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onScrollEvent: function(actor, event) {
 | 
			
		||||
        this.scroll(event);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _motionEvent: function(actor, event) {
 | 
			
		||||
        let absX, absY;
 | 
			
		||||
        [absX, absY] = event.get_coords();
 | 
			
		||||
@@ -889,7 +873,7 @@ const PopupMenuBase = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    addSettingsAction: function(title, desktopFile) {
 | 
			
		||||
        let menuItem = this.addAction(title, function() {
 | 
			
		||||
                           let app = Shell.AppSystem.get_default().lookup_app(desktopFile);
 | 
			
		||||
                           let app = Shell.AppSystem.get_default().lookup_setting(desktopFile);
 | 
			
		||||
 | 
			
		||||
                           if (!app) {
 | 
			
		||||
                               log('Settings panel for desktop file ' + desktopFile + ' could not be loaded!');
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,9 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const GdkPixbuf = imports.gi.GdkPixbuf;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
 | 
			
		||||
const FileUtils = imports.misc.fileUtils;
 | 
			
		||||
const Search = imports.ui.search;
 | 
			
		||||
@@ -137,12 +135,8 @@ function remoteProvidersLoaded(loadState) {
 | 
			
		||||
            idxB = sortOrder.indexOf(appIdB);
 | 
			
		||||
 | 
			
		||||
            // if no provider is found in the order, use alphabetical order
 | 
			
		||||
            if ((idxA == -1) && (idxB == -1)) {
 | 
			
		||||
                let nameA = providerA.appInfo.get_name();
 | 
			
		||||
                let nameB = providerB.appInfo.get_name();
 | 
			
		||||
 | 
			
		||||
                return GLib.utf8_collate(nameA, nameB);
 | 
			
		||||
            }
 | 
			
		||||
            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
 | 
			
		||||
@@ -193,18 +187,18 @@ const RemoteSearchProvider = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createIcon: function(size, meta) {
 | 
			
		||||
        let gicon;
 | 
			
		||||
        if (meta['gicon']) {
 | 
			
		||||
            gicon = Gio.icon_new_for_string(meta['gicon']);
 | 
			
		||||
            return new St.Icon({ gicon: Gio.icon_new_for_string(meta['gicon']),
 | 
			
		||||
                                 icon_size: size });
 | 
			
		||||
        } else if (meta['icon-data']) {
 | 
			
		||||
            let [width, height, rowStride, hasAlpha,
 | 
			
		||||
                 bitsPerSample, nChannels, data] = meta['icon-data'];
 | 
			
		||||
            gicon = Shell.util_create_pixbuf_from_data(data, GdkPixbuf.Colorspace.RGB, hasAlpha,
 | 
			
		||||
                                                       bitsPerSample, width, height, rowStride);
 | 
			
		||||
            let textureCache = St.TextureCache.get_default();
 | 
			
		||||
            return textureCache.load_from_raw(data, hasAlpha,
 | 
			
		||||
                                              width, height, rowStride, size);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return new St.Icon({ gicon: gicon,
 | 
			
		||||
                             icon_size: size });
 | 
			
		||||
        return null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getResultsFinished: function(results, error) {
 | 
			
		||||
@@ -221,7 +215,7 @@ const RemoteSearchProvider = new Lang.Class({
 | 
			
		||||
                                                 Lang.bind(this, this._getResultsFinished),
 | 
			
		||||
                                                 this._cancellable);
 | 
			
		||||
        } catch(e) {
 | 
			
		||||
            log('Error calling GetInitialResultSet for provider %s: %s'.format(this.id, e.toString()));
 | 
			
		||||
            log('Error calling GetInitialResultSet for provider %s: %s'.format( this.title, e.toString()));
 | 
			
		||||
            this.searchSystem.pushResults(this, []);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
@@ -234,7 +228,7 @@ const RemoteSearchProvider = new Lang.Class({
 | 
			
		||||
                                                   Lang.bind(this, this._getResultsFinished),
 | 
			
		||||
                                                   this._cancellable);
 | 
			
		||||
        } catch(e) {
 | 
			
		||||
            log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.id, e.toString()));
 | 
			
		||||
            log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.title, e.toString()));
 | 
			
		||||
            this.searchSystem.pushResults(this, []);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
@@ -265,7 +259,7 @@ const RemoteSearchProvider = new Lang.Class({
 | 
			
		||||
                                            Lang.bind(this, this._getResultMetasFinished, callback),
 | 
			
		||||
                                            this._cancellable);
 | 
			
		||||
        } catch(e) {
 | 
			
		||||
            log('Error calling GetResultMetas for provider %s: %s'.format(this.id, e.toString()));
 | 
			
		||||
            log('Error calling GetResultMetas for provider %s: %s'.format(this.title, e.toString()));
 | 
			
		||||
            callback([]);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -8,13 +8,11 @@ const GnomeDesktop = imports.gi.GnomeDesktop;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const TweenerEquations = imports.tweener.equations;
 | 
			
		||||
 | 
			
		||||
const GnomeSession = imports.misc.gnomeSession;
 | 
			
		||||
const Hash = imports.misc.hash;
 | 
			
		||||
const Layout = imports.ui.layout;
 | 
			
		||||
const LoginManager = imports.misc.loginManager;
 | 
			
		||||
const Lightbox = imports.ui.lightbox;
 | 
			
		||||
@@ -27,7 +25,6 @@ const Util = imports.misc.util;
 | 
			
		||||
 | 
			
		||||
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
 | 
			
		||||
const LOCK_ENABLED_KEY = 'lock-enabled';
 | 
			
		||||
const LOCK_DELAY_KEY = 'lock-delay';
 | 
			
		||||
 | 
			
		||||
const CURTAIN_SLIDE_TIME = 0.3;
 | 
			
		||||
// fraction of screen height the arrow must reach before completing
 | 
			
		||||
@@ -52,16 +49,36 @@ const SUMMARY_ICON_SIZE = 48;
 | 
			
		||||
const STANDARD_FADE_TIME = 10;
 | 
			
		||||
const SHORT_FADE_TIME = 0.3;
 | 
			
		||||
 | 
			
		||||
const GLSL_EFFECT_DECLARATIONS = ' \
 | 
			
		||||
uniform float desaturation; \n \
 | 
			
		||||
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_EFFECT_CODE = ' \
 | 
			
		||||
cogl_color_out.rgb = desaturate(cogl_color_out.rgb);\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({
 | 
			
		||||
@@ -109,48 +126,49 @@ const NotificationsBox = new Lang.Class({
 | 
			
		||||
                                        name: 'screenShieldNotifications',
 | 
			
		||||
                                        style_class: 'screen-shield-notifications-box' });
 | 
			
		||||
 | 
			
		||||
        this._musicBin = new St.Bin({ style_class: 'screen-shield-notifications-box',
 | 
			
		||||
                                      visible: false });
 | 
			
		||||
 | 
			
		||||
        this._residentNotificationBox = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                                           style_class: 'screen-shield-notifications-box' });
 | 
			
		||||
        let scrollView = new St.ScrollView({ x_fill: false, x_align: St.Align.START });
 | 
			
		||||
        this._notificationBox = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                                   style_class: 'screen-shield-notifications-box' });
 | 
			
		||||
        scrollView.add_actor(this._notificationBox);
 | 
			
		||||
        this._persistentNotificationBox = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                                             style_class: 'screen-shield-notifications-box' });
 | 
			
		||||
        scrollView.add_actor(this._persistentNotificationBox);
 | 
			
		||||
 | 
			
		||||
        this.actor.add(this._musicBin);
 | 
			
		||||
        this.actor.add(this._residentNotificationBox, { x_fill: true });
 | 
			
		||||
        this.actor.add(scrollView, { x_fill: true, x_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        this._sources = new Hash.Map();
 | 
			
		||||
        Main.messageTray.getSources().forEach(Lang.bind(this, function(source) {
 | 
			
		||||
            this._sourceAdded(Main.messageTray, source, true);
 | 
			
		||||
        this._items = [];
 | 
			
		||||
        Main.messageTray.getSummaryItems().forEach(Lang.bind(this, function(item) {
 | 
			
		||||
            this._summaryItemAdded(Main.messageTray, item, true);
 | 
			
		||||
        }));
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
 | 
			
		||||
        this._sourceAddedId = Main.messageTray.connect('source-added', Lang.bind(this, this._sourceAdded));
 | 
			
		||||
        this._summaryAddedId = Main.messageTray.connect('summary-item-added', Lang.bind(this, this._summaryItemAdded));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        if (this._sourceAddedId) {
 | 
			
		||||
            Main.messageTray.disconnect(this._sourceAddedId);
 | 
			
		||||
            this._sourceAddedId = 0;
 | 
			
		||||
        if (this._summaryAddedId) {
 | 
			
		||||
            Main.messageTray.disconnect(this._summaryAddedId);
 | 
			
		||||
            this._summaryAddedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let items = this._sources.items();
 | 
			
		||||
        for (let i = 0; i < items.length; i++) {
 | 
			
		||||
            let [source, obj] = items[i];
 | 
			
		||||
            this._removeSource(source, obj);
 | 
			
		||||
        }
 | 
			
		||||
        for (let i = 0; i < this._items.length; i++)
 | 
			
		||||
            this._removeItem(this._items[i]);
 | 
			
		||||
        this._items = [];
 | 
			
		||||
 | 
			
		||||
        this.actor.destroy();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateVisibility: function() {
 | 
			
		||||
        this._musicBin.visible = this._musicBin.child != null && this._musicBin.child.visible;
 | 
			
		||||
        this._notificationBox.visible = this._notificationBox.get_children().some(function(a) {
 | 
			
		||||
        this._residentNotificationBox.visible = this._residentNotificationBox.get_n_children() > 0;
 | 
			
		||||
        this._persistentNotificationBox.visible = this._persistentNotificationBox.get_children().some(function(a) {
 | 
			
		||||
            return a.visible;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.actor.visible = this._musicBin.visible || this._notificationBox.visible;
 | 
			
		||||
        this.actor.visible = this._residentNotificationBox.visible || this._persistentNotificationBox.visible;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _sourceIsResident: function(source) {
 | 
			
		||||
        return source.hasResidentNotification() && !source.isChat;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _makeNotificationCountText: function(count, isChat) {
 | 
			
		||||
@@ -160,16 +178,18 @@ const NotificationsBox = new Lang.Class({
 | 
			
		||||
            return ngettext("%d new notification", "%d new notifications", count).format(count);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _makeNotificationSource: function(source, box) {
 | 
			
		||||
    _makeNotificationSource: function(source) {
 | 
			
		||||
        let box = new St.BoxLayout({ style_class: 'screen-shield-notification-source' });
 | 
			
		||||
 | 
			
		||||
        let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
 | 
			
		||||
        box.add(sourceActor.actor, { y_fill: true });
 | 
			
		||||
 | 
			
		||||
        let textBox = new St.BoxLayout({ vertical: true });
 | 
			
		||||
        box.add(textBox, { y_fill: false, y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        let title = new St.Label({ text: source.title,
 | 
			
		||||
        let label = new St.Label({ text: source.title,
 | 
			
		||||
                                   style_class: 'screen-shield-notification-label' });
 | 
			
		||||
        textBox.add(title);
 | 
			
		||||
        textBox.add(label);
 | 
			
		||||
 | 
			
		||||
        let count = source.unseenCount;
 | 
			
		||||
        let countLabel = new St.Label({ text: this._makeNotificationCountText(count, source.isChat),
 | 
			
		||||
@@ -177,179 +197,118 @@ const NotificationsBox = new Lang.Class({
 | 
			
		||||
        textBox.add(countLabel);
 | 
			
		||||
 | 
			
		||||
        box.visible = count != 0;
 | 
			
		||||
        return [title, countLabel];
 | 
			
		||||
        return [box, countLabel];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _makeNotificationDetailedSource: function(source, box) {
 | 
			
		||||
        let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
 | 
			
		||||
        box.add(sourceActor.actor, { y_fill: true });
 | 
			
		||||
 | 
			
		||||
        let textBox = new St.BoxLayout({ vertical: true });
 | 
			
		||||
        box.add(textBox, { y_fill: false, y_align: St.Align.START });
 | 
			
		||||
 | 
			
		||||
        let title = new St.Label({ text: source.title,
 | 
			
		||||
                                   style_class: 'screen-shield-notification-label' });
 | 
			
		||||
        textBox.add(title);
 | 
			
		||||
 | 
			
		||||
        let visible = false;
 | 
			
		||||
        for (let i = 0; i < source.notifications.length; i++) {
 | 
			
		||||
            let n = source.notifications[i];
 | 
			
		||||
 | 
			
		||||
            if (n.acknowledged || n.isMusic)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            let body = '';
 | 
			
		||||
            if (n.bannerBodyText) {
 | 
			
		||||
                body = n.bannerBodyMarkup ? n.bannerBodyText :
 | 
			
		||||
                GLib.markup_escape_text(n.bannerBodyMarkup, -1);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let label = new St.Label({ style_class: 'screen-shield-notification-count-text' });
 | 
			
		||||
            label.clutter_text.set_markup('<b>' + n.title + '</b> ' + body);
 | 
			
		||||
            textBox.add(label);
 | 
			
		||||
 | 
			
		||||
            visible = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        box.visible = visible;
 | 
			
		||||
        return [title, null];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _showSource: function(source, obj, box) {
 | 
			
		||||
        let musicNotification = source.getMusicNotification();
 | 
			
		||||
 | 
			
		||||
        if (musicNotification != null &&
 | 
			
		||||
            this._musicBin.child == null) {
 | 
			
		||||
            if (musicNotification.actor.get_parent() != null)
 | 
			
		||||
                musicNotification.actor.get_parent().remove_actor(musicNotification.actor);
 | 
			
		||||
            this._musicBin.child = musicNotification.actor;
 | 
			
		||||
            this._musicBin.child.visible = obj.visible;
 | 
			
		||||
 | 
			
		||||
            musicNotification.expand(false /* animate */);
 | 
			
		||||
 | 
			
		||||
            obj.musicNotification = musicNotification;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (obj.detailed) {
 | 
			
		||||
            [obj.titleLabel, obj.countLabel] = this._makeNotificationDetailedSource(source, box);
 | 
			
		||||
        } else {
 | 
			
		||||
            [obj.titleLabel, obj.countLabel] = this._makeNotificationSource(source, box);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        box.visible = obj.visible &&
 | 
			
		||||
            (source.unseenCount > (musicNotification ? 1 : 0));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _sourceAdded: function(tray, source, dontUpdateVisibility) {
 | 
			
		||||
        // Ignore transient sources
 | 
			
		||||
        if (source.isTransient)
 | 
			
		||||
    _summaryItemAdded: function(tray, item, dontUpdateVisibility) {
 | 
			
		||||
        // Ignore transient sources, or sources explicitly marked not to show
 | 
			
		||||
        // in the lock screen
 | 
			
		||||
        if (item.source.isTransient || !item.source.showInLockScreen)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let obj = {
 | 
			
		||||
            visible: source.policy.showInLockScreen,
 | 
			
		||||
            detailed: source.policy.detailsInLockScreen,
 | 
			
		||||
            item: item,
 | 
			
		||||
            source: item.source,
 | 
			
		||||
            resident: this._sourceIsResident(item.source),
 | 
			
		||||
            contentUpdatedId: 0,
 | 
			
		||||
            sourceDestroyId: 0,
 | 
			
		||||
            sourceCountChangedId: 0,
 | 
			
		||||
            sourceTitleChangedId: 0,
 | 
			
		||||
            sourceUpdatedId: 0,
 | 
			
		||||
            musicNotification: null,
 | 
			
		||||
            sourceBox: null,
 | 
			
		||||
            titleLabel: null,
 | 
			
		||||
            countLabel: null,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        obj.sourceBox = new St.BoxLayout({ style_class: 'screen-shield-notification-source' });
 | 
			
		||||
        this._showSource(source, obj, obj.sourceBox);
 | 
			
		||||
        this._notificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START });
 | 
			
		||||
        if (obj.resident) {
 | 
			
		||||
            this._residentNotificationBox.add(item.notificationStackWidget);
 | 
			
		||||
            item.closeButton.hide();
 | 
			
		||||
            item.prepareNotificationStackForShowing();
 | 
			
		||||
        } else {
 | 
			
		||||
            [obj.sourceBox, obj.countLabel] = this._makeNotificationSource(item.source);
 | 
			
		||||
            this._persistentNotificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        obj.sourceCountChangedId = source.connect('count-updated', Lang.bind(this, function(source) {
 | 
			
		||||
            this._countChanged(source, obj);
 | 
			
		||||
        }));
 | 
			
		||||
        obj.sourceTitleChangedId = source.connect('title-changed', Lang.bind(this, function(source) {
 | 
			
		||||
            this._titleChanged(source, obj);
 | 
			
		||||
        }));
 | 
			
		||||
        obj.policyChangedId = source.policy.connect('policy-changed', Lang.bind(this, function(policy, key) {
 | 
			
		||||
            if (key == 'show-in-lock-screen')
 | 
			
		||||
                this._visibleChanged(source, obj);
 | 
			
		||||
            else
 | 
			
		||||
                this._detailedChanged(source, obj);
 | 
			
		||||
        }));
 | 
			
		||||
        obj.sourceDestroyId = source.connect('destroy', Lang.bind(this, function(source) {
 | 
			
		||||
            this._onSourceDestroy(source, obj);
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this._sources.set(source, obj);
 | 
			
		||||
        obj.contentUpdatedId = item.connect('content-updated', Lang.bind(this, this._onItemContentUpdated));
 | 
			
		||||
        obj.sourceCountChangedId = item.source.connect('count-updated', Lang.bind(this, this._onSourceChanged));
 | 
			
		||||
        obj.sourceTitleChangedId = item.source.connect('title-changed', Lang.bind(this, this._onSourceChanged));
 | 
			
		||||
        obj.sourceDestroyId = item.source.connect('destroy', Lang.bind(this, this._onSourceDestroy));
 | 
			
		||||
        this._items.push(obj);
 | 
			
		||||
 | 
			
		||||
        if (!dontUpdateVisibility)
 | 
			
		||||
            this._updateVisibility();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _titleChanged: function(source, obj) {
 | 
			
		||||
        obj.titleLabel.text = source.title;
 | 
			
		||||
    _findSource: function(source) {
 | 
			
		||||
        for (let i = 0; i < this._items.length; i++) {
 | 
			
		||||
            if (this._items[i].source == source)
 | 
			
		||||
                return i;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return -1;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _countChanged: function(source, obj) {
 | 
			
		||||
        if (obj.detailed) {
 | 
			
		||||
            // A new notification was pushed, or a previous notification was destroyed.
 | 
			
		||||
            // Give up, and build the list again.
 | 
			
		||||
    _onItemContentUpdated: function(item) {
 | 
			
		||||
        let obj = this._items[this._findSource(item.source)];
 | 
			
		||||
        this._updateItem(obj);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
            obj.sourceBox.destroy_all_children();
 | 
			
		||||
            obj.titleLabel = obj.countLabel = null;
 | 
			
		||||
            this._showSource(source, obj, obj.sourceBox);
 | 
			
		||||
    _onSourceChanged: function(source) {
 | 
			
		||||
        let obj = this._items[this._findSource(source)];
 | 
			
		||||
        this._updateItem(obj);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateItem: function(obj) {
 | 
			
		||||
        let itemShouldBeResident = this._sourceIsResident(obj.source);
 | 
			
		||||
 | 
			
		||||
        if (itemShouldBeResident && obj.resident) {
 | 
			
		||||
            // Nothing to do here, the actor is already updated
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (obj.resident && !itemShouldBeResident) {
 | 
			
		||||
            // make into a regular item
 | 
			
		||||
            obj.item.doneShowingNotificationStack();
 | 
			
		||||
            this._residentNotificationBox.remove_actor(obj.item.notificationStackWidget);
 | 
			
		||||
 | 
			
		||||
            [obj.sourceBox, obj.countLabel] = this._makeNotificationSource(obj.source);
 | 
			
		||||
            this._persistentNotificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START });
 | 
			
		||||
        } else if (itemShouldBeResident && !obj.resident) {
 | 
			
		||||
            // make into a resident item
 | 
			
		||||
            obj.sourceBox.destroy();
 | 
			
		||||
            obj.sourceBox = obj.countLabel = null;
 | 
			
		||||
            obj.resident = true;
 | 
			
		||||
 | 
			
		||||
            this._residentNotificationBox.add(obj.item.notificationStackWidget);
 | 
			
		||||
            obj.item.closeButton.hide();
 | 
			
		||||
            obj.item.prepareNotificationStackForShowing();
 | 
			
		||||
        } else {
 | 
			
		||||
            let count = source.unseenCount;
 | 
			
		||||
            obj.countLabel.text = this._makeNotificationCountText(count, source.isChat);
 | 
			
		||||
            // just update the counter
 | 
			
		||||
            let count = obj.source.unseenCount;
 | 
			
		||||
            obj.countLabel.text = this._makeNotificationCountText(count, obj.source.isChat);
 | 
			
		||||
            obj.sourceBox.visible = count != 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        obj.sourceBox.visible = obj.visible &&
 | 
			
		||||
            (source.unseenCount > (obj.musicNotification ? 1 : 0));
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _visibleChanged: function(source, obj) {
 | 
			
		||||
        if (obj.visible == source.policy.showInLockScreen)
 | 
			
		||||
            return;
 | 
			
		||||
    _onSourceDestroy: function(source) {
 | 
			
		||||
        let idx = this._findSource(source);
 | 
			
		||||
 | 
			
		||||
        obj.visible = source.policy.showInLockScreen;
 | 
			
		||||
        if (obj.musicNotification)
 | 
			
		||||
            obj.musicNotification.actor.visible = obj.visible;
 | 
			
		||||
        obj.sourceBox.visible = obj.visible &&
 | 
			
		||||
            source.unseenCount > (obj.musicNotification ? 1 : 0);
 | 
			
		||||
        this._removeItem(this._items[idx]);
 | 
			
		||||
        this._items.splice(idx, 1);
 | 
			
		||||
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _detailedChanged: function(source, obj) {
 | 
			
		||||
        if (obj.detailed == source.policy.detailsInLockScreen)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        obj.detailed = source.policy.detailsInLockScreen;
 | 
			
		||||
 | 
			
		||||
        obj.sourceBox.destroy_all_children();
 | 
			
		||||
        obj.titleLabel = obj.countLabel = null;
 | 
			
		||||
        this._showSource(source, obj, obj.sourceBox);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onSourceDestroy: function(source, obj) {
 | 
			
		||||
        this._removeSource(source, obj);
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _removeSource: function(source, obj) {
 | 
			
		||||
        obj.sourceBox.destroy();
 | 
			
		||||
        obj.sourceBox = obj.titleLabel = obj.countLabel = null;
 | 
			
		||||
 | 
			
		||||
        if (obj.musicNotification) {
 | 
			
		||||
            this._musicBin.child = null;
 | 
			
		||||
            obj.musicNotification = null;
 | 
			
		||||
    _removeItem: function(obj) {
 | 
			
		||||
        if (obj.resident) {
 | 
			
		||||
            obj.item.doneShowingNotificationStack();
 | 
			
		||||
            this._residentNotificationBox.remove_actor(obj.item.notificationStackWidget);
 | 
			
		||||
        } else {
 | 
			
		||||
            obj.sourceBox.destroy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        source.disconnect(obj.sourceDestroyId);
 | 
			
		||||
        source.disconnect(obj.sourceCountChangedId);
 | 
			
		||||
        source.disconnect(obj.sourceTitleChangedId);
 | 
			
		||||
        source.policy.disconnect(obj.policyChangedId);
 | 
			
		||||
 | 
			
		||||
        this._sources.delete(source);
 | 
			
		||||
        obj.item.disconnect(obj.contentUpdatedId);
 | 
			
		||||
        obj.source.disconnect(obj.sourceDestroyId);
 | 
			
		||||
        obj.source.disconnect(obj.sourceCountChangedId);
 | 
			
		||||
        obj.source.disconnect(obj.sourceTitleChangedId);
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@@ -435,7 +394,6 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
                                                reactive: true,
 | 
			
		||||
                                                can_focus: true,
 | 
			
		||||
                                                name: 'lockScreenGroup',
 | 
			
		||||
                                                visible: false,
 | 
			
		||||
                                              });
 | 
			
		||||
        this._lockScreenGroup.connect('key-release-event',
 | 
			
		||||
                                      Lang.bind(this, this._onLockScreenKeyRelease));
 | 
			
		||||
@@ -447,16 +405,16 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
                                                   name: 'lockScreenContents' });
 | 
			
		||||
        this._lockScreenContents.add_constraint(new Layout.MonitorConstraint({ primary: true }));
 | 
			
		||||
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
 | 
			
		||||
 | 
			
		||||
        let backgroundActor = new Meta.BackgroundActor({ screen: global.screen,
 | 
			
		||||
                                                         settings: this._settings });
 | 
			
		||||
        backgroundActor.add_glsl_snippet(Meta.SnippetHook.FRAGMENT,
 | 
			
		||||
                                         GLSL_EFFECT_DECLARATIONS,
 | 
			
		||||
                                         GLSL_EFFECT_CODE,
 | 
			
		||||
                                         false);
 | 
			
		||||
        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: backgroundActor });
 | 
			
		||||
@@ -509,36 +467,25 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
        this._loginManager = LoginManager.getLoginManager();
 | 
			
		||||
        this._loginSession = this._loginManager.getCurrentSessionProxy();
 | 
			
		||||
        this._loginSession.connectSignal('Lock', Lang.bind(this, function() { this.lock(false); }));
 | 
			
		||||
        this._loginSession.connectSignal('Unlock', Lang.bind(this, function() { this.deactivate(false); }));
 | 
			
		||||
        this._loginSession.connectSignal('Unlock', Lang.bind(this, function() { this.unlock(); }));
 | 
			
		||||
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
 | 
			
		||||
 | 
			
		||||
        this._isModal = false;
 | 
			
		||||
        this._hasLockScreen = false;
 | 
			
		||||
        this._isGreeter = false;
 | 
			
		||||
        this._isActive = false;
 | 
			
		||||
        this._isLocked = false;
 | 
			
		||||
        this._inUnlockAnimation = false;
 | 
			
		||||
        this._activationTime = 0;
 | 
			
		||||
        this._becameActiveId = 0;
 | 
			
		||||
        this._lockTimeoutId = 0;
 | 
			
		||||
 | 
			
		||||
        this._lightbox = new Lightbox.Lightbox(Main.uiGroup,
 | 
			
		||||
                                               { inhibitEvents: true,
 | 
			
		||||
                                                 fadeInTime: STANDARD_FADE_TIME,
 | 
			
		||||
                                                 fadeFactor: 1 });
 | 
			
		||||
        this._lightbox.connect('shown', Lang.bind(this, this._onLightboxShown));
 | 
			
		||||
 | 
			
		||||
        this.idleMonitor = new GnomeDesktop.IdleMonitor();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _liftShield: function(onPrimary, velocity) {
 | 
			
		||||
        if (this._isLocked) {
 | 
			
		||||
            this._ensureUnlockDialog(onPrimary, true /* allowCancel */);
 | 
			
		||||
            this._hideLockScreen(true /* animate */, velocity);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.deactivate(true /* animate */);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onLockScreenKeyRelease: function(actor, event) {
 | 
			
		||||
        let symbol = event.get_key_symbol();
 | 
			
		||||
 | 
			
		||||
@@ -556,7 +503,8 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
        if (symbol == Clutter.KEY_Escape ||
 | 
			
		||||
            symbol == Clutter.KEY_Return ||
 | 
			
		||||
            symbol == Clutter.KEY_KP_Enter) {
 | 
			
		||||
            this._liftShield(false, 0);
 | 
			
		||||
            this._ensureUnlockDialog(true, true);
 | 
			
		||||
            this._hideLockScreen(true, 0);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -578,7 +526,8 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        // 7 standard scrolls to lift up
 | 
			
		||||
        if (this._lockScreenScrollCounter > 35) {
 | 
			
		||||
            this._liftShield(true, 0);
 | 
			
		||||
            this._ensureUnlockDialog(false, true);
 | 
			
		||||
            this._hideLockScreen(true, 0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
@@ -609,9 +558,7 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
    _onDragBegin: function() {
 | 
			
		||||
        Tweener.removeTweens(this._lockScreenGroup);
 | 
			
		||||
        this._lockScreenState = MessageTray.State.HIDING;
 | 
			
		||||
 | 
			
		||||
        if (this._isLocked)
 | 
			
		||||
            this._ensureUnlockDialog(false, false);
 | 
			
		||||
        this._ensureUnlockDialog(false, false);
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    },
 | 
			
		||||
@@ -632,7 +579,8 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
        if (this._lockScreenGroup.y < -(ARROW_DRAG_THRESHOLD * global.stage.height)) {
 | 
			
		||||
            // Complete motion automatically
 | 
			
		||||
	    let [velocity, velocityX, velocityY] = this._dragAction.get_velocity(0);
 | 
			
		||||
            this._liftShield(true, -velocityY);
 | 
			
		||||
	    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
 | 
			
		||||
@@ -672,81 +620,35 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!this._isModal) {
 | 
			
		||||
            Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN });
 | 
			
		||||
            Main.pushModal(this.actor, { keybindingMode: Main.KeybindingMode.LOCK_SCREEN });
 | 
			
		||||
            this._isModal = true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        if (this._lightbox.actor.visible ||
 | 
			
		||||
            this._isActive) {
 | 
			
		||||
            // We're either shown and active, or in the process of
 | 
			
		||||
            // showing.
 | 
			
		||||
            // The latter is a very unlikely condition (it requires
 | 
			
		||||
            // idle-delay < 20), but in any case we have nothing
 | 
			
		||||
            // to do at this point: either isActive is true, or
 | 
			
		||||
            // it will soon be.
 | 
			
		||||
            // isActive can also be true if the lightbox is hidden,
 | 
			
		||||
            // in case the shield is down and the user hasn't unlocked yet
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._lightbox.show();
 | 
			
		||||
        if (!this._isActive) {
 | 
			
		||||
            this._lightbox.show();
 | 
			
		||||
 | 
			
		||||
        if (this._activationTime == 0)
 | 
			
		||||
            this._activationTime = GLib.get_monotonic_time();
 | 
			
		||||
            if (this._activationTime == 0)
 | 
			
		||||
                this._activationTime = GLib.get_monotonic_time();
 | 
			
		||||
 | 
			
		||||
        if (this._becameActiveId == 0)
 | 
			
		||||
            this._becameActiveId = this.idleMonitor.connect('became-active',
 | 
			
		||||
                                                            Lang.bind(this, this._onUserBecameActive));
 | 
			
		||||
            this._becameActiveId = this.idleMonitor.connect('became-active', Lang.bind(this, function() {
 | 
			
		||||
                this.idleMonitor.disconnect(this._becameActiveId);
 | 
			
		||||
 | 
			
		||||
        let shouldLock = this._settings.get_boolean(LOCK_ENABLED_KEY) && !this._isLocked;
 | 
			
		||||
                let lightboxWasShown = this._lightbox.shown;
 | 
			
		||||
                this._lightbox.hide();
 | 
			
		||||
 | 
			
		||||
        if (shouldLock) {
 | 
			
		||||
            let lockTimeout = Math.max(STANDARD_FADE_TIME, this._settings.get_uint(LOCK_DELAY_KEY));
 | 
			
		||||
            this._lockTimeoutId = Mainloop.timeout_add(lockTimeout * 1000,
 | 
			
		||||
                                                       Lang.bind(this, function() {
 | 
			
		||||
                                                           this._lockTimeoutId = 0;
 | 
			
		||||
                                                           this.lock(true);
 | 
			
		||||
                                                           return false;
 | 
			
		||||
                                                       }));
 | 
			
		||||
                let shouldLock = lightboxWasShown && this._settings.get_boolean(LOCK_ENABLED_KEY);
 | 
			
		||||
                if (shouldLock || this._isLocked) {
 | 
			
		||||
                    this.lock(false);
 | 
			
		||||
                } else if (this._isActive) {
 | 
			
		||||
                    this.unlock();
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
            this._isActive = true;
 | 
			
		||||
            this.emit('lock-status-changed');
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onUserBecameActive: function() {
 | 
			
		||||
        // This function gets called here when the user becomes active
 | 
			
		||||
        // after gnome-session changed the status to IDLE
 | 
			
		||||
        // There are four possibilities here:
 | 
			
		||||
        // - we're called when already locked; isActive and isLocked are true,
 | 
			
		||||
        //   we just go back to the lock screen curtain
 | 
			
		||||
        // - we're called before the lightbox is fully shown; at this point
 | 
			
		||||
        //   isActive is false, so we just hide the ligthbox, reset the activationTime
 | 
			
		||||
        //   and go back to the unlocked desktop
 | 
			
		||||
        // - we're called after showing the lightbox, but before the lock
 | 
			
		||||
        //   delay; this is mostly like the case above, but isActive is true now
 | 
			
		||||
        //   so we need to notify gnome-settings-daemon to go back to the normal
 | 
			
		||||
        //   policies for blanking
 | 
			
		||||
        //   (they're handled by the same code, and we emit one extra ActiveChanged
 | 
			
		||||
        //   signal in the case above)
 | 
			
		||||
        // - we're called after showing the lightbox and after lock-delay; the
 | 
			
		||||
        //   session is effectivelly locked now, it's time to build and show
 | 
			
		||||
        //   the lock screen
 | 
			
		||||
 | 
			
		||||
        this.idleMonitor.disconnect(this._becameActiveId);
 | 
			
		||||
        this._becameActiveId = 0;
 | 
			
		||||
 | 
			
		||||
        let lightboxWasShown = this._lightbox.shown;
 | 
			
		||||
        this._lightbox.hide();
 | 
			
		||||
 | 
			
		||||
        // Shortcircuit in case the mouse was moved before the fade completed
 | 
			
		||||
        if (!lightboxWasShown) {
 | 
			
		||||
            this.deactivate(false);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onLightboxShown: function() {
 | 
			
		||||
        this.activate(false);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    showDialog: function() {
 | 
			
		||||
        // Ensure that the stage window is mapped, before taking a grab
 | 
			
		||||
        // otherwise X errors out
 | 
			
		||||
@@ -761,7 +663,6 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
        this._isGreeter = Main.sessionMode.isGreeter;
 | 
			
		||||
        this._isLocked = true;
 | 
			
		||||
        this._ensureUnlockDialog(true, true);
 | 
			
		||||
        this._hideLockScreen(false, 0);
 | 
			
		||||
    },
 | 
			
		||||
@@ -782,9 +683,6 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hideLockScreen: function(animate, velocity) {
 | 
			
		||||
        if (this._lockScreenState == MessageTray.State.HIDDEN)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._lockScreenState = MessageTray.State.HIDING;
 | 
			
		||||
 | 
			
		||||
        if (animate) {
 | 
			
		||||
@@ -826,7 +724,7 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
            let constructor = Main.sessionMode.unlockDialog;
 | 
			
		||||
            if (!constructor) {
 | 
			
		||||
                // This session mode has no locking capabilities
 | 
			
		||||
                this.deactivate(true);
 | 
			
		||||
                this.unlock();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -836,10 +734,8 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
            let time = global.get_current_time();
 | 
			
		||||
            this._dialog.connect('loaded', Lang.bind(this, function() {
 | 
			
		||||
                if (!this._dialog.open(time, onPrimary)) {
 | 
			
		||||
                    // This is kind of an impossible error: we're already modal
 | 
			
		||||
                    // by the time we reach this...
 | 
			
		||||
                    log('Could not open login dialog: failed to acquire grab');
 | 
			
		||||
                    this.deactivate(true);
 | 
			
		||||
                    this.unlock();
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
@@ -855,17 +751,10 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onUnlockSucceded: function() {
 | 
			
		||||
        this.deactivate(true);
 | 
			
		||||
        this._tweenUnlocked();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _resetLockScreen: function(animateLockScreen, animateLockDialog) {
 | 
			
		||||
        // Don't reset the lock screen unless it is completely hidden
 | 
			
		||||
        // This prevents the shield going down if the lock-delay timeout
 | 
			
		||||
        // fires while the user is dragging (which has the potential
 | 
			
		||||
        // to confuse our state)
 | 
			
		||||
        if (this._lockScreenState != MessageTray.State.HIDDEN)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._ensureLockScreen();
 | 
			
		||||
        this._lockDialogGroup.scale_x = 1;
 | 
			
		||||
        this._lockDialogGroup.scale_y = 1;
 | 
			
		||||
@@ -932,12 +821,6 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
        this._lockScreenGroup.fixed_position_set = false;
 | 
			
		||||
        this._lockScreenScrollCounter = 0;
 | 
			
		||||
 | 
			
		||||
        let prevIsActive = this._isActive;
 | 
			
		||||
        this._isActive = true;
 | 
			
		||||
 | 
			
		||||
        if (prevIsActive != this._isActive)
 | 
			
		||||
            this.emit('active-changed');
 | 
			
		||||
 | 
			
		||||
        this.emit('lock-screen-shown');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -959,10 +842,12 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._lockScreenContents.add_actor(this._lockScreenContentsBox);
 | 
			
		||||
 | 
			
		||||
        this._notificationsBox = new NotificationsBox();
 | 
			
		||||
        this._lockScreenContentsBox.add(this._notificationsBox.actor, { x_fill: true,
 | 
			
		||||
                                                                        y_fill: true,
 | 
			
		||||
                                                                        expand: true });
 | 
			
		||||
        if (this._settings.get_boolean('show-notifications')) {
 | 
			
		||||
            this._notificationsBox = new NotificationsBox();
 | 
			
		||||
            this._lockScreenContentsBox.add(this._notificationsBox.actor, { x_fill: true,
 | 
			
		||||
                                                                            y_fill: true,
 | 
			
		||||
                                                                            expand: true });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._hasLockScreen = true;
 | 
			
		||||
    },
 | 
			
		||||
@@ -987,10 +872,6 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get locked() {
 | 
			
		||||
        return this._isLocked;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get active() {
 | 
			
		||||
        return this._isActive;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -998,20 +879,27 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
        return this._activationTime;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    deactivate: function(animate) {
 | 
			
		||||
        this._hideLockScreen(animate, 0);
 | 
			
		||||
 | 
			
		||||
    _tweenUnlocked: function() {
 | 
			
		||||
        this._inUnlockAnimation = true;
 | 
			
		||||
        this.unlock();
 | 
			
		||||
        Tweener.addTween(this._lockDialogGroup, {
 | 
			
		||||
            scale_x: 0,
 | 
			
		||||
            scale_y: 0,
 | 
			
		||||
            time: animate ? Overview.ANIMATION_TIME : 0,
 | 
			
		||||
            time: Overview.ANIMATION_TIME,
 | 
			
		||||
            transition: 'easeOutQuad',
 | 
			
		||||
            onComplete: Lang.bind(this, this._completeDeactivate),
 | 
			
		||||
            onComplete: function() {
 | 
			
		||||
                if (this._dialog) {
 | 
			
		||||
                    this._dialog.destroy();
 | 
			
		||||
                    this._dialog = null;
 | 
			
		||||
                }
 | 
			
		||||
                this.actor.hide();
 | 
			
		||||
                this._inUnlockAnimation = false;
 | 
			
		||||
            },
 | 
			
		||||
            onCompleteScope: this
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _completeDeactivate: function() {
 | 
			
		||||
    unlock: function() {
 | 
			
		||||
        if (this._hasLockScreen)
 | 
			
		||||
            this._clearLockScreen();
 | 
			
		||||
 | 
			
		||||
@@ -1027,31 +915,26 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
            this._isModal = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.actor.hide();
 | 
			
		||||
        if (!this._inUnlockAnimation)
 | 
			
		||||
            this.actor.hide();
 | 
			
		||||
 | 
			
		||||
        if (Main.sessionMode.currentMode == 'lock-screen')
 | 
			
		||||
            Main.sessionMode.popMode('lock-screen');
 | 
			
		||||
        if (Main.sessionMode.currentMode == 'unlock-dialog')
 | 
			
		||||
            Main.sessionMode.popMode('unlock-dialog');
 | 
			
		||||
 | 
			
		||||
        if (this._becameActiveId != 0) {
 | 
			
		||||
            this.idleMonitor.disconnect(this._becameActiveId);
 | 
			
		||||
            this._becameActiveId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._lockTimeoutId != 0) {
 | 
			
		||||
            Mainloop.source_remove(this._lockTimeoutId);
 | 
			
		||||
            this._lockTimeoutId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._activationTime = 0;
 | 
			
		||||
        this._isActive = false;
 | 
			
		||||
        this._isLocked = false;
 | 
			
		||||
        this.emit('active-changed');
 | 
			
		||||
        this.emit('locked-changed');
 | 
			
		||||
        this.emit('lock-status-changed');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    activate: function(animate) {
 | 
			
		||||
    lock: function(animate) {
 | 
			
		||||
        if (!this._isModal) {
 | 
			
		||||
            Main.pushModal(this.actor, { keybindingMode: Main.KeybindingMode.LOCK_SCREEN });
 | 
			
		||||
            this._isModal = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._activationTime == 0)
 | 
			
		||||
            this._activationTime = GLib.get_monotonic_time();
 | 
			
		||||
 | 
			
		||||
@@ -1066,28 +949,9 @@ const ScreenShield = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._resetLockScreen(animate, animate);
 | 
			
		||||
 | 
			
		||||
        // We used to set isActive and emit active-changed here,
 | 
			
		||||
        // but now we do that from lockScreenShown, which means
 | 
			
		||||
        // there is a 0.3 seconds window during which the lock
 | 
			
		||||
        // screen is effectively visible and the screen is locked, but
 | 
			
		||||
        // the DBus interface reports the screensaver is off.
 | 
			
		||||
        // This is because when we emit ActiveChanged(true),
 | 
			
		||||
        // gnome-settings-daemon blanks the screen, and we don't want
 | 
			
		||||
        // blank during the animation.
 | 
			
		||||
        // This is not a problem for the idle fade case, because we
 | 
			
		||||
        // activate without animation in that case.
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    lock: function(animate) {
 | 
			
		||||
        if (!this._isModal) {
 | 
			
		||||
            Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOCK_SCREEN });
 | 
			
		||||
            this._isModal = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._isActive = true;
 | 
			
		||||
        this._isLocked = true;
 | 
			
		||||
        this.activate(animate);
 | 
			
		||||
 | 
			
		||||
        this.emit('locked-changed');
 | 
			
		||||
        this.emit('lock-status-changed');
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(ScreenShield.prototype);
 | 
			
		||||
@@ -1121,13 +985,13 @@ const ScreenShieldFallback = new Lang.Class({
 | 
			
		||||
        else
 | 
			
		||||
            this._locked = false;
 | 
			
		||||
 | 
			
		||||
        this.emit('active-changed', this._locked);
 | 
			
		||||
        this.emit('lock-status-changed', this._locked);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onSignal: function(proxy, senderName, signalName, params) {
 | 
			
		||||
        if (signalName == 'ActiveChanged') {
 | 
			
		||||
            [this._locked] = params.deep_unpack();
 | 
			
		||||
            this.emit('active-changed', this._locked);
 | 
			
		||||
            this.emit('lock-status-changed', this._locked);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,272 +0,0 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gdk = imports.gi.Gdk;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Gtk = imports.gi.Gtk;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Lightbox = imports.ui.lightbox;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
 | 
			
		||||
const ScreenshotIface = <interface name="org.gnome.Shell.Screenshot">
 | 
			
		||||
<method name="ScreenshotArea">
 | 
			
		||||
    <arg type="i" direction="in" name="x"/>
 | 
			
		||||
    <arg type="i" direction="in" name="y"/>
 | 
			
		||||
    <arg type="i" direction="in" name="width"/>
 | 
			
		||||
    <arg type="i" direction="in" name="height"/>
 | 
			
		||||
    <arg type="b" direction="in" name="flash"/>
 | 
			
		||||
    <arg type="s" direction="in" name="filename"/>
 | 
			
		||||
    <arg type="b" direction="out" name="success"/>
 | 
			
		||||
    <arg type="s" direction="out" name="filename_used"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="ScreenshotWindow">
 | 
			
		||||
    <arg type="b" direction="in" name="include_frame"/>
 | 
			
		||||
    <arg type="b" direction="in" name="include_cursor"/>
 | 
			
		||||
    <arg type="b" direction="in" name="flash"/>
 | 
			
		||||
    <arg type="s" direction="in" name="filename"/>
 | 
			
		||||
    <arg type="b" direction="out" name="success"/>
 | 
			
		||||
    <arg type="s" direction="out" name="filename_used"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="Screenshot">
 | 
			
		||||
    <arg type="b" direction="in" name="include_cursor"/>
 | 
			
		||||
    <arg type="b" direction="in" name="flash"/>
 | 
			
		||||
    <arg type="s" direction="in" name="filename"/>
 | 
			
		||||
    <arg type="b" direction="out" name="success"/>
 | 
			
		||||
    <arg type="s" direction="out" name="filename_used"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="SelectArea">
 | 
			
		||||
    <arg type="i" direction="out" name="x"/>
 | 
			
		||||
    <arg type="i" direction="out" name="y"/>
 | 
			
		||||
    <arg type="i" direction="out" name="width"/>
 | 
			
		||||
    <arg type="i" direction="out" name="height"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="FlashArea">
 | 
			
		||||
    <arg type="i" direction="in" name="x"/>
 | 
			
		||||
    <arg type="i" direction="in" name="y"/>
 | 
			
		||||
    <arg type="i" direction="in" name="width"/>
 | 
			
		||||
    <arg type="i" direction="in" name="height"/>
 | 
			
		||||
</method>
 | 
			
		||||
</interface>;
 | 
			
		||||
 | 
			
		||||
const ScreenshotService = new Lang.Class({
 | 
			
		||||
    Name: 'ScreenshotService',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreenshotIface, this);
 | 
			
		||||
        this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/Screenshot');
 | 
			
		||||
 | 
			
		||||
        Gio.DBus.session.own_name('org.gnome.Shell.Screenshot', Gio.BusNameOwnerFlags.REPLACE, null, null);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onScreenshotComplete: function(obj, result, area, filenameUsed, flash, invocation) {
 | 
			
		||||
        if (flash && result) {
 | 
			
		||||
            let flashspot = new Flashspot(area);
 | 
			
		||||
            flashspot.fire();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let retval = GLib.Variant.new('(bs)', [result, filenameUsed]);
 | 
			
		||||
        invocation.return_value(retval);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    ScreenshotAreaAsync : function (params, invocation) {
 | 
			
		||||
        let [x, y, width, height, flash, filename, callback] = params;
 | 
			
		||||
        let screenshot = new Shell.Screenshot();
 | 
			
		||||
        screenshot.screenshot_area (x, y, width, height, filename,
 | 
			
		||||
                                Lang.bind(this, this._onScreenshotComplete,
 | 
			
		||||
                                          flash, invocation));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    ScreenshotWindowAsync : function (params, invocation) {
 | 
			
		||||
        let [include_frame, include_cursor, flash, filename] = params;
 | 
			
		||||
        let screenshot = new Shell.Screenshot();
 | 
			
		||||
        screenshot.screenshot_window (include_frame, include_cursor, filename,
 | 
			
		||||
                                  Lang.bind(this, this._onScreenshotComplete,
 | 
			
		||||
                                            flash, invocation));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    ScreenshotAsync : function (params, invocation) {
 | 
			
		||||
        let [include_cursor, flash, filename] = params;
 | 
			
		||||
        let screenshot = new Shell.Screenshot();
 | 
			
		||||
        screenshot.screenshot(include_cursor, filename,
 | 
			
		||||
                          Lang.bind(this, this._onScreenshotComplete,
 | 
			
		||||
                                    flash, invocation));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    SelectAreaAsync: function (params, invocation) {
 | 
			
		||||
        let selectArea = new SelectArea();
 | 
			
		||||
        selectArea.show();
 | 
			
		||||
        selectArea.connect('finished', Lang.bind(this,
 | 
			
		||||
            function(selectArea, areaRectangle) {
 | 
			
		||||
                if (areaRectangle) {
 | 
			
		||||
                    let retval = GLib.Variant.new('(iiii)',
 | 
			
		||||
                        [areaRectangle.x, areaRectangle.y,
 | 
			
		||||
                         areaRectangle.width, areaRectangle.height]);
 | 
			
		||||
                    invocation.return_value(retval);
 | 
			
		||||
                } else {
 | 
			
		||||
                    invocation.return_error_literal(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,
 | 
			
		||||
                        "Operation was cancelled");
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    FlashArea: function(x, y, width, height) {
 | 
			
		||||
        let flashspot = new Flashspot({ x : x, y : y, width: width, height: height});
 | 
			
		||||
        flashspot.fire();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const SelectArea = new Lang.Class({
 | 
			
		||||
    Name: 'SelectArea',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._startX = -1;
 | 
			
		||||
        this._startY = -1;
 | 
			
		||||
        this._lastX = 0;
 | 
			
		||||
        this._lastY = 0;
 | 
			
		||||
 | 
			
		||||
        this._initRubberbandColors();
 | 
			
		||||
 | 
			
		||||
        this._group = new St.Widget({ visible: false,
 | 
			
		||||
                                      reactive: true,
 | 
			
		||||
                                      x: 0,
 | 
			
		||||
                                      y: 0 });
 | 
			
		||||
        Main.uiGroup.add_actor(this._group);
 | 
			
		||||
 | 
			
		||||
        this._group.connect('button-press-event',
 | 
			
		||||
                            Lang.bind(this, this._onButtonPress));
 | 
			
		||||
        this._group.connect('button-release-event',
 | 
			
		||||
                            Lang.bind(this, this._onButtonRelease));
 | 
			
		||||
        this._group.connect('key-press-event',
 | 
			
		||||
                            Lang.bind(this, this._onKeyPress));
 | 
			
		||||
        this._group.connect('motion-event',
 | 
			
		||||
                            Lang.bind(this, this._onMotionEvent));
 | 
			
		||||
 | 
			
		||||
        let constraint = new Clutter.BindConstraint({ source: global.stage,
 | 
			
		||||
                                                      coordinate: Clutter.BindCoordinate.ALL });
 | 
			
		||||
        this._group.add_constraint(constraint);
 | 
			
		||||
 | 
			
		||||
        this._rubberband = new Clutter.Rectangle({ color: this._background,
 | 
			
		||||
                                                   has_border: true,
 | 
			
		||||
                                                   border_width: 1,
 | 
			
		||||
                                                   border_color: this._border });
 | 
			
		||||
        this._group.add_actor(this._rubberband);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    show: function() {
 | 
			
		||||
        if (!Main.pushModal(this._group) || this._group.visible)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        global.set_cursor(Shell.Cursor.CROSSHAIR);
 | 
			
		||||
        this._group.visible = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _initRubberbandColors: function() {
 | 
			
		||||
        function colorFromRGBA(rgba) {
 | 
			
		||||
            return new Clutter.Color({ red: rgba.red * 255,
 | 
			
		||||
                                       green: rgba.green * 255,
 | 
			
		||||
                                       blue: rgba.blue * 255,
 | 
			
		||||
                                       alpha: rgba.alpha * 255 });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let path = new Gtk.WidgetPath();
 | 
			
		||||
        path.append_type(Gtk.IconView);
 | 
			
		||||
 | 
			
		||||
        let context = new Gtk.StyleContext();
 | 
			
		||||
        context.set_path(path);
 | 
			
		||||
        context.add_class('rubberband');
 | 
			
		||||
 | 
			
		||||
        this._background = colorFromRGBA(context.get_background_color(Gtk.StateFlags.NORMAL));
 | 
			
		||||
        this._border = colorFromRGBA(context.get_border_color(Gtk.StateFlags.NORMAL));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getGeometry: function() {
 | 
			
		||||
        return { x: Math.min(this._startX, this._lastX),
 | 
			
		||||
                 y: Math.min(this._startY, this._lastY),
 | 
			
		||||
                 width: Math.abs(this._startX - this._lastX),
 | 
			
		||||
                 height: Math.abs(this._startY - this._lastY) };
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyPress: function(actor, event) {
 | 
			
		||||
        if (event.get_key_symbol() == Clutter.Escape)
 | 
			
		||||
            this._destroy(null, false);
 | 
			
		||||
 | 
			
		||||
        return;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onMotionEvent: function(actor, event) {
 | 
			
		||||
        if (this._startX == -1 || this._startY == -1)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        [this._lastX, this._lastY] = event.get_coords();
 | 
			
		||||
        let geometry = this._getGeometry();
 | 
			
		||||
 | 
			
		||||
        this._rubberband.set_position(geometry.x, geometry.y);
 | 
			
		||||
        this._rubberband.set_size(geometry.width, geometry.height);
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onButtonPress: function(actor, event) {
 | 
			
		||||
        [this._startX, this._startY] = event.get_coords();
 | 
			
		||||
        this._rubberband.set_position(this._startX, this._startY);
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onButtonRelease: function(actor, event) {
 | 
			
		||||
        this._destroy(this._getGeometry(), true);
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _destroy: function(geometry, fade) {
 | 
			
		||||
        Tweener.addTween(this._group,
 | 
			
		||||
                         { opacity: 0,
 | 
			
		||||
                           time: fade ? 0.2 : 0,
 | 
			
		||||
                           transition: 'easeOutQuad',
 | 
			
		||||
                           onComplete: Lang.bind(this,
 | 
			
		||||
                               function() {
 | 
			
		||||
                                   Main.popModal(this._group);
 | 
			
		||||
                                   this._group.destroy();
 | 
			
		||||
                                   global.unset_cursor();
 | 
			
		||||
 | 
			
		||||
                                   this.emit('finished', geometry);
 | 
			
		||||
                               })
 | 
			
		||||
                         });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(SelectArea.prototype);
 | 
			
		||||
 | 
			
		||||
const FLASHSPOT_ANIMATION_OUT_TIME = 0.5; // seconds
 | 
			
		||||
 | 
			
		||||
const Flashspot = new Lang.Class({
 | 
			
		||||
    Name: 'Flashspot',
 | 
			
		||||
    Extends: Lightbox.Lightbox,
 | 
			
		||||
 | 
			
		||||
    _init: function(area) {
 | 
			
		||||
        this.parent(Main.uiGroup, { inhibitEvents: true,
 | 
			
		||||
                                    width: area.width,
 | 
			
		||||
                                    height: area.height });
 | 
			
		||||
 | 
			
		||||
        this.actor.style_class = 'flashspot';
 | 
			
		||||
        this.actor.set_position(area.x, area.y);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    fire: function() {
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
        this.actor.opacity = 255;
 | 
			
		||||
        Tweener.addTween(this.actor,
 | 
			
		||||
                         { opacity: 0,
 | 
			
		||||
                           time: FLASHSPOT_ANIMATION_OUT_TIME,
 | 
			
		||||
                           transition: 'easeOutQuad',
 | 
			
		||||
                           onComplete: Lang.bind(this, function() {
 | 
			
		||||
                               this.destroy();
 | 
			
		||||
                           })
 | 
			
		||||
                         });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -17,26 +17,6 @@ const Search = imports.ui.search;
 | 
			
		||||
const MAX_LIST_SEARCH_RESULTS_ROWS = 3;
 | 
			
		||||
const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
 | 
			
		||||
 | 
			
		||||
const MaxWidthBin = new Lang.Class({
 | 
			
		||||
    Name: 'MaxWidthBin',
 | 
			
		||||
    Extends: St.Bin,
 | 
			
		||||
 | 
			
		||||
    vfunc_allocate: function(box, flags) {
 | 
			
		||||
        let themeNode = this.get_theme_node();
 | 
			
		||||
        let maxWidth = themeNode.get_max_width();
 | 
			
		||||
        let availWidth = box.x2 - box.x1;
 | 
			
		||||
        let adjustedBox = box;
 | 
			
		||||
 | 
			
		||||
        if (availWidth > maxWidth) {
 | 
			
		||||
            let excessWidth = availWidth - maxWidth;
 | 
			
		||||
            adjustedBox.x1 += Math.floor(excessWidth / 2);
 | 
			
		||||
            adjustedBox.x2 -= Math.floor(excessWidth / 2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.parent(adjustedBox, flags);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const SearchResult = new Lang.Class({
 | 
			
		||||
    Name: 'SearchResult',
 | 
			
		||||
 | 
			
		||||
@@ -198,7 +178,7 @@ const ListSearchResults = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._content = new St.BoxLayout({ style_class: 'list-search-results',
 | 
			
		||||
                                           vertical: true });
 | 
			
		||||
        this.actor.add(this._content, { expand: true });
 | 
			
		||||
        this.actor.add_actor(this._content);
 | 
			
		||||
 | 
			
		||||
        this._notDisplayedResult = [];
 | 
			
		||||
        this._terms = [];
 | 
			
		||||
@@ -321,19 +301,12 @@ const SearchResults = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._content = new St.BoxLayout({ name: 'searchResultsContent',
 | 
			
		||||
                                           vertical: true });
 | 
			
		||||
        this._contentBin = new MaxWidthBin({ name: 'searchResultsBin',
 | 
			
		||||
                                             x_fill: true,
 | 
			
		||||
                                             y_fill: true,
 | 
			
		||||
                                             child: this._content });
 | 
			
		||||
 | 
			
		||||
        let scrollChild = new St.BoxLayout();
 | 
			
		||||
        scrollChild.add(this._contentBin, { expand: true });
 | 
			
		||||
 | 
			
		||||
        this._scrollView = new St.ScrollView({ x_fill: true,
 | 
			
		||||
                                               y_fill: false,
 | 
			
		||||
                                               style_class: 'vfade' });
 | 
			
		||||
        this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
 | 
			
		||||
        this._scrollView.add_actor(scrollChild);
 | 
			
		||||
        this._scrollView.add_actor(this._content);
 | 
			
		||||
        let action = new Clutter.PanAction({ interpolate: true });
 | 
			
		||||
        action.connect('pan', Lang.bind(this, this._onPan));
 | 
			
		||||
        this._scrollView.add_action(action);
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,5 @@ const HorizontalSeparator = new Lang.Class({
 | 
			
		||||
        cr.setSource(pattern);
 | 
			
		||||
        cr.rectangle(margin, gradientOffset, gradientWidth, gradientHeight);
 | 
			
		||||
        cr.fill();
 | 
			
		||||
        cr.$dispose();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -9,8 +9,8 @@ const Config = imports.misc.config;
 | 
			
		||||
const ExtensionSystem = imports.ui.extensionSystem;
 | 
			
		||||
const ExtensionDownloader = imports.ui.extensionDownloader;
 | 
			
		||||
const ExtensionUtils = imports.misc.extensionUtils;
 | 
			
		||||
const Flashspot = imports.ui.flashspot;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Screenshot = imports.ui.screenshot;
 | 
			
		||||
 | 
			
		||||
const GnomeShellIface = <interface name="org.gnome.Shell">
 | 
			
		||||
<method name="Eval">
 | 
			
		||||
@@ -18,6 +18,34 @@ const GnomeShellIface = <interface name="org.gnome.Shell">
 | 
			
		||||
    <arg type="b" direction="out" name="success" />
 | 
			
		||||
    <arg type="s" direction="out" name="result" />
 | 
			
		||||
</method>
 | 
			
		||||
<method name="ScreenshotArea">
 | 
			
		||||
    <arg type="i" direction="in" name="x"/>
 | 
			
		||||
    <arg type="i" direction="in" name="y"/>
 | 
			
		||||
    <arg type="i" direction="in" name="width"/>
 | 
			
		||||
    <arg type="i" direction="in" name="height"/>
 | 
			
		||||
    <arg type="b" direction="in" name="flash"/>
 | 
			
		||||
    <arg type="s" direction="in" name="filename"/>
 | 
			
		||||
    <arg type="b" direction="out" name="success"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="ScreenshotWindow">
 | 
			
		||||
    <arg type="b" direction="in" name="include_frame"/>
 | 
			
		||||
    <arg type="b" direction="in" name="include_cursor"/>
 | 
			
		||||
    <arg type="b" direction="in" name="flash"/>
 | 
			
		||||
    <arg type="s" direction="in" name="filename"/>
 | 
			
		||||
    <arg type="b" direction="out" name="success"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="Screenshot">
 | 
			
		||||
    <arg type="b" direction="in" name="include_cursor"/>
 | 
			
		||||
    <arg type="b" direction="in" name="flash"/>
 | 
			
		||||
    <arg type="s" direction="in" name="filename"/>
 | 
			
		||||
    <arg type="b" direction="out" name="success"/>
 | 
			
		||||
</method>
 | 
			
		||||
<method name="FlashArea">
 | 
			
		||||
    <arg type="i" direction="in" name="x"/>
 | 
			
		||||
    <arg type="i" direction="in" name="y"/>
 | 
			
		||||
    <arg type="i" direction="in" name="width"/>
 | 
			
		||||
    <arg type="i" direction="in" name="height"/>
 | 
			
		||||
</method>
 | 
			
		||||
<property name="Mode" type="s" access="read" />
 | 
			
		||||
<property name="OverviewActive" type="b" access="readwrite" />
 | 
			
		||||
<property name="ShellVersion" type="s" access="read" />
 | 
			
		||||
@@ -48,7 +76,6 @@ const GnomeShell = new Lang.Class({
 | 
			
		||||
        this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
 | 
			
		||||
 | 
			
		||||
        this._extensionsSerivce = new GnomeShellExtensions();
 | 
			
		||||
        this._screenshotService = new Screenshot.ScreenshotService();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -84,6 +111,82 @@ const GnomeShell = new Lang.Class({
 | 
			
		||||
        return [success, returnValue];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onScreenshotComplete: function(obj, result, area, flash, invocation) {
 | 
			
		||||
        if (flash && result) {
 | 
			
		||||
            let flashspot = new Flashspot.Flashspot(area);
 | 
			
		||||
            flashspot.fire();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let retval = GLib.Variant.new('(b)', [result]);
 | 
			
		||||
        invocation.return_value(retval);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * ScreenshotArea:
 | 
			
		||||
     * @x: The X coordinate of the area
 | 
			
		||||
     * @y: The Y coordinate of the area
 | 
			
		||||
     * @width: The width of the area
 | 
			
		||||
     * @height: The height of the area
 | 
			
		||||
     * @flash: Whether to flash the area or not
 | 
			
		||||
     * @filename: The filename for the screenshot
 | 
			
		||||
     *
 | 
			
		||||
     * Takes a screenshot of the passed in area and saves it
 | 
			
		||||
     * in @filename as png image, it returns a boolean
 | 
			
		||||
     * indicating whether the operation was successful or not.
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    ScreenshotAreaAsync : function (params, invocation) {
 | 
			
		||||
        let [x, y, width, height, flash, filename, callback] = params;
 | 
			
		||||
        let screenshot = new Shell.Screenshot();
 | 
			
		||||
        screenshot.screenshot_area (x, y, width, height, filename,
 | 
			
		||||
                                Lang.bind(this, this._onScreenshotComplete,
 | 
			
		||||
                                          flash, invocation));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * ScreenshotWindow:
 | 
			
		||||
     * @include_frame: Whether to include the frame or not
 | 
			
		||||
     * @include_cursor: Whether to include the cursor image or not
 | 
			
		||||
     * @flash: Whether to flash the window area or not
 | 
			
		||||
     * @filename: The filename for the screenshot
 | 
			
		||||
     *
 | 
			
		||||
     * Takes a screenshot of the focused window (optionally omitting the frame)
 | 
			
		||||
     * and saves it in @filename as png image, it returns a boolean
 | 
			
		||||
     * indicating whether the operation was successful or not.
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    ScreenshotWindowAsync : function (params, invocation) {
 | 
			
		||||
        let [include_frame, include_cursor, flash, filename] = params;
 | 
			
		||||
        let screenshot = new Shell.Screenshot();
 | 
			
		||||
        screenshot.screenshot_window (include_frame, include_cursor, filename,
 | 
			
		||||
                                  Lang.bind(this, this._onScreenshotComplete,
 | 
			
		||||
                                            flash, invocation));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Screenshot:
 | 
			
		||||
     * @filename: The filename for the screenshot
 | 
			
		||||
     * @include_cursor: Whether to include the cursor image or not
 | 
			
		||||
     * @flash: Whether to flash the screen or not
 | 
			
		||||
     *
 | 
			
		||||
     * Takes a screenshot of the whole screen and saves it
 | 
			
		||||
     * in @filename as png image, it returns a boolean
 | 
			
		||||
     * indicating whether the operation was successful or not.
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    ScreenshotAsync : function (params, invocation) {
 | 
			
		||||
        let [include_cursor, flash, filename] = params;
 | 
			
		||||
        let screenshot = new Shell.Screenshot();
 | 
			
		||||
        screenshot.screenshot(include_cursor, filename,
 | 
			
		||||
                          Lang.bind(this, this._onScreenshotComplete,
 | 
			
		||||
                                    flash, invocation));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    FlashArea: function(x, y, width, height) {
 | 
			
		||||
        let flashspot = new Flashspot.Flashspot({ x : x, y : y, width: width, height: height});
 | 
			
		||||
        flashspot.fire();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    Mode: global.session_mode,
 | 
			
		||||
 | 
			
		||||
    get OverviewActive() {
 | 
			
		||||
@@ -247,8 +350,8 @@ const ScreenSaverDBus = new Lang.Class({
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        this._screenShield = screenShield;
 | 
			
		||||
        screenShield.connect('active-changed', Lang.bind(this, function(shield) {
 | 
			
		||||
            this._dbusImpl.emit_signal('ActiveChanged', GLib.Variant.new('(b)', [shield.active]));
 | 
			
		||||
        screenShield.connect('lock-status-changed', Lang.bind(this, function(shield) {
 | 
			
		||||
            this._dbusImpl.emit_signal('ActiveChanged', GLib.Variant.new('(b)', [shield.locked]));
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreenSaverIface, this);
 | 
			
		||||
@@ -269,13 +372,13 @@ const ScreenSaverDBus = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    SetActive: function(active) {
 | 
			
		||||
        if (active)
 | 
			
		||||
            this._screenShield.activate(true);
 | 
			
		||||
            this._screenShield.lock(true);
 | 
			
		||||
        else
 | 
			
		||||
            this._screenShield.unlock(false);
 | 
			
		||||
            this._screenShield.unlock();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    GetActive: function() {
 | 
			
		||||
        return this._screenShield.active;
 | 
			
		||||
        return this._screenShield.locked;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    GetActiveTime: function() {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@ const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
const NotificationDaemon = imports.ui.notificationDaemon;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
 | 
			
		||||
@@ -287,7 +286,6 @@ const Indicator = new Lang.Class({
 | 
			
		||||
    _ensureSource: function() {
 | 
			
		||||
        if (!this._source) {
 | 
			
		||||
            this._source = new MessageTray.Source(_("Bluetooth"), 'bluetooth-active');
 | 
			
		||||
            this._source.policy = new NotificationDaemon.NotificationApplicationPolicy('gnome-bluetooth-panel');
 | 
			
		||||
            Main.messageTray.add(this._source);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
@@ -448,5 +446,10 @@ const PinNotification = new Lang.Class({
 | 
			
		||||
            return this._entry.clutter_text.text.length == 6;
 | 
			
		||||
        else
 | 
			
		||||
            return true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    grabFocus: function(lockTray) {
 | 
			
		||||
        this.parent(lockTray);
 | 
			
		||||
        global.stage.set_key_focus(this._entry);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -115,14 +115,9 @@ const IBusManager = new Lang.Class({
 | 
			
		||||
            this._panelService.connect('update-property', Lang.bind(this, this._updateProperty));
 | 
			
		||||
            // If an engine is already active we need to get its properties
 | 
			
		||||
            this._ibus.get_global_engine_async(-1, null, Lang.bind(this, function(i, result) {
 | 
			
		||||
                let engine;
 | 
			
		||||
                try {
 | 
			
		||||
                    engine = this._ibus.get_global_engine_async_finish(result);
 | 
			
		||||
                    if (!engine)
 | 
			
		||||
                        return;
 | 
			
		||||
                } catch(e) {
 | 
			
		||||
                let engine = this._ibus.get_global_engine_async_finish(result);
 | 
			
		||||
                if (!engine)
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                this._engineChanged(this._ibus, engine.get_name());
 | 
			
		||||
            }));
 | 
			
		||||
            this._updateReadiness();
 | 
			
		||||
@@ -337,14 +332,14 @@ const InputSourceIndicator = new Lang.Class({
 | 
			
		||||
            Main.wm.addKeybinding('switch-input-source',
 | 
			
		||||
                                  new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }),
 | 
			
		||||
                                  Meta.KeyBindingFlags.REVERSES,
 | 
			
		||||
                                  Shell.KeyBindingMode.ALL,
 | 
			
		||||
                                  Main.KeybindingMode.ALL,
 | 
			
		||||
                                  Lang.bind(this, this._switchInputSource));
 | 
			
		||||
        this._keybindingActionBackward =
 | 
			
		||||
            Main.wm.addKeybinding('switch-input-source-backward',
 | 
			
		||||
                                  new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }),
 | 
			
		||||
                                  Meta.KeyBindingFlags.REVERSES |
 | 
			
		||||
                                  Meta.KeyBindingFlags.REVERSED,
 | 
			
		||||
                                  Shell.KeyBindingMode.ALL,
 | 
			
		||||
                                  Main.KeybindingMode.ALL,
 | 
			
		||||
                                  Lang.bind(this, this._switchInputSource));
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_SCHEMA });
 | 
			
		||||
        this._settings.connect('changed::' + KEY_CURRENT_INPUT_SOURCE, Lang.bind(this, this._currentInputSourceChanged));
 | 
			
		||||
@@ -371,13 +366,6 @@ const InputSourceIndicator = new Lang.Class({
 | 
			
		||||
        this._sessionUpdated();
 | 
			
		||||
 | 
			
		||||
        this.menu.addSettingsAction(_("Region and Language Settings"), 'gnome-region-panel.desktop');
 | 
			
		||||
 | 
			
		||||
        this._sourcesPerWindow = false;
 | 
			
		||||
        this._focusWindowNotifyId = 0;
 | 
			
		||||
        this._overviewShowingId = 0;
 | 
			
		||||
        this._overviewHiddenId = 0;
 | 
			
		||||
        this._settings.connect('changed::per-window', Lang.bind(this, this._sourcesPerWindowChanged));
 | 
			
		||||
        this._sourcesPerWindowChanged();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _sessionUpdated: function() {
 | 
			
		||||
@@ -443,8 +431,6 @@ const InputSourceIndicator = new Lang.Class({
 | 
			
		||||
                this._mruSources = currentSource.concat(this._mruSources);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        this._changePerWindowSource();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _inputSourcesChanged: function() {
 | 
			
		||||
@@ -484,8 +470,6 @@ const InputSourceIndicator = new Lang.Class({
 | 
			
		||||
            let is = new InputSource(type, id, displayName, shortName, i);
 | 
			
		||||
 | 
			
		||||
            is.connect('activate', Lang.bind(this, function() {
 | 
			
		||||
                if (this._currentSource.index == is.index)
 | 
			
		||||
                    return;
 | 
			
		||||
                this._settings.set_value(KEY_CURRENT_INPUT_SOURCE,
 | 
			
		||||
                                         GLib.Variant.new_uint32(is.index));
 | 
			
		||||
            }));
 | 
			
		||||
@@ -718,82 +702,6 @@ const InputSourceIndicator = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getNewInputSource: function(current) {
 | 
			
		||||
        for (let i in this._inputSources) {
 | 
			
		||||
            let is = this._inputSources[i];
 | 
			
		||||
            if (is.type == current.type &&
 | 
			
		||||
                is.id == current.id)
 | 
			
		||||
                return is;
 | 
			
		||||
        }
 | 
			
		||||
        return this._currentSource;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getCurrentWindow: function() {
 | 
			
		||||
        if (Main.overview.visible)
 | 
			
		||||
            return Main.overview;
 | 
			
		||||
        else
 | 
			
		||||
            return global.display.focus_window;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setPerWindowInputSource: function() {
 | 
			
		||||
        let window = this._getCurrentWindow();
 | 
			
		||||
        if (!window)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (!window._inputSources) {
 | 
			
		||||
            window._inputSources = this._inputSources;
 | 
			
		||||
            window._currentSource = this._currentSource;
 | 
			
		||||
        } else if (window._inputSources == this._inputSources) {
 | 
			
		||||
            window._currentSource.activate();
 | 
			
		||||
        } else {
 | 
			
		||||
            window._inputSources = this._inputSources;
 | 
			
		||||
            window._currentSource = this._getNewInputSource(window._currentSource);
 | 
			
		||||
            window._currentSource.activate();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _sourcesPerWindowChanged: function() {
 | 
			
		||||
        this._sourcesPerWindow = this._settings.get_boolean('per-window');
 | 
			
		||||
 | 
			
		||||
        if (this._sourcesPerWindow && this._focusWindowNotifyId == 0) {
 | 
			
		||||
            this._focusWindowNotifyId = global.display.connect('notify::focus-window',
 | 
			
		||||
                                                               Lang.bind(this, this._setPerWindowInputSource));
 | 
			
		||||
            this._overviewShowingId = Main.overview.connect('showing',
 | 
			
		||||
                                                            Lang.bind(this, this._setPerWindowInputSource));
 | 
			
		||||
            this._overviewHiddenId = Main.overview.connect('hidden',
 | 
			
		||||
                                                           Lang.bind(this, this._setPerWindowInputSource));
 | 
			
		||||
        } else if (!this._sourcesPerWindow && this._focusWindowNotifyId != 0) {
 | 
			
		||||
            global.display.disconnect(this._focusWindowNotifyId);
 | 
			
		||||
            this._focusWindowNotifyId = 0;
 | 
			
		||||
            Main.overview.disconnect(this._overviewShowingId);
 | 
			
		||||
            this._overviewShowingId = 0;
 | 
			
		||||
            Main.overview.disconnect(this._overviewHiddenId);
 | 
			
		||||
            this._overviewHiddenId = 0;
 | 
			
		||||
 | 
			
		||||
            let windows = global.get_window_actors().map(function(w) {
 | 
			
		||||
                return w.meta_window;
 | 
			
		||||
            });
 | 
			
		||||
            for (let i = 0; i < windows.length; ++i) {
 | 
			
		||||
                delete windows[i]._inputSources;
 | 
			
		||||
                delete windows[i]._currentSource;
 | 
			
		||||
            }
 | 
			
		||||
            delete Main.overview._inputSources;
 | 
			
		||||
            delete Main.overview._currentSource;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _changePerWindowSource: function() {
 | 
			
		||||
        if (!this._sourcesPerWindow)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let window = this._getCurrentWindow();
 | 
			
		||||
        if (!window)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        window._inputSources = this._inputSources;
 | 
			
		||||
        window._currentSource = this._currentSource;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _containerGetPreferredWidth: function(container, for_height, alloc) {
 | 
			
		||||
        // Here, and in _containerGetPreferredHeight, we need to query
 | 
			
		||||
        // for the height of all children, but we ignore the results
 | 
			
		||||
 
 | 
			
		||||
@@ -10,31 +10,6 @@ const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
const VolumeMenu = imports.ui.status.volume;
 | 
			
		||||
 | 
			
		||||
const FakeStatusIcon = new Lang.Class({
 | 
			
		||||
    Name: 'FakeStatusIcon',
 | 
			
		||||
 | 
			
		||||
    _init: function(button) {
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'panel-status-button-box' });
 | 
			
		||||
        this._button = button;
 | 
			
		||||
        this._button.connect('icons-updated', Lang.bind(this, this._reconstructIcons));
 | 
			
		||||
        this._button.actor.bind_property('visible', this.actor, 'visible',
 | 
			
		||||
                                         GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        this._reconstructIcons();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _reconstructIcons: function() {
 | 
			
		||||
        this.actor.destroy_all_children();
 | 
			
		||||
        this._button.icons.forEach(Lang.bind(this, function(icon) {
 | 
			
		||||
            let newIcon = new St.Icon({ style_class: 'system-status-icon' });
 | 
			
		||||
            icon.bind_property('gicon', newIcon, 'gicon',
 | 
			
		||||
                               GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
            icon.bind_property('visible', newIcon, 'visible',
 | 
			
		||||
                               GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
            this.actor.add_actor(newIcon);
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const Indicator = new Lang.Class({
 | 
			
		||||
    Name: 'LockScreenMenuIndicator',
 | 
			
		||||
    Extends: PanelMenu.SystemStatusButton,
 | 
			
		||||
@@ -43,20 +18,41 @@ const Indicator = new Lang.Class({
 | 
			
		||||
        this.parent(null, _("Volume, network, battery"));
 | 
			
		||||
        this._box.style_class = 'lock-screen-status-button-box';
 | 
			
		||||
 | 
			
		||||
        this._volumeControl = VolumeMenu.getMixerControl();
 | 
			
		||||
        this._volumeMenu = new VolumeMenu.VolumeMenu(this._volumeControl);
 | 
			
		||||
        this.menu.addMenuItem(this._volumeMenu);
 | 
			
		||||
        this._volume = Main.panel.statusArea.volume;
 | 
			
		||||
        if (this._volume) {
 | 
			
		||||
            this._volumeIcon = this.addIcon(null);
 | 
			
		||||
            this._volume.mainIcon.bind_property('gicon', this._volumeIcon, 'gicon',
 | 
			
		||||
                                                GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
            this._volume.mainIcon.bind_property('visible', this._volumeIcon, 'visible',
 | 
			
		||||
                                                GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
 | 
			
		||||
        this._volume = new FakeStatusIcon(Main.panel.statusArea.volume);
 | 
			
		||||
        this._box.add_child(this._volume.actor);
 | 
			
		||||
 | 
			
		||||
        // Network may not exist if the user doesn't have NetworkManager
 | 
			
		||||
        if (Main.panel.statusArea.network) {
 | 
			
		||||
            this._network = new FakeStatusIcon(Main.panel.statusArea.network);
 | 
			
		||||
            this._box.add_child(this._network.actor);
 | 
			
		||||
            this._volumeControl = VolumeMenu.getMixerControl();
 | 
			
		||||
            this._volumeMenu = new VolumeMenu.VolumeMenu(this._volumeControl);
 | 
			
		||||
            this.menu.addMenuItem(this._volumeMenu);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._battery = new FakeStatusIcon(Main.panel.statusArea.battery);
 | 
			
		||||
        this._box.add_child(this._battery.actor);
 | 
			
		||||
        this._network = Main.panel.statusArea.network;
 | 
			
		||||
        if (this._network) {
 | 
			
		||||
            this._networkIcon = this.addIcon(null);
 | 
			
		||||
            this._network.mainIcon.bind_property('gicon', this._networkIcon, 'gicon',
 | 
			
		||||
                                                 GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
            this._network.mainIcon.bind_property('visible', this._networkIcon, 'visible',
 | 
			
		||||
                                                 GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
 | 
			
		||||
            this._networkSecondaryIcon = this.addIcon(null);
 | 
			
		||||
            this._network.secondaryIcon.bind_property('gicon', this._networkSecondaryIcon, 'gicon',
 | 
			
		||||
                                                      GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
            this._network.secondaryIcon.bind_property('visible', this._networkSecondaryIcon, 'visible',
 | 
			
		||||
                                                      GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._battery = Main.panel.statusArea.battery;
 | 
			
		||||
        if (this._battery) {
 | 
			
		||||
            this._batteryIcon = this.addIcon(null);
 | 
			
		||||
            this._battery.mainIcon.bind_property('gicon', this._batteryIcon, 'gicon',
 | 
			
		||||
                                                 GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
            this._battery.mainIcon.bind_property('visible', this._batteryIcon, 'visible',
 | 
			
		||||
                                                 GObject.BindingFlags.SYNC_CREATE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -8,26 +8,16 @@ const NMClient = imports.gi.NMClient;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
// Some of the new code depends on as-yet-unreleased NM
 | 
			
		||||
var NMGtk;
 | 
			
		||||
try {
 | 
			
		||||
    NMGtk = imports.gi.NMGtk;
 | 
			
		||||
} catch(e) {
 | 
			
		||||
    NMGtk = null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
const NotificationDaemon = imports.ui.notificationDaemon;
 | 
			
		||||
const ModemManager = imports.misc.modemManager;
 | 
			
		||||
const Util = imports.misc.util;
 | 
			
		||||
 | 
			
		||||
const NMConnectionCategory = {
 | 
			
		||||
    INVALID: 'invalid',
 | 
			
		||||
    WIRED: 'wired',
 | 
			
		||||
    VIRTUAL: 'virtual',
 | 
			
		||||
    WIRELESS: 'wireless',
 | 
			
		||||
    WWAN: 'wwan',
 | 
			
		||||
    VPN: 'vpn'
 | 
			
		||||
@@ -149,6 +139,46 @@ 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,
 | 
			
		||||
@@ -309,16 +339,19 @@ const NMDevice = new Lang.Class({
 | 
			
		||||
    Extends: NMConnectionBased,
 | 
			
		||||
 | 
			
		||||
    _init: function(client, device, connections) {
 | 
			
		||||
        this._client = client;
 | 
			
		||||
        this._setDevice(device);
 | 
			
		||||
        this.parent(connections);
 | 
			
		||||
        this.device = device;
 | 
			
		||||
        this.device._delegate = this;
 | 
			
		||||
        this._stateChangedId = this.device.connect('state-changed', Lang.bind(this, this._deviceStateChanged));
 | 
			
		||||
 | 
			
		||||
        // protected
 | 
			
		||||
        this._client = client;
 | 
			
		||||
        this.parent(connections);
 | 
			
		||||
        this._activeConnection = null;
 | 
			
		||||
        this._activeConnectionItem = null;
 | 
			
		||||
        this._autoConnectionItem = null;
 | 
			
		||||
        this._overflowItem = null;
 | 
			
		||||
 | 
			
		||||
        this.statusItem = new PopupMenu.PopupSwitchMenuItem('', this.connected, { style_class: 'popup-subtitle-menu-item' });
 | 
			
		||||
        this.statusItem = new PopupMenu.PopupSwitchMenuItem(this._getDescription(), this.connected, { style_class: 'popup-subtitle-menu-item' });
 | 
			
		||||
        this._statusChanged = this.statusItem.connect('toggled', Lang.bind(this, function(item, state) {
 | 
			
		||||
            let ok;
 | 
			
		||||
            if (state)
 | 
			
		||||
@@ -337,12 +370,23 @@ const NMDevice = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        this._setDevice(null);
 | 
			
		||||
        if (this.device)
 | 
			
		||||
            this.device._delegate = null;
 | 
			
		||||
 | 
			
		||||
        if (this._deferredWorkId) {
 | 
			
		||||
            // Just clear out, the actual removal is handled when the
 | 
			
		||||
            // actor is destroyed
 | 
			
		||||
            this._deferredWorkId = 0;
 | 
			
		||||
        if (this._stateChangedId) {
 | 
			
		||||
            // Need to go through GObject.Object.prototype because
 | 
			
		||||
            // nm_device_disconnect conflicts with g_signal_disconnect
 | 
			
		||||
            GObject.Object.prototype.disconnect.call(this.device, this._stateChangedId);
 | 
			
		||||
            this._stateChangedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (this._carrierChangedId) {
 | 
			
		||||
            // see above for why this is needed
 | 
			
		||||
            GObject.Object.prototype.disconnect.call(this.device, this._carrierChangedId);
 | 
			
		||||
            this._carrierChangedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (this._firmwareChangedId) {
 | 
			
		||||
            GObject.Object.prototype.disconnect.call(this.device, this._firmwareChangedId);
 | 
			
		||||
            this._firmwareChangedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._clearSection();
 | 
			
		||||
@@ -351,33 +395,6 @@ const NMDevice = new Lang.Class({
 | 
			
		||||
        this.section.destroy();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setDevice: function(device) {
 | 
			
		||||
        if (device) {
 | 
			
		||||
            this.device = device;
 | 
			
		||||
            this.device._delegate = this;
 | 
			
		||||
            this._stateChangedId = this.device.connect('state-changed', Lang.bind(this, this._deviceStateChanged));
 | 
			
		||||
        } else if (this.device) {
 | 
			
		||||
            this.device._delegate = null;
 | 
			
		||||
 | 
			
		||||
            if (this._stateChangedId) {
 | 
			
		||||
                // Need to go through GObject.Object.prototype because
 | 
			
		||||
                // nm_device_disconnect conflicts with g_signal_disconnect
 | 
			
		||||
                GObject.Object.prototype.disconnect.call(this.device, this._stateChangedId);
 | 
			
		||||
                this._stateChangedId = 0;
 | 
			
		||||
            }
 | 
			
		||||
            if (this._carrierChangedId) {
 | 
			
		||||
                GObject.Object.prototype.disconnect.call(this.device, this._carrierChangedId);
 | 
			
		||||
                this._carrierChangedId = 0;
 | 
			
		||||
            }
 | 
			
		||||
            if (this._firmwareChangedId) {
 | 
			
		||||
                GObject.Object.prototype.disconnect.call(this.device, this._firmwareChangedId);
 | 
			
		||||
                this._firmwareChangedId = 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.device = null;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    deactivate: function() {
 | 
			
		||||
        this.device.disconnect(null);
 | 
			
		||||
        return true;
 | 
			
		||||
@@ -392,7 +409,7 @@ const NMDevice = new Lang.Class({
 | 
			
		||||
        // Otherwise, if no connection is currently configured,
 | 
			
		||||
        // try automatic configuration (or summon the config dialog)
 | 
			
		||||
        if (this._connections.length == 1) {
 | 
			
		||||
            this._client.activate_connection(this._connections[0].connection, this.device || null, null, null);
 | 
			
		||||
            this._client.activate_connection(this._connections[0].connection, this.device, null, null);
 | 
			
		||||
            return true;
 | 
			
		||||
        } else if (this._connections.length == 0) {
 | 
			
		||||
            return this._activateAutomaticConnection();
 | 
			
		||||
@@ -412,7 +429,7 @@ const NMDevice = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get connected() {
 | 
			
		||||
        return this.device && this.device.state == NetworkManager.DeviceState.ACTIVATED;
 | 
			
		||||
        return this.device.state == NetworkManager.DeviceState.ACTIVATED;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    clearActiveConnection: function(activeConnection) {
 | 
			
		||||
@@ -432,6 +449,7 @@ const NMDevice = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._activeConnection = activeConnection;
 | 
			
		||||
 | 
			
		||||
        this._clearSection();
 | 
			
		||||
        this._queueCreateSection();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -445,9 +463,6 @@ const NMDevice = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getStatusLabel: function() {
 | 
			
		||||
        if (!this.device)
 | 
			
		||||
            return null;
 | 
			
		||||
 | 
			
		||||
        switch(this.device.state) {
 | 
			
		||||
        case NetworkManager.DeviceState.DISCONNECTED:
 | 
			
		||||
        case NetworkManager.DeviceState.ACTIVATED:
 | 
			
		||||
@@ -497,21 +512,14 @@ const NMDevice = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    syncDescription: function() {
 | 
			
		||||
        if (this.device && this.device._description)
 | 
			
		||||
            this.statusItem.label.text = this.device._description;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // protected
 | 
			
		||||
    _createAutomaticConnection: function() {
 | 
			
		||||
        throw new TypeError('Invoking pure virtual function NMDevice.createAutomaticConnection');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _queueCreateSection: function() {
 | 
			
		||||
        if (this._deferredWorkId) {
 | 
			
		||||
            this._clearSection();
 | 
			
		||||
            Main.queueDeferredWork(this._deferredWorkId);
 | 
			
		||||
        }
 | 
			
		||||
        this._clearSection();
 | 
			
		||||
        Main.queueDeferredWork(this._deferredWorkId);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _clearSection: function() {
 | 
			
		||||
@@ -611,6 +619,7 @@ const NMDevice = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._updateStatusItem();
 | 
			
		||||
 | 
			
		||||
        this._clearSection();
 | 
			
		||||
        this._queueCreateSection();
 | 
			
		||||
        this.emit('state-changed');
 | 
			
		||||
    },
 | 
			
		||||
@@ -634,6 +643,25 @@ 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;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@@ -664,7 +692,6 @@ const NMDeviceWired = new Lang.Class({
 | 
			
		||||
    Extends: NMDeviceSimple,
 | 
			
		||||
 | 
			
		||||
    _init: function(client, device, connections) {
 | 
			
		||||
        device._description = _("Wired");
 | 
			
		||||
        this._autoConnectionName = _("Auto Ethernet");
 | 
			
		||||
        this.category = NMConnectionCategory.WIRED;
 | 
			
		||||
 | 
			
		||||
@@ -692,7 +719,6 @@ const NMDeviceModem = new Lang.Class({
 | 
			
		||||
    _init: function(client, device, connections) {
 | 
			
		||||
        let is_wwan = false;
 | 
			
		||||
 | 
			
		||||
        device._description = _("Mobile broadband");
 | 
			
		||||
        this._enabled = true;
 | 
			
		||||
        this.mobileDevice = null;
 | 
			
		||||
        this._connectionType = 'ppp';
 | 
			
		||||
@@ -811,7 +837,6 @@ const NMDeviceBluetooth = new Lang.Class({
 | 
			
		||||
    Extends: NMDevice,
 | 
			
		||||
 | 
			
		||||
    _init: function(client, device, connections) {
 | 
			
		||||
        device._description = _("Bluetooth");
 | 
			
		||||
        this._autoConnectionName = this._makeConnectionName(device);
 | 
			
		||||
        device.connect('notify::name', Lang.bind(this, this._updateAutoConnectionName));
 | 
			
		||||
 | 
			
		||||
@@ -854,8 +879,13 @@ const NMDeviceBluetooth = new Lang.Class({
 | 
			
		||||
    _updateAutoConnectionName: function() {
 | 
			
		||||
        this._autoConnectionName = this._makeConnectionName(this.device);
 | 
			
		||||
 | 
			
		||||
        this._clearSection();
 | 
			
		||||
        this._queueCreateSection();
 | 
			
		||||
        this._updateStatusItem();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getDescription: function() {
 | 
			
		||||
        return this.device.name || _("Bluetooth");
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@@ -1115,8 +1145,10 @@ const NMDeviceWireless = new Lang.Class({
 | 
			
		||||
        this._networks.splice(res.network, 1);
 | 
			
		||||
        let newPos = Util.insertSorted(this._networks, network, Lang.bind(this, this._networkSortFunction));
 | 
			
		||||
 | 
			
		||||
        if (newPos != res.network)
 | 
			
		||||
        if (newPos != res.network) {
 | 
			
		||||
            this._clearSection();
 | 
			
		||||
            this._queueCreateSection();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _accessPointAdded: function(device, accessPoint) {
 | 
			
		||||
@@ -1169,8 +1201,10 @@ const NMDeviceWireless = new Lang.Class({
 | 
			
		||||
        let newPos = Util.insertSorted(this._networks, apObj, this._networkSortFunction);
 | 
			
		||||
 | 
			
		||||
        // Queue an update of the UI if we changed the order
 | 
			
		||||
        if (newPos != pos)
 | 
			
		||||
        if (newPos != pos) {
 | 
			
		||||
            this._clearSection();
 | 
			
		||||
            this._queueCreateSection();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _accessPointRemoved: function(device, accessPoint) {
 | 
			
		||||
@@ -1230,10 +1264,12 @@ const NMDeviceWireless = new Lang.Class({
 | 
			
		||||
            if (res.network < this._networks.length-1)
 | 
			
		||||
                okNext = this._networkSortFunction(this._networks[res.network + 1], apObj) <= 0;
 | 
			
		||||
 | 
			
		||||
            if (!okPrev || !okNext)
 | 
			
		||||
            if (!okPrev || !okNext) {
 | 
			
		||||
                this._clearSection();
 | 
			
		||||
                this._queueCreateSection();
 | 
			
		||||
            else if (apObj.item)
 | 
			
		||||
            } else if (apObj.item) {
 | 
			
		||||
                apObj.item.updateBestAP(apObj.accessPoints[0]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -1309,6 +1345,7 @@ const NMDeviceWireless = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        if (forceupdate) {
 | 
			
		||||
            this._networks.sort(this._networkSortFunction);
 | 
			
		||||
            this._clearSection();
 | 
			
		||||
            this._queueCreateSection();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
@@ -1341,6 +1378,7 @@ const NMDeviceWireless = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        if (forceupdate) {
 | 
			
		||||
            this._networks.sort(this._networkSortFunction);
 | 
			
		||||
            this._clearSection();
 | 
			
		||||
            this._queueCreateSection();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
@@ -1451,56 +1489,6 @@ const NMDeviceWireless = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const NMDeviceVirtual = new Lang.Class({
 | 
			
		||||
    Name: 'NMDeviceVirtual',
 | 
			
		||||
    Extends: NMDeviceSimple,
 | 
			
		||||
 | 
			
		||||
    _init: function(client, iface, connections) {
 | 
			
		||||
        this.iface = iface;
 | 
			
		||||
        this.parent(client, null, connections);
 | 
			
		||||
        this.category = NMConnectionCategory.VIRTUAL;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _shouldShowConnectionList: function() {
 | 
			
		||||
        return this.hasConnections();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    connectionValid: function(connection) {
 | 
			
		||||
        return connection.get_virtual_iface_name() == this.iface;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addConnection: function(connection) {
 | 
			
		||||
        if (!this.device && !this.hasConnections())
 | 
			
		||||
            this.statusItem.label.text = NMGtk.utils_get_connection_device_name(connection);
 | 
			
		||||
 | 
			
		||||
        this.parent(connection);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    adoptDevice: function(device) {
 | 
			
		||||
        if (device.get_iface() == this.iface) {
 | 
			
		||||
            this._setDevice(device);
 | 
			
		||||
            if (device._description)
 | 
			
		||||
                this.syncDescription();
 | 
			
		||||
            this._updateStatusItem();
 | 
			
		||||
            this.emit('state-changed');
 | 
			
		||||
            return true;
 | 
			
		||||
        } else
 | 
			
		||||
            return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    removeDevice: function(device) {
 | 
			
		||||
        if (device == this.device) {
 | 
			
		||||
            this._setDevice(null);
 | 
			
		||||
            this._updateStatusItem();
 | 
			
		||||
            this.emit('state-changed');
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hasConnections: function() {
 | 
			
		||||
        return this._connections.length != 0;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const NMVPNSection = new Lang.Class({
 | 
			
		||||
    Name: 'NMVPNSection',
 | 
			
		||||
    Extends: NMConnectionBased,
 | 
			
		||||
@@ -1679,32 +1667,23 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
        this._mobileUpdateId = 0;
 | 
			
		||||
        this._mobileUpdateDevice = null;
 | 
			
		||||
 | 
			
		||||
        this._nmDevices = [];
 | 
			
		||||
        this._devices = { };
 | 
			
		||||
        this._virtualDevices = [ ];
 | 
			
		||||
 | 
			
		||||
        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());
 | 
			
		||||
 | 
			
		||||
        this._devices.virtual = {
 | 
			
		||||
            section: new PopupMenu.PopupMenuSection(),
 | 
			
		||||
            devices: [ ],
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this._devices.virtual.section.actor.hide();
 | 
			
		||||
        this.menu.addMenuItem(this._devices.virtual.section);
 | 
			
		||||
        this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
 | 
			
		||||
 | 
			
		||||
        this._devices.wireless = {
 | 
			
		||||
            section: new PopupMenu.PopupMenuSection(),
 | 
			
		||||
            devices: [ ],
 | 
			
		||||
            item: this._makeToggleItem('wireless', _("Wi-Fi"))
 | 
			
		||||
            item: this._makeToggleItem('wireless', _("Wireless"))
 | 
			
		||||
        };
 | 
			
		||||
        this._devices.wireless.section.addMenuItem(this._devices.wireless.item);
 | 
			
		||||
        this._devices.wireless.section.actor.hide();
 | 
			
		||||
@@ -1714,7 +1693,9 @@ 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());
 | 
			
		||||
@@ -1734,14 +1715,6 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
        this._dtypes[NetworkManager.DeviceType.INFINIBAND] = NMDeviceSimple;
 | 
			
		||||
        // TODO: WiMax support
 | 
			
		||||
 | 
			
		||||
        // Virtual device types
 | 
			
		||||
        this._vtypes = { };
 | 
			
		||||
        if (NMGtk) {
 | 
			
		||||
            this._vtypes[NetworkManager.SETTING_VLAN_SETTING_NAME] = NMDeviceVirtual;
 | 
			
		||||
            this._vtypes[NetworkManager.SETTING_BOND_SETTING_NAME] = NMDeviceVirtual;
 | 
			
		||||
            this._vtypes[NetworkManager.SETTING_BRIDGE_SETTING_NAME] = NMDeviceVirtual;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Connection types
 | 
			
		||||
        this._ctypes = { };
 | 
			
		||||
        this._ctypes[NetworkManager.SETTING_WIRELESS_SETTING_NAME] = NMConnectionCategory.WIRELESS;
 | 
			
		||||
@@ -1752,11 +1725,6 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
        this._ctypes[NetworkManager.SETTING_CDMA_SETTING_NAME] = NMConnectionCategory.WWAN;
 | 
			
		||||
        this._ctypes[NetworkManager.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN;
 | 
			
		||||
        this._ctypes[NetworkManager.SETTING_INFINIBAND_SETTING_NAME] = NMConnectionCategory.WIRED;
 | 
			
		||||
        if (NMGtk) {
 | 
			
		||||
            this._ctypes[NetworkManager.SETTING_VLAN_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
 | 
			
		||||
            this._ctypes[NetworkManager.SETTING_BOND_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
 | 
			
		||||
            this._ctypes[NetworkManager.SETTING_BRIDGE_SETTING_NAME] = NMConnectionCategory.VIRTUAL;
 | 
			
		||||
        }
 | 
			
		||||
        this._ctypes[NetworkManager.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN;
 | 
			
		||||
 | 
			
		||||
        this._settings = NMClient.RemoteSettings.new(null);
 | 
			
		||||
@@ -1784,7 +1752,6 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
        if (!this._source) {
 | 
			
		||||
            this._source = new MessageTray.Source(_("Network Manager"),
 | 
			
		||||
                                                  'network-transmit-receive');
 | 
			
		||||
            this._source.policy = new NotificationDaemon.NotificationApplicationPolicy('gnome-network-panel');
 | 
			
		||||
 | 
			
		||||
            this._source.connect('destroy', Lang.bind(this, function() {
 | 
			
		||||
                this._source = null;
 | 
			
		||||
@@ -1809,34 +1776,20 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
        let devices = this._devices[category].devices;
 | 
			
		||||
        let item = this._devices[category].item;
 | 
			
		||||
        let section = this._devices[category].section;
 | 
			
		||||
 | 
			
		||||
        let visible;
 | 
			
		||||
        if (category == NMConnectionCategory.VIRTUAL)
 | 
			
		||||
            visible = !section.isEmpty();
 | 
			
		||||
        else
 | 
			
		||||
            visible = devices.length > 0;
 | 
			
		||||
 | 
			
		||||
        if (!visible)
 | 
			
		||||
        if (devices.length == 0)
 | 
			
		||||
            section.actor.hide();
 | 
			
		||||
        else {
 | 
			
		||||
            section.actor.show();
 | 
			
		||||
 | 
			
		||||
            // 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);
 | 
			
		||||
                }
 | 
			
		||||
            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);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
@@ -1844,9 +1797,8 @@ 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], true);
 | 
			
		||||
            this._deviceAdded(this._client, devices[i]);
 | 
			
		||||
        }
 | 
			
		||||
        this._syncDeviceNames();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _notifyForDevice: function(device, iconName, title, text, urgency) {
 | 
			
		||||
@@ -1877,50 +1829,9 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
                              MessageTray.Urgency.HIGH);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _syncDeviceNames: function() {
 | 
			
		||||
        if (NMGtk) {
 | 
			
		||||
            let names = NMGtk.utils_disambiguate_device_names(this._nmDevices);
 | 
			
		||||
            for (let i = 0; i < this._nmDevices.length; i++) {
 | 
			
		||||
                let device = this._nmDevices[i];
 | 
			
		||||
                device._description = names[i];
 | 
			
		||||
                if (device._delegate)
 | 
			
		||||
                    device._delegate.syncDescription();
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            for (let i = 0; i < this._nmDevices.length; i++) {
 | 
			
		||||
                let device = this._nmDevices[i];
 | 
			
		||||
                device._delegate.syncDescription();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    _makeWrapperDevice: function(wrapperClass, device) {
 | 
			
		||||
        let wrapper = new wrapperClass(this._client, device, this._connections);
 | 
			
		||||
 | 
			
		||||
    _deviceAdded: function(client, device, skipSyncDeviceNames) {
 | 
			
		||||
        if (device._delegate) {
 | 
			
		||||
            // already seen, not adding again
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._virtualDevices.length; i++) {
 | 
			
		||||
            if (this._virtualDevices[i].adoptDevice(device)) {
 | 
			
		||||
                this._nmDevices.push(device);
 | 
			
		||||
                if (!skipSyncDeviceNames)
 | 
			
		||||
                    this._syncDeviceNames();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let wrapperClass = this._dtypes[device.get_device_type()];
 | 
			
		||||
        if (wrapperClass) {
 | 
			
		||||
            let wrapper = new wrapperClass(this._client, device, this._connections);
 | 
			
		||||
            this._addDeviceWrapper(wrapper);
 | 
			
		||||
 | 
			
		||||
            this._nmDevices.push(device);
 | 
			
		||||
            if (!skipSyncDeviceNames)
 | 
			
		||||
                this._syncDeviceNames();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addDeviceWrapper: function(wrapper) {
 | 
			
		||||
        wrapper._activationFailedId = wrapper.connect('activation-failed',
 | 
			
		||||
                                                      Lang.bind(this, this._onActivationFailed));
 | 
			
		||||
        wrapper._deviceStateChangedId = wrapper.connect('state-changed', Lang.bind(this, function(dev) {
 | 
			
		||||
@@ -1932,36 +1843,35 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
            wrapper.disconnect(wrapper._destroyId);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        let section = this._devices[wrapper.category].section;
 | 
			
		||||
        section.addMenuItem(wrapper.statusItem);
 | 
			
		||||
        section.addMenuItem(wrapper.section);
 | 
			
		||||
        return wrapper;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
        let devices = this._devices[wrapper.category].devices;
 | 
			
		||||
        devices.push(wrapper);
 | 
			
		||||
    _deviceAdded: function(client, device) {
 | 
			
		||||
        if (device._delegate) {
 | 
			
		||||
            // already seen, not adding again
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        let wrapperClass = this._dtypes[device.get_device_type()];
 | 
			
		||||
        if (wrapperClass) {
 | 
			
		||||
            let wrapper = this._makeWrapperDevice(wrapperClass, device);
 | 
			
		||||
            let section = this._devices[wrapper.category].section;
 | 
			
		||||
            let devices = this._devices[wrapper.category].devices;
 | 
			
		||||
 | 
			
		||||
        this._syncSectionTitle(wrapper.category);
 | 
			
		||||
            section.addMenuItem(wrapper.section, 1);
 | 
			
		||||
            section.addMenuItem(wrapper.statusItem, 1);
 | 
			
		||||
            devices.push(wrapper);
 | 
			
		||||
 | 
			
		||||
            this._syncSectionTitle(wrapper.category);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _deviceRemoved: function(client, device) {
 | 
			
		||||
        let pos = this._nmDevices.indexOf(device);
 | 
			
		||||
        if (pos != -1) {
 | 
			
		||||
            this._nmDevices.splice(pos, 1);
 | 
			
		||||
            this._syncDeviceNames();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let wrapper = device._delegate;
 | 
			
		||||
        if (!wrapper) {
 | 
			
		||||
        if (!device._delegate) {
 | 
			
		||||
            log('Removing a network device that was not added');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (wrapper instanceof NMDeviceVirtual)
 | 
			
		||||
            wrapper.removeDevice(device);
 | 
			
		||||
        else
 | 
			
		||||
            this._removeDeviceWrapper(wrapper);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _removeDeviceWrapper: function(wrapper) {
 | 
			
		||||
        let wrapper = device._delegate;
 | 
			
		||||
        wrapper.destroy();
 | 
			
		||||
 | 
			
		||||
        let devices = this._devices[wrapper.category].devices;
 | 
			
		||||
@@ -2162,13 +2072,6 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
                devices[i].removeConnection(connection);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (section == NMConnectionCategory.VIRTUAL) {
 | 
			
		||||
            let iface = connection.get_virtual_iface_name();
 | 
			
		||||
            let wrapper = this._findVirtualDevice(iface);
 | 
			
		||||
            if (wrapper && !wrapper.hasConnections())
 | 
			
		||||
                this._removeDeviceWrapper(wrapper);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        connection.disconnect(connection._removedId);
 | 
			
		||||
        connection.disconnect(connection._updatedId);
 | 
			
		||||
        connection._removedId = connection._updatedId = 0;
 | 
			
		||||
@@ -2182,27 +2085,6 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        let section = connection._section;
 | 
			
		||||
 | 
			
		||||
        if (section == NMConnectionCategory.VIRTUAL) {
 | 
			
		||||
            let wrapperClass = this._vtypes[connection._type];
 | 
			
		||||
            if (!wrapperClass)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            let iface = connection.get_virtual_iface_name();
 | 
			
		||||
            let wrapper = this._findVirtualDevice(iface);
 | 
			
		||||
            if (!wrapper) {
 | 
			
		||||
                wrapper = new wrapperClass(this._client, iface, this._connections);
 | 
			
		||||
                this._addDeviceWrapper(wrapper);
 | 
			
		||||
                this._virtualDevices.push(wrapper);
 | 
			
		||||
 | 
			
		||||
                // We might already have a device for this connection
 | 
			
		||||
                for (let i = 0; i < this._nmDevices.length; i++) {
 | 
			
		||||
                    let device = this._nmDevices[i];
 | 
			
		||||
                    if (wrapper.adoptDevice(device))
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (section == NMConnectionCategory.INVALID)
 | 
			
		||||
            return;
 | 
			
		||||
        if (section == NMConnectionCategory.VPN) {
 | 
			
		||||
@@ -2215,15 +2097,6 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findVirtualDevice: function(iface) {
 | 
			
		||||
        for (let i = 0; i < this._virtualDevices.length; i++) {
 | 
			
		||||
            if (this._virtualDevices[i].iface == iface)
 | 
			
		||||
                return this._virtualDevices[i];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hideDevices: function() {
 | 
			
		||||
        this._devicesHidden = true;
 | 
			
		||||
 | 
			
		||||
@@ -2239,7 +2112,6 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
        this._statusSection.actor.hide();
 | 
			
		||||
 | 
			
		||||
        this._syncSectionTitle(NMConnectionCategory.WIRED);
 | 
			
		||||
        this._syncSectionTitle(NMConnectionCategory.VIRTUAL);
 | 
			
		||||
        this._syncSectionTitle(NMConnectionCategory.WIRELESS);
 | 
			
		||||
        this._syncSectionTitle(NMConnectionCategory.WWAN);
 | 
			
		||||
    },
 | 
			
		||||
@@ -2277,7 +2149,6 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
                this.setIcon('network-wireless-acquiring-symbolic');
 | 
			
		||||
                break;
 | 
			
		||||
            case NMConnectionCategory.WIRED:
 | 
			
		||||
            case NMConnectionCategory.VIRTUAL:
 | 
			
		||||
                this.setIcon('network-wired-acquiring-symbolic');
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
@@ -2317,7 +2188,6 @@ const NMApplet = new Lang.Class({
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            case NMConnectionCategory.WIRED:
 | 
			
		||||
            case NMConnectionCategory.VIRTUAL:
 | 
			
		||||
                this.setIcon('network-wired-symbolic');
 | 
			
		||||
                break;
 | 
			
		||||
            case NMConnectionCategory.WWAN:
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ const St = imports.gi.St;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
 | 
			
		||||
const BUS_NAME = 'org.gnome.SettingsDaemon.Power';
 | 
			
		||||
const BUS_NAME = 'org.gnome.SettingsDaemon';
 | 
			
		||||
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
 | 
			
		||||
 | 
			
		||||
const UPDeviceType = {
 | 
			
		||||
@@ -54,23 +54,14 @@ const Indicator = new Lang.Class({
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.parent('battery-missing-symbolic', _("Battery"));
 | 
			
		||||
 | 
			
		||||
        this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
 | 
			
		||||
                                           Lang.bind(this, function(proxy, error) {
 | 
			
		||||
                                               if (error) {
 | 
			
		||||
                                                   log(error.message);
 | 
			
		||||
                                                   return;
 | 
			
		||||
                                               }
 | 
			
		||||
                                               this._proxy.connect('g-properties-changed',
 | 
			
		||||
                                                                   Lang.bind(this, this._devicesChanged));
 | 
			
		||||
                                               this._devicesChanged();
 | 
			
		||||
                                           }));
 | 
			
		||||
        this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH);
 | 
			
		||||
 | 
			
		||||
        this._deviceItems = [ ];
 | 
			
		||||
        this._hasPrimary = false;
 | 
			
		||||
        this._primaryDeviceId = null;
 | 
			
		||||
 | 
			
		||||
        this._batteryItem = new PopupMenu.PopupMenuItem('', { reactive: false });
 | 
			
		||||
        this._primaryPercentage = new St.Label({ style_class: 'popup-battery-percentage' });
 | 
			
		||||
        this._primaryPercentage = new St.Label();
 | 
			
		||||
        this._batteryItem.addActor(this._primaryPercentage, { align: St.Align.END });
 | 
			
		||||
        this.menu.addMenuItem(this._batteryItem);
 | 
			
		||||
 | 
			
		||||
@@ -79,6 +70,10 @@ const Indicator = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
 | 
			
		||||
        this.menu.addSettingsAction(_("Power Settings"), 'gnome-power-panel.desktop');
 | 
			
		||||
 | 
			
		||||
        this._proxy.connect('g-properties-changed',
 | 
			
		||||
                            Lang.bind(this, this._devicesChanged));
 | 
			
		||||
        this._devicesChanged();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _readPrimaryDevice: function() {
 | 
			
		||||
@@ -188,8 +183,7 @@ const DeviceItem = new Lang.Class({
 | 
			
		||||
        this._box.add_actor(this._label);
 | 
			
		||||
        this.addActor(this._box);
 | 
			
		||||
 | 
			
		||||
        let percentLabel = new St.Label({ text: C_("percent of battery remaining", "%d%%").format(Math.round(percentage)),
 | 
			
		||||
                                          style_class: 'popup-battery-percentage' });
 | 
			
		||||
        let percentLabel = new St.Label({ text: C_("percent of battery remaining", "%d%%").format(Math.round(percentage)) });
 | 
			
		||||
        this.addActor(percentLabel, { align: St.Align.END });
 | 
			
		||||
        //FIXME: ideally we would like to expose this._label and percentLabel
 | 
			
		||||
        this.actor.label_actor = percentLabel;
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ const Lang = imports.lang;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Gvc = imports.gi.Gvc;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
@@ -27,210 +26,6 @@ function getMixerControl() {
 | 
			
		||||
    return _mixerControl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const StreamSlider = new Lang.Class({
 | 
			
		||||
    Name: 'StreamSlider',
 | 
			
		||||
 | 
			
		||||
    _init: function(control, title) {
 | 
			
		||||
        this._control = control;
 | 
			
		||||
 | 
			
		||||
        this.item = new PopupMenu.PopupMenuSection();
 | 
			
		||||
 | 
			
		||||
        this._title = new PopupMenu.PopupMenuItem(title, { reactive: false });
 | 
			
		||||
        this._slider = new PopupMenu.PopupSliderMenuItem(0);
 | 
			
		||||
        this._slider.connect('value-changed', Lang.bind(this, this._sliderChanged));
 | 
			
		||||
        this._slider.connect('drag-end', Lang.bind(this, this._notifyVolumeChange));
 | 
			
		||||
 | 
			
		||||
        this.item.addMenuItem(this._title);
 | 
			
		||||
        this.item.addMenuItem(this._slider);
 | 
			
		||||
 | 
			
		||||
        this._stream = null;
 | 
			
		||||
        this._shouldShow = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    get stream() {
 | 
			
		||||
        return this._stream;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    set stream(stream) {
 | 
			
		||||
        if (this._stream) {
 | 
			
		||||
            this._disconnectStream(this._stream);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._stream = stream;
 | 
			
		||||
 | 
			
		||||
        if (this._stream) {
 | 
			
		||||
            this._connectStream(this._stream);
 | 
			
		||||
            this._updateVolume();
 | 
			
		||||
        } else {
 | 
			
		||||
            this.emit('stream-updated');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _disconnectStream: function(stream) {
 | 
			
		||||
        stream.disconnect(this._mutedChangedId);
 | 
			
		||||
        this._mutedChangedId = 0;
 | 
			
		||||
        stream.disconnect(this._volumeChangedId);
 | 
			
		||||
        this._volumeChangedId = 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _connectStream: function(stream) {
 | 
			
		||||
        this._mutedChangedId = stream.connect('notify::is-muted', Lang.bind(this, this._updateVolume));
 | 
			
		||||
        this._volumeChangedId = stream.connect('notify::volume', Lang.bind(this, this._updateVolume));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _shouldBeVisible: function() {
 | 
			
		||||
        return this._stream != null;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateVisibility: function() {
 | 
			
		||||
        let visible = this._shouldBeVisible();
 | 
			
		||||
        this._title.actor.visible = visible;
 | 
			
		||||
        this._slider.actor.visible = visible;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    scroll: function(event) {
 | 
			
		||||
        this._slider.scroll(event);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setValue: function(value) {
 | 
			
		||||
        // piggy-back off of sliderChanged
 | 
			
		||||
        this._slider.setValue(value);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _sliderChanged: function(slider, value, property) {
 | 
			
		||||
        if (!this._stream)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let volume = value * this._control.get_vol_max_norm();
 | 
			
		||||
        let prevMuted = this._stream.is_muted;
 | 
			
		||||
        if (volume < 1) {
 | 
			
		||||
            this._stream.volume = 0;
 | 
			
		||||
            if (!prevMuted)
 | 
			
		||||
                this._stream.change_is_muted(true);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._stream.volume = volume;
 | 
			
		||||
            if (prevMuted)
 | 
			
		||||
                this._stream.change_is_muted(false);
 | 
			
		||||
        }
 | 
			
		||||
        this._stream.push_volume();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _notifyVolumeChange: function() {
 | 
			
		||||
        global.cancel_theme_sound(VOLUME_NOTIFY_ID);
 | 
			
		||||
        global.play_theme_sound(VOLUME_NOTIFY_ID,
 | 
			
		||||
                                'audio-volume-change',
 | 
			
		||||
                                _("Volume changed"),
 | 
			
		||||
                                Clutter.get_current_event ());
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateVolume: function() {
 | 
			
		||||
        let muted = this._stream.is_muted;
 | 
			
		||||
        this._slider.setValue(muted ? 0 : (this._stream.volume / this._control.get_vol_max_norm()));
 | 
			
		||||
        this.emit('stream-updated');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getIcon: function() {
 | 
			
		||||
        if (!this._stream)
 | 
			
		||||
            return null;
 | 
			
		||||
 | 
			
		||||
        let volume = this._stream.volume;
 | 
			
		||||
        if (this._stream.is_muted || volume <= 0) {
 | 
			
		||||
            return 'audio-volume-muted-symbolic';
 | 
			
		||||
        } else {
 | 
			
		||||
            let n = Math.floor(3 * volume / this._control.get_vol_max_norm()) + 1;
 | 
			
		||||
            if (n < 2)
 | 
			
		||||
                return 'audio-volume-low-symbolic';
 | 
			
		||||
            if (n >= 3)
 | 
			
		||||
                return 'audio-volume-high-symbolic';
 | 
			
		||||
            return 'audio-volume-medium-symbolic';
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(StreamSlider.prototype);
 | 
			
		||||
 | 
			
		||||
const OutputStreamSlider = new Lang.Class({
 | 
			
		||||
    Name: 'OutputStreamSlider',
 | 
			
		||||
    Extends: StreamSlider,
 | 
			
		||||
 | 
			
		||||
    _connectStream: function(stream) {
 | 
			
		||||
        this.parent(stream);
 | 
			
		||||
        this._portChangedId = stream.connect('notify::port', Lang.bind(this, this._portChanged));
 | 
			
		||||
        this._portChanged();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findHeadphones: function(sink) {
 | 
			
		||||
        // This only works for external headphones (e.g. bluetooth)
 | 
			
		||||
        if (sink.get_form_factor() == 'headset' ||
 | 
			
		||||
            sink.get_form_factor() == 'headphone')
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        // a bit hackish, but ALSA/PulseAudio have a number
 | 
			
		||||
        // of different identifiers for headphones, and I could
 | 
			
		||||
        // not find the complete list
 | 
			
		||||
        if (sink.get_ports().length > 0)
 | 
			
		||||
            return sink.get_port().port.indexOf('headphone') >= 0;
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _disconnectStream: function(stream) {
 | 
			
		||||
        this.parent(stream);
 | 
			
		||||
        stream.disconnect(this._portChangedId);
 | 
			
		||||
        this._portChangedId = 0;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _portChanged: function() {
 | 
			
		||||
        let hasHeadphones = this._findHeadphones(this._stream);
 | 
			
		||||
        if (hasHeadphones != this._hasHeadphones) {
 | 
			
		||||
            this._hasHeadphones = hasHeadphones;
 | 
			
		||||
            this.emit('headphones-changed', this._hasHeadphones);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const InputStreamSlider = new Lang.Class({
 | 
			
		||||
    Name: 'InputStreamSlider',
 | 
			
		||||
    Extends: StreamSlider,
 | 
			
		||||
 | 
			
		||||
    _init: function(control, title) {
 | 
			
		||||
        this.parent(control, title);
 | 
			
		||||
        this._control.connect('stream-added', Lang.bind(this, this._maybeShowInput));
 | 
			
		||||
        this._control.connect('stream-removed', Lang.bind(this, this._maybeShowInput));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _connectStream: function(stream) {
 | 
			
		||||
        this.parent(stream);
 | 
			
		||||
        this._maybeShowInput();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _maybeShowInput: function() {
 | 
			
		||||
        // only show input widgets if any application is recording audio
 | 
			
		||||
        let showInput = false;
 | 
			
		||||
        let recordingApps = this._control.get_source_outputs();
 | 
			
		||||
        if (this._stream && recordingApps) {
 | 
			
		||||
            for (let i = 0; i < recordingApps.length; i++) {
 | 
			
		||||
                let outputStream = recordingApps[i];
 | 
			
		||||
                let id = outputStream.get_application_id();
 | 
			
		||||
                // but skip gnome-volume-control and pavucontrol
 | 
			
		||||
                // (that appear as recording because they show the input level)
 | 
			
		||||
                if (!id || (id != 'org.gnome.VolumeControl' && id != 'org.PulseAudio.pavucontrol')) {
 | 
			
		||||
                    showInput = true;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._showInput = showInput;
 | 
			
		||||
        this._updateVisibility();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _shouldBeVisible: function() {
 | 
			
		||||
        return this.parent() && this._showInput;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const VolumeMenu = new Lang.Class({
 | 
			
		||||
    Name: 'VolumeMenu',
 | 
			
		||||
    Extends: PopupMenu.PopupMenuSection,
 | 
			
		||||
@@ -244,48 +39,207 @@ const VolumeMenu = new Lang.Class({
 | 
			
		||||
        this._control.connect('state-changed', Lang.bind(this, this._onControlStateChanged));
 | 
			
		||||
        this._control.connect('default-sink-changed', Lang.bind(this, this._readOutput));
 | 
			
		||||
        this._control.connect('default-source-changed', Lang.bind(this, this._readInput));
 | 
			
		||||
        this._control.connect('stream-added', Lang.bind(this, this._maybeShowInput));
 | 
			
		||||
        this._control.connect('stream-removed', Lang.bind(this, this._maybeShowInput));
 | 
			
		||||
        this._volumeMax = this._control.get_vol_max_norm();
 | 
			
		||||
 | 
			
		||||
        this._output = null;
 | 
			
		||||
        this._outputVolumeId = 0;
 | 
			
		||||
        this._outputMutedId = 0;
 | 
			
		||||
        /* Translators: This is the label for audio volume */
 | 
			
		||||
        this._output = new OutputStreamSlider(this._control, _("Volume"));
 | 
			
		||||
        this._output.connect('stream-updated', Lang.bind(this, function() {
 | 
			
		||||
            this.emit('icon-changed');
 | 
			
		||||
        }));
 | 
			
		||||
        this._output.connect('headphones-changed', Lang.bind(this, function(stream, value) {
 | 
			
		||||
            this.emit('headphones-changed', value);
 | 
			
		||||
        }));
 | 
			
		||||
        this.addMenuItem(this._output.item);
 | 
			
		||||
 | 
			
		||||
        this._input = new InputStreamSlider(this._control, _("Microphone"));
 | 
			
		||||
        this.addMenuItem(this._input.item);
 | 
			
		||||
        this._outputTitle = new PopupMenu.PopupMenuItem(_("Volume"), { reactive: false });
 | 
			
		||||
        this._outputSlider = new PopupMenu.PopupSliderMenuItem(0);
 | 
			
		||||
        this._outputSlider.connect('value-changed', Lang.bind(this, this._sliderChanged, '_output'));
 | 
			
		||||
        this._outputSlider.connect('drag-end', Lang.bind(this, this._notifyVolumeChange));
 | 
			
		||||
        this.addMenuItem(this._outputTitle);
 | 
			
		||||
        this.addMenuItem(this._outputSlider);
 | 
			
		||||
 | 
			
		||||
        this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
 | 
			
		||||
 | 
			
		||||
        this._input = null;
 | 
			
		||||
        this._inputVolumeId = 0;
 | 
			
		||||
        this._inputMutedId = 0;
 | 
			
		||||
        this._inputTitle = new PopupMenu.PopupMenuItem(_("Microphone"), { reactive: false });
 | 
			
		||||
        this._inputSlider = new PopupMenu.PopupSliderMenuItem(0);
 | 
			
		||||
        this._inputSlider.connect('value-changed', Lang.bind(this, this._sliderChanged, '_input'));
 | 
			
		||||
        this._inputSlider.connect('drag-end', Lang.bind(this, this._notifyVolumeChange));
 | 
			
		||||
        this.addMenuItem(this._inputTitle);
 | 
			
		||||
        this.addMenuItem(this._inputSlider);
 | 
			
		||||
 | 
			
		||||
        this._onControlStateChanged();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    scroll: function(event) {
 | 
			
		||||
        this._output.scroll(event);
 | 
			
		||||
    scroll: function(direction) {
 | 
			
		||||
        let currentVolume = this._output.volume;
 | 
			
		||||
 | 
			
		||||
        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();
 | 
			
		||||
        }
 | 
			
		||||
        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();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._notifyVolumeChange();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onControlStateChanged: function() {
 | 
			
		||||
        if (this._control.get_state() == Gvc.MixerControlState.READY) {
 | 
			
		||||
            this._readInput();
 | 
			
		||||
            this._readOutput();
 | 
			
		||||
            this._readInput();
 | 
			
		||||
            this._maybeShowInput();
 | 
			
		||||
        } else {
 | 
			
		||||
            this.emit('icon-changed');
 | 
			
		||||
            this.emit('icon-changed', null);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _findHeadphones: function(sink) {
 | 
			
		||||
        // This only works for external headphones (e.g. bluetooth)
 | 
			
		||||
        if (sink.get_form_factor() == 'headset' ||
 | 
			
		||||
            sink.get_form_factor() == 'headphone')
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        // a bit hackish, but ALSA/PulseAudio have a number
 | 
			
		||||
        // of different identifiers for headphones, and I could
 | 
			
		||||
        // not find the complete list
 | 
			
		||||
        let port = sink.get_port();
 | 
			
		||||
        if (port)
 | 
			
		||||
            return port.port.indexOf('headphone') >= 0;
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _portChanged: function() {
 | 
			
		||||
        this.hasHeadphones = this._findHeadphones(this._output);
 | 
			
		||||
        this.emit('headphones-changed');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _readOutput: function() {
 | 
			
		||||
        this._output.stream = this._control.get_default_sink();
 | 
			
		||||
        if (this._outputVolumeId) {
 | 
			
		||||
            this._output.disconnect(this._outputVolumeId);
 | 
			
		||||
            this._output.disconnect(this._outputMutedId);
 | 
			
		||||
            this._output.disconnect(this._outputPortId);
 | 
			
		||||
            this._outputVolumeId = 0;
 | 
			
		||||
            this._outputMutedId = 0;
 | 
			
		||||
            this._outputPortId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        this._output = this._control.get_default_sink();
 | 
			
		||||
        if (this._output) {
 | 
			
		||||
            this._outputMutedId = this._output.connect('notify::is-muted', Lang.bind(this, this._mutedChanged, '_output'));
 | 
			
		||||
            this._outputVolumeId = this._output.connect('notify::volume', Lang.bind(this, this._volumeChanged, '_output'));
 | 
			
		||||
            this._outputPortId = this._output.connect('notify::port', Lang.bind(this, this._portChanged));
 | 
			
		||||
 | 
			
		||||
            this._mutedChanged(null, null, '_output');
 | 
			
		||||
            this._volumeChanged(null, null, '_output');
 | 
			
		||||
            this._portChanged();
 | 
			
		||||
        } else {
 | 
			
		||||
            this.hasHeadphones = false;
 | 
			
		||||
            this._outputSlider.setValue(0);
 | 
			
		||||
            this.emit('icon-changed', 'audio-volume-muted-symbolic');
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _readInput: function() {
 | 
			
		||||
        this._input.stream = this._control.get_default_source();
 | 
			
		||||
        if (this._inputVolumeId) {
 | 
			
		||||
            this._input.disconnect(this._inputVolumeId);
 | 
			
		||||
            this._input.disconnect(this._inputMutedId);
 | 
			
		||||
            this._inputVolumeId = 0;
 | 
			
		||||
            this._inputMutedId = 0;
 | 
			
		||||
        }
 | 
			
		||||
        this._input = this._control.get_default_source();
 | 
			
		||||
        if (this._input) {
 | 
			
		||||
            this._inputMutedId = this._input.connect('notify::is-muted', Lang.bind(this, this._mutedChanged, '_input'));
 | 
			
		||||
            this._inputVolumeId = this._input.connect('notify::volume', Lang.bind(this, this._volumeChanged, '_input'));
 | 
			
		||||
            this._mutedChanged (null, null, '_input');
 | 
			
		||||
            this._volumeChanged (null, null, '_input');
 | 
			
		||||
        } else {
 | 
			
		||||
            this._inputTitle.actor.hide();
 | 
			
		||||
            this._inputSlider.actor.hide();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getIcon: function() {
 | 
			
		||||
        return this._output.getIcon();
 | 
			
		||||
    _maybeShowInput: function() {
 | 
			
		||||
        // only show input widgets if any application is recording audio
 | 
			
		||||
        let showInput = false;
 | 
			
		||||
        let recordingApps = this._control.get_source_outputs();
 | 
			
		||||
        if (this._input && recordingApps) {
 | 
			
		||||
            for (let i = 0; i < recordingApps.length; i++) {
 | 
			
		||||
                let outputStream = recordingApps[i];
 | 
			
		||||
                let id = outputStream.get_application_id();
 | 
			
		||||
                // but skip gnome-volume-control and pavucontrol
 | 
			
		||||
                // (that appear as recording because they show the input level)
 | 
			
		||||
                if (!id || (id != 'org.gnome.VolumeControl' && id != 'org.PulseAudio.pavucontrol')) {
 | 
			
		||||
                    showInput = true;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._inputTitle.actor.visible = showInput;
 | 
			
		||||
        this._inputSlider.actor.visible = showInput;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _volumeToIcon: function(volume) {
 | 
			
		||||
        if (volume <= 0) {
 | 
			
		||||
            return 'audio-volume-muted-symbolic';
 | 
			
		||||
        } else {
 | 
			
		||||
            let n = Math.floor(3 * volume / this._volumeMax) + 1;
 | 
			
		||||
            if (n < 2)
 | 
			
		||||
                return 'audio-volume-low-symbolic';
 | 
			
		||||
            if (n >= 3)
 | 
			
		||||
                return 'audio-volume-high-symbolic';
 | 
			
		||||
            return 'audio-volume-medium-symbolic';
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _sliderChanged: function(slider, value, property) {
 | 
			
		||||
        if (this[property] == null) {
 | 
			
		||||
            log ('Volume slider changed for %s, but %s does not exist'.format(property, property));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        let volume = value * this._volumeMax;
 | 
			
		||||
        let prev_muted = this[property].is_muted;
 | 
			
		||||
        if (volume < 1) {
 | 
			
		||||
            this[property].volume = 0;
 | 
			
		||||
            if (!prev_muted)
 | 
			
		||||
                this[property].change_is_muted(true);
 | 
			
		||||
        } else {
 | 
			
		||||
            this[property].volume = volume;
 | 
			
		||||
            if (prev_muted)
 | 
			
		||||
                this[property].change_is_muted(false);
 | 
			
		||||
        }
 | 
			
		||||
        this[property].push_volume();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _notifyVolumeChange: function() {
 | 
			
		||||
        global.cancel_theme_sound(VOLUME_NOTIFY_ID);
 | 
			
		||||
        global.play_theme_sound(VOLUME_NOTIFY_ID, 'audio-volume-change');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _mutedChanged: function(object, param_spec, property) {
 | 
			
		||||
        let muted = this[property].is_muted;
 | 
			
		||||
        let slider = this[property+'Slider'];
 | 
			
		||||
        slider.setValue(muted ? 0 : (this[property].volume / this._volumeMax));
 | 
			
		||||
        if (property == '_output') {
 | 
			
		||||
            if (muted)
 | 
			
		||||
                this.emit('icon-changed', 'audio-volume-muted-symbolic');
 | 
			
		||||
            else
 | 
			
		||||
                this.emit('icon-changed', this._volumeToIcon(this._output.volume));
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _volumeChanged: function(object, param_spec, property) {
 | 
			
		||||
        this[property+'Slider'].setValue(this[property].volume / this._volumeMax);
 | 
			
		||||
        if (property == '_output' && !this._output.is_muted)
 | 
			
		||||
            this.emit('icon-changed', this._volumeToIcon(this._output.volume));
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@@ -298,13 +252,13 @@ const Indicator = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._control = getMixerControl();
 | 
			
		||||
        this._volumeMenu = new VolumeMenu(this._control);
 | 
			
		||||
        this._volumeMenu.connect('icon-changed', Lang.bind(this, function(menu) {
 | 
			
		||||
            let icon = this._volumeMenu.getIcon();
 | 
			
		||||
            this.actor.visible = (icon != null);
 | 
			
		||||
        this._volumeMenu.connect('icon-changed', Lang.bind(this, function(menu, icon) {
 | 
			
		||||
            this._hasPulseAudio = (icon != null);
 | 
			
		||||
            this.setIcon(icon);
 | 
			
		||||
            this._syncVisibility();
 | 
			
		||||
        }));
 | 
			
		||||
        this._volumeMenu.connect('headphones-changed', Lang.bind(this, function(menu, value) {
 | 
			
		||||
            this._headphoneIcon.visible = value;
 | 
			
		||||
        this._volumeMenu.connect('headphones-changed', Lang.bind(this, function() {
 | 
			
		||||
            this._syncVisibility();
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this._headphoneIcon = this.addIcon(new Gio.ThemedIcon({ name: 'headphones-symbolic' }));
 | 
			
		||||
@@ -318,7 +272,13 @@ const Indicator = new Lang.Class({
 | 
			
		||||
        this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _syncVisibility: function() {
 | 
			
		||||
        this.actor.visible = this._hasPulseAudio;
 | 
			
		||||
        this.mainIcon.visible = this._hasPulseAudio;
 | 
			
		||||
        this._headphoneIcon.visible = this._hasPulseAudio && this._volumeMenu.hasHeadphones;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onScrollEvent: function(actor, event) {
 | 
			
		||||
        this._volumeMenu.scroll(event);
 | 
			
		||||
        this._volumeMenu.scroll(event.get_scroll_direction());
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -46,8 +46,7 @@ const SwitcherPopup = new Lang.Class({
 | 
			
		||||
        this._selectedIndex = 0;
 | 
			
		||||
 | 
			
		||||
        this.actor = new Shell.GenericContainer({ style_class: 'switcher-popup',
 | 
			
		||||
                                                  reactive: true,
 | 
			
		||||
                                                  visible: false });
 | 
			
		||||
                                                  reactive: true });
 | 
			
		||||
        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));
 | 
			
		||||
@@ -638,6 +637,5 @@ function drawArrow(area, side) {
 | 
			
		||||
 | 
			
		||||
    Clutter.cairo_set_source_color(cr, bodyColor);
 | 
			
		||||
    cr.fill();
 | 
			
		||||
    cr.$dispose();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -115,7 +115,7 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
    _init: function(parentActor) {
 | 
			
		||||
        this.parent({ shellReactive: true,
 | 
			
		||||
                      styleClass: 'login-dialog',
 | 
			
		||||
                      keybindingMode: Shell.KeyBindingMode.UNLOCK_SCREEN,
 | 
			
		||||
                      keybindingMode: Main.KeybindingMode.UNLOCK_SCREEN,
 | 
			
		||||
                      parentActor: parentActor
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
@@ -198,23 +198,18 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
                                          x_align: St.Align.END,
 | 
			
		||||
                                          y_align: St.Align.MIDDLE });
 | 
			
		||||
 | 
			
		||||
        let screenSaverSettings = new Gio.Settings({ schema: 'org.gnome.desktop.screensaver' });
 | 
			
		||||
        if (screenSaverSettings.get_boolean('user-switch-enabled')) {
 | 
			
		||||
            let otherUserLabel = new St.Label({ text: _("Log in as another user"),
 | 
			
		||||
                                                style_class: 'login-dialog-not-listed-label' });
 | 
			
		||||
            this._otherUserButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
 | 
			
		||||
                                                    can_focus: true,
 | 
			
		||||
                                                    child: otherUserLabel,
 | 
			
		||||
                                                    reactive: true,
 | 
			
		||||
                                                    x_align: St.Align.START,
 | 
			
		||||
                                                    x_fill: true });
 | 
			
		||||
            this._otherUserButton.connect('clicked', Lang.bind(this, this._otherUserClicked));
 | 
			
		||||
            this.dialogLayout.add(this._otherUserButton,
 | 
			
		||||
                                  { x_align: St.Align.START,
 | 
			
		||||
                                    x_fill: false });
 | 
			
		||||
        } else {
 | 
			
		||||
            this._otherUserButton = null;
 | 
			
		||||
        }
 | 
			
		||||
        let otherUserLabel = new St.Label({ text: _("Log in as another user"),
 | 
			
		||||
                                            style_class: 'login-dialog-not-listed-label' });
 | 
			
		||||
        this._otherUserButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
 | 
			
		||||
                                                can_focus: true,
 | 
			
		||||
                                                child: otherUserLabel,
 | 
			
		||||
                                                reactive: true,
 | 
			
		||||
                                                x_align: St.Align.START,
 | 
			
		||||
                                                x_fill: true });
 | 
			
		||||
        this._otherUserButton.connect('clicked', Lang.bind(this, this._otherUserClicked));
 | 
			
		||||
        this.dialogLayout.add(this._otherUserButton,
 | 
			
		||||
                              { x_align: St.Align.START,
 | 
			
		||||
                                x_fill: false });
 | 
			
		||||
 | 
			
		||||
        this._updateSensitivity(true);
 | 
			
		||||
 | 
			
		||||
@@ -236,10 +231,8 @@ const UnlockDialog = new Lang.Class({
 | 
			
		||||
        this._promptEntry.reactive = sensitive;
 | 
			
		||||
        this._promptEntry.clutter_text.editable = sensitive;
 | 
			
		||||
        this._updateOkButtonSensitivity(sensitive && this._promptEntry.text.length > 0);
 | 
			
		||||
        if (this._otherUserButton) {
 | 
			
		||||
            this._otherUserButton.reactive = sensitive;
 | 
			
		||||
            this._otherUserButton.can_focus = sensitive;
 | 
			
		||||
        }
 | 
			
		||||
        this._otherUserButton.reactive = sensitive;
 | 
			
		||||
        this._otherUserButton.can_focus = sensitive;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateOkButtonSensitivity: function(sensitive) {
 | 
			
		||||
 
 | 
			
		||||
@@ -22,13 +22,12 @@ const Util = imports.misc.util;
 | 
			
		||||
 | 
			
		||||
const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown';
 | 
			
		||||
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
 | 
			
		||||
const PRIVACY_SCHEMA = 'org.gnome.desktop.privacy'
 | 
			
		||||
const DISABLE_USER_SWITCH_KEY = 'disable-user-switching';
 | 
			
		||||
const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen';
 | 
			
		||||
const DISABLE_LOG_OUT_KEY = 'disable-log-out';
 | 
			
		||||
const LOCK_ENABLED_KEY = 'lock-enabled';
 | 
			
		||||
const ALWAYS_SHOW_LOG_OUT_KEY = 'always-show-log-out';
 | 
			
		||||
const SHOW_FULL_NAME_IN_TOP_BAR_KEY = 'show-full-name-in-top-bar';
 | 
			
		||||
const SHOW_FULL_NAME_KEY = 'show-full-name';
 | 
			
		||||
 | 
			
		||||
const DIALOG_ICON_SIZE = 64;
 | 
			
		||||
 | 
			
		||||
@@ -478,7 +477,6 @@ const UserMenuButton = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._screenSaverSettings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
 | 
			
		||||
        this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
 | 
			
		||||
        this._privacySettings = new Gio.Settings({ schema: PRIVACY_SCHEMA });
 | 
			
		||||
 | 
			
		||||
        this._userManager = AccountsService.UserManager.get_default();
 | 
			
		||||
 | 
			
		||||
@@ -555,12 +553,10 @@ const UserMenuButton = new Lang.Class({
 | 
			
		||||
                                       Lang.bind(this, this._updateLogout));
 | 
			
		||||
        this._lockdownSettings.connect('changed::' + DISABLE_LOCK_SCREEN_KEY,
 | 
			
		||||
                                       Lang.bind(this, this._updateLockScreen));
 | 
			
		||||
        global.settings.connect('changed::' + ALWAYS_SHOW_LOG_OUT_KEY,
 | 
			
		||||
                                Lang.bind(this, this._updateLogout));
 | 
			
		||||
        this._screenSaverSettings.connect('changed::' + SHOW_FULL_NAME_IN_TOP_BAR_KEY,
 | 
			
		||||
        this._screenSaverSettings.connect('changed::' + SHOW_FULL_NAME_KEY,
 | 
			
		||||
                                           Lang.bind(this, this._updateUserName));
 | 
			
		||||
        this._privacySettings.connect('changed::' + SHOW_FULL_NAME_IN_TOP_BAR_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();
 | 
			
		||||
@@ -585,7 +581,6 @@ const UserMenuButton = new Lang.Class({
 | 
			
		||||
                                       Lang.bind(this, this._updateHaveShutdown));
 | 
			
		||||
 | 
			
		||||
        Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
 | 
			
		||||
        Main.screenShield.connect('locked-changed', Lang.bind(this, this._updatePresenceIcon));
 | 
			
		||||
        this._sessionUpdated();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -607,10 +602,10 @@ const UserMenuButton = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _updateUserName: function() {
 | 
			
		||||
        let settings = this._privacySettings;
 | 
			
		||||
        let settings = global.settings;
 | 
			
		||||
        if (Main.sessionMode.isLocked)
 | 
			
		||||
            settings = this._screenSaverSettings;
 | 
			
		||||
        if (this._user.is_loaded && settings.get_boolean(SHOW_FULL_NAME_IN_TOP_BAR_KEY))
 | 
			
		||||
        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("");
 | 
			
		||||
@@ -705,11 +700,6 @@ const UserMenuButton = new Lang.Class({
 | 
			
		||||
            this._iconBox.child = this._idleIcon;
 | 
			
		||||
        else
 | 
			
		||||
            this._iconBox.child = this._offlineIcon;
 | 
			
		||||
 | 
			
		||||
        if (Main.sessionMode.isLocked)
 | 
			
		||||
            this._iconBox.visible = Main.screenShield.locked;
 | 
			
		||||
        else
 | 
			
		||||
            this._iconBox.visible = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _setupAccounts: function() {
 | 
			
		||||
@@ -830,7 +820,7 @@ const UserMenuButton = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _onMyAccountActivate: function() {
 | 
			
		||||
        Main.overview.hide();
 | 
			
		||||
        let app = Shell.AppSystem.get_default().lookup_app('gnome-user-accounts-panel.desktop');
 | 
			
		||||
        let app = Shell.AppSystem.get_default().lookup_setting('gnome-user-accounts-panel.desktop');
 | 
			
		||||
        app.activate();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,6 @@ const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
const AppDisplay = imports.ui.appDisplay;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
const RemoteSearch = imports.ui.remoteSearch;
 | 
			
		||||
const Search = imports.ui.search;
 | 
			
		||||
const SearchDisplay = imports.ui.searchDisplay;
 | 
			
		||||
@@ -47,7 +46,8 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._activePage = null;
 | 
			
		||||
 | 
			
		||||
        this._searchActive = false;
 | 
			
		||||
        this.active = false;
 | 
			
		||||
        this._searchPending = false;
 | 
			
		||||
        this._searchTimeoutId = 0;
 | 
			
		||||
 | 
			
		||||
        this._searchSystem = new Search.SearchSystem();
 | 
			
		||||
@@ -77,17 +77,16 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
        this._capturedEventId = 0;
 | 
			
		||||
 | 
			
		||||
        this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
 | 
			
		||||
        this._workspacesPage = this._addPage(this._workspacesDisplay.actor,
 | 
			
		||||
        this._workspacesPage = this._addPage(this._workspacesDisplay.actor, null,
 | 
			
		||||
                                             _("Windows"), 'emblem-documents-symbolic');
 | 
			
		||||
 | 
			
		||||
        this._appDisplay = new AppDisplay.AllAppDisplay();
 | 
			
		||||
        this._appsPage = this._addPage(this._appDisplay.actor,
 | 
			
		||||
        this._appsPage = this._addPage(this._appDisplay.actor, null,
 | 
			
		||||
                                       _("Applications"), 'view-grid-symbolic');
 | 
			
		||||
 | 
			
		||||
        this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
 | 
			
		||||
        this._searchPage = this._addPage(this._searchResults.actor,
 | 
			
		||||
                                         _("Search"), 'edit-find-symbolic',
 | 
			
		||||
                                         { a11yFocus: this._entry });
 | 
			
		||||
        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));
 | 
			
		||||
@@ -136,8 +135,8 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
        Main.wm.addKeybinding('toggle-application-view',
 | 
			
		||||
                              new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }),
 | 
			
		||||
                              Meta.KeyBindingFlags.NONE,
 | 
			
		||||
                              Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                              Shell.KeyBindingMode.OVERVIEW,
 | 
			
		||||
                              Main.KeybindingMode.NORMAL |
 | 
			
		||||
                              Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                              Lang.bind(this, this._toggleAppsPage));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@@ -170,16 +169,14 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
        this._workspacesDisplay.hide();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _addPage: function(actor, name, a11yIcon, params) {
 | 
			
		||||
        params = Params.parse(params, { a11yFocus: null });
 | 
			
		||||
 | 
			
		||||
    _addPage: function(actor, a11yFocus, name, a11yIcon) {
 | 
			
		||||
        let page = new St.Bin({ child: actor,
 | 
			
		||||
                                x_align: St.Align.START,
 | 
			
		||||
                                y_align: St.Align.START,
 | 
			
		||||
                                x_fill: true,
 | 
			
		||||
                                y_fill: true });
 | 
			
		||||
        if (params.a11yFocus)
 | 
			
		||||
            Main.ctrlAltTabManager.addGroup(params.a11yFocus, name, a11yIcon);
 | 
			
		||||
        if (a11yFocus)
 | 
			
		||||
            Main.ctrlAltTabManager.addGroup(a11yFocus, name, a11yIcon);
 | 
			
		||||
        else
 | 
			
		||||
            Main.ctrlAltTabManager.addGroup(actor, name, a11yIcon,
 | 
			
		||||
                                            { proxy: this.actor,
 | 
			
		||||
@@ -223,7 +220,7 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onShowAppsButtonToggled: function() {
 | 
			
		||||
        if (this._searchActive)
 | 
			
		||||
        if (this.active)
 | 
			
		||||
            this.reset();
 | 
			
		||||
        else
 | 
			
		||||
            this._showPage(this._showAppsButton.checked ? this._appsPage
 | 
			
		||||
@@ -244,7 +241,7 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
        let symbol = event.get_key_symbol();
 | 
			
		||||
 | 
			
		||||
        if (symbol == Clutter.Escape) {
 | 
			
		||||
            if (this._searchActive)
 | 
			
		||||
            if (this.active)
 | 
			
		||||
                this.reset();
 | 
			
		||||
            else if (this._showAppsButton.checked)
 | 
			
		||||
                this._resetShowAppsButton();
 | 
			
		||||
@@ -252,9 +249,9 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
                Main.overview.hide();
 | 
			
		||||
            return true;
 | 
			
		||||
        } else if (Clutter.keysym_to_unicode(symbol) ||
 | 
			
		||||
                   (symbol == Clutter.BackSpace && this._searchActive)) {
 | 
			
		||||
                   (symbol == Clutter.BackSpace && this.active)) {
 | 
			
		||||
            this.startSearch(event);
 | 
			
		||||
        } else if (!this._searchActive) {
 | 
			
		||||
        } else if (!this.active) {
 | 
			
		||||
            if (symbol == Clutter.Tab || symbol == Clutter.Down) {
 | 
			
		||||
                this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
 | 
			
		||||
                return true;
 | 
			
		||||
@@ -328,37 +325,39 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onTextChanged: function (se, prop) {
 | 
			
		||||
        let searchPreviouslyActive = this._searchActive;
 | 
			
		||||
        this._searchActive = this._entry.get_text() != '';
 | 
			
		||||
 | 
			
		||||
        let startSearch = this._searchActive && !searchPreviouslyActive;
 | 
			
		||||
        if (startSearch)
 | 
			
		||||
        let searchPreviouslyActive = this.active;
 | 
			
		||||
        this.active = this._entry.get_text() != '';
 | 
			
		||||
        this._searchPending = this.active && !searchPreviouslyActive;
 | 
			
		||||
        if (this._searchPending) {
 | 
			
		||||
            this._searchResults.startingSearch();
 | 
			
		||||
 | 
			
		||||
        if (this._searchActive) {
 | 
			
		||||
        }
 | 
			
		||||
        if (this.active) {
 | 
			
		||||
            this._entry.set_secondary_icon(this._activeIcon);
 | 
			
		||||
 | 
			
		||||
            if (this._iconClickedId == 0)
 | 
			
		||||
            if (this._iconClickedId == 0) {
 | 
			
		||||
                this._iconClickedId = this._entry.connect('secondary-icon-clicked',
 | 
			
		||||
                    Lang.bind(this, this.reset));
 | 
			
		||||
 | 
			
		||||
            if (this._searchTimeoutId == 0)
 | 
			
		||||
                this._searchTimeoutId = Mainloop.timeout_add(150,
 | 
			
		||||
                    Lang.bind(this, this._doSearch));
 | 
			
		||||
                    Lang.bind(this, function() {
 | 
			
		||||
                        this.reset();
 | 
			
		||||
                    }));
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            if (this._iconClickedId > 0) {
 | 
			
		||||
            if (this._iconClickedId > 0)
 | 
			
		||||
                this._entry.disconnect(this._iconClickedId);
 | 
			
		||||
                this._iconClickedId = 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this._searchTimeoutId > 0) {
 | 
			
		||||
                Mainloop.source_remove(this._searchTimeoutId);
 | 
			
		||||
                this._searchTimeoutId = 0;
 | 
			
		||||
            }
 | 
			
		||||
            this._iconClickedId = 0;
 | 
			
		||||
 | 
			
		||||
            this._entry.set_secondary_icon(this._inactiveIcon);
 | 
			
		||||
            this._searchCancelled();
 | 
			
		||||
        }
 | 
			
		||||
        if (!this.active) {
 | 
			
		||||
            if (this._searchTimeoutId > 0) {
 | 
			
		||||
                Mainloop.source_remove(this._searchTimeoutId);
 | 
			
		||||
                this._searchTimeoutId = 0;
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (this._searchTimeoutId > 0)
 | 
			
		||||
            return;
 | 
			
		||||
        this._searchTimeoutId = Mainloop.timeout_add(150, Lang.bind(this, this._doSearch));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onKeyPress: function(entry, event) {
 | 
			
		||||
@@ -368,7 +367,16 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
                this.reset();
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (this._searchActive) {
 | 
			
		||||
        } else if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
 | 
			
		||||
            // We can't connect to 'activate' here because search providers
 | 
			
		||||
            // might want to do something with the modifiers in activateDefault.
 | 
			
		||||
            if (this._searchTimeoutId > 0) {
 | 
			
		||||
                Mainloop.source_remove(this._searchTimeoutId);
 | 
			
		||||
                this._doSearch();
 | 
			
		||||
            }
 | 
			
		||||
            this._searchResults.activateDefault();
 | 
			
		||||
            return true;
 | 
			
		||||
        } else if (this.active) {
 | 
			
		||||
            let arrowNext, nextDirection;
 | 
			
		||||
            if (entry.get_text_direction() == Clutter.TextDirection.RTL) {
 | 
			
		||||
                arrowNext = Clutter.Left;
 | 
			
		||||
@@ -392,15 +400,6 @@ const ViewSelector = new Lang.Class({
 | 
			
		||||
            } else if (symbol == arrowNext && this._text.position == -1) {
 | 
			
		||||
                this._searchResults.navigateFocus(nextDirection);
 | 
			
		||||
                return true;
 | 
			
		||||
            } else if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
 | 
			
		||||
                // We can't connect to 'activate' here because search providers
 | 
			
		||||
                // might want to do something with the modifiers in activateDefault.
 | 
			
		||||
                if (this._searchTimeoutId > 0) {
 | 
			
		||||
                    Mainloop.source_remove(this._searchTimeoutId);
 | 
			
		||||
                    this._doSearch();
 | 
			
		||||
                }
 | 
			
		||||
                this._searchResults.activateDefault();
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
 
 | 
			
		||||
@@ -105,74 +105,74 @@ const WindowManager = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this._workspaceSwitcherPopup = null;
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-to-workspace-left',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                                        Shell.KeyBindingMode.OVERVIEW,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-to-workspace-right',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                                        Shell.KeyBindingMode.OVERVIEW,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-to-workspace-up',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                                        Shell.KeyBindingMode.OVERVIEW,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-to-workspace-down',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                                        Shell.KeyBindingMode.OVERVIEW,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('move-to-workspace-left',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                                        Shell.KeyBindingMode.OVERVIEW,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('move-to-workspace-right',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                                        Shell.KeyBindingMode.OVERVIEW,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('move-to-workspace-up',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                                        Shell.KeyBindingMode.OVERVIEW,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('move-to-workspace-down',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                                        Shell.KeyBindingMode.OVERVIEW,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW,
 | 
			
		||||
                                        Lang.bind(this, this._showWorkspaceSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-applications',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL,
 | 
			
		||||
                                        Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-group',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL,
 | 
			
		||||
                                        Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-applications-backward',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL,
 | 
			
		||||
                                        Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-group-backward',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL,
 | 
			
		||||
                                        Lang.bind(this, this._startAppSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-windows',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL,
 | 
			
		||||
                                        Lang.bind(this, this._startWindowSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-windows-backward',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL,
 | 
			
		||||
                                        Lang.bind(this, this._startWindowSwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-panels',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                                        Shell.KeyBindingMode.OVERVIEW |
 | 
			
		||||
                                        Shell.KeyBindingMode.LOCK_SCREEN |
 | 
			
		||||
                                        Shell.KeyBindingMode.UNLOCK_SCREEN |
 | 
			
		||||
                                        Shell.KeyBindingMode.LOGIN_SCREEN,
 | 
			
		||||
                                        Main.KeybindingMode.NORMAL |
 | 
			
		||||
                                        Main.KeybindingMode.OVERVIEW |
 | 
			
		||||
                                        Main.KeybindingMode.LOCK_SCREEN |
 | 
			
		||||
                                        Main.KeybindingMode.UNLOCK_SCREEN |
 | 
			
		||||
                                        Main.KeybindingMode.LOGIN_SCREEN,
 | 
			
		||||
                                        Lang.bind(this, this._startA11ySwitcher));
 | 
			
		||||
        this.setCustomKeybindingHandler('switch-panels-backward',
 | 
			
		||||
                                        Shell.KeyBindingMode.NORMAL |
 | 
			
		||||
                                        Shell.KeyBindingMode.OVERVIEW |
 | 
			
		||||
                                        Shell.KeyBindingMode.LOCK_SCREEN |
 | 
			
		||||
                                        Shell.KeyBindingMode.UNLOCK_SCREEN |
 | 
			
		||||
                                        Shell.KeyBindingMode.LOGIN_SCREEN,
 | 
			
		||||
                                        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,
 | 
			
		||||
                           Shell.KeyBindingMode.NORMAL,
 | 
			
		||||
                           Main.KeybindingMode.NORMAL,
 | 
			
		||||
                           Lang.bind(this, this._openAppMenu));
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('showing', Lang.bind(this, function() {
 | 
			
		||||
@@ -199,7 +199,7 @@ const WindowManager = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    removeKeybinding: function(name) {
 | 
			
		||||
        if (global.display.remove_keybinding(name))
 | 
			
		||||
            this.allowKeybinding(name, Shell.KeyBindingMode.NONE);
 | 
			
		||||
            this.allowKeybinding(name, Main.KeybindingMode.NONE);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    allowKeybinding: function(name, modes) {
 | 
			
		||||
@@ -242,30 +242,22 @@ const WindowManager = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        actor.set_scale(1.0, 1.0);
 | 
			
		||||
        actor.move_anchor_point_from_gravity(Clutter.Gravity.CENTER);
 | 
			
		||||
 | 
			
		||||
        /* scale window down to 0x0.
 | 
			
		||||
         * maybe TODO: get icon geometry passed through and move the window towards it?
 | 
			
		||||
         */
 | 
			
		||||
        this._minimizing.push(actor);
 | 
			
		||||
 | 
			
		||||
        let xDest, yDest, xScale, yScale;
 | 
			
		||||
        let [success, geom] = actor.meta_window.get_icon_geometry();
 | 
			
		||||
        if (success) {
 | 
			
		||||
            xDest = geom.x;
 | 
			
		||||
            yDest = geom.y;
 | 
			
		||||
            xScale = geom.width / actor.width;
 | 
			
		||||
            yScale = geom.height / actor.height;
 | 
			
		||||
        } else {
 | 
			
		||||
            /* scale window down to 0x0.  */
 | 
			
		||||
            let monitor = Main.layoutManager.findMonitorForWindow(actor.meta_window);
 | 
			
		||||
            xDest = monitor.x;
 | 
			
		||||
            yDest = monitor.y;
 | 
			
		||||
            xScale = 0.0;
 | 
			
		||||
            yScale = 0.0;
 | 
			
		||||
            if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
                xDest += monitor.width;
 | 
			
		||||
        }
 | 
			
		||||
        let monitor = Main.layoutManager.findMonitorForWindow(actor.meta_window);
 | 
			
		||||
        let xDest = monitor.x;
 | 
			
		||||
        let yDest = monitor.y;
 | 
			
		||||
        if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
 | 
			
		||||
            xDest += monitor.width;
 | 
			
		||||
 | 
			
		||||
        Tweener.addTween(actor,
 | 
			
		||||
                         { scale_x: xScale,
 | 
			
		||||
                           scale_y: yScale,
 | 
			
		||||
                         { scale_x: 0.0,
 | 
			
		||||
                           scale_y: 0.0,
 | 
			
		||||
                           x: xDest,
 | 
			
		||||
                           y: yDest,
 | 
			
		||||
                           time: WINDOW_ANIMATION_TIME,
 | 
			
		||||
@@ -502,14 +494,14 @@ const WindowManager = new Lang.Class({
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _filterKeybinding: function(shellwm, binding) {
 | 
			
		||||
        if (Main.keybindingMode == Shell.KeyBindingMode.NONE)
 | 
			
		||||
        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 == Shell.KeyBindingMode.NORMAL &&
 | 
			
		||||
        if (Main.keybindingMode == Main.KeybindingMode.NORMAL &&
 | 
			
		||||
            binding.is_builtin())
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
@@ -29,6 +30,9 @@ const CLOSE_BUTTON_FADE_TIME = 0.1;
 | 
			
		||||
 | 
			
		||||
const DRAGGING_WINDOW_OPACITY = 100;
 | 
			
		||||
 | 
			
		||||
const BUTTON_LAYOUT_SCHEMA = 'org.gnome.shell.overrides';
 | 
			
		||||
const BUTTON_LAYOUT_KEY = 'button-layout';
 | 
			
		||||
 | 
			
		||||
// When calculating a layout, we calculate the scale of windows and the percent
 | 
			
		||||
// of the available area the new layout uses. If the values for the new layout,
 | 
			
		||||
// when weighted with the values as below, are worse than the previous layout's,
 | 
			
		||||
@@ -256,37 +260,23 @@ const WindowClone = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _onScroll : function (actor, event) {
 | 
			
		||||
        let direction = event.get_scroll_direction();
 | 
			
		||||
        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 (direction == Clutter.ScrollDirection.UP) {
 | 
			
		||||
            if (this._zoomStep == undefined)
 | 
			
		||||
                this._zoomStart();
 | 
			
		||||
            if (this._zoomStep < 100) {
 | 
			
		||||
                this._zoomStep += delta;
 | 
			
		||||
                this._zoomStep = Math.min(100, this._zoomStep);
 | 
			
		||||
                this._zoomStep += SCROLL_SCALE_AMOUNT;
 | 
			
		||||
                this._zoomUpdate();
 | 
			
		||||
            }
 | 
			
		||||
        } else if (delta < 0) {
 | 
			
		||||
        } else if (direction == Clutter.ScrollDirection.DOWN) {
 | 
			
		||||
            if (this._zoomStep > 0) {
 | 
			
		||||
                this._zoomStep += delta;
 | 
			
		||||
                this._zoomStep -= SCROLL_SCALE_AMOUNT;
 | 
			
		||||
                this._zoomStep = Math.max(0, this._zoomStep);
 | 
			
		||||
                this._zoomUpdate();
 | 
			
		||||
            }
 | 
			
		||||
            if (this._zoomStep <= 0.0)
 | 
			
		||||
                this._zoomEnd();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _zoomUpdate : function () {
 | 
			
		||||
@@ -451,6 +441,8 @@ const WindowOverlay = new Lang.Class({
 | 
			
		||||
        this._parentActor = parentActor;
 | 
			
		||||
        this._hidden = false;
 | 
			
		||||
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: BUTTON_LAYOUT_SCHEMA });
 | 
			
		||||
 | 
			
		||||
        this.borderSize = 0;
 | 
			
		||||
        this.border = new St.Bin({ style_class: 'window-clone-border' });
 | 
			
		||||
 | 
			
		||||
@@ -543,8 +535,15 @@ const WindowOverlay = new Lang.Class({
 | 
			
		||||
        let button = this.closeButton;
 | 
			
		||||
        let title = this.title;
 | 
			
		||||
 | 
			
		||||
        let layout = Meta.prefs_get_button_layout();
 | 
			
		||||
        let side = layout.left_buttons.indexOf(Meta.ButtonFunction.CLOSE) > -1 ? St.Side.LEFT : St.Side.RIGHT;
 | 
			
		||||
        let layout = this._settings.get_string(BUTTON_LAYOUT_KEY);
 | 
			
		||||
        let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
 | 
			
		||||
 | 
			
		||||
        let split = layout.split(":");
 | 
			
		||||
        let side;
 | 
			
		||||
        if (split[0].indexOf("close") > -1)
 | 
			
		||||
            side = rtl ? St.Side.RIGHT : St.Side.LEFT;
 | 
			
		||||
        else
 | 
			
		||||
            side = rtl ? St.Side.LEFT : St.Side.RIGHT;
 | 
			
		||||
 | 
			
		||||
        let buttonX;
 | 
			
		||||
        let buttonY = cloneY - (button.height - button._overlap);
 | 
			
		||||
@@ -746,10 +745,11 @@ const LayoutStrategy = new Lang.Class({
 | 
			
		||||
    Name: 'LayoutStrategy',
 | 
			
		||||
    Abstract: true,
 | 
			
		||||
 | 
			
		||||
    _init: function(monitor, rowSpacing, columnSpacing) {
 | 
			
		||||
    _init: function(monitor, rowSpacing, columnSpacing, bottomPadding) {
 | 
			
		||||
        this._monitor = monitor;
 | 
			
		||||
        this._rowSpacing = rowSpacing;
 | 
			
		||||
        this._columnSpacing = columnSpacing;
 | 
			
		||||
        this._bottomPadding = bottomPadding;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _newRow: function() {
 | 
			
		||||
@@ -774,23 +774,24 @@ const LayoutStrategy = new Lang.Class({
 | 
			
		||||
                 windows: [] };
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Computes and returns a fancy scale for @window using the
 | 
			
		||||
    // Compute the size and fancy scale for @window using the
 | 
			
		||||
    // base scale, @scale.
 | 
			
		||||
    _computeWindowScale: function(window, scale) {
 | 
			
		||||
        // Since we align windows next to each other, the height of the
 | 
			
		||||
        // thumbnails is much more important to preserve than the width of
 | 
			
		||||
        // them, so two windows with equal height, but maybe differering
 | 
			
		||||
        // widths line up.
 | 
			
		||||
        let ratio = window.actor.height / this._monitor.height;
 | 
			
		||||
    //
 | 
			
		||||
    // Returns a list structure: [ scaledWidth, scaledHeight, fancyScale ]
 | 
			
		||||
    // where scaledWidth and scaledHeight are the window's
 | 
			
		||||
    // width and height, scaled by fancyScale for convenience.
 | 
			
		||||
    _computeWindowSizeAndScale: function(window, scale) {
 | 
			
		||||
        let width = window.actor.width;
 | 
			
		||||
        let height = window.actor.height;
 | 
			
		||||
        let ratio;
 | 
			
		||||
 | 
			
		||||
        // The purpose of this manipulation here is to prevent windows
 | 
			
		||||
        // from getting too small. For something like a calculator window,
 | 
			
		||||
        // we need to bump up the size just a bit to make sure it looks
 | 
			
		||||
        // good. We'll use a multiplier of 1.5 for this.
 | 
			
		||||
        if (width > height)
 | 
			
		||||
            ratio = width / this._monitor.width;
 | 
			
		||||
        else
 | 
			
		||||
            ratio = height / this._monitor.height;
 | 
			
		||||
 | 
			
		||||
        // Map from [0, 1] to [1.5, 1]
 | 
			
		||||
        let fancyScale = _interpolate(1.5, 1, ratio) * scale;
 | 
			
		||||
        return fancyScale;
 | 
			
		||||
        let fancyScale = (2 / (1 + ratio)) * scale;
 | 
			
		||||
        return [width * fancyScale, height * fancyScale, fancyScale];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // Compute the size of each row, by assigning to the properties
 | 
			
		||||
@@ -828,7 +829,7 @@ const LayoutStrategy = new Lang.Class({
 | 
			
		||||
        let area = layout.area;
 | 
			
		||||
 | 
			
		||||
        let hspacing = (layout.maxColumns - 1) * this._columnSpacing;
 | 
			
		||||
        let vspacing = (layout.numRows - 1) * this._rowSpacing;
 | 
			
		||||
        let vspacing = (layout.numRows - 1) * this._rowSpacing + this._bottomPadding;
 | 
			
		||||
 | 
			
		||||
        let spacedWidth = area.width - hspacing;
 | 
			
		||||
        let spacedHeight = area.height - vspacing;
 | 
			
		||||
@@ -862,7 +863,7 @@ const LayoutStrategy = new Lang.Class({
 | 
			
		||||
            y += row.height + this._rowSpacing;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let height = y - this._rowSpacing;
 | 
			
		||||
        let height = y - this._rowSpacing + this._bottomPadding;
 | 
			
		||||
        let baseY = (area.height - height) / 2;
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < rows.length; i++) {
 | 
			
		||||
@@ -872,10 +873,7 @@ const LayoutStrategy = new Lang.Class({
 | 
			
		||||
            for (let j = 0; j < row.windows.length; j++) {
 | 
			
		||||
                let window = row.windows[j];
 | 
			
		||||
 | 
			
		||||
                let s = this._computeWindowScale(window, scale);
 | 
			
		||||
                s = Math.min(s, WINDOW_CLONE_MAXIMUM_SCALE);
 | 
			
		||||
                let width = window.actor.width * s;
 | 
			
		||||
                let height = window.actor.height * s;
 | 
			
		||||
                let [width, height, s] = this._computeWindowSizeAndScale(window, scale);
 | 
			
		||||
                let y = row.y + row.height - height;
 | 
			
		||||
 | 
			
		||||
                let x = baseX;
 | 
			
		||||
@@ -936,9 +934,7 @@ const UnalignedLayoutStrategy = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
            for (; windowIdx < windows.length; windowIdx++) {
 | 
			
		||||
                let window = windows[windowIdx];
 | 
			
		||||
                let s = this._computeWindowScale(window, 1);
 | 
			
		||||
                let width = window.actor.width * s;
 | 
			
		||||
                let height = window.actor.height * s;
 | 
			
		||||
                let [width, height] = this._computeWindowSizeAndScale(window, 1);
 | 
			
		||||
                row.fullHeight = Math.max(row.fullHeight, height);
 | 
			
		||||
 | 
			
		||||
                // either new width is < idealWidth or new width is nearer from idealWidth then oldWidth
 | 
			
		||||
@@ -1004,9 +1000,9 @@ const GridLayoutStrategy = new Lang.Class({
 | 
			
		||||
                let window = windows[windowIdx];
 | 
			
		||||
                row.windows.push(window);
 | 
			
		||||
 | 
			
		||||
                let s = this._computeWindowScale(window, 1);
 | 
			
		||||
                maxWindowWidth = Math.max(maxWindowWidth, window.actor.width * s);
 | 
			
		||||
                maxWindowHeight = Math.max(maxWindowHeight, window.actor.height * s);
 | 
			
		||||
                let [width, height] = this._computeWindowSizeAndScale(window, 1);
 | 
			
		||||
                maxWindowWidth = Math.max(maxWindowWidth, width);
 | 
			
		||||
                maxWindowHeight = Math.max(maxWindowHeight, height);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -1041,8 +1037,6 @@ const Workspace = new Lang.Class({
 | 
			
		||||
        this._windowOverlaysGroup.set_size(0, 0);
 | 
			
		||||
 | 
			
		||||
        this.actor = new St.Widget({ style_class: 'window-picker' });
 | 
			
		||||
        if (monitorIndex != Main.layoutManager.primaryIndex)
 | 
			
		||||
            this.actor.add_style_class_name('external-monitor');
 | 
			
		||||
        this.actor.set_size(0, 0);
 | 
			
		||||
 | 
			
		||||
        this._dropRect = new Clutter.Rectangle({ opacity: 0 });
 | 
			
		||||
@@ -1207,7 +1201,7 @@ const Workspace = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
                    // Make the window slightly transparent to indicate it's hidden
 | 
			
		||||
                    Tweener.addTween(clone.actor,
 | 
			
		||||
                                     { opacity: 128,
 | 
			
		||||
                                     { opacity: 255,
 | 
			
		||||
                                       time: Overview.ANIMATION_TIME,
 | 
			
		||||
                                       transition: 'easeInQuad'
 | 
			
		||||
                                     });
 | 
			
		||||
@@ -1629,7 +1623,7 @@ const Workspace = new Lang.Class({
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _computeLayout: function(windows, area, rowSpacing, columnSpacing) {
 | 
			
		||||
    _computeLayout: function(windows, area, rowSpacing, columnSpacing, bottomPadding) {
 | 
			
		||||
        // We look for the largest scale that allows us to fit the
 | 
			
		||||
        // largest row/tallest column on the workspace.
 | 
			
		||||
 | 
			
		||||
@@ -1645,7 +1639,7 @@ const Workspace = new Lang.Class({
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            let strategyClass = numRows > 2 ? GridLayoutStrategy : UnalignedLayoutStrategy;
 | 
			
		||||
            let strategy = new strategyClass(this._monitor, rowSpacing, columnSpacing);
 | 
			
		||||
            let strategy = new strategyClass(this._monitor, rowSpacing, columnSpacing, bottomPadding);
 | 
			
		||||
 | 
			
		||||
            let layout = { area: area, strategy: strategy, numRows: numRows, numColumns: numColumns };
 | 
			
		||||
            strategy.computeLayout(windows, layout);
 | 
			
		||||
@@ -1677,12 +1671,6 @@ const Workspace = new Lang.Class({
 | 
			
		||||
        // Window grid spacing
 | 
			
		||||
        let columnSpacing = node.get_length('-horizontal-spacing');
 | 
			
		||||
        let rowSpacing = node.get_length('-vertical-spacing');
 | 
			
		||||
        let padding = {
 | 
			
		||||
            left: node.get_padding(St.Side.LEFT),
 | 
			
		||||
            top: node.get_padding(St.Side.TOP),
 | 
			
		||||
            bottom: node.get_padding(St.Side.BOTTOM),
 | 
			
		||||
            right: node.get_padding(St.Side.RIGHT),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        if (!totalWindows)
 | 
			
		||||
            return [];
 | 
			
		||||
@@ -1697,25 +1685,19 @@ const Workspace = new Lang.Class({
 | 
			
		||||
            [leftBorder, rightBorder] = overlay.chromeWidths();
 | 
			
		||||
        } else {
 | 
			
		||||
            [closeButtonHeight, captionHeight] = [0, 0];
 | 
			
		||||
            [leftBorder, rightBorder] = [0, 0];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        rowSpacing += captionHeight;
 | 
			
		||||
        columnSpacing += (rightBorder + leftBorder) / 2;
 | 
			
		||||
        padding.top += closeButtonHeight;
 | 
			
		||||
        padding.bottom += captionHeight;
 | 
			
		||||
        padding.left += leftBorder;
 | 
			
		||||
        padding.right += rightBorder;
 | 
			
		||||
        columnSpacing += rightBorder;
 | 
			
		||||
 | 
			
		||||
        let area = {
 | 
			
		||||
            x: this._x + padding.left,
 | 
			
		||||
            y: this._y + padding.top,
 | 
			
		||||
            width: this._width - padding.left - padding.right,
 | 
			
		||||
            height: this._height - padding.top - padding.bottom,
 | 
			
		||||
        };
 | 
			
		||||
        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);
 | 
			
		||||
            this._currentLayout = this._computeLayout(windows, area, rowSpacing, columnSpacing, captionHeight);
 | 
			
		||||
 | 
			
		||||
        let layout = this._currentLayout;
 | 
			
		||||
        let strategy = layout.strategy;
 | 
			
		||||
 
 | 
			
		||||
@@ -170,8 +170,7 @@ const WorkspaceThumbnail = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
 | 
			
		||||
 | 
			
		||||
        this._background = new Meta.BackgroundActor({ screen: global.screen,
 | 
			
		||||
                                                      settings: Main.background });
 | 
			
		||||
        this._background = Meta.BackgroundActor.new_for_screen(global.screen);
 | 
			
		||||
        this._contents.add_actor(this._background);
 | 
			
		||||
 | 
			
		||||
        let monitor = Main.layoutManager.primaryMonitor;
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,6 @@ eu
 | 
			
		||||
fa
 | 
			
		||||
fi
 | 
			
		||||
fr
 | 
			
		||||
fur
 | 
			
		||||
ga
 | 
			
		||||
gl
 | 
			
		||||
gu
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,6 @@ js/misc/util.js
 | 
			
		||||
js/ui/appDisplay.js
 | 
			
		||||
js/ui/appFavorites.js
 | 
			
		||||
js/ui/calendar.js
 | 
			
		||||
js/ui/components/automountManager.js
 | 
			
		||||
js/ui/components/autorunManager.js
 | 
			
		||||
js/ui/components/keyring.js
 | 
			
		||||
js/ui/components/networkAgent.js
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										237
									
								
								po/ar.po
									
									
									
									
									
								
							
							
						
						
									
										237
									
								
								po/ar.po
									
									
									
									
									
								
							@@ -8,7 +8,7 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: HEAD\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: \n"
 | 
			
		||||
"POT-Creation-Date: 2012-12-23 18:34+0200\n"
 | 
			
		||||
"POT-Creation-Date: 2012-12-09 04:45+0200\n"
 | 
			
		||||
"PO-Revision-Date: 2012-12-09 04:52+0200\n"
 | 
			
		||||
"Last-Translator: Khaled Hosny <khaledhosny@eglug.org>\n"
 | 
			
		||||
"Language-Team: Arabic <doc@arabeyes.org>\n"
 | 
			
		||||
@@ -365,8 +365,8 @@ msgstr "نافذة الولوج"
 | 
			
		||||
msgid "Power"
 | 
			
		||||
msgstr "الطاقة"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:675 ../js/ui/userMenu.js:679
 | 
			
		||||
#: ../js/ui/userMenu.js:790
 | 
			
		||||
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:674 ../js/ui/userMenu.js:678
 | 
			
		||||
#: ../js/ui/userMenu.js:789
 | 
			
		||||
msgid "Suspend"
 | 
			
		||||
msgstr "علّق"
 | 
			
		||||
 | 
			
		||||
@@ -374,8 +374,8 @@ msgstr "علّق"
 | 
			
		||||
msgid "Restart"
 | 
			
		||||
msgstr "أعِد التشغيل"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:677
 | 
			
		||||
#: ../js/ui/userMenu.js:679 ../js/ui/userMenu.js:789
 | 
			
		||||
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:676
 | 
			
		||||
#: ../js/ui/userMenu.js:678 ../js/ui/userMenu.js:788
 | 
			
		||||
msgid "Power Off"
 | 
			
		||||
msgstr "أطفئ الحاسوب"
 | 
			
		||||
 | 
			
		||||
@@ -410,19 +410,27 @@ msgid "Execution of '%s' failed:"
 | 
			
		||||
msgstr "فشل تنفيذ '%s':"
 | 
			
		||||
 | 
			
		||||
#. Translators: Filter to display all applications
 | 
			
		||||
#: ../js/ui/appDisplay.js:258
 | 
			
		||||
#: ../js/ui/appDisplay.js:259
 | 
			
		||||
msgid "All"
 | 
			
		||||
msgstr "الكل"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/appDisplay.js:666
 | 
			
		||||
#: ../js/ui/appDisplay.js:318
 | 
			
		||||
msgid "APPLICATIONS"
 | 
			
		||||
msgstr "التطبيقات"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/appDisplay.js:375
 | 
			
		||||
msgid "SETTINGS"
 | 
			
		||||
msgstr "الإعدادات"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/appDisplay.js:679
 | 
			
		||||
msgid "New Window"
 | 
			
		||||
msgstr "نافذة جديدة"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/appDisplay.js:669 ../js/ui/dash.js:289
 | 
			
		||||
#: ../js/ui/appDisplay.js:682 ../js/ui/dash.js:289
 | 
			
		||||
msgid "Remove from Favorites"
 | 
			
		||||
msgstr "أزِل من المفضّلة"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/appDisplay.js:670
 | 
			
		||||
#: ../js/ui/appDisplay.js:683
 | 
			
		||||
msgid "Add to Favorites"
 | 
			
		||||
msgstr "أضِف إلى المفضّلة"
 | 
			
		||||
 | 
			
		||||
@@ -439,19 +447,19 @@ msgstr "أُزيل %s من مفضّلتك."
 | 
			
		||||
#. Translators: Shown in calendar event list for all day events
 | 
			
		||||
#. * Keep it short, best if you can use less then 10 characters
 | 
			
		||||
#.
 | 
			
		||||
#: ../js/ui/calendar.js:61
 | 
			
		||||
#: ../js/ui/calendar.js:62
 | 
			
		||||
msgctxt "event list time"
 | 
			
		||||
msgid "All Day"
 | 
			
		||||
msgstr "طوال اليوم"
 | 
			
		||||
 | 
			
		||||
#. Translators: Shown in calendar event list, if 24h format
 | 
			
		||||
#: ../js/ui/calendar.js:66
 | 
			
		||||
#: ../js/ui/calendar.js:67
 | 
			
		||||
msgctxt "event list time"
 | 
			
		||||
msgid "%H:%M"
 | 
			
		||||
msgstr "%H:%M"
 | 
			
		||||
 | 
			
		||||
#. Transators: Shown in calendar event list, if 12h format
 | 
			
		||||
#: ../js/ui/calendar.js:73
 | 
			
		||||
#: ../js/ui/calendar.js:74
 | 
			
		||||
msgctxt "event list time"
 | 
			
		||||
msgid "%l:%M %p"
 | 
			
		||||
msgstr "%l:%M %p"
 | 
			
		||||
@@ -461,43 +469,43 @@ msgstr "%l:%M %p"
 | 
			
		||||
#. * NOTE: These grid abbreviations are always shown together
 | 
			
		||||
#. * and in order, e.g. "S M T W T F S".
 | 
			
		||||
#.
 | 
			
		||||
#: ../js/ui/calendar.js:104
 | 
			
		||||
#: ../js/ui/calendar.js:114
 | 
			
		||||
msgctxt "grid sunday"
 | 
			
		||||
msgid "S"
 | 
			
		||||
msgstr "ح"
 | 
			
		||||
 | 
			
		||||
#. Translators: Calendar grid abbreviation for Monday
 | 
			
		||||
#: ../js/ui/calendar.js:106
 | 
			
		||||
#: ../js/ui/calendar.js:116
 | 
			
		||||
msgctxt "grid monday"
 | 
			
		||||
msgid "M"
 | 
			
		||||
msgstr "ن"
 | 
			
		||||
 | 
			
		||||
#. Translators: Calendar grid abbreviation for Tuesday
 | 
			
		||||
#: ../js/ui/calendar.js:108
 | 
			
		||||
#: ../js/ui/calendar.js:118
 | 
			
		||||
msgctxt "grid tuesday"
 | 
			
		||||
msgid "T"
 | 
			
		||||
msgstr "ث"
 | 
			
		||||
 | 
			
		||||
#. Translators: Calendar grid abbreviation for Wednesday
 | 
			
		||||
#: ../js/ui/calendar.js:110
 | 
			
		||||
#: ../js/ui/calendar.js:120
 | 
			
		||||
msgctxt "grid wednesday"
 | 
			
		||||
msgid "W"
 | 
			
		||||
msgstr "ر"
 | 
			
		||||
 | 
			
		||||
#. Translators: Calendar grid abbreviation for Thursday
 | 
			
		||||
#: ../js/ui/calendar.js:112
 | 
			
		||||
#: ../js/ui/calendar.js:122
 | 
			
		||||
msgctxt "grid thursday"
 | 
			
		||||
msgid "T"
 | 
			
		||||
msgstr "خ"
 | 
			
		||||
 | 
			
		||||
#. Translators: Calendar grid abbreviation for Friday
 | 
			
		||||
#: ../js/ui/calendar.js:114
 | 
			
		||||
#: ../js/ui/calendar.js:124
 | 
			
		||||
msgctxt "grid friday"
 | 
			
		||||
msgid "F"
 | 
			
		||||
msgstr "ج"
 | 
			
		||||
 | 
			
		||||
#. Translators: Calendar grid abbreviation for Saturday
 | 
			
		||||
#: ../js/ui/calendar.js:116
 | 
			
		||||
#: ../js/ui/calendar.js:126
 | 
			
		||||
msgctxt "grid saturday"
 | 
			
		||||
msgid "S"
 | 
			
		||||
msgstr "س"
 | 
			
		||||
@@ -508,77 +516,77 @@ msgstr "س"
 | 
			
		||||
#. * so they need to be unique (e.g. Tuesday and Thursday cannot
 | 
			
		||||
#. * both be 'T').
 | 
			
		||||
#.
 | 
			
		||||
#: ../js/ui/calendar.js:129
 | 
			
		||||
#: ../js/ui/calendar.js:139
 | 
			
		||||
msgctxt "list sunday"
 | 
			
		||||
msgid "Su"
 | 
			
		||||
msgstr "الأحد"
 | 
			
		||||
 | 
			
		||||
#. Translators: Event list abbreviation for Monday
 | 
			
		||||
#: ../js/ui/calendar.js:131
 | 
			
		||||
#: ../js/ui/calendar.js:141
 | 
			
		||||
msgctxt "list monday"
 | 
			
		||||
msgid "M"
 | 
			
		||||
msgstr "الاثنين"
 | 
			
		||||
 | 
			
		||||
#. Translators: Event list abbreviation for Tuesday
 | 
			
		||||
#: ../js/ui/calendar.js:133
 | 
			
		||||
#: ../js/ui/calendar.js:143
 | 
			
		||||
msgctxt "list tuesday"
 | 
			
		||||
msgid "T"
 | 
			
		||||
msgstr "الثلاثاء"
 | 
			
		||||
 | 
			
		||||
#. Translators: Event list abbreviation for Wednesday
 | 
			
		||||
#: ../js/ui/calendar.js:135
 | 
			
		||||
#: ../js/ui/calendar.js:145
 | 
			
		||||
msgctxt "list wednesday"
 | 
			
		||||
msgid "W"
 | 
			
		||||
msgstr "الأربعاء"
 | 
			
		||||
 | 
			
		||||
#. Translators: Event list abbreviation for Thursday
 | 
			
		||||
#: ../js/ui/calendar.js:137
 | 
			
		||||
#: ../js/ui/calendar.js:147
 | 
			
		||||
msgctxt "list thursday"
 | 
			
		||||
msgid "Th"
 | 
			
		||||
msgstr "الخميس"
 | 
			
		||||
 | 
			
		||||
#. Translators: Event list abbreviation for Friday
 | 
			
		||||
#: ../js/ui/calendar.js:139
 | 
			
		||||
#: ../js/ui/calendar.js:149
 | 
			
		||||
msgctxt "list friday"
 | 
			
		||||
msgid "F"
 | 
			
		||||
msgstr "الجمعة"
 | 
			
		||||
 | 
			
		||||
#. Translators: Event list abbreviation for Saturday
 | 
			
		||||
#: ../js/ui/calendar.js:141
 | 
			
		||||
#: ../js/ui/calendar.js:151
 | 
			
		||||
msgctxt "list saturday"
 | 
			
		||||
msgid "S"
 | 
			
		||||
msgstr "السبت"
 | 
			
		||||
 | 
			
		||||
#. Translators: Text to show if there are no events
 | 
			
		||||
#: ../js/ui/calendar.js:674
 | 
			
		||||
#: ../js/ui/calendar.js:700
 | 
			
		||||
msgid "Nothing Scheduled"
 | 
			
		||||
msgstr "الجدول خال"
 | 
			
		||||
 | 
			
		||||
#. Translators: Shown on calendar heading when selected day occurs on current year
 | 
			
		||||
#: ../js/ui/calendar.js:690
 | 
			
		||||
#: ../js/ui/calendar.js:716
 | 
			
		||||
msgctxt "calendar heading"
 | 
			
		||||
msgid "%A, %B %d"
 | 
			
		||||
msgstr "%A %d %B"
 | 
			
		||||
 | 
			
		||||
#. Translators: Shown on calendar heading when selected day occurs on different year
 | 
			
		||||
#: ../js/ui/calendar.js:693
 | 
			
		||||
#: ../js/ui/calendar.js:719
 | 
			
		||||
msgctxt "calendar heading"
 | 
			
		||||
msgid "%A, %B %d, %Y"
 | 
			
		||||
msgstr "%A %d %B %Y"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/calendar.js:703
 | 
			
		||||
#: ../js/ui/calendar.js:729
 | 
			
		||||
msgid "Today"
 | 
			
		||||
msgstr "اليوم"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/calendar.js:707
 | 
			
		||||
#: ../js/ui/calendar.js:733
 | 
			
		||||
msgid "Tomorrow"
 | 
			
		||||
msgstr "غدا"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/calendar.js:718
 | 
			
		||||
#: ../js/ui/calendar.js:744
 | 
			
		||||
msgid "This week"
 | 
			
		||||
msgstr "هذا الأسبوع"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/calendar.js:726
 | 
			
		||||
#: ../js/ui/calendar.js:752
 | 
			
		||||
msgid "Next week"
 | 
			
		||||
msgstr "الأسبوع القادم"
 | 
			
		||||
 | 
			
		||||
@@ -940,7 +948,7 @@ msgstr "أظهر الحساب"
 | 
			
		||||
msgid "Unknown reason"
 | 
			
		||||
msgstr "السبب غير معروف"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:81
 | 
			
		||||
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:87
 | 
			
		||||
msgid "Windows"
 | 
			
		||||
msgstr "النوافذ"
 | 
			
		||||
 | 
			
		||||
@@ -1080,7 +1088,7 @@ msgstr "هل تريد تنزيل وتثبيت '%s' من extensions.gnome.org؟"
 | 
			
		||||
msgid "tray"
 | 
			
		||||
msgstr "لوحة النظام"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/keyboard.js:555 ../js/ui/status/keyboard.js:309
 | 
			
		||||
#: ../js/ui/keyboard.js:555 ../js/ui/status/keyboard.js:195
 | 
			
		||||
#: ../js/ui/status/power.js:205
 | 
			
		||||
msgid "Keyboard"
 | 
			
		||||
msgstr "لوحة المفاتيح"
 | 
			
		||||
@@ -1107,9 +1115,7 @@ msgstr "اظهر الأخطاء"
 | 
			
		||||
msgid "Enabled"
 | 
			
		||||
msgstr "مفعّل"
 | 
			
		||||
 | 
			
		||||
#. translators:
 | 
			
		||||
#. * The device has been disabled
 | 
			
		||||
#: ../js/ui/lookingGlass.js:767 ../src/gvc/gvc-mixer-control.c:1830
 | 
			
		||||
#: ../js/ui/lookingGlass.js:767
 | 
			
		||||
msgid "Disabled"
 | 
			
		||||
msgstr "معطّل"
 | 
			
		||||
 | 
			
		||||
@@ -1141,15 +1147,15 @@ msgstr "افتح"
 | 
			
		||||
msgid "Remove"
 | 
			
		||||
msgstr "أزِل"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:1552
 | 
			
		||||
#: ../js/ui/messageTray.js:1551
 | 
			
		||||
msgid "No Messages"
 | 
			
		||||
msgstr "لا رسائل"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:1570
 | 
			
		||||
#: ../js/ui/messageTray.js:1568
 | 
			
		||||
msgid "Message Tray"
 | 
			
		||||
msgstr "لوحة الرسائل"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:2639
 | 
			
		||||
#: ../js/ui/messageTray.js:2635
 | 
			
		||||
msgid "System Information"
 | 
			
		||||
msgstr "معلومات النظام"
 | 
			
		||||
 | 
			
		||||
@@ -1158,11 +1164,11 @@ msgctxt "program"
 | 
			
		||||
msgid "Unknown"
 | 
			
		||||
msgstr "غير معروف"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/overview.js:92
 | 
			
		||||
#: ../js/ui/overview.js:95
 | 
			
		||||
msgid "Undo"
 | 
			
		||||
msgstr "تراجع"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/overview.js:139
 | 
			
		||||
#: ../js/ui/overview.js:144
 | 
			
		||||
msgid "Overview"
 | 
			
		||||
msgstr "نظرة عامة"
 | 
			
		||||
 | 
			
		||||
@@ -1170,13 +1176,13 @@ msgstr "نظرة عامة"
 | 
			
		||||
#. in the search entry when no search is
 | 
			
		||||
#. active; it should not exceed ~30
 | 
			
		||||
#. characters.
 | 
			
		||||
#: ../js/ui/overview.js:218
 | 
			
		||||
#: ../js/ui/overview.js:221
 | 
			
		||||
msgid "Type to search..."
 | 
			
		||||
msgstr "اكتب نصا للبحث عنه..."
 | 
			
		||||
 | 
			
		||||
#. Translators: this is the name of the dock/favorites area on
 | 
			
		||||
#. the left of the overview
 | 
			
		||||
#: ../js/ui/overview.js:236
 | 
			
		||||
#: ../js/ui/overview.js:242
 | 
			
		||||
msgid "Dash"
 | 
			
		||||
msgstr "الشريط"
 | 
			
		||||
 | 
			
		||||
@@ -1199,7 +1205,7 @@ msgstr "الشريط العلوي"
 | 
			
		||||
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
 | 
			
		||||
#. switches containing "◯" and "|"). Other values will
 | 
			
		||||
#. simply result in invisible toggle switches.
 | 
			
		||||
#: ../js/ui/popupMenu.js:725
 | 
			
		||||
#: ../js/ui/popupMenu.js:732
 | 
			
		||||
msgid "toggle-switch-us"
 | 
			
		||||
msgstr "toggle-switch-intl"
 | 
			
		||||
 | 
			
		||||
@@ -1239,15 +1245,15 @@ msgstr[3] "%d تنبيهات جديدة"
 | 
			
		||||
msgstr[4] "%d تنبيها جديدا"
 | 
			
		||||
msgstr[5] "%d تنبيه جديد"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/screenShield.js:402 ../js/ui/userMenu.js:781
 | 
			
		||||
#: ../js/ui/screenShield.js:402 ../js/ui/userMenu.js:780
 | 
			
		||||
msgid "Lock"
 | 
			
		||||
msgstr "أوصِد"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/searchDisplay.js:403
 | 
			
		||||
#: ../js/ui/searchDisplay.js:277
 | 
			
		||||
msgid "Searching..."
 | 
			
		||||
msgstr "يبحث..."
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/searchDisplay.js:451
 | 
			
		||||
#: ../js/ui/searchDisplay.js:325
 | 
			
		||||
msgid "No results."
 | 
			
		||||
msgstr "لا نتائج."
 | 
			
		||||
 | 
			
		||||
@@ -1363,7 +1369,7 @@ msgid "disconnecting..."
 | 
			
		||||
msgstr "يقطع الاتّصال..."
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:220 ../js/ui/status/network.js:442
 | 
			
		||||
#: ../js/ui/status/network.js:1464
 | 
			
		||||
#: ../js/ui/status/network.js:1453
 | 
			
		||||
msgid "connecting..."
 | 
			
		||||
msgstr "يتّصل..."
 | 
			
		||||
 | 
			
		||||
@@ -1379,7 +1385,7 @@ msgstr "إعدادات لوحة المفاتيح"
 | 
			
		||||
msgid "Mouse Settings"
 | 
			
		||||
msgstr "إعدادات الفأرة"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:253 ../js/ui/status/volume.js:314
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:253 ../js/ui/status/volume.js:270
 | 
			
		||||
msgid "Sound Settings"
 | 
			
		||||
msgstr "إعدادات الصوت"
 | 
			
		||||
 | 
			
		||||
@@ -1443,15 +1449,15 @@ msgstr "من فضلك أدخل الرقم المذكور على الجهاز."
 | 
			
		||||
msgid "OK"
 | 
			
		||||
msgstr "حسنا"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/keyboard.js:363
 | 
			
		||||
#: ../js/ui/status/keyboard.js:228
 | 
			
		||||
msgid "Show Keyboard Layout"
 | 
			
		||||
msgstr "أظهر تخطيط لوحة المفاتيح"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/keyboard.js:368
 | 
			
		||||
#: ../js/ui/status/keyboard.js:233
 | 
			
		||||
msgid "Region and Language Settings"
 | 
			
		||||
msgstr "إعدادات الإقليم واللغة"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/lockScreenMenu.js:43
 | 
			
		||||
#: ../js/ui/status/lockScreenMenu.js:18
 | 
			
		||||
msgid "Volume, network, battery"
 | 
			
		||||
msgstr "الصوت، الشبكة، البطارية"
 | 
			
		||||
 | 
			
		||||
@@ -1471,7 +1477,7 @@ msgid "unmanaged"
 | 
			
		||||
msgstr "غير مُدار"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is for network connections that require some kind of key or password
 | 
			
		||||
#: ../js/ui/status/network.js:445 ../js/ui/status/network.js:1467
 | 
			
		||||
#: ../js/ui/status/network.js:445 ../js/ui/status/network.js:1456
 | 
			
		||||
msgid "authentication required"
 | 
			
		||||
msgstr "الاستيثاق مطلوب"
 | 
			
		||||
 | 
			
		||||
@@ -1492,72 +1498,72 @@ msgstr "الكبل مفصول"
 | 
			
		||||
msgid "unavailable"
 | 
			
		||||
msgstr "غير متاح"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:469 ../js/ui/status/network.js:1469
 | 
			
		||||
#: ../js/ui/status/network.js:469 ../js/ui/status/network.js:1458
 | 
			
		||||
msgid "connection failed"
 | 
			
		||||
msgstr "فشل الاتصال"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:525 ../js/ui/status/network.js:1403
 | 
			
		||||
#: ../js/ui/status/network.js:1545
 | 
			
		||||
#: ../js/ui/status/network.js:525 ../js/ui/status/network.js:1392
 | 
			
		||||
#: ../js/ui/status/network.js:1534
 | 
			
		||||
msgid "More..."
 | 
			
		||||
msgstr "المزيد..."
 | 
			
		||||
 | 
			
		||||
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
 | 
			
		||||
#. and we cannot access its settings (including the name)
 | 
			
		||||
#: ../js/ui/status/network.js:561 ../js/ui/status/network.js:1333
 | 
			
		||||
#: ../js/ui/status/network.js:561 ../js/ui/status/network.js:1322
 | 
			
		||||
msgid "Connected (private)"
 | 
			
		||||
msgstr "متّصل (شخصي)"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:641
 | 
			
		||||
#: ../js/ui/status/network.js:619
 | 
			
		||||
msgid "Auto Ethernet"
 | 
			
		||||
msgstr "إيثرنت تلقائي"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:688
 | 
			
		||||
#: ../js/ui/status/network.js:677
 | 
			
		||||
msgid "Auto broadband"
 | 
			
		||||
msgstr "شبكة هاتف محمول تلقائية"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:691
 | 
			
		||||
#: ../js/ui/status/network.js:680
 | 
			
		||||
msgid "Auto dial-up"
 | 
			
		||||
msgstr "اتصال هاتفي تلقائي"
 | 
			
		||||
 | 
			
		||||
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
 | 
			
		||||
#: ../js/ui/status/network.js:820 ../js/ui/status/network.js:1350
 | 
			
		||||
#: ../js/ui/status/network.js:809 ../js/ui/status/network.js:1339
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Auto %s"
 | 
			
		||||
msgstr "%s تلقائي"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:822
 | 
			
		||||
#: ../js/ui/status/network.js:811
 | 
			
		||||
msgid "Auto bluetooth"
 | 
			
		||||
msgstr "بلوتوث تلقائي"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1352
 | 
			
		||||
#: ../js/ui/status/network.js:1341
 | 
			
		||||
msgid "Auto wireless"
 | 
			
		||||
msgstr "لاسلكي تلقائي"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1595
 | 
			
		||||
#: ../js/ui/status/network.js:1584
 | 
			
		||||
msgid "Enable networking"
 | 
			
		||||
msgstr "فعّل الشبكات"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1627
 | 
			
		||||
#: ../js/ui/status/network.js:1616
 | 
			
		||||
msgid "Wi-Fi"
 | 
			
		||||
msgstr "واي فاي"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1646
 | 
			
		||||
#: ../js/ui/status/network.js:1635
 | 
			
		||||
msgid "Network Settings"
 | 
			
		||||
msgstr "إعدادات الشّبكة"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1692
 | 
			
		||||
#: ../js/ui/status/network.js:1679
 | 
			
		||||
msgid "Network Manager"
 | 
			
		||||
msgstr "مدير الشبكة"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1774
 | 
			
		||||
#: ../js/ui/status/network.js:1761
 | 
			
		||||
msgid "Connection failed"
 | 
			
		||||
msgstr "فشل الاتصال"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1775
 | 
			
		||||
#: ../js/ui/status/network.js:1762
 | 
			
		||||
msgid "Activation of network connection failed"
 | 
			
		||||
msgstr "فشل تفعيل اتصال الشبكة"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:2092
 | 
			
		||||
#: ../js/ui/status/network.js:2079
 | 
			
		||||
msgid "Networking is disabled"
 | 
			
		||||
msgstr "عُطّلت الشبكات"
 | 
			
		||||
 | 
			
		||||
@@ -1675,11 +1681,11 @@ msgid "Unknown"
 | 
			
		||||
msgstr "غير معروف"
 | 
			
		||||
 | 
			
		||||
#. Translators: This is the label for audio volume
 | 
			
		||||
#: ../js/ui/status/volume.js:247 ../js/ui/status/volume.js:295
 | 
			
		||||
#: ../js/ui/status/volume.js:50 ../js/ui/status/volume.js:251
 | 
			
		||||
msgid "Volume"
 | 
			
		||||
msgstr "شدة الصوت"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/volume.js:256
 | 
			
		||||
#: ../js/ui/status/volume.js:62
 | 
			
		||||
msgid "Microphone"
 | 
			
		||||
msgstr "ميكروفون"
 | 
			
		||||
 | 
			
		||||
@@ -1715,31 +1721,31 @@ msgstr "ساكن"
 | 
			
		||||
msgid "Offline"
 | 
			
		||||
msgstr "غير متصل"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:755
 | 
			
		||||
#: ../js/ui/userMenu.js:754
 | 
			
		||||
msgid "Notifications"
 | 
			
		||||
msgstr "التنبيهات"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:763
 | 
			
		||||
#: ../js/ui/userMenu.js:762
 | 
			
		||||
msgid "Settings"
 | 
			
		||||
msgstr "الإعدادات"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:771
 | 
			
		||||
#: ../js/ui/userMenu.js:770
 | 
			
		||||
msgid "Switch User"
 | 
			
		||||
msgstr "بدّل المستخدم"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:776
 | 
			
		||||
#: ../js/ui/userMenu.js:775
 | 
			
		||||
msgid "Log Out"
 | 
			
		||||
msgstr "اخرج"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:796
 | 
			
		||||
#: ../js/ui/userMenu.js:795
 | 
			
		||||
msgid "Install Updates & Restart"
 | 
			
		||||
msgstr "ثبّت التحديثات وأعد التشغيل"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:814
 | 
			
		||||
#: ../js/ui/userMenu.js:813
 | 
			
		||||
msgid "Your chat status will be set to busy"
 | 
			
		||||
msgstr "ستُجعل حالة اتصالك ”مشغول“"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:815
 | 
			
		||||
#: ../js/ui/userMenu.js:814
 | 
			
		||||
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."
 | 
			
		||||
@@ -1747,15 +1753,15 @@ msgstr ""
 | 
			
		||||
"التنبيهات معطلة الآن، بما فيها رسائل المحادثة. حالة اتصالك تغيرت حتى يعلم "
 | 
			
		||||
"الآخرون أنك قد لا ترى رسائلهم."
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/viewSelector.js:85
 | 
			
		||||
#: ../js/ui/viewSelector.js:91
 | 
			
		||||
msgid "Applications"
 | 
			
		||||
msgstr "التطبيقات"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/viewSelector.js:89
 | 
			
		||||
#: ../js/ui/viewSelector.js:95
 | 
			
		||||
msgid "Search"
 | 
			
		||||
msgstr "ابحث"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/wanda.js:92
 | 
			
		||||
#: ../js/ui/wanda.js:94
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Sorry, no wisdom for you today:\n"
 | 
			
		||||
@@ -1764,11 +1770,15 @@ msgstr ""
 | 
			
		||||
"عذرًا, لا حكمة لك اليوم:\n"
 | 
			
		||||
"%s"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/wanda.js:96
 | 
			
		||||
#: ../js/ui/wanda.js:98
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s the Oracle says"
 | 
			
		||||
msgstr "يقول الحكيم %s"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/wanda.js:139
 | 
			
		||||
msgid "Your favorite Easter Egg"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/windowAttentionHandler.js:19
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "'%s' is ready"
 | 
			
		||||
@@ -1778,36 +1788,6 @@ msgstr "'%s' جاهز"
 | 
			
		||||
msgid "Evolution Calendar"
 | 
			
		||||
msgstr "تقويم إيفُليوشِن"
 | 
			
		||||
 | 
			
		||||
#. translators:
 | 
			
		||||
#. * The number of sound outputs on a particular device
 | 
			
		||||
#: ../src/gvc/gvc-mixer-control.c:1837
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%u Output"
 | 
			
		||||
msgid_plural "%u Outputs"
 | 
			
		||||
msgstr[0] "لا مخرَج"
 | 
			
		||||
msgstr[1] "مخرَج واحد"
 | 
			
		||||
msgstr[2] "مخرَجين"
 | 
			
		||||
msgstr[3] "%u مخارج"
 | 
			
		||||
msgstr[4] "%u مخرجا"
 | 
			
		||||
msgstr[5] "%u مخرج"
 | 
			
		||||
 | 
			
		||||
#. translators:
 | 
			
		||||
#. * The number of sound inputs on a particular device
 | 
			
		||||
#: ../src/gvc/gvc-mixer-control.c:1847
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%u Input"
 | 
			
		||||
msgid_plural "%u Inputs"
 | 
			
		||||
msgstr[0] "لا مدخل"
 | 
			
		||||
msgstr[1] "مدخل واحد"
 | 
			
		||||
msgstr[2] "مدخلين"
 | 
			
		||||
msgstr[3] "%u مداخل"
 | 
			
		||||
msgstr[4] "%u مدخلا"
 | 
			
		||||
msgstr[5] "%u مدخل"
 | 
			
		||||
 | 
			
		||||
#: ../src/gvc/gvc-mixer-control.c:2371
 | 
			
		||||
msgid "System Sounds"
 | 
			
		||||
msgstr "أصوات النظام"
 | 
			
		||||
 | 
			
		||||
#: ../src/main.c:332
 | 
			
		||||
msgid "Print version"
 | 
			
		||||
msgstr "اطبع الإصدارة"
 | 
			
		||||
@@ -1849,12 +1829,6 @@ msgstr "المبدئي"
 | 
			
		||||
msgid "Authentication dialog was dismissed by the user"
 | 
			
		||||
msgstr "أغلق المستخدم مربع الاستيثاق الحِواري"
 | 
			
		||||
 | 
			
		||||
#~ msgid "APPLICATIONS"
 | 
			
		||||
#~ msgstr "التطبيقات"
 | 
			
		||||
 | 
			
		||||
#~ msgid "SETTINGS"
 | 
			
		||||
#~ msgstr "الإعدادات"
 | 
			
		||||
 | 
			
		||||
#~ msgid "Subscription request"
 | 
			
		||||
#~ msgstr "طلب اشتراك"
 | 
			
		||||
 | 
			
		||||
@@ -1903,6 +1877,27 @@ msgstr "أغلق المستخدم مربع الاستيثاق الحِواري"
 | 
			
		||||
#~ msgid "System Settings"
 | 
			
		||||
#~ msgstr "إعدادات النظام"
 | 
			
		||||
 | 
			
		||||
#~ msgid "%u Output"
 | 
			
		||||
#~ msgid_plural "%u Outputs"
 | 
			
		||||
#~ msgstr[0] "لا مخرَج"
 | 
			
		||||
#~ msgstr[1] "مخرَج واحد"
 | 
			
		||||
#~ msgstr[2] "مخرَجين"
 | 
			
		||||
#~ msgstr[3] "%u مخارج"
 | 
			
		||||
#~ msgstr[4] "%u مخرجا"
 | 
			
		||||
#~ msgstr[5] "%u مخرج"
 | 
			
		||||
 | 
			
		||||
#~ msgid "%u Input"
 | 
			
		||||
#~ msgid_plural "%u Inputs"
 | 
			
		||||
#~ msgstr[0] "لا مدخل"
 | 
			
		||||
#~ msgstr[1] "مدخل واحد"
 | 
			
		||||
#~ msgstr[2] "مدخلين"
 | 
			
		||||
#~ msgstr[3] "%u مداخل"
 | 
			
		||||
#~ msgstr[4] "%u مدخلا"
 | 
			
		||||
#~ msgstr[5] "%u مدخل"
 | 
			
		||||
 | 
			
		||||
#~ msgid "System Sounds"
 | 
			
		||||
#~ msgstr "أصوات النظام"
 | 
			
		||||
 | 
			
		||||
#~ msgid "Failed to unmount '%s'"
 | 
			
		||||
#~ msgstr "فشل فصْل '%s'"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								po/et.po
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								po/et.po
									
									
									
									
									
								
							@@ -14,7 +14,7 @@ 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-12-09 13:03+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2012-12-19 16:47+0300\n"
 | 
			
		||||
"PO-Revision-Date: 2012-12-18 17:13+0300\n"
 | 
			
		||||
"Last-Translator: Mattias Põldaru <mahfiaz@gmail.com>\n"
 | 
			
		||||
"Language-Team: Estonian <>\n"
 | 
			
		||||
"Language: et\n"
 | 
			
		||||
@@ -153,8 +153,8 @@ msgid ""
 | 
			
		||||
"state of the checkbox."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Shell küsib parooli, kui haagitakse krüpteeritud seade või kaugfailisüsteem. "
 | 
			
		||||
"Kui parooli on võimalik salvestada edaspidiseks kasutuseks, näidatakse "
 | 
			
		||||
"'Salvesta parool' märkeruutu. See võti määrab selle märkeruudu vaikimisi "
 | 
			
		||||
"Kui parooli on võimalik salvestada järgmise kasutuse jaoks, näidatakse "
 | 
			
		||||
"\"Jäta parool meelde\" märkeruutu. See võti määrab märkeruudu vaikimisi "
 | 
			
		||||
"oleku."
 | 
			
		||||
 | 
			
		||||
msgid "Show the week date in the calendar"
 | 
			
		||||
@@ -257,9 +257,9 @@ msgid ""
 | 
			
		||||
"are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-"
 | 
			
		||||
"only' (shows only the application icon) or 'both'."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Seadistab, kuidas aknaid aknavahetajas kuvatakse. Sobivad väärtused on "
 | 
			
		||||
"'thumbnail-only' (näidatakse ainult pisipilti aknast), 'app-icon-"
 | 
			
		||||
"only' (näidatakse ainult akna ikooni) või 'both' (mõlemad)."
 | 
			
		||||
"Seadistab, kuidas aknaid akendevahetajas kuvatakse. Sobivad väärtused on "
 | 
			
		||||
"'thumbnail-only' (näidatakse ainult pisipilti), 'app-icon-only' (näidatakse "
 | 
			
		||||
"ainult rakenduse ikooni) või 'both' (näidatakse mõlemaid)."
 | 
			
		||||
 | 
			
		||||
msgid "Attach modal dialog to the parent window"
 | 
			
		||||
msgstr "Modaaldialoog kuulub vanemakna juurde"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1061
									
								
								po/pt_BR.po
									
									
									
									
									
								
							
							
						
						
									
										1061
									
								
								po/pt_BR.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										344
									
								
								po/sk.po
									
									
									
									
									
								
							
							
						
						
									
										344
									
								
								po/sk.po
									
									
									
									
									
								
							@@ -10,8 +10,8 @@ msgstr ""
 | 
			
		||||
"Project-Id-Version: gnome-shell\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
 | 
			
		||||
"shell&keywords=I18N+L10N&component=general\n"
 | 
			
		||||
"POT-Creation-Date: 2013-01-08 18:17+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2013-01-01 17:50+0100\n"
 | 
			
		||||
"POT-Creation-Date: 2012-12-09 02:53+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2012-11-19 22:23+0100\n"
 | 
			
		||||
"Last-Translator: Dušan Kazik <prescott66@gmail.com>\n"
 | 
			
		||||
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
 | 
			
		||||
"Language: sk\n"
 | 
			
		||||
@@ -40,7 +40,7 @@ msgstr "Zobrazí lištu správ"
 | 
			
		||||
 | 
			
		||||
#: ../data/50-gnome-shell-system.xml.in.h:3
 | 
			
		||||
msgid "Focus the active notification"
 | 
			
		||||
msgstr "Zamerať aktívne oznámenie"
 | 
			
		||||
msgstr "Zamerať na aktívne oznámenia"
 | 
			
		||||
 | 
			
		||||
# tooltip
 | 
			
		||||
#: ../data/50-gnome-shell-system.xml.in.h:4
 | 
			
		||||
@@ -166,23 +166,20 @@ msgstr ""
 | 
			
		||||
"s jedným používateľom alebo jednou reláciou."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
 | 
			
		||||
#, fuzzy
 | 
			
		||||
#| msgid "Always show the 'Log out' menuitem in the user menu."
 | 
			
		||||
msgid "Show full name in the user menu"
 | 
			
		||||
msgstr "Zobraziť celé meno v ponuke používateľa"
 | 
			
		||||
msgstr "Vždy zobraziť položku „Odhlásiť sa“ v ponuke používateľa"
 | 
			
		||||
 | 
			
		||||
# description
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16
 | 
			
		||||
msgid "Whether the users full name is shown in the user menu or not."
 | 
			
		||||
msgstr "Určuje, či bude alebo nebude zobrazené celé meno v ponuke používateľa."
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
# summary
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17
 | 
			
		||||
msgid ""
 | 
			
		||||
"Whether to remember password for mounting encrypted or remote filesystems"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Určiť, či bude zapamätané heslo pre pripojenie zašifrovaných alebo "
 | 
			
		||||
"prenosných súborových systémov"
 | 
			
		||||
 | 
			
		||||
# description
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
 | 
			
		||||
msgid ""
 | 
			
		||||
"The shell will request a password when an encrypted device or a remote "
 | 
			
		||||
@@ -190,10 +187,6 @@ msgid ""
 | 
			
		||||
"'Remember Password' checkbox will be present. This key sets the default "
 | 
			
		||||
"state of the checkbox."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Shell bude po pripojení zašifrovaného alebo prenosného súborového systému "
 | 
			
		||||
"požadovať heslo. Ak bude možné toto heslo uložiť pre neskoršie použitie, "
 | 
			
		||||
"zobrazí sa zaškrtávacie pole „Zapamätať heslo“. Tento kľúč nastaví "
 | 
			
		||||
"predvolený stav zaškrtávacieho poľa."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
 | 
			
		||||
msgid "Show the week date in the calendar"
 | 
			
		||||
@@ -316,11 +309,11 @@ msgstr ""
 | 
			
		||||
"základe aktuálneho dátumu a použije túto príponu. Pri nahrávaní do iného "
 | 
			
		||||
"formátu kontajneru by mala byť zmenená."
 | 
			
		||||
 | 
			
		||||
# PM: tento preklad podľa mňa nezodpovedá nasledujúcemu dlhému popisu nastavenia. Ide skor o režim tvorby ikon (z) aplikácií
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:40
 | 
			
		||||
#, fuzzy
 | 
			
		||||
#| msgid "Open the application menu"
 | 
			
		||||
msgid "The application icon mode."
 | 
			
		||||
msgstr "Režim aplikácií s ikonami."
 | 
			
		||||
msgstr "Otvorí ponuku aplikácií"
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:41
 | 
			
		||||
msgid ""
 | 
			
		||||
@@ -328,9 +321,6 @@ msgid ""
 | 
			
		||||
"are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-"
 | 
			
		||||
"only' (shows only the application icon) or 'both'."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Konfiguruje, ako sa majú zobraziť okná v prepínači. Platné možnosti sú "
 | 
			
		||||
"„thumbnail-only“ (zobrazí miniatúru okna), „app-icon-only“ (zobrazí iba "
 | 
			
		||||
"ikonu aplikácie) alebo „both“ (zobrazí oboje)."
 | 
			
		||||
 | 
			
		||||
#: ../data/org.gnome.shell.gschema.xml.in.in.h:42
 | 
			
		||||
msgid "Attach modal dialog to the parent window"
 | 
			
		||||
@@ -378,11 +368,11 @@ msgstr "Rozšírenie"
 | 
			
		||||
msgid "Select an extension to configure using the combobox above."
 | 
			
		||||
msgstr "Použitím ponuky vyberte rozšírenie na nastavenie"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/loginDialog.js:566
 | 
			
		||||
#: ../js/gdm/loginDialog.js:565
 | 
			
		||||
msgid "Session..."
 | 
			
		||||
msgstr "Relácia…"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/loginDialog.js:723
 | 
			
		||||
#: ../js/gdm/loginDialog.js:722
 | 
			
		||||
msgctxt "title"
 | 
			
		||||
msgid "Sign In"
 | 
			
		||||
msgstr "Prihlásenie"
 | 
			
		||||
@@ -391,35 +381,35 @@ msgstr "Prihlásenie"
 | 
			
		||||
#. 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:787
 | 
			
		||||
#: ../js/gdm/loginDialog.js:786
 | 
			
		||||
msgid "Not listed?"
 | 
			
		||||
msgstr "Nie ste v zozname?"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/loginDialog.js:963 ../js/ui/components/networkAgent.js:137
 | 
			
		||||
#: ../js/gdm/loginDialog.js:962 ../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:399
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:413 ../js/ui/unlockDialog.js:178
 | 
			
		||||
msgid "Cancel"
 | 
			
		||||
msgstr "Zrušiť"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/loginDialog.js:979
 | 
			
		||||
#: ../js/gdm/loginDialog.js:978
 | 
			
		||||
msgctxt "button"
 | 
			
		||||
msgid "Sign In"
 | 
			
		||||
msgstr "Prihlásiť sa"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/loginDialog.js:979
 | 
			
		||||
#: ../js/gdm/loginDialog.js:978
 | 
			
		||||
msgid "Next"
 | 
			
		||||
msgstr "Ďalej"
 | 
			
		||||
 | 
			
		||||
#. TTLS and PEAP are actually much more complicated, but this complication
 | 
			
		||||
#. is not visible here since we only care about phase2 authentication
 | 
			
		||||
#. (and don't even care of which one)
 | 
			
		||||
#: ../js/gdm/loginDialog.js:1087 ../js/ui/components/networkAgent.js:260
 | 
			
		||||
#: ../js/gdm/loginDialog.js:1086 ../js/ui/components/networkAgent.js:260
 | 
			
		||||
#: ../js/ui/components/networkAgent.js:278
 | 
			
		||||
msgid "Username: "
 | 
			
		||||
msgstr "Používateľské meno: "
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/loginDialog.js:1383
 | 
			
		||||
#: ../js/gdm/loginDialog.js:1382
 | 
			
		||||
msgid "Login Window"
 | 
			
		||||
msgstr "Prihlasovacie okno"
 | 
			
		||||
 | 
			
		||||
@@ -428,8 +418,8 @@ msgstr "Prihlasovacie okno"
 | 
			
		||||
msgid "Power"
 | 
			
		||||
msgstr "Napájanie"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:675 ../js/ui/userMenu.js:679
 | 
			
		||||
#: ../js/ui/userMenu.js:790
 | 
			
		||||
#: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:674 ../js/ui/userMenu.js:678
 | 
			
		||||
#: ../js/ui/userMenu.js:789
 | 
			
		||||
msgid "Suspend"
 | 
			
		||||
msgstr "Uspať"
 | 
			
		||||
 | 
			
		||||
@@ -437,8 +427,8 @@ msgstr "Uspať"
 | 
			
		||||
msgid "Restart"
 | 
			
		||||
msgstr "Reštartovať"
 | 
			
		||||
 | 
			
		||||
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:677
 | 
			
		||||
#: ../js/ui/userMenu.js:679 ../js/ui/userMenu.js:789
 | 
			
		||||
#: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:676
 | 
			
		||||
#: ../js/ui/userMenu.js:678 ../js/ui/userMenu.js:788
 | 
			
		||||
msgid "Power Off"
 | 
			
		||||
msgstr "Vypnúť"
 | 
			
		||||
 | 
			
		||||
@@ -473,19 +463,27 @@ msgid "Execution of '%s' failed:"
 | 
			
		||||
msgstr "Spustenie „%s“ zlyhalo:"
 | 
			
		||||
 | 
			
		||||
#. Translators: Filter to display all applications
 | 
			
		||||
#: ../js/ui/appDisplay.js:258
 | 
			
		||||
#: ../js/ui/appDisplay.js:259
 | 
			
		||||
msgid "All"
 | 
			
		||||
msgstr "Všetky"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/appDisplay.js:666
 | 
			
		||||
#: ../js/ui/appDisplay.js:318
 | 
			
		||||
msgid "APPLICATIONS"
 | 
			
		||||
msgstr "APLIKÁCIE"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/appDisplay.js:375
 | 
			
		||||
msgid "SETTINGS"
 | 
			
		||||
msgstr "NASTAVENIA"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/appDisplay.js:679
 | 
			
		||||
msgid "New Window"
 | 
			
		||||
msgstr "Nové okno"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/appDisplay.js:669 ../js/ui/dash.js:289
 | 
			
		||||
#: ../js/ui/appDisplay.js:682 ../js/ui/dash.js:289
 | 
			
		||||
msgid "Remove from Favorites"
 | 
			
		||||
msgstr "Odstrániť z obľúbených"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/appDisplay.js:670
 | 
			
		||||
#: ../js/ui/appDisplay.js:683
 | 
			
		||||
msgid "Add to Favorites"
 | 
			
		||||
msgstr "Pridať do obľúbených"
 | 
			
		||||
 | 
			
		||||
@@ -502,19 +500,19 @@ msgstr "Program %s bol odstránený z obľúbených."
 | 
			
		||||
#. Translators: Shown in calendar event list for all day events
 | 
			
		||||
#. * Keep it short, best if you can use less then 10 characters
 | 
			
		||||
#.
 | 
			
		||||
#: ../js/ui/calendar.js:61
 | 
			
		||||
#: ../js/ui/calendar.js:62
 | 
			
		||||
msgctxt "event list time"
 | 
			
		||||
msgid "All Day"
 | 
			
		||||
msgstr "Celý deň"
 | 
			
		||||
 | 
			
		||||
#. Translators: Shown in calendar event list, if 24h format
 | 
			
		||||
#: ../js/ui/calendar.js:66
 | 
			
		||||
#: ../js/ui/calendar.js:67
 | 
			
		||||
msgctxt "event list time"
 | 
			
		||||
msgid "%H:%M"
 | 
			
		||||
msgstr "%H:%M"
 | 
			
		||||
 | 
			
		||||
#. Transators: Shown in calendar event list, if 12h format
 | 
			
		||||
#: ../js/ui/calendar.js:73
 | 
			
		||||
#: ../js/ui/calendar.js:74
 | 
			
		||||
msgctxt "event list time"
 | 
			
		||||
msgid "%l:%M %p"
 | 
			
		||||
msgstr "%l:%M %p"
 | 
			
		||||
@@ -524,43 +522,43 @@ msgstr "%l:%M %p"
 | 
			
		||||
#. * NOTE: These grid abbreviations are always shown together
 | 
			
		||||
#. * and in order, e.g. "S M T W T F S".
 | 
			
		||||
#.
 | 
			
		||||
#: ../js/ui/calendar.js:104
 | 
			
		||||
#: ../js/ui/calendar.js:114
 | 
			
		||||
msgctxt "grid sunday"
 | 
			
		||||
msgid "S"
 | 
			
		||||
msgstr "Ne"
 | 
			
		||||
 | 
			
		||||
#. Translators: Calendar grid abbreviation for Monday
 | 
			
		||||
#: ../js/ui/calendar.js:106
 | 
			
		||||
#: ../js/ui/calendar.js:116
 | 
			
		||||
msgctxt "grid monday"
 | 
			
		||||
msgid "M"
 | 
			
		||||
msgstr "Po"
 | 
			
		||||
 | 
			
		||||
#. Translators: Calendar grid abbreviation for Tuesday
 | 
			
		||||
#: ../js/ui/calendar.js:108
 | 
			
		||||
#: ../js/ui/calendar.js:118
 | 
			
		||||
msgctxt "grid tuesday"
 | 
			
		||||
msgid "T"
 | 
			
		||||
msgstr "Ut"
 | 
			
		||||
 | 
			
		||||
#. Translators: Calendar grid abbreviation for Wednesday
 | 
			
		||||
#: ../js/ui/calendar.js:110
 | 
			
		||||
#: ../js/ui/calendar.js:120
 | 
			
		||||
msgctxt "grid wednesday"
 | 
			
		||||
msgid "W"
 | 
			
		||||
msgstr "St"
 | 
			
		||||
 | 
			
		||||
#. Translators: Calendar grid abbreviation for Thursday
 | 
			
		||||
#: ../js/ui/calendar.js:112
 | 
			
		||||
#: ../js/ui/calendar.js:122
 | 
			
		||||
msgctxt "grid thursday"
 | 
			
		||||
msgid "T"
 | 
			
		||||
msgstr "Št"
 | 
			
		||||
 | 
			
		||||
#. Translators: Calendar grid abbreviation for Friday
 | 
			
		||||
#: ../js/ui/calendar.js:114
 | 
			
		||||
#: ../js/ui/calendar.js:124
 | 
			
		||||
msgctxt "grid friday"
 | 
			
		||||
msgid "F"
 | 
			
		||||
msgstr "Pi"
 | 
			
		||||
 | 
			
		||||
#. Translators: Calendar grid abbreviation for Saturday
 | 
			
		||||
#: ../js/ui/calendar.js:116
 | 
			
		||||
#: ../js/ui/calendar.js:126
 | 
			
		||||
msgctxt "grid saturday"
 | 
			
		||||
msgid "S"
 | 
			
		||||
msgstr "So"
 | 
			
		||||
@@ -571,77 +569,77 @@ msgstr "So"
 | 
			
		||||
#. * so they need to be unique (e.g. Tuesday and Thursday cannot
 | 
			
		||||
#. * both be 'T').
 | 
			
		||||
#.
 | 
			
		||||
#: ../js/ui/calendar.js:129
 | 
			
		||||
#: ../js/ui/calendar.js:139
 | 
			
		||||
msgctxt "list sunday"
 | 
			
		||||
msgid "Su"
 | 
			
		||||
msgstr "Ne"
 | 
			
		||||
 | 
			
		||||
#. Translators: Event list abbreviation for Monday
 | 
			
		||||
#: ../js/ui/calendar.js:131
 | 
			
		||||
#: ../js/ui/calendar.js:141
 | 
			
		||||
msgctxt "list monday"
 | 
			
		||||
msgid "M"
 | 
			
		||||
msgstr "Po"
 | 
			
		||||
 | 
			
		||||
#. Translators: Event list abbreviation for Tuesday
 | 
			
		||||
#: ../js/ui/calendar.js:133
 | 
			
		||||
#: ../js/ui/calendar.js:143
 | 
			
		||||
msgctxt "list tuesday"
 | 
			
		||||
msgid "T"
 | 
			
		||||
msgstr "Ut"
 | 
			
		||||
 | 
			
		||||
#. Translators: Event list abbreviation for Wednesday
 | 
			
		||||
#: ../js/ui/calendar.js:135
 | 
			
		||||
#: ../js/ui/calendar.js:145
 | 
			
		||||
msgctxt "list wednesday"
 | 
			
		||||
msgid "W"
 | 
			
		||||
msgstr "St"
 | 
			
		||||
 | 
			
		||||
#. Translators: Event list abbreviation for Thursday
 | 
			
		||||
#: ../js/ui/calendar.js:137
 | 
			
		||||
#: ../js/ui/calendar.js:147
 | 
			
		||||
msgctxt "list thursday"
 | 
			
		||||
msgid "Th"
 | 
			
		||||
msgstr "Št"
 | 
			
		||||
 | 
			
		||||
#. Translators: Event list abbreviation for Friday
 | 
			
		||||
#: ../js/ui/calendar.js:139
 | 
			
		||||
#: ../js/ui/calendar.js:149
 | 
			
		||||
msgctxt "list friday"
 | 
			
		||||
msgid "F"
 | 
			
		||||
msgstr "Pi"
 | 
			
		||||
 | 
			
		||||
#. Translators: Event list abbreviation for Saturday
 | 
			
		||||
#: ../js/ui/calendar.js:141
 | 
			
		||||
#: ../js/ui/calendar.js:151
 | 
			
		||||
msgctxt "list saturday"
 | 
			
		||||
msgid "S"
 | 
			
		||||
msgstr "So"
 | 
			
		||||
 | 
			
		||||
#. Translators: Text to show if there are no events
 | 
			
		||||
#: ../js/ui/calendar.js:674
 | 
			
		||||
#: ../js/ui/calendar.js:700
 | 
			
		||||
msgid "Nothing Scheduled"
 | 
			
		||||
msgstr "Žiadne naplánované udalosti"
 | 
			
		||||
 | 
			
		||||
#. Translators: Shown on calendar heading when selected day occurs on current year
 | 
			
		||||
#: ../js/ui/calendar.js:690
 | 
			
		||||
#: ../js/ui/calendar.js:716
 | 
			
		||||
msgctxt "calendar heading"
 | 
			
		||||
msgid "%A, %B %d"
 | 
			
		||||
msgstr "%A, %e. %B"
 | 
			
		||||
 | 
			
		||||
#. Translators: Shown on calendar heading when selected day occurs on different year
 | 
			
		||||
#: ../js/ui/calendar.js:693
 | 
			
		||||
#: ../js/ui/calendar.js:719
 | 
			
		||||
msgctxt "calendar heading"
 | 
			
		||||
msgid "%A, %B %d, %Y"
 | 
			
		||||
msgstr "%A, %e. %B %Y"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/calendar.js:703
 | 
			
		||||
#: ../js/ui/calendar.js:729
 | 
			
		||||
msgid "Today"
 | 
			
		||||
msgstr "Dnes"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/calendar.js:707
 | 
			
		||||
#: ../js/ui/calendar.js:733
 | 
			
		||||
msgid "Tomorrow"
 | 
			
		||||
msgstr "Zajtra"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/calendar.js:718
 | 
			
		||||
#: ../js/ui/calendar.js:744
 | 
			
		||||
msgid "This week"
 | 
			
		||||
msgstr "Tento týždeň"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/calendar.js:726
 | 
			
		||||
#: ../js/ui/calendar.js:752
 | 
			
		||||
msgid "Next week"
 | 
			
		||||
msgstr "Ďalší týždeň"
 | 
			
		||||
 | 
			
		||||
@@ -659,11 +657,11 @@ msgstr "Otvoriť pomocou programu %s"
 | 
			
		||||
msgid "Eject"
 | 
			
		||||
msgstr "Vysunúť"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/keyring.js:82 ../js/ui/components/polkitAgent.js:268
 | 
			
		||||
#: ../js/ui/components/keyring.js:86 ../js/ui/components/polkitAgent.js:260
 | 
			
		||||
msgid "Password:"
 | 
			
		||||
msgstr "Heslo:"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/keyring.js:101
 | 
			
		||||
#: ../js/ui/components/keyring.js:105
 | 
			
		||||
msgid "Type again:"
 | 
			
		||||
msgstr "Zadajte znovu:"
 | 
			
		||||
 | 
			
		||||
@@ -752,7 +750,7 @@ msgstr "Požaduje sa overenie totožnosti"
 | 
			
		||||
msgid "Administrator"
 | 
			
		||||
msgstr "Správca"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/polkitAgent.js:165
 | 
			
		||||
#: ../js/ui/components/polkitAgent.js:166
 | 
			
		||||
msgid "Authenticate"
 | 
			
		||||
msgstr "Overiť totožnosť"
 | 
			
		||||
 | 
			
		||||
@@ -760,7 +758,7 @@ msgstr "Overiť totožnosť"
 | 
			
		||||
#. * requested authentication was not gained; this can happen
 | 
			
		||||
#. * because of an authentication error (like invalid password),
 | 
			
		||||
#. * for instance.
 | 
			
		||||
#: ../js/ui/components/polkitAgent.js:256 ../js/ui/shellMountOperation.js:383
 | 
			
		||||
#: ../js/ui/components/polkitAgent.js:248 ../js/ui/shellMountOperation.js:383
 | 
			
		||||
msgid "Sorry, that didn't work. Please try again."
 | 
			
		||||
msgstr "Prepáčte, ale nezabralo to. Skúste to, prosím, znova."
 | 
			
		||||
 | 
			
		||||
@@ -789,7 +787,7 @@ msgstr "Prenos súborov"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:417
 | 
			
		||||
msgid "Chat"
 | 
			
		||||
msgstr "Rozhovor"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:477
 | 
			
		||||
msgid "Unmute"
 | 
			
		||||
@@ -803,25 +801,28 @@ msgstr "Stlmiť"
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:931
 | 
			
		||||
#, no-c-format
 | 
			
		||||
msgid "<b>Yesterday</b>, <b>%H:%M</b>"
 | 
			
		||||
msgstr "<b>Včera</b> o <b>%H:%M</b>"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#. Translators: this is the week day name followed by a time string. i.e. "Monday, 14:30
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:937
 | 
			
		||||
#, no-c-format
 | 
			
		||||
#, fuzzy, no-c-format
 | 
			
		||||
#| msgid "<b>%H:%M</b> on <b>%A</b>"
 | 
			
		||||
msgid "<b>%A</b>, <b>%H:%M</b>"
 | 
			
		||||
msgstr "v <b>%A</b> o <b>%H:%M</b>"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is the month name and day number followed by a time string. i.e. "May 25, 14:30"
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:942
 | 
			
		||||
#, no-c-format
 | 
			
		||||
#, fuzzy, no-c-format
 | 
			
		||||
#| msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>"
 | 
			
		||||
msgid "<b>%B</b> <b>%d</b>, <b>%H:%M</b>"
 | 
			
		||||
msgstr "<b>%e.</b> <b>%B</b> o <b>%H:%M</b>"
 | 
			
		||||
msgstr "v <b>%A</b> o <b>%H:%M</b>, <b>%e.</b> <b>%B</b>"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is the month name, day number, year number followed by a time string. i.e. "May 25 2012, 14:30"
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:946
 | 
			
		||||
#, no-c-format
 | 
			
		||||
#, fuzzy, no-c-format
 | 
			
		||||
#| msgid "<b>%H:%M</b> on <b>%A</b>, <b>%B</b> <b>%d</b>"
 | 
			
		||||
msgid "<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> "
 | 
			
		||||
msgstr "<b>%e.</b> <b>%B</b> <b>%Y</b> o <b>%H:%M</b>"
 | 
			
		||||
msgstr "v <b>%A</b> o <b>%H:%M</b>, <b>%e.</b> <b>%B</b>"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is the other person changing their old IM name to their new
 | 
			
		||||
#. IM name.
 | 
			
		||||
@@ -1000,17 +1001,19 @@ msgstr "Vnútorná chyba"
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1339
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Unable to connect to %s"
 | 
			
		||||
msgstr "Nepodarilo sa pripojiť účet %s"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1344
 | 
			
		||||
#, fuzzy
 | 
			
		||||
#| msgid "Edit account"
 | 
			
		||||
msgid "View account"
 | 
			
		||||
msgstr "Zobraziť účet"
 | 
			
		||||
msgstr "Upraviť účet"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/components/telepathyClient.js:1384
 | 
			
		||||
msgid "Unknown reason"
 | 
			
		||||
msgstr "Neznámy dôvod"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:81
 | 
			
		||||
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:87
 | 
			
		||||
msgid "Windows"
 | 
			
		||||
msgstr "Okná"
 | 
			
		||||
 | 
			
		||||
@@ -1019,18 +1022,18 @@ msgstr "Okná"
 | 
			
		||||
msgid "Show Applications"
 | 
			
		||||
msgstr "Zobrazí aplikácie"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/dateMenu.js:87
 | 
			
		||||
#: ../js/ui/dateMenu.js:86
 | 
			
		||||
msgid "Date and Time Settings"
 | 
			
		||||
msgstr "Nastavenia dátumu a času"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/dateMenu.js:112
 | 
			
		||||
#: ../js/ui/dateMenu.js:111
 | 
			
		||||
msgid "Open Calendar"
 | 
			
		||||
msgstr "Otvoriť kalendár"
 | 
			
		||||
 | 
			
		||||
#. 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:191
 | 
			
		||||
#: ../js/ui/dateMenu.js:201
 | 
			
		||||
msgid "%A %B %e, %Y"
 | 
			
		||||
msgstr "%A, %e. %B %Y"
 | 
			
		||||
 | 
			
		||||
@@ -1139,81 +1142,85 @@ msgstr "Inštalovať"
 | 
			
		||||
msgid "Download and install '%s' from extensions.gnome.org?"
 | 
			
		||||
msgstr "Stiahnuť a nainštalovať „%s“ z extensions.gnome.org?"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/keyboard.js:291
 | 
			
		||||
#: ../js/ui/keyboard.js:308
 | 
			
		||||
msgid "tray"
 | 
			
		||||
msgstr "lišta"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/keyboard.js:636 ../js/ui/status/keyboard.js:309
 | 
			
		||||
#: ../js/ui/keyboard.js:555 ../js/ui/status/keyboard.js:195
 | 
			
		||||
#: ../js/ui/status/power.js:205
 | 
			
		||||
msgid "Keyboard"
 | 
			
		||||
msgstr "Klávesnica"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/lookingGlass.js:692
 | 
			
		||||
#: ../js/ui/lookingGlass.js:691
 | 
			
		||||
msgid "No extensions installed"
 | 
			
		||||
msgstr "Žiadne nainštalované rozšírenia"
 | 
			
		||||
 | 
			
		||||
#. Translators: argument is an extension UUID.
 | 
			
		||||
#: ../js/ui/lookingGlass.js:746
 | 
			
		||||
#: ../js/ui/lookingGlass.js:745
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s has not emitted any errors."
 | 
			
		||||
msgstr "%s nevyslal žiadnu chybu."
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/lookingGlass.js:752
 | 
			
		||||
#: ../js/ui/lookingGlass.js:751
 | 
			
		||||
msgid "Hide Errors"
 | 
			
		||||
msgstr "Skryť chyby"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/lookingGlass.js:756 ../js/ui/lookingGlass.js:816
 | 
			
		||||
#: ../js/ui/lookingGlass.js:755 ../js/ui/lookingGlass.js:815
 | 
			
		||||
msgid "Show Errors"
 | 
			
		||||
msgstr "Zobraziť chyby"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/lookingGlass.js:765
 | 
			
		||||
#: ../js/ui/lookingGlass.js:764
 | 
			
		||||
msgid "Enabled"
 | 
			
		||||
msgstr "Povolené"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/lookingGlass.js:768
 | 
			
		||||
#: ../js/ui/lookingGlass.js:767
 | 
			
		||||
msgid "Disabled"
 | 
			
		||||
msgstr "Zakázané"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/lookingGlass.js:770
 | 
			
		||||
#: ../js/ui/lookingGlass.js:769
 | 
			
		||||
msgid "Error"
 | 
			
		||||
msgstr "Chyba"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/lookingGlass.js:772
 | 
			
		||||
#: ../js/ui/lookingGlass.js:771
 | 
			
		||||
msgid "Out of date"
 | 
			
		||||
msgstr "Neaktuálne"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/lookingGlass.js:774
 | 
			
		||||
#: ../js/ui/lookingGlass.js:773
 | 
			
		||||
msgid "Downloading"
 | 
			
		||||
msgstr "Sťahuje sa"
 | 
			
		||||
 | 
			
		||||
# PK: ide tu o zdrojovy kod?
 | 
			
		||||
#: ../js/ui/lookingGlass.js:798
 | 
			
		||||
#: ../js/ui/lookingGlass.js:797
 | 
			
		||||
msgid "View Source"
 | 
			
		||||
msgstr "Zobraziť zdroj"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/lookingGlass.js:807
 | 
			
		||||
#: ../js/ui/lookingGlass.js:806
 | 
			
		||||
msgid "Web Page"
 | 
			
		||||
msgstr "Webová stránka"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:1090
 | 
			
		||||
#: ../js/ui/messageTray.js:1088
 | 
			
		||||
msgid "Open"
 | 
			
		||||
msgstr "Otvoriť"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:1097
 | 
			
		||||
#: ../js/ui/messageTray.js:1095
 | 
			
		||||
msgid "Remove"
 | 
			
		||||
msgstr "Odstrániť"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:1554
 | 
			
		||||
# DK: zvazoval som pouzit "Panel správ"
 | 
			
		||||
# neviem co bude vhodnejsie ako preklad "tray"
 | 
			
		||||
#: ../js/ui/messageTray.js:1551
 | 
			
		||||
#, fuzzy
 | 
			
		||||
#| msgid "Message Tray"
 | 
			
		||||
msgid "No Messages"
 | 
			
		||||
msgstr "Žiadne správy"
 | 
			
		||||
msgstr "Lišta správ"
 | 
			
		||||
 | 
			
		||||
# DK: zvazoval som pouzit "Panel správ"
 | 
			
		||||
# neviem co bude vhodnejsie ako preklad "tray"
 | 
			
		||||
#: ../js/ui/messageTray.js:1572
 | 
			
		||||
#: ../js/ui/messageTray.js:1568
 | 
			
		||||
msgid "Message Tray"
 | 
			
		||||
msgstr "Lišta správ"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/messageTray.js:2641
 | 
			
		||||
#: ../js/ui/messageTray.js:2635
 | 
			
		||||
msgid "System Information"
 | 
			
		||||
msgstr "Informácie o systéme"
 | 
			
		||||
 | 
			
		||||
@@ -1222,11 +1229,11 @@ msgctxt "program"
 | 
			
		||||
msgid "Unknown"
 | 
			
		||||
msgstr "Neznámy"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/overview.js:92
 | 
			
		||||
#: ../js/ui/overview.js:95
 | 
			
		||||
msgid "Undo"
 | 
			
		||||
msgstr "Vrátiť"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/overview.js:139
 | 
			
		||||
#: ../js/ui/overview.js:144
 | 
			
		||||
msgid "Overview"
 | 
			
		||||
msgstr "Prehľad"
 | 
			
		||||
 | 
			
		||||
@@ -1234,27 +1241,27 @@ msgstr "Prehľad"
 | 
			
		||||
#. in the search entry when no search is
 | 
			
		||||
#. active; it should not exceed ~30
 | 
			
		||||
#. characters.
 | 
			
		||||
#: ../js/ui/overview.js:218
 | 
			
		||||
#: ../js/ui/overview.js:221
 | 
			
		||||
msgid "Type to search..."
 | 
			
		||||
msgstr "Vyhľadávanie…"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is the name of the dock/favorites area on
 | 
			
		||||
#. the left of the overview
 | 
			
		||||
#: ../js/ui/overview.js:236
 | 
			
		||||
#: ../js/ui/overview.js:242
 | 
			
		||||
msgid "Dash"
 | 
			
		||||
msgstr "Dok"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/panel.js:613
 | 
			
		||||
#: ../js/ui/panel.js:608
 | 
			
		||||
msgid "Quit"
 | 
			
		||||
msgstr "Ukončiť"
 | 
			
		||||
 | 
			
		||||
#. Translators: If there is no suitable word for "Activities"
 | 
			
		||||
#. in your language, you can use the word for "Overview".
 | 
			
		||||
#: ../js/ui/panel.js:642
 | 
			
		||||
#: ../js/ui/panel.js:637
 | 
			
		||||
msgid "Activities"
 | 
			
		||||
msgstr "Aktivity"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/panel.js:976
 | 
			
		||||
#: ../js/ui/panel.js:980
 | 
			
		||||
msgid "Top Bar"
 | 
			
		||||
msgstr "Horná lišta"
 | 
			
		||||
 | 
			
		||||
@@ -1263,7 +1270,7 @@ msgstr "Horná lišta"
 | 
			
		||||
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
 | 
			
		||||
#. switches containing "◯" and "|"). Other values will
 | 
			
		||||
#. simply result in invisible toggle switches.
 | 
			
		||||
#: ../js/ui/popupMenu.js:727
 | 
			
		||||
#: ../js/ui/popupMenu.js:732
 | 
			
		||||
msgid "toggle-switch-us"
 | 
			
		||||
msgstr "toggle-switch-intl"
 | 
			
		||||
 | 
			
		||||
@@ -1280,11 +1287,11 @@ msgstr "Zavrieť"
 | 
			
		||||
# v ostatnych retazcoch je pouzite %e, tak to bude asi OK
 | 
			
		||||
#. Translators: This is a time format for a date in
 | 
			
		||||
#. long format
 | 
			
		||||
#: ../js/ui/screenShield.js:113
 | 
			
		||||
#: ../js/ui/screenShield.js:112
 | 
			
		||||
msgid "%A, %B %d"
 | 
			
		||||
msgstr "%A, %e. %B"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/screenShield.js:177
 | 
			
		||||
#: ../js/ui/screenShield.js:176
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%d new message"
 | 
			
		||||
msgid_plural "%d new messages"
 | 
			
		||||
@@ -1292,7 +1299,7 @@ msgstr[0] "%d nových správ"
 | 
			
		||||
msgstr[1] "%d nová správa"
 | 
			
		||||
msgstr[2] "%d nové správy"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/screenShield.js:179
 | 
			
		||||
#: ../js/ui/screenShield.js:178
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%d new notification"
 | 
			
		||||
msgid_plural "%d new notifications"
 | 
			
		||||
@@ -1300,15 +1307,15 @@ msgstr[0] "%d nových oznámení"
 | 
			
		||||
msgstr[1] "%d nové oznámenie"
 | 
			
		||||
msgstr[2] "%d nové oznámenia"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/screenShield.js:403 ../js/ui/userMenu.js:781
 | 
			
		||||
#: ../js/ui/screenShield.js:402 ../js/ui/userMenu.js:780
 | 
			
		||||
msgid "Lock"
 | 
			
		||||
msgstr "Uzamknúť"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/searchDisplay.js:403
 | 
			
		||||
#: ../js/ui/searchDisplay.js:277
 | 
			
		||||
msgid "Searching..."
 | 
			
		||||
msgstr "Hľadá sa…"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/searchDisplay.js:451
 | 
			
		||||
#: ../js/ui/searchDisplay.js:325
 | 
			
		||||
msgid "No results."
 | 
			
		||||
msgstr "Žiadne výsledky."
 | 
			
		||||
 | 
			
		||||
@@ -1427,7 +1434,7 @@ msgid "disconnecting..."
 | 
			
		||||
msgstr "odpája sa…"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:220 ../js/ui/status/network.js:442
 | 
			
		||||
#: ../js/ui/status/network.js:1464
 | 
			
		||||
#: ../js/ui/status/network.js:1453
 | 
			
		||||
msgid "connecting..."
 | 
			
		||||
msgstr "pripája sa…"
 | 
			
		||||
 | 
			
		||||
@@ -1443,7 +1450,7 @@ msgstr "Nastavenia klávesnice"
 | 
			
		||||
msgid "Mouse Settings"
 | 
			
		||||
msgstr "Nastavenia myši"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:253 ../js/ui/status/volume.js:314
 | 
			
		||||
#: ../js/ui/status/bluetooth.js:253 ../js/ui/status/volume.js:270
 | 
			
		||||
msgid "Sound Settings"
 | 
			
		||||
msgstr "Nastavenia zvuku"
 | 
			
		||||
 | 
			
		||||
@@ -1507,15 +1514,15 @@ msgstr "Zadajte PIN, ktoré je uvedené na zariadení."
 | 
			
		||||
msgid "OK"
 | 
			
		||||
msgstr "Ok"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/keyboard.js:363
 | 
			
		||||
#: ../js/ui/status/keyboard.js:228
 | 
			
		||||
msgid "Show Keyboard Layout"
 | 
			
		||||
msgstr "Zobraziť rozloženie klávesnice"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/keyboard.js:368
 | 
			
		||||
#: ../js/ui/status/keyboard.js:233
 | 
			
		||||
msgid "Region and Language Settings"
 | 
			
		||||
msgstr "Miestne a jazykové nastavenia"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/lockScreenMenu.js:43
 | 
			
		||||
#: ../js/ui/status/lockScreenMenu.js:18
 | 
			
		||||
msgid "Volume, network, battery"
 | 
			
		||||
msgstr "Hlasitosť, sieť, batéria"
 | 
			
		||||
 | 
			
		||||
@@ -1536,7 +1543,7 @@ msgid "unmanaged"
 | 
			
		||||
msgstr "nespravované"
 | 
			
		||||
 | 
			
		||||
#. Translators: this is for network connections that require some kind of key or password
 | 
			
		||||
#: ../js/ui/status/network.js:445 ../js/ui/status/network.js:1467
 | 
			
		||||
#: ../js/ui/status/network.js:445 ../js/ui/status/network.js:1456
 | 
			
		||||
msgid "authentication required"
 | 
			
		||||
msgstr "požaduje sa overenie totožnosti"
 | 
			
		||||
 | 
			
		||||
@@ -1557,72 +1564,72 @@ msgstr "kábel odpojený"
 | 
			
		||||
msgid "unavailable"
 | 
			
		||||
msgstr "nedostupné"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:469 ../js/ui/status/network.js:1469
 | 
			
		||||
#: ../js/ui/status/network.js:469 ../js/ui/status/network.js:1458
 | 
			
		||||
msgid "connection failed"
 | 
			
		||||
msgstr "pripojenie zlyhalo"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:525 ../js/ui/status/network.js:1403
 | 
			
		||||
#: ../js/ui/status/network.js:1545
 | 
			
		||||
#: ../js/ui/status/network.js:525 ../js/ui/status/network.js:1392
 | 
			
		||||
#: ../js/ui/status/network.js:1534
 | 
			
		||||
msgid "More..."
 | 
			
		||||
msgstr "Viac…"
 | 
			
		||||
 | 
			
		||||
#. 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:561 ../js/ui/status/network.js:1333
 | 
			
		||||
#: ../js/ui/status/network.js:561 ../js/ui/status/network.js:1322
 | 
			
		||||
msgid "Connected (private)"
 | 
			
		||||
msgstr "Pripojené (súkromne)"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:641
 | 
			
		||||
#: ../js/ui/status/network.js:619
 | 
			
		||||
msgid "Auto Ethernet"
 | 
			
		||||
msgstr "Automatický ethernet"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:688
 | 
			
		||||
#: ../js/ui/status/network.js:677
 | 
			
		||||
msgid "Auto broadband"
 | 
			
		||||
msgstr "Automatické širokopásmové pripojenie"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:691
 | 
			
		||||
#: ../js/ui/status/network.js:680
 | 
			
		||||
msgid "Auto dial-up"
 | 
			
		||||
msgstr "Automatické vytáčané pripojenie"
 | 
			
		||||
 | 
			
		||||
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
 | 
			
		||||
#: ../js/ui/status/network.js:820 ../js/ui/status/network.js:1350
 | 
			
		||||
#: ../js/ui/status/network.js:809 ../js/ui/status/network.js:1339
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "Auto %s"
 | 
			
		||||
msgstr "Automatické pripojenie %s"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:822
 | 
			
		||||
#: ../js/ui/status/network.js:811
 | 
			
		||||
msgid "Auto bluetooth"
 | 
			
		||||
msgstr "Automatický bluetooth"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1352
 | 
			
		||||
#: ../js/ui/status/network.js:1341
 | 
			
		||||
msgid "Auto wireless"
 | 
			
		||||
msgstr "Automatická bezdrôtová sieť"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1595
 | 
			
		||||
#: ../js/ui/status/network.js:1584
 | 
			
		||||
msgid "Enable networking"
 | 
			
		||||
msgstr "Povoliť sieť"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1627
 | 
			
		||||
#: ../js/ui/status/network.js:1616
 | 
			
		||||
msgid "Wi-Fi"
 | 
			
		||||
msgstr "Wi-Fi"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1646
 | 
			
		||||
#: ../js/ui/status/network.js:1635
 | 
			
		||||
msgid "Network Settings"
 | 
			
		||||
msgstr "Nastavenia siete"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1692
 | 
			
		||||
#: ../js/ui/status/network.js:1679
 | 
			
		||||
msgid "Network Manager"
 | 
			
		||||
msgstr "Správca siete"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1774
 | 
			
		||||
#: ../js/ui/status/network.js:1761
 | 
			
		||||
msgid "Connection failed"
 | 
			
		||||
msgstr "Pripojenie zlyhalo"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:1775
 | 
			
		||||
#: ../js/ui/status/network.js:1762
 | 
			
		||||
msgid "Activation of network connection failed"
 | 
			
		||||
msgstr "Aktivácia pripojenia k sieti zlyhala"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/network.js:2092
 | 
			
		||||
#: ../js/ui/status/network.js:2079
 | 
			
		||||
msgid "Networking is disabled"
 | 
			
		||||
msgstr "Sieť je zakázaná"
 | 
			
		||||
 | 
			
		||||
@@ -1728,19 +1735,19 @@ msgid "Unknown"
 | 
			
		||||
msgstr "Neznáme"
 | 
			
		||||
 | 
			
		||||
#. Translators: This is the label for audio volume
 | 
			
		||||
#: ../js/ui/status/volume.js:247 ../js/ui/status/volume.js:295
 | 
			
		||||
#: ../js/ui/status/volume.js:50 ../js/ui/status/volume.js:251
 | 
			
		||||
msgid "Volume"
 | 
			
		||||
msgstr "Hlasitosť"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/status/volume.js:256
 | 
			
		||||
#: ../js/ui/status/volume.js:62
 | 
			
		||||
msgid "Microphone"
 | 
			
		||||
msgstr "Mikrofón"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/unlockDialog.js:203
 | 
			
		||||
#: ../js/ui/unlockDialog.js:201
 | 
			
		||||
msgid "Log in as another user"
 | 
			
		||||
msgstr "Prihlásiť ako iný používateľ"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/unlockDialog.js:229
 | 
			
		||||
#: ../js/ui/unlockDialog.js:224
 | 
			
		||||
msgid "Unlock Window"
 | 
			
		||||
msgstr "Odomykacie okno"
 | 
			
		||||
 | 
			
		||||
@@ -1768,31 +1775,31 @@ msgstr "Nečinný"
 | 
			
		||||
msgid "Offline"
 | 
			
		||||
msgstr "Odhlásený"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:755
 | 
			
		||||
#: ../js/ui/userMenu.js:754
 | 
			
		||||
msgid "Notifications"
 | 
			
		||||
msgstr "Upozornenia"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:763
 | 
			
		||||
#: ../js/ui/userMenu.js:762
 | 
			
		||||
msgid "Settings"
 | 
			
		||||
msgstr "Nastavenia"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:771
 | 
			
		||||
#: ../js/ui/userMenu.js:770
 | 
			
		||||
msgid "Switch User"
 | 
			
		||||
msgstr "Prepnúť používateľa"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:776
 | 
			
		||||
#: ../js/ui/userMenu.js:775
 | 
			
		||||
msgid "Log Out"
 | 
			
		||||
msgstr "Odhlásiť sa"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:796
 | 
			
		||||
#: ../js/ui/userMenu.js:795
 | 
			
		||||
msgid "Install Updates & Restart"
 | 
			
		||||
msgstr "Nainštalovať aktualizácie a reštartovať"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:814
 | 
			
		||||
#: ../js/ui/userMenu.js:813
 | 
			
		||||
msgid "Your chat status will be set to busy"
 | 
			
		||||
msgstr "Váš stav bude nastavený na zaneprázdnený"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/userMenu.js:815
 | 
			
		||||
#: ../js/ui/userMenu.js:814
 | 
			
		||||
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."
 | 
			
		||||
@@ -1800,15 +1807,15 @@ msgstr ""
 | 
			
		||||
"Oznámenia, vrátane správ rozhovoru, sú teraz zakázané. Váš stav online bol "
 | 
			
		||||
"nastavený tak, aby ostatní vedeli, že nemusíte vidieť ich správy."
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/viewSelector.js:85
 | 
			
		||||
#: ../js/ui/viewSelector.js:91
 | 
			
		||||
msgid "Applications"
 | 
			
		||||
msgstr "Aplikácie"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/viewSelector.js:89
 | 
			
		||||
#: ../js/ui/viewSelector.js:95
 | 
			
		||||
msgid "Search"
 | 
			
		||||
msgstr "Hľadať"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/wanda.js:92
 | 
			
		||||
#: ../js/ui/wanda.js:94
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid ""
 | 
			
		||||
"Sorry, no wisdom for you today:\n"
 | 
			
		||||
@@ -1817,11 +1824,15 @@ msgstr ""
 | 
			
		||||
"Prepáčte, dnes nie je pre vás pripravená žiadna múdrosť:\n"
 | 
			
		||||
"%s"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/wanda.js:96
 | 
			
		||||
#: ../js/ui/wanda.js:98
 | 
			
		||||
#, c-format
 | 
			
		||||
msgid "%s the Oracle says"
 | 
			
		||||
msgstr "Veštec hovorí %s"
 | 
			
		||||
 | 
			
		||||
#: ../js/ui/wanda.js:139
 | 
			
		||||
msgid "Your favorite Easter Egg"
 | 
			
		||||
msgstr "Vaše obľúbené veľkonočné vajce"
 | 
			
		||||
 | 
			
		||||
# %s je totiž titulok okna
 | 
			
		||||
# informacna bublina
 | 
			
		||||
#: ../js/ui/windowAttentionHandler.js:19
 | 
			
		||||
@@ -1876,30 +1887,6 @@ msgstr "Predvolený"
 | 
			
		||||
msgid "Authentication dialog was dismissed by the user"
 | 
			
		||||
msgstr "Dialógové okno overenia totožnosti bolo zatvorené používateľom"
 | 
			
		||||
 | 
			
		||||
#~ msgid "APPLICATIONS"
 | 
			
		||||
#~ msgstr "APLIKÁCIE"
 | 
			
		||||
 | 
			
		||||
#~ msgid "SETTINGS"
 | 
			
		||||
#~ msgstr "NASTAVENIA"
 | 
			
		||||
 | 
			
		||||
#~ msgid "Your favorite Easter Egg"
 | 
			
		||||
#~ msgstr "Vaše obľúbené veľkonočné vajce"
 | 
			
		||||
 | 
			
		||||
#~ msgid "%u Output"
 | 
			
		||||
#~ msgid_plural "%u Outputs"
 | 
			
		||||
#~ msgstr[0] "%u výstupov"
 | 
			
		||||
#~ msgstr[1] "%u výstup"
 | 
			
		||||
#~ msgstr[2] "%u výstupy"
 | 
			
		||||
 | 
			
		||||
#~ msgid "%u Input"
 | 
			
		||||
#~ msgid_plural "%u Inputs"
 | 
			
		||||
#~ msgstr[0] "%u vstupov"
 | 
			
		||||
#~ msgstr[1] "%u vstup"
 | 
			
		||||
#~ msgstr[2] "%u vstupy"
 | 
			
		||||
 | 
			
		||||
#~ msgid "System Sounds"
 | 
			
		||||
#~ msgstr "Zvuky systému"
 | 
			
		||||
 | 
			
		||||
#~ msgid "Subscription request"
 | 
			
		||||
#~ msgstr "Žiadosť o potvrdenie prístupu"
 | 
			
		||||
 | 
			
		||||
@@ -1917,3 +1904,18 @@ msgstr "Dialógové okno overenia totožnosti bolo zatvorené používateľom"
 | 
			
		||||
 | 
			
		||||
#~ msgid "Reconnect"
 | 
			
		||||
#~ msgstr "Znovu sa pripojiť"
 | 
			
		||||
 | 
			
		||||
#~ msgid "%u Output"
 | 
			
		||||
#~ msgid_plural "%u Outputs"
 | 
			
		||||
#~ msgstr[0] "%u výstupov"
 | 
			
		||||
#~ msgstr[1] "%u výstup"
 | 
			
		||||
#~ msgstr[2] "%u výstupy"
 | 
			
		||||
 | 
			
		||||
#~ msgid "%u Input"
 | 
			
		||||
#~ msgid_plural "%u Inputs"
 | 
			
		||||
#~ msgstr[0] "%u vstupov"
 | 
			
		||||
#~ msgstr[1] "%u vstup"
 | 
			
		||||
#~ msgstr[2] "%u vstupy"
 | 
			
		||||
 | 
			
		||||
#~ msgid "System Sounds"
 | 
			
		||||
#~ msgstr "Zvuky systému"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										846
									
								
								po/sr@latin.po
									
									
									
									
									
								
							
							
						
						
									
										846
									
								
								po/sr@latin.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										830
									
								
								po/zh_CN.po
									
									
									
									
									
								
							
							
						
						
									
										830
									
								
								po/zh_CN.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										893
									
								
								po/zh_HK.po
									
									
									
									
									
								
							
							
						
						
									
										893
									
								
								po/zh_HK.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										900
									
								
								po/zh_TW.po
									
									
									
									
									
								
							
							
						
						
									
										900
									
								
								po/zh_TW.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -115,7 +115,6 @@ shell_public_headers_h =		\
 | 
			
		||||
	shell-gtk-embed.h		\
 | 
			
		||||
	shell-global.h			\
 | 
			
		||||
	shell-invert-lightness-effect.h	\
 | 
			
		||||
	shell-keybinding-modes.h	\
 | 
			
		||||
	shell-mobile-providers.h	\
 | 
			
		||||
	shell-mount-operation.h		\
 | 
			
		||||
	shell-network-agent.h		\
 | 
			
		||||
@@ -292,7 +291,7 @@ libgnome_shell_la_LIBADD =		\
 | 
			
		||||
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
 | 
			
		||||
 | 
			
		||||
Shell-0.1.gir: libgnome-shell.la St-1.0.gir
 | 
			
		||||
Shell_0_1_gir_INCLUDES = Clutter-1.0 ClutterX11-1.0 Meta-3.0 TelepathyGLib-0.12 TelepathyLogger-0.2 Soup-2.4 GMenu-3.0 NetworkManager-1.0 NMClient-1.0 xlib-2.0
 | 
			
		||||
Shell_0_1_gir_INCLUDES = Clutter-1.0 ClutterX11-1.0 Meta-3.0 TelepathyGLib-0.12 TelepathyLogger-0.2 Soup-2.4 GMenu-3.0 NetworkManager-1.0 NMClient-1.0
 | 
			
		||||
Shell_0_1_gir_CFLAGS = $(libgnome_shell_la_CPPFLAGS) -I $(srcdir)
 | 
			
		||||
Shell_0_1_gir_LIBS = libgnome-shell.la
 | 
			
		||||
Shell_0_1_gir_FILES = $(libgnome_shell_la_gir_sources)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,12 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
 | 
			
		||||
if [ -z "$GI_TYPELIB_PATH" ]; then
 | 
			
		||||
if [ -n "$GI_TYPELIB_PATH" ]; then
 | 
			
		||||
    export GI_TYPELIB_PATH=@pkglibdir@
 | 
			
		||||
else
 | 
			
		||||
    export GI_TYPELIB_PATH=@pkglibdir@:$GI_TYPELIB_PATH
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -z "$LD_LIBRARY_PATH" ] ; then
 | 
			
		||||
if [ -n "$LD_LIBRARY_PATH" ] ; then
 | 
			
		||||
    export LD_LIBRARY_PATH=@pkglibdir@
 | 
			
		||||
else
 | 
			
		||||
    export LD_LIBRARY_PATH=@pkglibdir@:$LD_LIBRARY_PATH
 | 
			
		||||
 
 | 
			
		||||
@@ -75,8 +75,9 @@ def start_shell():
 | 
			
		||||
        if 'GI_TYPELIB_PATH' in os.environ:
 | 
			
		||||
            typelib_dir += ':%s' % (os.environ['GI_TYPELIB_PATH'],)
 | 
			
		||||
 | 
			
		||||
        env.update({'GI_TYPELIB_PATH'      : typelib_dir,
 | 
			
		||||
                    'GNOME_SHELL_JS'       : os.path.join(top_dir, "js"),
 | 
			
		||||
        env.update({'GNOME_SHELL_JS'       : os.path.join(top_dir, "js"),
 | 
			
		||||
                    'GNOME_SHELL_BINDIR'   : self_dir,
 | 
			
		||||
                    'GI_TYPELIB_PATH'      : typelib_dir,
 | 
			
		||||
                    'GNOME_SHELL_DATADIR'  : os.path.join(top_dir, "data"),
 | 
			
		||||
                    'GSETTINGS_SCHEMA_DIR' : os.path.join(top_dir, "data") })
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -284,44 +284,12 @@ gnome_shell_plugin_kill_switch_workspace (MetaPlugin         *plugin)
 | 
			
		||||
  _shell_wm_kill_switch_workspace (get_shell_wm());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
ignore_crossing_event (MetaPlugin   *plugin,
 | 
			
		||||
                       XIEnterEvent *enter_event)
 | 
			
		||||
{
 | 
			
		||||
  MetaScreen *screen = meta_plugin_get_screen (plugin);
 | 
			
		||||
  ClutterStage *stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
 | 
			
		||||
 | 
			
		||||
  if (enter_event->event == clutter_x11_get_stage_window (stage))
 | 
			
		||||
    {
 | 
			
		||||
      /* If the pointer enters a child of the stage window (eg, a
 | 
			
		||||
       * trayicon), we want to consider it to still be in the stage,
 | 
			
		||||
       * so don't let Clutter see the event.
 | 
			
		||||
       */
 | 
			
		||||
      if (enter_event->detail == XINotifyInferior)
 | 
			
		||||
        return TRUE;
 | 
			
		||||
 | 
			
		||||
      /* If the pointer is grabbed by a window it is not currently in,
 | 
			
		||||
       * filter that out as well. In particular, if a trayicon grabs
 | 
			
		||||
       * the pointer after a click on its label, we don't want to hide
 | 
			
		||||
       * the message tray. Filtering out this event will leave Clutter
 | 
			
		||||
       * out of sync, but that happens fairly often with grabs, and we
 | 
			
		||||
       * can work around it. (Eg, shell_global_sync_pointer().)
 | 
			
		||||
       */
 | 
			
		||||
      if (enter_event->mode == XINotifyGrab &&
 | 
			
		||||
          (enter_event->detail == XINotifyNonlinear ||
 | 
			
		||||
           enter_event->detail == XINotifyNonlinearVirtual))
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
 | 
			
		||||
                                  XEvent     *xev)
 | 
			
		||||
{
 | 
			
		||||
  MetaScreen *screen = meta_plugin_get_screen (plugin);
 | 
			
		||||
  MetaDisplay *display = meta_screen_get_display (screen);
 | 
			
		||||
  ClutterStage *stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
 | 
			
		||||
 | 
			
		||||
  GnomeShellPlugin *shell_plugin = GNOME_SHELL_PLUGIN (plugin);
 | 
			
		||||
#ifdef GLX_INTEL_swap_event
 | 
			
		||||
@@ -341,15 +309,26 @@ gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  /* Make sure that Clutter doesn't see certain focus change events,
 | 
			
		||||
   * so that when we're moving into something like a tray icon, we
 | 
			
		||||
   * don't unfocus the container. */
 | 
			
		||||
  if (xev->type == GenericEvent &&
 | 
			
		||||
      xev->xcookie.extension == meta_display_get_xinput_opcode (display))
 | 
			
		||||
  if ((xev->xany.type == EnterNotify || xev->xany.type == LeaveNotify)
 | 
			
		||||
      && xev->xcrossing.window == clutter_x11_get_stage_window (stage))
 | 
			
		||||
    {
 | 
			
		||||
      XIEvent *input_event = (XIEvent *) xev->xcookie.data;
 | 
			
		||||
      if ((input_event->evtype == XI_Enter || input_event->evtype == XI_Leave) &&
 | 
			
		||||
          ignore_crossing_event (plugin, (XIEnterEvent *) input_event))
 | 
			
		||||
      /* If the pointer enters a child of the stage window (eg, a
 | 
			
		||||
       * trayicon), we want to consider it to still be in the stage,
 | 
			
		||||
       * so don't let Clutter see the event.
 | 
			
		||||
       */
 | 
			
		||||
      if (xev->xcrossing.detail == NotifyInferior)
 | 
			
		||||
        return TRUE;
 | 
			
		||||
 | 
			
		||||
      /* If the pointer is grabbed by a window it is not currently in,
 | 
			
		||||
       * filter that out as well. In particular, if a trayicon grabs
 | 
			
		||||
       * the pointer after a click on its label, we don't want to hide
 | 
			
		||||
       * the message tray. Filtering out this event will leave Clutter
 | 
			
		||||
       * out of sync, but that happens fairly often with grabs, and we
 | 
			
		||||
       * can work around it. (Eg, shell_global_sync_pointer().)
 | 
			
		||||
       */
 | 
			
		||||
      if (xev->xcrossing.mode == NotifyGrab &&
 | 
			
		||||
          (xev->xcrossing.detail == NotifyNonlinear ||
 | 
			
		||||
           xev->xcrossing.detail == NotifyNonlinearVirtual))
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/main.c
									
									
									
									
									
								
							@@ -8,7 +8,6 @@
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <cogl-pango/cogl-pango.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <clutter/x11/clutter-x11.h>
 | 
			
		||||
#include <gdk/gdk.h>
 | 
			
		||||
@@ -195,20 +194,6 @@ shell_introspection_init (void)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_fonts_init (void)
 | 
			
		||||
{
 | 
			
		||||
  CoglPangoFontMap *fontmap;
 | 
			
		||||
 | 
			
		||||
  /* Disable text mipmapping; it causes problems on pre-GEM Intel
 | 
			
		||||
   * drivers and we should just be rendering text at the right
 | 
			
		||||
   * size rather than scaling it. If we do effects where we dynamically
 | 
			
		||||
   * zoom labels, then we might want to reconsider.
 | 
			
		||||
   */
 | 
			
		||||
  fontmap = COGL_PANGO_FONT_MAP (clutter_get_font_map ());
 | 
			
		||||
  cogl_pango_font_map_set_use_mipmapping (fontmap, FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
malloc_statistics_callback (ShellPerfLog *perf_log,
 | 
			
		||||
                            gpointer      data)
 | 
			
		||||
@@ -411,7 +396,6 @@ main (int argc, char **argv)
 | 
			
		||||
  shell_perf_log_init ();
 | 
			
		||||
  shell_prefs_init ();
 | 
			
		||||
  shell_introspection_init ();
 | 
			
		||||
  shell_fonts_init ();
 | 
			
		||||
 | 
			
		||||
  /* Turn on telepathy-glib debugging but filter it out in
 | 
			
		||||
   * default_log_handler. This handler also exposes all the logs over D-Bus
 | 
			
		||||
 
 | 
			
		||||
@@ -457,6 +457,38 @@ shell_app_system_get_tree (ShellAppSystem *self)
 | 
			
		||||
  return self->priv->apps_tree;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_app_system_get_settings_tree:
 | 
			
		||||
 *
 | 
			
		||||
 * Return Value: (transfer none): The #GMenuTree for apps
 | 
			
		||||
 */
 | 
			
		||||
GMenuTree *
 | 
			
		||||
shell_app_system_get_settings_tree (ShellAppSystem *self)
 | 
			
		||||
{
 | 
			
		||||
  return self->priv->settings_tree;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_app_system_lookup_setting:
 | 
			
		||||
 * @system:
 | 
			
		||||
 * @id: desktop file id
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (transfer none): Application in gnomecc.menu, or %NULL if none
 | 
			
		||||
 */
 | 
			
		||||
ShellApp *
 | 
			
		||||
shell_app_system_lookup_setting (ShellAppSystem *self,
 | 
			
		||||
                                 const char     *id)
 | 
			
		||||
{
 | 
			
		||||
  ShellApp *app;
 | 
			
		||||
 | 
			
		||||
  /* Actually defer to the main app set if there's overlap */
 | 
			
		||||
  app = shell_app_system_lookup_app (self, id);
 | 
			
		||||
  if (app != NULL)
 | 
			
		||||
    return app;
 | 
			
		||||
 | 
			
		||||
  return g_hash_table_lookup (self->priv->setting_id_to_app, id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_app_system_get_default:
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -60,7 +60,13 @@ GSList         *shell_app_system_subsearch                 (ShellAppSystem  *sys
 | 
			
		||||
                                                            GSList          *previous_results,
 | 
			
		||||
                                                            GSList          *terms);
 | 
			
		||||
 | 
			
		||||
GMenuTree      *shell_app_system_get_settings_tree         (ShellAppSystem *system);
 | 
			
		||||
 | 
			
		||||
GSList         *shell_app_system_search_settings           (ShellAppSystem *system,
 | 
			
		||||
                                                            GSList         *terms);
 | 
			
		||||
 | 
			
		||||
ShellApp       *shell_app_system_lookup_setting            (ShellAppSystem *system,
 | 
			
		||||
                                                            const char     *id);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* __SHELL_APP_SYSTEM_H__ */
 | 
			
		||||
 
 | 
			
		||||
@@ -13,11 +13,10 @@
 | 
			
		||||
#ifdef HAVE_SYS_RESOURCE_H
 | 
			
		||||
#include <sys/resource.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <locale.h>
 | 
			
		||||
 | 
			
		||||
#include <X11/extensions/Xfixes.h>
 | 
			
		||||
#include <cogl-pango/cogl-pango.h>
 | 
			
		||||
#include <canberra.h>
 | 
			
		||||
#include <canberra-gtk.h>
 | 
			
		||||
#include <clutter/glx/clutter-glx.h>
 | 
			
		||||
#include <clutter/x11/clutter-x11.h>
 | 
			
		||||
#include <gdk/gdkx.h>
 | 
			
		||||
@@ -267,13 +266,8 @@ shell_global_init (ShellGlobal *global)
 | 
			
		||||
 | 
			
		||||
  global->input_mode = SHELL_STAGE_INPUT_MODE_NORMAL;
 | 
			
		||||
 | 
			
		||||
  global->sound_context = ca_gtk_context_get ();
 | 
			
		||||
  ca_context_change_props (global->sound_context,
 | 
			
		||||
                           CA_PROP_APPLICATION_NAME, "GNOME Shell",
 | 
			
		||||
                           CA_PROP_APPLICATION_ID, "org.gnome.Shell",
 | 
			
		||||
                           CA_PROP_APPLICATION_ICON_NAME, "start-here",
 | 
			
		||||
                           CA_PROP_APPLICATION_LANGUAGE, setlocale (LC_MESSAGES, NULL),
 | 
			
		||||
                           NULL);
 | 
			
		||||
  ca_context_create (&global->sound_context);
 | 
			
		||||
  ca_context_change_props (global->sound_context, CA_PROP_APPLICATION_NAME, PACKAGE_NAME, CA_PROP_APPLICATION_ID, "org.gnome.Shell", NULL);
 | 
			
		||||
  ca_context_open (global->sound_context);
 | 
			
		||||
 | 
			
		||||
  if (!shell_js)
 | 
			
		||||
@@ -622,9 +616,6 @@ shell_global_set_cursor (ShellGlobal *global,
 | 
			
		||||
    case SHELL_CURSOR_POINTING_HAND:
 | 
			
		||||
      name = "hand";
 | 
			
		||||
      break;
 | 
			
		||||
    case SHELL_CURSOR_CROSSHAIR:
 | 
			
		||||
      name = "crosshair";
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_return_if_reached ();
 | 
			
		||||
    }
 | 
			
		||||
@@ -647,9 +638,6 @@ shell_global_set_cursor (ShellGlobal *global,
 | 
			
		||||
        case SHELL_CURSOR_POINTING_HAND:
 | 
			
		||||
          cursor_type = GDK_HAND2;
 | 
			
		||||
          break;
 | 
			
		||||
        case SHELL_CURSOR_CROSSHAIR:
 | 
			
		||||
          cursor_type = GDK_CROSSHAIR;
 | 
			
		||||
          break;
 | 
			
		||||
        case SHELL_CURSOR_DND_UNSUPPORTED_TARGET:
 | 
			
		||||
          cursor_type = GDK_X_CURSOR;
 | 
			
		||||
          break;
 | 
			
		||||
@@ -817,6 +805,20 @@ global_stage_after_paint (ClutterStage *stage,
 | 
			
		||||
                        "clutter.stagePaintDone");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_fonts_init (ClutterStage *stage)
 | 
			
		||||
{
 | 
			
		||||
  CoglPangoFontMap *fontmap;
 | 
			
		||||
 | 
			
		||||
  /* Disable text mipmapping; it causes problems on pre-GEM Intel
 | 
			
		||||
   * drivers and we should just be rendering text at the right
 | 
			
		||||
   * size rather than scaling it. If we do effects where we dynamically
 | 
			
		||||
   * zoom labels, then we might want to reconsider.
 | 
			
		||||
   */
 | 
			
		||||
  fontmap = COGL_PANGO_FONT_MAP (clutter_get_font_map ());
 | 
			
		||||
  cogl_pango_font_map_set_use_mipmapping (fontmap, FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is an IBus workaround. The flow of events with IBus is that every time
 | 
			
		||||
 * it gets gets a key event, it:
 | 
			
		||||
 *
 | 
			
		||||
@@ -955,6 +957,8 @@ _shell_global_set_plugin (ShellGlobal *global,
 | 
			
		||||
  g_signal_connect (global->meta_display, "notify::focus-window",
 | 
			
		||||
                    G_CALLBACK (focus_window_changed), global);
 | 
			
		||||
 | 
			
		||||
  shell_fonts_init (global->stage);
 | 
			
		||||
 | 
			
		||||
  gdk_event_handler_set (gnome_shell_gdk_event_handler, global->stage, NULL);
 | 
			
		||||
 | 
			
		||||
  global->focus_manager = st_focus_manager_get_for_stage (global->stage);
 | 
			
		||||
@@ -1400,6 +1404,7 @@ guint32
 | 
			
		||||
shell_global_get_current_time (ShellGlobal *global)
 | 
			
		||||
{
 | 
			
		||||
  guint32 time;
 | 
			
		||||
  const ClutterEvent *clutter_event;
 | 
			
		||||
 | 
			
		||||
  /* In case we have a xdnd timestamp use it */
 | 
			
		||||
  if (global->xdnd_timestamp != 0)
 | 
			
		||||
@@ -1410,7 +1415,7 @@ shell_global_get_current_time (ShellGlobal *global)
 | 
			
		||||
     from some Clutter event callbacks.
 | 
			
		||||
 | 
			
		||||
     clutter_get_current_event_time() will return the correct time
 | 
			
		||||
     from a Clutter event callback, but may return CLUTTER_CURRENT_TIME
 | 
			
		||||
     from a Clutter event callback, but may return an out-of-date
 | 
			
		||||
     timestamp if called at other times.
 | 
			
		||||
 | 
			
		||||
     So we try meta_display_get_current_time() first, since we
 | 
			
		||||
@@ -1420,9 +1425,17 @@ shell_global_get_current_time (ShellGlobal *global)
 | 
			
		||||
 | 
			
		||||
  time = meta_display_get_current_time (global->meta_display);
 | 
			
		||||
  if (time != CLUTTER_CURRENT_TIME)
 | 
			
		||||
    return time;
 | 
			
		||||
      return time;
 | 
			
		||||
  /*
 | 
			
		||||
   * We don't use clutter_get_current_event_time as it can give us a
 | 
			
		||||
   * too old timestamp if there is no current event.
 | 
			
		||||
   */
 | 
			
		||||
  clutter_event = clutter_get_current_event ();
 | 
			
		||||
 | 
			
		||||
  return clutter_get_current_event_time ();
 | 
			
		||||
  if (clutter_event != NULL)
 | 
			
		||||
    return clutter_event_get_time (clutter_event);
 | 
			
		||||
  else
 | 
			
		||||
    return CLUTTER_CURRENT_TIME;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -1584,99 +1597,21 @@ shell_global_run_at_leisure (ShellGlobal         *global,
 | 
			
		||||
    schedule_leisure_functions (global);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
build_ca_proplist_for_event (ca_proplist  *props,
 | 
			
		||||
                             const char   *event_id,
 | 
			
		||||
                             const char   *event_description,
 | 
			
		||||
                             ClutterEvent *for_event)
 | 
			
		||||
{
 | 
			
		||||
  ca_proplist_sets (props, CA_PROP_EVENT_ID, event_id);
 | 
			
		||||
  ca_proplist_sets (props, CA_PROP_EVENT_DESCRIPTION, event_description);
 | 
			
		||||
  ca_proplist_sets (props, CA_PROP_CANBERRA_CACHE_CONTROL, "volatile");
 | 
			
		||||
 | 
			
		||||
  if (for_event)
 | 
			
		||||
    {
 | 
			
		||||
      if (clutter_event_type (for_event) != CLUTTER_KEY_PRESS &&
 | 
			
		||||
          clutter_event_type (for_event) != CLUTTER_KEY_RELEASE)
 | 
			
		||||
        {
 | 
			
		||||
          ClutterPoint point;
 | 
			
		||||
 | 
			
		||||
          clutter_event_get_position (for_event, &point);
 | 
			
		||||
 | 
			
		||||
          ca_proplist_setf (props, CA_PROP_EVENT_MOUSE_X, "%d", (int)point.x);
 | 
			
		||||
          ca_proplist_setf (props, CA_PROP_EVENT_MOUSE_Y, "%d", (int)point.y);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (clutter_event_type (for_event) == CLUTTER_BUTTON_PRESS ||
 | 
			
		||||
          clutter_event_type (for_event) == CLUTTER_BUTTON_RELEASE)
 | 
			
		||||
        {
 | 
			
		||||
          gint button;
 | 
			
		||||
 | 
			
		||||
          button = clutter_event_get_button (for_event);
 | 
			
		||||
          ca_proplist_setf (props, CA_PROP_EVENT_MOUSE_BUTTON, "%d", button);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_global_play_theme_sound:
 | 
			
		||||
 * @global: the #ShellGlobal
 | 
			
		||||
 * @id: an id, used to cancel later (0 if not needed)
 | 
			
		||||
 * @name: the sound name
 | 
			
		||||
 * @for_event: (allow-none): a #ClutterEvent in response to which the sound is played
 | 
			
		||||
 *
 | 
			
		||||
 * Plays a simple sound picked according to Freedesktop sound theme.
 | 
			
		||||
 * Really just a workaround for libcanberra not being introspected.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
shell_global_play_theme_sound (ShellGlobal  *global,
 | 
			
		||||
                               guint         id,
 | 
			
		||||
                               const char   *name,
 | 
			
		||||
                               const char   *description,
 | 
			
		||||
                               ClutterEvent *for_event)
 | 
			
		||||
shell_global_play_theme_sound (ShellGlobal *global,
 | 
			
		||||
                               guint        id,
 | 
			
		||||
                               const char  *name)
 | 
			
		||||
{
 | 
			
		||||
  ca_proplist *props;
 | 
			
		||||
 | 
			
		||||
  ca_proplist_create (&props);
 | 
			
		||||
  build_ca_proplist_for_event (props, name, description, for_event);
 | 
			
		||||
 | 
			
		||||
  ca_context_play_full (global->sound_context, id, props, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  ca_proplist_destroy (props);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_global_play_theme_sound_full:
 | 
			
		||||
 * @global: the #ShellGlobal
 | 
			
		||||
 * @id: an id, used to cancel later (0 if not needed)
 | 
			
		||||
 * @name: the sound name
 | 
			
		||||
 * @description: the localized description of the event that triggered this alert
 | 
			
		||||
 * @for_event: (allow-none): a #ClutterEvent in response to which the sound is played
 | 
			
		||||
 * @application_id: application on behalf of which the sound is played
 | 
			
		||||
 * @application_name:
 | 
			
		||||
 *
 | 
			
		||||
 * Plays a simple sound picked according to Freedesktop sound theme.
 | 
			
		||||
 * Really just a workaround for libcanberra not being introspected.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
shell_global_play_theme_sound_full (ShellGlobal  *global,
 | 
			
		||||
                                    guint         id,
 | 
			
		||||
                                    const char   *name,
 | 
			
		||||
                                    const char   *description,
 | 
			
		||||
                                    ClutterEvent *for_event,
 | 
			
		||||
                                    const char   *application_id,
 | 
			
		||||
                                    const char   *application_name)
 | 
			
		||||
{
 | 
			
		||||
  ca_proplist *props;
 | 
			
		||||
 | 
			
		||||
  ca_proplist_create (&props);
 | 
			
		||||
  build_ca_proplist_for_event (props, name, description, for_event);
 | 
			
		||||
  ca_proplist_sets (props, CA_PROP_APPLICATION_ID, application_id);
 | 
			
		||||
  ca_proplist_sets (props, CA_PROP_APPLICATION_NAME, application_name);
 | 
			
		||||
 | 
			
		||||
  ca_context_play_full (global->sound_context, id, props, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  ca_proplist_destroy (props);
 | 
			
		||||
  ca_context_play (global->sound_context, id, CA_PROP_EVENT_ID, name, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -63,8 +63,7 @@ typedef enum {
 | 
			
		||||
  SHELL_CURSOR_DND_UNSUPPORTED_TARGET,
 | 
			
		||||
  SHELL_CURSOR_DND_MOVE,
 | 
			
		||||
  SHELL_CURSOR_DND_COPY,
 | 
			
		||||
  SHELL_CURSOR_POINTING_HAND,
 | 
			
		||||
  SHELL_CURSOR_CROSSHAIR
 | 
			
		||||
  SHELL_CURSOR_POINTING_HAND
 | 
			
		||||
} ShellCursor;
 | 
			
		||||
 | 
			
		||||
void    shell_global_set_cursor              (ShellGlobal         *global,
 | 
			
		||||
@@ -121,18 +120,9 @@ void     shell_global_sync_pointer              (ShellGlobal  *global);
 | 
			
		||||
GAppLaunchContext *
 | 
			
		||||
         shell_global_create_app_launch_context (ShellGlobal  *global);
 | 
			
		||||
 | 
			
		||||
void     shell_global_play_theme_sound          (ShellGlobal *global,
 | 
			
		||||
                                                 guint        id,
 | 
			
		||||
                                                 const char   *name,
 | 
			
		||||
                                                 const char   *description,
 | 
			
		||||
                                                 ClutterEvent *for_event);
 | 
			
		||||
void     shell_global_play_theme_sound_full     (ShellGlobal  *global,
 | 
			
		||||
void     shell_global_play_theme_sound          (ShellGlobal  *global,
 | 
			
		||||
                                                 guint         id,
 | 
			
		||||
                                                 const char   *name,
 | 
			
		||||
                                                 const char   *description,
 | 
			
		||||
                                                 ClutterEvent *for_event,
 | 
			
		||||
                                                 const char   *application_id,
 | 
			
		||||
                                                 const char   *application_name);
 | 
			
		||||
                                                 const char   *name);
 | 
			
		||||
void     shell_global_cancel_theme_sound        (ShellGlobal  *global,
 | 
			
		||||
                                                 guint         id);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,35 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * ShellKeyBindingMode:
 | 
			
		||||
 * @SHELL_KEYBINDING_MODE_NONE: block keybinding
 | 
			
		||||
 * @SHELL_KEYBINDING_MODE_NORMAL: allow keybinding when in window mode,
 | 
			
		||||
 *     e.g. when the focus is in an application window
 | 
			
		||||
 * @SHELL_KEYBINDING_MODE_OVERVIEW: allow keybinding while the overview
 | 
			
		||||
 *     is active
 | 
			
		||||
 * @SHELL_KEYBINDING_MODE_LOCK_SCREEN: allow keybinding when the screen
 | 
			
		||||
 *     is locked, e.g. when the screen shield is shown
 | 
			
		||||
 * @SHELL_KEYBINDING_MODE_UNLOCK_SCREEN: allow keybinding in the unlock
 | 
			
		||||
 *     dialog
 | 
			
		||||
 * @SHELL_KEYBINDING_MODE_LOGIN_SCREEN: allow keybinding in the login screen
 | 
			
		||||
 * @SHELL_KEYBINDING_MODE_MESSAGE_TRAY: allow keybinding while the message
 | 
			
		||||
 *     tray is popped up
 | 
			
		||||
 * @SHELL_KEYBINDING_MODE_SYSTEM_MODAL: allow keybinding when a system modal
 | 
			
		||||
 *     dialog (e.g. authentification or session dialogs) is open
 | 
			
		||||
 * @SHELL_KEYBINDING_MODE_LOOKING_GLASS: allow keybinding in looking glass
 | 
			
		||||
 * @SHELL_KEYBINDING_MODE_ALL: always allow keybinding
 | 
			
		||||
 *
 | 
			
		||||
 * Controls in which GNOME Shell states a keybinding should be handled.
 | 
			
		||||
*/
 | 
			
		||||
typedef enum {
 | 
			
		||||
  SHELL_KEYBINDING_MODE_NONE          = 0,
 | 
			
		||||
  SHELL_KEYBINDING_MODE_NORMAL        = 1 << 0,
 | 
			
		||||
  SHELL_KEYBINDING_MODE_OVERVIEW      = 1 << 1,
 | 
			
		||||
  SHELL_KEYBINDING_MODE_LOCK_SCREEN   = 1 << 2,
 | 
			
		||||
  SHELL_KEYBINDING_MODE_UNLOCK_SCREEN = 1 << 3,
 | 
			
		||||
  SHELL_KEYBINDING_MODE_LOGIN_SCREEN  = 1 << 4,
 | 
			
		||||
  SHELL_KEYBINDING_MODE_MESSAGE_TRAY  = 1 << 5,
 | 
			
		||||
  SHELL_KEYBINDING_MODE_SYSTEM_MODAL  = 1 << 6,
 | 
			
		||||
  SHELL_KEYBINDING_MODE_LOOKING_GLASS = 1 << 7,
 | 
			
		||||
 | 
			
		||||
  SHELL_KEYBINDING_MODE_ALL = ~SHELL_KEYBINDING_MODE_NONE
 | 
			
		||||
} ShellKeyBindingMode;
 | 
			
		||||
 | 
			
		||||
@@ -32,7 +32,6 @@ typedef struct _screenshot_data {
 | 
			
		||||
  ShellScreenshot  *screenshot;
 | 
			
		||||
 | 
			
		||||
  char *filename;
 | 
			
		||||
  char *filename_used;
 | 
			
		||||
 | 
			
		||||
  cairo_surface_t *image;
 | 
			
		||||
  cairo_rectangle_int_t screenshot_area;
 | 
			
		||||
@@ -65,140 +64,25 @@ on_screenshot_written (GObject *source,
 | 
			
		||||
  if (screenshot_data->callback)
 | 
			
		||||
    screenshot_data->callback (screenshot_data->screenshot,
 | 
			
		||||
                               g_simple_async_result_get_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (result)),
 | 
			
		||||
                               &screenshot_data->screenshot_area,
 | 
			
		||||
                               screenshot_data->filename_used);
 | 
			
		||||
                               &screenshot_data->screenshot_area);
 | 
			
		||||
 | 
			
		||||
  cairo_surface_destroy (screenshot_data->image);
 | 
			
		||||
  g_object_unref (screenshot_data->screenshot);
 | 
			
		||||
  g_free (screenshot_data->filename);
 | 
			
		||||
  g_free (screenshot_data->filename_used);
 | 
			
		||||
  g_free (screenshot_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* called in an I/O thread */
 | 
			
		||||
static GOutputStream *
 | 
			
		||||
get_stream_for_unique_path (const gchar *path,
 | 
			
		||||
                            const gchar *filename,
 | 
			
		||||
                            gchar **filename_used)
 | 
			
		||||
{
 | 
			
		||||
  GOutputStream *stream;
 | 
			
		||||
  GFile *file;
 | 
			
		||||
  gchar *real_path, *real_filename, *name, *ptr;
 | 
			
		||||
  gint idx;
 | 
			
		||||
 | 
			
		||||
  ptr = g_strrstr (filename, ".png");
 | 
			
		||||
 | 
			
		||||
  if (ptr != NULL)
 | 
			
		||||
    real_filename = g_strndup (filename, ptr - filename);
 | 
			
		||||
  else
 | 
			
		||||
    real_filename = g_strdup (filename);
 | 
			
		||||
 | 
			
		||||
  idx = 0;
 | 
			
		||||
  real_path = NULL;
 | 
			
		||||
 | 
			
		||||
  do
 | 
			
		||||
    {
 | 
			
		||||
      if (idx == 0)
 | 
			
		||||
        name = g_strdup_printf ("%s.png", real_filename);
 | 
			
		||||
      else
 | 
			
		||||
        name = g_strdup_printf ("%s - %d.png", real_filename, idx);
 | 
			
		||||
 | 
			
		||||
      real_path = g_build_filename (path, name, NULL);
 | 
			
		||||
      g_free (name);
 | 
			
		||||
 | 
			
		||||
      file = g_file_new_for_path (real_path);
 | 
			
		||||
      stream = G_OUTPUT_STREAM (g_file_create (file, G_FILE_CREATE_NONE, NULL, NULL));
 | 
			
		||||
      g_object_unref (file);
 | 
			
		||||
 | 
			
		||||
      if (stream != NULL)
 | 
			
		||||
        *filename_used = real_path;
 | 
			
		||||
      else
 | 
			
		||||
        g_free (real_path);
 | 
			
		||||
 | 
			
		||||
      idx++;
 | 
			
		||||
    }
 | 
			
		||||
  while (stream == NULL);
 | 
			
		||||
 | 
			
		||||
  g_free (real_filename);
 | 
			
		||||
 | 
			
		||||
  return stream;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* called in an I/O thread */
 | 
			
		||||
static GOutputStream *
 | 
			
		||||
get_stream_for_filename (const gchar *filename,
 | 
			
		||||
                         gchar **filename_used)
 | 
			
		||||
{
 | 
			
		||||
  const gchar *path;
 | 
			
		||||
 | 
			
		||||
  path = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
 | 
			
		||||
  if (!g_file_test (path, G_FILE_TEST_EXISTS))
 | 
			
		||||
    {
 | 
			
		||||
      path = g_get_home_dir ();
 | 
			
		||||
      if (!g_file_test (path, G_FILE_TEST_EXISTS))
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return get_stream_for_unique_path (path, filename, filename_used);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GOutputStream *
 | 
			
		||||
prepare_write_stream (const gchar *filename,
 | 
			
		||||
                      gchar **filename_used)
 | 
			
		||||
{
 | 
			
		||||
  GOutputStream *stream;
 | 
			
		||||
  GFile *file;
 | 
			
		||||
 | 
			
		||||
  if (g_path_is_absolute (filename))
 | 
			
		||||
    {
 | 
			
		||||
      file = g_file_new_for_path (filename);
 | 
			
		||||
      *filename_used = g_strdup (filename);
 | 
			
		||||
      stream = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
 | 
			
		||||
      g_object_unref (file);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      stream = get_stream_for_filename (filename, filename_used);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return stream;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static cairo_status_t
 | 
			
		||||
do_write_to_stream (void *closure,
 | 
			
		||||
                    const guchar *data,
 | 
			
		||||
                    guint length)
 | 
			
		||||
{
 | 
			
		||||
  GOutputStream *stream = closure;
 | 
			
		||||
  gboolean res;
 | 
			
		||||
 | 
			
		||||
  res = g_output_stream_write_all (stream, data, length, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  return res ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
write_screenshot_thread (GSimpleAsyncResult *result,
 | 
			
		||||
                         GObject *object,
 | 
			
		||||
                         GCancellable *cancellable)
 | 
			
		||||
{
 | 
			
		||||
  cairo_status_t status;
 | 
			
		||||
  GOutputStream *stream;
 | 
			
		||||
  _screenshot_data *screenshot_data = g_async_result_get_user_data (G_ASYNC_RESULT (result));
 | 
			
		||||
 | 
			
		||||
  g_assert (screenshot_data != NULL);
 | 
			
		||||
 | 
			
		||||
  stream = prepare_write_stream (screenshot_data->filename,
 | 
			
		||||
                                 &screenshot_data->filename_used);
 | 
			
		||||
 | 
			
		||||
  if (stream == NULL)
 | 
			
		||||
    status = CAIRO_STATUS_FILE_NOT_FOUND;
 | 
			
		||||
  else
 | 
			
		||||
    status = cairo_surface_write_to_png_stream (screenshot_data->image, do_write_to_stream, stream);
 | 
			
		||||
 | 
			
		||||
  status = cairo_surface_write_to_png (screenshot_data->image, screenshot_data->filename);
 | 
			
		||||
  g_simple_async_result_set_op_res_gboolean (result, status == CAIRO_STATUS_SUCCESS);
 | 
			
		||||
 | 
			
		||||
  g_clear_object (&stream);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
@@ -26,9 +26,8 @@ GType shell_screenshot_get_type (void) G_GNUC_CONST;
 | 
			
		||||
ShellScreenshot *shell_screenshot_new (void);
 | 
			
		||||
 | 
			
		||||
typedef void (*ShellScreenshotCallback)  (ShellScreenshot *screenshot,
 | 
			
		||||
                                          gboolean success,
 | 
			
		||||
                                          cairo_rectangle_int_t *screenshot_area,
 | 
			
		||||
                                          const gchar *filename_used);
 | 
			
		||||
                                           gboolean success,
 | 
			
		||||
                                           cairo_rectangle_int_t *screenshot_area);
 | 
			
		||||
 | 
			
		||||
void    shell_screenshot_screenshot_area      (ShellScreenshot *screenshot,
 | 
			
		||||
                                                int x,
 | 
			
		||||
 
 | 
			
		||||
@@ -180,7 +180,6 @@ void
 | 
			
		||||
shell_tray_icon_click (ShellTrayIcon *icon,
 | 
			
		||||
                       ClutterEvent  *event)
 | 
			
		||||
{
 | 
			
		||||
  XKeyEvent xkevent;
 | 
			
		||||
  XButtonEvent xbevent;
 | 
			
		||||
  XCrossingEvent xcevent;
 | 
			
		||||
  GdkWindow *remote_window;
 | 
			
		||||
@@ -188,10 +187,8 @@ shell_tray_icon_click (ShellTrayIcon *icon,
 | 
			
		||||
  int x_root, y_root;
 | 
			
		||||
  Display *xdisplay;
 | 
			
		||||
  Window xwindow, xrootwindow;
 | 
			
		||||
  ClutterEventType event_type = clutter_event_type (event);
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (event_type == CLUTTER_BUTTON_RELEASE ||
 | 
			
		||||
                    event_type == CLUTTER_KEY_RELEASE);
 | 
			
		||||
  g_return_if_fail (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE);
 | 
			
		||||
 | 
			
		||||
  gdk_error_trap_push ();
 | 
			
		||||
 | 
			
		||||
@@ -218,44 +215,22 @@ shell_tray_icon_click (ShellTrayIcon *icon,
 | 
			
		||||
  XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent);
 | 
			
		||||
 | 
			
		||||
  /* Now do the click */
 | 
			
		||||
  if (event_type == CLUTTER_BUTTON_RELEASE)
 | 
			
		||||
    {
 | 
			
		||||
      xbevent.window = xwindow;
 | 
			
		||||
      xbevent.root = xrootwindow;
 | 
			
		||||
      xbevent.subwindow = None;
 | 
			
		||||
      xbevent.time = xcevent.time;
 | 
			
		||||
      xbevent.x = xcevent.x;
 | 
			
		||||
      xbevent.y = xcevent.y;
 | 
			
		||||
      xbevent.x_root = xcevent.x_root;
 | 
			
		||||
      xbevent.y_root = xcevent.y_root;
 | 
			
		||||
      xbevent.state = clutter_event_get_state (event);
 | 
			
		||||
      xbevent.same_screen = True;
 | 
			
		||||
      xbevent.type = ButtonPress;
 | 
			
		||||
      xbevent.button = clutter_event_get_button (event);
 | 
			
		||||
      XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent);
 | 
			
		||||
  xbevent.type = ButtonPress;
 | 
			
		||||
  xbevent.window = xwindow;
 | 
			
		||||
  xbevent.root = xrootwindow;
 | 
			
		||||
  xbevent.subwindow = None;
 | 
			
		||||
  xbevent.time = xcevent.time;
 | 
			
		||||
  xbevent.x = xcevent.x;
 | 
			
		||||
  xbevent.y = xcevent.y;
 | 
			
		||||
  xbevent.x_root = xcevent.x_root;
 | 
			
		||||
  xbevent.y_root = xcevent.y_root;
 | 
			
		||||
  xbevent.state = clutter_event_get_state (event);
 | 
			
		||||
  xbevent.button = clutter_event_get_button (event);
 | 
			
		||||
  xbevent.same_screen = True;
 | 
			
		||||
  XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent);
 | 
			
		||||
 | 
			
		||||
      xbevent.type = ButtonRelease;
 | 
			
		||||
      XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      xkevent.window = xwindow;
 | 
			
		||||
      xkevent.root = xrootwindow;
 | 
			
		||||
      xkevent.subwindow = None;
 | 
			
		||||
      xkevent.time = xcevent.time;
 | 
			
		||||
      xkevent.x = xcevent.x;
 | 
			
		||||
      xkevent.y = xcevent.y;
 | 
			
		||||
      xkevent.x_root = xcevent.x_root;
 | 
			
		||||
      xkevent.y_root = xcevent.y_root;
 | 
			
		||||
      xkevent.state = clutter_event_get_state (event);
 | 
			
		||||
      xkevent.same_screen = True;
 | 
			
		||||
      xkevent.type = KeyPress;
 | 
			
		||||
      xkevent.keycode = clutter_event_get_key_code (event);
 | 
			
		||||
      XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xkevent);
 | 
			
		||||
 | 
			
		||||
      xkevent.type = KeyRelease;
 | 
			
		||||
      XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xkevent);
 | 
			
		||||
    }
 | 
			
		||||
  xbevent.type = ButtonRelease;
 | 
			
		||||
  XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent);
 | 
			
		||||
 | 
			
		||||
  /* And move the pointer back out */
 | 
			
		||||
  xcevent.type = LeaveNotify;
 | 
			
		||||
 
 | 
			
		||||
@@ -9,8 +9,6 @@
 | 
			
		||||
#include <glib/gi18n-lib.h>
 | 
			
		||||
#include <gtk/gtk.h>
 | 
			
		||||
#include <gdk-pixbuf/gdk-pixbuf.h>
 | 
			
		||||
#include <gdk/gdkx.h>
 | 
			
		||||
#include <X11/Xatom.h>
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE__NL_TIME_FIRST_WEEKDAY
 | 
			
		||||
#include <langinfo.h>
 | 
			
		||||
@@ -432,56 +430,3 @@ shell_util_create_pixbuf_from_data (const guchar      *data,
 | 
			
		||||
                                   bits_per_sample, width, height, rowstride,
 | 
			
		||||
                                   (GdkPixbufDestroyNotify) g_free, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Pixmap
 | 
			
		||||
shell_util_get_root_background (void)
 | 
			
		||||
{
 | 
			
		||||
  Display *display;
 | 
			
		||||
  Pixmap pixmap;
 | 
			
		||||
  Window rootwin;
 | 
			
		||||
  Atom xrootpmap;
 | 
			
		||||
  Atom actual_type;
 | 
			
		||||
  int actual_format;
 | 
			
		||||
  unsigned long n_items;
 | 
			
		||||
  unsigned long bytes_after;
 | 
			
		||||
  unsigned char *buffer;
 | 
			
		||||
 | 
			
		||||
  display = gdk_x11_get_default_xdisplay ();
 | 
			
		||||
 | 
			
		||||
  xrootpmap = gdk_x11_atom_to_xatom (gdk_atom_intern_static_string ("_XROOTPMAP_ID"));
 | 
			
		||||
  rootwin = gdk_x11_get_default_root_xwindow ();
 | 
			
		||||
 | 
			
		||||
  gdk_error_trap_push ();
 | 
			
		||||
  actual_type = None;
 | 
			
		||||
  buffer = NULL;
 | 
			
		||||
  if (XGetWindowProperty (display, rootwin, xrootpmap,
 | 
			
		||||
                          0, G_MAXLONG,
 | 
			
		||||
                          False, XA_PIXMAP, &actual_type, &actual_format,
 | 
			
		||||
                          &n_items,
 | 
			
		||||
                          &bytes_after,
 | 
			
		||||
                          &buffer) != Success ||
 | 
			
		||||
      actual_type == None)
 | 
			
		||||
    {
 | 
			
		||||
      if (buffer)
 | 
			
		||||
        XFree (buffer);
 | 
			
		||||
      gdk_error_trap_pop_ignored ();
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (gdk_error_trap_pop () != Success ||
 | 
			
		||||
      n_items == 0 ||
 | 
			
		||||
      actual_type != XA_PIXMAP ||
 | 
			
		||||
      actual_format != 32)
 | 
			
		||||
    {
 | 
			
		||||
      if (buffer)
 | 
			
		||||
        XFree (buffer);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  pixmap = *((Pixmap*) buffer);
 | 
			
		||||
 | 
			
		||||
  XFree (buffer);
 | 
			
		||||
  return pixmap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <libsoup/soup.h>
 | 
			
		||||
#include <gdk-pixbuf/gdk-pixbuf.h>
 | 
			
		||||
#include <gdk/gdkx.h>
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
@@ -47,8 +46,6 @@ GdkPixbuf *shell_util_create_pixbuf_from_data (const guchar      *data,
 | 
			
		||||
                                               int                height,
 | 
			
		||||
                                               int                rowstride);
 | 
			
		||||
 | 
			
		||||
Pixmap  shell_util_get_root_background        (void);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* __SHELL_UTIL_H__ */
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user