Compare commits
	
		
			4 Commits
		
	
	
		
			wip/window
			...
			wip/is-swi
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 11bf65e2b4 | ||
|   | a8b7e559aa | ||
|   | b733e30a4a | ||
|   | b607958134 | 
							
								
								
									
										135
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								NEWS
									
									
									
									
									
								
							| @@ -1,138 +1,3 @@ | ||||
| 3.9.3 | ||||
| ===== | ||||
| * Don't push window thumbs when workspace switcher is hidden [Jasper; #701167] | ||||
| * Tweak timeout for activating windows during XDND [Adel; #700150] | ||||
| * Fix ellipsization in control buttons in app picker [Carlos; #696307] | ||||
| * Fix DND to empty dash [Florian; #684618] | ||||
| * Fix OSD window appearing below system modal dialogs [Rui; #701269] | ||||
| * Clear clipboard on screen lock to prevent information leak [Florian; #698922] | ||||
| * Allow session mode specific overrides schema [Florian; #701717] | ||||
| * window-switcher: Only show windows from current workspace by default | ||||
|   [Florian; #701214] | ||||
| * logout dialog: Show the correct text right away [Matthias; #702056] | ||||
| * bluetooth: Port to bluez 5 [Emilio; #700891] | ||||
| * dateMenu: Allow events to span multiple lines [Giovanni; #701231] | ||||
| * gdm: Clear message queue when no more messages are pending [Jonh; #702458] | ||||
| * Misc bug fixes and cleanups [Jasper, Florian, Adel, Giovanni; #693836, | ||||
|   #700972, #701386, #700877, #701755, #698918, #701224, #702125, #701954, | ||||
|   #701849, #702121] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Matthias Clasen, Fran Diéguez, Adel Gadllah, Rui Matos, | ||||
|   Florian Müllner, Emilio Pozuelo Monfort, Carlos Soriano, Jasper St. Pierre, | ||||
|   Jonh Wendell | ||||
|  | ||||
| Translations: | ||||
|   Marek Černocký [cs], Victor Ibragimov [tg], Fran Diéguez [gl], | ||||
|   Benjamin Steinwender [de], Cheng-Chia Tseng [zh_HK, zh_TW], | ||||
|   eternalhui [zh_CN], Ivaylo Valkov [bg], Kjartan Maraas [nb], | ||||
|   Daniel Mustieles [es] | ||||
|  | ||||
| 3.9.2 | ||||
| ===== | ||||
| * Use a symbolic icon for DESKTOP windows [Matthias; #697914] | ||||
| * Move paint state cache into StWidget [Jasper; #697274] | ||||
| * gdm: Fix regression where domain login hint not shown [Stef; #698200] | ||||
| * Make calendar keyboard navigable [Tanner; #667434] | ||||
| * Hide "Open Calendar" item when no calendar app is installed [Lionel; #697725] | ||||
| * Update how branding appears on login screen [Florian; #694912, #699877] | ||||
| * Allow OSD popups to grow if necessary [Marta; #696523] | ||||
| * Fix offset of shadow offscreen rendering [Lionel; #698301] | ||||
| * Fix insensitive button preventing empty keyring password [Stef; #696304] | ||||
| * Allow cancelling keyring dialog between prompts [Stef; #682830] | ||||
| * modalDialog: Show spinner while working [Stef; #684438] | ||||
| * overview: Only show close buttons for windows that may close [Jasper; #699269] | ||||
| * Add input purpose and hints to StEntry and StIMText [Daiki; #691392] | ||||
| * Set input-purpose property for password entries [Rui; #700043] | ||||
| * Provide a DBus API for screencasting [Florian; #696247] | ||||
| * overview: Disable hotcorner during DND [Jasper; #698484] | ||||
| * polkitAgent: Allow retrying after mistyped passwords [Stef; #684431] | ||||
| * Add a way to get backtraces from criticals and warnings [Giovanni; #700262] | ||||
| * Allow switch-to-workspace-n keybindings in overview [Florian; #649977] | ||||
| * Update man page [Matthias; #700339] | ||||
| * Add FocusSearch DBus method [Florian; #700536] | ||||
| * Hide frequent view when app monitoring is disabled [Florian; #699714] | ||||
| * Show switcher popup for switch-to-workspace-n keybindings [Elad; #659288] | ||||
| * gdm: Update the session chooser style [Allan; #695742] | ||||
| * Fix some app folders getting truncated at the top [Florian; #694371] | ||||
| * Don't block the message tray while a notification is showing [Jasper; #700639] | ||||
| * popupMenu: Allow for an optional border for slider handle [Florian; #697917] | ||||
| * Re-lock screen when restarted after a crash [Colin; #691987] | ||||
| * Synchronize input source switching with key events [Rui; #697007] | ||||
| * Switch input source on modifiers-only accelerator [Rui; #697008] | ||||
| * Allow input source switching in message tray [Rui; #697009] | ||||
| * Misc bug fixes and cleanups [Alban, Jasper, Giovanni, Florian, Rui, Tomeu, | ||||
|   Stef, Gustavo; #698863, #699799, #699800, #676285, #699975, #700097, #698812, | ||||
|   #698486, #700194, #695314, #700257, #699678, #700356, #700322, #700394, | ||||
|   #700409, #700595, #700625, #691746, #700620, #700807, #659288, #700784, | ||||
|   #700842, #700847, #700488, #700735, #696159, #700900, #700853, #700923, | ||||
|   #700944, #697661, #700854, #700190, #699189, #701097] | ||||
|  | ||||
| Contributors: | ||||
|   Elad Alfassa, Alban Browaeys, Giovanni Campagna, Matthias Clasen, Allan Day, | ||||
|   Tanner Doshier, Lionel Landwerlin, Rui Matos, Simon McVittie, | ||||
|   Marta Milakovic, Florian Müllner, Gustavo Padovan, Jasper St. Pierre, | ||||
|   Daiki Ueno, Tomeu Vizoso, Stef Walter, Colin Walters | ||||
|  | ||||
| Translations: | ||||
|   Matej Urbančič [sl], Kjartan Maraas [nb], Victor Ibragimov [tg], | ||||
|   Dušan Kazik [sk], Gil Forcada [ca], Daniel Mustieles [es] | ||||
|  | ||||
| 3.9.1 | ||||
| ===== | ||||
| * Add additional toggle-overview keybinding [Matthias; #698251] | ||||
| * Disable <super> shortcut when sticky keys are enabled [Matthias; #685974] | ||||
| * Disable tray context menu while a notification displays [Jasper; #695800] | ||||
| * Watch GApplication busy state [Cosimo; #697207] | ||||
| * Disable style transitions if animations are disabled [Jasper; #698391] | ||||
| * Filter out hidden applications from "Frequent" view [Giovanni; #696949] | ||||
| * Fix window previews swapping place randomly [Jasper; #694469, #698776] | ||||
| * Add support for serialized GIcons in remote search providers [Cosimo; #698761] | ||||
| * Fix hotcorner regression in RTL locales [Jasper; #698884] | ||||
| * Allow some keybindings to work while a top bar menu is open [Florian; #698938] | ||||
| * Make open-app-menu keybinding a toggle action [Florian; #686756] | ||||
| * Only recognize common URL schemes in notification messages [Monica; #661225] | ||||
| * Misc fixes and cleanups [Tim, Jasper, Florian, Giovanni, Owen; #698531, | ||||
|   #698622, #698427, #698483, #698513, #697203, #698959, #698918, #699029, | ||||
|   #699075, #696720, #649748] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Cosimo Cecchi, Monica Chelliah, Matthias Clasen, Tim Lunn, | ||||
|   Florian Müllner, Jasper St. Pierre, Michael Wood, Owen W. Taylor | ||||
|  | ||||
| Translations: | ||||
|   Fran Diéguez [gl], Muhammet Kara [tr], Daniel Mustieles [es], | ||||
|   Gil Forcada [ia], Anish A [ml], Dimitris Spingos [el], Marek Černocký [cs], | ||||
|   Žygimantas Beručka [lt] | ||||
|  | ||||
| 3.8.1 | ||||
| ===== | ||||
| * Clip window group during startup animation [Jasper; #696323] | ||||
| * Check for logind rather than systemd [Martin; #696252] | ||||
| * Don't special-case last remote search provider position [Giovanni; #694974] | ||||
| * Fix memory leaks [Ray, Jasper; ##697119, #697295, #697300, #697395] | ||||
| * AppSwitcherPopup: Activate only the selected window if any [Rui; #697480] | ||||
| * Enable screen recorder keybinding in all modes [Florian; #696200] | ||||
| * Remove box-shadow from screen shield for performance reasons [Adel; #697274] | ||||
| * Add support for -st-natural-width/height CSS properties [Giovanni; #664411] | ||||
| * Remove excessive padding from notification buttons [Allan; #664411] | ||||
| * Fix thumbnail dragging in overview [Jasper; #697504] | ||||
| * theme-node: Add get_url()/lookup_url() methods [Florian; #693688] | ||||
| * Misc bug fixes and cleanups [Jasper, Rui, Colin, David, Ray, Matthias: | ||||
|   #695859, #696259, #696585, #696436, #697432, #697435, #697560, #697722, | ||||
|   #697709] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Matthias Clasen, Allan Day, Adel Gadllah, David Gumberg, | ||||
|   Rui Matos, Florian Müllner, Martin Pitt, Jasper St. Pierre, Ray Strode, | ||||
|   Colin Walters | ||||
|  | ||||
| Translations: | ||||
|   Daniel Martinez [an], Bruce Cowan [en_GB], Khaled Hosny [ar], | ||||
|   Ihar Hrachyshka [be], Aron Xu [zh_CN], Wojciech Szczęsny [pl], | ||||
|   Inaki Larranaga Murgoitio [eu], Kjartan Maraas [nb], | ||||
|   Милош Поповић [sr, sr@latin], Trần Ngọc Quân [vi] | ||||
|  | ||||
| 3.8.0.1 | ||||
| ======= | ||||
| * Background bug fixes [Ray; #696712] | ||||
|   | ||||
							
								
								
									
										14
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								configure.ac
									
									
									
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| AC_PREREQ(2.63) | ||||
| AC_INIT([gnome-shell],[3.9.3],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell]) | ||||
| AC_INIT([gnome-shell],[3.8.0.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell]) | ||||
|  | ||||
| AC_CONFIG_HEADERS([config.h]) | ||||
| AC_CONFIG_SRCDIR([src/shell-global.c]) | ||||
| @@ -63,18 +63,18 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder) | ||||
| CLUTTER_MIN_VERSION=1.13.4 | ||||
| GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1 | ||||
| GJS_MIN_VERSION=1.35.4 | ||||
| MUTTER_MIN_VERSION=3.9.3 | ||||
| MUTTER_MIN_VERSION=3.8.0 | ||||
| GTK_MIN_VERSION=3.7.9 | ||||
| GIO_MIN_VERSION=2.37.0 | ||||
| GIO_MIN_VERSION=2.35.0 | ||||
| LIBECAL_MIN_VERSION=3.5.3 | ||||
| LIBEDATASERVER_MIN_VERSION=3.5.3 | ||||
| TELEPATHY_GLIB_MIN_VERSION=0.17.5 | ||||
| POLKIT_MIN_VERSION=0.100 | ||||
| STARTUP_NOTIFICATION_MIN_VERSION=0.11 | ||||
| GCR_MIN_VERSION=3.7.5 | ||||
| GCR_MIN_VERSION=3.3.90 | ||||
| GNOME_DESKTOP_REQUIRED_VERSION=3.7.90 | ||||
| GNOME_MENUS_REQUIRED_VERSION=3.5.3 | ||||
| NETWORKMANAGER_MIN_VERSION=0.9.8 | ||||
| NETWORKMANAGER_MIN_VERSION=0.9.6 | ||||
| PULSE_MIN_VERS=2.0 | ||||
|  | ||||
| # Collect more than 20 libraries for a prize! | ||||
| @@ -96,7 +96,7 @@ PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION | ||||
|                                polkit-agent-1 >= $POLKIT_MIN_VERSION xfixes | ||||
|                                libnm-glib libnm-util >= $NETWORKMANAGER_MIN_VERSION | ||||
|                                libnm-gtk >= $NETWORKMANAGER_MIN_VERSION | ||||
|                                libsecret-unstable gcr-base-3 >= $GCR_MIN_VERSION) | ||||
|                                libsecret-unstable gcr-3 >= $GCR_MIN_VERSION) | ||||
|  | ||||
| PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION) | ||||
| PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11) | ||||
| @@ -109,7 +109,7 @@ PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.4) | ||||
| PKG_CHECK_MODULES(CARIBOU, caribou-1.0 >= 0.4.8) | ||||
|  | ||||
| AC_MSG_CHECKING([for bluetooth support]) | ||||
| PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.9.0], | ||||
| PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0], | ||||
|         [BLUETOOTH_DIR=`$PKG_CONFIG --variable=applet_libdir gnome-bluetooth-1.0` | ||||
| 	 BLUETOOTH_LIBS=`$PKG_CONFIG --variable=applet_libs gnome-bluetooth-1.0` | ||||
| 	 AC_SUBST([BLUETOOTH_LIBS],["$BLUETOOTH_LIBS"]) | ||||
|   | ||||
| @@ -11,9 +11,6 @@ | ||||
| 	<KeyListEntry name="focus-active-notification" | ||||
|                       _description="Focus the active notification"/> | ||||
|  | ||||
| 	<KeyListEntry name="toggle-overview" | ||||
|                       _description="Show the overview"/> | ||||
|  | ||||
| 	<KeyListEntry name="toggle-application-view" | ||||
|                       _description="Show all applications"/> | ||||
|  | ||||
|   | ||||
| @@ -15,7 +15,6 @@ desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop | ||||
|  | ||||
| introspectiondir = $(datadir)/dbus-1/interfaces | ||||
| introspection_DATA =				\ | ||||
| 	org.gnome.Shell.Screencast.xml		\ | ||||
| 	org.gnome.Shell.Screenshot.xml		\ | ||||
| 	org.gnome.ShellSearchProvider.xml	\ | ||||
| 	org.gnome.ShellSearchProvider2.xml | ||||
|   | ||||
| @@ -1,96 +0,0 @@ | ||||
| <!DOCTYPE node PUBLIC | ||||
| '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN' | ||||
| 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'> | ||||
| <node> | ||||
|  | ||||
|   <!-- | ||||
|       org.gnome.Shell.Screencast: | ||||
|       @short_description: Screencast interface | ||||
|  | ||||
|       The interface used to record screen contents. | ||||
|   --> | ||||
|   <interface name="org.gnome.Shell.Screencast"> | ||||
|  | ||||
|     <!-- | ||||
|         Screencast: | ||||
|         @file_template: the template for the filename to use | ||||
|         @options: a dictionary of optional parameters | ||||
|         @success: whether the screencast was started successfully | ||||
|         @filename_used: the file where the screencast is being saved | ||||
|  | ||||
|         Records a screencast of the whole screen and saves it | ||||
|         (by default) as webm video under a filename derived from | ||||
|         @file_template. The template is either a relative or absolute | ||||
|         filename which may contain some escape sequences - %d and %t | ||||
|         will be replaced by the start date and time of the recording. | ||||
|         If a relative name is used, the screencast will be saved in the | ||||
|         $XDG_VIDEOS_DIR if it exists, or the home directory otherwise. | ||||
|         The actual filename of the saved video is returned in @filename_used. | ||||
|         The set of optional parameters in @options currently consists of: | ||||
|             'draw-cursor'(b): whether the cursor should be included in the | ||||
|                               recording (true) | ||||
|             'framerate'(i): the number of frames per second that should be | ||||
|                             recorded if possible (30) | ||||
|             'pipeline'(s): the GStreamer pipeline used to encode recordings | ||||
|                            in gst-launch format; if not specified, the | ||||
|                            recorder will produce vp8 (webm) video (unset) | ||||
|     --> | ||||
|     <method name="Screencast"> | ||||
|       <arg type="s" direction="in" name="file_template"/> | ||||
|       <arg type="a{sv}" direction="in" name="options"/> | ||||
|       <arg type="b" direction="in" name="flash"/> | ||||
|       <arg type="b" direction="out" name="success"/> | ||||
|       <arg type="s" direction="out" name="filename_used"/> | ||||
|     </method> | ||||
|  | ||||
|     <!-- | ||||
|         ScreencastArea: | ||||
|         @x: the X coordinate of the area to capture | ||||
|         @y: the Y coordinate of the area to capture | ||||
|         @width: the width of the area to capture | ||||
|         @height: the height of the area to capture | ||||
|         @file_template: the template for the filename to use | ||||
|         @options: a dictionary of optional parameters | ||||
|         @success: whether the screencast was started successfully | ||||
|         @filename_used: the file where the screencast is being saved | ||||
|  | ||||
|         Records a screencast of the passed in area and saves it | ||||
|         (by default) as webm video under a filename derived from | ||||
|         @file_template. The template is either a relative or absolute | ||||
|         filename which may contain some escape sequences - %d and %t | ||||
|         will be replaced by the start date and time of the recording. | ||||
|         If a relative name is used, the screencast will be saved in the | ||||
|         $XDG_VIDEOS_DIR if it exists, or the home directory otherwise. | ||||
|         The actual filename of the saved video is returned in @filename_used. | ||||
|         The set of optional parameters in @options currently consists of: | ||||
|             'draw-cursor'(b): whether the cursor should be included in the | ||||
|                               recording (true) | ||||
|             'framerate'(i): the number of frames per second that should be | ||||
|                             recorded if possible (30) | ||||
|             'pipeline'(s): the GStreamer pipeline used to encode recordings | ||||
|                            in gst-launch format; if not specified, the | ||||
|                            recorder will produce vp8 (webm) video (unset) | ||||
|     --> | ||||
|     <method name="ScreencastArea"> | ||||
|       <arg type="i" direction="in" name="x"/> | ||||
|       <arg type="i" direction="in" name="y"/> | ||||
|       <arg type="i" direction="in" name="width"/> | ||||
|       <arg type="i" direction="in" name="height"/> | ||||
|       <arg type="s" direction="in" name="file_template"/> | ||||
|       <arg type="a{sv}" direction="in" name="options"/> | ||||
|       <arg type="b" direction="out" name="success"/> | ||||
|       <arg type="s" direction="out" name="filename_used"/> | ||||
|     </method> | ||||
|  | ||||
|     <!-- | ||||
|         StopScreencast: | ||||
|         @success: whether stopping the recording was successful | ||||
|  | ||||
|         Stop the recording started by either Screencast or ScreencastArea. | ||||
|     --> | ||||
|     <method name="StopScreencast"> | ||||
|       <arg type="b" direction="out" name="success"/> | ||||
|     </method> | ||||
|  | ||||
|   </interface> | ||||
| </node> | ||||
| @@ -46,7 +46,7 @@ | ||||
|     <!-- | ||||
|         GetResultMetas: | ||||
|         @identifiers: An array of result identifiers as returned by GetInitialResultSet() or GetSubsearchResultSet() | ||||
|         @metas: A dictionary describing the given search result, containing a human-readable 'name' (string), along with the result identifier this meta is for, 'id' (string). Optionally, 'icon' (a serialized GIcon as obtained by g_icon_serialize) can be specified if the result can be better served with a thumbnail of the content (such as with images). 'gicon' (a serialized GIcon as obtained by g_icon_to_string) or 'icon-data' (raw image data as (iiibiiay) - width, height, rowstride, has-alpha, bits per sample, channels, data) are deprecated values that can also be used for that purpose. A 'description' field (string) may also be specified if more context would help the user find the desired result. | ||||
|         @metas: A dictionary describing the given search result, containing a human-readable 'name' (string), along with the result identifier this meta is for, 'id' (string). Optionally, either 'gicon' (a serialized GIcon) or 'icon-data' (raw image data as (iiibiiay) - width, height, rowstride, has-alpha, bits per sample, channels, data) can be specified if the result can be better served with a thumbnail of the content (such as with images). A 'description' field (string) may also be specified if more context would help the user find the desired result. | ||||
|  | ||||
|         Return an array of meta data used to display each given result | ||||
|     --> | ||||
|   | ||||
| @@ -21,6 +21,16 @@ | ||||
|         EnableExtension and DisableExtension DBus methods on org.gnome.Shell. | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="enable-app-monitoring" type="b"> | ||||
|       <default>true</default> | ||||
|       <_summary>Whether to collect stats about applications usage</_summary> | ||||
|       <_description> | ||||
|         The shell normally monitors active applications in order to present | ||||
|         the most used ones (e.g. in launchers). While this data will be | ||||
|         kept private, you may want to disable this for privacy reasons. | ||||
|         Please note that doing so won't remove already saved data. | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="favorite-apps" type="as"> | ||||
|       <default>[ 'epiphany.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'libreoffice-writer.desktop', 'nautilus.desktop', 'gnome-documents.desktop' ]</default> | ||||
|       <_summary>List of desktop file IDs for favorite applications</_summary> | ||||
| @@ -107,13 +117,6 @@ value here is from the GsmPresenceStatus enumeration.</_summary> | ||||
|         Overview. | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="toggle-overview" type="as"> | ||||
|       <default>["<Super>s"]</default> | ||||
|       <_summary>Keybinding to open the overview</_summary> | ||||
|       <_description> | ||||
|         Keybinding to open the Activities Overview. | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key name="toggle-message-tray" type="as"> | ||||
|       <default>["<Super>m"]</default> | ||||
|       <_summary>Keybinding to toggle the visibility of the message tray</_summary> | ||||
| @@ -204,7 +207,7 @@ value here is from the GsmPresenceStatus enumeration.</_summary> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key type="b" name="current-workspace-only"> | ||||
|       <default>true</default> | ||||
|       <default>false</default> | ||||
|       <summary>Limit switcher to current workspace.</summary> | ||||
|       <description> | ||||
| 	If true, only windows from the current workspace are shown in the switcher. | ||||
|   | ||||
| @@ -123,26 +123,8 @@ StScrollBar StButton#vhandle:active { | ||||
|     background-image: url("checkbox-focused.svg"); | ||||
| } | ||||
|  | ||||
| /* Slider */ | ||||
|  | ||||
| .slider { | ||||
|     height: 1em; | ||||
|     min-width: 15em; | ||||
|     -slider-height: 0.3em; | ||||
|     -slider-background-color: #333333; | ||||
|     -slider-border-color: #5f5f5f; | ||||
|     -slider-active-background-color: #76b0ec; | ||||
|     -slider-active-border-color: #1f6dbc; | ||||
|     -slider-border-width: 1px; | ||||
|     -slider-handle-radius: 0.5em; | ||||
| } | ||||
|  | ||||
| /* PopupMenu */ | ||||
|  | ||||
| .popup-menu-ornament { | ||||
|     text-align: center; | ||||
| } | ||||
|  | ||||
| .popup-menu-boxpointer, | ||||
| .candidate-popup-boxpointer { | ||||
|     -arrow-border-radius: 8px; | ||||
| @@ -236,6 +218,18 @@ StScrollBar StButton#vhandle:active { | ||||
|     font-weight: bold; | ||||
| } | ||||
|  | ||||
| .popup-slider-menu-item { | ||||
|     height: 1em; | ||||
|     min-width: 15em; | ||||
|     -slider-height: 0.3em; | ||||
|     -slider-background-color: #333333; | ||||
|     -slider-border-color: #5f5f5f; | ||||
|     -slider-active-background-color: #76b0ec; | ||||
|     -slider-active-border-color: #1f6dbc; | ||||
|     -slider-border-width: 1px; | ||||
|     -slider-handle-radius: 0.5em; | ||||
| } | ||||
|  | ||||
| .popup-device-menu-item { | ||||
|     spacing: .5em; | ||||
| } | ||||
| @@ -383,7 +377,6 @@ StScrollBar StButton#vhandle:active { | ||||
| /* Entries */ | ||||
|  | ||||
| #searchEntry, | ||||
| .login-dialog StEntry, | ||||
| .notification StEntry, | ||||
| .modal-dialog StEntry { | ||||
|     color: rgb(64, 64, 64); | ||||
| @@ -395,7 +388,6 @@ StScrollBar StButton#vhandle:active { | ||||
| } | ||||
|  | ||||
| #searchEntry, | ||||
| .login-dialog StEntry, | ||||
| .run-dialog-entry, | ||||
| .notification StEntry { | ||||
|     border: 2px solid rgba(245,245,245,0.2); | ||||
| @@ -408,7 +400,6 @@ StScrollBar StButton#vhandle:active { | ||||
|  | ||||
| #searchEntry:focus, | ||||
| #searchEntry:hover, | ||||
| .login-dialog StEntry:focus, | ||||
| .notification StEntry:focus, | ||||
| .modal-dialog StEntry { | ||||
|     border: 2px solid rgb(136,138,133); | ||||
| @@ -418,7 +409,6 @@ StScrollBar StButton#vhandle:active { | ||||
|     box-shadow: inset 0px 2px 4px rgba(0,0,0,0.6); | ||||
| } | ||||
|  | ||||
| .login-dialog StEntry:focus, | ||||
| .notification StEntry:focus, | ||||
| .modal-dialog StEntry:focus { | ||||
|     border: 2px solid #3465a4; | ||||
| @@ -442,7 +432,6 @@ StScrollBar StButton#vhandle:active { | ||||
|     transition-duration: 0ms; | ||||
| } | ||||
|  | ||||
| .login-dialog StEntry, | ||||
| .notification StEntry, | ||||
| .modal-dialog StEntry { | ||||
|     border-radius: 5px; | ||||
| @@ -456,7 +445,6 @@ StScrollBar StButton#vhandle:active { | ||||
|     padding: 0 4px; | ||||
| } | ||||
|  | ||||
| .login-dialog StEntry:insensitive, | ||||
| .modal-dialog StEntry:insensitive { | ||||
|     border-color: #666666; | ||||
|     color: #9f9f9f; | ||||
| @@ -524,7 +512,6 @@ StScrollBar StButton#vhandle:active { | ||||
| } | ||||
|  | ||||
| #appMenu { | ||||
|     spinner-image: url("process-working.svg"); | ||||
|     spacing: 4px; | ||||
| } | ||||
|  | ||||
| @@ -812,11 +799,6 @@ StScrollBar StButton#vhandle:active { | ||||
|     height: 24px; | ||||
| } | ||||
|  | ||||
| .empty-dash-drop-target { | ||||
|     width: 24px; | ||||
|     height: 24px; | ||||
| } | ||||
|  | ||||
| /* Search Box */ | ||||
|  | ||||
| #searchEntry { | ||||
| @@ -904,11 +886,12 @@ StScrollBar StButton#vhandle:active { | ||||
| } | ||||
|  | ||||
| .app-view-controls { | ||||
|     width: 250px; | ||||
|     padding-bottom: 32px; | ||||
| } | ||||
|  | ||||
| .app-view-control { | ||||
|     padding: 4px 32px; | ||||
|     padding: 4px 16px; | ||||
| } | ||||
|  | ||||
| .search-display > StBoxLayout, | ||||
| @@ -1160,6 +1143,11 @@ StScrollBar StButton#vhandle:active { | ||||
|  | ||||
| /* Calendar popup */ | ||||
|  | ||||
| #calendarEventsArea { | ||||
|     /* this is the width of the second column of the popup */ | ||||
|     min-width: 320px; | ||||
| } | ||||
|  | ||||
| .calendar-vertical-separator { | ||||
|     -stipple-width: 1px; | ||||
|     -stipple-color: #505050; | ||||
| @@ -1195,8 +1183,7 @@ StScrollBar StButton#vhandle:active { | ||||
|     background-image: url("calendar-arrow-right.svg"); | ||||
| } | ||||
|  | ||||
| .calendar-change-month-back:hover, | ||||
| .calendar-change-month-back:focus { | ||||
| .calendar-change-month-back:hover { | ||||
|     background-color: #999999; | ||||
| } | ||||
| .calendar-change-month-back:active { | ||||
| @@ -1214,8 +1201,7 @@ StScrollBar StButton#vhandle:active { | ||||
|     background-image: url("calendar-arrow-left.svg"); | ||||
| } | ||||
|  | ||||
| .calendar-change-month-forward:hover, | ||||
| .calendar-change-month-forward:focus { | ||||
| .calendar-change-month-forward:hover { | ||||
|     background-color: #999999; | ||||
| } | ||||
| .calendar-change-month-forward:active { | ||||
| @@ -1236,8 +1222,7 @@ StScrollBar StButton#vhandle:active { | ||||
|     height: 2.4em; | ||||
| } | ||||
|  | ||||
| .calendar-day-base:hover, | ||||
| .calendar-day-base:focus { | ||||
| .calendar-day-base:hover { | ||||
|     background-color: #777777; | ||||
| } | ||||
|  | ||||
| @@ -1296,40 +1281,32 @@ StScrollBar StButton#vhandle:active { | ||||
|     color: #333333; | ||||
| } | ||||
|  | ||||
| .events-table { | ||||
|     min-width: 320px; | ||||
|     spacing-columns: 6pt; | ||||
|     padding: 0 1.4em; | ||||
| .events-header-vbox { | ||||
|     spacing: 6pt; | ||||
|     padding-right: .5em; | ||||
| } | ||||
|  | ||||
| .events-table:ltr { | ||||
|     padding-right: 1.9em; | ||||
| .events-header-vbox:rtl { | ||||
|     padding-left: .5em; | ||||
| } | ||||
|  | ||||
| .events-table:rtl { | ||||
|     padding-left: 1.9em; | ||||
| .events-header-hbox { | ||||
|     padding: 0.3em 1.4em; | ||||
| } | ||||
|  | ||||
| .events-day-header { | ||||
|     font-weight: bold; | ||||
|     color: #999999; | ||||
|     padding-left: 0.4em; | ||||
|     padding-top: 1.2em; | ||||
| } | ||||
|  | ||||
| .events-day-header:first-child { | ||||
|     padding-top: 0; | ||||
|     padding: 0.4em 1.4em 0em 1.4em; | ||||
| } | ||||
|  | ||||
| .events-day-header:rtl { | ||||
|     padding-left: 0; | ||||
|     padding-right: 0.4em; | ||||
|     padding: 0em 1.4em 0.4em 1.4em; | ||||
| } | ||||
|  | ||||
| .events-day-dayname { | ||||
|     color: rgba(153, 153, 153, 1.0); | ||||
|     text-align: left; | ||||
|     min-width: 20px; | ||||
| } | ||||
|  | ||||
| .events-day-dayname:rtl { | ||||
| @@ -1347,12 +1324,23 @@ StScrollBar StButton#vhandle:active { | ||||
|  | ||||
| .events-day-task { | ||||
|     color: rgba(153, 153, 153, 1.0); | ||||
|     padding-left: 8pt; | ||||
| } | ||||
|  | ||||
| .events-day-task:rtl { | ||||
|     padding-left: 0px; | ||||
|     padding-right: 8pt; | ||||
| .events-day-name-box { | ||||
|     min-width: 15pt; | ||||
| } | ||||
|  | ||||
| .events-time-box { | ||||
|     min-width: 48pt; | ||||
|     padding-right: 12pt; | ||||
| } | ||||
|  | ||||
| .events-time-box:rtl { | ||||
|     padding-right: 0px; | ||||
|     padding-left: 12pt; | ||||
| } | ||||
|  | ||||
| .events-event-box { | ||||
| } | ||||
|  | ||||
| .url-highlighter { | ||||
| @@ -1465,13 +1453,11 @@ StScrollBar StButton#vhandle:active { | ||||
| } | ||||
|  | ||||
| .notification-button { | ||||
|     -st-natural-width: 140px; | ||||
|     padding: 4px 4px 5px; | ||||
|     padding: 4px 42px 5px; | ||||
| } | ||||
|  | ||||
| .notification-button:focus { | ||||
|     -st-natural-width: 138px; | ||||
|     padding: 3px 4px 4px; | ||||
|     padding: 3px 41px 4px; | ||||
| } | ||||
|  | ||||
| .notification-icon-button { | ||||
| @@ -2319,7 +2305,6 @@ StScrollBar StButton#vhandle:active { | ||||
|     font-weight: bold; | ||||
|     color: #666666; | ||||
|     padding-top: 1em; | ||||
|     padding-left: 2px; | ||||
| } | ||||
|  | ||||
| .login-dialog-not-listed-button:focus .login-dialog-not-listed-label, | ||||
| @@ -2350,21 +2335,52 @@ StScrollBar StButton#vhandle:active { | ||||
|     width: 15em; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-button StIcon { | ||||
|     icon-size: 1.25em; | ||||
| .login-dialog-session-list { | ||||
|     color: #ffffff; | ||||
|     font-size: 10.5pt; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-button { | ||||
|     color: #8b8b8b; | ||||
|     padding: 4px; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-button:focus { | ||||
|     background-color: #4c4c4c; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-button:hover, | ||||
| .login-dialog-session-list-button:active { | ||||
|     color: white; | ||||
|     background-color: #4c4c4c; | ||||
| } | ||||
|  | ||||
| .login-dialog-logo-bin { | ||||
|     padding: 24px 0px; | ||||
| .login-dialog-session-list-button:hover { | ||||
|     font-weight: bold; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-scroll-view { | ||||
|     background-gradient-start: rgba(80,80,80,0.3); | ||||
|     background-gradient-end: rgba(80,80,80,0.7); | ||||
|     background-gradient-direction: vertical; | ||||
|     box-shadow: inset 0px 2px 4px rgba(0,0,0,0.9); | ||||
|     border-radius: 8px; | ||||
|     border: 1px solid rgba(80,80,80,1.0); | ||||
|     padding: .5em; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-item:focus { | ||||
|     background-color: #666666; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-triangle { | ||||
|     padding-right: .5em; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-item-box { | ||||
|     spacing: .25em; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-item-dot { | ||||
|     width: .75em; | ||||
|     height: .75em; | ||||
| } | ||||
|  | ||||
| .login-dialog .modal-dialog-button-box { | ||||
|   | ||||
| @@ -46,7 +46,6 @@ | ||||
|     <xi:include href="doc-gen-org.gnome.Shell.SearchProvider.xml"/> | ||||
|     <xi:include href="doc-gen-org.gnome.Shell.SearchProvider2.xml"/> | ||||
|     <xi:include href="xml/shell-global.xml"/> | ||||
|     <xi:include href="xml/shell-keybinding-modes.xml"/> | ||||
|     <xi:include href="xml/shell-wm.xml"/> | ||||
|     <xi:include href="xml/shell-xfixes-cursor.xml"/> | ||||
|     <xi:include href="xml/shell-util.xml"/> | ||||
|   | ||||
| @@ -37,7 +37,6 @@ nobase_dist_js_DATA = 	\ | ||||
| 	misc/util.js		\ | ||||
| 	perf/core.js		\ | ||||
| 	ui/altTab.js		\ | ||||
| 	ui/animation.js		\ | ||||
| 	ui/appDisplay.js	\ | ||||
| 	ui/appFavorites.js	\ | ||||
| 	ui/backgroundMenu.js	\ | ||||
| @@ -69,7 +68,6 @@ nobase_dist_js_DATA = 	\ | ||||
| 	ui/sessionMode.js	\ | ||||
| 	ui/shellEntry.js	\ | ||||
| 	ui/shellMountOperation.js \ | ||||
| 	ui/slider.js		\ | ||||
| 	ui/notificationDaemon.js \ | ||||
| 	ui/osdWindow.js		\ | ||||
| 	ui/overview.js		\ | ||||
| @@ -79,9 +77,7 @@ nobase_dist_js_DATA = 	\ | ||||
| 	ui/pointerWatcher.js    \ | ||||
| 	ui/popupMenu.js		\ | ||||
| 	ui/remoteSearch.js	\ | ||||
| 	ui/remoteMenu.js	\ | ||||
| 	ui/runDialog.js		\ | ||||
| 	ui/screencast.js	\ | ||||
| 	ui/screenshot.js	\ | ||||
|         ui/screenShield.js	\ | ||||
| 	ui/scripting.js		\ | ||||
|   | ||||
| @@ -19,46 +19,72 @@ | ||||
|  */ | ||||
|  | ||||
| const AccountsService = imports.gi.AccountsService; | ||||
| const Atk = imports.gi.Atk; | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Gdm = imports.gi.Gdm; | ||||
| const CtrlAltTab = imports.ui.ctrlAltTab; | ||||
| const Gio = imports.gi.Gio; | ||||
| const GLib = imports.gi.GLib; | ||||
| const Gtk = imports.gi.Gtk; | ||||
| const Lang = imports.lang; | ||||
| const Mainloop = imports.mainloop; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Shell = imports.gi.Shell; | ||||
| const Lang = imports.lang; | ||||
| const Pango = imports.gi.Pango; | ||||
| const Signals = imports.signals; | ||||
| const Shell = imports.gi.Shell; | ||||
| const St = imports.gi.St; | ||||
| const Gdm = imports.gi.Gdm; | ||||
|  | ||||
| const Animation = imports.ui.animation; | ||||
| const Batch = imports.gdm.batch; | ||||
| const BoxPointer = imports.ui.boxpointer; | ||||
| const CtrlAltTab = imports.ui.ctrlAltTab; | ||||
| const Fprint = imports.gdm.fingerprint; | ||||
| const GdmUtil = imports.gdm.util; | ||||
| const Layout = imports.ui.layout; | ||||
| const Lightbox = imports.ui.lightbox; | ||||
| const Main = imports.ui.main; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
| const Realmd = imports.gdm.realmd; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
| const Panel = imports.ui.panel; | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const UserMenu = imports.ui.userMenu; | ||||
| const UserWidget = imports.ui.userWidget; | ||||
|  | ||||
| const _FADE_ANIMATION_TIME = 0.25; | ||||
| const _SCROLL_ANIMATION_TIME = 0.5; | ||||
| const _DEFAULT_BUTTON_WELL_ICON_SIZE = 24; | ||||
| const _DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1.0; | ||||
| const _DEFAULT_BUTTON_WELL_ANIMATION_TIME = 0.3; | ||||
| const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0; | ||||
| const _LOGO_ICON_HEIGHT = 48; | ||||
| const _LOGO_ICON_HEIGHT = 16; | ||||
|  | ||||
| const WORK_SPINNER_ICON_SIZE = 24; | ||||
| const WORK_SPINNER_ANIMATION_DELAY = 1.0; | ||||
| const WORK_SPINNER_ANIMATION_TIME = 0.3; | ||||
|  | ||||
| let _loginDialog = null; | ||||
|  | ||||
| const DefaultButtonWellMode = { | ||||
|     NONE: 0, | ||||
|     SESSION_MENU_BUTTON: 1, | ||||
|     SPINNER: 2 | ||||
| }; | ||||
| const LogoMenuButton = new Lang.Class({ | ||||
|     Name: 'LogoMenuButton', | ||||
|     Extends: PanelMenu.Button, | ||||
|  | ||||
|     _init: function() { | ||||
|         this.parent(0.0, null, true); | ||||
|  | ||||
|         this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA }); | ||||
|         this._settings.connect('changed::' + GdmUtil.LOGO_KEY, | ||||
|                                Lang.bind(this, this._updateLogo)); | ||||
|  | ||||
|         this._iconBin = new St.Bin(); | ||||
|         this.actor.add_actor(this._iconBin); | ||||
|  | ||||
|         this._updateLogo(); | ||||
|     }, | ||||
|  | ||||
|     _updateLogo: function() { | ||||
|         let path = this._settings.get_string(GdmUtil.LOGO_KEY); | ||||
|         let icon = null; | ||||
|  | ||||
|         if (path) { | ||||
|             let file = Gio.file_new_for_path(path); | ||||
|             let cache = St.TextureCache.get_default(); | ||||
|             icon = cache.load_uri_async(file.get_uri(), -1, _LOGO_ICON_HEIGHT); | ||||
|         } | ||||
|         this._iconBin.set_child(icon); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const UserListItem = new Lang.Class({ | ||||
|     Name: 'UserListItem', | ||||
| @@ -77,8 +103,8 @@ const UserListItem = new Lang.Class({ | ||||
|                                      x_align: St.Align.START, | ||||
|                                      x_fill: true }); | ||||
|  | ||||
|         this._userAvatar = new UserWidget.Avatar(this.user, | ||||
|                                                  { styleClass: 'login-dialog-user-list-item-icon' }); | ||||
|         this._userAvatar = new UserMenu.UserAvatarWidget(this.user, | ||||
|                                                          { styleClass: 'login-dialog-user-list-item-icon' }); | ||||
|         layout.add(this._userAvatar.actor); | ||||
|         let textLayout = new St.BoxLayout({ style_class: 'login-dialog-user-list-item-text-box', | ||||
|                                             vertical:    true }); | ||||
| @@ -296,118 +322,203 @@ const UserList = new Lang.Class({ | ||||
| }); | ||||
| Signals.addSignalMethods(UserList.prototype); | ||||
|  | ||||
| const SessionMenuButton = new Lang.Class({ | ||||
|     Name: 'SessionMenuButton', | ||||
| const SessionListItem = new Lang.Class({ | ||||
|     Name: 'SessionListItem', | ||||
|  | ||||
|     _init: function(id, name) { | ||||
|         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, | ||||
|                                      x_align: St.Align.START }); | ||||
|  | ||||
|         this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list-item-box' }); | ||||
|  | ||||
|         this.actor.add_actor(this._box); | ||||
|         this.actor.connect('clicked', Lang.bind(this, this._onClicked)); | ||||
|  | ||||
|         this._dot = new St.DrawingArea({ style_class: 'login-dialog-session-list-item-dot' }); | ||||
|         this._dot.connect('repaint', Lang.bind(this, this._onRepaintDot)); | ||||
|         this._box.add_actor(this._dot); | ||||
|         this.setShowDot(false); | ||||
|  | ||||
|         let label = new St.Label({ style_class: 'login-dialog-session-list-item-label', | ||||
|                                    text: name }); | ||||
|         this.actor.label_actor = label; | ||||
|  | ||||
|         this._box.add_actor(label); | ||||
|     }, | ||||
|  | ||||
|     setShowDot: function(show) { | ||||
|         if (show) | ||||
|             this._dot.opacity = 255; | ||||
|         else | ||||
|             this._dot.opacity = 0; | ||||
|     }, | ||||
|  | ||||
|     _onRepaintDot: function(area) { | ||||
|         let cr = area.get_context(); | ||||
|         let [width, height] = area.get_surface_size(); | ||||
|         let color = area.get_theme_node().get_foreground_color(); | ||||
|  | ||||
|         cr.setSourceRGBA (color.red / 255, | ||||
|                           color.green / 255, | ||||
|                           color.blue / 255, | ||||
|                           color.alpha / 255); | ||||
|         cr.arc(width / 2, height / 2, width / 3, 0, 2 * Math.PI); | ||||
|         cr.fill(); | ||||
|         cr.$dispose(); | ||||
|     }, | ||||
|  | ||||
|     _onClicked: function() { | ||||
|         this.emit('activate'); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(SessionListItem.prototype); | ||||
|  | ||||
| const SessionList = new Lang.Class({ | ||||
|     Name: 'SessionList', | ||||
|  | ||||
|     _init: function() { | ||||
|         let gearIcon = new St.Icon({ icon_name: 'emblem-system-symbolic' }); | ||||
|         this.actor = new St.Bin(); | ||||
|  | ||||
|         this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list', | ||||
|                                        vertical: true}); | ||||
|         this.actor.child = this._box; | ||||
|  | ||||
|         this._button = new St.Button({ style_class: 'login-dialog-session-list-button', | ||||
|                                        reactive: true, | ||||
|                                        track_hover: true, | ||||
|                                        button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, | ||||
|                                        can_focus: true, | ||||
|                                        accessible_name: _("Choose Session"), | ||||
|                                        accessible_role: Atk.Role.MENU, | ||||
|                                        child: gearIcon }); | ||||
|                                        x_fill: true, | ||||
|                                        y_fill: true }); | ||||
|         let box = new St.BoxLayout(); | ||||
|         this._button.add_actor(box); | ||||
|  | ||||
|         this.actor = new St.Bin({ child: this._button }); | ||||
|         this._triangle = new St.Label({ style_class: 'login-dialog-session-list-triangle', | ||||
|                                         text: '\u25B8' }); | ||||
|         box.add_actor(this._triangle); | ||||
|  | ||||
|         this._menu = new PopupMenu.PopupMenu(this._button, 0, St.Side.TOP); | ||||
|         Main.uiGroup.add_actor(this._menu.actor); | ||||
|         this._menu.actor.hide(); | ||||
|         let label = new St.Label({ style_class: 'login-dialog-session-list-label', | ||||
|                                    text: _("Session…") }); | ||||
|         box.add_actor(label); | ||||
|  | ||||
|         this._menu.connect('open-state-changed', | ||||
|                            Lang.bind(this, function(menu, isOpen) { | ||||
|                                 if (isOpen) | ||||
|                                     this._button.add_style_pseudo_class('active'); | ||||
|                                 else | ||||
|                                     this._button.remove_style_pseudo_class('active'); | ||||
|                            })); | ||||
|  | ||||
|         let subtitle = new PopupMenu.PopupMenuItem(_("Session"), { style_class: 'popup-subtitle-menu-item', | ||||
|                                                                    reactive: false }); | ||||
|         this._menu.addMenuItem(subtitle); | ||||
|  | ||||
|         this._manager = new PopupMenu.PopupMenuManager({ actor: this._button }); | ||||
|         this._manager.addMenu(this._menu); | ||||
|  | ||||
|         this._button.connect('clicked', Lang.bind(this, function() { | ||||
|             this._menu.toggle(); | ||||
|         })); | ||||
|  | ||||
|         this._items = {}; | ||||
|         this._activeSessionId = null; | ||||
|         this._button.connect('clicked', | ||||
|                              Lang.bind(this, this._onClicked)); | ||||
|         this._box.add_actor(this._button); | ||||
|         this._scrollView = new St.ScrollView({ style_class: 'login-dialog-session-list-scroll-view'}); | ||||
|         this._scrollView.set_policy(Gtk.PolicyType.NEVER, | ||||
|                                     Gtk.PolicyType.AUTOMATIC); | ||||
|         this._box.add_actor(this._scrollView); | ||||
|         this._itemList = new St.BoxLayout({ style_class: 'login-dialog-session-item-list', | ||||
|                                             vertical: true }); | ||||
|         this._scrollView.add_actor(this._itemList); | ||||
|         this._scrollView.hide(); | ||||
|         this.isOpen = false; | ||||
|         this._populate(); | ||||
|     }, | ||||
|  | ||||
|     open: function() { | ||||
|         if (this.isOpen) | ||||
|             return; | ||||
|  | ||||
|         this._button.add_style_pseudo_class('open'); | ||||
|         this._scrollView.show(); | ||||
|         this._triangle.set_text('\u25BE'); | ||||
|  | ||||
|         this.isOpen = true; | ||||
|     }, | ||||
|  | ||||
|     close: function() { | ||||
|         if (!this.isOpen) | ||||
|             return; | ||||
|  | ||||
|         this._button.remove_style_pseudo_class('open'); | ||||
|         this._scrollView.hide(); | ||||
|         this._triangle.set_text('\u25B8'); | ||||
|  | ||||
|         this.isOpen = false; | ||||
|     }, | ||||
|  | ||||
|     _onClicked: function() { | ||||
|         if (!this.isOpen) | ||||
|             this.open(); | ||||
|         else | ||||
|             this.close(); | ||||
|     }, | ||||
|  | ||||
|     updateSensitivity: function(sensitive) { | ||||
|         this._button.reactive = sensitive; | ||||
|         this._button.can_focus = sensitive; | ||||
|         this._menu.close(BoxPointer.PopupAnimation.NONE); | ||||
|     }, | ||||
|  | ||||
|     _updateOrnament: function() { | ||||
|         let itemIds = Object.keys(this._items); | ||||
|         for (let i = 0; i < itemIds.length; i++) { | ||||
|             if (itemIds[i] == this._activeSessionId) | ||||
|                 this._items[itemIds[i]].setOrnament(PopupMenu.Ornament.DOT); | ||||
|             else | ||||
|                 this._items[itemIds[i]].setOrnament(PopupMenu.Ornament.NONE); | ||||
|         } | ||||
|         for (let id in this._items) | ||||
|             this._items[id].actor.reactive = sensitive; | ||||
|     }, | ||||
|  | ||||
|     setActiveSession: function(sessionId) { | ||||
|          if (sessionId == this._activeSessionId) | ||||
|              return; | ||||
|  | ||||
|          if (this._activeSessionId) | ||||
|              this._items[this._activeSessionId].setShowDot(false); | ||||
|  | ||||
|          this._items[sessionId].setShowDot(true); | ||||
|          this._activeSessionId = sessionId; | ||||
|          this._updateOrnament(); | ||||
|  | ||||
|          this.emit('session-activated', this._activeSessionId); | ||||
|     }, | ||||
|  | ||||
|     close: function() { | ||||
|         this._menu.close(); | ||||
|     }, | ||||
|  | ||||
|     _populate: function() { | ||||
|         this._itemList.destroy_all_children(); | ||||
|         this._activeSessionId = null; | ||||
|         this._items = {}; | ||||
|  | ||||
|         let ids = Gdm.get_session_ids(); | ||||
|         ids.sort(); | ||||
|  | ||||
|         if (ids.length <= 1) { | ||||
|             this._box.hide(); | ||||
|             this._button.hide(); | ||||
|             return; | ||||
|         } else { | ||||
|             this._button.show(); | ||||
|             this._box.show(); | ||||
|         } | ||||
|  | ||||
|         for (let i = 0; i < ids.length; i++) { | ||||
|             let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]); | ||||
|  | ||||
|             let id = ids[i]; | ||||
|             let item = new PopupMenu.PopupMenuItem(sessionName); | ||||
|             this._menu.addMenuItem(item); | ||||
|             this._items[id] = item; | ||||
|             let item = new SessionListItem(ids[i], sessionName); | ||||
|             this._itemList.add_actor(item.actor); | ||||
|             this._items[ids[i]] = item; | ||||
|  | ||||
|             if (!this._activeSessionId) | ||||
|                 this.setActiveSession(id); | ||||
|                 this.setActiveSession(ids[i]); | ||||
|  | ||||
|             item.connect('activate', Lang.bind(this, function() { | ||||
|                 this.setActiveSession(id); | ||||
|             })); | ||||
|             item.connect('activate', | ||||
|                          Lang.bind(this, function() { | ||||
|                              this.setActiveSession(item.id); | ||||
|                          })); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(SessionMenuButton.prototype); | ||||
| Signals.addSignalMethods(SessionList.prototype); | ||||
|  | ||||
| const LoginDialog = new Lang.Class({ | ||||
|     Name: 'LoginDialog', | ||||
|     Extends: ModalDialog.ModalDialog, | ||||
|  | ||||
|     _init: function(parentActor) { | ||||
|         this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW, | ||||
|                                      style_class: 'login-dialog', | ||||
|                                      visible: false }); | ||||
|  | ||||
|         this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true })); | ||||
|         this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | ||||
|         parentActor.add_child(this.actor); | ||||
|         this.parent({ shellReactive: true, | ||||
|                       styleClass: 'login-dialog', | ||||
|                       parentActor: parentActor, | ||||
|                       keybindingMode: Shell.KeyBindingMode.LOGIN_SCREEN, | ||||
|                       shouldFadeIn: false }); | ||||
|         this.connect('destroy', | ||||
|                      Lang.bind(this, this._onDestroy)); | ||||
|         this.connect('opened', | ||||
|                      Lang.bind(this, this._onOpened)); | ||||
|  | ||||
|         this._userManager = AccountsService.UserManager.get_default() | ||||
|         this._greeterClient = new Gdm.Client(); | ||||
| @@ -441,19 +552,10 @@ const LoginDialog = new Lang.Class({ | ||||
|                                Lang.bind(this, this._updateBanner)); | ||||
|         this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY, | ||||
|                                Lang.bind(this, this._updateDisableUserList)); | ||||
|         this._settings.connect('changed::' + GdmUtil.LOGO_KEY, | ||||
|                                Lang.bind(this, this._updateLogo)); | ||||
|  | ||||
|         this._textureCache = St.TextureCache.get_default(); | ||||
|         this._textureCache.connect('texture-file-changed', | ||||
|                                    Lang.bind(this, this._updateLogoTexture)); | ||||
|  | ||||
|         this._userSelectionBox = new St.BoxLayout({ style_class: 'login-dialog-user-selection-box', | ||||
|                                                     vertical: true }); | ||||
|         this._userSelectionBox.add_constraint(new Clutter.AlignConstraint({ source: this.actor, | ||||
|                                                                             align_axis: Clutter.AlignAxis.BOTH, | ||||
|                                                                             factor: 0.5 })); | ||||
|         this.actor.add_child(this._userSelectionBox); | ||||
|         this.contentLayout.add(this._userSelectionBox); | ||||
|  | ||||
|         this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner', | ||||
|                                            text: '' }); | ||||
| @@ -466,20 +568,15 @@ const LoginDialog = new Lang.Class({ | ||||
|                                      x_fill: true, | ||||
|                                      y_fill: true }); | ||||
|  | ||||
|         this.setInitialKeyFocus(this._userList.actor); | ||||
|  | ||||
|         this._promptBox = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout', | ||||
|                                              vertical: true }); | ||||
|  | ||||
|         this._promptBox.connect('button-press-event', | ||||
|                                  Lang.bind(this, function(actor, event) { | ||||
|                                     if (event.get_key_symbol() == Clutter.KEY_Escape) { | ||||
|                                         this.cancel(); | ||||
|                                     } | ||||
|                                  })); | ||||
|  | ||||
|         this._promptBox.add_constraint(new Clutter.AlignConstraint({ source: this.actor, | ||||
|                                                                      align_axis: Clutter.AlignAxis.BOTH, | ||||
|                                                                      factor: 0.5 })); | ||||
|         this.actor.add_child(this._promptBox); | ||||
|         this.contentLayout.add(this._promptBox, | ||||
|                                { expand: true, | ||||
|                                  x_fill: true, | ||||
|                                  y_fill: true, | ||||
|                                  x_align: St.Align.START }); | ||||
|         this._promptUser = new St.Bin({ x_fill: true, | ||||
|                                         x_align: St.Align.START }); | ||||
|         this._promptBox.add(this._promptUser, | ||||
| @@ -511,15 +608,20 @@ const LoginDialog = new Lang.Class({ | ||||
|         this._promptLoginHint.hide(); | ||||
|         this._promptBox.add(this._promptLoginHint); | ||||
|  | ||||
|         this._buttonBox = new St.BoxLayout({ style_class: 'modal-dialog-button-box', | ||||
|                                              vertical: false }); | ||||
|         this._promptBox.add(this._buttonBox, | ||||
|                             { expand:  true, | ||||
|                               x_align: St.Align.MIDDLE, | ||||
|                               y_align: St.Align.END }); | ||||
|         this._cancelButton = null; | ||||
|         this._signInButton = null; | ||||
|         this._workSpinner = null; | ||||
|  | ||||
|         this._sessionList = new SessionList(); | ||||
|         this._sessionList.connect('session-activated', | ||||
|                                   Lang.bind(this, function(list, sessionId) { | ||||
|                                                 this._greeter.call_select_session_sync (sessionId, null); | ||||
|                                             })); | ||||
|  | ||||
|         this._promptBox.add(this._sessionList.actor, | ||||
|                             { expand: true, | ||||
|                               x_fill: false, | ||||
|                               y_fill: true, | ||||
|                               x_align: St.Align.START }); | ||||
|         this._promptBox.hide(); | ||||
|  | ||||
|         // translators: this message is shown below the user list on the | ||||
| @@ -536,24 +638,12 @@ const LoginDialog = new Lang.Class({ | ||||
|                                                 x_fill: true }); | ||||
|  | ||||
|         this._notListedButton.connect('clicked', Lang.bind(this, this._hideUserListAndLogIn)); | ||||
|         this._notListedButton.hide(); | ||||
|  | ||||
|         this._userSelectionBox.add(this._notListedButton, | ||||
|                                    { expand: false, | ||||
|                                      x_align: St.Align.START, | ||||
|                                      x_fill: true }); | ||||
|  | ||||
|         this._logoBin = new St.Bin({ style_class: 'login-dialog-logo-bin', y_expand: true }); | ||||
|         this._logoBin.set_y_align(Clutter.ActorAlign.END); | ||||
|         this._logoBin.add_constraint(new Clutter.AlignConstraint({ source: this.actor, | ||||
|                                                                    align_axis: Clutter.AlignAxis.X_AXIS, | ||||
|                                                                    factor: 0.5 })); | ||||
|         this._logoBin.add_constraint(new Clutter.AlignConstraint({ source: this.actor, | ||||
|                                                                    align_axis: Clutter.AlignAxis.Y_AXIS, | ||||
|                                                                    factor: 1.0 })); | ||||
|         this.actor.add_child(this._logoBin); | ||||
|         this._updateLogo(); | ||||
|  | ||||
|         if (!this._userManager.is_loaded) | ||||
|             this._userManagerLoadedId = this._userManager.connect('notify::is-loaded', | ||||
|                                                                   Lang.bind(this, function() { | ||||
| @@ -571,27 +661,6 @@ const LoginDialog = new Lang.Class({ | ||||
|                                    this._onUserListActivated(item); | ||||
|                                })); | ||||
|  | ||||
|         this._defaultButtonWell = new St.Widget(); | ||||
|         this._defaultButtonWellMode = DefaultButtonWellMode.NONE; | ||||
|  | ||||
|         this._sessionMenuButton = new SessionMenuButton(); | ||||
|         this._sessionMenuButton.connect('session-activated', | ||||
|                                   Lang.bind(this, function(list, sessionId) { | ||||
|                                                 this._greeter.call_select_session_sync (sessionId, null); | ||||
|                                             })); | ||||
|         this._sessionMenuButton.actor.opacity = 0; | ||||
|         this._sessionMenuButton.actor.show(); | ||||
|         this._defaultButtonWell.add_child(this._sessionMenuButton.actor); | ||||
|  | ||||
|         let spinnerIcon = global.datadir + '/theme/process-working.svg'; | ||||
|         this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, _DEFAULT_BUTTON_WELL_ICON_SIZE); | ||||
|         this._workSpinner.actor.opacity = 0; | ||||
|         this._workSpinner.actor.show(); | ||||
|  | ||||
|         this._defaultButtonWell.add_child(this._workSpinner.actor); | ||||
|         this._sessionMenuButton.actor.add_constraint(new Clutter.AlignConstraint({ source: this._workSpinner.actor, | ||||
|                                                                                    align_axis: Clutter.AlignAxis.BOTH, | ||||
|                                                                                    factor: 0.5 })); | ||||
|    }, | ||||
|  | ||||
|     _updateDisableUserList: function() { | ||||
| @@ -621,24 +690,6 @@ const LoginDialog = new Lang.Class({ | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _updateLogoTexture: function(cache, uri) { | ||||
|         if (this._logoFileUri != uri) | ||||
|             return; | ||||
|  | ||||
|         let icon = null; | ||||
|         if (this._logoFileUri) | ||||
|             icon = this._textureCache.load_uri_async(this._logoFileUri, | ||||
|                                                      -1, _LOGO_ICON_HEIGHT); | ||||
|         this._logoBin.set_child(icon); | ||||
|     }, | ||||
|  | ||||
|     _updateLogo: function() { | ||||
|         let path = this._settings.get_string(GdmUtil.LOGO_KEY); | ||||
|  | ||||
|         this._logoFileUri = path ? Gio.file_new_for_path(path).get_uri() : null; | ||||
|         this._updateLogoTexture(this._textureCache, this._logoFileUri); | ||||
|     }, | ||||
|  | ||||
|     _reset: function() { | ||||
|         this._userVerifier.clear(); | ||||
|  | ||||
| @@ -653,77 +704,15 @@ const LoginDialog = new Lang.Class({ | ||||
|             this._showUserList(); | ||||
|     }, | ||||
|  | ||||
|     _getActorForDefaultButtonWellMode: function(mode) { | ||||
|         let actor; | ||||
|  | ||||
|         if (mode == DefaultButtonWellMode.NONE) | ||||
|             actor = null; | ||||
|         else if (mode == DefaultButtonWellMode.SPINNER) | ||||
|             actor = this._workSpinner.actor; | ||||
|         else if (mode == DefaultButtonWellMode.SESSION_MENU_BUTTON) | ||||
|             actor = this._sessionMenuButton.actor; | ||||
|  | ||||
|         return actor; | ||||
|     }, | ||||
|  | ||||
|     _setDefaultButtonWellMode: function(mode, immediately) { | ||||
|         if (this._defaultButtonWellMode == DefaultButtonWellMode.NONE && | ||||
|             mode == DefaultButtonWellMode.NONE) | ||||
|             return; | ||||
|  | ||||
|         let oldActor = this._getActorForDefaultButtonWellMode(this._defaultButtonWellMode); | ||||
|  | ||||
|         if (oldActor) | ||||
|             Tweener.removeTweens(oldActor); | ||||
|  | ||||
|         let actor = this._getActorForDefaultButtonWellMode(mode); | ||||
|  | ||||
|         if (this._defaultButtonWellMode != mode && oldActor) { | ||||
|             if (immediately) | ||||
|                 oldActor.opacity = 0; | ||||
|             else | ||||
|                 Tweener.addTween(oldActor, | ||||
|                                  { opacity: 0, | ||||
|                                    time: _DEFAULT_BUTTON_WELL_ANIMATION_TIME, | ||||
|                                    delay: _DEFAULT_BUTTON_WELL_ANIMATION_DELAY, | ||||
|                                    transition: 'linear', | ||||
|                                    onCompleteScope: this, | ||||
|                                    onComplete: function() { | ||||
|                                        if (mode == DefaultButtonWellMode.SPINNER) { | ||||
|                                            if (this._workSpinner) | ||||
|                                                this._workSpinner.stop(); | ||||
|                                        } | ||||
|                                    } | ||||
|                                  }); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         if (actor) { | ||||
|             if (mode == DefaultButtonWellMode.SPINNER) | ||||
|                 this._workSpinner.play(); | ||||
|  | ||||
|             if (immediately) | ||||
|                 actor.opacity = 255; | ||||
|             else | ||||
|                 Tweener.addTween(actor, | ||||
|                                  { opacity: 255, | ||||
|                                    time: _DEFAULT_BUTTON_WELL_ANIMATION_TIME, | ||||
|                                    delay: _DEFAULT_BUTTON_WELL_ANIMATION_DELAY, | ||||
|                                    transition: 'linear' }); | ||||
|         } | ||||
|  | ||||
|         this._defaultButtonWellMode = mode; | ||||
|     }, | ||||
|  | ||||
|     _verificationFailed: function() { | ||||
|         this._promptEntry.text = ''; | ||||
|  | ||||
|         this._updateSensitivity(true); | ||||
|         this._setDefaultButtonWellMode(DefaultButtonWellMode.NONE, true); | ||||
|         this._setWorking(false); | ||||
|     }, | ||||
|  | ||||
|     _onDefaultSessionChanged: function(client, sessionId) { | ||||
|         this._sessionMenuButton.setActiveSession(sessionId); | ||||
|         this._sessionList.setActiveSession(sessionId); | ||||
|     }, | ||||
|  | ||||
|     _showMessage: function(userVerifier, message, styleClass) { | ||||
| @@ -754,20 +743,8 @@ const LoginDialog = new Lang.Class({ | ||||
|             this._reset(); | ||||
|     }, | ||||
|  | ||||
|     _shouldShowSessionMenuButton: function() { | ||||
|         if (this._verifyingUser) | ||||
|           return true; | ||||
|  | ||||
|         if (!this._user) | ||||
|           return false; | ||||
|  | ||||
|         if (this._user.is_logged_in) | ||||
|           return false; | ||||
|  | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _showPrompt: function(forSecret) { | ||||
|         this._sessionList.actor.hide(); | ||||
|         this._promptLabel.show(); | ||||
|         this._promptEntry.show(); | ||||
|         this._promptLoginHint.opacity = 0; | ||||
| @@ -779,10 +756,8 @@ const LoginDialog = new Lang.Class({ | ||||
|                            time: _FADE_ANIMATION_TIME, | ||||
|                            transition: 'easeOutQuad' }); | ||||
|  | ||||
|         if (this._shouldShowSessionMenuButton()) | ||||
|             this._setDefaultButtonWellMode(DefaultButtonWellMode.SESSION_MENU_BUTTON, true); | ||||
|         else | ||||
|             this._setDefaultButtonWellMode(DefaultButtonWellMode.NONE, true); | ||||
|         if ((this._user && !this._user.is_logged_in()) || this._verifyingUser) | ||||
|             this._sessionList.actor.show(); | ||||
|  | ||||
|         this._promptEntry.grab_key_focus(); | ||||
|  | ||||
| @@ -799,49 +774,38 @@ const LoginDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _prepareDialog: function(forSecret, hold) { | ||||
|         this._buttonBox.visible = true; | ||||
|         this._buttonBox.remove_all_children(); | ||||
|         this._workSpinner = new Panel.AnimatedIcon('process-working.svg', WORK_SPINNER_ICON_SIZE); | ||||
|         this._workSpinner.actor.opacity = 0; | ||||
|         this._workSpinner.actor.show(); | ||||
|  | ||||
|         if (!this._disableUserList || this._verifyingUser) { | ||||
|             this._cancelButton = new St.Button({ style_class: 'modal-dialog-button', | ||||
|                                                  button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, | ||||
|                                                  reactive: true, | ||||
|                                                  can_focus: true, | ||||
|                                                  label: _("Cancel") }); | ||||
|             this._cancelButton.connect('clicked', | ||||
|                                        Lang.bind(this, function() { | ||||
|                                            this.cancel(); | ||||
|                                        })); | ||||
|             this._buttonBox.add(this._cancelButton, | ||||
|                                 { expand: false, | ||||
|                                   x_fill: false, | ||||
|                                   y_fill: false, | ||||
|                                   x_align: St.Align.START, | ||||
|                                   y_align: St.Align.END }); | ||||
|         } | ||||
|         this.buttonLayout.visible = true; | ||||
|         this.clearButtons(); | ||||
|  | ||||
|         this._buttonBox.add(this._defaultButtonWell, | ||||
|                             { expand: true, | ||||
|                               x_fill: false, | ||||
|                               y_fill: false, | ||||
|                               x_align: St.Align.END, | ||||
|                               y_align: St.Align.MIDDLE }); | ||||
|         this._signInButton = new St.Button({ style_class: 'modal-dialog-button', | ||||
|                                              button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, | ||||
|                                              reactive: true, | ||||
|                                              can_focus: true, | ||||
|                                              label: forSecret ? C_("button", "Sign In") : _("Next") }); | ||||
|         this._signInButton.connect('clicked', | ||||
|                                    Lang.bind(this, function() { | ||||
|                                        hold.release(); | ||||
|                                    })); | ||||
|         this._signInButton.add_style_pseudo_class('default'); | ||||
|         this._buttonBox.add(this._signInButton, | ||||
|                             { expand: false, | ||||
|                               x_fill: false, | ||||
|                               y_fill: false, | ||||
|                               x_align: St.Align.END, | ||||
|                               y_align: St.Align.END }); | ||||
|         if (!this._disableUserList || this._verifyingUser) | ||||
|             this.addButton({ action: Lang.bind(this, this.cancel), | ||||
|                              label: _("Cancel"), | ||||
|                              key: Clutter.Escape }, | ||||
|                            { expand: true, | ||||
|                              x_fill: false, | ||||
|                              y_fill: false, | ||||
|                              x_align: St.Align.START, | ||||
|                              y_align: St.Align.MIDDLE }); | ||||
|         this.buttonLayout.add(this._workSpinner.actor, | ||||
|                               { expand: false, | ||||
|                                 x_fill: false, | ||||
|                                 y_fill: false, | ||||
|                                 x_align: St.Align.END, | ||||
|                                 y_align: St.Align.MIDDLE }); | ||||
|         this._signInButton = this.addButton({ action: Lang.bind(this, function() { | ||||
|                                                           hold.release(); | ||||
|                                                       }), | ||||
|                                               label: forSecret ? C_("button", "Sign In") : _("Next"), | ||||
|                                               default: true }, | ||||
|                                             { expand: false, | ||||
|                                               x_fill: false, | ||||
|                                               y_fill: false, | ||||
|                                               x_align: St.Align.END, | ||||
|                                               y_align: St.Align.MIDDLE }); | ||||
|  | ||||
|         this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0); | ||||
|  | ||||
| @@ -860,7 +824,7 @@ const LoginDialog = new Lang.Class({ | ||||
|     _updateSensitivity: function(sensitive) { | ||||
|         this._promptEntry.reactive = sensitive; | ||||
|         this._promptEntry.clutter_text.editable = sensitive; | ||||
|         this._sessionMenuButton.updateSensitivity(sensitive); | ||||
|         this._sessionList.updateSensitivity(sensitive); | ||||
|         this._updateSignInButtonSensitivity(sensitive); | ||||
|     }, | ||||
|  | ||||
| @@ -872,6 +836,8 @@ const LoginDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _hidePrompt: function() { | ||||
|         this.setButtons([]); | ||||
|  | ||||
|         if (this._promptEntryTextChangedId > 0) { | ||||
|             this._promptEntry.clutter_text.disconnect(this._promptEntryTextChangedId); | ||||
|             this._promptEntryTextChangedId = 0; | ||||
| @@ -882,7 +848,7 @@ const LoginDialog = new Lang.Class({ | ||||
|             this._promptEntryActivateId = 0; | ||||
|         } | ||||
|  | ||||
|         this._setDefaultButtonWellMode(DefaultButtonWellMode.NONE, true); | ||||
|         this._setWorking(false); | ||||
|         this._promptBox.hide(); | ||||
|         this._promptLoginHint.hide(); | ||||
|  | ||||
| @@ -891,12 +857,38 @@ const LoginDialog = new Lang.Class({ | ||||
|         this._updateSensitivity(true); | ||||
|         this._promptEntry.set_text(''); | ||||
|  | ||||
|         this._sessionMenuButton.close(); | ||||
|         this._sessionList.close(); | ||||
|         this._promptLoginHint.hide(); | ||||
|  | ||||
|         this._buttonBox.remove_all_children(); | ||||
|         this.clearButtons(); | ||||
|         this._workSpinner = null; | ||||
|         this._signInButton = null; | ||||
|         this._cancelButton = null; | ||||
|     }, | ||||
|  | ||||
|     _setWorking: function(working) { | ||||
|         if (!this._workSpinner) | ||||
|             return; | ||||
|  | ||||
|         if (working) { | ||||
|             this._workSpinner.play(); | ||||
|             Tweener.addTween(this._workSpinner.actor, | ||||
|                              { opacity: 255, | ||||
|                                delay: WORK_SPINNER_ANIMATION_DELAY, | ||||
|                                time: WORK_SPINNER_ANIMATION_TIME, | ||||
|                                transition: 'linear' | ||||
|                              }); | ||||
|         } else { | ||||
|             Tweener.addTween(this._workSpinner.actor, | ||||
|                              { opacity: 0, | ||||
|                                time: WORK_SPINNER_ANIMATION_TIME, | ||||
|                                transition: 'linear', | ||||
|                                onCompleteScope: this, | ||||
|                                onComplete: function() { | ||||
|                                    if (this._workSpinner) | ||||
|                                        this._workSpinner.stop(); | ||||
|                                } | ||||
|                              }); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _askQuestion: function(verifier, serviceName, question, passwordChar) { | ||||
| @@ -913,7 +905,7 @@ const LoginDialog = new Lang.Class({ | ||||
|                      function() { | ||||
|                          let text = this._promptEntry.get_text(); | ||||
|                          this._updateSensitivity(false); | ||||
|                          this._setDefaultButtonWellMode(DefaultButtonWellMode.SPINNER, false); | ||||
|                          this._setWorking(true); | ||||
|                          this._userVerifier.answerQuery(serviceName, text); | ||||
|                      }]; | ||||
|  | ||||
| @@ -921,40 +913,17 @@ const LoginDialog = new Lang.Class({ | ||||
|         return batch.run(); | ||||
|     }, | ||||
|  | ||||
|     _showRealmLoginHint: function(realmManager, hint) { | ||||
|         if (!hint) | ||||
|             return; | ||||
|  | ||||
|         hint = hint.replace(/%U/g, 'user'); | ||||
|         hint = hint.replace(/%D/g, 'DOMAIN'); | ||||
|         hint = hint.replace(/%[^UD]/g, ''); | ||||
|  | ||||
|         // Translators: this message is shown below the username entry field | ||||
|         // to clue the user in on how to login to the local network realm | ||||
|         this._showLoginHint(null, _("(e.g., user or %s)").format(hint)); | ||||
|     }, | ||||
|  | ||||
|     _askForUsernameAndLogIn: function() { | ||||
|         this._promptLabel.set_text(_("Username: ")); | ||||
|         this._promptEntry.set_text(''); | ||||
|         this._promptEntry.clutter_text.set_password_char(''); | ||||
|  | ||||
|         let realmManager = new Realmd.Manager(); | ||||
|         let signalId = realmManager.connect('login-format-changed', | ||||
| 	                                        Lang.bind(this, this._showRealmLoginHint)); | ||||
|         this._showRealmLoginHint(realmManager.loginFormat); | ||||
|  | ||||
|         let tasks = [this._showPrompt, | ||||
|  | ||||
|                      function() { | ||||
|                          let userName = this._promptEntry.get_text(); | ||||
|                          this._promptEntry.reactive = false; | ||||
|                          return this._beginVerificationForUser(userName); | ||||
|                      }, | ||||
|  | ||||
|                      function() { | ||||
|                          realmManager.disconnect(signalId) | ||||
|                          realmManager.release(); | ||||
|                      }]; | ||||
|  | ||||
|         let batch = new Batch.ConsecutiveBatch(this, tasks); | ||||
| @@ -962,7 +931,7 @@ const LoginDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _startSession: function(serviceName) { | ||||
|         Tweener.addTween(this.actor, | ||||
|         Tweener.addTween(this.dialogLayout, | ||||
|                          { opacity: 0, | ||||
|                            time: _FADE_ANIMATION_TIME, | ||||
|                            transition: 'easeOutQuad', | ||||
| @@ -971,7 +940,7 @@ const LoginDialog = new Lang.Class({ | ||||
|  | ||||
|                                for (let i = 0; i < children.length; i++) { | ||||
|                                    if (children[i] != Main.layoutManager.screenShieldGroup) | ||||
|                                        children[i].opacity = this.actor.opacity; | ||||
|                                        children[i].opacity = this.dialogLayout.opacity; | ||||
|                                } | ||||
|                            }, | ||||
|                            onUpdateScope: this, | ||||
| @@ -1134,7 +1103,6 @@ const LoginDialog = new Lang.Class({ | ||||
|     _showUserList: function() { | ||||
|         this._hidePrompt(); | ||||
|         this._setUserListExpanded(true); | ||||
|         this._notListedButton.show(); | ||||
|         this._userList.actor.grab_key_focus(); | ||||
|     }, | ||||
|  | ||||
| @@ -1200,18 +1168,17 @@ const LoginDialog = new Lang.Class({ | ||||
|                                   })); | ||||
|     }, | ||||
|  | ||||
|     open: function() { | ||||
|         Main.ctrlAltTabManager.addGroup(this.actor, | ||||
|     _onOpened: function() { | ||||
|         Main.ctrlAltTabManager.addGroup(this.dialogLayout, | ||||
|                                         _("Login Window"), | ||||
|                                         'dialog-password-symbolic', | ||||
|                                         { sortGroup: CtrlAltTab.SortGroup.MIDDLE }); | ||||
|         this._userList.actor.grab_key_focus(); | ||||
|         this.actor.show(); | ||||
|  | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     close: function() { | ||||
|         this.parent(); | ||||
|  | ||||
|         Main.ctrlAltTabManager.removeGroup(this.dialogLayout); | ||||
|     }, | ||||
|  | ||||
| @@ -1219,4 +1186,3 @@ const LoginDialog = new Lang.Class({ | ||||
|         this._promptEntry.clutter_text.insert_unichar(unichar); | ||||
|     }, | ||||
| }); | ||||
| Signals.addSignalMethods(LoginDialog.prototype); | ||||
|   | ||||
| @@ -63,7 +63,7 @@ const Manager = new Lang.Class({ | ||||
|                                            Lang.bind(this, this._reloadRealms)) | ||||
|         this._realms = {}; | ||||
|  | ||||
|         this._signalId = this._aggregateProvider.connect('g-properties-changed', | ||||
|         this._aggregateProvider.connect('g-properties-changed', | ||||
|                                         Lang.bind(this, function(proxy, properties) { | ||||
|                                             if ('Realms' in properties.deep_unpack()) | ||||
|                                                 this._reloadRealms(); | ||||
| @@ -106,7 +106,7 @@ const Manager = new Lang.Class({ | ||||
|         realm.connect('g-properties-changed', | ||||
|                       Lang.bind(this, function(proxy, properties) { | ||||
|                                 if ('Configured' in properties.deep_unpack()) | ||||
|                                     this._reloadRealm(realm); | ||||
|                                     this._reloadRealm(); | ||||
|                                 })); | ||||
|     }, | ||||
|  | ||||
| @@ -134,18 +134,6 @@ const Manager = new Lang.Class({ | ||||
|         this._updateLoginFormat(); | ||||
|  | ||||
|         return this._loginFormat; | ||||
|     }, | ||||
|  | ||||
|     release: function() { | ||||
|         Service(Gio.DBus.system, | ||||
|                 'org.freedesktop.realmd', | ||||
|                 '/org/freedesktop/realmd', | ||||
|                 function(service) { | ||||
|                     service.ReleaseRemote(); | ||||
|                 }); | ||||
|         this._aggregateProvider.disconnect(this._signalId); | ||||
|         this._realms = { }; | ||||
|         this._updateLoginFormat(); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(Manager.prototype) | ||||
|   | ||||
| @@ -9,6 +9,7 @@ const Signals = imports.signals; | ||||
|  | ||||
| const Batch = imports.gdm.batch; | ||||
| const Fprint = imports.gdm.fingerprint; | ||||
| const Realmd = imports.gdm.realmd; | ||||
| const Main = imports.ui.main; | ||||
| const Params = imports.misc.params; | ||||
| const Tweener = imports.ui.tweener; | ||||
| @@ -116,6 +117,7 @@ const ShellUserVerifier = new Lang.Class({ | ||||
|         this._settings = new Gio.Settings({ schema: LOGIN_SCREEN_SCHEMA }); | ||||
|  | ||||
|         this._fprintManager = new Fprint.FprintManager(); | ||||
|         this._realmManager = new Realmd.Manager(); | ||||
|         this._messageQueue = []; | ||||
|         this._messageQueueTimeoutId = 0; | ||||
|         this.hasPendingMessages = false; | ||||
| @@ -164,7 +166,6 @@ const ShellUserVerifier = new Lang.Class({ | ||||
|  | ||||
|     answerQuery: function(serviceName, answer) { | ||||
|         if (!this._userVerifier.hasPendingMessages) { | ||||
|             this._clearMessageQueue(); | ||||
|             this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null); | ||||
|         } else { | ||||
|             let signalId = this._userVerifier.connect('no-more-messages', | ||||
| @@ -376,11 +377,30 @@ const ShellUserVerifier = new Lang.Class({ | ||||
|         this._queueMessage(problem, 'login-dialog-message-warning'); | ||||
|     }, | ||||
|  | ||||
|     _showRealmLoginHint: function() { | ||||
|         if (this._realmManager.loginFormat) { | ||||
|             let hint = this._realmManager.loginFormat; | ||||
|  | ||||
|             hint = hint.replace(/%U/g, 'user'); | ||||
|             hint = hint.replace(/%D/g, 'DOMAIN'); | ||||
|             hint = hint.replace(/%[^UD]/g, ''); | ||||
|  | ||||
|             // Translators: this message is shown below the username entry field | ||||
|             // to clue the user in on how to login to the local network realm | ||||
|             this.emit('show-login-hint', | ||||
|                       _("(e.g., user or %s)").format(hint)); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _onInfoQuery: function(client, serviceName, question) { | ||||
|         // We only expect questions to come from the main auth service | ||||
|         if (serviceName != PASSWORD_SERVICE_NAME) | ||||
|             return; | ||||
|  | ||||
|         this._showRealmLoginHint(); | ||||
|         this._realmLoginHintSignalId = this._realmManager.connect('login-format-changed', | ||||
|                                                                   Lang.bind(this, this._showRealmLoginHint)); | ||||
|  | ||||
|         this.emit('ask-question', serviceName, question, ''); | ||||
|     }, | ||||
|  | ||||
| @@ -456,6 +476,11 @@ const ShellUserVerifier = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         this.emit('hide-login-hint'); | ||||
|  | ||||
|         if (this._realmLoginHintSignalId) { | ||||
|             this._realmManager.disconnect(this._realmLoginHintSignalId); | ||||
|             this._realmLoginHintSignalId = 0; | ||||
|         } | ||||
|     }, | ||||
| }); | ||||
| Signals.addSignalMethods(ShellUserVerifier.prototype); | ||||
|   | ||||
| @@ -58,7 +58,6 @@ const Map = new Lang.Class({ | ||||
|  | ||||
|     _init: function(iterable) { | ||||
|         this._pool = { }; | ||||
|         this._size = 0; | ||||
|  | ||||
|         if (iterable) { | ||||
|             for (let i = 0; i < iterable.length; i++) { | ||||
| @@ -100,7 +99,6 @@ const Map = new Lang.Class({ | ||||
|             node.value = value; | ||||
|         } else { | ||||
|             this._pool[hash] = { key: key, value: value }; | ||||
|             this._size++; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -110,7 +108,6 @@ const Map = new Lang.Class({ | ||||
|  | ||||
|         if (node && _sameValue(node.key, key)) { | ||||
|             delete this._pool[hash]; | ||||
|             this._size--; | ||||
|             return [node.key, node.value]; | ||||
|         } else { | ||||
|             return [null, null]; | ||||
| @@ -139,6 +136,6 @@ const Map = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     size: function() { | ||||
|         return this._size; | ||||
|         return Object.getOwnPropertyNames(this._pool).length; | ||||
|     }, | ||||
| }); | ||||
|   | ||||
| @@ -18,7 +18,7 @@ const _urlRegexp = new RegExp( | ||||
|     '(^|' + _leadingJunk + ')' + | ||||
|     '(' + | ||||
|         '(?:' + | ||||
|             '(?:http|https|ftp)://' +             // scheme:// | ||||
|             '[a-z][\\w-]+://' +                   // scheme:// | ||||
|             '|' + | ||||
|             'www\\d{0,3}[.]' +                    // www. | ||||
|             '|' + | ||||
|   | ||||
| @@ -233,10 +233,8 @@ const AppSwitcherPopup = new Lang.Class({ | ||||
|  | ||||
|     _finish : function(timestamp) { | ||||
|         let appIcon = this._items[this._selectedIndex]; | ||||
|         if (this._currentWindow < 0) | ||||
|             appIcon.app.activate_window(appIcon.cachedWindows[0], timestamp); | ||||
|         else | ||||
|             Main.activateWindow(appIcon.cachedWindows[this._currentWindow], timestamp); | ||||
|         let window = this._currentWindow > 0 ? this._currentWindow : 0; | ||||
|         appIcon.app.activate_window(appIcon.cachedWindows[window], timestamp); | ||||
|  | ||||
|         this.parent(); | ||||
|     }, | ||||
|   | ||||
| @@ -1,84 +0,0 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const Lang = imports.lang; | ||||
| const Mainloop = imports.mainloop; | ||||
| const St = imports.gi.St; | ||||
| const Signals = imports.signals; | ||||
| const Atk = imports.gi.Atk; | ||||
|  | ||||
| const ANIMATED_ICON_UPDATE_TIMEOUT = 100; | ||||
|  | ||||
| const Animation = new Lang.Class({ | ||||
|     Name: 'Animation', | ||||
|  | ||||
|     _init: function(filename, width, height, speed) { | ||||
|         this.actor = new St.Bin(); | ||||
|         this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | ||||
|         this._speed = speed; | ||||
|  | ||||
|         this._isLoaded = false; | ||||
|         this._isPlaying = false; | ||||
|         this._timeoutId = 0; | ||||
|         this._frame = 0; | ||||
|         this._animations = St.TextureCache.get_default().load_sliced_image (filename, width, height, | ||||
|                                                                             Lang.bind(this, this._animationsLoaded)); | ||||
|         this.actor.set_child(this._animations); | ||||
|     }, | ||||
|  | ||||
|     play: function() { | ||||
|         if (this._isLoaded && this._timeoutId == 0) { | ||||
|             if (this._frame == 0) | ||||
|                 this._showFrame(0); | ||||
|  | ||||
|             this._timeoutId = Mainloop.timeout_add(this._speed, Lang.bind(this, this._update)); | ||||
|         } | ||||
|  | ||||
|         this._isPlaying = true; | ||||
|     }, | ||||
|  | ||||
|     stop: function() { | ||||
|         if (this._timeoutId > 0) { | ||||
|             Mainloop.source_remove(this._timeoutId); | ||||
|             this._timeoutId = 0; | ||||
|         } | ||||
|  | ||||
|         this._isPlaying = false; | ||||
|     }, | ||||
|  | ||||
|     _showFrame: function(frame) { | ||||
|         let oldFrameActor = this._animations.get_child_at_index(this._frame); | ||||
|         if (oldFrameActor) | ||||
|             oldFrameActor.hide(); | ||||
|  | ||||
|         this._frame = (frame % this._animations.get_n_children()); | ||||
|  | ||||
|         let newFrameActor = this._animations.get_child_at_index(this._frame); | ||||
|         if (newFrameActor) | ||||
|             newFrameActor.show(); | ||||
|     }, | ||||
|  | ||||
|     _update: function() { | ||||
|         this._showFrame(this._frame + 1); | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _animationsLoaded: function() { | ||||
|         this._isLoaded = true; | ||||
|  | ||||
|         if (this._isPlaying) | ||||
|             this.play(); | ||||
|     }, | ||||
|  | ||||
|     _onDestroy: function() { | ||||
|         this.stop(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const AnimatedIcon = new Lang.Class({ | ||||
|     Name: 'AnimatedIcon', | ||||
|     Extends: Animation, | ||||
|  | ||||
|     _init: function(filename, size) { | ||||
|         this.parent(filename, size, size, ANIMATED_ICON_UPDATE_TIMEOUT); | ||||
|     } | ||||
| }); | ||||
| @@ -187,9 +187,6 @@ const AllView = new Lang.Class({ | ||||
|     _init: function() { | ||||
|         this.parent(); | ||||
|  | ||||
|         this._grid.actor.y_align = Clutter.ActorAlign.START; | ||||
|         this._grid.actor.y_expand = true; | ||||
|  | ||||
|         let box = new St.BoxLayout({ vertical: true }); | ||||
|         this._stack = new St.Widget({ layout_manager: new AllViewLayout() }); | ||||
|         this._stack.add_actor(this._grid.actor); | ||||
| @@ -279,12 +276,8 @@ const AllView = new Lang.Class({ | ||||
|                 this._eventBlocker.reactive = isOpen; | ||||
|                 this._currentPopup = isOpen ? popup : null; | ||||
|                 this._updateIconOpacities(isOpen); | ||||
|                 if (isOpen) { | ||||
|                 if (isOpen) | ||||
|                     this._ensureIconVisible(popup.actor); | ||||
|                     this._grid.actor.y = popup.parentOffset; | ||||
|                 } else { | ||||
|                     this._grid.actor.y = 0; | ||||
|                 } | ||||
|             })); | ||||
|     }, | ||||
|  | ||||
| @@ -323,8 +316,6 @@ const FrequentView = new Lang.Class({ | ||||
|     loadApps: function() { | ||||
|         let mostUsed = this._usage.get_most_used (""); | ||||
|         for (let i = 0; i < mostUsed.length; i++) { | ||||
|             if (!mostUsed[i].get_app_info().should_show()) | ||||
|                 continue; | ||||
|             let appIcon = new AppIcon(mostUsed[i]); | ||||
|             this._grid.addItem(appIcon.actor, -1); | ||||
|         } | ||||
| @@ -336,42 +327,6 @@ const Views = { | ||||
|     ALL: 1 | ||||
| }; | ||||
|  | ||||
| const ControlsBoxLayout = Lang.Class({ | ||||
|     Name: 'ControlsBoxLayout', | ||||
|     Extends: Clutter.BoxLayout, | ||||
|  | ||||
|     /** | ||||
|      * Override the BoxLayout behavior to use the maximum preferred width of all | ||||
|      * buttons for each child | ||||
|      */ | ||||
|     vfunc_get_preferred_width: function(container, forHeight) { | ||||
|         let maxMinWidth = 0; | ||||
|         let maxNaturalWidth = 0; | ||||
|         for (let child = container.get_first_child(); | ||||
|              child; | ||||
|              child = child.get_next_sibling()) { | ||||
|              let [minWidth, natWidth] = child.get_preferred_width(forHeight); | ||||
|              maxMinWidth = Math.max(maxMinWidth, minWidth); | ||||
|              maxNaturalWidth = Math.max(maxNaturalWidth, natWidth); | ||||
|         } | ||||
|         let childrenCount = container.get_n_children(); | ||||
|         let totalSpacing = this.spacing * (childrenCount - 1); | ||||
|         return [maxMinWidth * childrenCount + totalSpacing, | ||||
|                 maxNaturalWidth * childrenCount + totalSpacing]; | ||||
|     }, | ||||
|  | ||||
|     vfunc_set_container: function(container) { | ||||
|         if(this._styleChangedId) { | ||||
|             this._container.disconnect(this._styleChangedId); | ||||
|             this._styleChangedId = 0; | ||||
|         } | ||||
|         if(container != null) | ||||
|             this._styleChangedId = container.connect('style-changed', Lang.bind(this, | ||||
|                     function() { this.spacing = this._container.get_theme_node().get_length('spacing'); })); | ||||
|         this._container = container; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const AppDisplay = new Lang.Class({ | ||||
|     Name: 'AppDisplay', | ||||
|  | ||||
| @@ -386,9 +341,6 @@ const AppDisplay = new Lang.Class({ | ||||
|         global.settings.connect('changed::app-folder-categories', Lang.bind(this, function() { | ||||
|             Main.queueDeferredWork(this._allAppsWorkId); | ||||
|         })); | ||||
|         this._privacySettings = new Gio.Settings({ schema: 'org.gnome.desktop.privacy' }); | ||||
|         this._privacySettings.connect('changed::remember-app-usage', | ||||
|                                       Lang.bind(this, this._updateFrequentVisibility)); | ||||
|  | ||||
|         this._views = []; | ||||
|  | ||||
| @@ -415,9 +367,9 @@ const AppDisplay = new Lang.Class({ | ||||
|                                           x_expand: true, y_expand: true }); | ||||
|         this.actor.add(this._viewStack, { expand: true }); | ||||
|  | ||||
|         let layout = new ControlsBoxLayout({ homogeneous: true }); | ||||
|         this._controls = new St.Widget({ style_class: 'app-view-controls' }); | ||||
|         this._controls.set_layout_manager(layout); | ||||
|         let layout = new Clutter.BoxLayout({ homogeneous: true }); | ||||
|         this._controls = new St.Widget({ style_class: 'app-view-controls', | ||||
|                                          layout_manager: layout }); | ||||
|         this.actor.add(new St.Bin({ child: this._controls })); | ||||
|  | ||||
|  | ||||
| @@ -432,7 +384,6 @@ const AppDisplay = new Lang.Class({ | ||||
|                 })); | ||||
|         } | ||||
|         this._showView(Views.FREQUENT); | ||||
|         this._updateFrequentVisibility(); | ||||
|  | ||||
|         // We need a dummy actor to catch the keyboard focus if the | ||||
|         // user Ctrl-Alt-Tabs here before the deferred work creates | ||||
| @@ -462,19 +413,6 @@ const AppDisplay = new Lang.Class({ | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _updateFrequentVisibility: function() { | ||||
|         let enabled = this._privacySettings.get_boolean('remember-app-usage'); | ||||
|         this._views[Views.FREQUENT].control.visible = enabled; | ||||
|  | ||||
|         let visibleViews = this._views.filter(function(v) { | ||||
|             return v.control.visible; | ||||
|         }); | ||||
|         this._controls.visible = visibleViews.length > 1; | ||||
|  | ||||
|         if (!enabled && this._views[Views.FREQUENT].view.actor.visible) | ||||
|             this._showView(Views.ALL); | ||||
|     }, | ||||
|  | ||||
|     _redisplay: function() { | ||||
|         this._redisplayFrequentApps(); | ||||
|         this._redisplayAllApps(); | ||||
| @@ -545,11 +483,11 @@ const AppSearchProvider = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     getInitialResultSet: function(terms) { | ||||
|         this.searchSystem.setResults(this, this._appSys.initial_search(terms)); | ||||
|         this.searchSystem.pushResults(this, this._appSys.initial_search(terms)); | ||||
|     }, | ||||
|  | ||||
|     getSubsearchResultSet: function(previousResults, terms) { | ||||
|         this.searchSystem.setResults(this, this._appSys.subsearch(previousResults, terms)); | ||||
|         this.searchSystem.pushResults(this, this._appSys.subsearch(previousResults, terms)); | ||||
|     }, | ||||
|  | ||||
|     activateResult: function(app) { | ||||
| @@ -634,11 +572,7 @@ const FolderIcon = new Lang.Class({ | ||||
|         // Position the popup above or below the source icon | ||||
|         if (side == St.Side.BOTTOM) { | ||||
|             this._popup.actor.show(); | ||||
|             let closeButtonOffset = -this._popup.closeButton.translation_y; | ||||
|             let y = this.actor.y - this._popup.actor.height; | ||||
|             let yWithButton = y - closeButtonOffset; | ||||
|             this._popup.parentOffset = yWithButton < 0 ? -yWithButton : 0; | ||||
|             this._popup.actor.y = Math.max(y, closeButtonOffset); | ||||
|             this._popup.actor.y = this.actor.y - this._popup.actor.height; | ||||
|             this._popup.actor.hide(); | ||||
|         } else { | ||||
|             this._popup.actor.y = this.actor.y + this.actor.height; | ||||
| @@ -661,7 +595,6 @@ const AppFolderPopup = new Lang.Class({ | ||||
|         this._arrowSide = side; | ||||
|  | ||||
|         this._isOpen = false; | ||||
|         this.parentOffset = 0; | ||||
|  | ||||
|         this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(), | ||||
|                                      visible: false, | ||||
| @@ -685,31 +618,17 @@ const AppFolderPopup = new Lang.Class({ | ||||
|         this.actor.add_actor(this._boxPointer.actor); | ||||
|         this._boxPointer.bin.set_child(this._view.actor); | ||||
|  | ||||
|         this.closeButton = Util.makeCloseButton(); | ||||
|         this.closeButton.connect('clicked', Lang.bind(this, this.popdown)); | ||||
|         this.actor.add_actor(this.closeButton); | ||||
|         let closeButton = Util.makeCloseButton(); | ||||
|         closeButton.connect('clicked', Lang.bind(this, this.popdown)); | ||||
|         this.actor.add_actor(closeButton); | ||||
|  | ||||
|         this._boxPointer.actor.bind_property('opacity', this.closeButton, 'opacity', | ||||
|         this._boxPointer.actor.bind_property('opacity', closeButton, 'opacity', | ||||
|                                              GObject.BindingFlags.SYNC_CREATE); | ||||
|  | ||||
|         global.focus_manager.add_group(this.actor); | ||||
|  | ||||
|         source.actor.connect('destroy', Lang.bind(this, | ||||
|             function() { | ||||
|                 this.actor.destroy(); | ||||
|             })); | ||||
|         this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPress)); | ||||
|     }, | ||||
|  | ||||
|     _onKeyPress: function(actor, event) { | ||||
|         if (!this._isOpen) | ||||
|             return false; | ||||
|  | ||||
|         if (event.get_key_symbol() != Clutter.KEY_Escape) | ||||
|             return false; | ||||
|  | ||||
|         this.popdown(); | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     toggle: function() { | ||||
| @@ -724,7 +643,6 @@ const AppFolderPopup = new Lang.Class({ | ||||
|             return; | ||||
|  | ||||
|         this.actor.show(); | ||||
|         this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); | ||||
|  | ||||
|         this._boxPointer.setArrowActor(this._source.actor); | ||||
|         this._boxPointer.show(BoxPointer.PopupAnimation.FADE | | ||||
|   | ||||
| @@ -126,11 +126,6 @@ const BackgroundCache = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     removeImageContent: function(content) { | ||||
|         let filename = content.get_filename(); | ||||
|  | ||||
|         if (filename && this._fileMonitors[filename]) | ||||
|             delete this._fileMonitors[filename]; | ||||
|  | ||||
|         this._removeContent(this._images, content); | ||||
|     }, | ||||
|  | ||||
| @@ -431,7 +426,7 @@ const Background = new Lang.Class({ | ||||
|         content.brightness = this._brightness; | ||||
|         content.vignette_sharpness = this._vignetteSharpness; | ||||
|  | ||||
|         this._cache.removeImageContent(this._images[index].content); | ||||
|         this._cache.removeImageContent(content); | ||||
|         this._images[index].content = content; | ||||
|         this._watchCacheFile(filename); | ||||
|     }, | ||||
| @@ -571,16 +566,7 @@ const Background = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         let uri = this._settings.get_string(PICTURE_URI_KEY); | ||||
|         let filename; | ||||
|         if (GLib.uri_parse_scheme(uri) != null) | ||||
|             filename = Gio.File.new_for_uri(uri).get_path(); | ||||
|         else | ||||
|             filename = uri; | ||||
|  | ||||
|         if (!filename) { | ||||
|             this._setLoaded(); | ||||
|             return; | ||||
|         } | ||||
|         let filename = Gio.File.new_for_uri(uri).get_path(); | ||||
|  | ||||
|         this._loadFile(filename); | ||||
|     }, | ||||
| @@ -756,15 +742,11 @@ const BackgroundManager = new Lang.Class({ | ||||
|                                    time: FADE_ANIMATION_TIME, | ||||
|                                    transition: 'easeOutQuad', | ||||
|                                    onComplete: Lang.bind(this, function() { | ||||
|                                        if (this._newBackground == newBackground) { | ||||
|                                        if (this.background == background) { | ||||
|                                            this.background = newBackground; | ||||
|                                            this._newBackground = null; | ||||
|                                        } else { | ||||
|                                            newBackground.actor.destroy(); | ||||
|                                            background.actor.destroy(); | ||||
|                                        } | ||||
|  | ||||
|                                        background.actor.destroy(); | ||||
|  | ||||
|                                        this.emit('changed'); | ||||
|                                    }) | ||||
|                                  }); | ||||
|   | ||||
| @@ -46,10 +46,8 @@ function addBackgroundMenu(actor) { | ||||
|     clickAction.connect('long-press', function(action, actor, state) { | ||||
|         if (state == Clutter.LongPressState.QUERY) | ||||
|             return action.get_button() == 1 && !actor._backgroundMenu.isOpen; | ||||
|         if (state == Clutter.LongPressState.ACTIVATE) { | ||||
|         if (state == Clutter.LongPressState.ACTIVATE) | ||||
|             openMenu(); | ||||
|             actor._backgroundManager.ignoreRelease(); | ||||
|         } | ||||
|         return true; | ||||
|     }); | ||||
|     clickAction.connect('clicked', function(action) { | ||||
| @@ -62,7 +60,5 @@ function addBackgroundMenu(actor) { | ||||
|                       actor._backgroundMenu.destroy(); | ||||
|                       actor._backgroundMenu = null; | ||||
|                       actor._backgroundManager = null; | ||||
|  | ||||
|                       cursor.destroy(); | ||||
|                   }); | ||||
| } | ||||
|   | ||||
| @@ -589,12 +589,12 @@ const BoxPointer = new Lang.Class({ | ||||
|                 return St.Side.TOP; | ||||
|             break; | ||||
|         case St.Side.LEFT: | ||||
|             if (sourceAllocation.x2 + boxWidth > monitor.x + monitor.width && | ||||
|             if (sourceAllocation.y2 + boxWidth > monitor.x + monitor.width && | ||||
|                 boxWidth < sourceAllocation.x1 - monitor.x) | ||||
|                 return St.Side.RIGHT; | ||||
|             break; | ||||
|         case St.Side.RIGHT: | ||||
|             if (sourceAllocation.x1 - boxWidth < monitor.x && | ||||
|             if (sourceAllocation.y1 - boxWidth < monitor.x && | ||||
|                 boxWidth < monitor.x + monitor.width - sourceAllocation.x2) | ||||
|                 return St.Side.LEFT; | ||||
|             break; | ||||
|   | ||||
| @@ -443,18 +443,16 @@ const Calendar = new Lang.Class({ | ||||
|         this.actor.add(this._topBox, | ||||
|                        { row: 0, col: 0, col_span: offsetCols + 7 }); | ||||
|  | ||||
|         this._backButton = new St.Button({ style_class: 'calendar-change-month-back', | ||||
|                                            can_focus: true }); | ||||
|         this._topBox.add(this._backButton); | ||||
|         this._backButton.connect('clicked', Lang.bind(this, this._onPrevMonthButtonClicked)); | ||||
|         let back = new St.Button({ style_class: 'calendar-change-month-back' }); | ||||
|         this._topBox.add(back); | ||||
|         back.connect('clicked', Lang.bind(this, this._onPrevMonthButtonClicked)); | ||||
|  | ||||
|         this._monthLabel = new St.Label({style_class: 'calendar-month-label'}); | ||||
|         this._topBox.add(this._monthLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE }); | ||||
|  | ||||
|         this._forwardButton = new St.Button({ style_class: 'calendar-change-month-forward', | ||||
|                                               can_focus: true }); | ||||
|         this._topBox.add(this._forwardButton); | ||||
|         this._forwardButton.connect('clicked', Lang.bind(this, this._onNextMonthButtonClicked)); | ||||
|         let forward = new St.Button({ style_class: 'calendar-change-month-forward' }); | ||||
|         this._topBox.add(forward); | ||||
|         forward.connect('clicked', Lang.bind(this, this._onNextMonthButtonClicked)); | ||||
|  | ||||
|         // Add weekday labels... | ||||
|         // | ||||
| @@ -513,12 +511,10 @@ const Calendar = new Lang.Class({ | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this._backButton.grab_key_focus(); | ||||
|  | ||||
|         this.setDate(newDate, false); | ||||
|     }, | ||||
|    }, | ||||
|  | ||||
|     _onNextMonthButtonClicked: function() { | ||||
|    _onNextMonthButtonClicked: function() { | ||||
|         let newDate = new Date(this._selectedDate); | ||||
|         let oldMonth = newDate.getMonth(); | ||||
|         if (oldMonth == 11) { | ||||
| @@ -537,9 +533,7 @@ const Calendar = new Lang.Class({ | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this._forwardButton.grab_key_focus(); | ||||
|  | ||||
|         this.setDate(newDate, false); | ||||
|        this.setDate(newDate, false); | ||||
|     }, | ||||
|  | ||||
|     _onSettingsChange: function() { | ||||
| @@ -596,8 +590,7 @@ const Calendar = new Lang.Class({ | ||||
|         // nRows here means 6 weeks + one header + one navbar | ||||
|         let nRows = 8; | ||||
|         while (row < 8) { | ||||
|             let button = new St.Button({ label: iter.getDate().toString(), | ||||
|                                          can_focus: true }); | ||||
|             let button = new St.Button({ label: iter.getDate().toString() }); | ||||
|             let rtl = button.get_text_direction() == Clutter.TextDirection.RTL; | ||||
|  | ||||
|             if (this._eventSource.isDummy) | ||||
| @@ -605,12 +598,8 @@ const Calendar = new Lang.Class({ | ||||
|  | ||||
|             let iterStr = iter.toUTCString(); | ||||
|             button.connect('clicked', Lang.bind(this, function() { | ||||
|                 this._shouldDateGrabFocus = true; | ||||
|  | ||||
|                 let newlySelectedDate = new Date(iterStr); | ||||
|                 this.setDate(newlySelectedDate, false); | ||||
|  | ||||
|                 this._shouldDateGrabFocus = false; | ||||
|             })); | ||||
|  | ||||
|             let hasEvents = this._eventSource.hasEvents(iter); | ||||
| @@ -635,6 +624,9 @@ const Calendar = new Lang.Class({ | ||||
|             else if (iter.getMonth() != this._selectedDate.getMonth()) | ||||
|                 styleClass += ' calendar-other-month-day'; | ||||
|  | ||||
|             if (_sameDay(this._selectedDate, iter)) | ||||
|                 button.add_style_pseudo_class('active'); | ||||
|  | ||||
|             if (hasEvents) | ||||
|                 styleClass += ' calendar-day-with-events' | ||||
|  | ||||
| @@ -644,13 +636,6 @@ const Calendar = new Lang.Class({ | ||||
|             this.actor.add(button, | ||||
|                            { row: row, col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7 }); | ||||
|  | ||||
|             if (_sameDay(this._selectedDate, iter)) { | ||||
|                 button.add_style_pseudo_class('active'); | ||||
|  | ||||
|                 if (this._shouldDateGrabFocus) | ||||
|                     button.grab_key_focus(); | ||||
|             } | ||||
|  | ||||
|             if (this._useWeekdate && iter.getDay() == 4) { | ||||
|                 let label = new St.Label({ text: _getCalendarWeekForDate(iter).toString(), | ||||
|                                            style_class: 'calendar-day-base calendar-week-number'}); | ||||
| @@ -675,7 +660,7 @@ const EventsList = new Lang.Class({ | ||||
|     Name: 'EventsList', | ||||
|  | ||||
|     _init: function() { | ||||
|         this.actor = new St.Table({ style_class: 'events-table' }); | ||||
|         this.actor = new St.BoxLayout({ vertical: true, style_class: 'events-header-vbox'}); | ||||
|         this._date = new Date(); | ||||
|         this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' }); | ||||
|         this._desktopSettings.connect('changed', Lang.bind(this, this._update)); | ||||
| @@ -687,72 +672,55 @@ const EventsList = new Lang.Class({ | ||||
|         this._eventSource.connect('changed', Lang.bind(this, this._update)); | ||||
|     }, | ||||
|  | ||||
|     _addEvent: function(event, index, includeDayName) { | ||||
|         let dayString; | ||||
|         if (includeDayName) | ||||
|             dayString = _getEventDayAbbreviation(event.date.getDay()); | ||||
|         else | ||||
|             dayString = ''; | ||||
|  | ||||
|         let dayLabel = new St.Label({ style_class: 'events-day-dayname', | ||||
|                                       text: dayString }); | ||||
|         dayLabel.clutter_text.line_wrap = false; | ||||
|         dayLabel.clutter_text.ellipsize = false; | ||||
|  | ||||
|         this.actor.add(dayLabel, { row: index, col: 0, | ||||
|                                    x_expand: false, x_align: St.Align.END, | ||||
|                                    y_fill: false, y_align: St.Align.START }); | ||||
|  | ||||
|         let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY); | ||||
|         let timeString = _formatEventTime(event, clockFormat); | ||||
|         let timeLabel = new St.Label({ style_class: 'events-day-time', | ||||
|                                        text: timeString }); | ||||
|         timeLabel.clutter_text.line_wrap = false; | ||||
|         timeLabel.clutter_text.ellipsize = false; | ||||
|  | ||||
|         this.actor.add(timeLabel, { row: index, col: 1, | ||||
|                                     x_expand: false, x_align: St.Align.MIDDLE, | ||||
|                                     y_fill: false, y_align: St.Align.START }); | ||||
|  | ||||
|         let titleLabel = new St.Label({ style_class: 'events-day-task', | ||||
|                                         text: event.summary }); | ||||
|         titleLabel.clutter_text.line_wrap = true; | ||||
|         titleLabel.clutter_text.ellipsize = false; | ||||
|  | ||||
|         this.actor.add(titleLabel, { row: index, col: 2, | ||||
|                                      x_expand: true, x_align: St.Align.START, | ||||
|                                      y_fill: false, y_align: St.Align.START }); | ||||
|     _addEvent: function(dayNameBox, timeBox, eventTitleBox, includeDayName, day, time, desc) { | ||||
|         if (includeDayName) { | ||||
|             dayNameBox.add(new St.Label( { style_class: 'events-day-dayname', | ||||
|                                            text: day } ), | ||||
|                            { x_fill: true } ); | ||||
|         } | ||||
|         timeBox.add(new St.Label( { style_class: 'events-day-time', | ||||
|                                     text: time} ), | ||||
|                     { x_fill: true } ); | ||||
|         eventTitleBox.add(new St.Label( { style_class: 'events-day-task', | ||||
|                                           text: desc} )); | ||||
|     }, | ||||
|  | ||||
|     _addPeriod: function(header, index, begin, end, includeDayName, showNothingScheduled) { | ||||
|     _addPeriod: function(header, begin, end, includeDayName, showNothingScheduled) { | ||||
|         let events = this._eventSource.getEvents(begin, end); | ||||
|  | ||||
|         if (events.length == 0 && !showNothingScheduled) | ||||
|             return index; | ||||
|         let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);; | ||||
|  | ||||
|         this.actor.add(new St.Label({ style_class: 'events-day-header', text: header }), | ||||
|                        { row: index, col: 0, col_span: 3, | ||||
|                          // In theory, x_expand should be true here, but x_expand | ||||
|                          // is a property of the column for StTable, ie all day cells | ||||
|                          // get it too | ||||
|                          x_expand: false, x_align: St.Align.START, | ||||
|                          y_fill: false, y_align: St.Align.START }); | ||||
|         index++; | ||||
|         if (events.length == 0 && !showNothingScheduled) | ||||
|             return; | ||||
|  | ||||
|         let vbox = new St.BoxLayout( {vertical: true} ); | ||||
|         this.actor.add(vbox); | ||||
|  | ||||
|         vbox.add(new St.Label({ style_class: 'events-day-header', text: header })); | ||||
|         let box = new St.BoxLayout({style_class: 'events-header-hbox'}); | ||||
|         let dayNameBox = new St.BoxLayout({ vertical: true, style_class: 'events-day-name-box' }); | ||||
|         let timeBox = new St.BoxLayout({ vertical: true, style_class: 'events-time-box' }); | ||||
|         let eventTitleBox = new St.BoxLayout({ vertical: true, style_class: 'events-event-box' }); | ||||
|         box.add(dayNameBox, {x_fill: false}); | ||||
|         box.add(timeBox, {x_fill: false}); | ||||
|         box.add(eventTitleBox, {expand: true}); | ||||
|         vbox.add(box); | ||||
|  | ||||
|         for (let n = 0; n < events.length; n++) { | ||||
|             this._addEvent(events[n], index, includeDayName); | ||||
|             index++; | ||||
|             let event = events[n]; | ||||
|             let dayString = _getEventDayAbbreviation(event.date.getDay()); | ||||
|             let timeString = _formatEventTime(event, clockFormat); | ||||
|             let summaryString = event.summary; | ||||
|             this._addEvent(dayNameBox, timeBox, eventTitleBox, includeDayName, dayString, timeString, summaryString); | ||||
|         } | ||||
|  | ||||
|         if (events.length == 0 && showNothingScheduled) { | ||||
|             let now = new Date(); | ||||
|             /* Translators: Text to show if there are no events */ | ||||
|             let nothingEvent = new CalendarEvent(now, now, _("Nothing Scheduled"), true); | ||||
|             this._addEvent(nothingEvent, index, false); | ||||
|             index++; | ||||
|             let timeString = _formatEventTime(nothingEvent, clockFormat); | ||||
|             this._addEvent(dayNameBox, timeBox, eventTitleBox, false, "", timeString, nothingEvent.summary); | ||||
|         } | ||||
|  | ||||
|         return index; | ||||
|     }, | ||||
|  | ||||
|     _showOtherDay: function(day) { | ||||
| @@ -769,21 +737,20 @@ const EventsList = new Lang.Class({ | ||||
|         else | ||||
|             /* Translators: Shown on calendar heading when selected day occurs on different year */ | ||||
|             dayString = day.toLocaleFormat(C_("calendar heading", "%A, %B %d, %Y")); | ||||
|         this._addPeriod(dayString, 0, dayBegin, dayEnd, false, true); | ||||
|         this._addPeriod(dayString, dayBegin, dayEnd, false, true); | ||||
|     }, | ||||
|  | ||||
|     _showToday: function() { | ||||
|         this.actor.destroy_all_children(); | ||||
|         let index = 0; | ||||
|  | ||||
|         let now = new Date(); | ||||
|         let dayBegin = _getBeginningOfDay(now); | ||||
|         let dayEnd = _getEndOfDay(now); | ||||
|         index = this._addPeriod(_("Today"), index, dayBegin, dayEnd, false, true); | ||||
|         this._addPeriod(_("Today"), dayBegin, dayEnd, false, true); | ||||
|  | ||||
|         let tomorrowBegin = new Date(dayBegin.getTime() + 86400 * 1000); | ||||
|         let tomorrowEnd = new Date(dayEnd.getTime() + 86400 * 1000); | ||||
|         index = this._addPeriod(_("Tomorrow"), index, tomorrowBegin, tomorrowEnd, false, true); | ||||
|         this._addPeriod(_("Tomorrow"), tomorrowBegin, tomorrowEnd, false, true); | ||||
|  | ||||
|         let dayInWeek = (dayEnd.getDay() - this._weekStart + 7) % 7; | ||||
|  | ||||
| @@ -794,7 +761,7 @@ const EventsList = new Lang.Class({ | ||||
|              */ | ||||
|             let thisWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000); | ||||
|             let thisWeekEnd = new Date(dayEnd.getTime() + (6 - dayInWeek) * 86400 * 1000); | ||||
|             index = this._addPeriod(_("This week"), index, thisWeekBegin, thisWeekEnd, true, false); | ||||
|             this._addPeriod(_("This week"), thisWeekBegin, thisWeekEnd, true, false); | ||||
|         } else { | ||||
|             /* otherwise it's one of the two last days of the week ... show | ||||
|              * "Next week" and include events up until and including *next* | ||||
| @@ -802,7 +769,7 @@ const EventsList = new Lang.Class({ | ||||
|              */ | ||||
|             let nextWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000); | ||||
|             let nextWeekEnd = new Date(dayEnd.getTime() + (13 - dayInWeek) * 86400 * 1000); | ||||
|             index = this._addPeriod(_("Next week"), index, nextWeekBegin, nextWeekEnd, true, false); | ||||
|             this._addPeriod(_("Next week"), nextWeekBegin, nextWeekEnd, true, false); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|   | ||||
| @@ -31,7 +31,7 @@ function shouldAutorunMount(mount, forTransient) { | ||||
|     if (!volume || (!volume.allowAutorun && forTransient)) | ||||
|         return false; | ||||
|  | ||||
|     if (root.is_native() && isMountRootHidden(root)) | ||||
|     if (!root.is_native() || isMountRootHidden(root)) | ||||
|         return false; | ||||
|  | ||||
|     return true; | ||||
|   | ||||
| @@ -25,7 +25,7 @@ const KeyringDialog = new Lang.Class({ | ||||
|         this.prompt = new Shell.KeyringPrompt(); | ||||
|         this.prompt.connect('show-password', Lang.bind(this, this._onShowPassword)); | ||||
|         this.prompt.connect('show-confirm', Lang.bind(this, this._onShowConfirm)); | ||||
|         this.prompt.connect('prompt-close', Lang.bind(this, this._onHidePrompt)); | ||||
|         this.prompt.connect('hide-prompt', Lang.bind(this, this._onHidePrompt)); | ||||
|  | ||||
|         let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout', | ||||
|                                                 vertical: false }); | ||||
| @@ -63,17 +63,11 @@ const KeyringDialog = new Lang.Class({ | ||||
|  | ||||
|         this._cancelButton = this.addButton({ label: '', | ||||
|                                               action: Lang.bind(this, this._onCancelButton), | ||||
|                                               key: Clutter.Escape }, | ||||
|                                             { expand: true, x_fill: false, x_align: St.Align.START }); | ||||
|         this.placeSpinner({ expand: false, | ||||
|                             x_fill: false, | ||||
|                             y_fill: false, | ||||
|                             x_align: St.Align.END, | ||||
|                             y_align: St.Align.MIDDLE }); | ||||
|                                               key: Clutter.Escape }); | ||||
|         this._continueButton = this.addButton({ label: '', | ||||
|                                                 action: Lang.bind(this, this._onContinueButton), | ||||
|                                                 default: true }, | ||||
|                                               { expand: false, x_fill: false, x_align: St.Align.END }); | ||||
|                                               { expand: true, x_fill: false, x_align: St.Align.END }); | ||||
|  | ||||
|         this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE); | ||||
|         this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE); | ||||
| @@ -149,19 +143,11 @@ const KeyringDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _updateSensitivity: function(sensitive) { | ||||
|         if (this._passwordEntry) { | ||||
|             this._passwordEntry.reactive = sensitive; | ||||
|             this._passwordEntry.clutter_text.editable = sensitive; | ||||
|         } | ||||
|  | ||||
|         if (this._confirmEntry) { | ||||
|             this._confirmEntry.reactive = sensitive; | ||||
|             this._confirmEntry.clutter_text.editable = sensitive; | ||||
|         } | ||||
|         this._passwordEntry.reactive = sensitive; | ||||
|         this._passwordEntry.clutter_text.editable = sensitive; | ||||
|  | ||||
|         this._continueButton.can_focus = sensitive; | ||||
|         this._continueButton.reactive = sensitive; | ||||
|         this.setWorking(!sensitive); | ||||
|     }, | ||||
|  | ||||
|     _ensureOpen: function() { | ||||
|   | ||||
| @@ -16,7 +16,7 @@ const PolkitAgent = imports.gi.PolkitAgent; | ||||
| const Components = imports.ui.components; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
| const ShellEntry = imports.ui.shellEntry; | ||||
| const UserWidget = imports.ui.userWidget; | ||||
| const UserMenu = imports.ui.userMenu; | ||||
|  | ||||
| const DIALOG_ICON_SIZE = 48; | ||||
|  | ||||
| @@ -31,6 +31,7 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|         this.message = message; | ||||
|         this.userNames = userNames; | ||||
|         this._wasDismissed = false; | ||||
|         this._completed = false; | ||||
|  | ||||
|         let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout', | ||||
|                                                 vertical: false }); | ||||
| @@ -100,9 +101,9 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|             let userBox = new St.BoxLayout({ style_class: 'polkit-dialog-user-layout', | ||||
|                                              vertical: false }); | ||||
|             messageBox.add(userBox); | ||||
|             this._userAvatar = new UserWidget.Avatar(this._user, | ||||
|                                                      { iconSize: DIALOG_ICON_SIZE, | ||||
|                                                        styleClass: 'polkit-dialog-user-icon' }); | ||||
|             this._userAvatar = new UserMenu.UserAvatarWidget(this._user, | ||||
|                                                              { iconSize: DIALOG_ICON_SIZE, | ||||
|                                                                styleClass: 'polkit-dialog-user-icon' }); | ||||
|             this._userAvatar.actor.hide(); | ||||
|             userBox.add(this._userAvatar.actor, | ||||
|                         { x_fill:  true, | ||||
| @@ -160,32 +161,26 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|  | ||||
|         this._cancelButton = this.addButton({ label: _("Cancel"), | ||||
|                                               action: Lang.bind(this, this.cancel), | ||||
|                                               key: Clutter.Escape }, | ||||
|                                             { expand: true, x_fill: false, x_align: St.Align.START }); | ||||
|         this.placeSpinner({ expand: false, | ||||
|                             x_fill: false, | ||||
|                             y_fill: false, | ||||
|                             x_align: St.Align.END, | ||||
|                             y_align: St.Align.MIDDLE }); | ||||
|                                               key: Clutter.Escape }); | ||||
|         this._okButton = this.addButton({ label:  _("Authenticate"), | ||||
|                                           action: Lang.bind(this, this._onAuthenticateButtonPressed), | ||||
|                                           default: true }, | ||||
|                                         { expand: false, x_fill: false, x_align: St.Align.END }); | ||||
|                                         { expand: true, x_fill: false, x_align: St.Align.END }); | ||||
|  | ||||
|         this._doneEmitted = false; | ||||
|  | ||||
|         this._identityToAuth = Polkit.UnixUser.new_for_name(userName); | ||||
|         this._cookie = cookie; | ||||
|     }, | ||||
|  | ||||
|     performAuthentication: function() { | ||||
|         this.destroySession(); | ||||
|         this._session = new PolkitAgent.Session({ identity: this._identityToAuth, | ||||
|                                                   cookie: this._cookie }); | ||||
|         this._session.connect('completed', Lang.bind(this, this._onSessionCompleted)); | ||||
|         this._session.connect('request', Lang.bind(this, this._onSessionRequest)); | ||||
|         this._session.connect('show-error', Lang.bind(this, this._onSessionShowError)); | ||||
|         this._session.connect('show-info', Lang.bind(this, this._onSessionShowInfo)); | ||||
|     }, | ||||
|  | ||||
|     startAuthentication: function() { | ||||
|         this._session.initiate(); | ||||
|     }, | ||||
|  | ||||
| @@ -207,14 +202,14 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|             log('polkitAuthenticationAgent: Failed to show modal dialog.' + | ||||
|                 ' Dismissing authentication request for action-id ' + this.actionId + | ||||
|                 ' cookie ' + this._cookie); | ||||
|             this._emitDone(true); | ||||
|             this._emitDone(false, true); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _emitDone: function(dismissed) { | ||||
|     _emitDone: function(keepVisible, dismissed) { | ||||
|         if (!this._doneEmitted) { | ||||
|             this._doneEmitted = true; | ||||
|             this.emit('done', dismissed); | ||||
|             this.emit('done', keepVisible, dismissed); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -224,7 +219,6 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|  | ||||
|         this._okButton.can_focus = sensitive; | ||||
|         this._okButton.reactive = sensitive; | ||||
|         this.setWorking(!sensitive); | ||||
|     }, | ||||
|  | ||||
|     _onEntryActivate: function() { | ||||
| @@ -243,16 +237,12 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _onSessionCompleted: function(session, gainedAuthorization) { | ||||
|         if (this._completed || this._doneEmitted) | ||||
|         if (this._completed) | ||||
|             return; | ||||
|  | ||||
|         this._completed = true; | ||||
|  | ||||
|         /* Yay, all done */ | ||||
|         if (gainedAuthorization) { | ||||
|             this._emitDone(false); | ||||
|  | ||||
|         } else { | ||||
|         if (!gainedAuthorization) { | ||||
|             /* Unless we are showing an existing error message from the PAM | ||||
|              * module (the PAM module could be reporting the authentication | ||||
|              * error providing authentication-method specific information), | ||||
| @@ -268,10 +258,8 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|                 this._infoMessageLabel.hide(); | ||||
|                 this._nullMessageLabel.hide(); | ||||
|             } | ||||
|  | ||||
|             /* Try and authenticate again */ | ||||
|             this.performAuthentication(); | ||||
|         } | ||||
|         this._emitDone(!gainedAuthorization, false); | ||||
|     }, | ||||
|  | ||||
|     _onSessionRequest: function(session, request, echo_on) { | ||||
| @@ -315,7 +303,6 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|         if (this._session) { | ||||
|             if (!this._completed) | ||||
|                 this._session.cancel(); | ||||
|             this._completed = false; | ||||
|             this._session = null; | ||||
|         } | ||||
|     }, | ||||
| @@ -330,7 +317,7 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|     cancel: function() { | ||||
|         this._wasDismissed = true; | ||||
|         this.close(global.get_current_time()); | ||||
|         this._emitDone(true); | ||||
|         this._emitDone(false, true); | ||||
|     }, | ||||
| }); | ||||
| Signals.addSignalMethods(AuthenticationDialog.prototype); | ||||
| @@ -340,6 +327,7 @@ const AuthenticationAgent = new Lang.Class({ | ||||
|  | ||||
|     _init: function() { | ||||
|         this._currentDialog = null; | ||||
|         this._isCompleting = false; | ||||
|         this._handle = null; | ||||
|         this._native = new Shell.PolkitAuthenticationAgent(); | ||||
|         this._native.connect('initiate', Lang.bind(this, this._onInitiate)); | ||||
| @@ -376,24 +364,45 @@ const AuthenticationAgent = new Lang.Class({ | ||||
|         // discussion. | ||||
|  | ||||
|         this._currentDialog.connect('done', Lang.bind(this, this._onDialogDone)); | ||||
|         this._currentDialog.performAuthentication(); | ||||
|         this._currentDialog.startAuthentication(); | ||||
|     }, | ||||
|  | ||||
|     _onCancel: function(nativeAgent) { | ||||
|         this._completeRequest(false); | ||||
|         this._completeRequest(false, false); | ||||
|     }, | ||||
|  | ||||
|     _onDialogDone: function(dialog, dismissed) { | ||||
|         this._completeRequest(dismissed); | ||||
|     _onDialogDone: function(dialog, keepVisible, dismissed) { | ||||
|         this._completeRequest(keepVisible, dismissed); | ||||
|     }, | ||||
|  | ||||
|     _completeRequest: function(dismissed) { | ||||
|     _reallyCompleteRequest: function(dismissed) { | ||||
|         this._currentDialog.close(); | ||||
|         this._currentDialog.destroySession(); | ||||
|         this._currentDialog = null; | ||||
|         this._isCompleting = false; | ||||
|  | ||||
|         this._native.complete(dismissed); | ||||
|         this._native.complete(dismissed) | ||||
|     }, | ||||
|  | ||||
|     _completeRequest: function(keepVisible, wasDismissed) { | ||||
|         if (this._isCompleting) | ||||
|             return; | ||||
|  | ||||
|         this._isCompleting = true; | ||||
|  | ||||
|         if (keepVisible) { | ||||
|             // Give the user 2 seconds to read 'Authentication Failure' before | ||||
|             // dismissing the dialog | ||||
|             Mainloop.timeout_add(2000, | ||||
|                                  Lang.bind(this, | ||||
|                                            function() { | ||||
|                                                this._reallyCompleteRequest(wasDismissed); | ||||
|                                                return false; | ||||
|                                            })); | ||||
|         } else { | ||||
|             this._reallyCompleteRequest(wasDismissed); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const Component = AuthenticationAgent; | ||||
|   | ||||
| @@ -20,7 +20,8 @@ const Recorder = new Lang.Class({ | ||||
|         Main.wm.addKeybinding('toggle-recording', | ||||
|                               this._bindingSettings, | ||||
|                               Meta.KeyBindingFlags.NONE, | ||||
|                               Shell.KeyBindingMode.ALL, | ||||
|                               Shell.KeyBindingMode.NORMAL | | ||||
|                               Shell.KeyBindingMode.OVERVIEW, | ||||
|                               Lang.bind(this, this._toggleRecorder)); | ||||
|     }, | ||||
|  | ||||
|   | ||||
| @@ -18,7 +18,7 @@ const Params = imports.misc.params; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
|  | ||||
| // See Notification.appendMessage | ||||
| const SCROLLBACK_IMMEDIATE_TIME = 3 * 60; // 3 minutes | ||||
| const SCROLLBACK_IMMEDIATE_TIME = 60; // 1 minute | ||||
| const SCROLLBACK_RECENT_TIME = 15 * 60; // 15 minutes | ||||
| const SCROLLBACK_RECENT_LENGTH = 20; | ||||
| const SCROLLBACK_IDLE_LENGTH = 5; | ||||
| @@ -967,8 +967,7 @@ const ChatNotification = new Lang.Class({ | ||||
|         let timeLabel = this._append({ body: this._formatTimestamp(lastMessageDate), | ||||
|                                        group: 'meta', | ||||
|                                        styles: ['chat-meta-message'], | ||||
|                                        childProps: { expand: true, x_fill: false, | ||||
|                                                      x_align: St.Align.END }, | ||||
|                                        childProps: { expand: true, x_fill: false }, | ||||
|                                        noTimestamp: true, | ||||
|                                        timestamp: lastMessageTime }); | ||||
|  | ||||
|   | ||||
| @@ -61,7 +61,8 @@ const CtrlAltTabManager = new Lang.Class({ | ||||
|         if (item.focusCallback) { | ||||
|             item.focusCallback(timestamp); | ||||
|         } else { | ||||
|             if (global.stage_input_mode == Shell.StageInputMode.NORMAL) | ||||
|             if (global.stage_input_mode == Shell.StageInputMode.NONREACTIVE || | ||||
|                 global.stage_input_mode == Shell.StageInputMode.NORMAL) | ||||
|                 global.set_stage_input_mode(Shell.StageInputMode.FOCUSED); | ||||
|  | ||||
|             item.root.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); | ||||
| @@ -88,25 +89,19 @@ const CtrlAltTabManager = new Lang.Class({ | ||||
|         let items = this._items.filter(function (item) { return item.proxy.mapped; }); | ||||
|  | ||||
|         // And add the windows metacity would show in its Ctrl-Alt-Tab list | ||||
|         if (Main.sessionMode.hasWindows && !Main.overview.visible) { | ||||
|         if (!Main.overview.visible) { | ||||
|             let screen = global.screen; | ||||
|             let display = screen.get_display(); | ||||
|             let windows = display.get_tab_list(Meta.TabList.DOCKS, screen, screen.get_active_workspace ()); | ||||
|             let windowTracker = Shell.WindowTracker.get_default(); | ||||
|             let textureCache = St.TextureCache.get_default(); | ||||
|             for (let i = 0; i < windows.length; i++) { | ||||
|                 let icon = null; | ||||
|                 let iconName = null; | ||||
|                 if (windows[i].get_window_type () == Meta.WindowType.DESKTOP) { | ||||
|                     iconName = 'video-display-symbolic'; | ||||
|                 } else { | ||||
|                     let app = windowTracker.get_window_app(windows[i]); | ||||
|                     if (app) | ||||
|                         icon = app.create_icon_texture(POPUP_APPICON_SIZE); | ||||
|                     else | ||||
|                         icon = textureCache.bind_pixbuf_property(windows[i], 'icon'); | ||||
|                 } | ||||
|  | ||||
|                 let icon; | ||||
|                 let app = windowTracker.get_window_app(windows[i]); | ||||
|                 if (app) | ||||
|                     icon = app.create_icon_texture(POPUP_APPICON_SIZE); | ||||
|                 else | ||||
|                     icon = textureCache.bind_pixbuf_property(windows[i], 'icon'); | ||||
|                 items.push({ name: windows[i].title, | ||||
|                              proxy: windows[i].get_compositor_private(), | ||||
|                              focusCallback: Lang.bind(windows[i], | ||||
| @@ -114,7 +109,6 @@ const CtrlAltTabManager = new Lang.Class({ | ||||
|                                      Main.activateWindow(this, timestamp); | ||||
|                                  }), | ||||
|                              iconActor: icon, | ||||
|                              iconName: iconName, | ||||
|                              sortGroup: SortGroup.MIDDLE }); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -287,7 +287,13 @@ const ShowAppsIcon = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     handleDragOver: function(source, actor, x, y, time) { | ||||
|         if (!this._canRemoveApp(getAppFromSource(source))) | ||||
|         let app = getAppFromSource(source); | ||||
|         if (app == null) | ||||
|             return DND.DragMotionResult.NO_DROP; | ||||
|  | ||||
|         let id = app.get_id(); | ||||
|         let isFavorite = AppFavorites.getAppFavorites().isFavorite(id); | ||||
|         if (!isFavorite) | ||||
|             return DND.DragMotionResult.NO_DROP; | ||||
|  | ||||
|         return DND.DragMotionResult.MOVE_DROP; | ||||
| @@ -295,7 +301,7 @@ const ShowAppsIcon = new Lang.Class({ | ||||
|  | ||||
|     acceptDrop: function(source, actor, x, y, time) { | ||||
|         let app = getAppFromSource(source); | ||||
|         if (!this._canRemoveApp(app)) | ||||
|         if (app == null) | ||||
|             return false; | ||||
|  | ||||
|         let id = app.get_id(); | ||||
| @@ -320,16 +326,6 @@ const DragPlaceholderItem = new Lang.Class({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const EmptyDropTargetItem = new Lang.Class({ | ||||
|     Name: 'EmptyDropTargetItem', | ||||
|     Extends: DashItemContainer, | ||||
|  | ||||
|     _init: function() { | ||||
|         this.parent(); | ||||
|         this.setChild(new St.Bin({ style_class: 'empty-dash-drop-target' })); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const DashActor = new Lang.Class({ | ||||
|     Name: 'DashActor', | ||||
|     Extends: St.Widget, | ||||
| @@ -445,12 +441,6 @@ const Dash = new Lang.Class({ | ||||
|             dragMotion: Lang.bind(this, this._onDragMotion) | ||||
|         }; | ||||
|         DND.addDragMonitor(this._dragMonitor); | ||||
|  | ||||
|         if (this._box.get_n_children() == 0) { | ||||
|             this._emptyDropTarget = new EmptyDropTargetItem(); | ||||
|             this._box.insert_child_at_index(this._emptyDropTarget, 0); | ||||
|             this._emptyDropTarget.show(true); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _onDragCancelled: function() { | ||||
| @@ -467,7 +457,6 @@ const Dash = new Lang.Class({ | ||||
|  | ||||
|     _endDrag: function() { | ||||
|         this._clearDragPlaceholder(); | ||||
|         this._clearEmptyDropTarget(); | ||||
|         this._showAppsIcon.setDragApp(null); | ||||
|         DND.removeDragMonitor(this._dragMonitor); | ||||
|     }, | ||||
| @@ -808,21 +797,9 @@ const Dash = new Lang.Class({ | ||||
|  | ||||
|     _clearDragPlaceholder: function() { | ||||
|         if (this._dragPlaceholder) { | ||||
|             this._animatingPlaceholdersCount++; | ||||
|             this._dragPlaceholder.animateOutAndDestroy(); | ||||
|             this._dragPlaceholder.connect('destroy', | ||||
|                 Lang.bind(this, function() { | ||||
|                     this._animatingPlaceholdersCount--; | ||||
|                 })); | ||||
|             this._dragPlaceholder = null; | ||||
|         } | ||||
|         this._dragPlaceholderPos = -1; | ||||
|     }, | ||||
|  | ||||
|     _clearEmptyDropTarget: function() { | ||||
|         if (this._emptyDropTarget) { | ||||
|             this._emptyDropTarget.animateOutAndDestroy(); | ||||
|             this._emptyDropTarget = null; | ||||
|             this._dragPlaceholderPos = -1; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -850,18 +827,23 @@ const Dash = new Lang.Class({ | ||||
|             numChildren--; | ||||
|         } | ||||
|  | ||||
|         let pos; | ||||
|         if (!this._emptyDropTarget) | ||||
|             pos = Math.floor(y * numChildren / boxHeight); | ||||
|         else | ||||
|             pos = 0; // always insert at the top when dash is empty | ||||
|         let pos = Math.floor(y * numChildren / boxHeight); | ||||
|  | ||||
|         if (pos != this._dragPlaceholderPos && pos <= numFavorites && this._animatingPlaceholdersCount == 0) { | ||||
|             this._dragPlaceholderPos = pos; | ||||
|  | ||||
|             // Don't allow positioning before or after self | ||||
|             if (favPos != -1 && (pos == favPos || pos == favPos + 1)) { | ||||
|                 this._clearDragPlaceholder(); | ||||
|                 if (this._dragPlaceholder) { | ||||
|                     this._dragPlaceholder.animateOutAndDestroy(); | ||||
|                     this._animatingPlaceholdersCount++; | ||||
|                     this._dragPlaceholder.connect('destroy', | ||||
|                         Lang.bind(this, function() { | ||||
|                             this._animatingPlaceholdersCount--; | ||||
|                         })); | ||||
|                 } | ||||
|                 this._dragPlaceholder = null; | ||||
|  | ||||
|                 return DND.DragMotionResult.CONTINUE; | ||||
|             } | ||||
|  | ||||
| @@ -886,9 +868,9 @@ const Dash = new Lang.Class({ | ||||
|  | ||||
|         // Remove the drag placeholder if we are not in the | ||||
|         // "favorites zone" | ||||
|         if (pos > numFavorites) | ||||
|         if (pos > numFavorites && this._dragPlaceholder) { | ||||
|             this._clearDragPlaceholder(); | ||||
|  | ||||
|         } | ||||
|         if (!this._dragPlaceholder) | ||||
|             return DND.DragMotionResult.NO_DROP; | ||||
|  | ||||
|   | ||||
| @@ -49,6 +49,11 @@ const DateMenuButton = new Lang.Class({ | ||||
|             menuAlignment = 1.0 - menuAlignment; | ||||
|         this.parent(menuAlignment); | ||||
|  | ||||
|         // At this moment calendar menu is not keyboard navigable at | ||||
|         // all (so not accessible), so it doesn't make sense to set as | ||||
|         // role ATK_ROLE_MENU like other elements of the panel. | ||||
|         this.actor.accessible_role = Atk.Role.LABEL; | ||||
|  | ||||
|         this._clockDisplay = new St.Label(); | ||||
|         this.actor.add_actor(this._clockDisplay); | ||||
|  | ||||
| @@ -80,22 +85,27 @@ const DateMenuButton = new Lang.Class({ | ||||
|         vbox.add(this._calendar.actor); | ||||
|  | ||||
|         let separator = new PopupMenu.PopupSeparatorMenuItem(); | ||||
|         vbox.add(separator.actor, { y_align: St.Align.END, expand: true, y_fill: false }); | ||||
|         separator.setColumnWidths(1); | ||||
|         vbox.add(separator.actor, {y_align: St.Align.END, expand: true, y_fill: false}); | ||||
|  | ||||
|         this._openCalendarItem = new PopupMenu.PopupMenuItem(_("Open Calendar")); | ||||
|         this._openCalendarItem.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 & Time Settings"), 'gnome-datetime-panel.desktop'); | ||||
|         if (item) { | ||||
|             item.actor.show_on_set_parent = false; | ||||
|             item.actor.can_focus = false; | ||||
|             item.actor.reparent(vbox); | ||||
|             this._dateAndTimeSeparator = separator; | ||||
|         } | ||||
| @@ -106,7 +116,12 @@ const DateMenuButton = new Lang.Class({ | ||||
|         hbox.add(this._separator); | ||||
|  | ||||
|         // Fill up the second column | ||||
|         hbox.add(this._eventList.actor, { expand: true, y_fill: false, y_align: St.Align.START }); | ||||
|         vbox = new St.BoxLayout({ name: 'calendarEventsArea', | ||||
|                                   vertical: true }); | ||||
|         hbox.add(vbox, { expand: true }); | ||||
|  | ||||
|         // Event list | ||||
|         vbox.add(this._eventList.actor, { expand: true }); | ||||
|  | ||||
|         // Whenever the menu is opened, select today | ||||
|         this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) { | ||||
| @@ -142,25 +157,24 @@ const DateMenuButton = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _appInstalledChanged: function() { | ||||
|         this._calendarApp = undefined; | ||||
|         this._updateEventsVisibility(); | ||||
|         let app = Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop'); | ||||
|         this._openClocksItem.actor.visible = app !== null; | ||||
|     }, | ||||
|  | ||||
|     _updateEventsVisibility: function() { | ||||
|         let visible = this._eventSource.hasCalendars; | ||||
|         this._openCalendarItem.actor.visible = visible && | ||||
|             (this._getCalendarApp() != null); | ||||
|         this._openClocksItem.actor.visible = visible && | ||||
|             (this._getClockApp() != null); | ||||
|         this._openCalendarItem.actor.visible = visible; | ||||
|         this._openClocksItem.actor.visible = visible; | ||||
|         this._separator.visible = visible; | ||||
|         this._eventList.actor.visible = visible; | ||||
|         if (visible) { | ||||
|             let alignment = 0.25; | ||||
|             if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) | ||||
|                 alignment = 1.0 - alignment; | ||||
|             this.menu._arrowAlignment = alignment; | ||||
|           let alignment = 0.25; | ||||
|           if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) | ||||
|             alignment = 1.0 - alignment; | ||||
|           this.menu._arrowAlignment = alignment; | ||||
|           this._eventList.actor.get_parent().show(); | ||||
|         } else { | ||||
|             this.menu._arrowAlignment = 0.5; | ||||
|           this.menu._arrowAlignment = 0.5; | ||||
|           this._eventList.actor.get_parent().hide(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -203,34 +217,18 @@ const DateMenuButton = new Lang.Class({ | ||||
|         this._date.set_text(displayDate.toLocaleFormat(dateFormat)); | ||||
|     }, | ||||
|  | ||||
|     _getCalendarApp: function() { | ||||
|         if (this._calendarApp !== undefined) | ||||
|             return this._calendarApp; | ||||
|  | ||||
|         let apps = Gio.AppInfo.get_recommended_for_type('text/calendar'); | ||||
|         if (apps && (apps.length > 0)) | ||||
|             this._calendarApp = apps[0]; | ||||
|         else | ||||
|             this._calendarApp = null; | ||||
|         return this._calendarApp; | ||||
|     }, | ||||
|  | ||||
|     _getClockApp: function() { | ||||
|         return Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop'); | ||||
|     }, | ||||
|  | ||||
|     _onOpenCalendarActivate: function() { | ||||
|         this.menu.close(); | ||||
|  | ||||
|         let app = this._getCalendarApp(); | ||||
|         if (app.get_id() == 'evolution.desktop') | ||||
|             app = Gio.DesktopAppInfo.new('evolution-calendar.desktop'); | ||||
|         let app = Gio.AppInfo.get_default_for_type('text/calendar', false); | ||||
|         if (app.get_id() == 'evolution') | ||||
|             app = Gio.DesktopAppInfo.new('evolution-calendar'); | ||||
|         app.launch([], global.create_app_launch_context()); | ||||
|     }, | ||||
|  | ||||
|     _onOpenClocksActivate: function() { | ||||
|         this.menu.close(); | ||||
|         let app = this._getClockApp(); | ||||
|         let app = Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop'); | ||||
|         app.activate(); | ||||
|     } | ||||
| }); | ||||
|   | ||||
							
								
								
									
										137
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								js/ui/dnd.js
									
									
									
									
									
								
							| @@ -1,7 +1,6 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const GLib = imports.gi.GLib; | ||||
| const Gtk = imports.gi.Gtk; | ||||
| const St = imports.gi.St; | ||||
| const Lang = imports.lang; | ||||
| @@ -44,7 +43,9 @@ let dragMonitors = []; | ||||
|  | ||||
| function _getEventHandlerActor() { | ||||
|     if (!eventHandlerActor) { | ||||
|         eventHandlerActor = new Clutter.Actor({ width: 0, height: 0 }); | ||||
|         eventHandlerActor = new Clutter.Rectangle(); | ||||
|         eventHandlerActor.width = 0; | ||||
|         eventHandlerActor.height = 0; | ||||
|         Main.uiGroup.add_actor(eventHandlerActor); | ||||
|         // We connect to 'event' rather than 'captured-event' because the capturing phase doesn't happen | ||||
|         // when you've grabbed the pointer. | ||||
| @@ -148,16 +149,16 @@ const _Draggable = new Lang.Class({ | ||||
|  | ||||
|     _grabEvents: function() { | ||||
|         if (!this._eventsGrabbed) { | ||||
|             this._eventsGrabbed = Main.pushModal(_getEventHandlerActor()); | ||||
|             if (this._eventsGrabbed) | ||||
|                 Clutter.grab_pointer(_getEventHandlerActor()); | ||||
|             Clutter.grab_pointer(_getEventHandlerActor()); | ||||
|             Clutter.grab_keyboard(_getEventHandlerActor()); | ||||
|             this._eventsGrabbed = true; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _ungrabEvents: function() { | ||||
|         if (this._eventsGrabbed) { | ||||
|             Clutter.ungrab_pointer(); | ||||
|             Main.popModal(_getEventHandlerActor()); | ||||
|             Clutter.ungrab_keyboard(); | ||||
|             this._eventsGrabbed = false; | ||||
|         } | ||||
|     }, | ||||
| @@ -290,19 +291,19 @@ const _Draggable = new Lang.Class({ | ||||
|             this._dragOrigY = this._dragActor.y; | ||||
|             this._dragOrigScale = this._dragActor.scale_x; | ||||
|  | ||||
|             // Set the actor's scale such that it will keep the same | ||||
|             // transformed size when it's reparented to the uiGroup | ||||
|             let [scaledWidth, scaledHeight] = this.actor.get_transformed_size(); | ||||
|             this._dragActor.set_scale(scaledWidth / this.actor.width, | ||||
|                                       scaledHeight / this.actor.height); | ||||
|             this._dragActor.reparent(Main.uiGroup); | ||||
|             this._dragActor.raise_top(); | ||||
|             Shell.util_set_hidden_from_pick(this._dragActor, true); | ||||
|  | ||||
|             let [actorStageX, actorStageY] = this.actor.get_transformed_position(); | ||||
|             this._dragOffsetX = actorStageX - this._dragStartX; | ||||
|             this._dragOffsetY = actorStageY - this._dragStartY; | ||||
|  | ||||
|             this._dragActor.reparent(Main.uiGroup); | ||||
|             this._dragActor.raise_top(); | ||||
|             Shell.util_set_hidden_from_pick(this._dragActor, true); | ||||
|             // Set the actor's scale such that it will keep the same | ||||
|             // transformed size when it's reparented to the uiGroup | ||||
|             let [scaledWidth, scaledHeight] = this.actor.get_transformed_size(); | ||||
|             this.actor.set_scale(scaledWidth / this.actor.width, | ||||
|                                  scaledHeight / this.actor.height); | ||||
|         } | ||||
|  | ||||
|         this._dragOrigOpacity = this._dragActor.opacity; | ||||
| @@ -359,65 +360,60 @@ const _Draggable = new Lang.Class({ | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _updateDragHover : function () { | ||||
|         let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL, | ||||
|                                                                   this._dragX, this._dragY); | ||||
|         let dragEvent = { | ||||
|             x: this._dragX, | ||||
|             y: this._dragY, | ||||
|             dragActor: this._dragActor, | ||||
|             source: this.actor._delegate, | ||||
|             targetActor: target | ||||
|         }; | ||||
|         for (let i = 0; i < dragMonitors.length; i++) { | ||||
|             let motionFunc = dragMonitors[i].dragMotion; | ||||
|             if (motionFunc) { | ||||
|                 let result = motionFunc(dragEvent); | ||||
|                 if (result != DragMotionResult.CONTINUE) { | ||||
|                     global.set_cursor(DRAG_CURSOR_MAP[result]); | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         while (target) { | ||||
|             if (target._delegate && target._delegate.handleDragOver) { | ||||
|                 let [r, targX, targY] = target.transform_stage_point(this._dragX, this._dragY); | ||||
|                 // We currently loop through all parents on drag-over even if one of the children has handled it. | ||||
|                 // We can check the return value of the function and break the loop if it's true if we don't want | ||||
|                 // to continue checking the parents. | ||||
|                 let result = target._delegate.handleDragOver(this.actor._delegate, | ||||
|                                                              this._dragActor, | ||||
|                                                              targX, | ||||
|                                                              targY, | ||||
|                                                              0); | ||||
|                 if (result != DragMotionResult.CONTINUE) { | ||||
|                     global.set_cursor(DRAG_CURSOR_MAP[result]); | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
|             target = target.get_parent(); | ||||
|         } | ||||
|         global.set_cursor(Shell.Cursor.DND_IN_DRAG); | ||||
|         return false; | ||||
|     }, | ||||
|  | ||||
|     _queueUpdateDragHover: function() { | ||||
|         if (this._updateHoverId) | ||||
|             GLib.source_remove(this._updateHoverId); | ||||
|  | ||||
|         this._updateHoverId = GLib.idle_add(GLib.PRIORITY_DEFAULT, | ||||
|                                             Lang.bind(this, this._updateDragHover)); | ||||
|     }, | ||||
|  | ||||
|     _updateDragPosition : function (event) { | ||||
|         let [stageX, stageY] = event.get_coords(); | ||||
|         this._dragX = stageX; | ||||
|         this._dragY = stageY; | ||||
|         this._dragActor.set_position(stageX + this._dragOffsetX, | ||||
|                                      stageY + this._dragOffsetY); | ||||
|  | ||||
|         this._queueUpdateDragHover(); | ||||
|         // If we are dragging, update the position | ||||
|         if (this._dragActor) { | ||||
|             this._dragActor.set_position(stageX + this._dragOffsetX, | ||||
|                                          stageY + this._dragOffsetY); | ||||
|  | ||||
|             let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL, | ||||
|                                                                       stageX, stageY); | ||||
|  | ||||
|             // We call observers only once per motion with the innermost | ||||
|             // target actor. If necessary, the observer can walk the | ||||
|             // parent itself. | ||||
|             let dragEvent = { | ||||
|                 x: stageX, | ||||
|                 y: stageY, | ||||
|                 dragActor: this._dragActor, | ||||
|                 source: this.actor._delegate, | ||||
|                 targetActor: target | ||||
|             }; | ||||
|             for (let i = 0; i < dragMonitors.length; i++) { | ||||
|                 let motionFunc = dragMonitors[i].dragMotion; | ||||
|                 if (motionFunc) { | ||||
|                     let result = motionFunc(dragEvent); | ||||
|                     if (result != DragMotionResult.CONTINUE) { | ||||
|                         global.set_cursor(DRAG_CURSOR_MAP[result]); | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             while (target) { | ||||
|                 if (target._delegate && target._delegate.handleDragOver) { | ||||
|                     let [r, targX, targY] = target.transform_stage_point(stageX, stageY); | ||||
|                     // We currently loop through all parents on drag-over even if one of the children has handled it. | ||||
|                     // We can check the return value of the function and break the loop if it's true if we don't want | ||||
|                     // to continue checking the parents. | ||||
|                     let result = target._delegate.handleDragOver(this.actor._delegate, | ||||
|                                                                  this._dragActor, | ||||
|                                                                  targX, | ||||
|                                                                  targY, | ||||
|                                                                  event.get_time()); | ||||
|                     if (result != DragMotionResult.CONTINUE) { | ||||
|                         global.set_cursor(DRAG_CURSOR_MAP[result]); | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
|                 target = target.get_parent(); | ||||
|             } | ||||
|             global.set_cursor(Shell.Cursor.DND_IN_DRAG); | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
| @@ -517,11 +513,6 @@ const _Draggable = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _cancelDrag: function(eventTime) { | ||||
|         if (this._updateHoverId) { | ||||
|             GLib.source_remove(this._updateHoverId); | ||||
|             this._updateHoverId = 0; | ||||
|         } | ||||
|  | ||||
|         this.emit('drag-cancelled', eventTime); | ||||
|         this._dragInProgress = false; | ||||
|         let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation(); | ||||
|   | ||||
| @@ -35,7 +35,7 @@ const GnomeSession = imports.misc.gnomeSession; | ||||
| const Main = imports.ui.main; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const UserWidget = imports.ui.userWidget; | ||||
| const UserMenu = imports.ui.userMenu; | ||||
|  | ||||
| let _endSessionDialog = null; | ||||
|  | ||||
| @@ -360,9 +360,9 @@ const EndSessionDialog = new Lang.Class({ | ||||
|                                                 icon_size: _DIALOG_ICON_SIZE, | ||||
|                                                 style_class: dialogContent.iconStyleClass }); | ||||
|         } else { | ||||
|             let avatarWidget = new UserWidget.Avatar(this._user, | ||||
|                                                      { iconSize: _DIALOG_ICON_SIZE, | ||||
|                                                        styleClass: dialogContent.iconStyleClass }); | ||||
|             let avatarWidget = new UserMenu.UserAvatarWidget(this._user, | ||||
|                                                              { iconSize: _DIALOG_ICON_SIZE, | ||||
|                                                                styleClass: dialogContent.iconStyleClass }); | ||||
|             this._iconBin.child = avatarWidget.actor; | ||||
|             avatarWidget.update(); | ||||
|         } | ||||
| @@ -420,7 +420,6 @@ const EndSessionDialog = new Lang.Class({ | ||||
|     _startTimer: function() { | ||||
|         let startTime = GLib.get_monotonic_time(); | ||||
|         this._secondsLeft = this._totalSecondsToStayOpen; | ||||
|         this._updateDescription(); | ||||
|  | ||||
|         this._timerId = Mainloop.timeout_add_seconds(1, Lang.bind(this, | ||||
|             function() { | ||||
|   | ||||
| @@ -292,7 +292,7 @@ function disableAllExtensions() { | ||||
|         return; | ||||
|  | ||||
|     if (initted) { | ||||
|         extensionOrder.slice().reverse().forEach(function(uuid) { | ||||
|         enabledExtensions.forEach(function(uuid) { | ||||
|             disableExtension(uuid); | ||||
|         }); | ||||
|     } | ||||
|   | ||||
| @@ -211,8 +211,10 @@ const GrabHelper = new Lang.Class({ | ||||
|             this._grabbedFromKeynav = hadFocus; | ||||
|             this._preGrabInputMode = global.stage_input_mode; | ||||
|  | ||||
|             if (this._preGrabInputMode == Shell.StageInputMode.NORMAL) | ||||
|             if (this._preGrabInputMode == Shell.StageInputMode.NONREACTIVE || | ||||
|                 this._preGrabInputMode == Shell.StageInputMode.NORMAL) { | ||||
|                 global.set_stage_input_mode(Shell.StageInputMode.FOCUSED); | ||||
|             } | ||||
|  | ||||
|             this._keyFocusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged)); | ||||
|             this._focusWindowChangedId = metaDisplay.connect('notify::focus-window', Lang.bind(this, this._focusWindowChanged)); | ||||
|   | ||||
							
								
								
									
										184
									
								
								js/ui/layout.js
									
									
									
									
									
								
							
							
						
						
									
										184
									
								
								js/ui/layout.js
									
									
									
									
									
								
							| @@ -118,25 +118,10 @@ const MonitorConstraint = new Lang.Class({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const Monitor = new Lang.Class({ | ||||
|     Name: 'Monitor', | ||||
|  | ||||
|     _init: function(index, geometry) { | ||||
|         this.index = index; | ||||
|         this.x = geometry.x; | ||||
|         this.y = geometry.y; | ||||
|         this.width = geometry.width; | ||||
|         this.height = geometry.height; | ||||
|     }, | ||||
|  | ||||
|     get inFullscreen() { | ||||
|         return global.screen.get_monitor_in_fullscreen(this.index); | ||||
|     } | ||||
| }) | ||||
|  | ||||
| const defaultParams = { | ||||
|     trackFullscreen: false, | ||||
|     affectsStruts: false, | ||||
|     affectsInputRegion: true | ||||
| }; | ||||
|  | ||||
| const LayoutManager = new Lang.Class({ | ||||
| @@ -188,12 +173,10 @@ const LayoutManager = new Lang.Class({ | ||||
|         global.stage.remove_actor(global.window_group); | ||||
|         this.uiGroup.add_actor(global.window_group); | ||||
|  | ||||
|         global.stage.remove_actor(global.overlay_group); | ||||
|         this.uiGroup.add_actor(global.overlay_group); | ||||
|         global.stage.add_child(this.uiGroup); | ||||
|  | ||||
|         this.overviewGroup = new St.Widget({ name: 'overviewGroup', | ||||
|                                              visible: false }); | ||||
|         this.addChrome(this.overviewGroup); | ||||
|  | ||||
|         this.screenShieldGroup = new St.Widget({ name: 'screenShieldGroup', | ||||
|                                                  visible: false, | ||||
|                                                  clip_to_allocation: true, | ||||
| @@ -244,24 +227,24 @@ const LayoutManager = new Lang.Class({ | ||||
|         this._monitorsChanged(); | ||||
|     }, | ||||
|  | ||||
|     // This is called by Main after everything else is constructed | ||||
|     // This is called by Main after everything else is constructed; | ||||
|     // it needs access to Main.overview, which didn't exist | ||||
|     // yet when the LayoutManager was constructed. | ||||
|     init: function() { | ||||
|         Main.overview.connect('showing', Lang.bind(this, this._overviewShowing)); | ||||
|         Main.overview.connect('hidden', Lang.bind(this, this._overviewHidden)); | ||||
|         Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated)); | ||||
|  | ||||
|         this._loadBackground(); | ||||
|         this._prepareStartupAnimation(); | ||||
|     }, | ||||
|  | ||||
|     showOverview: function() { | ||||
|         this.overviewGroup.show(); | ||||
|  | ||||
|     _overviewShowing: function() { | ||||
|         this._inOverview = true; | ||||
|         this._updateVisibility(); | ||||
|         this._queueUpdateRegions(); | ||||
|     }, | ||||
|  | ||||
|     hideOverview: function() { | ||||
|         this.overviewGroup.hide(); | ||||
|  | ||||
|     _overviewHidden: function() { | ||||
|         this._inOverview = false; | ||||
|         this._updateVisibility(); | ||||
|         this._queueUpdateRegions(); | ||||
| @@ -278,7 +261,7 @@ const LayoutManager = new Lang.Class({ | ||||
|         this.monitors = []; | ||||
|         let nMonitors = screen.get_n_monitors(); | ||||
|         for (let i = 0; i < nMonitors; i++) | ||||
|             this.monitors.push(new Monitor(i, screen.get_monitor_geometry(i))); | ||||
|             this.monitors.push(screen.get_monitor_geometry(i)); | ||||
|  | ||||
|         if (nMonitors == 1) { | ||||
|             this.primaryIndex = this.bottomIndex = 0; | ||||
| @@ -300,10 +283,8 @@ const LayoutManager = new Lang.Class({ | ||||
|  | ||||
|     _updateHotCorners: function() { | ||||
|         // destroy old hot corners | ||||
|         this.hotCorners.forEach(function(corner) { | ||||
|             if (corner) | ||||
|                 corner.destroy(); | ||||
|         }); | ||||
|         for (let i = 0; i < this.hotCorners.length; i++) | ||||
|             this.hotCorners[i].destroy(); | ||||
|         this.hotCorners = []; | ||||
|  | ||||
|         let size = this.panelBox.height; | ||||
| @@ -314,9 +295,9 @@ const LayoutManager = new Lang.Class({ | ||||
|             let cornerX = this._rtl ? monitor.x + monitor.width : monitor.x; | ||||
|             let cornerY = monitor.y; | ||||
|  | ||||
|             let haveTopLeftCorner = true; | ||||
|  | ||||
|             if (i != this.primaryIndex) { | ||||
|                 let haveTopLeftCorner = true; | ||||
|  | ||||
|                 // Check if we have a top left (right for RTL) corner. | ||||
|                 // I.e. if there is no monitor directly above or to the left(right) | ||||
|                 let besideX = this._rtl ? monitor.x + 1 : cornerX - 1; | ||||
| @@ -343,15 +324,14 @@ const LayoutManager = new Lang.Class({ | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (!haveTopLeftCorner) | ||||
|                     continue; | ||||
|             } | ||||
|  | ||||
|             if (haveTopLeftCorner) { | ||||
|                 let corner = new HotCorner(this, monitor, cornerX, cornerY); | ||||
|                 corner.setBarrierSize(size); | ||||
|                 this.hotCorners.push(corner); | ||||
|             } else { | ||||
|                 this.hotCorners.push(null); | ||||
|             } | ||||
|             let corner = new HotCorner(this, monitor, cornerX, cornerY); | ||||
|             corner.setBarrierSize(size); | ||||
|             this.hotCorners.push(corner); | ||||
|         } | ||||
|  | ||||
|         this.emit('hot-corners-changed'); | ||||
| @@ -428,8 +408,7 @@ const LayoutManager = new Lang.Class({ | ||||
|  | ||||
|         let size = this.panelBox.height; | ||||
|         this.hotCorners.forEach(function(corner) { | ||||
|             if (corner) | ||||
|                 corner.setBarrierSize(size); | ||||
|             corner.setBarrierSize(size); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
| @@ -557,25 +536,6 @@ const LayoutManager = new Lang.Class({ | ||||
|         return this._keyboardIndex; | ||||
|     }, | ||||
|  | ||||
|     _loadBackground: function() { | ||||
|         this._systemBackground = new Background.SystemBackground(); | ||||
|         this._systemBackground.actor.hide(); | ||||
|  | ||||
|         global.stage.insert_child_below(this._systemBackground.actor, null); | ||||
|  | ||||
|         let constraint = new Clutter.BindConstraint({ source: global.stage, | ||||
|                                                       coordinate: Clutter.BindCoordinate.ALL }); | ||||
|         this._systemBackground.actor.add_constraint(constraint); | ||||
|  | ||||
|         let signalId = this._systemBackground.connect('loaded', Lang.bind(this, function() { | ||||
|             this._systemBackground.disconnect(signalId); | ||||
|             this._systemBackground.actor.show(); | ||||
|             global.stage.show(); | ||||
|  | ||||
|             this._prepareStartupAnimation(); | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     // Startup Animations | ||||
|     // | ||||
|     // We have two different animations, depending on whether we're a greeter | ||||
| @@ -621,18 +581,35 @@ const LayoutManager = new Lang.Class({ | ||||
|             global.window_group.set_clip(monitor.x, monitor.y, monitor.width, monitor.height); | ||||
|         } | ||||
|  | ||||
|         this.emit('startup-prepared'); | ||||
|         this._systemBackground = new Background.SystemBackground(); | ||||
|         this._systemBackground.actor.hide(); | ||||
|  | ||||
|         // We're mostly prepared for the startup animation | ||||
|         // now, but since a lot is going on asynchronously | ||||
|         // during startup, let's defer the startup animation | ||||
|         // until the event loop is uncontended and idle. | ||||
|         // This helps to prevent us from running the animation | ||||
|         // when the system is bogged down | ||||
|         GLib.idle_add(GLib.PRIORITY_LOW, Lang.bind(this, function() { | ||||
|             this._startupAnimation(); | ||||
|             return false; | ||||
|         })); | ||||
|         global.stage.insert_child_below(this._systemBackground.actor, null); | ||||
|  | ||||
|         let constraint = new Clutter.BindConstraint({ source: global.stage, | ||||
|                                                       coordinate: Clutter.BindCoordinate.ALL }); | ||||
|         this._systemBackground.actor.add_constraint(constraint); | ||||
|  | ||||
|         let signalId = this._systemBackground.connect('loaded', | ||||
|                                                       Lang.bind(this, function() { | ||||
|                                                           this._systemBackground.disconnect(signalId); | ||||
|                                                           this._systemBackground.actor.show(); | ||||
|                                                           global.stage.show(); | ||||
|  | ||||
|                                                           this.emit('startup-prepared'); | ||||
|  | ||||
|                                                           // We're mostly prepared for the startup animation | ||||
|                                                           // now, but since a lot is going on asynchronously | ||||
|                                                           // during startup, let's defer the startup animation | ||||
|                                                           // until the event loop is uncontended and idle. | ||||
|                                                           // This helps to prevent us from running the animation | ||||
|                                                           // when the system is bogged down | ||||
|                                                           GLib.idle_add(GLib.PRIORITY_LOW, | ||||
|                                                                         Lang.bind(this, function() { | ||||
|                                                                             this._startupAnimation(); | ||||
|                                                                             return false; | ||||
|                                                                         })); | ||||
|                                                       })); | ||||
|     }, | ||||
|  | ||||
|     _startupAnimation: function() { | ||||
| @@ -689,6 +666,7 @@ const LayoutManager = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     showKeyboard: function () { | ||||
|         this.keyboardBox.raise_top(); | ||||
|         Tweener.addTween(this.keyboardBox, | ||||
|                          { anchor_y: this.keyboardBox.height, | ||||
|                            time: KEYBOARD_ANIMATION_TIME, | ||||
| @@ -733,10 +711,11 @@ const LayoutManager = new Lang.Class({ | ||||
|     // @actor: an actor to add to the chrome | ||||
|     // @params: (optional) additional params | ||||
|     // | ||||
|     // Adds @actor to the chrome, and extends the input region | ||||
|     // to include it. Changes in @actor's size, position, and | ||||
|     // visibility will automatically result in appropriate changes | ||||
|     // to the input region. | ||||
|     // Adds @actor to the chrome, and (unless %affectsInputRegion in | ||||
|     // @params is %false) extends the input region to include it. | ||||
|     // Changes in @actor's size, position, and visibility will | ||||
|     // automatically result in appropriate changes to the input | ||||
|     // region. | ||||
|     // | ||||
|     // If %affectsStruts in @params is %true (and @actor is along a | ||||
|     // screen edge), then @actor's size and position will also affect | ||||
| @@ -749,8 +728,6 @@ const LayoutManager = new Lang.Class({ | ||||
|     // and shown otherwise) | ||||
|     addChrome: function(actor, params) { | ||||
|         this.uiGroup.add_actor(actor); | ||||
|         if (this.uiGroup.contains(global.top_window_group)) | ||||
|             this.uiGroup.set_child_below_sibling(actor, global.top_window_group); | ||||
|         this._trackActor(actor, params); | ||||
|     }, | ||||
|  | ||||
| @@ -923,8 +900,13 @@ const LayoutManager = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _updateFullscreen: function() { | ||||
|         for (let i = 0; i < this.monitors.length; i++) | ||||
|             this.monitors[i].inFullscreen = global.screen.get_monitor_in_fullscreen (i); | ||||
|  | ||||
|         this._updateVisibility(); | ||||
|         this._queueUpdateRegions(); | ||||
|  | ||||
|         this.emit('fullscreen-changed'); | ||||
|     }, | ||||
|  | ||||
|     _windowsRestacked: function() { | ||||
| @@ -952,7 +934,7 @@ const LayoutManager = new Lang.Class({ | ||||
|  | ||||
|         for (i = 0; i < this._trackedActors.length; i++) { | ||||
|             let actorData = this._trackedActors[i]; | ||||
|             if (!wantsInputRegion && !actorData.affectsStruts) | ||||
|             if (!(actorData.affectsInputRegion && wantsInputRegion) && !actorData.affectsStruts) | ||||
|                 continue; | ||||
|  | ||||
|             let [x, y] = actorData.actor.get_transformed_position(); | ||||
| @@ -962,8 +944,13 @@ const LayoutManager = new Lang.Class({ | ||||
|             w = Math.round(w); | ||||
|             h = Math.round(h); | ||||
|  | ||||
|             if (wantsInputRegion && actorData.actor.get_paint_visibility()) | ||||
|                 rects.push(new Meta.Rectangle({ x: x, y: y, width: w, height: h })); | ||||
|             if (actorData.affectsInputRegion && wantsInputRegion) { | ||||
|                 let rect = new Meta.Rectangle({ x: x, y: y, width: w, height: h}); | ||||
|  | ||||
|                 if (actorData.actor.get_paint_visibility() && | ||||
|                     !this.uiGroup.get_skip_paint(actorData.actor)) | ||||
|                     rects.push(rect); | ||||
|             } | ||||
|  | ||||
|             if (actorData.affectsStruts) { | ||||
|                 // Limit struts to the size of the screen | ||||
| @@ -1105,21 +1092,12 @@ const HotCorner = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         if (size > 0) { | ||||
|             if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) { | ||||
|                 this._verticalBarrier = new Meta.Barrier({ display: global.display, | ||||
|                                                            x1: this._x, x2: this._x, y1: this._y, y2: this._y + size, | ||||
|                                                            directions: Meta.BarrierDirection.NEGATIVE_X }); | ||||
|                 this._horizontalBarrier = new Meta.Barrier({ display: global.display, | ||||
|                                                              x1: this._x - size, x2: this._x, y1: this._y, y2: this._y, | ||||
|                                                              directions: Meta.BarrierDirection.POSITIVE_Y }); | ||||
|             } else { | ||||
|                 this._verticalBarrier = new Meta.Barrier({ display: global.display, | ||||
|                                                            x1: this._x, x2: this._x, y1: this._y, y2: this._y + size, | ||||
|                                                            directions: Meta.BarrierDirection.POSITIVE_X }); | ||||
|                 this._horizontalBarrier = new Meta.Barrier({ display: global.display, | ||||
|                                                              x1: this._x, x2: this._x + size, y1: this._y, y2: this._y, | ||||
|                                                              directions: Meta.BarrierDirection.POSITIVE_Y }); | ||||
|             } | ||||
|             this._verticalBarrier = new Meta.Barrier({ display: global.display, | ||||
|                                                        x1: this._x, x2: this._x, y1: this._y, y2: this._y + size, | ||||
|                                                        directions: Meta.BarrierDirection.POSITIVE_X }); | ||||
|             this._horizontalBarrier = new Meta.Barrier({ display: global.display, | ||||
|                                                          x1: this._x, x2: this._x + size, y1: this._y, y2: this._y, | ||||
|                                                          directions: Meta.BarrierDirection.POSITIVE_Y }); | ||||
|  | ||||
|             this._pressureBarrier.addBarrier(this._verticalBarrier); | ||||
|             this._pressureBarrier.addBarrier(this._horizontalBarrier); | ||||
| @@ -1134,11 +1112,11 @@ const HotCorner = new Lang.Class({ | ||||
|                                              height: 3, | ||||
|                                              reactive: true }); | ||||
|  | ||||
|             this._corner = new Clutter.Actor({ name: 'hot-corner', | ||||
|                                                width: 1, | ||||
|                                                height: 1, | ||||
|                                                opacity: 0, | ||||
|                                                reactive: true }); | ||||
|             this._corner = new Clutter.Rectangle({ name: 'hot-corner', | ||||
|                                                    width: 1, | ||||
|                                                    height: 1, | ||||
|                                                    opacity: 0, | ||||
|                                                    reactive: true }); | ||||
|             this._corner._delegate = this; | ||||
|  | ||||
|             this.actor.add_child(this._corner); | ||||
|   | ||||
| @@ -308,6 +308,10 @@ const Result = new Lang.Class({ | ||||
|         box.add(resultTxt); | ||||
|         let objLink = new ObjLink(this._lookingGlass, o); | ||||
|         box.add(objLink.actor); | ||||
|         let line = new Clutter.Rectangle({ name: 'Separator' }); | ||||
|         let padBin = new St.Bin({ name: 'Separator', x_fill: true, y_fill: true }); | ||||
|         padBin.add_actor(line); | ||||
|         this.actor.add(padBin); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -985,18 +989,28 @@ const LookingGlass = new Lang.Class({ | ||||
|  | ||||
|     _showCompletions: function(completions) { | ||||
|         if (!this._completionActor) { | ||||
|             this._completionActor = new St.Label({ name: 'LookingGlassAutoCompletionText', style_class: 'lg-completions-text' }); | ||||
|             this._completionActor.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; | ||||
|             this._completionActor.clutter_text.line_wrap = true; | ||||
|             let actor = new St.BoxLayout({ vertical: true }); | ||||
|  | ||||
|             this._completionText = new St.Label({ name: 'LookingGlassAutoCompletionText', style_class: 'lg-completions-text' }); | ||||
|             this._completionText.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; | ||||
|             this._completionText.clutter_text.line_wrap = true; | ||||
|             actor.add(this._completionText); | ||||
|  | ||||
|             let line = new Clutter.Rectangle(); | ||||
|             let padBin = new St.Bin({ x_fill: true, y_fill: true }); | ||||
|             padBin.add_actor(line); | ||||
|             actor.add(padBin); | ||||
|  | ||||
|             this._completionActor = actor; | ||||
|             this._evalBox.insert_child_below(this._completionActor, this._entryArea); | ||||
|         } | ||||
|  | ||||
|         this._completionActor.set_text(completions.join(', ')); | ||||
|         this._completionText.set_text(completions.join(', ')); | ||||
|  | ||||
|         // Setting the height to -1 allows us to get its actual preferred height rather than | ||||
|         // whatever was last given in set_height by Tweener. | ||||
|         this._completionActor.set_height(-1); | ||||
|         let [minHeight, naturalHeight] = this._completionActor.get_preferred_height(this._resultsArea.get_width()); | ||||
|         let [minHeight, naturalHeight] = this._completionText.get_preferred_height(this._resultsArea.get_width()); | ||||
|  | ||||
|         // Don't reanimate if we are already visible | ||||
|         if (this._completionActor.visible) { | ||||
|   | ||||
							
								
								
									
										230
									
								
								js/ui/main.js
									
									
									
									
									
								
							
							
						
						
									
										230
									
								
								js/ui/main.js
									
									
									
									
									
								
							| @@ -38,11 +38,9 @@ const Magnifier = imports.ui.magnifier; | ||||
| 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 A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard'; | ||||
| const STICKY_KEYS_ENABLE = 'stickykeys-enable'; | ||||
|  | ||||
| let componentManager = null; | ||||
| let panel = null; | ||||
| let overview = null; | ||||
| @@ -70,8 +68,7 @@ let layoutManager = null; | ||||
| let _startDate; | ||||
| let _defaultCssStylesheet = null; | ||||
| let _cssStylesheet = null; | ||||
| let _a11ySettings = null; | ||||
| let dynamicWorkspacesSchema = null; | ||||
| let _overridesSettings = null; | ||||
|  | ||||
| function _sessionUpdated() { | ||||
|     _loadDefaultStylesheet(); | ||||
| @@ -109,7 +106,6 @@ function start() { | ||||
|  | ||||
| function _sessionsLoaded() { | ||||
|     sessionMode.connect('updated', _sessionUpdated); | ||||
|     _initializePrefs(); | ||||
|     _initializeUI(); | ||||
|  | ||||
|     shellDBusService = new ShellDBus.GnomeShell(); | ||||
| @@ -118,17 +114,6 @@ function _sessionsLoaded() { | ||||
|     _sessionUpdated(); | ||||
| } | ||||
|  | ||||
| function _initializePrefs() { | ||||
|     let keys = new Gio.Settings({ schema: sessionMode.overridesSchema }).list_keys(); | ||||
|     for (let i = 0; i < keys.length; i++) | ||||
|         Meta.prefs_override_preference_schema(keys[i], sessionMode.overridesSchema); | ||||
|  | ||||
|     if (keys.indexOf('dynamic-workspaces') > -1) | ||||
|         dynamicWorkspacesSchema = sessionMode.overridesSchema; | ||||
|     else | ||||
|         dynamicWorkspacesSchema = 'org.gnome.mutter'; | ||||
| } | ||||
|  | ||||
| function _initializeUI() { | ||||
|     // Ensure ShellWindowTracker and ShellAppUsage are initialized; this will | ||||
|     // also initialize ShellAppSystem first.  ShellAppSystem | ||||
| @@ -138,9 +123,11 @@ function _initializeUI() { | ||||
|     // and recalculate application associations, so to avoid | ||||
|     // races for now we initialize it here.  It's better to | ||||
|     // be predictable anyways. | ||||
|     Shell.WindowTracker.get_default(); | ||||
|     let tracker = Shell.WindowTracker.get_default(); | ||||
|     Shell.AppUsage.get_default(); | ||||
|  | ||||
|     tracker.connect('startup-sequence-changed', _queueCheckWorkspaces); | ||||
|  | ||||
|     _loadDefaultStylesheet(); | ||||
|  | ||||
|     // Setup the stage hierarchy early | ||||
| @@ -170,12 +157,9 @@ function _initializeUI() { | ||||
|     layoutManager.init(); | ||||
|     overview.init(); | ||||
|  | ||||
|     _a11ySettings = new Gio.Settings({ schema: A11Y_SCHEMA }); | ||||
|  | ||||
|     global.display.connect('overlay-key', Lang.bind(overview, function () { | ||||
|         if (!_a11ySettings.get_boolean (STICKY_KEYS_ENABLE)) | ||||
|             overview.toggle(); | ||||
|     })); | ||||
|     global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, | ||||
|                                             false, -1, 1); | ||||
|     global.display.connect('overlay-key', Lang.bind(overview, overview.toggle)); | ||||
|  | ||||
|     // Provide the bus object for gnome-session to | ||||
|     // initiate logouts. | ||||
| @@ -195,6 +179,17 @@ function _initializeUI() { | ||||
|         Scripting.runPerfScript(module, perfOutput); | ||||
|     } | ||||
|  | ||||
|     _overridesSettings = new Gio.Settings({ schema: OVERRIDES_SCHEMA }); | ||||
|     _overridesSettings.connect('changed::dynamic-workspaces', _queueCheckWorkspaces); | ||||
|  | ||||
|     global.screen.connect('notify::n-workspaces', _nWorkspacesChanged); | ||||
|  | ||||
|     global.screen.connect('window-entered-monitor', _windowEnteredMonitor); | ||||
|     global.screen.connect('window-left-monitor', _windowLeftMonitor); | ||||
|     global.screen.connect('restacked', _windowsRestacked); | ||||
|  | ||||
|     _nWorkspacesChanged(); | ||||
|  | ||||
|     ExtensionDownloader.init(); | ||||
|     ExtensionSystem.init(); | ||||
|  | ||||
| @@ -208,12 +203,190 @@ function _initializeUI() { | ||||
|                               if (keybindingMode == Shell.KeyBindingMode.NONE) { | ||||
|                                   keybindingMode = Shell.KeyBindingMode.NORMAL; | ||||
|                               } | ||||
|                               if (screenShield) { | ||||
|                                   screenShield.lockIfWasLocked(); | ||||
|                               } | ||||
|                           }); | ||||
| } | ||||
|  | ||||
| let _workspaces = []; | ||||
| let _checkWorkspacesId = 0; | ||||
|  | ||||
| /* | ||||
|  * When the last window closed on a workspace is a dialog or splash | ||||
|  * screen, we assume that it might be an initial window shown before | ||||
|  * the main window of an application, and give the app a grace period | ||||
|  * where it can map another window before we remove the workspace. | ||||
|  */ | ||||
| const LAST_WINDOW_GRACE_TIME = 1000; | ||||
|  | ||||
| function _checkWorkspaces() { | ||||
|     let i; | ||||
|     let emptyWorkspaces = []; | ||||
|  | ||||
|     if (!Meta.prefs_get_dynamic_workspaces()) { | ||||
|         _checkWorkspacesId = 0; | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     for (i = 0; i < _workspaces.length; i++) { | ||||
|         let lastRemoved = _workspaces[i]._lastRemovedWindow; | ||||
|         if ((lastRemoved && | ||||
|              (lastRemoved.get_window_type() == Meta.WindowType.SPLASHSCREEN || | ||||
|               lastRemoved.get_window_type() == Meta.WindowType.DIALOG || | ||||
|               lastRemoved.get_window_type() == Meta.WindowType.MODAL_DIALOG)) || | ||||
|             _workspaces[i]._keepAliveId) | ||||
|                 emptyWorkspaces[i] = false; | ||||
|         else | ||||
|             emptyWorkspaces[i] = true; | ||||
|     } | ||||
|  | ||||
|     let sequences = Shell.WindowTracker.get_default().get_startup_sequences(); | ||||
|     for (i = 0; i < sequences.length; i++) { | ||||
|         let index = sequences[i].get_workspace(); | ||||
|         if (index >= 0 && index <= global.screen.n_workspaces) | ||||
|             emptyWorkspaces[index] = false; | ||||
|     } | ||||
|  | ||||
|     let windows = global.get_window_actors(); | ||||
|     for (i = 0; i < windows.length; i++) { | ||||
|         let win = windows[i]; | ||||
|  | ||||
|         if (win.get_meta_window().is_on_all_workspaces()) | ||||
|             continue; | ||||
|  | ||||
|         let workspaceIndex = win.get_workspace(); | ||||
|         emptyWorkspaces[workspaceIndex] = false; | ||||
|     } | ||||
|  | ||||
|     // If we don't have an empty workspace at the end, add one | ||||
|     if (!emptyWorkspaces[emptyWorkspaces.length -1]) { | ||||
|         global.screen.append_new_workspace(false, global.get_current_time()); | ||||
|         emptyWorkspaces.push(false); | ||||
|     } | ||||
|  | ||||
|     let activeWorkspaceIndex = global.screen.get_active_workspace_index(); | ||||
|     let removingCurrentWorkspace = (emptyWorkspaces[activeWorkspaceIndex] && | ||||
|                                     activeWorkspaceIndex < emptyWorkspaces.length - 1); | ||||
|     // Don't enter the overview when removing multiple empty workspaces at startup | ||||
|     let showOverview  = (removingCurrentWorkspace && | ||||
|                          !emptyWorkspaces.every(function(x) { return x; })); | ||||
|  | ||||
|     if (removingCurrentWorkspace) { | ||||
|         // "Merge" the empty workspace we are removing with the one at the end | ||||
|         wm.blockAnimations(); | ||||
|     } | ||||
|  | ||||
|     // Delete other empty workspaces; do it from the end to avoid index changes | ||||
|     for (i = emptyWorkspaces.length - 2; i >= 0; i--) { | ||||
|         if (emptyWorkspaces[i]) | ||||
|             global.screen.remove_workspace(_workspaces[i], global.get_current_time()); | ||||
|     } | ||||
|  | ||||
|     if (removingCurrentWorkspace) { | ||||
|         global.screen.get_workspace_by_index(global.screen.n_workspaces - 1).activate(global.get_current_time()); | ||||
|         wm.unblockAnimations(); | ||||
|  | ||||
|         if (!overview.visible && showOverview) | ||||
|             overview.show(); | ||||
|     } | ||||
|  | ||||
|     _checkWorkspacesId = 0; | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| function keepWorkspaceAlive(workspace, duration) { | ||||
|     if (workspace._keepAliveId) | ||||
|         Mainloop.source_remove(workspace._keepAliveId); | ||||
|  | ||||
|     workspace._keepAliveId = Mainloop.timeout_add(duration, function() { | ||||
|         workspace._keepAliveId = 0; | ||||
|         _queueCheckWorkspaces(); | ||||
|         return false; | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function _windowRemoved(workspace, window) { | ||||
|     workspace._lastRemovedWindow = window; | ||||
|     _queueCheckWorkspaces(); | ||||
|     Mainloop.timeout_add(LAST_WINDOW_GRACE_TIME, function() { | ||||
|         if (workspace._lastRemovedWindow == window) { | ||||
|             workspace._lastRemovedWindow = null; | ||||
|             _queueCheckWorkspaces(); | ||||
|         } | ||||
|         return false; | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function _windowLeftMonitor(metaScreen, monitorIndex, metaWin) { | ||||
|     // If the window left the primary monitor, that | ||||
|     // might make that workspace empty | ||||
|     if (monitorIndex == layoutManager.primaryIndex) | ||||
|         _queueCheckWorkspaces(); | ||||
| } | ||||
|  | ||||
| function _windowEnteredMonitor(metaScreen, monitorIndex, metaWin) { | ||||
|     // If the window entered the primary monitor, that | ||||
|     // might make that workspace non-empty | ||||
|     if (monitorIndex == layoutManager.primaryIndex) | ||||
|         _queueCheckWorkspaces(); | ||||
| } | ||||
|  | ||||
| function _windowsRestacked() { | ||||
|     // Figure out where the pointer is in case we lost track of | ||||
|     // it during a grab. (In particular, if a trayicon popup menu | ||||
|     // is dismissed, see if we need to close the message tray.) | ||||
|     global.sync_pointer(); | ||||
| } | ||||
|  | ||||
| function _queueCheckWorkspaces() { | ||||
|     if (_checkWorkspacesId == 0) | ||||
|         _checkWorkspacesId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, _checkWorkspaces); | ||||
| } | ||||
|  | ||||
| function _nWorkspacesChanged() { | ||||
|     let oldNumWorkspaces = _workspaces.length; | ||||
|     let newNumWorkspaces = global.screen.n_workspaces; | ||||
|  | ||||
|     if (oldNumWorkspaces == newNumWorkspaces) | ||||
|         return false; | ||||
|  | ||||
|     let lostWorkspaces = []; | ||||
|     if (newNumWorkspaces > oldNumWorkspaces) { | ||||
|         let w; | ||||
|  | ||||
|         // Assume workspaces are only added at the end | ||||
|         for (w = oldNumWorkspaces; w < newNumWorkspaces; w++) | ||||
|             _workspaces[w] = global.screen.get_workspace_by_index(w); | ||||
|  | ||||
|         for (w = oldNumWorkspaces; w < newNumWorkspaces; w++) { | ||||
|             let workspace = _workspaces[w]; | ||||
|             workspace._windowAddedId = workspace.connect('window-added', _queueCheckWorkspaces); | ||||
|             workspace._windowRemovedId = workspace.connect('window-removed', _windowRemoved); | ||||
|         } | ||||
|  | ||||
|     } else { | ||||
|         // Assume workspaces are only removed sequentially | ||||
|         // (e.g. 2,3,4 - not 2,4,7) | ||||
|         let removedIndex; | ||||
|         let removedNum = oldNumWorkspaces - newNumWorkspaces; | ||||
|         for (let w = 0; w < oldNumWorkspaces; w++) { | ||||
|             let workspace = global.screen.get_workspace_by_index(w); | ||||
|             if (_workspaces[w] != workspace) { | ||||
|                 removedIndex = w; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         let lostWorkspaces = _workspaces.splice(removedIndex, removedNum); | ||||
|         lostWorkspaces.forEach(function(workspace) { | ||||
|                                    workspace.disconnect(workspace._windowAddedId); | ||||
|                                    workspace.disconnect(workspace._windowRemovedId); | ||||
|                                }); | ||||
|     } | ||||
|  | ||||
|     _queueCheckWorkspaces(); | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| function _loadDefaultStylesheet() { | ||||
|     if (!sessionMode.isPrimary) | ||||
|         return; | ||||
| @@ -264,8 +437,7 @@ function loadTheme() { | ||||
|     if (_cssStylesheet != null) | ||||
|         cssStylesheet = _cssStylesheet; | ||||
|  | ||||
|     let theme = new St.Theme ({ application_stylesheet: cssStylesheet, | ||||
|                                 default_stylesheet: _defaultCssStylesheet }); | ||||
|     let theme = new St.Theme ({ application_stylesheet: cssStylesheet }); | ||||
|  | ||||
|     if (previousTheme) { | ||||
|         let customStylesheets = previousTheme.get_custom_stylesheets(); | ||||
|   | ||||
| @@ -1530,7 +1530,11 @@ const MessageTrayContextMenu = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _updateClearSensitivity: function() { | ||||
|         this._clearItem.setSensitive(this._tray.clearableCount > 0); | ||||
|         let sources = this._tray.getSources(); | ||||
|         sources = sources.filter(function(source) { | ||||
|             return !source.trayIcon && !source.isChat && !source.resident; | ||||
|         }); | ||||
|         this._clearItem.setSensitive(sources.length > 0); | ||||
|     }, | ||||
|  | ||||
|     setPosition: function(x, y) { | ||||
| @@ -1553,22 +1557,23 @@ const MessageTray = new Lang.Class({ | ||||
|  | ||||
|         this.actor = new St.Widget({ name: 'message-tray', | ||||
|                                      reactive: true, | ||||
|                                      track_hover: true, | ||||
|                                      layout_manager: new Clutter.BinLayout(), | ||||
|                                      x_expand: true, | ||||
|                                      y_expand: true, | ||||
|                                      y_align: Clutter.ActorAlign.START, | ||||
|                                    }); | ||||
|         this.actor.connect('notify::hover', Lang.bind(this, this._onTrayHoverChanged)); | ||||
|  | ||||
|         this._notificationWidget = new St.Widget({ name: 'notification-container', | ||||
|                                                    reactive: true, | ||||
|                                                    track_hover: true, | ||||
|                                                    y_align: Clutter.ActorAlign.START, | ||||
|                                                    x_align: Clutter.ActorAlign.CENTER, | ||||
|                                                    y_expand: true, | ||||
|                                                    x_expand: true, | ||||
|                                                    layout_manager: new Clutter.BinLayout() }); | ||||
|         this._notificationWidget.connect('key-release-event', Lang.bind(this, this._onNotificationKeyRelease)); | ||||
|         this._notificationWidget.connect('notify::hover', Lang.bind(this, this._onNotificationHoverChanged)); | ||||
|  | ||||
|         this.actor.add_actor(this._notificationWidget); | ||||
|  | ||||
|         this._notificationBin = new St.Bin({ y_expand: true }); | ||||
|         this._notificationBin.set_y_align(Clutter.ActorAlign.START); | ||||
| @@ -1623,25 +1628,24 @@ const MessageTray = new Lang.Class({ | ||||
|                                                      { keybindingMode: Shell.KeyBindingMode.MESSAGE_TRAY }); | ||||
|         this._grabHelper.addActor(this._summaryBoxPointer.actor); | ||||
|         this._grabHelper.addActor(this.actor); | ||||
|         this._grabHelper.addActor(this._notificationWidget); | ||||
|  | ||||
|         Main.layoutManager.connect('keyboard-visible-changed', Lang.bind(this, this._onKeyboardVisibleChanged)); | ||||
|  | ||||
|         this._trayState = State.HIDDEN; | ||||
|         this._traySummoned = false; | ||||
|         this._useLongerNotificationLeftTimeout = false; | ||||
|         this._useLongerTrayLeftTimeout = false; | ||||
|         this._trayLeftTimeoutId = 0; | ||||
|  | ||||
|         // pointerInNotification is sort of a misnomer -- it tracks whether | ||||
|         // pointerInTray is sort of a misnomer -- it tracks whether | ||||
|         // a message tray notification should expand. The value is | ||||
|         // partially driven by the hover state of the notification, but has | ||||
|         // partially driven by the hover state of the tray, but has | ||||
|         // a lot of complex state related to timeouts and the current | ||||
|         // state of the pointer when a notification pops up. | ||||
|         this._pointerInNotification = false; | ||||
|         this._pointerInTray = false; | ||||
|  | ||||
|         // This tracks this._notificationWidget.hover and is used to fizzle | ||||
|         // out non-changing hover notifications in onNotificationHoverChanged. | ||||
|         this._notificationHovered = false; | ||||
|         // This tracks this.actor.hover and is used to fizzle | ||||
|         // out non-changing hover notifications in onTrayHoverChanged. | ||||
|         this._trayHovered = false; | ||||
|  | ||||
|         this._keyboardVisible = false; | ||||
|         this._notificationClosed = false; | ||||
| @@ -1653,29 +1657,23 @@ const MessageTray = new Lang.Class({ | ||||
|         this._desktopCloneState = State.HIDDEN; | ||||
|         this._notificationRemoved = false; | ||||
|         this._reNotifyAfterHideNotification = null; | ||||
|         this._inFullscreen = false; | ||||
|         this._desktopClone = null; | ||||
|         this._inCtrlAltTab = false; | ||||
|  | ||||
|         this.clearableCount = 0; | ||||
|  | ||||
|         this._lightboxes = []; | ||||
|         let lightboxContainers = [global.window_group, | ||||
|                                   Main.layoutManager.overviewGroup]; | ||||
|         for (let i = 0; i < lightboxContainers.length; i++) | ||||
|             this._lightboxes.push(new Lightbox.Lightbox(lightboxContainers[i], | ||||
|                                                         { inhibitEvents: true, | ||||
|                                                           fadeInTime: ANIMATION_TIME, | ||||
|                                                           fadeOutTime: ANIMATION_TIME, | ||||
|                                                           fadeFactor: 0.2 | ||||
|                                                         })); | ||||
|         this._lightbox = new Lightbox.Lightbox(global.overlay_group, | ||||
|                                                { inhibitEvents: true, | ||||
|                                                  fadeInTime: ANIMATION_TIME, | ||||
|                                                  fadeOutTime: ANIMATION_TIME, | ||||
|                                                  fadeFactor: 0.2 | ||||
|                                                }); | ||||
|  | ||||
|         Main.layoutManager.trayBox.add_actor(this.actor); | ||||
|         Main.layoutManager.trayBox.add_actor(this._notificationWidget); | ||||
|         Main.layoutManager.trackChrome(this.actor); | ||||
|         Main.layoutManager.trackChrome(this._notificationWidget); | ||||
|         Main.layoutManager.trackChrome(this._closeButton); | ||||
|  | ||||
|         global.screen.connect('in-fullscreen-changed', Lang.bind(this, this._updateState)); | ||||
|         Main.layoutManager.connect('fullscreen-changed', Lang.bind(this, this._updateState)); | ||||
|         Main.layoutManager.connect('hot-corners-changed', Lang.bind(this, this._hotCornersChanged)); | ||||
|  | ||||
|         // If the overview shows or hides while we're in | ||||
| @@ -1749,7 +1747,7 @@ const MessageTray = new Lang.Class({ | ||||
|         let [x, y, mask] = global.get_pointer(); | ||||
|         this._contextMenu.setPosition(Math.round(x), Math.round(y)); | ||||
|         this._grabHelper.grab({ actor: this._contextMenu.actor, | ||||
|                                 modal: true, | ||||
|                                 grabFocus: true, | ||||
|                                 onUngrab: Lang.bind(this, function () { | ||||
|                                     this._contextMenu.close(BoxPointer.PopupAnimation.FULL); | ||||
|                                 }) | ||||
| @@ -1795,12 +1793,12 @@ const MessageTray = new Lang.Class({ | ||||
|                            y == monitor.y + monitor.height - 1); | ||||
|         if (shouldDwell) { | ||||
|             // We only set up dwell timeout when the user is not hovering over the tray | ||||
|             // (!this._notificationHovered). This avoids bringing up the message tray after the | ||||
|             // (!this.actor.hover). This avoids bringing up the message tray after the | ||||
|             // user clicks on a notification with the pointer on the bottom pixel | ||||
|             // of the monitor. The _trayDwelling variable is used so that we only try to | ||||
|             // fire off one tray dwell - if it fails (because, say, the user has the mouse down), | ||||
|             // we don't try again until the user moves the mouse up and down again. | ||||
|             if (!this._trayDwelling && !this._notificationHovered && this._trayDwellTimeoutId == 0) { | ||||
|             if (!this._trayDwelling && !this.actor.hover && this._trayDwellTimeoutId == 0) { | ||||
|                 // Save the interaction timestamp so we can detect user input | ||||
|                 let focusWindow = global.display.focus_window; | ||||
|                 this._trayDwellUserTime = focusWindow ? focusWindow.user_time : 0; | ||||
| @@ -1898,9 +1896,6 @@ const MessageTray = new Lang.Class({ | ||||
|             this._summary.insert_child_at_index(summaryItem.actor, this._chatSummaryItemsCount); | ||||
|         } | ||||
|  | ||||
|         if (!source.trayIcon && !source.isChat && !source.resident) | ||||
|             this.clearableCount++; | ||||
|  | ||||
|         this._sources.set(source, obj); | ||||
|  | ||||
|         obj.notifyId = source.connect('notify', Lang.bind(this, this._onNotify)); | ||||
| @@ -1942,9 +1937,6 @@ const MessageTray = new Lang.Class({ | ||||
|         if (source.isChat) | ||||
|             this._chatSummaryItemsCount--; | ||||
|  | ||||
|         if (!source.trayIcon && !source.isChat && !source.resident) | ||||
|             this.clearableCount--; | ||||
|  | ||||
|         source.disconnect(obj.notifyId); | ||||
|         source.disconnect(obj.destroyId); | ||||
|         source.disconnect(obj.mutedChangedId); | ||||
| @@ -2000,6 +1992,7 @@ const MessageTray = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         let index = this._notificationQueue.indexOf(notification); | ||||
|         notification.destroy(); | ||||
|         if (index != -1) | ||||
|             this._notificationQueue.splice(index, 1); | ||||
|     }, | ||||
| @@ -2028,6 +2021,7 @@ const MessageTray = new Lang.Class({ | ||||
|  | ||||
|     hide: function() { | ||||
|         this._traySummoned = false; | ||||
|         this.actor.set_hover(false); | ||||
|         this._updateState(); | ||||
|     }, | ||||
|  | ||||
| @@ -2094,21 +2088,25 @@ const MessageTray = new Lang.Class({ | ||||
|             this._grabHelper.addActor(corner.actor); | ||||
|     }, | ||||
|  | ||||
|     _onNotificationHoverChanged: function() { | ||||
|         if (this._notificationWidget.hover == this._notificationHovered) | ||||
|     _onTrayHoverChanged: function() { | ||||
|         if (this.actor.hover == this._trayHovered) | ||||
|             return; | ||||
|  | ||||
|         this._notificationHovered = this._notificationWidget.hover; | ||||
|         if (this._notificationHovered) { | ||||
|         this._trayHovered = this.actor.hover; | ||||
|         if (this._trayHovered) { | ||||
|             // No dwell inside notifications at the bottom of the screen | ||||
|             this._cancelTrayDwell(); | ||||
|  | ||||
|             this._useLongerNotificationLeftTimeout = false; | ||||
|             if (this._notificationLeftTimeoutId) { | ||||
|                 Mainloop.source_remove(this._notificationLeftTimeoutId); | ||||
|                 this._notificationLeftTimeoutId = 0; | ||||
|                 this._notificationLeftMouseX = -1; | ||||
|                 this._notificationLeftMouseY = -1; | ||||
|             // Don't do anything if the one pixel area at the bottom is hovered over while the tray is hidden. | ||||
|             if (this._trayState == State.HIDDEN && this._notificationState == State.HIDDEN) | ||||
|                 return; | ||||
|  | ||||
|             this._useLongerTrayLeftTimeout = false; | ||||
|             if (this._trayLeftTimeoutId) { | ||||
|                 Mainloop.source_remove(this._trayLeftTimeoutId); | ||||
|                 this._trayLeftTimeoutId = 0; | ||||
|                 this._trayLeftMouseX = -1; | ||||
|                 this._trayLeftMouseY = -1; | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
| @@ -2117,32 +2115,32 @@ const MessageTray = new Lang.Class({ | ||||
|                     global.stage.get_actor_at_pos(Clutter.PickMode.ALL, this._showNotificationMouseX, this._showNotificationMouseY); | ||||
|                 this._showNotificationMouseX = -1; | ||||
|                 this._showNotificationMouseY = -1; | ||||
|                 // Don't set this._pointerInNotification to true if the pointer was initially in the area where the notification | ||||
|                 // Don't set this._pointerInTray to true if the pointer was initially in the area where the notification | ||||
|                 // popped up. That way we will not be expanding notifications that happen to pop up over the pointer | ||||
|                 // automatically. Instead, the user is able to expand the notification by mousing away from it and then | ||||
|                 // mousing back in. Because this is an expected action, we set the boolean flag that indicates that a longer | ||||
|                 // timeout should be used before popping down the notification. | ||||
|                 if (this.actor.contains(actorAtShowNotificationPosition)) { | ||||
|                     this._useLongerNotificationLeftTimeout = true; | ||||
|                     this._useLongerTrayLeftTimeout = true; | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             this._pointerInNotification = true; | ||||
|             this._pointerInTray = true; | ||||
|             this._updateState(); | ||||
|         } else { | ||||
|             // We record the position of the mouse the moment it leaves the tray. These coordinates are used in | ||||
|             // this._onNotificationLeftTimeout() to determine if the mouse has moved far enough during the initial timeout for us | ||||
|             // this._onTrayLeftTimeout() to determine if the mouse has moved far enough during the initial timeout for us | ||||
|             // to consider that the user intended to leave the tray and therefore hide the tray. If the mouse is still | ||||
|             // close to its previous position, we extend the timeout once. | ||||
|             let [x, y, mods] = global.get_pointer(); | ||||
|             this._notificationLeftMouseX = x; | ||||
|             this._notificationLeftMouseY = y; | ||||
|             this._trayLeftMouseX = x; | ||||
|             this._trayLeftMouseY = y; | ||||
|  | ||||
|             // We wait just a little before hiding the message tray in case the user quickly moves the mouse back into it. | ||||
|             // We wait for a longer period if the notification popped up where the mouse pointer was already positioned. | ||||
|             // That gives the user more time to mouse away from the notification and mouse back in in order to expand it. | ||||
|             let timeout = this._useLongerNotificationLeftTimeout ? LONGER_HIDE_TIMEOUT * 1000 : HIDE_TIMEOUT * 1000; | ||||
|             this._notificationLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onNotificationLeftTimeout)); | ||||
|             let timeout = this._useLongerTrayLeftTimeout ? LONGER_HIDE_TIMEOUT * 1000 : HIDE_TIMEOUT * 1000; | ||||
|             this._trayLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onTrayLeftTimeout)); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -2166,22 +2164,22 @@ const MessageTray = new Lang.Class({ | ||||
|         this._updateState(); | ||||
|     }, | ||||
|  | ||||
|     _onNotificationLeftTimeout: function() { | ||||
|     _onTrayLeftTimeout: function() { | ||||
|         let [x, y, mods] = global.get_pointer(); | ||||
|         // We extend the timeout once if the mouse moved no further than MOUSE_LEFT_ACTOR_THRESHOLD to either side or up. | ||||
|         // We don't check how far down the mouse moved because any point above the tray, but below the exit coordinate, | ||||
|         // is close to the tray. | ||||
|         if (this._notificationLeftMouseX > -1 && | ||||
|             y > this._notificationLeftMouseY - MOUSE_LEFT_ACTOR_THRESHOLD && | ||||
|             x < this._notificationLeftMouseX + MOUSE_LEFT_ACTOR_THRESHOLD && | ||||
|             x > this._notificationLeftMouseX - MOUSE_LEFT_ACTOR_THRESHOLD) { | ||||
|             this._notificationLeftMouseX = -1; | ||||
|             this._notificationLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT * 1000, | ||||
|                                                              Lang.bind(this, this._onNotificationLeftTimeout)); | ||||
|         if (this._trayLeftMouseX > -1 && | ||||
|             y > this._trayLeftMouseY - MOUSE_LEFT_ACTOR_THRESHOLD && | ||||
|             x < this._trayLeftMouseX + MOUSE_LEFT_ACTOR_THRESHOLD && | ||||
|             x > this._trayLeftMouseX - MOUSE_LEFT_ACTOR_THRESHOLD) { | ||||
|             this._trayLeftMouseX = -1; | ||||
|             this._trayLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT * 1000, | ||||
|                                                              Lang.bind(this, this._onTrayLeftTimeout)); | ||||
|         } else { | ||||
|             this._notificationLeftTimeoutId = 0; | ||||
|             this._useLongerNotificationLeftTimeout = false; | ||||
|             this._pointerInNotification = false; | ||||
|             this._trayLeftTimeoutId = 0; | ||||
|             this._useLongerTrayLeftTimeout = false; | ||||
|             this._pointerInTray = false; | ||||
|             this._updateNotificationTimeout(0); | ||||
|             this._updateState(); | ||||
|         } | ||||
| @@ -2189,7 +2187,7 @@ const MessageTray = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _escapeTray: function() { | ||||
|         this._pointerInNotification = false; | ||||
|         this._pointerInTray = false; | ||||
|         this._traySummoned = false; | ||||
|         this._setClickedSummaryItem(null); | ||||
|         this._updateNotificationTimeout(0); | ||||
| @@ -2198,33 +2196,26 @@ const MessageTray = new Lang.Class({ | ||||
|  | ||||
|     // All of the logic for what happens when occurs here; the various | ||||
|     // event handlers merely update variables such as | ||||
|     // 'this._pointerInNotification', 'this._traySummoned', etc, and | ||||
|     // 'this._pointerInTray', 'this._traySummoned', etc, and | ||||
|     // _updateState() figures out what (if anything) needs to be done | ||||
|     // at the present time. | ||||
|     _updateState: function() { | ||||
|         // Notifications | ||||
|         let notificationQueue = this._notificationQueue.filter(function(n) { | ||||
|             return !n.acknowledged; | ||||
|         }); | ||||
|         let hasNotifications = Main.sessionMode.hasNotifications; | ||||
|  | ||||
|         this._notificationQueue = notificationQueue; | ||||
|         let notificationQueue = this._notificationQueue; | ||||
|         let notificationUrgent = notificationQueue.length > 0 && notificationQueue[0].urgency == Urgency.CRITICAL; | ||||
|         let notificationForFeedback = notificationQueue.length > 0 && notificationQueue[0].forFeedback; | ||||
|         let notificationsLimited = this._busy || Main.layoutManager.bottomMonitor.inFullscreen; | ||||
|         let notificationsPending = notificationQueue.length > 0 && (!notificationsLimited || notificationUrgent || notificationForFeedback) && hasNotifications; | ||||
|         let notificationsPending = notificationQueue.length > 0 && (!notificationsLimited || notificationUrgent || notificationForFeedback) && Main.sessionMode.hasNotifications; | ||||
|         let nextNotification = notificationQueue.length > 0 ? notificationQueue[0] : null; | ||||
|         let notificationPinned = this._pointerInNotification && !this._notificationRemoved; | ||||
|         let notificationPinned = this._pointerInTray && !this._notificationRemoved; | ||||
|         let notificationExpanded = this._notification && this._notification.expanded; | ||||
|         let notificationExpired = this._notificationTimeoutId == 0 && | ||||
|                                   !(this._notification && this._notification.urgency == Urgency.CRITICAL) && | ||||
|                                   !(this._notification && this._notification.focused) && | ||||
|                                   !this._pointerInNotification; | ||||
|         let notificationLockedOut = !hasNotifications && this._notification; | ||||
|         let notificationMustClose = (this._notificationRemoved || notificationLockedOut || | ||||
|                                      (notificationExpired && this._userActiveWhileNotificationShown) || | ||||
|                                      this._notificationClosed || this._traySummoned); | ||||
|         let canShowNotification = notificationsPending && this._trayState == State.HIDDEN && !this._traySummoned; | ||||
|                                   !this._pointerInTray; | ||||
|         let notificationLockedOut = !Main.sessionMode.hasNotifications && this._notification; | ||||
|         let notificationMustClose = this._notificationRemoved || notificationLockedOut || (notificationExpired && this._userActiveWhileNotificationShown) || this._notificationClosed; | ||||
|         let canShowNotification = notificationsPending && this._trayState == State.HIDDEN; | ||||
|  | ||||
|         if (this._notificationState == State.HIDDEN) { | ||||
|             if (canShowNotification) | ||||
| @@ -2238,6 +2229,12 @@ const MessageTray = new Lang.Class({ | ||||
|                 this._ensureNotificationFocused(); | ||||
|         } | ||||
|  | ||||
|         let notificationsVisible = this._notificationState != State.HIDDEN; | ||||
|         let notificationsDone = !notificationsVisible && !notificationsPending; | ||||
|  | ||||
|         let mustHideTray = ((notificationsPending && notificationUrgent) | ||||
|                            || notificationsVisible || !Main.sessionMode.hasNotifications); | ||||
|  | ||||
|         // Summary notification | ||||
|         let haveClickedSummaryItem = this._clickedSummaryItem != null; | ||||
|         let summarySourceIsMainNotificationSource = (haveClickedSummaryItem && this._notification && | ||||
| @@ -2245,15 +2242,10 @@ const MessageTray = new Lang.Class({ | ||||
|         let canShowSummaryBoxPointer = this._trayState == State.SHOWN; | ||||
|         // We only have sources with empty notification stacks for legacy tray icons. Currently, we never attempt | ||||
|         // to show notifications for legacy tray icons, but this would be necessary if we did. | ||||
|         let requestedNotificationStackIsEmpty = (haveClickedSummaryItem && | ||||
|                                                  this._clickedSummaryItemMouseButton == 1 && | ||||
|                                                  this._clickedSummaryItem.source.notifications.length == 0); | ||||
|         let wrongSummaryNotificationStack = (haveClickedSummaryItem && | ||||
|                                              this._clickedSummaryItemMouseButton == 1 && | ||||
|         let requestedNotificationStackIsEmpty = (this._clickedSummaryItemMouseButton == 1 && this._clickedSummaryItem.source.notifications.length == 0); | ||||
|         let wrongSummaryNotificationStack = (this._clickedSummaryItemMouseButton == 1 && | ||||
|                                              this._summaryBoxPointer.bin.child != this._clickedSummaryItem.notificationStackWidget); | ||||
|         let wrongSummaryRightClickMenu = (haveClickedSummaryItem && | ||||
|                                           this._clickedSummaryItemMouseButton == 3 && | ||||
|                                           this._clickedSummaryItem.rightClickMenu != null && | ||||
|         let wrongSummaryRightClickMenu = (this._clickedSummaryItemMouseButton == 3 && | ||||
|                                           this._summaryBoxPointer.bin.child != this._clickedSummaryItem.rightClickMenu); | ||||
|         let wrongSummaryBoxPointer = (haveClickedSummaryItem && | ||||
|                                       (wrongSummaryNotificationStack || wrongSummaryRightClickMenu)); | ||||
| @@ -2262,7 +2254,7 @@ const MessageTray = new Lang.Class({ | ||||
|             if (haveClickedSummaryItem && !summarySourceIsMainNotificationSource && canShowSummaryBoxPointer && !requestedNotificationStackIsEmpty) | ||||
|                 this._showSummaryBoxPointer(); | ||||
|         } else if (this._summaryBoxPointerState == State.SHOWN) { | ||||
|             if (!haveClickedSummaryItem || !canShowSummaryBoxPointer || wrongSummaryBoxPointer || !hasNotifications) { | ||||
|             if (!haveClickedSummaryItem || !canShowSummaryBoxPointer || wrongSummaryBoxPointer || mustHideTray) { | ||||
|                 this._hideSummaryBoxPointer(); | ||||
|                 if (wrongSummaryBoxPointer) | ||||
|                     this._showSummaryBoxPointer(); | ||||
| @@ -2272,7 +2264,7 @@ const MessageTray = new Lang.Class({ | ||||
|         // Tray itself | ||||
|         let trayIsVisible = (this._trayState == State.SHOWING || | ||||
|                              this._trayState == State.SHOWN); | ||||
|         let trayShouldBeVisible = this._traySummoned && !this._keyboardVisible && hasNotifications; | ||||
|         let trayShouldBeVisible = this._traySummoned && !this._keyboardVisible && !mustHideTray; | ||||
|         if (!trayIsVisible && trayShouldBeVisible) | ||||
|             trayShouldBeVisible = this._showTray(); | ||||
|         else if (trayIsVisible && !trayShouldBeVisible) | ||||
| @@ -2329,8 +2321,7 @@ const MessageTray = new Lang.Class({ | ||||
|                       transition: 'easeOutQuad' | ||||
|                     }); | ||||
|  | ||||
|         for (let i = 0; i < this._lightboxes.length; i++) | ||||
|             this._lightboxes[i].show(); | ||||
|         this._lightbox.show(); | ||||
|  | ||||
|         return true; | ||||
|     }, | ||||
| @@ -2353,7 +2344,7 @@ const MessageTray = new Lang.Class({ | ||||
|  | ||||
|         if (this._desktopClone) | ||||
|             this._desktopClone.destroy(); | ||||
|         let cloneSource = Main.overview.visible ? Main.layoutManager.overviewGroup : global.window_group; | ||||
|         let cloneSource = Main.overview.visible ? global.overlay_group : global.window_group; | ||||
|         this._desktopClone = new Clutter.Clone({ source: cloneSource, | ||||
|                                                  clip: new Clutter.Geometry(this._bottomMonitorGeometry) }); | ||||
|         Main.uiGroup.insert_child_above(this._desktopClone, cloneSource); | ||||
| @@ -2385,8 +2376,7 @@ const MessageTray = new Lang.Class({ | ||||
|         // which would happen if GrabHelper ungrabbed for us. | ||||
|         // This is a no-op in that case. | ||||
|         this._grabHelper.ungrab({ actor: this.actor }); | ||||
|         for (let i = 0; i < this._lightboxes.length; i++) | ||||
|             this._lightboxes[i].hide(); | ||||
|         this._lightbox.hide(); | ||||
|     }, | ||||
|  | ||||
|     _hideDesktopClone: function() { | ||||
| @@ -2435,7 +2425,7 @@ const MessageTray = new Lang.Class({ | ||||
|         let [x, y, mods] = global.get_pointer(); | ||||
|         // We save the position of the mouse at the time when we started showing the notification | ||||
|         // in order to determine if the notification popped up under it. We make that check if | ||||
|         // the user starts moving the mouse and _onNotificationHoverChanged() gets called. We don't | ||||
|         // the user starts moving the mouse and _onTrayHoverChanged() gets called. We don't | ||||
|         // expand the notification if it just happened to pop up under the mouse unless the user | ||||
|         // explicitly mouses away from it and then mouses back in. | ||||
|         this._showNotificationMouseX = x; | ||||
| @@ -2497,13 +2487,13 @@ const MessageTray = new Lang.Class({ | ||||
|  | ||||
|     _notificationTimeout: function() { | ||||
|         let [x, y, mods] = global.get_pointer(); | ||||
|         if (y > this._lastSeenMouseY + 10 && !this._notificationHovered) { | ||||
|         if (y > this._lastSeenMouseY + 10 && !this.actor.hover) { | ||||
|             // The mouse is moving towards the notification, so don't | ||||
|             // hide it yet. (We just create a new timeout (and destroy | ||||
|             // the old one) each time because the bookkeeping is | ||||
|             // simpler.) | ||||
|             this._updateNotificationTimeout(1000); | ||||
|         } else if (this._useLongerNotificationLeftTimeout && !this._notificationLeftTimeoutId && | ||||
|         } else if (this._useLongerTrayLeftTimeout && !this._trayLeftTimeoutId && | ||||
|                   (x != this._lastSeenMouseX || y != this._lastSeenMouseY)) { | ||||
|             // Refresh the timeout if the notification originally | ||||
|             // popped up under the pointer, and the pointer is hovering | ||||
| @@ -2547,12 +2537,12 @@ const MessageTray = new Lang.Class({ | ||||
|             this._notificationUnfocusedId = 0; | ||||
|         } | ||||
|  | ||||
|         this._useLongerNotificationLeftTimeout = false; | ||||
|         if (this._notificationLeftTimeoutId) { | ||||
|             Mainloop.source_remove(this._notificationLeftTimeoutId); | ||||
|             this._notificationLeftTimeoutId = 0; | ||||
|             this._notificationLeftMouseX = -1; | ||||
|             this._notificationLeftMouseY = -1; | ||||
|         this._useLongerTrayLeftTimeout = false; | ||||
|         if (this._trayLeftTimeoutId) { | ||||
|             Mainloop.source_remove(this._trayLeftTimeoutId); | ||||
|             this._trayLeftTimeoutId = 0; | ||||
|             this._trayLeftMouseX = -1; | ||||
|             this._trayLeftMouseY = -1; | ||||
|         } | ||||
|  | ||||
|         if (this._notificationRemoved) { | ||||
| @@ -2582,9 +2572,14 @@ const MessageTray = new Lang.Class({ | ||||
|         if (notification.isTransient) | ||||
|             notification.destroy(NotificationDestroyedReason.EXPIRED); | ||||
|  | ||||
|         this._closeButton.hide(); | ||||
|         this._pointerInNotification = false; | ||||
|         this._notificationRemoved = false; | ||||
|         this._closeButton.hide(); | ||||
|         this._pointerInTray = false; | ||||
|  | ||||
|         // Clutter will send a leave-event the next time the mouse | ||||
|         // moves, but we need to set this here now to update the | ||||
|         // state machine. | ||||
|         this.actor.hover = false; | ||||
|         this._notificationBin.child = null; | ||||
|         this._notificationWidget.hide(); | ||||
|     }, | ||||
| @@ -2597,16 +2592,16 @@ const MessageTray = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _expandNotification: function(autoExpanding) { | ||||
|         // Don't focus notifications that are auto-expanding. | ||||
|         if (!autoExpanding) | ||||
|             this._ensureNotificationFocused(); | ||||
|  | ||||
|         if (!this._notificationExpandedId) | ||||
|             this._notificationExpandedId = | ||||
|                 this._notification.connect('expanded', | ||||
|                                            Lang.bind(this, this._onNotificationExpanded)); | ||||
|         // Don't animate changes in notifications that are auto-expanding. | ||||
|         this._notification.expand(!autoExpanding); | ||||
|  | ||||
|         // Don't focus notifications that are auto-expanding. | ||||
|         if (!autoExpanding) | ||||
|             this._ensureNotificationFocused(); | ||||
|     }, | ||||
|  | ||||
|     _onNotificationExpanded: function() { | ||||
| @@ -2644,37 +2639,38 @@ const MessageTray = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _showSummaryBoxPointer: function() { | ||||
|         let child; | ||||
|         let summaryItem = this._clickedSummaryItem; | ||||
|         if (this._clickedSummaryItemMouseButton == 1) { | ||||
|             // Acknowledge all our notifications | ||||
|             summaryItem.source.notifications.forEach(function(n) { n.acknowledged = true; }); | ||||
|  | ||||
|             child = summaryItem.notificationStackWidget; | ||||
|  | ||||
|             let closeButton = summaryItem.closeButton; | ||||
|             closeButton.show(); | ||||
|             this._summaryBoxPointerCloseClickedId = closeButton.connect('clicked', Lang.bind(this, this._hideSummaryBoxPointer)); | ||||
|             summaryItem.prepareNotificationStackForShowing(); | ||||
|         } else if (this._clickedSummaryItemMouseButton == 3) { | ||||
|             child = summaryItem.rightClickMenu; | ||||
|             this._summaryBoxPointerCloseClickedId = 0; | ||||
|         } | ||||
|  | ||||
|         // If the user clicked the middle mouse button, or the item | ||||
|         // doesn't have a right-click menu, do nothing. | ||||
|         if (!child) | ||||
|             return; | ||||
|  | ||||
|         this._summaryBoxPointerItem = summaryItem; | ||||
|         this._summaryBoxPointerItem = this._clickedSummaryItem; | ||||
|         this._summaryBoxPointerContentUpdatedId = this._summaryBoxPointerItem.connect('content-updated', | ||||
|                                                                                       Lang.bind(this, this._onSummaryBoxPointerContentUpdated)); | ||||
|         this._sourceDoneDisplayingId = this._summaryBoxPointerItem.source.connect('done-displaying-content', | ||||
|                                                                                   Lang.bind(this, this._onSourceDoneDisplayingContent)); | ||||
|  | ||||
|         this._summaryBoxPointer.bin.child = child; | ||||
|         let hasRightClickMenu = this._summaryBoxPointerItem.rightClickMenu != null; | ||||
|         if (this._clickedSummaryItemMouseButton == 1 || !hasRightClickMenu) { | ||||
|             let newQueue = []; | ||||
|             for (let i = 0; i < this._notificationQueue.length; i++) { | ||||
|                 let notification = this._notificationQueue[i]; | ||||
|                 let sameSource = this._summaryBoxPointerItem.source == notification.source; | ||||
|                 if (sameSource) | ||||
|                     notification.acknowledged = true; | ||||
|                 else | ||||
|                     newQueue.push(notification); | ||||
|             } | ||||
|             this._notificationQueue = newQueue; | ||||
|  | ||||
|             this._summaryBoxPointer.bin.child = this._summaryBoxPointerItem.notificationStackWidget; | ||||
|  | ||||
|             let closeButton = this._summaryBoxPointerItem.closeButton; | ||||
|             closeButton.show(); | ||||
|             this._summaryBoxPointerCloseClickedId = closeButton.connect('clicked', Lang.bind(this, this._hideSummaryBoxPointer)); | ||||
|             this._summaryBoxPointerItem.prepareNotificationStackForShowing(); | ||||
|         } else if (this._clickedSummaryItemMouseButton == 3) { | ||||
|             this._summaryBoxPointer.bin.child = this._clickedSummaryItem.rightClickMenu; | ||||
|             this._summaryBoxPointerCloseClickedId = 0; | ||||
|         } | ||||
|  | ||||
|         this._grabHelper.grab({ actor: this._summaryBoxPointer.bin.child, | ||||
|                                 modal: true, | ||||
|                                 grabFocus: true, | ||||
|                                 onUngrab: Lang.bind(this, this._onSummaryBoxPointerUngrabbed) }); | ||||
|  | ||||
|         this._summaryBoxPointer.actor.opacity = 0; | ||||
| @@ -2783,14 +2779,17 @@ const MessageTray = new Lang.Class({ | ||||
|         this._summaryBoxPointerState = State.HIDDEN; | ||||
|         this._summaryBoxPointer.bin.child = null; | ||||
|  | ||||
|         let sourceNotificationStackDoneShowing = null; | ||||
|         if (doneShowingNotificationStack) { | ||||
|             let source = this._summaryBoxPointerItem.source; | ||||
|  | ||||
|             this._summaryBoxPointerItem.doneShowingNotificationStack(); | ||||
|             this._summaryBoxPointerItem = null; | ||||
|             sourceNotificationStackDoneShowing = this._summaryBoxPointerItem.source; | ||||
|         } | ||||
|  | ||||
|             if (source.isTransient && !this._reNotifyAfterHideNotification) | ||||
|                 source.destroy(NotificationDestroyedReason.EXPIRED); | ||||
|         this._summaryBoxPointerItem = null; | ||||
|  | ||||
|         if (sourceNotificationStackDoneShowing) { | ||||
|             if (sourceNotificationStackDoneShowing.isTransient && !this._reNotifyAfterHideNotification) | ||||
|                 sourceNotificationStackDoneShowing.destroy(NotificationDestroyedReason.EXPIRED); | ||||
|             if (this._reNotifyAfterHideNotification) { | ||||
|                 this._onNotify(this._reNotifyAfterHideNotification.source, this._reNotifyAfterHideNotification); | ||||
|                 this._reNotifyAfterHideNotification = null; | ||||
|   | ||||
| @@ -14,7 +14,6 @@ const Atk = imports.gi.Atk; | ||||
|  | ||||
| const Params = imports.misc.params; | ||||
|  | ||||
| const Animation = imports.ui.animation; | ||||
| const Layout = imports.ui.layout; | ||||
| const Lightbox = imports.ui.lightbox; | ||||
| const Main = imports.ui.main; | ||||
| @@ -23,10 +22,6 @@ const Tweener = imports.ui.tweener; | ||||
| const OPEN_AND_CLOSE_TIME = 0.1; | ||||
| const FADE_OUT_DIALOG_TIME = 1.0; | ||||
|  | ||||
| const WORK_SPINNER_ICON_SIZE = 24; | ||||
| const WORK_SPINNER_ANIMATION_DELAY = 1.0; | ||||
| const WORK_SPINNER_ANIMATION_TIME = 0.3; | ||||
|  | ||||
| const State = { | ||||
|     OPENED: 0, | ||||
|     CLOSED: 1, | ||||
| @@ -70,9 +65,7 @@ const ModalDialog = new Lang.Class({ | ||||
|         this._group.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent)); | ||||
|         this._group.connect('key-release-event', Lang.bind(this, this._onKeyReleaseEvent)); | ||||
|  | ||||
|         this.backgroundStack = new St.Widget({ layout_manager: new Clutter.BinLayout() }); | ||||
|         this._backgroundBin = new St.Bin({ child: this.backgroundStack, | ||||
|                                            x_fill: true, y_fill: true }); | ||||
|         this._backgroundBin = new St.Bin(); | ||||
|         this._monitorConstraint = new Layout.MonitorConstraint(); | ||||
|         this._backgroundBin.add_constraint(this._monitorConstraint); | ||||
|         this._group.add_actor(this._backgroundBin); | ||||
| @@ -88,10 +81,15 @@ const ModalDialog = new Lang.Class({ | ||||
|                                                    { inhibitEvents: true }); | ||||
|             this._lightbox.highlight(this._backgroundBin); | ||||
|  | ||||
|             let stack = new Shell.Stack(); | ||||
|             this._backgroundBin.child = stack; | ||||
|  | ||||
|             this._eventBlocker = new Clutter.Actor({ reactive: true }); | ||||
|             this.backgroundStack.add_actor(this._eventBlocker); | ||||
|             stack.add_actor(this._eventBlocker); | ||||
|             stack.add_actor(this.dialogLayout); | ||||
|         } else { | ||||
|             this._backgroundBin.child = this.dialogLayout; | ||||
|         } | ||||
|         this.backgroundStack.add_actor(this.dialogLayout); | ||||
|  | ||||
|  | ||||
|         this.contentLayout = new St.BoxLayout({ vertical: true }); | ||||
| @@ -112,8 +110,6 @@ const ModalDialog = new Lang.Class({ | ||||
|         this._initialKeyFocus = this.dialogLayout; | ||||
|         this._initialKeyFocusDestroyId = 0; | ||||
|         this._savedKeyFocus = null; | ||||
|  | ||||
|         this._workSpinner = null; | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
| @@ -187,42 +183,6 @@ const ModalDialog = new Lang.Class({ | ||||
|         return button; | ||||
|     }, | ||||
|  | ||||
|     placeSpinner: function(layoutInfo) { | ||||
|         let spinnerIcon = global.datadir + '/theme/process-working.svg'; | ||||
|         this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE); | ||||
|         this._workSpinner.actor.opacity = 0; | ||||
|         this._workSpinner.actor.show(); | ||||
|  | ||||
|         this.buttonLayout.add(this._workSpinner.actor, layoutInfo); | ||||
|     }, | ||||
|  | ||||
|     setWorking: function(working) { | ||||
|         if (!this._workSpinner) | ||||
|             return; | ||||
|  | ||||
|         Tweener.removeTweens(this._workSpinner.actor); | ||||
|         if (working) { | ||||
|             this._workSpinner.play(); | ||||
|             Tweener.addTween(this._workSpinner.actor, | ||||
|                              { opacity: 255, | ||||
|                                delay: WORK_SPINNER_ANIMATION_DELAY, | ||||
|                                time: WORK_SPINNER_ANIMATION_TIME, | ||||
|                                transition: 'linear' | ||||
|                              }); | ||||
|         } else { | ||||
|             Tweener.addTween(this._workSpinner.actor, | ||||
|                              { opacity: 0, | ||||
|                                time: WORK_SPINNER_ANIMATION_TIME, | ||||
|                                transition: 'linear', | ||||
|                                onCompleteScope: this, | ||||
|                                onComplete: function() { | ||||
|                                    if (this._workSpinner) | ||||
|                                        this._workSpinner.stop(); | ||||
|                                } | ||||
|                              }); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _onKeyPressEvent: function(object, event) { | ||||
|         this._pressedKey = event.get_key_symbol(); | ||||
|     }, | ||||
|   | ||||
| @@ -8,7 +8,6 @@ const Layout = imports.ui.layout; | ||||
| const Main = imports.ui.main; | ||||
| const Mainloop = imports.mainloop; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const Meta = imports.gi.Meta; | ||||
|  | ||||
| const HIDE_TIMEOUT = 1500; | ||||
| const FADE_TIME = 0.1; | ||||
| @@ -72,7 +71,6 @@ const OsdWindow = new Lang.Class({ | ||||
|     Name: 'OsdWindow', | ||||
|  | ||||
|     _init: function() { | ||||
|         this._popupSize = 0; | ||||
|         this.actor = new St.Widget({ x_expand: true, | ||||
|                                      y_expand: true, | ||||
|                                      x_align: Clutter.ActorAlign.CENTER, | ||||
| @@ -82,15 +80,6 @@ const OsdWindow = new Lang.Class({ | ||||
|                                        vertical: true }); | ||||
|         this.actor.add_actor(this._box); | ||||
|  | ||||
|         this._box.connect('style-changed', Lang.bind(this, this._onStyleChanged)); | ||||
|         this._box.connect('notify::height', Lang.bind(this, | ||||
|             function() { | ||||
|                 Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, | ||||
|                     function() { | ||||
|                         this._box.width = this._box.height; | ||||
|                     })); | ||||
|             })); | ||||
|  | ||||
|         this._icon = new St.Icon(); | ||||
|         this._box.add(this._icon, { expand: true }); | ||||
|  | ||||
| @@ -107,7 +96,7 @@ const OsdWindow = new Lang.Class({ | ||||
|                                    Lang.bind(this, this._monitorsChanged)); | ||||
|         this._monitorsChanged(); | ||||
|  | ||||
|         Main.uiGroup.add_child(this.actor); | ||||
|         Main.layoutManager.addChrome(this.actor, { affectsInputRegion: false }); | ||||
|     }, | ||||
|  | ||||
|     setIcon: function(icon) { | ||||
| @@ -136,10 +125,8 @@ const OsdWindow = new Lang.Class({ | ||||
|             return; | ||||
|  | ||||
|         if (!this.actor.visible) { | ||||
|             Meta.disable_unredirect_for_screen(global.screen); | ||||
|             this.actor.show(); | ||||
|             this.actor.opacity = 0; | ||||
|             this.actor.get_parent().set_child_above_sibling(this.actor, null); | ||||
|  | ||||
|             Tweener.addTween(this.actor, | ||||
|                              { opacity: 255, | ||||
| @@ -158,20 +145,16 @@ const OsdWindow = new Lang.Class({ | ||||
|             return; | ||||
|  | ||||
|         Mainloop.source_remove(this._hideTimeoutId); | ||||
|         this._hideTimeoutId = 0; | ||||
|         this._hide(); | ||||
|     }, | ||||
|  | ||||
|     _hide: function() { | ||||
|         this._hideTimeoutId = 0; | ||||
|         Tweener.addTween(this.actor, | ||||
|                          { opacity: 0, | ||||
|                            time: FADE_TIME, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            onComplete: Lang.bind(this, function() { | ||||
|                               this._reset(); | ||||
|                               Meta.enable_unredirect_for_screen(global.screen); | ||||
|                            }) | ||||
|                          }); | ||||
|                            onComplete: Lang.bind(this, this._reset) }); | ||||
|     }, | ||||
|  | ||||
|     _reset: function() { | ||||
| @@ -186,25 +169,11 @@ const OsdWindow = new Lang.Class({ | ||||
|         let scalew = monitor.width / 640.0; | ||||
|         let scaleh = monitor.height / 480.0; | ||||
|         let scale = Math.min(scalew, scaleh); | ||||
|         this._popupSize = 110 * Math.max(1, scale); | ||||
|         let size = 110 * Math.max(1, scale); | ||||
|  | ||||
|         this._box.set_size(size, size); | ||||
|         this._box.translation_y = monitor.height / 4; | ||||
|         this._icon.icon_size = this._popupSize / 2; | ||||
|         this._box.style_changed(); | ||||
|     }, | ||||
|  | ||||
|     _onStyleChanged: function() { | ||||
|         let themeNode = this._box.get_theme_node(); | ||||
|         let horizontalPadding = themeNode.get_horizontal_padding(); | ||||
|         let verticalPadding = themeNode.get_vertical_padding(); | ||||
|         let topBorder = themeNode.get_border_width(St.Side.TOP); | ||||
|         let bottomBorder = themeNode.get_border_width(St.Side.BOTTOM); | ||||
|         let leftBorder = themeNode.get_border_width(St.Side.LEFT); | ||||
|         let rightBorder = themeNode.get_border_width(St.Side.RIGHT); | ||||
|  | ||||
|         let minWidth = this._popupSize - verticalPadding - leftBorder - rightBorder; | ||||
|         let minHeight = this._popupSize - horizontalPadding - topBorder - bottomBorder; | ||||
|  | ||||
|         this._box.style = 'min-height: %dpx;'.format(Math.max(minWidth, minHeight)); | ||||
|         this._icon.icon_size = size / 2; | ||||
|     } | ||||
| }); | ||||
|   | ||||
| @@ -11,6 +11,7 @@ const Shell = imports.gi.Shell; | ||||
| const Gdk = imports.gi.Gdk; | ||||
|  | ||||
| const Background = imports.ui.background; | ||||
| const Dash = imports.ui.dash; | ||||
| const DND = imports.ui.dnd; | ||||
| const LayoutManager = imports.ui.layout; | ||||
| const Main = imports.ui.main; | ||||
| @@ -19,6 +20,7 @@ const OverviewControls = imports.ui.overviewControls; | ||||
| const Panel = imports.ui.panel; | ||||
| const Params = imports.misc.params; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const ViewSelector = imports.ui.viewSelector; | ||||
| const WorkspaceThumbnail = imports.ui.workspaceThumbnail; | ||||
|  | ||||
| // Time for initial animation going into Overview mode | ||||
| @@ -29,7 +31,7 @@ const ANIMATION_TIME = 0.25; | ||||
| // and don't want the shading animation to get cut off | ||||
| const SHADE_ANIMATION_TIME = .20; | ||||
|  | ||||
| const DND_WINDOW_SWITCH_TIMEOUT = 750; | ||||
| const DND_WINDOW_SWITCH_TIMEOUT = 1250; | ||||
|  | ||||
| const OVERVIEW_ACTIVATION_TIMEOUT = 0.5; | ||||
|  | ||||
| @@ -115,7 +117,7 @@ const Overview = new Lang.Class({ | ||||
|         let monitor = Main.layoutManager.primaryMonitor; | ||||
|  | ||||
|         this._desktopFade = new St.Bin(); | ||||
|         Main.layoutManager.overviewGroup.add_child(this._desktopFade); | ||||
|         global.overlay_group.add_actor(this._desktopFade); | ||||
|  | ||||
|         let layout = new Clutter.BinLayout(); | ||||
|         this._stack = new Clutter.Actor({ layout_manager: layout }); | ||||
| @@ -131,8 +133,17 @@ const Overview = new Lang.Class({ | ||||
|                                             y_expand: true }); | ||||
|         this._overview._delegate = this; | ||||
|  | ||||
|         this._groupStack = new St.Widget({ layout_manager: new Clutter.BinLayout(), | ||||
|                                            x_expand: true, y_expand: true, | ||||
|                                            clip_to_allocation: true }); | ||||
|         this._group = new St.BoxLayout({ name: 'overview-group', | ||||
|                                          reactive: true, | ||||
|                                          x_expand: true, y_expand: true }); | ||||
|         this._groupStack.add_actor(this._group); | ||||
|  | ||||
|         this._backgroundGroup = new Meta.BackgroundGroup(); | ||||
|         Main.layoutManager.overviewGroup.add_child(this._backgroundGroup); | ||||
|         global.overlay_group.add_child(this._backgroundGroup); | ||||
|         this._backgroundGroup.hide(); | ||||
|         this._bgManagers = []; | ||||
|  | ||||
|         this._activationTime = 0; | ||||
| @@ -146,13 +157,14 @@ const Overview = new Lang.Class({ | ||||
|         // During transitions, we raise this to the top to avoid having the overview | ||||
|         // area be reactive; it causes too many issues such as double clicks on | ||||
|         // Dash elements, or mouseover handlers in the workspaces. | ||||
|         this._coverPane = new Clutter.Actor({ opacity: 0, | ||||
|                                               reactive: true }); | ||||
|         this._coverPane = new Clutter.Rectangle({ opacity: 0, | ||||
|                                                   reactive: true }); | ||||
|         this._overview.add_actor(this._coverPane); | ||||
|         this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; })); | ||||
|  | ||||
|         this._stack.hide(); | ||||
|         this._stack.add_actor(this._overview); | ||||
|         Main.layoutManager.overviewGroup.add_child(this._stack); | ||||
|         global.overlay_group.add_actor(this._stack); | ||||
|  | ||||
|         this._coverPane.hide(); | ||||
|  | ||||
| @@ -165,6 +177,7 @@ const Overview = new Lang.Class({ | ||||
|         Main.xdndHandler.connect('drag-end', Lang.bind(this, this._onDragEnd)); | ||||
|  | ||||
|         global.screen.connect('restacked', Lang.bind(this, this._onRestacked)); | ||||
|         this._group.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); | ||||
|  | ||||
|         this._windowSwitchTimeoutId = 0; | ||||
|         this._windowSwitchTimestamp = 0; | ||||
| @@ -263,13 +276,28 @@ const Overview = new Lang.Class({ | ||||
|         this._overview.add_actor(this._searchEntryBin); | ||||
|  | ||||
|         // Create controls | ||||
|         this._controls = new OverviewControls.ControlsManager(this._searchEntry); | ||||
|         this._dash = this._controls.dash; | ||||
|         this._viewSelector = this._controls.viewSelector; | ||||
|         this._dash = new Dash.Dash(); | ||||
|         this._viewSelector = new ViewSelector.ViewSelector(this._searchEntry, | ||||
|                                                            this._dash.showAppsButton); | ||||
|         this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox(); | ||||
|         this._controls = new OverviewControls.ControlsManager(this._dash, | ||||
|                                                               this._thumbnailsBox, | ||||
|                                                               this._viewSelector); | ||||
|  | ||||
|         this._controls.dashActor.x_align = Clutter.ActorAlign.START; | ||||
|         this._controls.dashActor.y_expand = true; | ||||
|  | ||||
|         // Put the dash in a separate layer to allow content to be centered | ||||
|         this._groupStack.add_actor(this._controls.dashActor); | ||||
|  | ||||
|         // Pack all the actors into the group | ||||
|         this._group.add_actor(this._controls.dashSpacer); | ||||
|         this._group.add(this._viewSelector.actor, { x_fill: true, | ||||
|                                                     expand: true }); | ||||
|         this._group.add_actor(this._controls.thumbnailsActor); | ||||
|  | ||||
|         // Add our same-line elements after the search entry | ||||
|         this._overview.add(this._controls.actor, { y_fill: true, expand: true }); | ||||
|         this._controls.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); | ||||
|         this._overview.add(this._groupStack, { y_fill: true, expand: true }); | ||||
|  | ||||
|         this._stack.add_actor(this._controls.indicatorActor); | ||||
|  | ||||
| @@ -433,7 +461,6 @@ const Overview = new Lang.Class({ | ||||
|  | ||||
|     beginItemDrag: function(source) { | ||||
|         this.emit('item-drag-begin'); | ||||
|         this._inDrag = true; | ||||
|     }, | ||||
|  | ||||
|     cancelledItemDrag: function(source) { | ||||
| @@ -442,12 +469,10 @@ const Overview = new Lang.Class({ | ||||
|  | ||||
|     endItemDrag: function(source) { | ||||
|         this.emit('item-drag-end'); | ||||
|         this._inDrag = false; | ||||
|     }, | ||||
|  | ||||
|     beginWindowDrag: function(source) { | ||||
|         this.emit('window-drag-begin'); | ||||
|         this._inDrag = true; | ||||
|     }, | ||||
|  | ||||
|     cancelledWindowDrag: function(source) { | ||||
| @@ -456,31 +481,24 @@ const Overview = new Lang.Class({ | ||||
|  | ||||
|     endWindowDrag: function(source) { | ||||
|         this.emit('window-drag-end'); | ||||
|         this._inDrag = false; | ||||
|     }, | ||||
|  | ||||
|     // show: | ||||
|     // | ||||
|     // Animates the overview visible and grabs mouse and keyboard input | ||||
|     show: function() { | ||||
|     show : function() { | ||||
|         if (this.isDummy) | ||||
|             return; | ||||
|         if (this._shown) | ||||
|             return; | ||||
|         this._shown = true; | ||||
|  | ||||
|         if (!this._syncGrab()) | ||||
|         if (!this._syncInputMode()) | ||||
|             return; | ||||
|  | ||||
|         Main.layoutManager.showOverview(); | ||||
|         this._animateVisible(); | ||||
|     }, | ||||
|  | ||||
|     focusSearch: function() { | ||||
|         this.show(); | ||||
|         this._searchEntry.grab_key_focus(); | ||||
|     }, | ||||
|  | ||||
|     fadeInDesktop: function() { | ||||
|             this._desktopFade.opacity = 0; | ||||
|             this._desktopFade.show(); | ||||
| @@ -522,6 +540,8 @@ const Overview = new Lang.Class({ | ||||
|         // | ||||
|         // Disable unredirection while in the overview | ||||
|         Meta.disable_unredirect_for_screen(global.screen); | ||||
|         this._stack.show(); | ||||
|         this._backgroundGroup.show(); | ||||
|         this._viewSelector.show(); | ||||
|  | ||||
|         this._stack.opacity = 0; | ||||
| @@ -562,7 +582,7 @@ const Overview = new Lang.Class({ | ||||
|         this._animateNotVisible(); | ||||
|  | ||||
|         this._shown = false; | ||||
|         this._syncGrab(); | ||||
|         this._syncInputMode(); | ||||
|     }, | ||||
|  | ||||
|     toggle: function() { | ||||
| @@ -584,8 +604,6 @@ const Overview = new Lang.Class({ | ||||
|     shouldToggleByCornerOrButton: function() { | ||||
|         if (this.animationInProgress) | ||||
|             return false; | ||||
|         if (this._inDrag) | ||||
|             return false; | ||||
|         if (this._activationTime == 0 || Date.now() / 1000 - this._activationTime > OVERVIEW_ACTIVATION_TIMEOUT) | ||||
|             return true; | ||||
|         return false; | ||||
| @@ -593,8 +611,8 @@ const Overview = new Lang.Class({ | ||||
|  | ||||
|     //// Private methods //// | ||||
|  | ||||
|     _syncGrab: function() { | ||||
|         // We delay grab changes during animation so that when removing the | ||||
|     _syncInputMode: function() { | ||||
|         // We delay input mode changes during animation so that when removing the | ||||
|         // overview we don't have a problem with the release of a press/release | ||||
|         // going to an application. | ||||
|         if (this.animationInProgress) | ||||
| @@ -612,12 +630,16 @@ const Overview = new Lang.Class({ | ||||
|                         return false; | ||||
|                     } | ||||
|                 } | ||||
|             } else { | ||||
|                 global.stage_input_mode = Shell.StageInputMode.FULLSCREEN; | ||||
|             } | ||||
|         } else { | ||||
|             if (this._modal) { | ||||
|                 Main.popModal(this._overview); | ||||
|                 this._modal = false; | ||||
|             } | ||||
|             else if (global.stage_input_mode == Shell.StageInputMode.FULLSCREEN) | ||||
|                 global.stage_input_mode = Shell.StageInputMode.NORMAL; | ||||
|         } | ||||
|         return true; | ||||
|     }, | ||||
| @@ -656,7 +678,7 @@ const Overview = new Lang.Class({ | ||||
|         if (!this._shown) | ||||
|             this._animateNotVisible(); | ||||
|  | ||||
|         this._syncGrab(); | ||||
|         this._syncInputMode(); | ||||
|         global.sync_pointer(); | ||||
|     }, | ||||
|  | ||||
| @@ -666,19 +688,20 @@ const Overview = new Lang.Class({ | ||||
|  | ||||
|         this._viewSelector.hide(); | ||||
|         this._desktopFade.hide(); | ||||
|         this._coverPane.hide(); | ||||
|         this._backgroundGroup.hide(); | ||||
|         this._stack.hide(); | ||||
|  | ||||
|         this.visible = false; | ||||
|         this.animationInProgress = false; | ||||
|  | ||||
|         this._coverPane.hide(); | ||||
|  | ||||
|         this.emit('hidden'); | ||||
|         // Handle any calls to show* while we were hiding | ||||
|         if (this._shown) | ||||
|             this._animateVisible(); | ||||
|         else | ||||
|             Main.layoutManager.hideOverview(); | ||||
|  | ||||
|         this._syncGrab(); | ||||
|         this._syncInputMode(); | ||||
|  | ||||
|         // Fake a pointer event if requested | ||||
|         if (this._needsFakePointerEvent) { | ||||
|   | ||||
| @@ -1,18 +1,15 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const GObject = imports.gi.GObject; | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Lang = imports.lang; | ||||
| const Meta = imports.gi.Meta; | ||||
| const St = imports.gi.St; | ||||
| const Shell = imports.gi.Shell; | ||||
|  | ||||
| const Dash = imports.ui.dash; | ||||
| const Main = imports.ui.main; | ||||
| const Params = imports.misc.params; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const ViewSelector = imports.ui.viewSelector; | ||||
| const WorkspaceThumbnail = imports.ui.workspaceThumbnail; | ||||
|  | ||||
| const SIDE_CONTROLS_ANIMATION_TIME = 0.16; | ||||
|  | ||||
| @@ -247,7 +244,6 @@ const ThumbnailsSlider = new Lang.Class({ | ||||
|  | ||||
|         Main.layoutManager.connect('monitors-changed', Lang.bind(this, this.updateSlide)); | ||||
|         this.actor.connect('notify::hover', Lang.bind(this, this.updateSlide)); | ||||
|         this._thumbnailsBox.actor.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE); | ||||
|     }, | ||||
|  | ||||
|     _getAlwaysZoomOut: function() { | ||||
| @@ -273,11 +269,6 @@ const ThumbnailsSlider = new Lang.Class({ | ||||
|         return alwaysZoomOut; | ||||
|     }, | ||||
|  | ||||
|     getNonExpandedWidth: function() { | ||||
|         let child = this.actor.get_first_child(); | ||||
|         return child.get_theme_node().get_length('visible-width'); | ||||
|     }, | ||||
|  | ||||
|     getSlide: function() { | ||||
|         if (!this.visible) | ||||
|             return 0; | ||||
| @@ -289,16 +280,18 @@ const ThumbnailsSlider = new Lang.Class({ | ||||
|         let child = this.actor.get_first_child(); | ||||
|         let preferredHeight = child.get_preferred_height(-1)[1]; | ||||
|         let expandedWidth = child.get_preferred_width(preferredHeight)[1]; | ||||
|         let visibleWidth = child.get_theme_node().get_length('visible-width'); | ||||
|  | ||||
|         return this.getNonExpandedWidth() / expandedWidth; | ||||
|         return visibleWidth / expandedWidth; | ||||
|     }, | ||||
|  | ||||
|     getVisibleWidth: function() { | ||||
|         let alwaysZoomOut = this._getAlwaysZoomOut(); | ||||
|         if (alwaysZoomOut) | ||||
|             return this.parent(); | ||||
|         else | ||||
|             return this.getNonExpandedWidth(); | ||||
|  | ||||
|         let child = this.actor.get_first_child(); | ||||
|         return child.get_theme_node().get_length('visible-width'); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -316,10 +309,6 @@ const DashSlider = new Lang.Class({ | ||||
|         // available allocation | ||||
|         this._dash.actor.x_expand = true; | ||||
|         this._dash.actor.y_expand = true; | ||||
|  | ||||
|         this.actor.x_align = Clutter.ActorAlign.START; | ||||
|         this.actor.y_expand = true; | ||||
|  | ||||
|         this.actor.add_actor(this._dash.actor); | ||||
|  | ||||
|         this._dash.connect('icon-size-changed', Lang.bind(this, this.updateSlide)); | ||||
| @@ -490,77 +479,39 @@ const MessagesIndicator = new Lang.Class({ | ||||
| const ControlsManager = new Lang.Class({ | ||||
|     Name: 'ControlsManager', | ||||
|  | ||||
|     _init: function(searchEntry) { | ||||
|         this.dash = new Dash.Dash(); | ||||
|         this._dashSlider = new DashSlider(this.dash); | ||||
|         this._dashSpacer = new DashSpacer(); | ||||
|         this._dashSpacer.setDashActor(this._dashSlider.actor); | ||||
|     _init: function(dash, thumbnails, viewSelector) { | ||||
|         this._dashSlider = new DashSlider(dash); | ||||
|         this.dashActor = this._dashSlider.actor; | ||||
|         this.dashSpacer = new DashSpacer(); | ||||
|         this.dashSpacer.setDashActor(this.dashActor); | ||||
|  | ||||
|         this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox(); | ||||
|         this._thumbnailsSlider = new ThumbnailsSlider(this._thumbnailsBox); | ||||
|         this._thumbnailsSlider = new ThumbnailsSlider(thumbnails); | ||||
|         this.thumbnailsActor = this._thumbnailsSlider.actor; | ||||
|  | ||||
|         this.viewSelector = new ViewSelector.ViewSelector(searchEntry, | ||||
|                                                           this.dash.showAppsButton); | ||||
|         this.viewSelector.connect('page-changed', Lang.bind(this, this._setVisibility)); | ||||
|         this.viewSelector.connect('page-empty', Lang.bind(this, this._onPageEmpty)); | ||||
|  | ||||
|         this._indicator = new MessagesIndicator(this.viewSelector); | ||||
|         this._indicator = new MessagesIndicator(viewSelector); | ||||
|         this.indicatorActor = this._indicator.actor; | ||||
|  | ||||
|         this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(), | ||||
|                                      reactive: true, | ||||
|                                      x_expand: true, y_expand: true, | ||||
|                                      clip_to_allocation: true }); | ||||
|         this._group = new St.BoxLayout({ name: 'overview-group', | ||||
|                                         x_expand: true, y_expand: true }); | ||||
|         this.actor.add_actor(this._group); | ||||
|  | ||||
|         this.actor.add_actor(this._dashSlider.actor); | ||||
|  | ||||
|         this._group.add_actor(this._dashSpacer); | ||||
|         this._group.add(this.viewSelector.actor, { x_fill: true, | ||||
|                                                    expand: true }); | ||||
|         this._group.add_actor(this._thumbnailsSlider.actor); | ||||
|  | ||||
|         this._group.connect('notify::allocation', Lang.bind(this, this._updateWorkspacesGeometry)); | ||||
|         this._viewSelector = viewSelector; | ||||
|         this._viewSelector.connect('page-changed', Lang.bind(this, this._setVisibility)); | ||||
|         this._viewSelector.connect('page-empty', Lang.bind(this, this._onPageEmpty)); | ||||
|  | ||||
|         Main.overview.connect('showing', Lang.bind(this, this._updateSpacerVisibility)); | ||||
|         Main.overview.connect('item-drag-begin', Lang.bind(this, | ||||
|             function() { | ||||
|                 let activePage = this.viewSelector.getActivePage(); | ||||
|                 let activePage = this._viewSelector.getActivePage(); | ||||
|                 if (activePage != ViewSelector.ViewPage.WINDOWS) | ||||
|                     this.viewSelector.fadeHalf(); | ||||
|                     this._viewSelector.fadeHalf(); | ||||
|             })); | ||||
|         Main.overview.connect('item-drag-end', Lang.bind(this, | ||||
|             function() { | ||||
|                 this.viewSelector.fadeIn(); | ||||
|                 this._viewSelector.fadeIn(); | ||||
|             })); | ||||
|         Main.overview.connect('item-drag-cancelled', Lang.bind(this, | ||||
|             function() { | ||||
|                 this.viewSelector.fadeIn(); | ||||
|                 this._viewSelector.fadeIn(); | ||||
|             })); | ||||
|     }, | ||||
|  | ||||
|     _updateWorkspacesGeometry: function() { | ||||
|         let [x, y] = this.actor.get_transformed_position(); | ||||
|         let [width, height] = this.actor.get_transformed_size(); | ||||
|         let geometry = { x: x, y: y, width: width, height: height }; | ||||
|  | ||||
|         let spacing = this.actor.get_theme_node().get_length('spacing'); | ||||
|         let dashWidth = this._dashSlider.getVisibleWidth() + spacing; | ||||
|         let thumbnailsWidth = this._thumbnailsSlider.getNonExpandedWidth() + spacing; | ||||
|  | ||||
|         geometry.width -= dashWidth; | ||||
|         geometry.width -= thumbnailsWidth; | ||||
|  | ||||
|         if (this.actor.get_text_direction() == Clutter.TextDirection.LTR) | ||||
|             geometry.x += dashWidth; | ||||
|         else | ||||
|             geometry.x += thumbnailsWidth; | ||||
|  | ||||
|         this.viewSelector.setWorkspacesFullGeometry(geometry); | ||||
|     }, | ||||
|  | ||||
|     _setVisibility: function() { | ||||
|         // Ignore the case when we're leaving the overview, since | ||||
|         // actors will be made visible again when entering the overview | ||||
| @@ -570,7 +521,7 @@ const ControlsManager = new Lang.Class({ | ||||
|             (Main.overview.animationInProgress && !Main.overview.visibleTarget)) | ||||
|             return; | ||||
|  | ||||
|         let activePage = this.viewSelector.getActivePage(); | ||||
|         let activePage = this._viewSelector.getActivePage(); | ||||
|         let dashVisible = (activePage == ViewSelector.ViewPage.WINDOWS || | ||||
|                            activePage == ViewSelector.ViewPage.APPS); | ||||
|         let thumbnailsVisible = (activePage == ViewSelector.ViewPage.WINDOWS); | ||||
| @@ -590,8 +541,8 @@ const ControlsManager = new Lang.Class({ | ||||
|         if (Main.overview.animationInProgress && !Main.overview.visibleTarget) | ||||
|             return; | ||||
|  | ||||
|         let activePage = this.viewSelector.getActivePage(); | ||||
|         this._dashSpacer.visible = (activePage == ViewSelector.ViewPage.WINDOWS); | ||||
|         let activePage = this._viewSelector.getActivePage(); | ||||
|         this.dashSpacer.visible = (activePage == ViewSelector.ViewPage.WINDOWS); | ||||
|     }, | ||||
|  | ||||
|     _onPageEmpty: function() { | ||||
|   | ||||
							
								
								
									
										178
									
								
								js/ui/panel.js
									
									
									
									
									
								
							
							
						
						
									
										178
									
								
								js/ui/panel.js
									
									
									
									
									
								
							| @@ -15,14 +15,12 @@ const Signals = imports.signals; | ||||
| const Atk = imports.gi.Atk; | ||||
|  | ||||
|  | ||||
| const Animation = imports.ui.animation; | ||||
| const Config = imports.misc.config; | ||||
| const CtrlAltTab = imports.ui.ctrlAltTab; | ||||
| const DND = imports.ui.dnd; | ||||
| const Overview = imports.ui.overview; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| const RemoteMenu = imports.ui.remoteMenu; | ||||
| const Main = imports.ui.main; | ||||
| const Tweener = imports.ui.tweener; | ||||
|  | ||||
| @@ -30,6 +28,7 @@ const PANEL_ICON_SIZE = 24; | ||||
|  | ||||
| const BUTTON_DND_ACTIVATION_TIMEOUT = 250; | ||||
|  | ||||
| const ANIMATED_ICON_UPDATE_TIMEOUT = 100; | ||||
| const SPINNER_ANIMATION_TIME = 0.2; | ||||
|  | ||||
| // To make sure the panel corners blend nicely with the panel, | ||||
| @@ -75,6 +74,81 @@ function _unpremultiply(color) { | ||||
|                                blue: blue, alpha: color.alpha }); | ||||
| }; | ||||
|  | ||||
| const Animation = new Lang.Class({ | ||||
|     Name: 'Animation', | ||||
|  | ||||
|     _init: function(filename, width, height, speed) { | ||||
|         this.actor = new St.Bin(); | ||||
|         this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | ||||
|         this._speed = speed; | ||||
|  | ||||
|         this._isLoaded = false; | ||||
|         this._isPlaying = false; | ||||
|         this._timeoutId = 0; | ||||
|         this._frame = 0; | ||||
|         this._animations = St.TextureCache.get_default().load_sliced_image (filename, width, height, | ||||
|                                                                             Lang.bind(this, this._animationsLoaded)); | ||||
|         this.actor.set_child(this._animations); | ||||
|     }, | ||||
|  | ||||
|     play: function() { | ||||
|         if (this._isLoaded && this._timeoutId == 0) { | ||||
|             if (this._frame == 0) | ||||
|                 this._showFrame(0); | ||||
|  | ||||
|             this._timeoutId = Mainloop.timeout_add(this._speed, Lang.bind(this, this._update)); | ||||
|         } | ||||
|  | ||||
|         this._isPlaying = true; | ||||
|     }, | ||||
|  | ||||
|     stop: function() { | ||||
|         if (this._timeoutId > 0) { | ||||
|             Mainloop.source_remove(this._timeoutId); | ||||
|             this._timeoutId = 0; | ||||
|         } | ||||
|  | ||||
|         this._isPlaying = false; | ||||
|     }, | ||||
|  | ||||
|     _showFrame: function(frame) { | ||||
|         let oldFrameActor = this._animations.get_child_at_index(this._frame); | ||||
|         if (oldFrameActor) | ||||
|             oldFrameActor.hide(); | ||||
|  | ||||
|         this._frame = (frame % this._animations.get_n_children()); | ||||
|  | ||||
|         let newFrameActor = this._animations.get_child_at_index(this._frame); | ||||
|         if (newFrameActor) | ||||
|             newFrameActor.show(); | ||||
|     }, | ||||
|  | ||||
|     _update: function() { | ||||
|         this._showFrame(this._frame + 1); | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _animationsLoaded: function() { | ||||
|         this._isLoaded = true; | ||||
|  | ||||
|         if (this._isPlaying) | ||||
|             this.play(); | ||||
|     }, | ||||
|  | ||||
|     _onDestroy: function() { | ||||
|         this.stop(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const AnimatedIcon = new Lang.Class({ | ||||
|     Name: 'AnimatedIcon', | ||||
|     Extends: Animation, | ||||
|  | ||||
|     _init: function(name, size) { | ||||
|         this.parent(global.datadir + '/theme/' + name, size, size, ANIMATED_ICON_UPDATE_TIMEOUT); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const TextShadower = new Lang.Class({ | ||||
|     Name: 'TextShadower', | ||||
|  | ||||
| @@ -184,7 +258,6 @@ const AppMenuButton = new Lang.Class({ | ||||
|         this._actionGroupNotifyId = 0; | ||||
|  | ||||
|         let bin = new St.Bin({ name: 'appMenu' }); | ||||
|         bin.connect('style-changed', Lang.bind(this, this._onStyleChanged)); | ||||
|         this.actor.add_actor(bin); | ||||
|  | ||||
|         this.actor.bind_property("reactive", this.actor, "can-focus", 0); | ||||
| @@ -215,25 +288,27 @@ const AppMenuButton = new Lang.Class({ | ||||
|         this._visible = !Main.overview.visible; | ||||
|         if (!this._visible) | ||||
|             this.actor.hide(); | ||||
|         this._overviewHidingId = Main.overview.connect('hiding', Lang.bind(this, function () { | ||||
|         Main.overview.connect('hiding', Lang.bind(this, function () { | ||||
|             this.show(); | ||||
|         })); | ||||
|         this._overviewShowingId = Main.overview.connect('showing', Lang.bind(this, function () { | ||||
|         Main.overview.connect('showing', Lang.bind(this, function () { | ||||
|             this.hide(); | ||||
|         })); | ||||
|  | ||||
|         this._stop = true; | ||||
|  | ||||
|         this._spinner = null; | ||||
|         this._spinner = new AnimatedIcon('process-working.svg', | ||||
|                                          PANEL_ICON_SIZE); | ||||
|         this._container.add_actor(this._spinner.actor); | ||||
|         this._spinner.actor.hide(); | ||||
|         this._spinner.actor.lower_bottom(); | ||||
|  | ||||
|         let tracker = Shell.WindowTracker.get_default(); | ||||
|         let appSys = Shell.AppSystem.get_default(); | ||||
|         this._focusAppNotifyId = | ||||
|             tracker.connect('notify::focus-app', Lang.bind(this, this._focusAppChanged)); | ||||
|         this._appStateChangedSignalId = | ||||
|             appSys.connect('app-state-changed', Lang.bind(this, this._onAppStateChanged)); | ||||
|         this._switchWorkspaceNotifyId = | ||||
|             global.window_manager.connect('switch-workspace', Lang.bind(this, this._sync)); | ||||
|         tracker.connect('notify::focus-app', Lang.bind(this, this._focusAppChanged)); | ||||
|         appSys.connect('app-state-changed', Lang.bind(this, this._onAppStateChanged)); | ||||
|  | ||||
|         global.window_manager.connect('switch-workspace', Lang.bind(this, this._sync)); | ||||
|  | ||||
|         this._sync(); | ||||
|     }, | ||||
| @@ -279,18 +354,6 @@ const AppMenuButton = new Lang.Class({ | ||||
|                            onCompleteScope: this }); | ||||
|     }, | ||||
|  | ||||
|     _onStyleChanged: function(actor) { | ||||
|         let node = actor.get_theme_node(); | ||||
|         let [success, icon] = node.lookup_url('spinner-image', false); | ||||
|         if (!success || this._spinnerIcon == icon) | ||||
|             return; | ||||
|         this._spinnerIcon = icon; | ||||
|         this._spinner = new Animation.AnimatedIcon(this._spinnerIcon, PANEL_ICON_SIZE); | ||||
|         this._container.add_actor(this._spinner.actor); | ||||
|         this._spinner.actor.hide(); | ||||
|         this._spinner.actor.lower_bottom(); | ||||
|     }, | ||||
|  | ||||
|     _onIconBoxStyleChanged: function() { | ||||
|         let node = this._iconBox.get_theme_node(); | ||||
|         this._iconBottomClip = node.get_length('app-icon-bottom-clip'); | ||||
| @@ -322,10 +385,6 @@ const AppMenuButton = new Lang.Class({ | ||||
|  | ||||
|         this._stop = true; | ||||
|         this.actor.reactive = true; | ||||
|  | ||||
|         if (this._spinner == null) | ||||
|             return; | ||||
|  | ||||
|         Tweener.addTween(this._spinner.actor, | ||||
|                          { opacity: 0, | ||||
|                            time: SPINNER_ANIMATION_TIME, | ||||
| @@ -342,10 +401,6 @@ const AppMenuButton = new Lang.Class({ | ||||
|     startAnimation: function() { | ||||
|         this._stop = false; | ||||
|         this.actor.reactive = false; | ||||
|  | ||||
|         if (this._spinner == null) | ||||
|             return; | ||||
|  | ||||
|         this._spinner.play(); | ||||
|         this._spinner.actor.show(); | ||||
|     }, | ||||
| @@ -408,9 +463,6 @@ const AppMenuButton = new Lang.Class({ | ||||
|         } | ||||
|         this._label.actor.allocate(childBox, flags); | ||||
|  | ||||
|         if (this._spinner == null) | ||||
|             return; | ||||
|  | ||||
|         if (direction == Clutter.TextDirection.LTR) { | ||||
|             childBox.x1 = Math.floor(iconWidth / 2) + this._label.actor.width; | ||||
|             childBox.x2 = childBox.x1 + this._spinner.actor.width; | ||||
| @@ -494,20 +546,14 @@ const AppMenuButton = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         if (targetApp == this._targetApp) { | ||||
|             if (targetApp && | ||||
|                 targetApp.get_state() != Shell.AppState.STARTING && | ||||
|                 targetApp.get_state() != Shell.AppState.BUSY) { | ||||
|             if (targetApp && targetApp.get_state() != Shell.AppState.STARTING) { | ||||
|                 this.stopAnimation(); | ||||
|                 this._maybeSetMenu(); | ||||
|             } else if (targetApp && | ||||
|                        targetApp.get_state() == Shell.AppState.BUSY) { | ||||
|                 this.startAnimation(); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (this._spinner) | ||||
|             this._spinner.actor.hide(); | ||||
|         this._spinner.actor.hide(); | ||||
|         if (this._iconBox.child != null) | ||||
|             this._iconBox.child.destroy(); | ||||
|         this._iconBox.hide(); | ||||
| @@ -534,8 +580,7 @@ const AppMenuButton = new Lang.Class({ | ||||
|         this._iconBox.set_child(icon); | ||||
|         this._iconBox.show(); | ||||
|  | ||||
|         if (targetApp.get_state() == Shell.AppState.STARTING || | ||||
|             targetApp.get_state() == Shell.AppState.BUSY) | ||||
|         if (targetApp.get_state() == Shell.AppState.STARTING) | ||||
|             this.startAnimation(); | ||||
|         else | ||||
|             this._maybeSetMenu(); | ||||
| @@ -547,11 +592,11 @@ const AppMenuButton = new Lang.Class({ | ||||
|         let menu; | ||||
|  | ||||
|         if (this._targetApp.action_group && this._targetApp.menu) { | ||||
|             if (this.menu instanceof RemoteMenu.RemoteMenu && | ||||
|             if (this.menu instanceof PopupMenu.RemoteMenu && | ||||
|                 this.menu.actionGroup == this._targetApp.action_group) | ||||
|                 return; | ||||
|  | ||||
|             menu = new RemoteMenu.RemoteMenu(this.actor, this._targetApp.menu, this._targetApp.action_group); | ||||
|             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()); | ||||
| @@ -571,33 +616,6 @@ const AppMenuButton = new Lang.Class({ | ||||
|  | ||||
|         this.setMenu(menu); | ||||
|         this._menuManager.addMenu(menu); | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
|         if (this._appStateChangedSignalId > 0) { | ||||
|             let appSys = Shell.AppSystem.get_default(); | ||||
|             appSys.disconnect(this._appStateChangedSignalId); | ||||
|             this._appStateChangedSignalId = 0; | ||||
|         } | ||||
|         if (this._focusAppNotifyId > 0) { | ||||
|             let tracker = Shell.WindowTracker.get_default(); | ||||
|             tracker.disconnect(this._focusAppNotifyId); | ||||
|             this._focusAppNotifyId = 0; | ||||
|         } | ||||
|         if (this._overviewHidingId > 0) { | ||||
|             Main.overview.disconnect(this._overviewHidingId); | ||||
|             this._overviewHidingId = 0; | ||||
|         } | ||||
|         if (this._overviewShowingId > 0) { | ||||
|             Main.overview.disconnect(this._overviewShowingId); | ||||
|             this._overviewShowingId = 0; | ||||
|         } | ||||
|         if (this._switchWorkspaceNotifyId > 0) { | ||||
|             global.window_manager.disconnect(this._switchWorkspaceNotifyId); | ||||
|             this._switchWorkspaceNotifyId = 0; | ||||
|         } | ||||
|  | ||||
|         this.parent(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -855,6 +873,7 @@ const PANEL_ITEM_IMPLEMENTATIONS = { | ||||
|     'volume': imports.ui.status.volume.Indicator, | ||||
|     'battery': imports.ui.status.power.Indicator, | ||||
|     'lockScreen': imports.ui.status.lockScreenMenu.Indicator, | ||||
|     'logo': imports.gdm.loginDialog.LogoMenuButton, | ||||
|     'keyboard': imports.ui.status.keyboard.InputSourceIndicator, | ||||
|     'powerMenu': imports.gdm.powerMenu.PowerMenuButton, | ||||
|     'userMenu': imports.ui.userMenu.UserMenuButton | ||||
| @@ -883,7 +902,7 @@ const Panel = new Lang.Class({ | ||||
|  | ||||
|         this.statusArea = {}; | ||||
|  | ||||
|         this.menuManager = new PopupMenu.PopupMenuManager(this, { keybindingMode: Shell.KeyBindingMode.TOPBAR_POPUP }); | ||||
|         this.menuManager = new PopupMenu.PopupMenuManager(this); | ||||
|  | ||||
|         this._leftBox = new St.BoxLayout({ name: 'panelLeft' }); | ||||
|         this.actor.add_actor(this._leftBox); | ||||
| @@ -1037,18 +1056,17 @@ const Panel = new Lang.Class({ | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     toggleAppMenu: function() { | ||||
|     openAppMenu: function() { | ||||
|         let indicator = this.statusArea.appMenu; | ||||
|         if (!indicator) // appMenu not supported by current session mode | ||||
|             return; | ||||
|  | ||||
|         let menu = indicator.menu; | ||||
|         if (!indicator.actor.reactive) | ||||
|         if (!indicator.actor.reactive || menu.isOpen) | ||||
|             return; | ||||
|  | ||||
|         menu.toggle(); | ||||
|         if (menu.isOpen) | ||||
|             menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); | ||||
|         menu.open(); | ||||
|         menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); | ||||
|     }, | ||||
|  | ||||
|     set boxOpacity(value) { | ||||
|   | ||||
| @@ -184,9 +184,6 @@ const Button = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _onMenuKeyPress: function(actor, event) { | ||||
|         if (global.focus_manager.navigate_from_event(event)) | ||||
|             return true; | ||||
|  | ||||
|         let symbol = event.get_key_symbol(); | ||||
|         if (symbol == Clutter.KEY_Left || symbol == Clutter.KEY_Right) { | ||||
|             let group = global.focus_manager.get_group(this.actor); | ||||
|   | ||||
| @@ -15,14 +15,9 @@ const GrabHelper = imports.ui.grabHelper; | ||||
| const Main = imports.ui.main; | ||||
| const Params = imports.misc.params; | ||||
| const Separator = imports.ui.separator; | ||||
| const Slider = imports.ui.slider; | ||||
| const Tweener = imports.ui.tweener; | ||||
|  | ||||
| const Ornament = { | ||||
|     NONE: 0, | ||||
|     DOT: 1, | ||||
|     CHECK: 2, | ||||
| }; | ||||
| const SLIDER_SCROLL_STEP = 0.05; /* Slider scrolling step in % */ | ||||
|  | ||||
| function _ensureStyle(actor) { | ||||
|     if (actor.get_children) { | ||||
| @@ -58,9 +53,7 @@ const PopupBaseMenuItem = new Lang.Class({ | ||||
|         this.actor._delegate = this; | ||||
|  | ||||
|         this._children = []; | ||||
|         this._ornament = Ornament.NONE; | ||||
|         this._ornamentLabel = new St.Label({ style_class: 'popup-menu-ornament' }); | ||||
|         this.actor.add_actor(this._ornamentLabel); | ||||
|         this._dot = null; | ||||
|         this._columnWidths = null; | ||||
|         this._spacing = 0; | ||||
|         this.active = false; | ||||
| @@ -183,24 +176,40 @@ const PopupBaseMenuItem = new Lang.Class({ | ||||
|         this._removeChild(child); | ||||
|     }, | ||||
|  | ||||
|     setOrnament: function(ornament) { | ||||
|         if (ornament == this._ornament) | ||||
|             return; | ||||
|     setShowDot: function(show) { | ||||
|         if (show) { | ||||
|             if (this._dot) | ||||
|                 return; | ||||
|  | ||||
|         this._ornament = ornament; | ||||
|             this._dot = new St.DrawingArea({ style_class: 'popup-menu-item-dot' }); | ||||
|             this._dot.connect('repaint', Lang.bind(this, this._onRepaintDot)); | ||||
|             this.actor.add_actor(this._dot); | ||||
|             this.actor.add_accessible_state (Atk.StateType.CHECKED); | ||||
|         } else { | ||||
|             if (!this._dot) | ||||
|                 return; | ||||
|  | ||||
|         if (ornament == Ornament.DOT) { | ||||
|             this._ornamentLabel.text = '\u2022'; | ||||
|             this.actor.add_accessible_state(Atk.StateType.CHECKED); | ||||
|         } else if (ornament == Ornament.CHECK) { | ||||
|             this._ornamentLabel.text = '\u2713'; | ||||
|             this.actor.add_accessible_state(Atk.StateType.CHECKED); | ||||
|         } else if (ornament == Ornament.NONE) { | ||||
|             this._ornamentLabel.text = ''; | ||||
|             this.actor.remove_accessible_state(Atk.StateType.CHECKED); | ||||
|             this._dot.destroy(); | ||||
|             this._dot = null; | ||||
|             this.actor.remove_accessible_state (Atk.StateType.CHECKED); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _onRepaintDot: function(area) { | ||||
|         let cr = area.get_context(); | ||||
|         let [width, height] = area.get_surface_size(); | ||||
|         let color = area.get_theme_node().get_foreground_color(); | ||||
|  | ||||
|         cr.setSourceRGBA ( | ||||
|             color.red / 255, | ||||
|             color.green / 255, | ||||
|             color.blue / 255, | ||||
|             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 | ||||
|     // to the image), not in visual order (left to right) | ||||
|     getColumnWidths: function() { | ||||
| @@ -271,25 +280,26 @@ const PopupBaseMenuItem = new Lang.Class({ | ||||
|         let height = box.y2 - box.y1; | ||||
|         let direction = this.actor.get_text_direction(); | ||||
|  | ||||
|         // The ornament is placed outside box | ||||
|         // one quarter of padding from the border of the container | ||||
|         // (so 3/4 from the inner border) | ||||
|         // (padding is box.x1) | ||||
|         let ornamentBox = new Clutter.ActorBox(); | ||||
|         let ornamentWidth = box.x1; | ||||
|         if (this._dot) { | ||||
|             // The dot is placed outside box | ||||
|             // one quarter of padding from the border of the container | ||||
|             // (so 3/4 from the inner border) | ||||
|             // (padding is box.x1) | ||||
|             let dotBox = new Clutter.ActorBox(); | ||||
|             let dotWidth = Math.round(box.x1 / 2); | ||||
|  | ||||
|         ornamentBox.x1 = 0; | ||||
|         ornamentBox.x2 = ornamentWidth; | ||||
|         ornamentBox.y1 = box.y1; | ||||
|         ornamentBox.y2 = box.y2; | ||||
|  | ||||
|         if (direction == Clutter.TextDirection.RTL) { | ||||
|             ornamentBox.x1 += box.x2; | ||||
|             ornamentBox.x2 += box.x2; | ||||
|             if (direction == Clutter.TextDirection.LTR) { | ||||
|                 dotBox.x1 = Math.round(box.x1 / 4); | ||||
|                 dotBox.x2 = dotBox.x1 + dotWidth; | ||||
|             } else { | ||||
|                 dotBox.x2 = box.x2 + 3 * Math.round(box.x1 / 4); | ||||
|                 dotBox.x1 = dotBox.x2 - dotWidth; | ||||
|             } | ||||
|             dotBox.y1 = Math.round(box.y1 + (height - dotWidth) / 2); | ||||
|             dotBox.y2 = dotBox.y1 + dotWidth; | ||||
|             this._dot.allocate(dotBox, flags); | ||||
|         } | ||||
|  | ||||
|         this._ornamentLabel.allocate(ornamentBox, flags); | ||||
|  | ||||
|         let x; | ||||
|         if (direction == Clutter.TextDirection.LTR) | ||||
|             x = box.x1; | ||||
| @@ -392,19 +402,12 @@ const PopupSeparatorMenuItem = new Lang.Class({ | ||||
|     Name: 'PopupSeparatorMenuItem', | ||||
|     Extends: PopupBaseMenuItem, | ||||
|  | ||||
|     _init: function (text) { | ||||
|     _init: function () { | ||||
|         this.parent({ reactive: false, | ||||
|                       can_focus: false}); | ||||
|  | ||||
|         this._box = new St.BoxLayout(); | ||||
|         this.addActor(this._box, { span: -1, expand: true }); | ||||
|  | ||||
|         this.label = new St.Label({ text: text || '' }); | ||||
|         this._box.add(this.label); | ||||
|         this.actor.label_actor = this.label; | ||||
|  | ||||
|         this._separator = new Separator.HorizontalSeparator({ style_class: 'popup-separator-menu-item' }); | ||||
|         this._box.add(this._separator.actor, { expand: true }); | ||||
|         this.addActor(this._separator.actor, { span: -1, expand: true }); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -514,23 +517,198 @@ const PopupSliderMenuItem = new Lang.Class({ | ||||
|     _init: function(value) { | ||||
|         this.parent({ activate: false }); | ||||
|  | ||||
|         this._slider = new Slider.Slider(value); | ||||
|         this._slider.connect('value-changed', Lang.bind(this, function(actor, value) { | ||||
|             this.emit('value-changed', value); | ||||
|         this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent)); | ||||
|  | ||||
|         if (isNaN(value)) | ||||
|             // Avoid spreading NaNs around | ||||
|             throw TypeError('The slider value must be a number'); | ||||
|         this._value = Math.max(Math.min(value, 1), 0); | ||||
|  | ||||
|         this._slider = new St.DrawingArea({ style_class: 'popup-slider-menu-item', reactive: true }); | ||||
|         this.addActor(this._slider, { span: -1, expand: true }); | ||||
|         this._slider.connect('repaint', Lang.bind(this, this._sliderRepaint)); | ||||
|         this.actor.connect('button-press-event', Lang.bind(this, this._startDragging)); | ||||
|         this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); | ||||
|         this.actor.connect('notify::mapped', Lang.bind(this, function() { | ||||
|             if (!this.actor.mapped) | ||||
|                 this._endDragging(); | ||||
|         })); | ||||
|         this.addActor(this._slider.actor); | ||||
|  | ||||
|         this._releaseId = this._motionId = 0; | ||||
|         this._dragging = false; | ||||
|     }, | ||||
|  | ||||
|     setValue: function(value) { | ||||
|         this._slider.setValue(value); | ||||
|         if (isNaN(value)) | ||||
|             throw TypeError('The slider value must be a number'); | ||||
|  | ||||
|         this._value = Math.max(Math.min(value, 1), 0); | ||||
|         this._slider.queue_repaint(); | ||||
|     }, | ||||
|  | ||||
|     _sliderRepaint: function(area) { | ||||
|         let cr = area.get_context(); | ||||
|         let themeNode = area.get_theme_node(); | ||||
|         let [width, height] = area.get_surface_size(); | ||||
|  | ||||
|         let handleRadius = themeNode.get_length('-slider-handle-radius'); | ||||
|  | ||||
|         let sliderWidth = width - 2 * handleRadius; | ||||
|         let sliderHeight = themeNode.get_length('-slider-height'); | ||||
|  | ||||
|         let sliderBorderWidth = themeNode.get_length('-slider-border-width'); | ||||
|  | ||||
|         let sliderBorderColor = themeNode.get_color('-slider-border-color'); | ||||
|         let sliderColor = themeNode.get_color('-slider-background-color'); | ||||
|  | ||||
|         let sliderActiveBorderColor = themeNode.get_color('-slider-active-border-color'); | ||||
|         let sliderActiveColor = themeNode.get_color('-slider-active-background-color'); | ||||
|  | ||||
|         cr.setSourceRGBA ( | ||||
|             sliderActiveColor.red / 255, | ||||
|             sliderActiveColor.green / 255, | ||||
|             sliderActiveColor.blue / 255, | ||||
|             sliderActiveColor.alpha / 255); | ||||
|         cr.rectangle(handleRadius, (height - sliderHeight) / 2, sliderWidth * this._value, sliderHeight); | ||||
|         cr.fillPreserve(); | ||||
|         cr.setSourceRGBA ( | ||||
|             sliderActiveBorderColor.red / 255, | ||||
|             sliderActiveBorderColor.green / 255, | ||||
|             sliderActiveBorderColor.blue / 255, | ||||
|             sliderActiveBorderColor.alpha / 255); | ||||
|         cr.setLineWidth(sliderBorderWidth); | ||||
|         cr.stroke(); | ||||
|  | ||||
|         cr.setSourceRGBA ( | ||||
|             sliderColor.red / 255, | ||||
|             sliderColor.green / 255, | ||||
|             sliderColor.blue / 255, | ||||
|             sliderColor.alpha / 255); | ||||
|         cr.rectangle(handleRadius + sliderWidth * this._value, (height - sliderHeight) / 2, sliderWidth * (1 - this._value), sliderHeight); | ||||
|         cr.fillPreserve(); | ||||
|         cr.setSourceRGBA ( | ||||
|             sliderBorderColor.red / 255, | ||||
|             sliderBorderColor.green / 255, | ||||
|             sliderBorderColor.blue / 255, | ||||
|             sliderBorderColor.alpha / 255); | ||||
|         cr.setLineWidth(sliderBorderWidth); | ||||
|         cr.stroke(); | ||||
|  | ||||
|         let handleY = height / 2; | ||||
|         let handleX = handleRadius + (width - 2 * handleRadius) * this._value; | ||||
|  | ||||
|         let color = themeNode.get_foreground_color(); | ||||
|         cr.setSourceRGBA ( | ||||
|             color.red / 255, | ||||
|             color.green / 255, | ||||
|             color.blue / 255, | ||||
|             color.alpha / 255); | ||||
|         cr.arc(handleX, handleY, handleRadius, 0, 2 * Math.PI); | ||||
|         cr.fill(); | ||||
|         cr.$dispose(); | ||||
|     }, | ||||
|  | ||||
|     _startDragging: function(actor, event) { | ||||
|         if (this._dragging) // don't allow two drags at the same time | ||||
|             return; | ||||
|  | ||||
|         this._dragging = true; | ||||
|  | ||||
|         // FIXME: we should only grab the specific device that originated | ||||
|         // the event, but for some weird reason events are still delivered | ||||
|         // outside the slider if using clutter_grab_pointer_for_device | ||||
|         Clutter.grab_pointer(this._slider); | ||||
|         this._releaseId = this._slider.connect('button-release-event', Lang.bind(this, this._endDragging)); | ||||
|         this._motionId = this._slider.connect('motion-event', Lang.bind(this, this._motionEvent)); | ||||
|         let absX, absY; | ||||
|         [absX, absY] = event.get_coords(); | ||||
|         this._moveHandle(absX, absY); | ||||
|     }, | ||||
|  | ||||
|     _endDragging: function() { | ||||
|         if (this._dragging) { | ||||
|             this._slider.disconnect(this._releaseId); | ||||
|             this._slider.disconnect(this._motionId); | ||||
|  | ||||
|             Clutter.ungrab_pointer(); | ||||
|             this._dragging = false; | ||||
|  | ||||
|             this.emit('drag-end'); | ||||
|         } | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     scroll: function(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.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(); | ||||
|         this._moveHandle(absX, absY); | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _moveHandle: function(absX, absY) { | ||||
|         let relX, relY, sliderX, sliderY; | ||||
|         [sliderX, sliderY] = this._slider.get_transformed_position(); | ||||
|         relX = absX - sliderX; | ||||
|         relY = absY - sliderY; | ||||
|  | ||||
|         let width = this._slider.width; | ||||
|         let handleRadius = this._slider.get_theme_node().get_length('-slider-handle-radius'); | ||||
|  | ||||
|         let newvalue; | ||||
|         if (relX < handleRadius) | ||||
|             newvalue = 0; | ||||
|         else if (relX > width - handleRadius) | ||||
|             newvalue = 1; | ||||
|         else | ||||
|             newvalue = (relX - handleRadius) / (width - 2 * handleRadius); | ||||
|         this._value = newvalue; | ||||
|         this._slider.queue_repaint(); | ||||
|         this.emit('value-changed', this._value); | ||||
|     }, | ||||
|  | ||||
|     get value() { | ||||
|         return this._slider.value; | ||||
|         return this._value; | ||||
|     }, | ||||
|  | ||||
|     scroll: function (event) { | ||||
|         this._slider.scroll(event); | ||||
|     _onKeyPressEvent: function (actor, event) { | ||||
|         let key = event.get_key_symbol(); | ||||
|         if (key == Clutter.KEY_Right || key == Clutter.KEY_Left) { | ||||
|             let delta = key == Clutter.KEY_Right ? 0.1 : -0.1; | ||||
|             this._value = Math.max(0, Math.min(this._value + delta, 1)); | ||||
|             this._slider.queue_repaint(); | ||||
|             this.emit('value-changed', this._value); | ||||
|             this.emit('drag-end'); | ||||
|             return true; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -814,9 +992,6 @@ const PopupMenuBase = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _updateSeparatorVisibility: function(menuItem) { | ||||
|         if (menuItem.label.text) | ||||
|             return; | ||||
|  | ||||
|         let children = this.box.get_children(); | ||||
|  | ||||
|         let index = children.indexOf(menuItem.actor); | ||||
| @@ -982,7 +1157,6 @@ const PopupMenuBase = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
|         this.close(); | ||||
|         this.removeAll(); | ||||
|         this.actor.destroy(); | ||||
|  | ||||
| @@ -1300,12 +1474,23 @@ const PopupMenuSection = new Lang.Class({ | ||||
|         this.actor = this.box; | ||||
|         this.actor._delegate = this; | ||||
|         this.isOpen = true; | ||||
|  | ||||
|         // an array of externally managed separators | ||||
|         this.separators = []; | ||||
|     }, | ||||
|  | ||||
|     // deliberately ignore any attempt to open() or close(), but emit the | ||||
|     // corresponding signal so children can still pick it up | ||||
|     open: function() { this.emit('open-state-changed', true); }, | ||||
|     close: function() { this.emit('open-state-changed', false); }, | ||||
|  | ||||
|     destroy: function() { | ||||
|         for (let i = 0; i < this.separators.length; i++) | ||||
|             this.separators[i].destroy(); | ||||
|         this.separators = []; | ||||
|  | ||||
|         this.parent(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const PopupSubMenuMenuItem = new Lang.Class({ | ||||
| @@ -1340,30 +1525,15 @@ const PopupSubMenuMenuItem = new Lang.Class({ | ||||
|         this.parent(); | ||||
|     }, | ||||
|  | ||||
|     setSubmenuShown: function(open) { | ||||
|         if (open) | ||||
|             this.menu.open(BoxPointer.PopupAnimation.FULL); | ||||
|         else | ||||
|             this.menu.close(BoxPointer.PopupAnimation.FULL); | ||||
|     }, | ||||
|  | ||||
|     _setOpenState: function(open) { | ||||
|         this.setSubmenuShown(open); | ||||
|     }, | ||||
|  | ||||
|     _getOpenState: function() { | ||||
|         return this.menu.isOpen; | ||||
|     }, | ||||
|  | ||||
|     _onKeyPressEvent: function(actor, event) { | ||||
|         let symbol = event.get_key_symbol(); | ||||
|  | ||||
|         if (symbol == Clutter.KEY_Right) { | ||||
|             this._setOpenState(true); | ||||
|             this.menu.open(BoxPointer.PopupAnimation.FULL); | ||||
|             this.menu.actor.navigate_focus(null, Gtk.DirectionType.DOWN, false); | ||||
|             return true; | ||||
|         } else if (symbol == Clutter.KEY_Left && this._getOpenState()) { | ||||
|             this._setOpenState(false); | ||||
|         } else if (symbol == Clutter.KEY_Left && this.menu.isOpen) { | ||||
|             this.menu.close(); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
| @@ -1371,11 +1541,11 @@ const PopupSubMenuMenuItem = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     activate: function(event) { | ||||
|         this._setOpenState(true); | ||||
|         this.menu.open(BoxPointer.PopupAnimation.FULL); | ||||
|     }, | ||||
|  | ||||
|     _onButtonReleaseEvent: function(actor) { | ||||
|         this._setOpenState(!this._getOpenState()); | ||||
|         this.menu.toggle(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -1621,15 +1791,269 @@ const PopupComboBoxMenuItem = new Lang.Class({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| /** | ||||
|  * RemoteMenu: | ||||
|  * | ||||
|  * A PopupMenu that tracks a GMenuModel and shows its actions | ||||
|  * (exposed by GApplication/GActionGroup) | ||||
|  */ | ||||
| const RemoteMenu = new Lang.Class({ | ||||
|     Name: 'RemoteMenu', | ||||
|     Extends: PopupMenu, | ||||
|  | ||||
|     _init: function(sourceActor, model, actionGroup) { | ||||
|         this.parent(sourceActor, 0.0, St.Side.TOP); | ||||
|  | ||||
|         this.model = model; | ||||
|         this.actionGroup = actionGroup; | ||||
|  | ||||
|         this._actions = { }; | ||||
|         this._modelChanged(this.model, 0, 0, this.model.get_n_items(), this); | ||||
|  | ||||
|         this._actionStateChangeId = this.actionGroup.connect('action-state-changed', Lang.bind(this, this._actionStateChanged)); | ||||
|         this._actionEnableChangeId = this.actionGroup.connect('action-enabled-changed', Lang.bind(this, this._actionEnabledChanged)); | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
|         if (this._actionStateChangeId) { | ||||
|             this.actionGroup.disconnect(this._actionStateChangeId); | ||||
|             this._actionStateChangeId = 0; | ||||
|         } | ||||
|  | ||||
|         if (this._actionEnableChangeId) { | ||||
|             this.actionGroup.disconnect(this._actionEnableChangeId); | ||||
|             this._actionEnableChangeId = 0; | ||||
|         } | ||||
|  | ||||
|         this.parent(); | ||||
|     }, | ||||
|  | ||||
|     _createMenuItem: function(model, index) { | ||||
|         let labelValue = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_LABEL, null); | ||||
|         let label = labelValue ? labelValue.deep_unpack() : ''; | ||||
|         // remove all underscores that are not followed by another underscore | ||||
|         label = label.replace(/_([^_])/, '$1'); | ||||
|  | ||||
|         let section_link = model.get_item_link(index, Gio.MENU_LINK_SECTION); | ||||
|         if (section_link) { | ||||
|             let item = new PopupMenuSection(); | ||||
|             if (label) { | ||||
|                 let title = new PopupMenuItem(label, { reactive: false, | ||||
|                                                        style_class: 'popup-subtitle-menu-item' }); | ||||
|                 item._titleMenuItem = title; | ||||
|                 title._ignored = true; | ||||
|                 item.addMenuItem(title); | ||||
|             } | ||||
|             this._modelChanged(section_link, 0, 0, section_link.get_n_items(), item); | ||||
|             return [item, true, '']; | ||||
|         } | ||||
|  | ||||
|         let submenu_link = model.get_item_link(index, Gio.MENU_LINK_SUBMENU); | ||||
|  | ||||
|         if (submenu_link) { | ||||
|             let item = new PopupSubMenuMenuItem(label); | ||||
|             this._modelChanged(submenu_link, 0, 0, submenu_link.get_n_items(), item.menu); | ||||
|             return [item, false, '']; | ||||
|         } | ||||
|  | ||||
|         let action_id = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_ACTION, null).deep_unpack(); | ||||
|         if (!this.actionGroup.has_action(action_id)) { | ||||
|             // the action may not be there yet, wait for action-added | ||||
|             return [null, false, 'action-added']; | ||||
|         } | ||||
|  | ||||
|         if (!this._actions[action_id]) | ||||
|             this._actions[action_id] = { enabled: this.actionGroup.get_action_enabled(action_id), | ||||
|                                          state: this.actionGroup.get_action_state(action_id), | ||||
|                                          items: [ ], | ||||
|                                        }; | ||||
|         let action = this._actions[action_id]; | ||||
|         let item, target, destroyId, specificSignalId; | ||||
|  | ||||
|         if (action.state) { | ||||
|             // Docs have get_state_hint(), except that the DBus protocol | ||||
|             // has no provision for it (so ShellApp does not implement it, | ||||
|             // and neither GApplication), and g_action_get_state_hint() | ||||
|             // always returns null | ||||
|             // Funny :) | ||||
|  | ||||
|             switch (String.fromCharCode(action.state.classify())) { | ||||
|             case 'b': | ||||
|                 item = new PopupSwitchMenuItem(label, action.state.get_boolean()); | ||||
|                 action.items.push(item); | ||||
|                 specificSignalId = item.connect('toggled', Lang.bind(this, function(item) { | ||||
|                     this.actionGroup.activate_action(action_id, null); | ||||
|                 })); | ||||
|                 break; | ||||
|             case 's': | ||||
|                 item = new PopupMenuItem(label); | ||||
|                 item._remoteTarget = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null).deep_unpack(); | ||||
|                 action.items.push(item); | ||||
|                 item.setShowDot(action.state.deep_unpack() == item._remoteTarget); | ||||
|                 specificSignalId = item.connect('activate', Lang.bind(this, function(item) { | ||||
|                     this.actionGroup.activate_action(action_id, GLib.Variant.new_string(item._remoteTarget)); | ||||
|                 })); | ||||
|                 break; | ||||
|             default: | ||||
|                 log('Action "%s" has state of type %s, which is not supported'.format(action_id, action.state.get_type_string())); | ||||
|                 return [null, false, 'action-state-changed']; | ||||
|             } | ||||
|         } else { | ||||
|             target = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null); | ||||
|             item = new PopupMenuItem(label); | ||||
|             action.items.push(item); | ||||
|             specificSignalId = item.connect('activate', Lang.bind(this, function() { | ||||
|                 this.actionGroup.activate_action(action_id, target); | ||||
|             })); | ||||
|         } | ||||
|  | ||||
|         item.actor.reactive = item.actor.can_focus = action.enabled; | ||||
|  | ||||
|         destroyId = item.connect('destroy', Lang.bind(this, function() { | ||||
|             item.disconnect(destroyId); | ||||
|             item.disconnect(specificSignalId); | ||||
|  | ||||
|             let pos = action.items.indexOf(item); | ||||
|             if (pos != -1) | ||||
|                 action.items.splice(pos, 1); | ||||
|         })); | ||||
|  | ||||
|         return [item, false, '']; | ||||
|     },  | ||||
|  | ||||
|     _modelChanged: function(model, position, removed, added, target) { | ||||
|         let j, k; | ||||
|         let j0, k0; | ||||
|  | ||||
|         let currentItems = target._getMenuItems(); | ||||
|  | ||||
|         k0 = 0; | ||||
|         // skip ignored items at the beginning | ||||
|         while (k0 < currentItems.length && currentItems[k0]._ignored) | ||||
|             k0++; | ||||
|         // find the right menu item matching the model item | ||||
|         for (j0 = 0; k0 < currentItems.length && j0 < position; j0++, k0++) { | ||||
|             if (currentItems[k0]._ignored) | ||||
|                 k0++; | ||||
|         } | ||||
|  | ||||
|         if (removed == -1) { | ||||
|             // special flag to indicate we should destroy everything | ||||
|             for (k = k0; k < currentItems.length; k++) | ||||
|                 currentItems[k].destroy(); | ||||
|         } else { | ||||
|             for (j = j0, k = k0; k < currentItems.length && j < j0 + removed; j++, k++) { | ||||
|                 currentItems[k].destroy(); | ||||
|  | ||||
|                 if (currentItems[k]._ignored) | ||||
|                     j--; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         for (j = j0, k = k0; j < j0 + added; j++, k++) { | ||||
|             let [item, addSeparator, changeSignal] = this._createMenuItem(model, j); | ||||
|  | ||||
|             if (item) { | ||||
|                 // separators must be added in the parent to make autohiding work | ||||
|                 if (addSeparator) { | ||||
|                     let separator = new PopupSeparatorMenuItem(); | ||||
|                     item.separators.push(separator); | ||||
|                     separator._ignored = true; | ||||
|                     target.addMenuItem(separator, k+1); | ||||
|                     k++; | ||||
|                 } | ||||
|  | ||||
|                 target.addMenuItem(item, k); | ||||
|  | ||||
|                 if (addSeparator) { | ||||
|                     let separator = new PopupSeparatorMenuItem(); | ||||
|                     item.separators.push(separator); | ||||
|                     separator._ignored = true; | ||||
|                     target.addMenuItem(separator, k+1); | ||||
|                     k++; | ||||
|                 } | ||||
|             } else if (changeSignal) { | ||||
|                 let signalId = this.actionGroup.connect(changeSignal, Lang.bind(this, function(actionGroup, actionName) { | ||||
|                     actionGroup.disconnect(signalId); | ||||
|                     if (this._actions[actionName]) return; | ||||
|  | ||||
|                     // force a full update | ||||
|                     this._modelChanged(model, 0, -1, model.get_n_items(), target); | ||||
|                 })); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (!model._changedId) { | ||||
|             model._changedId = model.connect('items-changed', Lang.bind(this, this._modelChanged, target)); | ||||
|             model._destroyId = target.connect('destroy', function() { | ||||
|                 if (model._changedId) | ||||
|                     model.disconnect(model._changedId); | ||||
|                 if (model._destroyId) | ||||
|                     target.disconnect(model._destroyId); | ||||
|                 model._changedId = 0; | ||||
|                 model._destroyId = 0; | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         if (target instanceof PopupMenuSection) { | ||||
|             if (target._titleMenuItem) | ||||
|                 target.actor.visible = target.numMenuItems != 1; | ||||
|             else | ||||
|                 target.actor.visible = target.numMenuItems != 0; | ||||
|         } else { | ||||
|             let sourceItem = target.sourceActor._delegate; | ||||
|             if (sourceItem instanceof PopupSubMenuMenuItem) | ||||
|                 sourceItem.actor.visible = target.numMenuItems != 0; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _actionStateChanged: function(actionGroup, action_id) { | ||||
|         let action = this._actions[action_id]; | ||||
|         if (!action) | ||||
|             return; | ||||
|  | ||||
|         action.state = actionGroup.get_action_state(action_id); | ||||
|         if (action.items.length) { | ||||
|             switch (String.fromCharCode(action.state.classify())) { | ||||
|             case 'b': | ||||
|                 for (let i = 0; i < action.items.length; i++) | ||||
|                     action.items[i].setToggleState(action.state.get_boolean()); | ||||
|                 break; | ||||
|             case 'd': | ||||
|                 for (let i = 0; i < action.items.length; i++) | ||||
|                     action.items[i].setValue(action.state.get_double()); | ||||
|                 break; | ||||
|             case 's': | ||||
|                 for (let i = 0; i < action.items.length; i++) | ||||
|                     action.items[i].setShowDot(action.items[i]._remoteTarget == action.state.deep_unpack()); | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _actionEnabledChanged: function(actionGroup, action_id) { | ||||
|         let action = this._actions[action_id]; | ||||
|         if (!action) | ||||
|             return; | ||||
|  | ||||
|         action.enabled = actionGroup.get_action_enabled(action_id); | ||||
|         if (action.items.length) { | ||||
|             for (let i = 0; i < action.items.length; i++) { | ||||
|                 let item = action.items[i]; | ||||
|                 item.actor.reactive = item.actor.can_focus = action.enabled; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }); | ||||
|  | ||||
| /* Basic implementation of a menu manager. | ||||
|  * Call addMenu to add menus | ||||
|  */ | ||||
| const PopupMenuManager = new Lang.Class({ | ||||
|     Name: 'PopupMenuManager', | ||||
|  | ||||
|     _init: function(owner, grabParams) { | ||||
|     _init: function(owner) { | ||||
|         this._owner = owner; | ||||
|         this._grabHelper = new GrabHelper.GrabHelper(owner.actor, grabParams); | ||||
|         this._grabHelper = new GrabHelper.GrabHelper(owner.actor); | ||||
|         this._menus = []; | ||||
|     }, | ||||
|  | ||||
| @@ -1699,8 +2123,6 @@ const PopupMenuManager = new Lang.Class({ | ||||
|  | ||||
|     _onMenuOpenState: function(menu, open) { | ||||
|         if (open) { | ||||
|             if (this.activeMenu && !this.activeMenu.isChildMenu(menu)) | ||||
|                 this.activeMenu.close(BoxPointer.PopupAnimation.FADE); | ||||
|             this._grabHelper.grab({ actor: menu.actor, modal: true, focus: menu.sourceActor, | ||||
|                                     onUngrab: Lang.bind(this, this._closeMenu, menu) }); | ||||
|         } else { | ||||
| @@ -1717,8 +2139,13 @@ const PopupMenuManager = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _changeMenu: function(newMenu) { | ||||
|         newMenu.open(this.activeMenu ? BoxPointer.PopupAnimation.FADE | ||||
|                                      : BoxPointer.PopupAnimation.FULL); | ||||
|         let oldMenu = this.activeMenu; | ||||
|         if (oldMenu) { | ||||
|             oldMenu.close(BoxPointer.PopupAnimation.FADE); | ||||
|             newMenu.open(BoxPointer.PopupAnimation.FADE); | ||||
|         } else { | ||||
|             newMenu.open(BoxPointer.PopupAnimation.FULL); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _onMenuSourceEnter: function(menu) { | ||||
|   | ||||
| @@ -1,199 +0,0 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const Atk = imports.gi.Atk; | ||||
| const GLib = imports.gi.GLib; | ||||
| const GObject = imports.gi.GObject; | ||||
| const Gio = imports.gi.Gio; | ||||
| const Lang = imports.lang; | ||||
| const Shell = imports.gi.Shell; | ||||
| const ShellMenu = imports.gi.ShellMenu; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
|  | ||||
| function stripMnemonics(label) { | ||||
|     if (!label) | ||||
|         return ''; | ||||
|  | ||||
|     // remove all underscores that are not followed by another underscore | ||||
|     return label.replace(/_([^_])/, '$1'); | ||||
| } | ||||
|  | ||||
| function _insertItem(menu, trackerItem, position) { | ||||
|     let mapper; | ||||
|  | ||||
|     if (trackerItem.get_is_separator()) | ||||
|         mapper = new RemoteMenuSeparatorItemMapper(trackerItem); | ||||
|     else if (trackerItem.get_has_submenu()) | ||||
|         mapper = new RemoteMenuSubmenuItemMapper(trackerItem); | ||||
|     else | ||||
|         mapper = new RemoteMenuItemMapper(trackerItem); | ||||
|  | ||||
|     let item = mapper.menuItem; | ||||
|     menu.addMenuItem(item, position); | ||||
| } | ||||
|  | ||||
| function _removeItem(menu, position) { | ||||
|     let items = menu._getMenuItems(); | ||||
|     items[position].destroy(); | ||||
| } | ||||
|  | ||||
| const RemoteMenuSeparatorItemMapper = new Lang.Class({ | ||||
|     Name: 'RemoteMenuSeparatorItemMapper', | ||||
|  | ||||
|     _init: function(trackerItem) { | ||||
|         this._trackerItem = trackerItem; | ||||
|         this.menuItem = new PopupMenu.PopupSeparatorMenuItem(); | ||||
|         this._trackerItem.connect('notify::label', Lang.bind(this, this._updateLabel)); | ||||
|         this._updateLabel(); | ||||
|  | ||||
|         this.menuItem.connect('destroy', function() { | ||||
|             trackerItem.run_dispose(); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     _updateLabel: function() { | ||||
|         this.menuItem.label.text = stripMnemonics(this._trackerItem.label); | ||||
|     }, | ||||
| }); | ||||
|  | ||||
| const RequestSubMenu = new Lang.Class({ | ||||
|     Name: 'RequestSubMenu', | ||||
|     Extends: PopupMenu.PopupSubMenuMenuItem, | ||||
|  | ||||
|     _init: function() { | ||||
|         this.parent(''); | ||||
|         this._requestOpen = false; | ||||
|     }, | ||||
|  | ||||
|     _setOpenState: function(open) { | ||||
|         this.emit('request-open', open); | ||||
|         this._requestOpen = open; | ||||
|     }, | ||||
|  | ||||
|     _getOpenState: function() { | ||||
|         return this._requestOpen; | ||||
|     }, | ||||
| }); | ||||
|  | ||||
| const RemoteMenuSubmenuItemMapper = new Lang.Class({ | ||||
|     Name: 'RemoteMenuSubmenuItemMapper', | ||||
|  | ||||
|     _init: function(trackerItem) { | ||||
|         this._trackerItem = trackerItem; | ||||
|         this.menuItem = new RequestSubMenu(); | ||||
|         this._trackerItem.connect('notify::label', Lang.bind(this, this._updateLabel)); | ||||
|         this._updateLabel(); | ||||
|  | ||||
|         this._tracker = Shell.MenuTracker.new_for_item_submenu(this._trackerItem, | ||||
|                                                                _insertItem.bind(null, this.menuItem.menu), | ||||
|                                                                _removeItem.bind(null, this.menuItem.menu)); | ||||
|  | ||||
|         this.menuItem.connect('request-open', Lang.bind(this, function(menu, open) { | ||||
|             this._trackerItem.request_submenu_shown(open); | ||||
|         })); | ||||
|  | ||||
|         this._trackerItem.connect('notify::submenu-shown', Lang.bind(this, function() { | ||||
|             this.menuItem.setSubmenuShown(this._trackerItem.get_submenu_shown()); | ||||
|         })); | ||||
|  | ||||
|         this.menuItem.connect('destroy', function() { | ||||
|             trackerItem.run_dispose(); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
|         this._tracker.destroy(); | ||||
|         this.parent(); | ||||
|     }, | ||||
|  | ||||
|     _updateLabel: function() { | ||||
|         this.menuItem.label.text = stripMnemonics(this._trackerItem.label); | ||||
|     }, | ||||
| }); | ||||
|  | ||||
| const RemoteMenuItemMapper = new Lang.Class({ | ||||
|     Name: 'RemoteMenuItemMapper', | ||||
|  | ||||
|     _init: function(trackerItem) { | ||||
|         this._trackerItem = trackerItem; | ||||
|  | ||||
|         this.menuItem = new PopupMenu.PopupBaseMenuItem(); | ||||
|         this._label = new St.Label(); | ||||
|         this.menuItem.addActor(this._label); | ||||
|         this.menuItem.actor.label_actor = this._label; | ||||
|  | ||||
|         this.menuItem.connect('activate', Lang.bind(this, function() { | ||||
|             this._trackerItem.activated(); | ||||
|         })); | ||||
|  | ||||
|         this._trackerItem.bind_property('visible', this.menuItem.actor, 'visible', GObject.BindingFlags.SYNC_CREATE); | ||||
|  | ||||
|         this._trackerItem.connect('notify::label', Lang.bind(this, this._updateLabel)); | ||||
|         this._trackerItem.connect('notify::sensitive', Lang.bind(this, this._updateSensitivity)); | ||||
|         this._trackerItem.connect('notify::role', Lang.bind(this, this._updateRole)); | ||||
|         this._trackerItem.connect('notify::toggled', Lang.bind(this, this._updateDecoration)); | ||||
|  | ||||
|         this._updateLabel(); | ||||
|         this._updateSensitivity(); | ||||
|         this._updateRole(); | ||||
|  | ||||
|         this.menuItem.connect('destroy', function() { | ||||
|             trackerItem.run_dispose(); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     _updateLabel: function() { | ||||
|         this._label.text = stripMnemonics(this._trackerItem.label); | ||||
|     }, | ||||
|  | ||||
|     _updateSensitivity: function() { | ||||
|         this.menuItem.setSensitive(this._trackerItem.sensitive); | ||||
|     }, | ||||
|  | ||||
|     _updateDecoration: function() { | ||||
|         let ornamentForRole = {}; | ||||
|         ornamentForRole[ShellMenu.MenuTrackerItemRole.RADIO] = PopupMenu.Ornament.DOT; | ||||
|         ornamentForRole[ShellMenu.MenuTrackerItemRole.CHECK] = PopupMenu.Ornament.CHECK; | ||||
|  | ||||
|         let ornament = PopupMenu.Ornament.NONE; | ||||
|         if (this._trackerItem.toggled) | ||||
|             ornament = ornamentForRole[this._trackerItem.role]; | ||||
|  | ||||
|         this.menuItem.setOrnament(ornament); | ||||
|     }, | ||||
|  | ||||
|     _updateRole: function() { | ||||
|         let a11yRoles = {}; | ||||
|         a11yRoles[ShellMenu.MenuTrackerItemRole.NORMAL] = Atk.Role.MENU_ITEM; | ||||
|         a11yRoles[ShellMenu.MenuTrackerItemRole.RADIO] = Atk.Role.RADIO_MENU_ITEM; | ||||
|         a11yRoles[ShellMenu.MenuTrackerItemRole.CHECK] = Atk.Role.CHECK_MENU_ITEM; | ||||
|  | ||||
|         let a11yRole = a11yRoles[this._trackerItem.role]; | ||||
|         this.menuItem.actor.accessible_role = a11yRole; | ||||
|  | ||||
|         this._updateDecoration(); | ||||
|     }, | ||||
| }); | ||||
|  | ||||
| const RemoteMenu = new Lang.Class({ | ||||
|     Name: 'RemoteMenu', | ||||
|     Extends: PopupMenu.PopupMenu, | ||||
|  | ||||
|     _init: function(sourceActor, model, actionGroup) { | ||||
|         this.parent(sourceActor, 0.0, St.Side.TOP); | ||||
|  | ||||
|         this._model = model; | ||||
|         this._actionGroup = actionGroup; | ||||
|         this._tracker = Shell.MenuTracker.new(this._actionGroup, | ||||
|                                               this._model, | ||||
|                                               null, /* action namespace */ | ||||
|                                               _insertItem.bind(null, this), | ||||
|                                               _removeItem.bind(null, this)); | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
|         this._tracker.destroy(); | ||||
|         this.parent(); | ||||
|     }, | ||||
| }); | ||||
| @@ -187,9 +187,7 @@ const RemoteSearchProvider = new Lang.Class({ | ||||
|  | ||||
|     createIcon: function(size, meta) { | ||||
|         let gicon; | ||||
|         if (meta['icon']) { | ||||
|             gicon = Gio.icon_deserialize(meta['icon']); | ||||
|         } else if (meta['gicon']) { | ||||
|         if (meta['gicon']) { | ||||
|             gicon = Gio.icon_new_for_string(meta['gicon']); | ||||
|         } else if (meta['icon-data']) { | ||||
|             let [width, height, rowStride, hasAlpha, | ||||
| @@ -205,7 +203,7 @@ const RemoteSearchProvider = new Lang.Class({ | ||||
|     _getResultsFinished: function(results, error) { | ||||
|         if (error) | ||||
|             return; | ||||
|         this.searchSystem.setResults(this, results[0]); | ||||
|         this.searchSystem.pushResults(this, results[0]); | ||||
|     }, | ||||
|  | ||||
|     getInitialResultSet: function(terms) { | ||||
| @@ -217,7 +215,7 @@ const RemoteSearchProvider = new Lang.Class({ | ||||
|                                                  this._cancellable); | ||||
|         } catch(e) { | ||||
|             log('Error calling GetInitialResultSet for provider %s: %s'.format(this.id, e.toString())); | ||||
|             this.searchSystem.setResults(this, []); | ||||
|             this.searchSystem.pushResults(this, []); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -230,7 +228,7 @@ const RemoteSearchProvider = new Lang.Class({ | ||||
|                                                    this._cancellable); | ||||
|         } catch(e) { | ||||
|             log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.id, e.toString())); | ||||
|             this.searchSystem.setResults(this, []); | ||||
|             this.searchSystem.pushResults(this, []); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -242,12 +240,8 @@ const RemoteSearchProvider = new Lang.Class({ | ||||
|         let metas = results[0]; | ||||
|         let resultMetas = []; | ||||
|         for (let i = 0; i < metas.length; i++) { | ||||
|             for (let prop in metas[i]) { | ||||
|                 // we can use the serialized icon variant directly | ||||
|                 if (prop != 'icon') | ||||
|                     metas[i][prop] = metas[i][prop].deep_unpack(); | ||||
|             } | ||||
|  | ||||
|             for (let prop in metas[i]) | ||||
|                 metas[i][prop] = metas[i][prop].deep_unpack(); | ||||
|             resultMetas.push({ id: metas[i]['id'], | ||||
|                                name: metas[i]['name'], | ||||
|                                description: metas[i]['description'], | ||||
|   | ||||
| @@ -35,8 +35,7 @@ const RunDialog = new Lang.Class({ | ||||
|     Extends: ModalDialog.ModalDialog, | ||||
|  | ||||
|     _init : function() { | ||||
|         this.parent({ styleClass: 'run-dialog', | ||||
|                       destroyOnClose: false }); | ||||
|         this.parent({ styleClass: 'run-dialog' }); | ||||
|  | ||||
|         this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA }); | ||||
|         this._terminalSettings = new Gio.Settings({ schema: TERMINAL_SCHEMA }); | ||||
|   | ||||
| @@ -30,7 +30,6 @@ const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver'; | ||||
| const LOCK_ENABLED_KEY = 'lock-enabled'; | ||||
| const LOCK_DELAY_KEY = 'lock-delay'; | ||||
|  | ||||
| const LOCKED_STATE_STR = 'screenShield.locked'; | ||||
| // fraction of screen height the arrow must reach before completing | ||||
| // the slide up automatically | ||||
| const ARROW_DRAG_THRESHOLD = 0.1; | ||||
| @@ -215,7 +214,6 @@ const NotificationsBox = new Lang.Class({ | ||||
|  | ||||
|         if (musicNotification != null && | ||||
|             this._musicBin.child == null) { | ||||
|             musicNotification.acknowledged = true; | ||||
|             if (musicNotification.actor.get_parent() != null) | ||||
|                 musicNotification.actor.get_parent().remove_actor(musicNotification.actor); | ||||
|             this._musicBin.child = musicNotification.actor; | ||||
| @@ -248,7 +246,6 @@ const NotificationsBox = new Lang.Class({ | ||||
|             sourceCountChangedId: 0, | ||||
|             sourceTitleChangedId: 0, | ||||
|             sourceUpdatedId: 0, | ||||
|             sourceNotifyId: 0, | ||||
|             musicNotification: null, | ||||
|             sourceBox: null, | ||||
|             titleLabel: null, | ||||
| @@ -259,12 +256,6 @@ const NotificationsBox = new Lang.Class({ | ||||
|         this._showSource(source, obj, obj.sourceBox); | ||||
|         this._notificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START }); | ||||
|  | ||||
|         if (obj.musicNotification) { | ||||
|             obj.sourceNotifyId = source.connect('notify', Lang.bind(this, function(source, notification) { | ||||
|                 notification.acknowledged = true; | ||||
|             })); | ||||
|         } | ||||
|  | ||||
|         obj.sourceCountChangedId = source.connect('count-updated', Lang.bind(this, function(source) { | ||||
|             this._countChanged(source, obj); | ||||
|         })); | ||||
| @@ -345,8 +336,6 @@ const NotificationsBox = new Lang.Class({ | ||||
|         if (obj.musicNotification) { | ||||
|             this._musicBin.child = null; | ||||
|             obj.musicNotification = null; | ||||
|  | ||||
|             source.disconnect(obj.sourceNotifyId); | ||||
|         } | ||||
|  | ||||
|         source.disconnect(obj.sourceDestroyId); | ||||
| @@ -573,7 +562,6 @@ const ScreenShield = new Lang.Class({ | ||||
|             this._bgManagers[i].destroy(); | ||||
|  | ||||
|         this._bgManagers = []; | ||||
|         this._backgroundGroup.destroy_all_children(); | ||||
|  | ||||
|         for (let i = 0; i < Main.layoutManager.monitors.length; i++) | ||||
|             this._createBackground(i); | ||||
| @@ -720,8 +708,6 @@ const ScreenShield = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _onDragEnd: function(action, actor, eventX, eventY, modifiers) { | ||||
|         if (this._lockScreenState != MessageTray.State.HIDING) | ||||
|             return; | ||||
|         if (this._lockScreenGroup.y < -(ARROW_DRAG_THRESHOLD * global.stage.height)) { | ||||
|             // Complete motion automatically | ||||
| 	    let [velocity, velocityX, velocityY] = this._dragAction.get_velocity(0); | ||||
| @@ -1128,22 +1114,11 @@ const ScreenShield = new Lang.Class({ | ||||
|     deactivate: function(animate) { | ||||
|         this._hideLockScreen(animate, 0); | ||||
|  | ||||
|         if (this._hasLockScreen) | ||||
|             this._clearLockScreen(); | ||||
|  | ||||
|         if (Main.sessionMode.currentMode == 'lock-screen') | ||||
|             Main.sessionMode.popMode('lock-screen'); | ||||
|         if (Main.sessionMode.currentMode == 'unlock-dialog') | ||||
|             Main.sessionMode.popMode('unlock-dialog'); | ||||
|  | ||||
|         if (this._dialog && !this._isGreeter) | ||||
|             this._dialog.popModal(); | ||||
|  | ||||
|         if (this._isModal) { | ||||
|             Main.popModal(this.actor); | ||||
|             this._isModal = false; | ||||
|         } | ||||
|  | ||||
|         Tweener.addTween(this._lockDialogGroup, { | ||||
|             scale_x: 0, | ||||
|             scale_y: 0, | ||||
| @@ -1155,12 +1130,21 @@ const ScreenShield = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _completeDeactivate: function() { | ||||
|         if (this._hasLockScreen) | ||||
|             this._clearLockScreen(); | ||||
|  | ||||
|         if (this._dialog && !this._isGreeter) { | ||||
|             this._dialog.destroy(); | ||||
|             this._dialog = null; | ||||
|         } | ||||
|  | ||||
|         this._lightbox.hide(); | ||||
|  | ||||
|         if (this._isModal) { | ||||
|             Main.popModal(this.actor); | ||||
|             this._isModal = false; | ||||
|         } | ||||
|  | ||||
|         this.actor.hide(); | ||||
|  | ||||
|         if (this._becameActiveId != 0) { | ||||
| @@ -1178,7 +1162,6 @@ const ScreenShield = new Lang.Class({ | ||||
|         this._isLocked = false; | ||||
|         this.emit('active-changed'); | ||||
|         this.emit('locked-changed'); | ||||
|         global.set_runtime_state(LOCKED_STATE_STR, null); | ||||
|     }, | ||||
|  | ||||
|     activate: function(animate) { | ||||
| @@ -1195,7 +1178,6 @@ const ScreenShield = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         this._resetLockScreen(animate, animate); | ||||
|         global.set_runtime_state(LOCKED_STATE_STR, GLib.Variant.new('b', true)); | ||||
|  | ||||
|         // We used to set isActive and emit active-changed here, | ||||
|         // but now we do that from lockScreenShown, which means | ||||
| @@ -1217,26 +1199,10 @@ const ScreenShield = new Lang.Class({ | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // Clear the clipboard - otherwise, its contents may be leaked | ||||
|         // to unauthorized parties by pasting into the unlock dialog's | ||||
|         // password entry and unmasking the entry | ||||
|         St.Clipboard.get_default().set_text(St.ClipboardType.CLIPBOARD, ''); | ||||
|         St.Clipboard.get_default().set_text(St.ClipboardType.PRIMARY, ''); | ||||
|  | ||||
|         this._isLocked = true; | ||||
|         this.activate(animate); | ||||
|  | ||||
|         this.emit('locked-changed'); | ||||
|     }, | ||||
|  | ||||
|     // If the previous shell crashed, and gnome-session restarted us, then re-lock | ||||
|     lockIfWasLocked: function() { | ||||
|         let wasLocked = global.get_runtime_state('b', LOCKED_STATE_STR); | ||||
|         if (wasLocked === null) | ||||
|             return; | ||||
|         Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { | ||||
|             this.lock(false); | ||||
|         })); | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(ScreenShield.prototype); | ||||
|   | ||||
| @@ -1,140 +0,0 @@ | ||||
| // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- | ||||
|  | ||||
| const Gio = imports.gi.Gio; | ||||
| const GLib = imports.gi.GLib; | ||||
| const Lang = imports.lang; | ||||
| const Shell = imports.gi.Shell; | ||||
|  | ||||
| const Hash = imports.misc.hash; | ||||
| const Main = imports.ui.main; | ||||
|  | ||||
| const ScreencastIface = <interface name="org.gnome.Shell.Screencast"> | ||||
| <method name="Screencast"> | ||||
|     <arg type="s" direction="in" name="file_template"/> | ||||
|     <arg type="a{sv}" direction="in" name="options"/> | ||||
|     <arg type="b" direction="out" name="success"/> | ||||
|     <arg type="s" direction="out" name="filename_used"/> | ||||
| </method> | ||||
| <method name="ScreencastArea"> | ||||
|     <arg type="i" direction="in" name="x"/> | ||||
|     <arg type="i" direction="in" name="y"/> | ||||
|     <arg type="i" direction="in" name="width"/> | ||||
|     <arg type="i" direction="in" name="height"/> | ||||
|     <arg type="s" direction="in" name="file_template"/> | ||||
|     <arg type="a{sv}" direction="in" name="options"/> | ||||
|     <arg type="b" direction="out" name="success"/> | ||||
|     <arg type="s" direction="out" name="filename_used"/> | ||||
| </method> | ||||
| <method name="StopScreencast"> | ||||
|     <arg type="b" direction="out" name="success"/> | ||||
| </method> | ||||
| </interface>; | ||||
|  | ||||
| const ScreencastService = new Lang.Class({ | ||||
|     Name: 'ScreencastService', | ||||
|  | ||||
|     _init: function() { | ||||
|         this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreencastIface, this); | ||||
|         this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/Screencast'); | ||||
|  | ||||
|         Gio.DBus.session.own_name('org.gnome.Shell.Screencast', Gio.BusNameOwnerFlags.REPLACE, null, null); | ||||
|  | ||||
|         this._recorders = new Hash.Map(); | ||||
|  | ||||
|         Main.sessionMode.connect('updated', | ||||
|                                  Lang.bind(this, this._sessionModeChanged)); | ||||
|     }, | ||||
|  | ||||
|     _ensureRecorderForSender: function(sender) { | ||||
|         let recorder = this._recorders.get(sender); | ||||
|         if (!recorder) { | ||||
|             recorder = new Shell.Recorder({ stage: global.stage }); | ||||
|             recorder._watchNameId = | ||||
|                 Gio.bus_watch_name(Gio.BusType.SESSION, sender, 0, null, | ||||
|                                    Lang.bind(this, this._onNameVanished)); | ||||
|             this._recorders.set(sender, recorder); | ||||
|         } | ||||
|         return recorder; | ||||
|     }, | ||||
|  | ||||
|     _sessionModeChanged: function() { | ||||
|         if (Main.sessionMode.allowScreencast) | ||||
|             return; | ||||
|  | ||||
|         for (let sender in this._recorders.keys()) | ||||
|             this._recorders.delete(sender); | ||||
|     }, | ||||
|  | ||||
|     _onNameVanished: function(connection, name) { | ||||
|         this._stopRecordingForSender(name); | ||||
|     }, | ||||
|  | ||||
|     _stopRecordingForSender: function(sender) { | ||||
|         let recorder = this._recorders.get(sender); | ||||
|         if (!recorder) | ||||
|             return false; | ||||
|  | ||||
|         Gio.bus_unwatch_name(recorder._watchNameId); | ||||
|         recorder.close(); | ||||
|         this._recorders.delete(sender); | ||||
|  | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _applyOptionalParameters: function(recorder, options) { | ||||
|         for (let option in options) | ||||
|             options[option] = options[option].deep_unpack(); | ||||
|  | ||||
|         if (options['pipeline']) | ||||
|             recorder.set_pipeline(options['pipeline']); | ||||
|         if (options['framerate']) | ||||
|             recorder.set_framerate(options['framerate']); | ||||
|         if (options['draw-cursor']) | ||||
|             recorder.set_draw_cursor(options['draw-cursor']); | ||||
|     }, | ||||
|  | ||||
|     ScreencastAsync: function(params, invocation) { | ||||
|         let returnValue = [false, '']; | ||||
|         if (!Main.sessionMode.allowScreencast) | ||||
|             invocation.return_value(GLib.Variant.new('(bs)', returnValue)); | ||||
|  | ||||
|         let sender = invocation.get_sender(); | ||||
|         let recorder = this._ensureRecorderForSender(sender); | ||||
|         if (!recorder.is_recording()) { | ||||
|             let [fileTemplate, options] = params; | ||||
|  | ||||
|             recorder.set_file_template(fileTemplate); | ||||
|             this._applyOptionalParameters(recorder, options); | ||||
|             let [success, fileName] = recorder.record(); | ||||
|             returnValue = [success, fileName ? fileName : '']; | ||||
|         } | ||||
|  | ||||
|         invocation.return_value(GLib.Variant.new('(bs)', returnValue)); | ||||
|     }, | ||||
|  | ||||
|     ScreencastAreaAsync: function(params, invocation) { | ||||
|         let returnValue = [false, '']; | ||||
|         if (!Main.sessionMode.allowScreencast) | ||||
|             invocation.return_value(GLib.Variant.new('(bs)', returnValue)); | ||||
|  | ||||
|         let sender = invocation.get_sender(); | ||||
|         let recorder = this._ensureRecorderForSender(sender); | ||||
|  | ||||
|         if (!recorder.is_recording()) { | ||||
|             let [x, y, width, height, fileTemplate, options] = params; | ||||
|  | ||||
|             recorder.set_file_template(fileTemplate); | ||||
|             recorder.set_area(x, y, width, height); | ||||
|             this._applyOptionalParameters(recorder, options); | ||||
|             let [success, fileName] = recorder.record(); | ||||
|             returnValue = [success, fileName ? fileName : '']; | ||||
|         } | ||||
|  | ||||
|         invocation.return_value(GLib.Variant.new('(bs)', returnValue)); | ||||
|     }, | ||||
|  | ||||
|     StopScreencastAsync: function(params, invocation) { | ||||
|         let success = this._stopRecordingForSender(invocation.get_sender()); | ||||
|         invocation.return_value(GLib.Variant.new('(b)', [success])); | ||||
|     } | ||||
| }); | ||||
| @@ -51,7 +51,7 @@ const SearchSystem = new Lang.Class({ | ||||
|         this._previousResults = []; | ||||
|     }, | ||||
|  | ||||
|     setResults: function(provider, results) { | ||||
|     pushResults: function(provider, results) { | ||||
|         let i = this._providers.indexOf(provider); | ||||
|         if (i == -1) | ||||
|             return; | ||||
|   | ||||
| @@ -180,82 +180,13 @@ const GridSearchResult = new Lang.Class({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const SearchResultsBase = new Lang.Class({ | ||||
|     Name: 'SearchResultsBase', | ||||
| const ListSearchResults = new Lang.Class({ | ||||
|     Name: 'ListSearchResults', | ||||
|  | ||||
|     _init: function(provider) { | ||||
|         this.provider = provider; | ||||
|  | ||||
|         this._terms = []; | ||||
|  | ||||
|         this.actor = new St.BoxLayout({ style_class: 'search-section', | ||||
|                                         vertical: true }); | ||||
|  | ||||
|         this._resultDisplayBin = new St.Bin({ x_fill: true, | ||||
|                                               y_fill: true }); | ||||
|         this.actor.add(this._resultDisplayBin, { expand: true }); | ||||
|  | ||||
|         let separator = new Separator.HorizontalSeparator({ style_class: 'search-section-separator' }); | ||||
|         this.actor.add(separator.actor); | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
|         this.actor.destroy(); | ||||
|         this._terms = []; | ||||
|     }, | ||||
|  | ||||
|     _clearResultDisplay: function() { | ||||
|     }, | ||||
|  | ||||
|     clear: function() { | ||||
|         this._clearResultDisplay(); | ||||
|         this.actor.hide(); | ||||
|     }, | ||||
|  | ||||
|     _keyFocusIn: function(icon) { | ||||
|         this.emit('key-focus-in', icon); | ||||
|     }, | ||||
|  | ||||
|     _setMoreIconVisible: function(visible) { | ||||
|     }, | ||||
|  | ||||
|     updateSearch: function(providerResults, terms, callback) { | ||||
|         this._terms = terms; | ||||
|  | ||||
|         if (providerResults.length == 0) { | ||||
|             this._clearResultDisplay(); | ||||
|             this.actor.hide(); | ||||
|             callback(); | ||||
|         } else { | ||||
|             let maxResults = this._getMaxDisplayedResults(); | ||||
|             let results = providerResults.slice(0, maxResults); | ||||
|             let hasMoreResults = results.length < providerResults.length; | ||||
|  | ||||
|             this.provider.getResultMetas(results, Lang.bind(this, function(metas) { | ||||
|                 this.clear(); | ||||
|  | ||||
|                 // To avoid CSS transitions causing flickering when | ||||
|                 // the first search result stays the same, we hide the | ||||
|                 // content while filling in the results. | ||||
|                 this.actor.hide(); | ||||
|                 this._clearResultDisplay(); | ||||
|                 this._renderResults(metas); | ||||
|                 this._setMoreIconVisible(hasMoreResults && this.provider.canLaunchSearch); | ||||
|                 this.actor.show(); | ||||
|                 callback(); | ||||
|             })); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const ListSearchResults = new Lang.Class({ | ||||
|     Name: 'ListSearchResults', | ||||
|     Extends: SearchResultsBase, | ||||
|  | ||||
|     _init: function(provider) { | ||||
|         this.parent(provider); | ||||
|  | ||||
|         this._container = new St.BoxLayout({ style_class: 'search-section-content' }); | ||||
|         this.actor = new St.BoxLayout({ style_class: 'search-section-content' }); | ||||
|         this.providerIcon = new ProviderIcon(provider); | ||||
|         this.providerIcon.connect('clicked', Lang.bind(this, | ||||
|             function() { | ||||
| @@ -263,27 +194,48 @@ const ListSearchResults = new Lang.Class({ | ||||
|                 Main.overview.toggle(); | ||||
|             })); | ||||
|  | ||||
|         this._container.add(this.providerIcon, { x_fill: false, | ||||
|                                                  y_fill: false, | ||||
|                                                  x_align: St.Align.START, | ||||
|                                                  y_align: St.Align.START }); | ||||
|         this.actor.add(this.providerIcon, { x_fill: false, | ||||
|                                             y_fill: false, | ||||
|                                             x_align: St.Align.START, | ||||
|                                             y_align: St.Align.START }); | ||||
|  | ||||
|         this._content = new St.BoxLayout({ style_class: 'list-search-results', | ||||
|                                            vertical: true }); | ||||
|         this._container.add(this._content, { expand: true }); | ||||
|         this.actor.add(this._content, { expand: true }); | ||||
|  | ||||
|         this._resultDisplayBin.set_child(this._container); | ||||
|         this._notDisplayedResult = []; | ||||
|         this._terms = []; | ||||
|         this._pendingClear = false; | ||||
|     }, | ||||
|  | ||||
|     _setMoreIconVisible: function(visible) { | ||||
|         this.providerIcon.moreIcon.visible = true; | ||||
|     getResultsForDisplay: function() { | ||||
|         let alreadyVisible = this._pendingClear ? 0 : this.getVisibleResultCount(); | ||||
|         let canDisplay = MAX_LIST_SEARCH_RESULTS_ROWS - alreadyVisible; | ||||
|  | ||||
|         let newResults = this._notDisplayedResult.splice(0, canDisplay); | ||||
|         return newResults; | ||||
|     }, | ||||
|  | ||||
|     _getMaxDisplayedResults: function() { | ||||
|         return MAX_LIST_SEARCH_RESULTS_ROWS; | ||||
|     getVisibleResultCount: function() { | ||||
|         return this._content.get_n_children(); | ||||
|     }, | ||||
|  | ||||
|     _renderResults: function(metas) { | ||||
|     hasMoreResults: function() { | ||||
|         return this._notDisplayedResult.length > 0; | ||||
|     }, | ||||
|  | ||||
|     setResults: function(results, terms) { | ||||
|         // copy the lists | ||||
|         this._notDisplayedResult = results.slice(0); | ||||
|         this._terms = terms.slice(0); | ||||
|         this._pendingClear = true; | ||||
|     }, | ||||
|  | ||||
|     _keyFocusIn: function(icon) { | ||||
|         this.emit('key-focus-in', icon); | ||||
|     }, | ||||
|  | ||||
|     renderResults: function(metas) { | ||||
|         for (let i = 0; i < metas.length; i++) { | ||||
|             let display = new ListSearchResult(this.provider, metas[i], this._terms); | ||||
|             display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn)); | ||||
| @@ -291,12 +243,13 @@ const ListSearchResults = new Lang.Class({ | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _clearResultDisplay: function () { | ||||
|     clear: function () { | ||||
|         this._content.destroy_all_children(); | ||||
|         this._pendingClear = false; | ||||
|     }, | ||||
|  | ||||
|     getFirstResult: function() { | ||||
|         if (this._content.get_n_children() > 0) | ||||
|         if (this.getVisibleResultCount() > 0) | ||||
|             return this._content.get_child_at_index(0)._delegate; | ||||
|         else | ||||
|             return null; | ||||
| @@ -306,24 +259,50 @@ Signals.addSignalMethods(ListSearchResults.prototype); | ||||
|  | ||||
| const GridSearchResults = new Lang.Class({ | ||||
|     Name: 'GridSearchResults', | ||||
|     Extends: SearchResultsBase, | ||||
|  | ||||
|     _init: function(provider) { | ||||
|         this.parent(provider); | ||||
|         this.provider = provider; | ||||
|  | ||||
|         this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS, | ||||
|                                              xAlign: St.Align.START }); | ||||
|         this._bin = new St.Bin({ x_align: St.Align.MIDDLE }); | ||||
|         this._bin.set_child(this._grid.actor); | ||||
|         this.actor = new St.Bin({ x_align: St.Align.MIDDLE }); | ||||
|  | ||||
|         this._resultDisplayBin.set_child(this._bin); | ||||
|         this.actor.set_child(this._grid.actor); | ||||
|  | ||||
|         this._notDisplayedResult = []; | ||||
|         this._terms = []; | ||||
|         this._pendingClear = false; | ||||
|     }, | ||||
|  | ||||
|     _getMaxDisplayedResults: function() { | ||||
|         return this._grid.childrenInRow(this._bin.width) * this._grid.getRowLimit(); | ||||
|     getResultsForDisplay: function() { | ||||
|         let alreadyVisible = this._pendingClear ? 0 : this._grid.visibleItemsCount(); | ||||
|         let canDisplay = this._grid.childrenInRow(this.actor.width) * this._grid.getRowLimit() | ||||
|                          - alreadyVisible; | ||||
|  | ||||
|         let newResults = this._notDisplayedResult.splice(0, canDisplay); | ||||
|         return newResults; | ||||
|     }, | ||||
|  | ||||
|     _renderResults: function(metas) { | ||||
|     getVisibleResultCount: function() { | ||||
|         return this._grid.visibleItemsCount(); | ||||
|     }, | ||||
|  | ||||
|     hasMoreResults: function() { | ||||
|         return this._notDisplayedResult.length > 0; | ||||
|     }, | ||||
|  | ||||
|     setResults: function(results, terms) { | ||||
|         // copy the lists | ||||
|         this._notDisplayedResult = results.slice(0); | ||||
|         this._terms = terms.slice(0); | ||||
|         this._pendingClear = true; | ||||
|     }, | ||||
|  | ||||
|     _keyFocusIn: function(icon) { | ||||
|         this.emit('key-focus-in', icon); | ||||
|     }, | ||||
|  | ||||
|     renderResults: function(metas) { | ||||
|         for (let i = 0; i < metas.length; i++) { | ||||
|             let display = new GridSearchResult(this.provider, metas[i], this._terms); | ||||
|             display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn)); | ||||
| @@ -331,12 +310,13 @@ const GridSearchResults = new Lang.Class({ | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _clearResultDisplay: function () { | ||||
|     clear: function () { | ||||
|         this._grid.removeAll(); | ||||
|         this._pendingClear = false; | ||||
|     }, | ||||
|  | ||||
|     getFirstResult: function() { | ||||
|         if (this._grid.visibleItemsCount() > 0) | ||||
|         if (this.getVisibleResultCount() > 0) | ||||
|             return this._grid.getItemAtIndex(0)._delegate; | ||||
|         else | ||||
|             return null; | ||||
| @@ -386,9 +366,9 @@ const SearchResults = new Lang.Class({ | ||||
|         this._content.add(this._statusBin, { expand: true }); | ||||
|         this._statusBin.add_actor(this._statusText); | ||||
|         this._providers = this._searchSystem.getProviders(); | ||||
|         this._providerDisplays = {}; | ||||
|         this._providerMeta = []; | ||||
|         for (let i = 0; i < this._providers.length; i++) { | ||||
|             this.createProviderDisplay(this._providers[i]); | ||||
|             this.createProviderMeta(this._providers[i]); | ||||
|         } | ||||
|  | ||||
|         this._highlightDefault = false; | ||||
| @@ -406,33 +386,61 @@ const SearchResults = new Lang.Class({ | ||||
|         Util.ensureActorVisibleInScrollView(this._scrollView, icon); | ||||
|     }, | ||||
|  | ||||
|     createProviderDisplay: function(provider) { | ||||
|         let providerDisplay = null; | ||||
|     createProviderMeta: function(provider) { | ||||
|         let providerBox = new St.BoxLayout({ style_class: 'search-section', | ||||
|                                              vertical: true }); | ||||
|         let providerIcon = null; | ||||
|         let resultDisplay = null; | ||||
|  | ||||
|         if (provider.appInfo) { | ||||
|             providerDisplay = new ListSearchResults(provider); | ||||
|             resultDisplay = new ListSearchResults(provider); | ||||
|             providerIcon = resultDisplay.providerIcon; | ||||
|         } else { | ||||
|             providerDisplay = new GridSearchResults(provider); | ||||
|             resultDisplay = new GridSearchResults(provider); | ||||
|         } | ||||
|  | ||||
|         providerDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn)); | ||||
|         this._providerDisplays[provider.id] = providerDisplay; | ||||
|         this._content.add(providerDisplay.actor); | ||||
|         resultDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn)); | ||||
|  | ||||
|         let resultDisplayBin = new St.Bin({ child: resultDisplay.actor, | ||||
|                                             x_fill: true, | ||||
|                                             y_fill: true }); | ||||
|         providerBox.add(resultDisplayBin, { expand: true }); | ||||
|  | ||||
|         let separator = new Separator.HorizontalSeparator({ style_class: 'search-section-separator' }); | ||||
|         providerBox.add(separator.actor); | ||||
|  | ||||
|         this._providerMeta.push({ provider: provider, | ||||
|                                   actor: providerBox, | ||||
|                                   icon: providerIcon, | ||||
|                                   resultDisplay: resultDisplay }); | ||||
|         this._content.add(providerBox); | ||||
|     }, | ||||
|  | ||||
|     destroyProviderDisplay: function(provider) { | ||||
|         this._providerDisplays[provider.id].destroy(); | ||||
|         delete this._providerDisplays[provider.id]; | ||||
|     destroyProviderMeta: function(provider) { | ||||
|         for (let i=0; i < this._providerMeta.length; i++) { | ||||
|             let meta = this._providerMeta[i]; | ||||
|             if (meta.provider == provider) { | ||||
|                 meta.actor.destroy(); | ||||
|                 this._providerMeta.splice(i, 1); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _clearDisplay: function() { | ||||
|         for (let i = 0; i < this._providers.length; i++) { | ||||
|             let provider = this._providers[i]; | ||||
|             let providerDisplay = this._providerDisplays[provider.id]; | ||||
|             providerDisplay.clear(); | ||||
|         for (let i = 0; i < this._providerMeta.length; i++) { | ||||
|             let meta = this._providerMeta[i]; | ||||
|             meta.resultDisplay.clear(); | ||||
|             meta.actor.hide(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _clearDisplayForProvider: function(provider) { | ||||
|         let meta = this._metaForProvider(provider); | ||||
|         meta.resultDisplay.clear(); | ||||
|         meta.actor.hide(); | ||||
|     }, | ||||
|  | ||||
|     reset: function() { | ||||
|         this._searchSystem.reset(); | ||||
|         this._statusBin.hide(); | ||||
| @@ -446,17 +454,20 @@ const SearchResults = new Lang.Class({ | ||||
|         this._statusBin.show(); | ||||
|     }, | ||||
|  | ||||
|     _metaForProvider: function(provider) { | ||||
|         return this._providerMeta[this._providers.indexOf(provider)]; | ||||
|     }, | ||||
|  | ||||
|     _maybeSetInitialSelection: function() { | ||||
|         let newDefaultResult = null; | ||||
|  | ||||
|         for (let i = 0; i < this._providers.length; i++) { | ||||
|             let provider = this._providers[i]; | ||||
|             let display = this._providerDisplays[provider.id]; | ||||
|         for (let i = 0; i < this._providerMeta.length; i++) { | ||||
|             let meta = this._providerMeta[i]; | ||||
|  | ||||
|             if (!display.actor.visible) | ||||
|             if (!meta.actor.visible) | ||||
|                 continue; | ||||
|  | ||||
|             let firstResult = display.getFirstResult(); | ||||
|             let firstResult = meta.resultDisplay.getFirstResult(); | ||||
|             if (firstResult) { | ||||
|                 newDefaultResult = firstResult; | ||||
|                 break; // select this one! | ||||
| @@ -476,14 +487,11 @@ const SearchResults = new Lang.Class({ | ||||
|     _updateStatusText: function () { | ||||
|         let haveResults = false; | ||||
|  | ||||
|         for (let i = 0; i < this._providers.length; i++) { | ||||
|             let provider = this._providers[i]; | ||||
|             let display = this._providerDisplays[provider.id]; | ||||
|             if (display.getFirstResult()) { | ||||
|         for (let i = 0; i < this._providerMeta.length; ++i) | ||||
|             if (this._providerMeta[i].resultDisplay.getFirstResult()) { | ||||
|                 haveResults = true; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (!haveResults) { | ||||
|             this._statusText.set_text(_("No results.")); | ||||
| @@ -496,12 +504,42 @@ const SearchResults = new Lang.Class({ | ||||
|     _updateResults: function(searchSystem, results) { | ||||
|         let terms = searchSystem.getTerms(); | ||||
|         let [provider, providerResults] = results; | ||||
|         let display = this._providerDisplays[provider.id]; | ||||
|         let meta = this._metaForProvider(provider); | ||||
|  | ||||
|         display.updateSearch(providerResults, terms, Lang.bind(this, function() { | ||||
|         if (providerResults.length == 0) { | ||||
|             this._clearDisplayForProvider(provider); | ||||
|             meta.resultDisplay.setResults([], []); | ||||
|             this._maybeSetInitialSelection(); | ||||
|             this._updateStatusText(); | ||||
|         })); | ||||
|         } else { | ||||
|             meta.resultDisplay.setResults(providerResults, terms); | ||||
|             let results = meta.resultDisplay.getResultsForDisplay(); | ||||
|  | ||||
|             if (meta.icon) | ||||
|                 meta.icon.moreIcon.visible = | ||||
|                     meta.resultDisplay.hasMoreResults() && | ||||
|                     provider.canLaunchSearch; | ||||
|  | ||||
|             provider.getResultMetas(results, Lang.bind(this, function(metas) { | ||||
|                 this._clearDisplayForProvider(provider); | ||||
|                 meta.actor.show(); | ||||
|  | ||||
|                 // Hiding drops the key focus if we have it | ||||
|                 let focus = global.stage.get_key_focus(); | ||||
|                 // To avoid CSS transitions causing flickering when | ||||
|                 // the first search result stays the same, we hide the | ||||
|                 // content while filling in the results. | ||||
|                 this._content.hide(); | ||||
|  | ||||
|                 meta.resultDisplay.renderResults(metas); | ||||
|                 this._maybeSetInitialSelection(); | ||||
|                 this._updateStatusText(); | ||||
|  | ||||
|                 this._content.show(); | ||||
|                 if (this._content.contains(focus)) | ||||
|                     global.stage.set_key_focus(focus); | ||||
|             })); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     activateDefault: function() { | ||||
|   | ||||
| @@ -16,7 +16,6 @@ const _modes = { | ||||
|     'restrictive': { | ||||
|         parentMode: null, | ||||
|         stylesheetName: 'gnome-shell.css', | ||||
|         overridesSchema: 'org.gnome.shell.overrides', | ||||
|         hasOverview: false, | ||||
|         showCalendarEvents: false, | ||||
|         allowSettings: false, | ||||
| @@ -46,7 +45,7 @@ const _modes = { | ||||
|         unlockDialog: imports.gdm.loginDialog.LoginDialog, | ||||
|         components: ['polkitAgent'], | ||||
|         panel: { | ||||
|             left: [], | ||||
|             left: ['logo'], | ||||
|             center: ['dateMenu'], | ||||
|             right: ['a11yGreeter', 'display', 'keyboard', | ||||
|                     'volume', 'battery', 'powerMenu'] | ||||
| @@ -79,6 +78,17 @@ const _modes = { | ||||
|         panelStyle: 'unlock-screen' | ||||
|     }, | ||||
|  | ||||
|     'initial-setup': { | ||||
|         hasWindows: true, | ||||
|         isPrimary: true, | ||||
|         components: ['keyring'], | ||||
|         panel: { | ||||
|             left: [], | ||||
|             center: ['dateMenu'], | ||||
|             right: ['a11yGreeter', 'keyboard', 'volume', 'battery'] | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     'user': { | ||||
|         hasOverview: true, | ||||
|         showCalendarEvents: true, | ||||
| @@ -185,10 +195,6 @@ const SessionMode = new Lang.Class({ | ||||
|         return this._modeStack[this._modeStack.length - 1]; | ||||
|     }, | ||||
|  | ||||
|     get allowScreencast() { | ||||
|         return this.components.indexOf('recorder') != -1; | ||||
|     }, | ||||
|  | ||||
|     _sync: function() { | ||||
|         let params = this._modes[this.currentMode]; | ||||
|         let defaults; | ||||
|   | ||||
| @@ -12,7 +12,6 @@ const ExtensionDownloader = imports.ui.extensionDownloader; | ||||
| const ExtensionUtils = imports.misc.extensionUtils; | ||||
| const Hash = imports.misc.hash; | ||||
| const Main = imports.ui.main; | ||||
| const Screencast = imports.ui.screencast; | ||||
| const Screenshot = imports.ui.screenshot; | ||||
|  | ||||
| const GnomeShellIface = <interface name="org.gnome.Shell"> | ||||
| @@ -21,7 +20,6 @@ const GnomeShellIface = <interface name="org.gnome.Shell"> | ||||
|     <arg type="b" direction="out" name="success" /> | ||||
|     <arg type="s" direction="out" name="result" /> | ||||
| </method> | ||||
| <method name="FocusSearch"/> | ||||
| <method name="ShowOSD"> | ||||
|     <arg type="a{sv}" direction="in" name="params"/> | ||||
| </method> | ||||
| @@ -72,7 +70,6 @@ const GnomeShell = new Lang.Class({ | ||||
|         this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell'); | ||||
|  | ||||
|         this._extensionsService = new GnomeShellExtensions(); | ||||
|         this._screencastService = new Screencast.ScreencastService(); | ||||
|         this._screenshotService = new Screenshot.ScreenshotService(); | ||||
|  | ||||
|         this._grabbedAccelerators = new Hash.Map(); | ||||
| @@ -100,7 +97,7 @@ const GnomeShell = new Lang.Class({ | ||||
|      */ | ||||
|     Eval: function(code) { | ||||
|         if (!global.settings.get_boolean('development-tools')) | ||||
|             return [false, '']; | ||||
|             return [false, null]; | ||||
|  | ||||
|         let returnValue; | ||||
|         let success; | ||||
| @@ -117,10 +114,6 @@ const GnomeShell = new Lang.Class({ | ||||
|         return [success, returnValue]; | ||||
|     }, | ||||
|  | ||||
|     FocusSearch: function() { | ||||
|         Main.overview.focusSearch(); | ||||
|     }, | ||||
|  | ||||
|     ShowOSD: function(params) { | ||||
|         for (let param in params) | ||||
|             params[param] = params[param].deep_unpack(); | ||||
|   | ||||
| @@ -14,7 +14,9 @@ const EntryMenu = new Lang.Class({ | ||||
|     Name: 'ShellEntryMenu', | ||||
|     Extends: PopupMenu.PopupMenu, | ||||
|  | ||||
|     _init: function(entry) { | ||||
|     _init: function(entry, params) { | ||||
|         params = Params.parse (params, { isPassword: false }); | ||||
|  | ||||
|         this.parent(entry, 0, St.Side.TOP); | ||||
|  | ||||
|         this.actor.add_style_class_name('entry-context-menu'); | ||||
| @@ -35,6 +37,8 @@ const EntryMenu = new Lang.Class({ | ||||
|         this._pasteItem = item; | ||||
|  | ||||
|         this._passwordItem = null; | ||||
|         if (params.isPassword) | ||||
| 	    this._makePasswordItem(); | ||||
|  | ||||
|         Main.uiGroup.add_actor(this.actor); | ||||
|         this.actor.hide(); | ||||
| @@ -49,21 +53,19 @@ const EntryMenu = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     get isPassword() { | ||||
|         return this._passwordItem != null; | ||||
| 	return this._passwordItem != null; | ||||
|     }, | ||||
|  | ||||
|     set isPassword(v) { | ||||
|         if (v == this.isPassword) | ||||
|             return; | ||||
| 	if (v == this.isPassword) | ||||
| 	    return; | ||||
|  | ||||
|         if (v) { | ||||
|             this._makePasswordItem(); | ||||
|             this._entry.input_purpose = Gtk.InputPurpose.PASSWORD; | ||||
|         } else { | ||||
|             this._passwordItem.destroy(); | ||||
|             this._passwordItem = null; | ||||
|             this._entry.input_purpose = Gtk.InputPurpose.FREE_FORM; | ||||
|         } | ||||
| 	if (v) | ||||
| 	    this._makePasswordItem(); | ||||
| 	else { | ||||
| 	    this._passwordItem.destroy(); | ||||
| 	    this._passwordItem = null; | ||||
| 	} | ||||
|     }, | ||||
|  | ||||
|     open: function(animate) { | ||||
| @@ -80,6 +82,11 @@ const EntryMenu = new Lang.Class({ | ||||
|             this.actor.grab_key_focus(); | ||||
|     }, | ||||
|  | ||||
|     close: function(animate) { | ||||
|         this._entry.grab_key_focus(); | ||||
|         this.parent(animate); | ||||
|     }, | ||||
|  | ||||
|     _updateCopyItem: function() { | ||||
|         let selection = this._entry.clutter_text.get_selection(); | ||||
|         this._copyItem.setSensitive(!this._entry.clutter_text.password_char && | ||||
| @@ -153,10 +160,7 @@ function addContextMenu(entry, params) { | ||||
|     if (entry.menu) | ||||
|         return; | ||||
|  | ||||
|     params = Params.parse (params, { isPassword: false }); | ||||
|  | ||||
|     entry.menu = new EntryMenu(entry); | ||||
|     entry.menu.isPassword = params.isPassword; | ||||
|     entry.menu = new EntryMenu(entry, params); | ||||
|     entry._menuManager = new PopupMenu.PopupMenuManager({ actor: entry }); | ||||
|     entry._menuManager.addMenu(entry.menu); | ||||
|  | ||||
|   | ||||
							
								
								
									
										206
									
								
								js/ui/slider.js
									
									
									
									
									
								
							
							
						
						
									
										206
									
								
								js/ui/slider.js
									
									
									
									
									
								
							| @@ -1,206 +0,0 @@ | ||||
| /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ | ||||
|  | ||||
| const Cairo = imports.cairo; | ||||
| const Clutter = imports.gi.Clutter; | ||||
| const Lang = imports.lang; | ||||
| const St = imports.gi.St; | ||||
| const Signals = imports.signals; | ||||
|  | ||||
| const SLIDER_SCROLL_STEP = 0.05; /* Slider scrolling step in % */ | ||||
|  | ||||
| const Slider = new Lang.Class({ | ||||
|     Name: "Slider", | ||||
|  | ||||
|     _init: function(value) { | ||||
|         if (isNaN(value)) | ||||
|             // Avoid spreading NaNs around | ||||
|             throw TypeError('The slider value must be a number'); | ||||
|         this._value = Math.max(Math.min(value, 1), 0); | ||||
|  | ||||
|         this.actor = new St.DrawingArea({ style_class: 'slider', | ||||
|                                           can_focus: true, | ||||
|                                           reactive: true }); | ||||
|         this.actor.connect('repaint', Lang.bind(this, this._sliderRepaint)); | ||||
|         this.actor.connect('button-press-event', Lang.bind(this, this._startDragging)); | ||||
|         this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); | ||||
|         this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent)); | ||||
|  | ||||
|         this._releaseId = this._motionId = 0; | ||||
|         this._dragging = false; | ||||
|     }, | ||||
|  | ||||
|     setValue: function(value) { | ||||
|         if (isNaN(value)) | ||||
|             throw TypeError('The slider value must be a number'); | ||||
|  | ||||
|         this._value = Math.max(Math.min(value, 1), 0); | ||||
|         this.actor.queue_repaint(); | ||||
|     }, | ||||
|  | ||||
|     _sliderRepaint: function(area) { | ||||
|         let cr = area.get_context(); | ||||
|         let themeNode = area.get_theme_node(); | ||||
|         let [width, height] = area.get_surface_size(); | ||||
|  | ||||
|         let handleRadius = themeNode.get_length('-slider-handle-radius'); | ||||
|  | ||||
|         let handleBorderWidth = themeNode.get_length('-slider-handle-border-width'); | ||||
|         let [hasHandleColor, handleBorderColor] = | ||||
|             themeNode.lookup_color('-slider-handle-border-color', false); | ||||
|  | ||||
|         let sliderHeight = themeNode.get_length('-slider-height'); | ||||
|  | ||||
|         let sliderBorderWidth = themeNode.get_length('-slider-border-width'); | ||||
|         let sliderBorderRadius = Math.min(width, sliderHeight) / 2; | ||||
|  | ||||
|         let sliderBorderColor = themeNode.get_color('-slider-border-color'); | ||||
|         let sliderColor = themeNode.get_color('-slider-background-color'); | ||||
|  | ||||
|         let sliderActiveBorderColor = themeNode.get_color('-slider-active-border-color'); | ||||
|         let sliderActiveColor = themeNode.get_color('-slider-active-background-color'); | ||||
|  | ||||
|         const TAU = Math.PI * 2; | ||||
|  | ||||
|         let handleX = handleRadius + (width - 2 * handleRadius) * this._value; | ||||
|  | ||||
|         cr.arc(sliderBorderRadius + sliderBorderWidth, height / 2, sliderBorderRadius, TAU * 1/4, TAU * 3/4); | ||||
|         cr.lineTo(handleX, (height - sliderHeight) / 2); | ||||
|         cr.lineTo(handleX, (height + sliderHeight) / 2); | ||||
|         cr.lineTo(sliderBorderRadius + sliderBorderWidth, (height + sliderHeight) / 2); | ||||
|         Clutter.cairo_set_source_color(cr, sliderActiveColor); | ||||
|         cr.fillPreserve(); | ||||
|         Clutter.cairo_set_source_color(cr, sliderActiveBorderColor); | ||||
|         cr.setLineWidth(sliderBorderWidth); | ||||
|         cr.stroke(); | ||||
|  | ||||
|         cr.arc(width - sliderBorderRadius - sliderBorderWidth, height / 2, sliderBorderRadius, TAU * 3/4, TAU * 1/4); | ||||
|         cr.lineTo(handleX, (height + sliderHeight) / 2); | ||||
|         cr.lineTo(handleX, (height - sliderHeight) / 2); | ||||
|         cr.lineTo(width - sliderBorderRadius - sliderBorderWidth, (height - sliderHeight) / 2); | ||||
|         Clutter.cairo_set_source_color(cr, sliderColor); | ||||
|         cr.fillPreserve(); | ||||
|         Clutter.cairo_set_source_color(cr, sliderBorderColor); | ||||
|         cr.setLineWidth(sliderBorderWidth); | ||||
|         cr.stroke(); | ||||
|  | ||||
|         let handleY = height / 2; | ||||
|  | ||||
|         let color = themeNode.get_foreground_color(); | ||||
|         Clutter.cairo_set_source_color(cr, color); | ||||
|         cr.arc(handleX, handleY, handleRadius, 0, 2 * Math.PI); | ||||
|         cr.fillPreserve(); | ||||
|         if (hasHandleColor && handleBorderWidth) { | ||||
|             Clutter.cairo_set_source_color(cr, handleBorderColor); | ||||
|             cr.setLineWidth(handleBorderWidth); | ||||
|             cr.stroke(); | ||||
|         } | ||||
|         cr.$dispose(); | ||||
|     }, | ||||
|  | ||||
|     _startDragging: function(actor, event) { | ||||
|         if (this._dragging) // don't allow two drags at the same time | ||||
|             return false; | ||||
|  | ||||
|         this._dragging = true; | ||||
|  | ||||
|         // FIXME: we should only grab the specific device that originated | ||||
|         // the event, but for some weird reason events are still delivered | ||||
|         // outside the slider if using clutter_grab_pointer_for_device | ||||
|         Clutter.grab_pointer(this.actor); | ||||
|         this._releaseId = this.actor.connect('button-release-event', Lang.bind(this, this._endDragging)); | ||||
|         this._motionId = this.actor.connect('motion-event', Lang.bind(this, this._motionEvent)); | ||||
|         let absX, absY; | ||||
|         [absX, absY] = event.get_coords(); | ||||
|         this._moveHandle(absX, absY); | ||||
|  | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _endDragging: function() { | ||||
|         if (this._dragging) { | ||||
|             this.actor.disconnect(this._releaseId); | ||||
|             this.actor.disconnect(this._motionId); | ||||
|  | ||||
|             Clutter.ungrab_pointer(); | ||||
|             this._dragging = false; | ||||
|  | ||||
|             this.emit('drag-end'); | ||||
|         } | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     scroll: function(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.min(Math.max(0, this._value + delta), 1); | ||||
|  | ||||
|         this.actor.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(); | ||||
|         this._moveHandle(absX, absY); | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _onKeyPressEvent: function (actor, event) { | ||||
|         let key = event.get_key_symbol(); | ||||
|         if (key == Clutter.KEY_Right || key == Clutter.KEY_Left) { | ||||
|             let delta = key == Clutter.KEY_Right ? 0.1 : -0.1; | ||||
|             this._value = Math.max(0, Math.min(this._value + delta, 1)); | ||||
|             this._slider.queue_repaint(); | ||||
|             this.emit('value-changed', this._value); | ||||
|             this.emit('drag-end'); | ||||
|             return true; | ||||
|         } | ||||
|         return false; | ||||
|     }, | ||||
|  | ||||
|     _moveHandle: function(absX, absY) { | ||||
|         let relX, relY, sliderX, sliderY; | ||||
|         [sliderX, sliderY] = this.actor.get_transformed_position(); | ||||
|         relX = absX - sliderX; | ||||
|         relY = absY - sliderY; | ||||
|  | ||||
|         let width = this.actor.width; | ||||
|         let handleRadius = this.actor.get_theme_node().get_length('-slider-handle-radius'); | ||||
|  | ||||
|         let newvalue; | ||||
|         if (relX < handleRadius) | ||||
|             newvalue = 0; | ||||
|         else if (relX > width - handleRadius) | ||||
|             newvalue = 1; | ||||
|         else | ||||
|             newvalue = (relX - handleRadius) / (width - 2 * handleRadius); | ||||
|         this._value = newvalue; | ||||
|         this.actor.queue_repaint(); | ||||
|         this.emit('value-changed', this._value); | ||||
|     }, | ||||
|  | ||||
|     get value() { | ||||
|         return this._value; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| Signals.addSignalMethods(Slider.prototype); | ||||
| @@ -86,7 +86,6 @@ const Indicator = new Lang.Class({ | ||||
|         this._applet.connect('pincode-request', Lang.bind(this, this._pinRequest)); | ||||
|         this._applet.connect('confirm-request', Lang.bind(this, this._confirmRequest)); | ||||
|         this._applet.connect('auth-request', Lang.bind(this, this._authRequest)); | ||||
|         this._applet.connect('auth-service-request', Lang.bind(this, this._authServiceRequest)); | ||||
|         this._applet.connect('cancel-request', Lang.bind(this, this._cancelRequest)); | ||||
|     }, | ||||
|  | ||||
| @@ -293,14 +292,9 @@ const Indicator = new Lang.Class({ | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _authRequest: function(applet, device_path, name, long_name) { | ||||
|     _authRequest: function(applet, device_path, name, long_name, uuid) { | ||||
|         this._ensureSource(); | ||||
|         this._source.notify(new AuthNotification(this._source, this._applet, device_path, name, long_name)); | ||||
|     }, | ||||
|  | ||||
|     _authServiceRequest: function(applet, device_path, name, long_name, uuid) { | ||||
|         this._ensureSource(); | ||||
|         this._source.notify(new AuthServiceNotification(this._source, this._applet, device_path, name, long_name, uuid)); | ||||
|         this._source.notify(new AuthNotification(this._source, this._applet, device_path, name, long_name, uuid)); | ||||
|     }, | ||||
|  | ||||
|     _confirmRequest: function(applet, device_path, name, long_name, pin) { | ||||
| @@ -322,34 +316,6 @@ const AuthNotification = new Lang.Class({ | ||||
|     Name: 'AuthNotification', | ||||
|     Extends: MessageTray.Notification, | ||||
|  | ||||
|     _init: function(source, applet, device_path, name, long_name) { | ||||
|         this.parent(source, | ||||
|                     _("Bluetooth"), | ||||
|                     _("Authorization request from %s").format(name), | ||||
|                     { customContent: true }); | ||||
|         this.setResident(true); | ||||
|  | ||||
|         this._applet = applet; | ||||
|         this._devicePath = device_path; | ||||
|         this.addBody(_("Device %s wants to pair with this computer").format(long_name)); | ||||
|  | ||||
|         this.addButton('allow', _("Allow")); | ||||
|         this.addButton('deny', _("Deny")); | ||||
|  | ||||
|         this.connect('action-invoked', Lang.bind(this, function(self, action) { | ||||
|             if (action == 'allow') | ||||
|                 this._applet.agent_reply_confirm(this._devicePath, true); | ||||
|             else | ||||
|                 this._applet.agent_reply_confirm(this._devicePath, false); | ||||
|             this.destroy(); | ||||
|         })); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const AuthServiceNotification = new Lang.Class({ | ||||
|     Name: 'AuthServiceNotification', | ||||
|     Extends: MessageTray.Notification, | ||||
|  | ||||
|     _init: function(source, applet, device_path, name, long_name, uuid) { | ||||
|         this.parent(source, | ||||
|                     _("Bluetooth"), | ||||
| @@ -368,14 +334,14 @@ const AuthServiceNotification = new Lang.Class({ | ||||
|         this.connect('action-invoked', Lang.bind(this, function(self, action) { | ||||
|             switch (action) { | ||||
|             case 'always-grant': | ||||
|                 this._applet.agent_reply_auth_service(this._devicePath, true, true); | ||||
|                 this._applet.agent_reply_auth(this._devicePath, true, true); | ||||
|                 break; | ||||
|             case 'grant': | ||||
|                 this._applet.agent_reply_auth_service(this._devicePath, true, false); | ||||
|                 this._applet.agent_reply_auth(this._devicePath, true, false); | ||||
|                 break; | ||||
|             case 'reject': | ||||
|             default: | ||||
|                 this._applet.agent_reply_auth_service(this._devicePath, false, false); | ||||
|                 this._applet.agent_reply_auth(this._devicePath, false, false); | ||||
|             } | ||||
|             this.destroy(); | ||||
|         })); | ||||
| @@ -397,7 +363,7 @@ const ConfirmNotification = new Lang.Class({ | ||||
|         this._applet = applet; | ||||
|         this._devicePath = device_path; | ||||
|         this.addBody(_("Device %s wants to pair with this computer").format(long_name)); | ||||
|         this.addBody(_("Please confirm whether the Passkey '%06d' matches the one on the device.").format(pin)); | ||||
|         this.addBody(_("Please confirm whether the PIN '%06d' matches the one on the device.").format(pin)); | ||||
|  | ||||
|         /* Translators: this is the verb, not the noun */ | ||||
|         this.addButton('matches', _("Matches")); | ||||
|   | ||||
| @@ -33,9 +33,9 @@ const KEY_INPUT_SOURCES = 'sources'; | ||||
| const INPUT_SOURCE_TYPE_XKB = 'xkb'; | ||||
| const INPUT_SOURCE_TYPE_IBUS = 'ibus'; | ||||
|  | ||||
| // This is the longest we'll keep the keyboard frozen until an input | ||||
| // This is longest we'll keep the keyboard frozen until an input | ||||
| // source is active. | ||||
| const MAX_INPUT_SOURCE_ACTIVATION_TIME = 4000; // ms | ||||
| const MAX_INPUT_SOURCE_ACTIVATION_TIME = 2000; // ms | ||||
|  | ||||
| const BUS_NAME = 'org.gnome.SettingsDaemon.Keyboard'; | ||||
| const OBJECT_PATH = '/org/gnome/SettingsDaemon/Keyboard'; | ||||
| @@ -57,7 +57,10 @@ function releaseKeyboard() { | ||||
| } | ||||
|  | ||||
| function holdKeyboard() { | ||||
|     global.freeze_keyboard(global.get_current_time()); | ||||
|     if (Main.modalCount > 0) | ||||
|         global.display.freeze_keyboard(global.get_current_time()); | ||||
|     else | ||||
|         global.display.grab_keyboard(global.get_current_time()); | ||||
| } | ||||
|  | ||||
| const IBusManager = new Lang.Class({ | ||||
| @@ -72,24 +75,26 @@ const IBusManager = new Lang.Class({ | ||||
|         this._readyCallback = readyCallback; | ||||
|         this._candidatePopup = new IBusCandidatePopup.CandidatePopup(); | ||||
|  | ||||
|         this._ibus = null; | ||||
|         this._panelService = null; | ||||
|         this._engines = {}; | ||||
|         this._ready = false; | ||||
|         this._registerPropertiesId = 0; | ||||
|         this._currentEngineName = null; | ||||
|  | ||||
|         this._ibus = IBus.Bus.new_async(); | ||||
|         this._ibus.connect('connected', Lang.bind(this, this._onConnected)); | ||||
|         this._ibus.connect('disconnected', Lang.bind(this, this._clear)); | ||||
|         // Need to set this to get 'global-engine-changed' emitions | ||||
|         this._ibus.set_watch_ibus_signal(true); | ||||
|         this._ibus.connect('global-engine-changed', Lang.bind(this, this._engineChanged)); | ||||
|         this._nameWatcherId = Gio.DBus.session.watch_name(IBus.SERVICE_IBUS, | ||||
|                                                           Gio.BusNameWatcherFlags.NONE, | ||||
|                                                           Lang.bind(this, this._onNameAppeared), | ||||
|                                                           Lang.bind(this, this._clear)); | ||||
|     }, | ||||
|  | ||||
|     _clear: function() { | ||||
|         if (this._panelService) | ||||
|             this._panelService.destroy(); | ||||
|         if (this._ibus) | ||||
|             this._ibus.destroy(); | ||||
|  | ||||
|         this._ibus = null; | ||||
|         this._panelService = null; | ||||
|         this._candidatePopup.setPanelService(null); | ||||
|         this._engines = {}; | ||||
| @@ -101,12 +106,18 @@ const IBusManager = new Lang.Class({ | ||||
|             this._readyCallback(false); | ||||
|     }, | ||||
|  | ||||
|     _onNameAppeared: function() { | ||||
|         this._ibus = IBus.Bus.new_async(); | ||||
|         this._ibus.connect('connected', Lang.bind(this, this._onConnected)); | ||||
|     }, | ||||
|  | ||||
|     _onConnected: function() { | ||||
|         this._ibus.list_engines_async(-1, null, Lang.bind(this, this._initEngines)); | ||||
|         this._ibus.request_name_async(IBus.SERVICE_PANEL, | ||||
|                                       IBus.BusNameFlag.REPLACE_EXISTING, | ||||
|                                       -1, null, | ||||
|                                       Lang.bind(this, this._initPanelService)); | ||||
|         this._ibus.connect('disconnected', Lang.bind(this, this._clear)); | ||||
|     }, | ||||
|  | ||||
|     _initEngines: function(ibus, result) { | ||||
| @@ -128,6 +139,9 @@ const IBusManager = new Lang.Class({ | ||||
|             this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(), | ||||
|                                                          object_path: IBus.PATH_PANEL }); | ||||
|             this._candidatePopup.setPanelService(this._panelService); | ||||
|             // Need to set this to get 'global-engine-changed' emitions | ||||
|             this._ibus.set_watch_ibus_signal(true); | ||||
|             this._ibus.connect('global-engine-changed', Lang.bind(this, this._engineChanged)); | ||||
|             this._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) { | ||||
| @@ -156,9 +170,6 @@ const IBusManager = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _engineChanged: function(bus, engineName) { | ||||
|         if (!this._ready) | ||||
|             return; | ||||
|  | ||||
|         this._currentEngineName = engineName; | ||||
|  | ||||
|         if (this._registerPropertiesId != 0) | ||||
| @@ -249,6 +260,7 @@ const InputSource = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     activate: function() { | ||||
|         holdKeyboard(); | ||||
|         this.emit('activate'); | ||||
|     }, | ||||
| }); | ||||
| @@ -281,11 +293,11 @@ const InputSourcePopup = new Lang.Class({ | ||||
|         this._select(this._selectedIndex); | ||||
|     }, | ||||
|  | ||||
|     _keyPressHandler: function(keysym, backwards, action) { | ||||
|     _keyPressHandler: function(keysym, _ignored, action) { | ||||
|         if (action == this._action) | ||||
|             this._select(backwards ? this._previous() : this._next()); | ||||
|             this._select(this._next()); | ||||
|         else if (action == this._actionBackward) | ||||
|             this._select(backwards ? this._next() : this._previous()); | ||||
|             this._select(this._previous()); | ||||
|         else if (keysym == Clutter.Left) | ||||
|             this._select(this._previous()); | ||||
|         else if (keysym == Clutter.Right) | ||||
| @@ -355,14 +367,13 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|         this._keybindingAction = | ||||
|             Main.wm.addKeybinding('switch-input-source', | ||||
|                                   new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }), | ||||
|                                   Meta.KeyBindingFlags.REVERSES, | ||||
|                                   Meta.KeyBindingFlags.NONE, | ||||
|                                   Shell.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, | ||||
|                                   Meta.KeyBindingFlags.NONE, | ||||
|                                   Shell.KeyBindingMode.ALL, | ||||
|                                   Lang.bind(this, this._switchInputSource)); | ||||
|         this._settings = new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_SCHEMA }); | ||||
| @@ -388,8 +399,6 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|                                                              if (error) | ||||
|                                                                  log(error.message); | ||||
|                                                          }); | ||||
|         this._keyboardManager.g_default_timeout = MAX_INPUT_SOURCE_ACTIVATION_TIME; | ||||
|  | ||||
|         global.display.connect('modifiers-accelerator-activated', Lang.bind(this, this._modifiersSwitcher)); | ||||
|  | ||||
|         this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); | ||||
| @@ -429,7 +438,7 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|         let sourceIndexes = Object.keys(this._inputSources); | ||||
|         if (sourceIndexes.length == 0) { | ||||
|             releaseKeyboard(); | ||||
|             return true; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let is = this._currentSource; | ||||
| @@ -444,7 +453,6 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|             nextIndex += 1; | ||||
|  | ||||
|         is.activate(); | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _switchInputSource: function(display, screen, window, binding) { | ||||
| @@ -452,19 +460,18 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|             return; | ||||
|  | ||||
|         // HACK: Fall back on simple input source switching since we | ||||
|         // can't show a popup switcher while a GrabHelper grab is in | ||||
|         // effect without considerable work to consolidate the usage | ||||
|         // of pushModal/popModal and grabHelper. See | ||||
|         // can't show a popup switcher while the message tray is up | ||||
|         // without considerable work to consolidate the usage of | ||||
|         // pushModal/popModal and grabHelper. See | ||||
|         // https://bugzilla.gnome.org/show_bug.cgi?id=695143 . | ||||
|         if (Main.keybindingMode == Shell.KeyBindingMode.MESSAGE_TRAY || | ||||
|             Main.keybindingMode == Shell.KeyBindingMode.TOPBAR_POPUP) { | ||||
|         if (Main.keybindingMode == Shell.KeyBindingMode.MESSAGE_TRAY) { | ||||
|             this._modifiersSwitcher(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let popup = new InputSourcePopup(this._mruSources, this._keybindingAction, this._keybindingActionBackward); | ||||
|         let modifiers = binding.get_modifiers(); | ||||
|         let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK; | ||||
|         let backwards = false;  // Not using this | ||||
|         if (!popup.show(backwards, binding.get_name(), binding.get_mask())) | ||||
|             popup.destroy(); | ||||
|     }, | ||||
| @@ -478,7 +485,7 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|         [oldSource, this._currentSource] = [this._currentSource, newSource]; | ||||
|  | ||||
|         if (oldSource) { | ||||
|             oldSource.menuItem.setOrnament(PopupMenu.Ornament.NONE); | ||||
|             oldSource.menuItem.setShowDot(false); | ||||
|             oldSource.indicatorLabel.hide(); | ||||
|         } | ||||
|  | ||||
| @@ -496,7 +503,7 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|  | ||||
|         this.actor.show(); | ||||
|  | ||||
|         newSource.menuItem.setOrnament(PopupMenu.Ornament.DOT); | ||||
|         newSource.menuItem.setShowDot(true); | ||||
|         newSource.indicatorLabel.show(); | ||||
|  | ||||
|         this._buildPropSection(newSource.properties); | ||||
| @@ -520,7 +527,6 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|  | ||||
|         this._inputSources = {}; | ||||
|         this._ibusSources = {}; | ||||
|         this._currentSource = null; | ||||
|  | ||||
|         let inputSourcesByShortName = {}; | ||||
|  | ||||
| @@ -549,8 +555,10 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|             let is = new InputSource(type, id, displayName, shortName, i); | ||||
|  | ||||
|             is.connect('activate', Lang.bind(this, function() { | ||||
|                 holdKeyboard(); | ||||
|                 this._keyboardManager.SetInputSourceRemote(is.index, releaseKeyboard); | ||||
|                 let inVariant = new GLib.Variant('(u)', [is.index]); | ||||
|                 this._keyboardManager.call('SetInputSource', inVariant, 0, | ||||
|                                            MAX_INPUT_SOURCE_ACTIVATION_TIME, | ||||
|                                            null, releaseKeyboard); | ||||
|             })); | ||||
|  | ||||
|             if (!(is.shortName in inputSourcesByShortName)) | ||||
| @@ -720,8 +728,7 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|                 item.prop = prop; | ||||
|                 radioGroup.push(item); | ||||
|                 item.radioGroup = radioGroup; | ||||
|                 item.setOrnament(prop.get_state() == IBus.PropState.CHECKED ? | ||||
|                                  PopupMenu.Ornament.DOT : PopupMenu.Ornament.NONE); | ||||
|                 item.setShowDot(prop.get_state() == IBus.PropState.CHECKED); | ||||
|                 item.connect('activate', Lang.bind(this, function() { | ||||
|                     if (item.prop.get_state() == IBus.PropState.CHECKED) | ||||
|                         return; | ||||
| @@ -729,12 +736,12 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|                     let group = item.radioGroup; | ||||
|                     for (let i = 0; i < group.length; ++i) { | ||||
|                         if (group[i] == item) { | ||||
|                             item.setOrnament(PopupMenu.Ornament.DOT); | ||||
|                             item.setShowDot(true); | ||||
|                             item.prop.set_state(IBus.PropState.CHECKED); | ||||
|                             this._ibusManager.activateProperty(item.prop.get_key(), | ||||
|                                                                IBus.PropState.CHECKED); | ||||
|                         } else { | ||||
|                             group[i].setOrnament(PopupMenu.Ornament.NONE); | ||||
|                             group[i].setShowDot(false); | ||||
|                             group[i].prop.set_state(IBus.PropState.UNCHECKED); | ||||
|                             this._ibusManager.activateProperty(group[i].prop.get_key(), | ||||
|                                                                IBus.PropState.UNCHECKED); | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -10,6 +10,8 @@ const Signals = imports.signals; | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
|  | ||||
| const VOLUME_ADJUSTMENT_STEP = 0.05; /* Volume adjustment step in % */ | ||||
|  | ||||
| const VOLUME_NOTIFY_ID = 1; | ||||
|  | ||||
| // Each Gvc.MixerControl is a connection to PulseAudio, | ||||
| @@ -42,6 +44,7 @@ const StreamSlider = new Lang.Class({ | ||||
|         this.item.addMenuItem(this._slider); | ||||
|  | ||||
|         this._stream = null; | ||||
|         this._shouldShow = true; | ||||
|     }, | ||||
|  | ||||
|     get stream() { | ||||
| @@ -304,7 +307,7 @@ const Indicator = new Lang.Class({ | ||||
|             this._headphoneIcon.visible = value; | ||||
|         })); | ||||
|  | ||||
|         this._headphoneIcon = this.addIcon(new Gio.ThemedIcon({ name: 'audio-headphones-symbolic' })); | ||||
|         this._headphoneIcon = this.addIcon(new Gio.ThemedIcon({ name: 'headphones-symbolic' })); | ||||
|         this._headphoneIcon.visible = false; | ||||
|  | ||||
|         this.menu.addMenuItem(this._volumeMenu); | ||||
|   | ||||
| @@ -17,6 +17,7 @@ const ModalDialog = imports.ui.modalDialog; | ||||
| const Panel = imports.ui.panel; | ||||
| const ShellEntry = imports.ui.shellEntry; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const UserMenu = imports.ui.userMenu; | ||||
| const UserWidget = imports.ui.userWidget; | ||||
|  | ||||
| const Batch = imports.gdm.batch; | ||||
| @@ -90,6 +91,9 @@ const UnlockDialog = new Lang.Class({ | ||||
|         this._promptLoginHint.hide(); | ||||
|         this.contentLayout.add_actor(this._promptLoginHint); | ||||
|  | ||||
|         this._workSpinner = new Panel.AnimatedIcon('process-working.svg', LoginDialog.WORK_SPINNER_ICON_SIZE); | ||||
|         this._workSpinner.actor.opacity = 0; | ||||
|  | ||||
|         this.allowCancel = false; | ||||
|         this.buttonLayout.visible = true; | ||||
|         this.addButton({ label: _("Cancel"), | ||||
| @@ -100,11 +104,12 @@ const UnlockDialog = new Lang.Class({ | ||||
|                          y_fill: false, | ||||
|                          x_align: St.Align.START, | ||||
|                          y_align: St.Align.MIDDLE }); | ||||
|         this.placeSpinner({ expand: false, | ||||
|                             x_fill: false, | ||||
|                             y_fill: false, | ||||
|                             x_align: St.Align.END, | ||||
|                             y_align: St.Align.MIDDLE }); | ||||
|         this.buttonLayout.add(this._workSpinner.actor, | ||||
|                               { expand: false, | ||||
|                                 x_fill: false, | ||||
|                                 y_fill: false, | ||||
|                                 x_align: St.Align.END, | ||||
|                                 y_align: St.Align.MIDDLE }); | ||||
|         this._okButton = this.addButton({ label: _("Unlock"), | ||||
|                                           action: Lang.bind(this, this._doUnlock), | ||||
|                                           default: true }, | ||||
| @@ -158,6 +163,28 @@ const UnlockDialog = new Lang.Class({ | ||||
|         this._okButton.can_focus = sensitive; | ||||
|     }, | ||||
|  | ||||
|     _setWorking: function(working) { | ||||
|         if (working) { | ||||
|             this._workSpinner.play(); | ||||
|             Tweener.addTween(this._workSpinner.actor, | ||||
|                              { opacity: 255, | ||||
|                                delay: LoginDialog.WORK_SPINNER_ANIMATION_DELAY, | ||||
|                                time: LoginDialog.WORK_SPINNER_ANIMATION_TIME, | ||||
|                                transition: 'linear' | ||||
|                              }); | ||||
|         } else { | ||||
|             Tweener.addTween(this._workSpinner.actor, | ||||
|                              { opacity: 0, | ||||
|                                time: LoginDialog.WORK_SPINNER_ANIMATION_TIME, | ||||
|                                transition: 'linear', | ||||
|                                onCompleteScope: this, | ||||
|                                onComplete: function() { | ||||
|                                    this._workSpinner.stop(); | ||||
|                                } | ||||
|                              }); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _showMessage: function(userVerifier, message, styleClass) { | ||||
|         if (message) { | ||||
|             this._promptMessage.text = message; | ||||
| @@ -188,7 +215,7 @@ const UnlockDialog = new Lang.Class({ | ||||
|  | ||||
|         this._currentQuery = serviceName; | ||||
|         this._updateSensitivity(true); | ||||
|         this.setWorking(false); | ||||
|         this._setWorking(false); | ||||
|     }, | ||||
|  | ||||
|     _showLoginHint: function(verifier, message) { | ||||
| @@ -207,7 +234,7 @@ const UnlockDialog = new Lang.Class({ | ||||
|             // the actual reply to GDM will be sent as soon as asked | ||||
|             this._firstQuestionAnswer = this._promptEntry.text; | ||||
|             this._updateSensitivity(false); | ||||
|             this.setWorking(true); | ||||
|             this._setWorking(true); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| @@ -218,7 +245,7 @@ const UnlockDialog = new Lang.Class({ | ||||
|         this._currentQuery = null; | ||||
|  | ||||
|         this._updateSensitivity(false); | ||||
|         this.setWorking(true); | ||||
|         this._setWorking(true); | ||||
|  | ||||
|         this._userVerifier.answerQuery(query, this._promptEntry.text); | ||||
|     }, | ||||
| @@ -258,7 +285,7 @@ const UnlockDialog = new Lang.Class({ | ||||
|         this._promptEntry.menu.isPassword = true; | ||||
|  | ||||
|         this._updateSensitivity(false); | ||||
|         this.setWorking(false); | ||||
|         this._setWorking(false); | ||||
|     }, | ||||
|  | ||||
|     _escape: function() { | ||||
|   | ||||
| @@ -20,8 +20,8 @@ const Main = imports.ui.main; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
| const Params = imports.misc.params; | ||||
| const Util = imports.misc.util; | ||||
| const UserWidget = imports.ui.userWidget; | ||||
|  | ||||
| const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown'; | ||||
| const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver'; | ||||
| @@ -32,6 +32,8 @@ const DISABLE_LOG_OUT_KEY = 'disable-log-out'; | ||||
| 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 DIALOG_ICON_SIZE = 64; | ||||
|  | ||||
| const MAX_USERS_IN_SESSION_DIALOG = 5; | ||||
|  | ||||
| const IMStatus = { | ||||
| @@ -55,6 +57,48 @@ const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session | ||||
|  | ||||
| const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface); | ||||
|  | ||||
| // Adapted from gdm/gui/user-switch-applet/applet.c | ||||
| // | ||||
| // Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>. | ||||
| // Copyright (C) 2008,2009 Red Hat, Inc. | ||||
|  | ||||
| const UserAvatarWidget = new Lang.Class({ | ||||
|     Name: 'UserAvatarWidget', | ||||
|  | ||||
|     _init: function(user, params) { | ||||
|         this._user = user; | ||||
|         params = Params.parse(params, { reactive: false, | ||||
|                                         iconSize: DIALOG_ICON_SIZE, | ||||
|                                         styleClass: 'status-chooser-user-icon' }); | ||||
|         this._iconSize = params.iconSize; | ||||
|  | ||||
|         this.actor = new St.Bin({ style_class: params.styleClass, | ||||
|                                   track_hover: params.reactive, | ||||
|                                   reactive: params.reactive }); | ||||
|     }, | ||||
|  | ||||
|     setSensitive: function(sensitive) { | ||||
|         this.actor.can_focus = sensitive; | ||||
|         this.actor.reactive = sensitive; | ||||
|     }, | ||||
|  | ||||
|     update: function() { | ||||
|         let iconFile = this._user.get_icon_file(); | ||||
|         if (iconFile && !GLib.file_test(iconFile, GLib.FileTest.EXISTS)) | ||||
|             iconFile = null; | ||||
|  | ||||
|         if (iconFile) { | ||||
|             let file = Gio.File.new_for_path(iconFile); | ||||
|             this.actor.child = null; | ||||
|             this.actor.style = 'background-image: url("%s");'.format(iconFile); | ||||
|         } else { | ||||
|             this.actor.style = null; | ||||
|             this.actor.child = new St.Icon({ icon_name: 'avatar-default-symbolic', | ||||
|                                              icon_size: this._iconSize }); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const IMStatusItem = new Lang.Class({ | ||||
|     Name: 'IMStatusItem', | ||||
|     Extends: PopupMenu.PopupBaseMenuItem, | ||||
| @@ -126,7 +170,7 @@ const IMStatusChooserItem = new Lang.Class({ | ||||
|         this._userManager = AccountsService.UserManager.get_default(); | ||||
|         this._user = this._userManager.get_user(GLib.get_user_name()); | ||||
|  | ||||
|         this._avatar = new UserWidget.Avatar(this._user, { reactive: true }); | ||||
|         this._avatar = new UserAvatarWidget(this._user, { reactive: true }); | ||||
|         this._iconBin = new St.Button({ child: this._avatar.actor }); | ||||
|         this.addActor(this._iconBin); | ||||
|  | ||||
| @@ -566,6 +610,7 @@ const UserMenuButton = new Lang.Class({ | ||||
|  | ||||
|         let allowSettings = Main.sessionMode.allowSettings; | ||||
|         this._statusChooser.setSensitive(allowSettings); | ||||
|         this._systemSettings.visible = allowSettings; | ||||
|  | ||||
|         this.setSensitive(!Main.sessionMode.isLocked); | ||||
|         this._updatePresenceIcon(); | ||||
| @@ -741,7 +786,10 @@ const UserMenuButton = new Lang.Class({ | ||||
|         item = new PopupMenu.PopupSeparatorMenuItem(); | ||||
|         this.menu.addMenuItem(item); | ||||
|  | ||||
|         this.menu.addSettingsAction(_("Settings"), 'gnome-control-center.desktop'); | ||||
|         item = new PopupMenu.PopupMenuItem(_("Settings")); | ||||
|         item.connect('activate', Lang.bind(this, this._onPreferencesActivate)); | ||||
|         this.menu.addMenuItem(item); | ||||
|         this._systemSettings = item; | ||||
|  | ||||
|         item = new PopupMenu.PopupSeparatorMenuItem(); | ||||
|         this.menu.addMenuItem(item); | ||||
| @@ -802,6 +850,12 @@ const UserMenuButton = new Lang.Class({ | ||||
|         app.activate(); | ||||
|     }, | ||||
|  | ||||
|     _onPreferencesActivate: function() { | ||||
|         Main.overview.hide(); | ||||
|         let app = Shell.AppSystem.get_default().lookup_app('gnome-control-center.desktop'); | ||||
|         app.activate(); | ||||
|     }, | ||||
|  | ||||
|     _onLockScreenActivate: function() { | ||||
|         this.menu.close(BoxPointer.PopupAnimation.NONE); | ||||
|         Main.overview.hide(); | ||||
| @@ -854,7 +908,7 @@ const UserMenuButton = new Lang.Class({ | ||||
|             let session = sessions[i]; | ||||
|             let userEntry = new St.BoxLayout({ style_class: 'login-dialog-user-list-item', | ||||
|                                                vertical: false }); | ||||
|             let avatar = new UserWidget.Avatar(session.user); | ||||
|             let avatar = new UserAvatarWidget(session.user); | ||||
|             avatar.update(); | ||||
|             userEntry.add(avatar.actor); | ||||
|  | ||||
|   | ||||
| @@ -3,56 +3,10 @@ | ||||
| // | ||||
| // A widget showing the user avatar and name | ||||
| const AccountsService = imports.gi.AccountsService; | ||||
| const GLib = imports.gi.GLib; | ||||
| const Gio = imports.gi.Gio; | ||||
| const Lang = imports.lang; | ||||
| const St = imports.gi.St; | ||||
|  | ||||
| const Params = imports.misc.params; | ||||
|  | ||||
| const AVATAR_ICON_SIZE = 64; | ||||
|  | ||||
| // Adapted from gdm/gui/user-switch-applet/applet.c | ||||
| // | ||||
| // Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>. | ||||
| // Copyright (C) 2008,2009 Red Hat, Inc. | ||||
|  | ||||
| const Avatar = new Lang.Class({ | ||||
|     Name: 'Avatar', | ||||
|  | ||||
|     _init: function(user, params) { | ||||
|         this._user = user; | ||||
|         params = Params.parse(params, { reactive: false, | ||||
|                                         iconSize: AVATAR_ICON_SIZE, | ||||
|                                         styleClass: 'status-chooser-user-icon' }); | ||||
|         this._iconSize = params.iconSize; | ||||
|  | ||||
|         this.actor = new St.Bin({ style_class: params.styleClass, | ||||
|                                   track_hover: params.reactive, | ||||
|                                   reactive: params.reactive }); | ||||
|     }, | ||||
|  | ||||
|     setSensitive: function(sensitive) { | ||||
|         this.actor.can_focus = sensitive; | ||||
|         this.actor.reactive = sensitive; | ||||
|     }, | ||||
|  | ||||
|     update: function() { | ||||
|         let iconFile = this._user.get_icon_file(); | ||||
|         if (iconFile && !GLib.file_test(iconFile, GLib.FileTest.EXISTS)) | ||||
|             iconFile = null; | ||||
|  | ||||
|         if (iconFile) { | ||||
|             let file = Gio.File.new_for_path(iconFile); | ||||
|             this.actor.child = null; | ||||
|             this.actor.style = 'background-image: url("%s");'.format(iconFile); | ||||
|         } else { | ||||
|             this.actor.style = null; | ||||
|             this.actor.child = new St.Icon({ icon_name: 'avatar-default-symbolic', | ||||
|                                              icon_size: this._iconSize }); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
| const UserMenu = imports.ui.userMenu; | ||||
|  | ||||
| const UserWidget = new Lang.Class({ | ||||
|     Name: 'UserWidget', | ||||
| @@ -62,9 +16,8 @@ const UserWidget = new Lang.Class({ | ||||
|  | ||||
|         this.actor = new St.BoxLayout({ style_class: 'user-widget', | ||||
|                                         vertical: false }); | ||||
|         this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); | ||||
|  | ||||
|         this._avatar = new Avatar(user); | ||||
|         this._avatar = new UserMenu.UserAvatarWidget(user); | ||||
|         this.actor.add(this._avatar.actor, | ||||
|                        { x_fill: true, y_fill: true }); | ||||
|  | ||||
| @@ -83,7 +36,7 @@ const UserWidget = new Lang.Class({ | ||||
|             this._updateUser(); | ||||
|     }, | ||||
|  | ||||
|     _onDestroy: function() { | ||||
|     destroy: function() { | ||||
|         if (this._userLoadedId != 0) { | ||||
|             this._user.disconnect(this._userLoadedId); | ||||
|             this._userLoadedId = 0; | ||||
| @@ -93,6 +46,8 @@ const UserWidget = new Lang.Class({ | ||||
|             this._user.disconnect(this._userChangedId); | ||||
|             this._userChangedId = 0; | ||||
|         } | ||||
|  | ||||
|         this.actor.destroy(); | ||||
|     }, | ||||
|  | ||||
|     _updateUser: function() { | ||||
|   | ||||
| @@ -150,14 +150,6 @@ const ViewSelector = new Lang.Class({ | ||||
|                               Shell.KeyBindingMode.NORMAL | | ||||
|                               Shell.KeyBindingMode.OVERVIEW, | ||||
|                               Lang.bind(this, this._toggleAppsPage)); | ||||
|  | ||||
|         Main.wm.addKeybinding('toggle-overview', | ||||
|                               new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                               Meta.KeyBindingFlags.NONE, | ||||
|                               Shell.KeyBindingMode.NORMAL | | ||||
|                               Shell.KeyBindingMode.OVERVIEW, | ||||
|                               Lang.bind(Main.overview, Main.overview.toggle)); | ||||
|  | ||||
|     }, | ||||
|  | ||||
|     _toggleAppsPage: function() { | ||||
| @@ -186,10 +178,6 @@ const ViewSelector = new Lang.Class({ | ||||
|             Main.overview.fadeInDesktop(); | ||||
|     }, | ||||
|  | ||||
|     setWorkspacesFullGeometry: function(geom) { | ||||
|         this._workspacesDisplay.setWorkspacesFullGeometry(geom); | ||||
|     }, | ||||
|  | ||||
|     hide: function() { | ||||
|         this._workspacesDisplay.hide(); | ||||
|     }, | ||||
| @@ -508,12 +496,12 @@ const ViewSelector = new Lang.Class({ | ||||
|             return; | ||||
|  | ||||
|         this._searchSystem.registerProvider(provider); | ||||
|         this._searchResults.createProviderDisplay(provider); | ||||
|         this._searchResults.createProviderMeta(provider); | ||||
|     }, | ||||
|  | ||||
|     removeSearchProvider: function(provider) { | ||||
|         this._searchSystem.unregisterProvider(provider); | ||||
|         this._searchResults.destroyProviderDisplay(provider); | ||||
|         this._searchResults.destroyProviderMeta(provider); | ||||
|     }, | ||||
|  | ||||
|     getActivePage: function() { | ||||
|   | ||||
| @@ -134,9 +134,9 @@ const WandaSearchProvider = new Lang.Class({ | ||||
|  | ||||
|     getInitialResultSet: function(terms) { | ||||
|         if (terms.join(' ') == MAGIC_FISH_KEY) { | ||||
|             this.searchSystem.setResults(this, [ FISH_NAME ]); | ||||
|             this.searchSystem.pushResults(this, [ FISH_NAME ]); | ||||
|         } else { | ||||
|             this.searchSystem.setResults(this, []); | ||||
|             this.searchSystem.pushResults(this, []); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|   | ||||
| @@ -4,7 +4,6 @@ const Clutter = imports.gi.Clutter; | ||||
| const GLib = imports.gi.GLib; | ||||
| const Gio = imports.gi.Gio; | ||||
| const Lang = imports.lang; | ||||
| const Mainloop = imports.mainloop; | ||||
| const Meta = imports.gi.Meta; | ||||
| const St = imports.gi.St; | ||||
| const Shell = imports.gi.Shell; | ||||
| @@ -67,209 +66,6 @@ function getWindowDimmer(actor) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * When the last window closed on a workspace is a dialog or splash | ||||
|  * screen, we assume that it might be an initial window shown before | ||||
|  * the main window of an application, and give the app a grace period | ||||
|  * where it can map another window before we remove the workspace. | ||||
|  */ | ||||
| const LAST_WINDOW_GRACE_TIME = 1000; | ||||
|  | ||||
| const WorkspaceTracker = new Lang.Class({ | ||||
|     Name: 'WorkspaceTracker', | ||||
|  | ||||
|     _init: function(wm) { | ||||
|         this._wm = wm; | ||||
|  | ||||
|         this._workspaces = []; | ||||
|         this._checkWorkspacesId = 0; | ||||
|  | ||||
|         let tracker = Shell.WindowTracker.get_default(); | ||||
|         tracker.connect('startup-sequence-changed', Lang.bind(this, this._queueCheckWorkspaces)); | ||||
|  | ||||
|         global.screen.connect('notify::n-workspaces', Lang.bind(this, this._nWorkspacesChanged)); | ||||
|  | ||||
|         global.screen.connect('window-entered-monitor', Lang.bind(this, this._windowEnteredMonitor)); | ||||
|         global.screen.connect('window-left-monitor', Lang.bind(this, this._windowLeftMonitor)); | ||||
|         global.screen.connect('restacked', Lang.bind(this, this._windowsRestacked)); | ||||
|  | ||||
|         this._workspaceSettings = new Gio.Settings({ schema: Main.dynamicWorkspacesSchema }); | ||||
|         this._workspaceSettings.connect('changed::dynamic-workspaces', Lang.bind(this, this._queueCheckWorkspaces)); | ||||
|  | ||||
|         this._nWorkspacesChanged(); | ||||
|     }, | ||||
|  | ||||
|     _checkWorkspaces: function() { | ||||
|         let i; | ||||
|         let emptyWorkspaces = []; | ||||
|  | ||||
|         if (!Meta.prefs_get_dynamic_workspaces()) { | ||||
|             this._checkWorkspacesId = 0; | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         for (i = 0; i < this._workspaces.length; i++) { | ||||
|             let lastRemoved = this._workspaces[i]._lastRemovedWindow; | ||||
|             if ((lastRemoved && | ||||
|                  (lastRemoved.get_window_type() == Meta.WindowType.SPLASHSCREEN || | ||||
|                   lastRemoved.get_window_type() == Meta.WindowType.DIALOG || | ||||
|                   lastRemoved.get_window_type() == Meta.WindowType.MODAL_DIALOG)) || | ||||
|                 this._workspaces[i]._keepAliveId) | ||||
|                 emptyWorkspaces[i] = false; | ||||
|             else | ||||
|                 emptyWorkspaces[i] = true; | ||||
|         } | ||||
|  | ||||
|         let sequences = Shell.WindowTracker.get_default().get_startup_sequences(); | ||||
|         for (i = 0; i < sequences.length; i++) { | ||||
|             let index = sequences[i].get_workspace(); | ||||
|             if (index >= 0 && index <= global.screen.n_workspaces) | ||||
|                 emptyWorkspaces[index] = false; | ||||
|         } | ||||
|  | ||||
|         let windows = global.get_window_actors(); | ||||
|         for (i = 0; i < windows.length; i++) { | ||||
|             let win = windows[i]; | ||||
|  | ||||
|             if (win.get_meta_window().is_on_all_workspaces()) | ||||
|                 continue; | ||||
|  | ||||
|             let workspaceIndex = win.get_workspace(); | ||||
|             emptyWorkspaces[workspaceIndex] = false; | ||||
|         } | ||||
|  | ||||
|         // If we don't have an empty workspace at the end, add one | ||||
|         if (!emptyWorkspaces[emptyWorkspaces.length -1]) { | ||||
|             global.screen.append_new_workspace(false, global.get_current_time()); | ||||
|             emptyWorkspaces.push(false); | ||||
|         } | ||||
|  | ||||
|         let activeWorkspaceIndex = global.screen.get_active_workspace_index(); | ||||
|         let removingCurrentWorkspace = (emptyWorkspaces[activeWorkspaceIndex] && | ||||
|                                         activeWorkspaceIndex < emptyWorkspaces.length - 1); | ||||
|         // Don't enter the overview when removing multiple empty workspaces at startup | ||||
|         let showOverview  = (removingCurrentWorkspace && | ||||
|                              !emptyWorkspaces.every(function(x) { return x; })); | ||||
|  | ||||
|         if (removingCurrentWorkspace) { | ||||
|             // "Merge" the empty workspace we are removing with the one at the end | ||||
|             this._wm.blockAnimations(); | ||||
|         } | ||||
|  | ||||
|         // Delete other empty workspaces; do it from the end to avoid index changes | ||||
|         for (i = emptyWorkspaces.length - 2; i >= 0; i--) { | ||||
|             if (emptyWorkspaces[i]) | ||||
|                 global.screen.remove_workspace(this._workspaces[i], global.get_current_time()); | ||||
|         } | ||||
|  | ||||
|         if (removingCurrentWorkspace) { | ||||
|             global.screen.get_workspace_by_index(global.screen.n_workspaces - 1).activate(global.get_current_time()); | ||||
|             this._wm.unblockAnimations(); | ||||
|  | ||||
|             if (!Main.overview.visible && showOverview) | ||||
|                 Main.overview.show(); | ||||
|         } | ||||
|  | ||||
|         this._checkWorkspacesId = 0; | ||||
|         return false; | ||||
|     }, | ||||
|  | ||||
|     keepWorkspaceAlive: function(workspace, duration) { | ||||
|         if (workspace._keepAliveId) | ||||
|             Mainloop.source_remove(workspace._keepAliveId); | ||||
|  | ||||
|         workspace._keepAliveId = Mainloop.timeout_add(duration, Lang.bind(this, function() { | ||||
|             workspace._keepAliveId = 0; | ||||
|             this._queueCheckWorkspaces(); | ||||
|             return false; | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     _windowRemoved: function(workspace, window) { | ||||
|         workspace._lastRemovedWindow = window; | ||||
|         this._queueCheckWorkspaces(); | ||||
|         Mainloop.timeout_add(LAST_WINDOW_GRACE_TIME, Lang.bind(this, function() { | ||||
|             if (workspace._lastRemovedWindow == window) { | ||||
|                 workspace._lastRemovedWindow = null; | ||||
|                 this._queueCheckWorkspaces(); | ||||
|             } | ||||
|             return false; | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     _windowLeftMonitor: function(metaScreen, monitorIndex, metaWin) { | ||||
|         // If the window left the primary monitor, that | ||||
|         // might make that workspace empty | ||||
|         if (monitorIndex == Main.layoutManager.primaryIndex) | ||||
|             this._queueCheckWorkspaces(); | ||||
|     }, | ||||
|  | ||||
|     _windowEnteredMonitor: function(metaScreen, monitorIndex, metaWin) { | ||||
|         // If the window entered the primary monitor, that | ||||
|         // might make that workspace non-empty | ||||
|         if (monitorIndex == Main.layoutManager.primaryIndex) | ||||
|             this._queueCheckWorkspaces(); | ||||
|     }, | ||||
|  | ||||
|     _windowsRestacked: function() { | ||||
|         // Figure out where the pointer is in case we lost track of | ||||
|         // it during a grab. (In particular, if a trayicon popup menu | ||||
|         // is dismissed, see if we need to close the message tray.) | ||||
|         global.sync_pointer(); | ||||
|     }, | ||||
|  | ||||
|     _queueCheckWorkspaces: function() { | ||||
|         if (this._checkWorkspacesId == 0) | ||||
|             this._checkWorkspacesId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, this._checkWorkspaces)); | ||||
|     }, | ||||
|  | ||||
|     _nWorkspacesChanged: function() { | ||||
|         let oldNumWorkspaces = this._workspaces.length; | ||||
|         let newNumWorkspaces = global.screen.n_workspaces; | ||||
|  | ||||
|         if (oldNumWorkspaces == newNumWorkspaces) | ||||
|             return false; | ||||
|  | ||||
|         let lostWorkspaces = []; | ||||
|         if (newNumWorkspaces > oldNumWorkspaces) { | ||||
|             let w; | ||||
|  | ||||
|             // Assume workspaces are only added at the end | ||||
|             for (w = oldNumWorkspaces; w < newNumWorkspaces; w++) | ||||
|                 this._workspaces[w] = global.screen.get_workspace_by_index(w); | ||||
|  | ||||
|             for (w = oldNumWorkspaces; w < newNumWorkspaces; w++) { | ||||
|                 let workspace = this._workspaces[w]; | ||||
|                 workspace._windowAddedId = workspace.connect('window-added', Lang.bind(this, this._queueCheckWorkspaces)); | ||||
|                 workspace._windowRemovedId = workspace.connect('window-removed', Lang.bind(this, this._windowRemoved)); | ||||
|             } | ||||
|  | ||||
|         } else { | ||||
|             // Assume workspaces are only removed sequentially | ||||
|             // (e.g. 2,3,4 - not 2,4,7) | ||||
|             let removedIndex; | ||||
|             let removedNum = oldNumWorkspaces - newNumWorkspaces; | ||||
|             for (let w = 0; w < oldNumWorkspaces; w++) { | ||||
|                 let workspace = global.screen.get_workspace_by_index(w); | ||||
|                 if (this._workspaces[w] != workspace) { | ||||
|                     removedIndex = w; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             let lostWorkspaces = this._workspaces.splice(removedIndex, removedNum); | ||||
|             lostWorkspaces.forEach(function(workspace) { | ||||
|                 workspace.disconnect(workspace._windowAddedId); | ||||
|                 workspace.disconnect(workspace._windowRemovedId); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         this._queueCheckWorkspaces(); | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| const WindowManager = new Lang.Class({ | ||||
|     Name: 'WindowManager', | ||||
|  | ||||
| @@ -340,90 +136,6 @@ const WindowManager = new Lang.Class({ | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-to-workspace-1', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-to-workspace-2', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-to-workspace-3', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-to-workspace-4', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-to-workspace-5', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-to-workspace-6', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-to-workspace-7', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-to-workspace-8', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-to-workspace-9', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-to-workspace-10', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-to-workspace-11', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-to-workspace-12', | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-1', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-2', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-3', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-4', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-5', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-6', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-7', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-8', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-9', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-10', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-11', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('move-to-workspace-12', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.setCustomKeybindingHandler('switch-applications', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._startAppSwitcher)); | ||||
| @@ -460,9 +172,8 @@ const WindowManager = new Lang.Class({ | ||||
|         this.addKeybinding('open-application-menu', | ||||
|                            new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                            Meta.KeyBindingFlags.NONE, | ||||
|                            Shell.KeyBindingMode.NORMAL | | ||||
|                            Shell.KeyBindingMode.TOPBAR_POPUP, | ||||
|                            Lang.bind(this, this._toggleAppMenu)); | ||||
|                            Shell.KeyBindingMode.NORMAL, | ||||
|                            Lang.bind(this, this._openAppMenu)); | ||||
|  | ||||
|         Main.overview.connect('showing', Lang.bind(this, function() { | ||||
|             for (let i = 0; i < this._dimmedWindows.length; i++) | ||||
| @@ -472,15 +183,6 @@ const WindowManager = new Lang.Class({ | ||||
|             for (let i = 0; i < this._dimmedWindows.length; i++) | ||||
|                 this._dimWindow(this._dimmedWindows[i]); | ||||
|         })); | ||||
|  | ||||
|         this._workspaceTracker = new WorkspaceTracker(this); | ||||
|  | ||||
|         global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, | ||||
|                                                 false, -1, 1); | ||||
|     }, | ||||
|  | ||||
|     keepWorkspaceAlive: function(workspace, duration) { | ||||
|         this._workspaceTracker.keepWorkspaceAlive(workspace, duration); | ||||
|     }, | ||||
|  | ||||
|     setCustomKeybindingHandler: function(name, modes, handler) { | ||||
| @@ -977,39 +679,27 @@ const WindowManager = new Lang.Class({ | ||||
|         Main.ctrlAltTabManager.popup(backwards, binding.get_name(), binding.get_mask()); | ||||
|     }, | ||||
|  | ||||
|     _toggleAppMenu : function(display, screen, window, event, binding) { | ||||
|         Main.panel.toggleAppMenu(); | ||||
|     _openAppMenu : function(display, screen, window, event, binding) { | ||||
|         Main.panel.openAppMenu(); | ||||
|     }, | ||||
|  | ||||
|     _showWorkspaceSwitcher : function(display, screen, window, binding) { | ||||
|         if (screen.n_workspaces == 1) | ||||
|             return; | ||||
|  | ||||
|         let [action,,,target] = binding.get_name().split('-'); | ||||
|         let [action,,,direction] = binding.get_name().split('-'); | ||||
|         let direction = Meta.MotionDirection[direction.toUpperCase()]; | ||||
|         let newWs; | ||||
|         let direction; | ||||
|  | ||||
|         if (isNaN(target)) { | ||||
|             direction = Meta.MotionDirection[target.toUpperCase()]; | ||||
|             newWs = screen.get_active_workspace().get_neighbor(direction); | ||||
|         } else if (target > 0) { | ||||
|             target--; | ||||
|             newWs = screen.get_workspace_by_index(target); | ||||
|  | ||||
|             if (screen.get_active_workspace().index() > target) | ||||
|                 direction = Meta.MotionDirection.UP; | ||||
|             else | ||||
|                 direction = Meta.MotionDirection.DOWN; | ||||
|         } | ||||
|  | ||||
|         if (direction != Meta.MotionDirection.UP && | ||||
|             direction != Meta.MotionDirection.DOWN) | ||||
|             return; | ||||
|  | ||||
|         if (action == 'switch') | ||||
|             this.actionMoveWorkspace(newWs); | ||||
|             newWs = this.actionMoveWorkspace(direction); | ||||
|         else | ||||
|             this.actionMoveWindow(window, newWs); | ||||
|             newWs = this.actionMoveWindow(window, direction); | ||||
|  | ||||
|         if (!Main.overview.visible) { | ||||
|             if (this._workspaceSwitcherPopup == null) { | ||||
| @@ -1022,27 +712,31 @@ const WindowManager = new Lang.Class({ | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     actionMoveWorkspace: function(workspace) { | ||||
|     actionMoveWorkspace: function(direction) { | ||||
|         let activeWorkspace = global.screen.get_active_workspace(); | ||||
|         let toActivate = activeWorkspace.get_neighbor(direction); | ||||
|  | ||||
|         if (activeWorkspace != workspace) | ||||
|             workspace.activate(global.get_current_time()); | ||||
|         if (activeWorkspace != toActivate) | ||||
|             toActivate.activate(global.get_current_time()); | ||||
|  | ||||
|         return toActivate; | ||||
|     }, | ||||
|  | ||||
|     actionMoveWindow: function(window, workspace) { | ||||
|     actionMoveWindow: function(window, direction) { | ||||
|         let activeWorkspace = global.screen.get_active_workspace(); | ||||
|         let toActivate = activeWorkspace.get_neighbor(direction); | ||||
|  | ||||
|         if (activeWorkspace != workspace) { | ||||
|         if (activeWorkspace != toActivate) { | ||||
|             // This won't have any effect for "always sticky" windows | ||||
|             // (like desktop windows or docks) | ||||
|  | ||||
|             this._movingWindow = window; | ||||
|             window.change_workspace(workspace); | ||||
|             window.change_workspace(toActivate); | ||||
|  | ||||
|             global.display.clear_mouse_mode(); | ||||
|             workspace.activate_with_focus (window, global.get_current_time()); | ||||
|             toActivate.activate_with_focus (window, global.get_current_time()); | ||||
|         } | ||||
|  | ||||
|         return toActivate; | ||||
|     }, | ||||
| }); | ||||
|   | ||||
| @@ -127,7 +127,7 @@ const WindowClone = new Lang.Class({ | ||||
|         if (this._stackAbove == null) | ||||
|             return null; | ||||
|  | ||||
|         if (this.inDrag) { | ||||
|         if (this.inDrag || this._zooming) { | ||||
|             if (this._stackAbove._delegate) | ||||
|                 return this._stackAbove._delegate.getActualStackAbove(); | ||||
|             else | ||||
| @@ -453,10 +453,6 @@ const WindowOverlay = new Lang.Class({ | ||||
|         metaWindow.delete(global.get_current_time()); | ||||
|     }, | ||||
|  | ||||
|     _windowCanClose: function() { | ||||
|         return this._windowClone.metaWindow.can_close(); | ||||
|     }, | ||||
|  | ||||
|     _onWindowAdded: function(workspace, win) { | ||||
|         let metaWindow = this._windowClone.metaWindow; | ||||
|  | ||||
| @@ -492,14 +488,12 @@ const WindowOverlay = new Lang.Class({ | ||||
|     _animateVisible: function() { | ||||
|         this._parentActor.raise_top(); | ||||
|  | ||||
|         if (this._windowCanClose()) { | ||||
|             this.closeButton.show(); | ||||
|             this.closeButton.opacity = 0; | ||||
|             Tweener.addTween(this.closeButton, | ||||
|                              { opacity: 255, | ||||
|                                time: CLOSE_BUTTON_FADE_TIME, | ||||
|                                transition: 'easeOutQuad' }); | ||||
|         } | ||||
|         this.closeButton.show(); | ||||
|         this.closeButton.opacity = 0; | ||||
|         Tweener.addTween(this.closeButton, | ||||
|                          { opacity: 255, | ||||
|                            time: CLOSE_BUTTON_FADE_TIME, | ||||
|                            transition: 'easeOutQuad' }); | ||||
|  | ||||
|         this.border.show(); | ||||
|         this.border.opacity = 0; | ||||
| @@ -759,6 +753,13 @@ const LayoutStrategy = new Lang.Class({ | ||||
|         layout.space = space; | ||||
|     }, | ||||
|  | ||||
|     _getDistance: function (row, actor) { | ||||
|         let dist_x = actor.x - row.x; | ||||
|         let dist_y = actor.y - row.y; | ||||
|  | ||||
|         return Math.sqrt(Math.pow(dist_x, 2) + Math.pow(dist_y, 2)); | ||||
|     }, | ||||
|  | ||||
|     computeWindowSlots: function(layout, area) { | ||||
|         this._computeRowSizes(layout); | ||||
|  | ||||
| @@ -766,36 +767,28 @@ const LayoutStrategy = new Lang.Class({ | ||||
|  | ||||
|         let slots = []; | ||||
|  | ||||
|         // Do this in three parts. | ||||
|         let height = 0; | ||||
|         for (let i = 0; i < rows.length; i++) { | ||||
|             let row = rows[i]; | ||||
|             height += row.height + this._rowSpacing; | ||||
|         } | ||||
|  | ||||
|         height -= this._rowSpacing; | ||||
|  | ||||
|         let y = 0; | ||||
|  | ||||
|         for (let i = 0; i < rows.length; i++) { | ||||
|             let row = rows[i]; | ||||
|  | ||||
|             // If this window layout row doesn't fit in the actual | ||||
|             // geometry, then apply an additional scale to it. | ||||
|             row.additionalScale = Math.min(1, area.width / row.width, area.height / height); | ||||
|  | ||||
|             row.x = area.x + (Math.max(area.width - row.width, 0) / 2) * row.additionalScale; | ||||
|             row.y = area.y + (y + Math.max(area.height - height, 0) / 2) * row.additionalScale; | ||||
|             row.x = area.x + (area.width - row.width) / 2; | ||||
|             row.y = area.y + y; | ||||
|             y += row.height + this._rowSpacing; | ||||
|             row.windows.sort(Lang.bind(this, function(a, b) { | ||||
|                 return this._getDistance(row, a.realWindow) - this._getDistance(row, b.realWindow); | ||||
|             })); | ||||
|         } | ||||
|  | ||||
|         let height = y - this._rowSpacing; | ||||
|         let baseY = (area.height - height) / 2; | ||||
|  | ||||
|         for (let i = 0; i < rows.length; i++) { | ||||
|             let row = rows[i]; | ||||
|             row.y += baseY; | ||||
|             let x = row.x; | ||||
|             for (let j = 0; j < row.windows.length; j++) { | ||||
|                 let window = row.windows[j]; | ||||
|  | ||||
|                 let s = scale * this._computeWindowScale(window) * row.additionalScale; | ||||
|                 let s = scale * this._computeWindowScale(window); | ||||
|                 let cellWidth = window.actor.width * s; | ||||
|                 let cellHeight = window.actor.height * s; | ||||
|  | ||||
| @@ -839,13 +832,6 @@ const UnalignedLayoutStrategy = new Lang.Class({ | ||||
|         return false; | ||||
|     }, | ||||
|  | ||||
|     _sortRow: function(row) { | ||||
|         // Sort windows horizontally to minimize travel distance | ||||
|         row.windows.sort(function(a, b) { | ||||
|             return a.realWindow.x - b.realWindow.x; | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     computeLayout: function(windows, layout) { | ||||
|         let numRows = layout.numRows; | ||||
|  | ||||
| @@ -876,7 +862,6 @@ const UnalignedLayoutStrategy = new Lang.Class({ | ||||
|                     row.windows.push(window); | ||||
|                     row.fullWidth += width; | ||||
|                 } else { | ||||
|                     this._sortRow(row); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
| @@ -898,14 +883,6 @@ const UnalignedLayoutStrategy = new Lang.Class({ | ||||
|     } | ||||
| }); | ||||
|  | ||||
| function padArea(area, padding) { | ||||
|     return { | ||||
|         x: area.x + padding.left, | ||||
|         y: area.y + padding.top, | ||||
|         width: area.width - padding.left - padding.right, | ||||
|         height: area.height - padding.top - padding.bottom, | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @metaWorkspace: a #Meta.Workspace, or null | ||||
| @@ -917,19 +894,10 @@ const Workspace = new Lang.Class({ | ||||
|         // When dragging a window, we use this slot for reserve space. | ||||
|         this._reservedSlot = null; | ||||
|         this.metaWorkspace = metaWorkspace; | ||||
|  | ||||
|         // The full geometry is the geometry we should try and position | ||||
|         // windows for. The actual geometry we allocate may be less than | ||||
|         // this, like if the workspace switcher is slid out. | ||||
|         this._fullGeometry = null; | ||||
|  | ||||
|         // The actual geometry is the geometry we need to arrange windows | ||||
|         // in. If this is a smaller area than the full geometry, we'll | ||||
|         // do some simple aspect ratio like math to fit the layout calculated | ||||
|         // for the full geometry into this area. | ||||
|         this._actualGeometry = null; | ||||
|  | ||||
|         this._currentLayout = null; | ||||
|         this._x = 0; | ||||
|         this._y = 0; | ||||
|         this._width = 0; | ||||
|         this._height = 0; | ||||
|  | ||||
|         this.monitorIndex = monitorIndex; | ||||
|         this._monitor = Main.layoutManager.monitors[this.monitorIndex]; | ||||
| @@ -942,7 +910,7 @@ const Workspace = new Lang.Class({ | ||||
|             this.actor.add_style_class_name('external-monitor'); | ||||
|         this.actor.set_size(0, 0); | ||||
|  | ||||
|         this._dropRect = new Clutter.Actor({ opacity: 0 }); | ||||
|         this._dropRect = new Clutter.Rectangle({ opacity: 0 }); | ||||
|         this._dropRect._delegate = this; | ||||
|  | ||||
|         this.actor.add_actor(this._dropRect); | ||||
| @@ -979,29 +947,23 @@ const Workspace = new Lang.Class({ | ||||
|  | ||||
|         this._positionWindowsFlags = 0; | ||||
|         this._positionWindowsId = 0; | ||||
|  | ||||
|         this._currentLayout = null; | ||||
|     }, | ||||
|  | ||||
|     setFullGeometry: function(geom) { | ||||
|         this._fullGeometry = geom; | ||||
|         this._recalculateWindowPositions(WindowPositionFlags.NONE); | ||||
|     }, | ||||
|     setGeometry: function(x, y, width, height) { | ||||
|         this._x = x; | ||||
|         this._y = y; | ||||
|         this._width = width; | ||||
|         this._height = height; | ||||
|  | ||||
|     setActualGeometry: function(geom) { | ||||
|         this._actualGeometry = geom; | ||||
|  | ||||
|         if (this._actualGeometryLater) | ||||
|             return; | ||||
|  | ||||
|         this._actualGeometryLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { | ||||
|             let geom = this._actualGeometry; | ||||
|  | ||||
|             this._dropRect.set_position(geom.x, geom.y); | ||||
|             this._dropRect.set_size(geom.width, geom.height); | ||||
|             this._updateWindowPositions(Main.overview.animationInProgress ? WindowPositionFlags.ANIMATE : WindowPositionFlags.NONE); | ||||
|  | ||||
|             this._actualGeometryLater = 0; | ||||
|         Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { | ||||
|             this._dropRect.set_position(x, y); | ||||
|             this._dropRect.set_size(width, height); | ||||
|             return false; | ||||
|         })); | ||||
|  | ||||
|         this.positionWindows(WindowPositionFlags.NONE); | ||||
|     }, | ||||
|  | ||||
|     _lookupIndex: function (metaWindow) { | ||||
| @@ -1029,32 +991,37 @@ const Workspace = new Lang.Class({ | ||||
|             clone = null; | ||||
|  | ||||
|         this._reservedSlot = clone; | ||||
|         this._recalculateWindowPositions(WindowPositionFlags.ANIMATE); | ||||
|         this._currentLayout = null; | ||||
|         this.positionWindows(WindowPositionFlags.ANIMATE); | ||||
|     }, | ||||
|  | ||||
|     _recalculateWindowPositions: function(flags) { | ||||
|     /** | ||||
|      * positionWindows: | ||||
|      * @flags: | ||||
|      *  INITIAL - this is the initial positioning of the windows. | ||||
|      *  ANIMATE - Indicates that we need animate changing position. | ||||
|      */ | ||||
|     positionWindows: function(flags) { | ||||
|         this._positionWindowsFlags |= flags; | ||||
|  | ||||
|         if (this._positionWindowsId > 0) | ||||
|             return; | ||||
|  | ||||
|         this._positionWindowsId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { | ||||
|             this._realRecalculateWindowPositions(this._positionWindowsFlags); | ||||
|             this._realPositionWindows(this._positionWindowsFlags); | ||||
|             this._positionWindowsFlags = 0; | ||||
|             this._positionWindowsId = 0; | ||||
|             return false; | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     _realRecalculateWindowPositions: function(flags) { | ||||
|     _realPositionWindows : function(flags) { | ||||
|         if (this._repositionWindowsId > 0) { | ||||
|             Mainloop.source_remove(this._repositionWindowsId); | ||||
|             this._repositionWindowsId = 0; | ||||
|         } | ||||
|  | ||||
|         let clones = this._windows.slice(); | ||||
|         if (clones.length == 0) | ||||
|             return; | ||||
|  | ||||
|         clones.sort(function(a, b) { | ||||
|             return a.metaWindow.get_stable_sequence() - b.metaWindow.get_stable_sequence(); | ||||
| @@ -1063,25 +1030,11 @@ const Workspace = new Lang.Class({ | ||||
|         if (this._reservedSlot) | ||||
|             clones.push(this._reservedSlot); | ||||
|  | ||||
|         this._currentLayout = this._computeLayout(clones); | ||||
|         this._updateWindowPositions(flags); | ||||
|     }, | ||||
|  | ||||
|     _updateWindowPositions: function(flags) { | ||||
|         if (this._currentLayout == null) { | ||||
|             this._recalculateWindowPositions(flags); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         let initialPositioning = flags & WindowPositionFlags.INITIAL; | ||||
|         let animate = flags & WindowPositionFlags.ANIMATE; | ||||
|  | ||||
|         let layout = this._currentLayout; | ||||
|         let strategy = layout.strategy; | ||||
|  | ||||
|         let [, , padding] = this._getSpacingAndPadding(); | ||||
|         let area = padArea(this._actualGeometry, padding); | ||||
|         let slots = strategy.computeWindowSlots(layout, area); | ||||
|         // Start the animations | ||||
|         let slots = this._computeAllWindowSlots(clones); | ||||
|  | ||||
|         let currentWorkspace = global.screen.get_active_workspace(); | ||||
|         let isOnCurrentWorkspace = this.metaWorkspace == null || this.metaWorkspace == currentWorkspace; | ||||
| @@ -1195,8 +1148,8 @@ const Workspace = new Lang.Class({ | ||||
|         let [x, y, mask] = global.get_pointer(); | ||||
|  | ||||
|         let pointerHasMoved = (this._cursorX != x && this._cursorY != y); | ||||
|         let inWorkspace = (this._fullGeometry.x < x && x < this._fullGeometry.x + this._fullGeometry.width && | ||||
|                            this._fullGeometry.y < y && y < this._fullGeometry.y + this._fullGeometry.height); | ||||
|         let inWorkspace = (this._x < x && x < this._x + this._width && | ||||
|                            this._y < y && y < this._y + this._height); | ||||
|  | ||||
|         if (pointerHasMoved && inWorkspace) { | ||||
|             // store current cursor position | ||||
| @@ -1211,7 +1164,7 @@ const Workspace = new Lang.Class({ | ||||
|                 return true; | ||||
|         } | ||||
|  | ||||
|         this._recalculateWindowPositions(WindowPositionFlags.ANIMATE); | ||||
|         this.positionWindows(WindowPositionFlags.ANIMATE); | ||||
|         return false; | ||||
|     }, | ||||
|  | ||||
| @@ -1316,7 +1269,7 @@ const Workspace = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         this._currentLayout = null; | ||||
|         this._recalculateWindowPositions(WindowPositionFlags.ANIMATE); | ||||
|         this.positionWindows(WindowPositionFlags.ANIMATE); | ||||
|     }, | ||||
|  | ||||
|     _windowAdded : function(metaWorkspace, metaWin) { | ||||
| @@ -1353,8 +1306,13 @@ const Workspace = new Lang.Class({ | ||||
|  | ||||
|     // Animate the full-screen to Overview transition. | ||||
|     zoomToOverview : function() { | ||||
|         this._currentLayout = null; | ||||
|  | ||||
|         // Position and scale the windows. | ||||
|         this._recalculateWindowPositions(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL); | ||||
|         if (Main.overview.animationInProgress) | ||||
|             this.positionWindows(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL); | ||||
|         else | ||||
|             this.positionWindows(WindowPositionFlags.INITIAL); | ||||
|     }, | ||||
|  | ||||
|     // Animates the return from Overview mode | ||||
| @@ -1478,7 +1436,7 @@ const Workspace = new Lang.Class({ | ||||
|                       })); | ||||
|         clone.connect('size-changed', | ||||
|                       Lang.bind(this, function() { | ||||
|                           this._recalculateWindowPositions(WindowPositionFlags.NONE); | ||||
|                           this.positionWindows(0); | ||||
|                       })); | ||||
|  | ||||
|         this.actor.add_actor(clone.actor); | ||||
| @@ -1527,14 +1485,12 @@ const Workspace = new Lang.Class({ | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _getBestLayout: function(windows, area, rowSpacing, columnSpacing) { | ||||
|     _computeLayout: function(windows, area, rowSpacing, columnSpacing) { | ||||
|         // We look for the largest scale that allows us to fit the | ||||
|         // largest row/tallest column on the workspace. | ||||
|  | ||||
|         let lastLayout = {}; | ||||
|  | ||||
|         let strategy = new UnalignedLayoutStrategy(this._monitor, rowSpacing, columnSpacing); | ||||
|  | ||||
|         for (let numRows = 1; ; numRows++) { | ||||
|             let numColumns = Math.ceil(windows.length / numRows); | ||||
|  | ||||
| @@ -1544,6 +1500,8 @@ const Workspace = new Lang.Class({ | ||||
|             if (numColumns == lastLayout.numColumns) | ||||
|                 break; | ||||
|  | ||||
|             let strategy = new UnalignedLayoutStrategy(this._monitor, rowSpacing, columnSpacing); | ||||
|  | ||||
|             let layout = { area: area, strategy: strategy, numRows: numRows, numColumns: numColumns }; | ||||
|             strategy.computeLayout(windows, layout); | ||||
|             strategy.computeScaleAndSpace(layout); | ||||
| @@ -1557,7 +1515,18 @@ const Workspace = new Lang.Class({ | ||||
|         return lastLayout; | ||||
|     }, | ||||
|  | ||||
|     _getSpacingAndPadding: function() { | ||||
|     _rectEqual: function(one, two) { | ||||
|         if (one == two) | ||||
|             return true; | ||||
|  | ||||
|         return (one.x == two.x && | ||||
|                 one.y == two.y && | ||||
|                 one.width == two.width && | ||||
|                 one.height == two.height); | ||||
|     }, | ||||
|  | ||||
|     _computeAllWindowSlots: function(windows) { | ||||
|         let totalWindows = windows.length; | ||||
|         let node = this.actor.get_theme_node(); | ||||
|  | ||||
|         // Window grid spacing | ||||
| @@ -1570,14 +1539,21 @@ const Workspace = new Lang.Class({ | ||||
|             right: node.get_padding(St.Side.RIGHT), | ||||
|         }; | ||||
|  | ||||
|         if (!totalWindows) | ||||
|             return []; | ||||
|  | ||||
|         let closeButtonHeight, captionHeight; | ||||
|         let leftBorder, rightBorder; | ||||
|  | ||||
|         // All of the overlays have the same chrome sizes, | ||||
|         // so just pick the first one. | ||||
|         let overlay = this._windowOverlays[0]; | ||||
|         [closeButtonHeight, captionHeight] = overlay.chromeHeights(); | ||||
|         [leftBorder, rightBorder] = overlay.chromeWidths(); | ||||
|         if (this._windowOverlays.length) { | ||||
|             // All of the overlays have the same chrome sizes, | ||||
|             // so just pick the first one. | ||||
|             let overlay = this._windowOverlays[0]; | ||||
|             [closeButtonHeight, captionHeight] = overlay.chromeHeights(); | ||||
|             [leftBorder, rightBorder] = overlay.chromeWidths(); | ||||
|         } else { | ||||
|             [closeButtonHeight, captionHeight] = [0, 0]; | ||||
|             [leftBorder, rightBorder] = [0, 0]; | ||||
|         } | ||||
|  | ||||
|         rowSpacing += captionHeight; | ||||
|         columnSpacing += (rightBorder + leftBorder) / 2; | ||||
| @@ -1586,13 +1562,25 @@ const Workspace = new Lang.Class({ | ||||
|         padding.left += leftBorder; | ||||
|         padding.right += rightBorder; | ||||
|  | ||||
|         return [rowSpacing, columnSpacing, padding]; | ||||
|     }, | ||||
|         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, | ||||
|         }; | ||||
|  | ||||
|     _computeLayout: function(windows) { | ||||
|         let [rowSpacing, columnSpacing, padding] = this._getSpacingAndPadding(); | ||||
|         let area = padArea(this._fullGeometry, padding); | ||||
|         return this._getBestLayout(windows, area, rowSpacing, columnSpacing); | ||||
|         if (!this._currentLayout) | ||||
|             this._currentLayout = this._computeLayout(windows, area, rowSpacing, columnSpacing); | ||||
|  | ||||
|         let layout = this._currentLayout; | ||||
|         let strategy = layout.strategy; | ||||
|  | ||||
|         if (!this._rectEqual(area, layout.area)) { | ||||
|             layout.area = area; | ||||
|             strategy.computeScaleAndSpace(layout); | ||||
|         } | ||||
|  | ||||
|         return strategy.computeWindowSlots(layout, area); | ||||
|     }, | ||||
|  | ||||
|     _onCloneSelected : function (clone, time) { | ||||
|   | ||||
| @@ -764,8 +764,8 @@ const ThumbnailsBox = new Lang.Class({ | ||||
|                 // to open its first window within some time, as tracked by Shell.WindowTracker. | ||||
|                 // Here, we only add a very brief timeout to avoid the _immediate_ removal of the | ||||
|                 // workspace while we wait for the startup sequence to load. | ||||
|                 Main.wm.keepWorkspaceAlive(global.screen.get_workspace_by_index(newWorkspaceIndex), | ||||
|                                            WORKSPACE_KEEP_ALIVE_TIME); | ||||
|                 Main.keepWorkspaceAlive(global.screen.get_workspace_by_index(newWorkspaceIndex), | ||||
|                                         WORKSPACE_KEEP_ALIVE_TIME); | ||||
|             } | ||||
|  | ||||
|             // Start the animation on the workspace (which is actually | ||||
|   | ||||
| @@ -23,18 +23,6 @@ const MAX_WORKSPACES = 16; | ||||
|  | ||||
| const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides'; | ||||
|  | ||||
| function rectEqual(one, two) { | ||||
|     if (one == two) | ||||
|         return true; | ||||
|  | ||||
|     if (!one || !two) | ||||
|         return false; | ||||
|  | ||||
|     return (one.x == two.x && | ||||
|             one.y == two.y && | ||||
|             one.width == two.width && | ||||
|             one.height == two.height); | ||||
| } | ||||
|  | ||||
| const WorkspacesView = new Lang.Class({ | ||||
|     Name: 'WorkspacesView', | ||||
| @@ -55,9 +43,10 @@ const WorkspacesView = new Lang.Class({ | ||||
|                 this._updateWorkspaceActors(false); | ||||
|             })); | ||||
|  | ||||
|         this._fullGeometry = null; | ||||
|         this._actualGeometry = null; | ||||
|  | ||||
|         this._width = 0; | ||||
|         this._height = 0; | ||||
|         this._x = 0; | ||||
|         this._y = 0; | ||||
|         this._spacing = 0; | ||||
|         this._animating = false; // tweening | ||||
|         this._scrolling = false; // swipe-scrolling | ||||
| @@ -96,8 +85,8 @@ const WorkspacesView = new Lang.Class({ | ||||
|         this._overviewShownId = | ||||
|             Main.overview.connect('shown', | ||||
|                                  Lang.bind(this, function() { | ||||
|                 this.actor.set_clip(this._fullGeometry.x, this._fullGeometry.y, | ||||
|                                     this._fullGeometry.width, this._fullGeometry.height); | ||||
|                 this.actor.set_clip(this._x, this._y, | ||||
|                                     this._width, this._height); | ||||
|         })); | ||||
|  | ||||
|         this.scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex, | ||||
| @@ -135,9 +124,11 @@ const WorkspacesView = new Lang.Class({ | ||||
|                 continue; | ||||
|  | ||||
|             let ws = new Workspace.Workspace(null, i); | ||||
|             ws.setFullGeometry(monitors[i]); | ||||
|             ws.setActualGeometry(monitors[i]); | ||||
|             Main.layoutManager.overviewGroup.add_actor(ws.actor); | ||||
|             ws.setGeometry(monitors[i].x, | ||||
|                            monitors[i].y, | ||||
|                            monitors[i].width, | ||||
|                            monitors[i].height); | ||||
|             global.overlay_group.add_actor(ws.actor); | ||||
|             this._extraWorkspaces.push(ws); | ||||
|         } | ||||
|     }, | ||||
| @@ -148,24 +139,18 @@ const WorkspacesView = new Lang.Class({ | ||||
|         this._extraWorkspaces = []; | ||||
|     }, | ||||
|  | ||||
|     setFullGeometry: function(geom) { | ||||
|         if (rectEqual(this._fullGeometry, geom)) | ||||
|             return; | ||||
|     setGeometry: function(x, y, width, height) { | ||||
|       if (this._x == x && this._y == y && | ||||
|           this._width == width && this._height == height) | ||||
|           return; | ||||
|  | ||||
|         this._fullGeometry = geom; | ||||
|         this._width = width; | ||||
|         this._height = height; | ||||
|         this._x = x; | ||||
|         this._y = y; | ||||
|  | ||||
|         for (let i = 0; i < this._workspaces.length; i++) | ||||
|             this._workspaces[i].setFullGeometry(geom); | ||||
|     }, | ||||
|  | ||||
|     setActualGeometry: function(geom) { | ||||
|         if (rectEqual(this._actualGeometry, geom)) | ||||
|             return; | ||||
|  | ||||
|         this._actualGeometry = geom; | ||||
|  | ||||
|         for (let i = 0; i < this._workspaces.length; i++) | ||||
|             this._workspaces[i].setActualGeometry(geom); | ||||
|             this._workspaces[i].setGeometry(x, y, width, height); | ||||
|     }, | ||||
|  | ||||
|     _lookupWorkspaceForMetaWindow: function (metaWindow) { | ||||
| @@ -225,7 +210,7 @@ const WorkspacesView = new Lang.Class({ | ||||
|  | ||||
|             Tweener.removeTweens(workspace.actor); | ||||
|  | ||||
|             let y = (w - active) * (this._fullGeometry.height + this._spacing); | ||||
|             let y = (w - active) * (this._height + this._spacing); | ||||
|  | ||||
|             if (showAnimation) { | ||||
|                 let params = { y: y, | ||||
| @@ -296,9 +281,8 @@ const WorkspacesView = new Lang.Class({ | ||||
|  | ||||
|         if (newNumWorkspaces > oldNumWorkspaces) { | ||||
|             for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) { | ||||
|                 this._workspaces[w].setFullGeometry(this._fullGeometry); | ||||
|                 if (this._actualGeometry) | ||||
|                     this._workspaces[w].setActualGeometry(this._actualGeometry); | ||||
|                 this._workspaces[w].setGeometry(this._x, this._y, | ||||
|                                                 this._width, this._height); | ||||
|                 this.actor.add_actor(this._workspaces[w].actor); | ||||
|             } | ||||
|  | ||||
| @@ -446,7 +430,7 @@ const WorkspacesDisplay = new Lang.Class({ | ||||
|  | ||||
|     _init: function() { | ||||
|         this.actor = new St.Widget({ clip_to_allocation: true }); | ||||
|         this.actor.connect('notify::allocation', Lang.bind(this, this._updateWorkspacesActualGeometry)); | ||||
|         this.actor.connect('notify::allocation', Lang.bind(this, this._updateWorkspacesGeometry)); | ||||
|         this.actor.connect('parent-set', Lang.bind(this, this._parentSet)); | ||||
|  | ||||
|         let clickAction = new Clutter.ClickAction() | ||||
| @@ -500,8 +484,6 @@ const WorkspacesDisplay = new Lang.Class({ | ||||
|  | ||||
|         this._notifyOpacityId = 0; | ||||
|         this._scrollEventId = 0; | ||||
|  | ||||
|         this._fullGeometry = null; | ||||
|     }, | ||||
|  | ||||
|     _onPan: function(action) { | ||||
| @@ -590,11 +572,10 @@ const WorkspacesDisplay = new Lang.Class({ | ||||
|             this._workspacesViews.push(view); | ||||
|         } | ||||
|  | ||||
|         this._updateWorkspacesFullGeometry(); | ||||
|         this._updateWorkspacesActualGeometry(); | ||||
|         this._updateWorkspacesGeometry(); | ||||
|  | ||||
|         for (let i = 0; i < this._workspacesViews.length; i++) | ||||
|             Main.layoutManager.overviewGroup.add_actor(this._workspacesViews[i].actor); | ||||
|             global.overlay_group.add_actor(this._workspacesViews[i].actor); | ||||
|     }, | ||||
|  | ||||
|     _scrollValueChanged: function() { | ||||
| @@ -638,7 +619,7 @@ const WorkspacesDisplay = new Lang.Class({ | ||||
|  | ||||
|                 // This is kinda hackish - we want the primary view to | ||||
|                 // appear as parent of this.actor, though in reality it | ||||
|                 // is added directly to Main.layoutManager.overviewGroup | ||||
|                 // is added directly to overlay_group | ||||
|                 this._notifyOpacityId = newParent.connect('notify::opacity', | ||||
|                     Lang.bind(this, function() { | ||||
|                         let opacity = this.actor.get_parent().opacity; | ||||
| @@ -651,48 +632,31 @@ const WorkspacesDisplay = new Lang.Class({ | ||||
|         })); | ||||
|     }, | ||||
|  | ||||
|     // This geometry should always be the fullest geometry | ||||
|     // the workspaces switcher can ever be allocated, as if | ||||
|     // the sliding controls were never slid in at all. | ||||
|     setWorkspacesFullGeometry: function(geom) { | ||||
|         this._fullGeometry = geom; | ||||
|         this._updateWorkspacesFullGeometry(); | ||||
|     }, | ||||
|  | ||||
|     _updateWorkspacesFullGeometry: function() { | ||||
|     _updateWorkspacesGeometry: function() { | ||||
|         if (!this._workspacesViews.length) | ||||
|             return; | ||||
|  | ||||
|         let monitors = Main.layoutManager.monitors; | ||||
|         let m = 0; | ||||
|         for (let i = 0; i < monitors.length; i++) { | ||||
|             if (i == this._primaryIndex) { | ||||
|                 this._workspacesViews[m].setFullGeometry(this._fullGeometry); | ||||
|                 m++; | ||||
|             } else if (!this._workspacesOnlyOnPrimary) { | ||||
|                 this._workspacesViews[m].setFullGeometry(monitors[i]); | ||||
|                 m++; | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|         let fullWidth = this.actor.allocation.x2 - this.actor.allocation.x1; | ||||
|         let fullHeight = this.actor.allocation.y2 - this.actor.allocation.y1; | ||||
|  | ||||
|     _updateWorkspacesActualGeometry: function() { | ||||
|         if (!this._workspacesViews.length) | ||||
|             return; | ||||
|         let width = fullWidth; | ||||
|         let height = fullHeight; | ||||
|  | ||||
|         let [x, y] = this.actor.get_transformed_position(); | ||||
|         let width = this.actor.allocation.x2 - this.actor.allocation.x1; | ||||
|         let height = this.actor.allocation.y2 - this.actor.allocation.y1; | ||||
|         let geometry = { x: x, y: y, width: width, height: height }; | ||||
|  | ||||
|         let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL); | ||||
|  | ||||
|         let monitors = Main.layoutManager.monitors; | ||||
|         let m = 0; | ||||
|         for (let i = 0; i < monitors.length; i++) { | ||||
|             if (i == this._primaryIndex) { | ||||
|                 this._workspacesViews[m].setActualGeometry(geometry); | ||||
|                 this._workspacesViews[m].setGeometry(x, y, width, height); | ||||
|                 m++; | ||||
|             } else if (!this._workspacesOnlyOnPrimary) { | ||||
|                 this._workspacesViews[m].setActualGeometry(monitors[i]); | ||||
|                 this._workspacesViews[m].setGeometry(monitors[i].x, | ||||
|                                                      monitors[i].y, | ||||
|                                                      monitors[i].width, | ||||
|                                                      monitors[i].height); | ||||
|                 m++; | ||||
|             } | ||||
|         } | ||||
| @@ -760,20 +724,15 @@ const WorkspacesDisplay = new Lang.Class({ | ||||
|     _onScrollEvent: function(actor, event) { | ||||
|         if (!this.actor.mapped) | ||||
|             return false; | ||||
|         let activeWs = global.screen.get_active_workspace(); | ||||
|         let ws; | ||||
|         switch (event.get_scroll_direction()) { | ||||
|         case Clutter.ScrollDirection.UP: | ||||
|             ws = activeWs.get_neighbor(Meta.MotionDirection.UP); | ||||
|             break; | ||||
|             Main.wm.actionMoveWorkspace(Meta.MotionDirection.UP); | ||||
|             return true; | ||||
|         case Clutter.ScrollDirection.DOWN: | ||||
|             ws = activeWs.get_neighbor(Meta.MotionDirection.DOWN); | ||||
|             break; | ||||
|         default: | ||||
|             return false; | ||||
|             Main.wm.actionMoveWorkspace(Meta.MotionDirection.DOWN); | ||||
|             return true; | ||||
|         } | ||||
|         Main.wm.actionMoveWorkspace(ws); | ||||
|         return true; | ||||
|         return false; | ||||
|     } | ||||
| }); | ||||
| Signals.addSignalMethods(WorkspacesDisplay.prototype); | ||||
|   | ||||
| @@ -16,7 +16,7 @@ const XdndHandler = new Lang.Class({ | ||||
|         this._cursorWindowClone = null; | ||||
|  | ||||
|         // Used as a drag actor in case we don't have a cursor window clone | ||||
|         this._dummy = new Clutter.Actor({ width: 1, height: 1, opacity: 0 }); | ||||
|         this._dummy = new Clutter.Rectangle({ width: 1, height: 1, opacity: 0 }); | ||||
|         Main.uiGroup.add_actor(this._dummy); | ||||
|         Shell.util_set_hidden_from_pick(this._dummy, true); | ||||
|         this._dummy.hide(); | ||||
|   | ||||
| @@ -125,12 +125,6 @@ | ||||
|                                 <listitem><para>List possible modes and exit</para></listitem> | ||||
|                         </varlistentry> | ||||
|  | ||||
|                         <varlistentry> | ||||
|                                 <term><option>--clutter-display=<replaceable>DISPLAY</replaceable></option></term> | ||||
|  | ||||
|                                 <listitem><para>Clutter the option display (otherwise ignored)</para></listitem> | ||||
|                         </varlistentry> | ||||
|  | ||||
|                 </variablelist> | ||||
|  | ||||
|         </refsect1> | ||||
|   | ||||
| @@ -28,7 +28,6 @@ gu | ||||
| he | ||||
| hi | ||||
| hu | ||||
| ia | ||||
| id | ||||
| it | ||||
| ja | ||||
|   | ||||
| @@ -55,7 +55,6 @@ js/ui/viewSelector.js | ||||
| js/ui/wanda.js | ||||
| js/ui/windowAttentionHandler.js | ||||
| src/calendar-server/evolution-calendar.desktop.in.in | ||||
| # Please do not remove this file from POTFILES.in. Run "git submodule init && git submodule update" to get it. | ||||
| src/gvc/gvc-mixer-control.c | ||||
| src/main.c | ||||
| src/shell-app.c | ||||
|   | ||||
							
								
								
									
										4
									
								
								po/ca.po
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								po/ca.po
									
									
									
									
									
								
							| @@ -11,7 +11,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: 2013-03-11 21:29+0000\n" | ||||
| "PO-Revision-Date: 2013-05-26 08:21+0200\n" | ||||
| "PO-Revision-Date: 2013-03-11 00:03+0100\n" | ||||
| "Last-Translator: Gil Forcada <gilforcada@guifi.net>\n" | ||||
| "Language-Team: Catalan <tradgnome@softcatala.org>\n" | ||||
| "Language: ca\n" | ||||
| @@ -1048,7 +1048,7 @@ msgstr "Obre els rellotges" | ||||
|  | ||||
| #: ../js/ui/dateMenu.js:105 | ||||
| msgid "Date & Time Settings" | ||||
| msgstr "Configuració de la data i de l'hora" | ||||
| msgstr "Configuració de la data i l'hora" | ||||
|  | ||||
| #. 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"). | ||||
|   | ||||
							
								
								
									
										389
									
								
								po/de.po
									
									
									
									
									
								
							
							
						
						
									
										389
									
								
								po/de.po
									
									
									
									
									
								
							| @@ -17,10 +17,9 @@ | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: gnome-shell master\n" | ||||
| "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" | ||||
| "shell&keywords=I18N+L10N&component=general\n" | ||||
| "POT-Creation-Date: 2013-05-31 22:35+0000\n" | ||||
| "PO-Revision-Date: 2013-06-02 09:48+0100\n" | ||||
| "Report-Msgid-Bugs-To: \n" | ||||
| "POT-Creation-Date: 2013-03-11 14:22+0100\n" | ||||
| "PO-Revision-Date: 2013-03-11 14:25+0100\n" | ||||
| "Last-Translator: Christian Kirbach <christian.kirbach@gmail.com>\n" | ||||
| "Language-Team: Deutsch <gnome-de@gnome.org>\n" | ||||
| "Language: de_DE\n" | ||||
| @@ -28,7 +27,7 @@ msgstr "" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||||
| "X-Generator: Poedit 1.5.4\n" | ||||
| "X-Generator: Gtranslator 2.91.6\n" | ||||
|  | ||||
| #: ../data/50-gnome-shell-screenshot.xml.in.h:1 | ||||
| msgid "Screenshots" | ||||
| @@ -51,14 +50,10 @@ msgid "Focus the active notification" | ||||
| msgstr "Auf aktive Benachrichtigungen ausrichten" | ||||
|  | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:4 | ||||
| msgid "Show the overview" | ||||
| msgstr "Die Übersicht anzeigen" | ||||
|  | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:5 | ||||
| msgid "Show all applications" | ||||
| msgstr "Alle Anwendungen anzeigen" | ||||
|  | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:6 | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:5 | ||||
| msgid "Open the application menu" | ||||
| msgstr "Das Anwendungsmenü öffnen" | ||||
|  | ||||
| @@ -107,10 +102,27 @@ msgstr "" | ||||
| "gnome.Shell bearbeiten." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:5 | ||||
| msgid "Whether to collect stats about applications usage" | ||||
| msgstr "Legt fest, ob Statistiken über Anwendungsnutzung erfasst werden sollen" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:6 | ||||
| msgid "" | ||||
| "The shell normally monitors active applications in order to present the most " | ||||
| "used ones (e.g. in launchers). While this data will be kept private, you may " | ||||
| "want to disable this for privacy reasons. Please note that doing so won't " | ||||
| "remove already saved data." | ||||
| msgstr "" | ||||
| "Die Shell überwacht normalerweise aktive Anwendungen, wobei die " | ||||
| "meistgenutzten zuerst erfasst werden (z.B. in Anwendungsstartern). Zwar " | ||||
| "werden diese Daten privat gespeichert, doch möglicherweise wollen Sie dies " | ||||
| "deaktivieren, um Ihre Privatsphäre zu schützen. Bitte beachten Sie, dass " | ||||
| "bereits gespeicherte Daten hiervon nicht beeinflusst werden." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:7 | ||||
| msgid "List of desktop file IDs for favorite applications" | ||||
| msgstr "Liste der Kennungen der Desktop-Dateien für bevorzugte Anwendungen" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:6 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:8 | ||||
| msgid "" | ||||
| "The applications corresponding to these identifiers will be displayed in the " | ||||
| "favorites area." | ||||
| @@ -118,11 +130,11 @@ msgstr "" | ||||
| "Programme, welche auf diese Bezeichner zutreffen, werden im Favoriten-" | ||||
| "Bereich angezeigt." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:7 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:9 | ||||
| msgid "List of categories that should be displayed as folders" | ||||
| msgstr "Liste der Kategorien, die als Ordner angezeigt werden sollen" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:8 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:10 | ||||
| msgid "" | ||||
| "Each category name in this list will be represented as folder in the " | ||||
| "application view, rather than being displayed inline in the main view." | ||||
| @@ -130,15 +142,15 @@ msgstr "" | ||||
| "Jeder Kategoriename in dieser Liste wird als Ordner in der Anwendungsansicht " | ||||
| "dargestellt, anstatt in der Hauptansicht eingebettet." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:9 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:11 | ||||
| msgid "History for command (Alt-F2) dialog" | ||||
| msgstr "Verlauf des Befehlsdialogs (Alt+F2)" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:10 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:12 | ||||
| msgid "History for the looking glass dialog" | ||||
| msgstr "Chronik des Dialogs »looking glass«" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:11 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:13 | ||||
| msgid "" | ||||
| "Internally used to store the last IM presence explicitly set by the user. " | ||||
| "The value here is from the TpConnectionPresenceType enumeration." | ||||
| @@ -147,7 +159,7 @@ msgstr "" | ||||
| "der explizit vom Benutzer gesetzt wurde. Der hier verwendete Wert wird der " | ||||
| "TpConnectionPresenceType-Aufzählung entnommen." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:12 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:14 | ||||
| msgid "" | ||||
| "Internally used to store the last session presence status for the user. The " | ||||
| "value here is from the GsmPresenceStatus enumeration." | ||||
| @@ -156,11 +168,11 @@ msgstr "" | ||||
| "Benutzers verwendet. Der hier verwendete Wert wird der GsmPresenceStatus-" | ||||
| "Aufzählung entnommen." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:13 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:15 | ||||
| msgid "Always show the 'Log out' menuitem in the user menu." | ||||
| msgstr "Den Menüeintrag »Abmelden« immer im Benutzermenü anzeigen." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:14 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:16 | ||||
| msgid "" | ||||
| "This key overrides the automatic hiding of the 'Log out' menuitem in single-" | ||||
| "user, single-session situations." | ||||
| @@ -168,14 +180,14 @@ msgstr "" | ||||
| "Dieser Schlüssel überschreibt das automatische Verbergen des Menüeintrags " | ||||
| "»Abmelden« in Einzelbenutzer, Einzelsitzungssituationen." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:15 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:17 | ||||
| msgid "" | ||||
| "Whether to remember password for mounting encrypted or remote filesystems" | ||||
| msgstr "" | ||||
| "Legt fest, ob Passwörter für eingehängte, verschlüsselte oder ferne " | ||||
| "Dateisysteme gespeichert werden" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:16 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:18 | ||||
| msgid "" | ||||
| "The shell will request a password when an encrypted device or a remote " | ||||
| "filesystem is mounted. If the password can be saved for future use a " | ||||
| @@ -188,42 +200,34 @@ msgstr "" | ||||
| "angeboten. Dieser Schlüssel stellt den Standardstatus für dieses Ankreuzfeld " | ||||
| "ein." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:17 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:19 | ||||
| msgid "Show the week date in the calendar" | ||||
| msgstr "Wochentag im Kalender anzeigen" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:18 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:20 | ||||
| msgid "If true, display the ISO week date in the calendar." | ||||
| msgstr "" | ||||
| "Wenn dieser Wert gesetzt ist, wird der ISO-Wochentag im Kalender angezeigt." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:19 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:21 | ||||
| msgid "Keybinding to open the application menu" | ||||
| msgstr "Tastenkombination zum Öffnen des Anwendungsmenüs" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:20 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:22 | ||||
| msgid "Keybinding to open the application menu." | ||||
| msgstr "Tastenkombination zum Öffnen des Anwendungsmenüs." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:21 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:23 | ||||
| msgid "Keybinding to open the \"Show Applications\" view" | ||||
| msgstr "Tastenkombination zum Öffnen der »Anwendungen anzeigen«-Ansicht" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:22 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:24 | ||||
| msgid "" | ||||
| "Keybinding to open the \"Show Applications\" view of the Activities Overview." | ||||
| msgstr "" | ||||
| "Tastenkombination zum Öffnen der »Anwendungen anzeigen«-Ansicht der " | ||||
| "Aktivitätenübersicht." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:23 | ||||
| msgid "Keybinding to open the overview" | ||||
| msgstr "Tastenkombination zum Öffnen der Übersicht" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:24 | ||||
| msgid "Keybinding to open the Activities Overview." | ||||
| msgstr "Tastenkombination zum Öffnen der »Aktivitäten«-Übersicht" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:25 | ||||
| msgid "Keybinding to toggle the visibility of the message tray" | ||||
| msgstr "" | ||||
| @@ -387,50 +391,43 @@ msgstr "Erweiterung" | ||||
| msgid "Select an extension to configure using the combobox above." | ||||
| msgstr "Wählen Sie oben eine Erweiterung aus, die Sie konfigurieren wollen." | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:371 | ||||
| #: ../js/gdm/loginDialog.js:405 | ||||
| msgid "Session…" | ||||
| msgstr "Sitzung …" | ||||
|  | ||||
| #. 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:601 | ||||
| #: ../js/gdm/loginDialog.js:630 | ||||
| msgid "Not listed?" | ||||
| msgstr "Nicht aufgeführt?" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:376 | ||||
| #: ../js/gdm/loginDialog.js:784 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 | ||||
| #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:96 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:98 | ||||
| #: ../js/ui/userMenu.js:938 | ||||
| msgid "Cancel" | ||||
| msgstr "Abbrechen" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:791 | ||||
| #: ../js/gdm/loginDialog.js:800 | ||||
| msgctxt "button" | ||||
| msgid "Sign In" | ||||
| msgstr "Anmelden" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:791 | ||||
| #: ../js/gdm/loginDialog.js:800 | ||||
| msgid "Next" | ||||
| msgstr "Nächstes" | ||||
|  | ||||
| #. Translators: this message is shown below the username entry field | ||||
| #. to clue the user in on how to login to the local network realm | ||||
| #: ../js/gdm/loginDialog.js:888 | ||||
| #, c-format | ||||
| msgid "(e.g., user or %s)" | ||||
| msgstr "(z.B. Benutzer oder %s)" | ||||
|  | ||||
| #. TTLS and PEAP are actually much more complicated, but this complication | ||||
| #. is not visible here since we only care about phase2 authentication | ||||
| #. (and don't even care of which one) | ||||
| #: ../js/gdm/loginDialog.js:892 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/gdm/loginDialog.js:915 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/ui/components/networkAgent.js:278 | ||||
| msgid "Username: " | ||||
| msgstr "Benutzername:" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:1158 | ||||
| #: ../js/gdm/loginDialog.js:1168 | ||||
| msgid "Login Window" | ||||
| msgstr "Anmeldefenster" | ||||
|  | ||||
| @@ -453,48 +450,53 @@ msgstr "Neu starten" | ||||
| msgid "Power Off" | ||||
| msgstr "Ausschalten" | ||||
|  | ||||
| #: ../js/gdm/util.js:247 | ||||
| #: ../js/gdm/util.js:182 | ||||
| msgid "Authentication error" | ||||
| msgstr "Legitimationsfehler" | ||||
|  | ||||
| #. Translators: this message is shown below the password entry field | ||||
| #. to indicate the user can swipe their finger instead | ||||
| #: ../js/gdm/util.js:364 | ||||
| #: ../js/gdm/util.js:299 | ||||
| msgid "(or swipe finger)" | ||||
| msgstr "(oder benutzen Sie den Fingerabdruckleser)" | ||||
|  | ||||
| #: ../js/misc/util.js:97 | ||||
| #: ../js/gdm/util.js:324 | ||||
| #, c-format | ||||
| msgid "(e.g., user or %s)" | ||||
| msgstr "(z.B. Benutzer oder %s)" | ||||
|  | ||||
| #: ../js/misc/util.js:94 | ||||
| msgid "Command not found" | ||||
| msgstr "Befehl nicht gefunden" | ||||
|  | ||||
| #. Replace "Error invoking GLib.shell_parse_argv: " with | ||||
| #. something nicer | ||||
| #: ../js/misc/util.js:130 | ||||
| #: ../js/misc/util.js:127 | ||||
| msgid "Could not parse command:" | ||||
| msgstr "Befehl konnte nicht verarbeitet werden:" | ||||
|  | ||||
| #: ../js/misc/util.js:138 | ||||
| #: ../js/misc/util.js:135 | ||||
| #, c-format | ||||
| msgid "Execution of '%s' failed:" | ||||
| msgstr "Ausführung von »%s« ist gescheitert:" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:361 | ||||
| #: ../js/ui/appDisplay.js:348 | ||||
| msgid "Frequent" | ||||
| msgstr "Häufig" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:368 | ||||
| #: ../js/ui/appDisplay.js:355 | ||||
| msgid "All" | ||||
| msgstr "Alle" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:960 | ||||
| #: ../js/ui/appDisplay.js:913 | ||||
| msgid "New Window" | ||||
| msgstr "Neues Fenster" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:963 ../js/ui/dash.js:284 | ||||
| #: ../js/ui/appDisplay.js:916 ../js/ui/dash.js:284 | ||||
| msgid "Remove from Favorites" | ||||
| msgstr "Aus Favoriten entfernen" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:964 | ||||
| #: ../js/ui/appDisplay.js:917 | ||||
| msgid "Add to Favorites" | ||||
| msgstr "Zu Favoriten hinzufügen" | ||||
|  | ||||
| @@ -534,7 +536,7 @@ msgstr "%H\\u2236%M" | ||||
|  | ||||
| # wird nur verwendet, wenn die Anwendung explizit auf 12h-Format eingestellt ist. | ||||
| # http://linux.die.net/man/3/strftime | ||||
| #. Translators: Shown in calendar event list, if 12h format, | ||||
| #. Transators: Shown in calendar event list, if 12h format, | ||||
| #. \u2236 is a ratio character, similar to : and \u2009 is | ||||
| #. a thin space | ||||
| #: ../js/ui/calendar.js:77 | ||||
| @@ -636,35 +638,35 @@ msgid "S" | ||||
| msgstr "Sa" | ||||
|  | ||||
| #. Translators: Text to show if there are no events | ||||
| #: ../js/ui/calendar.js:735 | ||||
| #: ../js/ui/calendar.js:720 | ||||
| msgid "Nothing Scheduled" | ||||
| msgstr "Nichts geplant" | ||||
|  | ||||
| #. Translators: Shown on calendar heading when selected day occurs on current year | ||||
| #: ../js/ui/calendar.js:751 | ||||
| #: ../js/ui/calendar.js:736 | ||||
| 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:754 | ||||
| #: ../js/ui/calendar.js:739 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d, %Y" | ||||
| msgstr "%a, %d. %B %Y" | ||||
|  | ||||
| #: ../js/ui/calendar.js:764 | ||||
| #: ../js/ui/calendar.js:749 | ||||
| msgid "Today" | ||||
| msgstr "Heute" | ||||
|  | ||||
| #: ../js/ui/calendar.js:768 | ||||
| #: ../js/ui/calendar.js:753 | ||||
| msgid "Tomorrow" | ||||
| msgstr "Morgen" | ||||
|  | ||||
| #: ../js/ui/calendar.js:779 | ||||
| #: ../js/ui/calendar.js:764 | ||||
| msgid "This week" | ||||
| msgstr "Diese Woche" | ||||
|  | ||||
| #: ../js/ui/calendar.js:787 | ||||
| #: ../js/ui/calendar.js:772 | ||||
| msgid "Next week" | ||||
| msgstr "Nächste Woche" | ||||
|  | ||||
| @@ -680,20 +682,20 @@ msgstr "Externes Laufwerk getrennt" | ||||
| msgid "Removable Devices" | ||||
| msgstr "Wechseldatenträger" | ||||
|  | ||||
| #: ../js/ui/components/autorunManager.js:594 | ||||
| #: ../js/ui/components/autorunManager.js:593 | ||||
| #, c-format | ||||
| msgid "Open with %s" | ||||
| msgstr "Öffnen mit %s" | ||||
|  | ||||
| #: ../js/ui/components/autorunManager.js:620 | ||||
| #: ../js/ui/components/autorunManager.js:619 | ||||
| msgid "Eject" | ||||
| msgstr "Auswerfen" | ||||
|  | ||||
| #: ../js/ui/components/keyring.js:88 ../js/ui/components/polkitAgent.js:280 | ||||
| #: ../js/ui/components/keyring.js:82 ../js/ui/components/polkitAgent.js:268 | ||||
| msgid "Password:" | ||||
| msgstr "Passwort:" | ||||
|  | ||||
| #: ../js/ui/components/keyring.js:107 | ||||
| #: ../js/ui/components/keyring.js:101 | ||||
| msgid "Type again:" | ||||
| msgstr "Erneut eingeben:" | ||||
|  | ||||
| @@ -773,15 +775,15 @@ msgstr "Passwort der mobilen Breitbandverbindung" | ||||
| msgid "A password is required to connect to '%s'." | ||||
| msgstr "Es wird ein Passwort benötigt, um sich mit »%s« zu verbinden." | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:54 | ||||
| #: ../js/ui/components/polkitAgent.js:55 | ||||
| msgid "Authentication Required" | ||||
| msgstr "Legitimierung erforderlich" | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:92 | ||||
| #: ../js/ui/components/polkitAgent.js:93 | ||||
| msgid "Administrator" | ||||
| msgstr "Systemverwalter" | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:170 | ||||
| #: ../js/ui/components/polkitAgent.js:165 | ||||
| msgid "Authenticate" | ||||
| msgstr "Legitimieren" | ||||
|  | ||||
| @@ -789,12 +791,12 @@ msgstr "Legitimieren" | ||||
| #. * requested authentication was not gained; this can happen | ||||
| #. * because of an authentication error (like invalid password), | ||||
| #. * for instance. | ||||
| #: ../js/ui/components/polkitAgent.js:266 ../js/ui/shellMountOperation.js:383 | ||||
| #: ../js/ui/components/polkitAgent.js:256 ../js/ui/shellMountOperation.js:383 | ||||
| msgid "Sorry, that didn't work. Please try again." | ||||
| msgstr "Entschuldigung, das hat nicht geklappt. Bitte versuchen Sie es erneut." | ||||
|  | ||||
| #. Translators: this is a filename used for screencast recording | ||||
| #: ../js/ui/components/recorder.js:47 | ||||
| #: ../js/ui/components/recorder.js:48 | ||||
| #, no-c-format | ||||
| msgid "Screencast from %d %t" | ||||
| msgstr "Bildschirmaufzeichnung von %d %t" | ||||
| @@ -1053,26 +1055,26 @@ msgstr "Anwendungen anzeigen" | ||||
| # Würde ich so übernehmen, oder evtl. »Dock«. | ||||
| #. Translators: this is the name of the dock/favorites area on | ||||
| #. the left of the overview | ||||
| #: ../js/ui/dash.js:429 | ||||
| #: ../js/ui/dash.js:435 | ||||
| msgid "Dash" | ||||
| msgstr "Dash" | ||||
|  | ||||
| #: ../js/ui/dateMenu.js:86 | ||||
| #: ../js/ui/dateMenu.js:91 | ||||
| msgid "Open Calendar" | ||||
| msgstr "Kalender öffnen" | ||||
|  | ||||
| #: ../js/ui/dateMenu.js:90 | ||||
| #: ../js/ui/dateMenu.js:96 | ||||
| msgid "Open Clocks" | ||||
| msgstr "Uhren öffnen" | ||||
|  | ||||
| #: ../js/ui/dateMenu.js:97 | ||||
| #: ../js/ui/dateMenu.js:105 | ||||
| msgid "Date & Time Settings" | ||||
| msgstr "Einstellungen für Datum und Uhrzeit" | ||||
|  | ||||
| #. 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:208 | ||||
| #: ../js/ui/dateMenu.js:215 | ||||
| msgid "%A %B %e, %Y" | ||||
| msgstr "%A, %e. %B %Y" | ||||
|  | ||||
| @@ -1179,56 +1181,56 @@ msgstr "Installieren" | ||||
| msgid "Download and install '%s' from extensions.gnome.org?" | ||||
| msgstr "»%s« von extensions.gnome.org herunterladen und installieren?" | ||||
|  | ||||
| #: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:333 | ||||
| #: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:314 | ||||
| #: ../js/ui/status/power.js:211 | ||||
| msgid "Keyboard" | ||||
| msgstr "Tastatur" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:689 | ||||
| #: ../js/ui/lookingGlass.js:693 | ||||
| msgid "No extensions installed" | ||||
| msgstr "Keine Erweiterungen installiert" | ||||
|  | ||||
| #. Translators: argument is an extension UUID. | ||||
| #: ../js/ui/lookingGlass.js:743 | ||||
| #: ../js/ui/lookingGlass.js:747 | ||||
| #, c-format | ||||
| msgid "%s has not emitted any errors." | ||||
| msgstr "%s hat keine Fehler ausgegeben." | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:749 | ||||
| #: ../js/ui/lookingGlass.js:753 | ||||
| msgid "Hide Errors" | ||||
| msgstr "Fehler verbergen" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:753 ../js/ui/lookingGlass.js:813 | ||||
| #: ../js/ui/lookingGlass.js:757 ../js/ui/lookingGlass.js:817 | ||||
| msgid "Show Errors" | ||||
| msgstr "Fehler anzeigen" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:762 | ||||
| #: ../js/ui/lookingGlass.js:766 | ||||
| msgid "Enabled" | ||||
| msgstr "Aktiviert" | ||||
|  | ||||
| #. translators: | ||||
| #. * The device has been disabled | ||||
| #: ../js/ui/lookingGlass.js:765 ../src/gvc/gvc-mixer-control.c:1830 | ||||
| #: ../js/ui/lookingGlass.js:769 ../src/gvc/gvc-mixer-control.c:1830 | ||||
| msgid "Disabled" | ||||
| msgstr "Deaktiviert" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:767 | ||||
| #: ../js/ui/lookingGlass.js:771 | ||||
| msgid "Error" | ||||
| msgstr "Fehler" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:769 | ||||
| #: ../js/ui/lookingGlass.js:773 | ||||
| msgid "Out of date" | ||||
| msgstr "Veraltet" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:771 | ||||
| #: ../js/ui/lookingGlass.js:775 | ||||
| msgid "Downloading" | ||||
| msgstr "Herunterladen" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:795 | ||||
| #: ../js/ui/lookingGlass.js:799 | ||||
| msgid "View Source" | ||||
| msgstr "Quelle zeigen" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:804 | ||||
| #: ../js/ui/lookingGlass.js:808 | ||||
| msgid "Web Page" | ||||
| msgstr "Webseite" | ||||
|  | ||||
| @@ -1248,35 +1250,35 @@ msgstr "Nachrichten leeren" | ||||
| msgid "Notification Settings" | ||||
| msgstr "Benachrichtigungseinstellungen" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1711 | ||||
| #: ../js/ui/messageTray.js:1707 | ||||
| msgid "No Messages" | ||||
| msgstr "Keine Nachrichten" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1784 | ||||
| #: ../js/ui/messageTray.js:1782 | ||||
| msgid "Message Tray" | ||||
| msgstr "Benachrichtigungsfeld" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:2811 | ||||
| #: ../js/ui/messageTray.js:2869 | ||||
| msgid "System Information" | ||||
| msgstr "Systeminformationen" | ||||
|  | ||||
| #: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:378 | ||||
| #: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:374 | ||||
| msgctxt "program" | ||||
| msgid "Unknown" | ||||
| msgstr "Unbekannt" | ||||
|  | ||||
| #: ../js/ui/overviewControls.js:474 ../js/ui/screenShield.js:150 | ||||
| #: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:153 | ||||
| #, c-format | ||||
| msgid "%d new message" | ||||
| msgid_plural "%d new messages" | ||||
| msgstr[0] "%d neue Nachricht" | ||||
| msgstr[1] "%d neue Nachrichten" | ||||
|  | ||||
| #: ../js/ui/overview.js:82 | ||||
| #: ../js/ui/overview.js:84 | ||||
| msgid "Undo" | ||||
| msgstr "Rückgängig" | ||||
|  | ||||
| #: ../js/ui/overview.js:127 | ||||
| #: ../js/ui/overview.js:131 | ||||
| msgid "Overview" | ||||
| msgstr "Übersicht" | ||||
|  | ||||
| @@ -1284,21 +1286,21 @@ msgstr "Übersicht" | ||||
| #. in the search entry when no search is | ||||
| #. active; it should not exceed ~30 | ||||
| #. characters. | ||||
| #: ../js/ui/overview.js:258 | ||||
| #: ../js/ui/overview.js:287 | ||||
| msgid "Type to search…" | ||||
| msgstr "Suchbegriff eingeben …" | ||||
|  | ||||
| #: ../js/ui/panel.js:642 | ||||
| #: ../js/ui/panel.js:612 | ||||
| msgid "Quit" | ||||
| msgstr "Beenden" | ||||
|  | ||||
| #. Translators: If there is no suitable word for "Activities" | ||||
| #. in your language, you can use the word for "Overview". | ||||
| #: ../js/ui/panel.js:693 | ||||
| #: ../js/ui/panel.js:636 | ||||
| msgid "Activities" | ||||
| msgstr "Aktivitäten" | ||||
|  | ||||
| #: ../js/ui/panel.js:989 | ||||
| #: ../js/ui/panel.js:933 | ||||
| msgid "Top Bar" | ||||
| msgstr "Oberes Panel" | ||||
|  | ||||
| @@ -1307,15 +1309,15 @@ msgstr "Oberes Panel" | ||||
| #. "ON" and "OFF") or "toggle-switch-intl" (for toggle | ||||
| #. switches containing "◯" and "|"). Other values will | ||||
| #. simply result in invisible toggle switches. | ||||
| #: ../js/ui/popupMenu.js:738 | ||||
| #: ../js/ui/popupMenu.js:727 | ||||
| msgid "toggle-switch-us" | ||||
| msgstr "toggle-switch-intl" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:74 | ||||
| #: ../js/ui/runDialog.js:73 | ||||
| msgid "Enter a Command" | ||||
| msgstr "Bitte geben Sie einen Befehl ein" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:110 | ||||
| #: ../js/ui/runDialog.js:109 | ||||
| msgid "Close" | ||||
| msgstr "Schließen" | ||||
|  | ||||
| @@ -1324,22 +1326,22 @@ msgstr "Schließen" | ||||
| # %B - ausgeschriebener Name des Monats, abhängig von der gesetzten Umgebung | ||||
| #. Translators: This is a time format for a date in | ||||
| #. long format | ||||
| #: ../js/ui/screenShield.js:87 | ||||
| #: ../js/ui/screenShield.js:90 | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%A, %d. %B" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:152 | ||||
| #: ../js/ui/screenShield.js:155 | ||||
| #, c-format | ||||
| msgid "%d new notification" | ||||
| msgid_plural "%d new notifications" | ||||
| msgstr[0] "%d neue Benachrichtigung" | ||||
| msgstr[1] "%d neue Benachrichtigungen" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:449 ../js/ui/userMenu.js:807 | ||||
| #: ../js/ui/screenShield.js:442 ../js/ui/userMenu.js:807 | ||||
| msgid "Lock" | ||||
| msgstr "Sperren" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:652 | ||||
| #: ../js/ui/screenShield.js:639 | ||||
| msgid "GNOME needs to lock the screen" | ||||
| msgstr "GNOME muss den Bildschirm sperren" | ||||
|  | ||||
| @@ -1350,35 +1352,35 @@ msgstr "GNOME muss den Bildschirm sperren" | ||||
| #. | ||||
| #. XXX: another option is to kick the user into the gdm login | ||||
| #. screen, where we're not affected by grabs | ||||
| #: ../js/ui/screenShield.js:773 ../js/ui/screenShield.js:1213 | ||||
| #: ../js/ui/screenShield.js:758 ../js/ui/screenShield.js:1169 | ||||
| msgid "Unable to lock" | ||||
| msgstr "Sperrung fehlgeschlagen" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:774 ../js/ui/screenShield.js:1214 | ||||
| #: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1170 | ||||
| msgid "Lock was blocked by an application" | ||||
| msgstr "Sperrung wurde von einer Anwendung blockiert" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:445 | ||||
| #: ../js/ui/searchDisplay.js:431 | ||||
| msgid "Searching…" | ||||
| msgstr "Suche läuft …" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:489 | ||||
| #: ../js/ui/searchDisplay.js:475 | ||||
| msgid "No results." | ||||
| msgstr "Keine Ergebnisse." | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:27 | ||||
| #: ../js/ui/shellEntry.js:29 | ||||
| msgid "Copy" | ||||
| msgstr "Kopieren" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:32 | ||||
| #: ../js/ui/shellEntry.js:34 | ||||
| msgid "Paste" | ||||
| msgstr "Einfügen" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:99 | ||||
| #: ../js/ui/shellEntry.js:106 | ||||
| msgid "Show Text" | ||||
| msgstr "Text anzeigen" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:101 | ||||
| #: ../js/ui/shellEntry.js:108 | ||||
| msgid "Hide Text" | ||||
| msgstr "Text verbergen" | ||||
|  | ||||
| @@ -1390,7 +1392,7 @@ msgstr "Passwort" | ||||
| msgid "Remember Password" | ||||
| msgstr "An Passwort erinnern" | ||||
|  | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:109 | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:112 | ||||
| msgid "Unlock" | ||||
| msgstr "Entsperren" | ||||
|  | ||||
| @@ -1445,7 +1447,7 @@ msgstr "Große Schrift" | ||||
| #: ../js/ui/status/bluetooth.js:28 ../js/ui/status/bluetooth.js:32 | ||||
| #: ../js/ui/status/bluetooth.js:289 ../js/ui/status/bluetooth.js:321 | ||||
| #: ../js/ui/status/bluetooth.js:357 ../js/ui/status/bluetooth.js:388 | ||||
| #: ../js/ui/status/network.js:739 | ||||
| #: ../js/ui/status/network.js:826 | ||||
| msgid "Bluetooth" | ||||
| msgstr "Bluetooth" | ||||
|  | ||||
| @@ -1466,7 +1468,7 @@ msgid "Bluetooth Settings" | ||||
| msgstr "Bluetooth-Einstellungen" | ||||
|  | ||||
| #. TRANSLATORS: this means that bluetooth was disabled by hardware rfkill | ||||
| #: ../js/ui/status/bluetooth.js:104 ../js/ui/status/network.js:142 | ||||
| #: ../js/ui/status/bluetooth.js:104 ../js/ui/status/network.js:178 | ||||
| msgid "hardware disabled" | ||||
| msgstr "Hardware deaktiviert" | ||||
|  | ||||
| @@ -1474,12 +1476,12 @@ msgstr "Hardware deaktiviert" | ||||
| msgid "Connection" | ||||
| msgstr "Verbindung" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:208 ../js/ui/status/network.js:404 | ||||
| #: ../js/ui/status/bluetooth.js:208 ../js/ui/status/network.js:460 | ||||
| msgid "disconnecting..." | ||||
| msgstr "Verbindungsabbau …" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:410 | ||||
| #: ../js/ui/status/network.js:1343 | ||||
| #: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:466 | ||||
| #: ../js/ui/status/network.js:1546 | ||||
| msgid "connecting..." | ||||
| msgstr "Verbindungsaufbau …" | ||||
|  | ||||
| @@ -1534,8 +1536,7 @@ msgstr "Gerät »%s« möchte mit diesem Rechner gekoppelt werden" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:366 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Please confirm whether the Passkey '%06d' matches the one on the device." | ||||
| msgid "Please confirm whether the PIN '%06d' matches the one on the device." | ||||
| msgstr "" | ||||
| "Bitte bestätigen Sie, ob die PIN »%06d« mit der des Gerätes übereinstimmt." | ||||
|  | ||||
| @@ -1561,11 +1562,11 @@ msgstr "Bitte geben Sie die auf dem Gerät angezeigte PIN ein." | ||||
| msgid "OK" | ||||
| msgstr "OK" | ||||
|  | ||||
| #: ../js/ui/status/keyboard.js:396 | ||||
| #: ../js/ui/status/keyboard.js:368 | ||||
| msgid "Show Keyboard Layout" | ||||
| msgstr "Tastaturbelegung zeigen" | ||||
|  | ||||
| #: ../js/ui/status/keyboard.js:401 | ||||
| #: ../js/ui/status/keyboard.js:373 | ||||
| msgid "Region & Language Settings" | ||||
| msgstr "Einstellungen für Region und Sprache" | ||||
|  | ||||
| @@ -1573,91 +1574,117 @@ msgstr "Einstellungen für Region und Sprache" | ||||
| msgid "Volume, network, battery" | ||||
| msgstr "Lautstärke, Netzwerk, Batterie" | ||||
|  | ||||
| #: ../js/ui/status/network.js:75 | ||||
| #: ../js/ui/status/network.js:104 | ||||
| msgid "<unknown>" | ||||
| msgstr "<Unbekannt>" | ||||
|  | ||||
| #: ../js/ui/status/network.js:127 | ||||
| msgid "Wi-Fi" | ||||
| msgstr "WLAN" | ||||
|  | ||||
| #. Translators: this indicates that wireless or wwan is disabled by hardware killswitch | ||||
| #: ../js/ui/status/network.js:164 | ||||
| #: ../js/ui/status/network.js:200 | ||||
| msgid "disabled" | ||||
| msgstr "Deaktiviert" | ||||
|  | ||||
| #. Translators: this is for network devices that are physically present but are not | ||||
| #. under NetworkManager's control (and thus cannot be used in the menu) | ||||
| #: ../js/ui/status/network.js:402 | ||||
| #: ../js/ui/status/network.js:458 | ||||
| msgid "unmanaged" | ||||
| msgstr "nicht verwaltet" | ||||
|  | ||||
| #. Translators: this is for network connections that require some kind of key or password | ||||
| #: ../js/ui/status/network.js:413 ../js/ui/status/network.js:1346 | ||||
| #: ../js/ui/status/network.js:469 ../js/ui/status/network.js:1549 | ||||
| msgid "authentication required" | ||||
| msgstr "Legitimierung erforderlich" | ||||
|  | ||||
| #. Translators: this is for devices that require some kind of firmware or kernel | ||||
| #. module, which is missing | ||||
| #: ../js/ui/status/network.js:423 | ||||
| #: ../js/ui/status/network.js:479 | ||||
| msgid "firmware missing" | ||||
| msgstr "Firmware fehlt" | ||||
|  | ||||
| #. Translators: this is for wired network devices that are physically disconnected | ||||
| #: ../js/ui/status/network.js:430 | ||||
| #: ../js/ui/status/network.js:486 | ||||
| msgid "cable unplugged" | ||||
| msgstr "Kabel nicht angeschlossen" | ||||
|  | ||||
| #. Translators: this is for a network device that cannot be activated (for example it | ||||
| #. is disabled by rfkill, or it has no coverage | ||||
| #: ../js/ui/status/network.js:435 | ||||
| #: ../js/ui/status/network.js:491 | ||||
| msgid "unavailable" | ||||
| msgstr "nicht verfügbar" | ||||
|  | ||||
| #: ../js/ui/status/network.js:437 ../js/ui/status/network.js:1348 | ||||
| #: ../js/ui/status/network.js:493 ../js/ui/status/network.js:1551 | ||||
| msgid "connection failed" | ||||
| msgstr "Verbindung gescheitert" | ||||
|  | ||||
| #: ../js/ui/status/network.js:490 ../js/ui/status/network.js:1236 | ||||
| #: ../js/ui/status/network.js:1424 | ||||
| #: ../js/ui/status/network.js:552 ../js/ui/status/network.js:1435 | ||||
| #: ../js/ui/status/network.js:1627 | ||||
| msgid "More…" | ||||
| msgstr "Mehr …" | ||||
|  | ||||
| #. 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:518 ../js/ui/status/network.js:1191 | ||||
| #: ../js/ui/status/network.js:588 ../js/ui/status/network.js:1365 | ||||
| msgid "Connected (private)" | ||||
| msgstr "Verbunden (privat)" | ||||
|  | ||||
| #: ../js/ui/status/network.js:597 | ||||
| #: ../js/ui/status/network.js:667 | ||||
| msgid "Wired" | ||||
| msgstr "Kabelgebunden" | ||||
|  | ||||
| #: ../js/ui/status/network.js:611 | ||||
| #: ../js/ui/status/network.js:668 | ||||
| msgid "Auto Ethernet" | ||||
| msgstr "Ethernet (automatisch)" | ||||
|  | ||||
| #: ../js/ui/status/network.js:695 | ||||
| msgid "Mobile broadband" | ||||
| msgstr "Mobiles Breitband" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1522 | ||||
| #: ../js/ui/status/network.js:728 | ||||
| msgid "Auto broadband" | ||||
| msgstr "Mobiles Breitband (automatisch)" | ||||
|  | ||||
| #: ../js/ui/status/network.js:731 | ||||
| msgid "Auto dial-up" | ||||
| msgstr "Einwählverbindung (automatisch)" | ||||
|  | ||||
| #. TRANSLATORS: this the automatic wireless connection name (including the network name) | ||||
| #: ../js/ui/status/network.js:861 ../js/ui/status/network.js:1382 | ||||
| #, c-format | ||||
| msgid "Auto %s" | ||||
| msgstr "%s (automatisch)" | ||||
|  | ||||
| #: ../js/ui/status/network.js:863 | ||||
| msgid "Auto bluetooth" | ||||
| msgstr "Bluetooth (automatisch)" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1384 | ||||
| msgid "Auto wireless" | ||||
| msgstr "Drahtlos (automatisch)" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1729 | ||||
| msgid "Enable networking" | ||||
| msgstr "Netzwerk aktivieren" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1583 | ||||
| #: ../js/ui/status/network.js:1771 | ||||
| msgid "Wi-Fi" | ||||
| msgstr "WLAN" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1790 | ||||
| msgid "Network Settings" | ||||
| msgstr "Netzwerkeinstellungen" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1600 | ||||
| #: ../js/ui/status/network.js:1807 | ||||
| msgid "Network Manager" | ||||
| msgstr "Netzwerk-Verwaltung" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1690 | ||||
| #: ../js/ui/status/network.js:1897 | ||||
| msgid "Connection failed" | ||||
| msgstr "Verbindung gescheitert" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1691 | ||||
| #: ../js/ui/status/network.js:1898 | ||||
| msgid "Activation of network connection failed" | ||||
| msgstr "Aktivierung der Netzwerkverbindung ist gescheitert" | ||||
|  | ||||
| #: ../js/ui/status/network.js:2047 | ||||
| #: ../js/ui/status/network.js:2276 | ||||
| msgid "Networking is disabled" | ||||
| msgstr "Netzwerk ist deaktiviert" | ||||
|  | ||||
| @@ -1771,11 +1798,11 @@ msgstr "Lautstärke" | ||||
| msgid "Microphone" | ||||
| msgstr "Mikrofon" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:120 | ||||
| #: ../js/ui/unlockDialog.js:123 | ||||
| msgid "Log in as another user" | ||||
| msgstr "Als anderer Benutzer anmelden" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:141 | ||||
| #: ../js/ui/unlockDialog.js:149 | ||||
| msgid "Unlock Window" | ||||
| msgstr "Fenster entsperren" | ||||
|  | ||||
| @@ -1901,37 +1928,37 @@ msgid_plural "%u Inputs" | ||||
| msgstr[0] "%u Eingang" | ||||
| msgstr[1] "%u Eingänge" | ||||
|  | ||||
| #: ../src/gvc/gvc-mixer-control.c:2373 | ||||
| #: ../src/gvc/gvc-mixer-control.c:2371 | ||||
| msgid "System Sounds" | ||||
| msgstr "Systemklänge" | ||||
|  | ||||
| #: ../src/main.c:372 | ||||
| #: ../src/main.c:347 | ||||
| msgid "Print version" | ||||
| msgstr "Version ausgeben" | ||||
|  | ||||
| #: ../src/main.c:378 | ||||
| #: ../src/main.c:353 | ||||
| msgid "Mode used by GDM for login screen" | ||||
| msgstr "Der durch GDM im Anmeldefenster verwendete Modus" | ||||
|  | ||||
| #: ../src/main.c:384 | ||||
| #: ../src/main.c:359 | ||||
| msgid "Use a specific mode, e.g. \"gdm\" for login screen" | ||||
| msgstr "" | ||||
| "Einen spezifischen Modus nutzen, wie z.B. »gdm« für den Anmeldebildschirm" | ||||
|  | ||||
| #: ../src/main.c:390 | ||||
| #: ../src/main.c:365 | ||||
| msgid "List possible modes" | ||||
| msgstr "Die möglichen Modi auflisten" | ||||
|  | ||||
| #: ../src/shell-app.c:626 | ||||
| #: ../src/shell-app.c:622 | ||||
| #, c-format | ||||
| msgid "Failed to launch '%s'" | ||||
| msgstr "»%s« konnte nicht gestartet werden" | ||||
|  | ||||
| #: ../src/shell-keyring-prompt.c:714 | ||||
| #: ../src/shell-keyring-prompt.c:708 | ||||
| msgid "Passwords do not match." | ||||
| msgstr "Passwörter stimmen nicht überein." | ||||
|  | ||||
| #: ../src/shell-keyring-prompt.c:722 | ||||
| #: ../src/shell-keyring-prompt.c:716 | ||||
| msgid "Password cannot be blank" | ||||
| msgstr "Das Passwort darf nicht leer sein" | ||||
|  | ||||
| @@ -1939,40 +1966,6 @@ msgstr "Das Passwort darf nicht leer sein" | ||||
| msgid "Authentication dialog was dismissed by the user" | ||||
| msgstr "Der Dialog zur Legitimierung wurde vom Benutzer geschlossen" | ||||
|  | ||||
| #~ msgid "Whether to collect stats about applications usage" | ||||
| #~ msgstr "" | ||||
| #~ "Legt fest, ob Statistiken über Anwendungsnutzung erfasst werden sollen" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "The shell normally monitors active applications in order to present the " | ||||
| #~ "most used ones (e.g. in launchers). While this data will be kept private, " | ||||
| #~ "you may want to disable this for privacy reasons. Please note that doing " | ||||
| #~ "so won't remove already saved data." | ||||
| #~ msgstr "" | ||||
| #~ "Die Shell überwacht normalerweise aktive Anwendungen, wobei die " | ||||
| #~ "meistgenutzten zuerst erfasst werden (z.B. in Anwendungsstartern). Zwar " | ||||
| #~ "werden diese Daten privat gespeichert, doch möglicherweise wollen Sie " | ||||
| #~ "dies deaktivieren, um Ihre Privatsphäre zu schützen. Bitte beachten Sie, " | ||||
| #~ "dass bereits gespeicherte Daten hiervon nicht beeinflusst werden." | ||||
|  | ||||
| #~ msgid "Auto Ethernet" | ||||
| #~ msgstr "Ethernet (automatisch)" | ||||
|  | ||||
| #~ msgid "Auto broadband" | ||||
| #~ msgstr "Mobiles Breitband (automatisch)" | ||||
|  | ||||
| #~ msgid "Auto dial-up" | ||||
| #~ msgstr "Einwählverbindung (automatisch)" | ||||
|  | ||||
| #~ msgid "Auto %s" | ||||
| #~ msgstr "%s (automatisch)" | ||||
|  | ||||
| #~ msgid "Auto bluetooth" | ||||
| #~ msgstr "Bluetooth (automatisch)" | ||||
|  | ||||
| #~ msgid "Auto wireless" | ||||
| #~ msgstr "Drahtlos (automatisch)" | ||||
|  | ||||
| #~ msgctxt "title" | ||||
| #~ msgid "Sign In" | ||||
| #~ msgstr "Anmelden" | ||||
|   | ||||
							
								
								
									
										239
									
								
								po/el.po
									
									
									
									
									
								
							
							
						
						
									
										239
									
								
								po/el.po
									
									
									
									
									
								
							| @@ -5,8 +5,8 @@ msgstr "" | ||||
| "Project-Id-Version: gnome-shell.po.master\n" | ||||
| "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" | ||||
| "shell&keywords=I18N+L10N&component=general\n" | ||||
| "POT-Creation-Date: 2013-04-19 02:48+0000\n" | ||||
| "PO-Revision-Date: 2013-04-25 08:11+0300\n" | ||||
| "POT-Creation-Date: 2013-03-02 23:02+0000\n" | ||||
| "PO-Revision-Date: 2013-03-03 13:22+0300\n" | ||||
| "Last-Translator: Dimitris Spingos (Δημήτρης Σπίγγος) <dmtrs32@gmail.com>\n" | ||||
| "Language-Team: team@gnome.gr\n" | ||||
| "Language: el\n" | ||||
| @@ -40,14 +40,10 @@ msgid "Focus the active notification" | ||||
| msgstr "Εστίαση στην ενεργή ειδοποίηση" | ||||
|  | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:4 | ||||
| msgid "Show the overview" | ||||
| msgstr "Εμφάνιση της επισκόπησης" | ||||
|  | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:5 | ||||
| msgid "Show all applications" | ||||
| msgstr "Προβολή όλων των εφαρμογών" | ||||
|  | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:6 | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:5 | ||||
| msgid "Open the application menu" | ||||
| msgstr "Άνοιγμα του μενού εφαρμογών" | ||||
|  | ||||
| @@ -227,55 +223,45 @@ msgstr "" | ||||
| "επισκόπησης ενεργειών." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:25 | ||||
| #| msgid "Keybinding to open the \"Show Applications\" view" | ||||
| msgid "Keybinding to open the overview" | ||||
| msgstr "Συνδυασμός πλήκτρων για το άνοιγμα της επισκόπησης" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:26 | ||||
| #| msgid "Keybinding to open the \"Show Applications\" view" | ||||
| msgid "Keybinding to open the Activities Overview." | ||||
| msgstr "Συνδυασμός πλήκτρων για το άνοιγμα της προβολής ενέργειες." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:27 | ||||
| msgid "Keybinding to toggle the visibility of the message tray" | ||||
| msgstr "Συνδυασμός πλήκτρων για την ορατότητα της περιοχής ειδοποιήσεων" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:28 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:26 | ||||
| msgid "Keybinding to toggle the visibility of the message tray." | ||||
| msgstr "Συνδυασμός πλήκτρων για την ορατότητα της περιοχής ειδοποιήσεων." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:29 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:27 | ||||
| msgid "Keybinding to focus the active notification" | ||||
| msgstr "Ο συνδυασμός πλήκτρων για εστίαση της ενεργής ειδοποίησης" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:30 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:28 | ||||
| msgid "Keybinding to focus the active notification." | ||||
| msgstr "Ο συνδυασμός πλήκτρων για εστίαση της ενεργής ειδοποίησης." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:31 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:29 | ||||
| msgid "Keybinding to toggle the screen recorder" | ||||
| msgstr "Συνδυασμός πλήκτρων για την εναλλαγή της μαγνητοσκόπησης οθόνης" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:32 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:30 | ||||
| msgid "Keybinding to start/stop the builtin screen recorder." | ||||
| msgstr "" | ||||
| "Συνδυασμός πλήκτρων για το άνοιγμα/κλείσιμο της ενσωματωμένης " | ||||
| "μαγνητοσκόπησης οθόνης." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:33 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:31 | ||||
| msgid "Which keyboard to use" | ||||
| msgstr "Ποιο πληκτρολόγιο θα χρησιμοποιηθεί" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:34 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:32 | ||||
| msgid "The type of keyboard to use." | ||||
| msgstr "Ο τύπος του πληκτρολογίου που θα χρησιμοποιηθεί." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:35 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:33 | ||||
| msgid "Framerate used for recording screencasts." | ||||
| msgstr "" | ||||
| "Ο ρυθμός καρέ που θα χρησιμοποιηθεί για την καταγραφή του βίντεο οθόνης." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:36 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:34 | ||||
| msgid "" | ||||
| "The framerate of the resulting screencast recordered by GNOME Shell's " | ||||
| "screencast recorder in frames-per-second." | ||||
| @@ -283,13 +269,13 @@ msgstr "" | ||||
| "Ο ρυθμός καρέ του στιγμιότυπου που παράγεται από τον εγγραφέα βίντεο οθόνης " | ||||
| "του GNOME Shell σε καρέ ανά δευτερόλεπτο." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:37 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:35 | ||||
| msgid "The gstreamer pipeline used to encode the screencast" | ||||
| msgstr "" | ||||
| "Ο δίαυλος του gstreamer που χρησιμοποιήθηκε για την κωδικοποίηση του βίντεο " | ||||
| "οθόνης" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:39 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:37 | ||||
| #, no-c-format | ||||
| msgid "" | ||||
| "Sets the GStreamer pipeline used to encode recordings. It follows the syntax " | ||||
| @@ -317,12 +303,12 @@ msgstr "" | ||||
| "χρησιμοποιείται ως παράδειγμα για το πιθανό βέλτιστο αριθμό πυρήνων του " | ||||
| "συστήματος." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:40 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:38 | ||||
| msgid "File extension used for storing the screencast" | ||||
| msgstr "" | ||||
| "Επέκταση αρχείου που θα χρησιμοποιηθεί για την αποθήκευση του βίντεο οθόνης" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:41 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:39 | ||||
| msgid "" | ||||
| "The filename for recorded screencasts will be a unique filename based on the " | ||||
| "current date, and use this extension. It should be changed when recording to " | ||||
| @@ -332,11 +318,11 @@ msgstr "" | ||||
| "βασισμένο στην τρέχουσα ημερομηνία και θα χρησιμοποιεί αυτή την επέκταση. Θα " | ||||
| "πρέπει να αλλάζει όταν γίνεται εγγραφή σε διαφορετικό πρότυπο περιέκτη." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:42 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:40 | ||||
| msgid "The application icon mode." | ||||
| msgstr "Η κατάσταση εικονιδίου εφαρμογής." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:43 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:41 | ||||
| msgid "" | ||||
| "Configures how the windows are shown in the switcher. Valid possibilities " | ||||
| "are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-" | ||||
| @@ -347,22 +333,22 @@ msgstr "" | ||||
| "παραθύρου), 'app-icon-only' (εμφανίζει μόνο το εικονίδιο της εφαρμογής) ή " | ||||
| "'both' - και τα δύο." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:44 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:42 | ||||
| msgid "Attach modal dialog to the parent window" | ||||
| msgstr "Προσάρτηση αναγκαστικού διαλόγου στο γονικό παράθυρο" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:45 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:43 | ||||
| msgid "" | ||||
| "This key overrides the key in org.gnome.mutter when running GNOME Shell." | ||||
| msgstr "" | ||||
| "Αυτό το κλειδί υπερισχύει του κλειδιού στο org.gnome.mutter όταν εκτελείται " | ||||
| "το κέλυφος GNOME." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:46 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:44 | ||||
| msgid "Arrangement of buttons on the titlebar" | ||||
| msgstr "Διάταξη των κουμπιών στη γραμμή τίτλου" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:47 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:45 | ||||
| msgid "" | ||||
| "This key overrides the key in org.gnome.desktop.wm.preferences when running " | ||||
| "GNOME Shell." | ||||
| @@ -370,17 +356,17 @@ msgstr "" | ||||
| "Αυτό το κλειδί υπερισχύει του κλειδιού στο org.gnome.desktop.wm.preferences " | ||||
| "όταν εκτελείται το κέλυφος GNOME." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:48 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:46 | ||||
| msgid "Enable edge tiling when dropping windows on screen edges" | ||||
| msgstr "" | ||||
| "Ενεργοποίηση της παράθεσης άκρων όταν αποθέτετε παράθυρα στις άκρες της " | ||||
| "οθόνης" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:49 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:47 | ||||
| msgid "Workspaces are managed dynamically" | ||||
| msgstr "Οι χώροι εργασίας διαχειρίζονται δυναμικά" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:50 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:48 | ||||
| msgid "Workspaces only on primary monitor" | ||||
| msgstr "Χώροι εργασίας μόνο στην κύρια οθόνη" | ||||
|  | ||||
| @@ -402,42 +388,43 @@ msgstr "" | ||||
| "πολλαπλών επιλογών." | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:405 | ||||
| #| msgid "Session..." | ||||
| msgid "Session…" | ||||
| msgstr "Συνεδρία…" | ||||
|  | ||||
| #. 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:630 | ||||
| #: ../js/gdm/loginDialog.js:629 | ||||
| msgid "Not listed?" | ||||
| msgstr "Δεν είστε στη λίστα;" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:787 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:376 | ||||
| #: ../js/gdm/loginDialog.js:783 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 | ||||
| #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:100 | ||||
| #: ../js/ui/userMenu.js:938 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:126 | ||||
| #: ../js/ui/userMenu.js:932 | ||||
| msgid "Cancel" | ||||
| msgstr "Ακύρωση" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:803 | ||||
| #: ../js/gdm/loginDialog.js:799 | ||||
| msgctxt "button" | ||||
| msgid "Sign In" | ||||
| msgstr "Σύνδεση" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:803 | ||||
| #: ../js/gdm/loginDialog.js:799 | ||||
| msgid "Next" | ||||
| msgstr "Επόμενο" | ||||
|  | ||||
| #. 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:918 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/gdm/loginDialog.js:904 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/ui/components/networkAgent.js:278 | ||||
| msgid "Username: " | ||||
| msgstr "Όνομα χρήστη: " | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:1174 | ||||
| #: ../js/gdm/loginDialog.js:1157 | ||||
| msgid "Login Window" | ||||
| msgstr "Παράθυρο σύνδεσης" | ||||
|  | ||||
| @@ -446,8 +433,8 @@ msgstr "Παράθυρο σύνδεσης" | ||||
| msgid "Power" | ||||
| msgstr "Ενέργεια" | ||||
|  | ||||
| #: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:696 ../js/ui/userMenu.js:700 | ||||
| #: ../js/ui/userMenu.js:816 | ||||
| #: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:694 ../js/ui/userMenu.js:698 | ||||
| #: ../js/ui/userMenu.js:814 | ||||
| msgid "Suspend" | ||||
| msgstr "Αναστολή" | ||||
|  | ||||
| @@ -455,58 +442,58 @@ msgstr "Αναστολή" | ||||
| msgid "Restart" | ||||
| msgstr "Επανεκκίνηση" | ||||
|  | ||||
| #: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:698 | ||||
| #: ../js/ui/userMenu.js:700 ../js/ui/userMenu.js:815 ../js/ui/userMenu.js:942 | ||||
| #: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:696 | ||||
| #: ../js/ui/userMenu.js:698 ../js/ui/userMenu.js:813 ../js/ui/userMenu.js:936 | ||||
| msgid "Power Off" | ||||
| msgstr "Απενεργοποίηση" | ||||
|  | ||||
| #: ../js/gdm/util.js:249 | ||||
| #: ../js/gdm/util.js:182 | ||||
| msgid "Authentication error" | ||||
| msgstr "Σφάλμα πιστοποίησης" | ||||
|  | ||||
| #. Translators: this message is shown below the password entry field | ||||
| #. to indicate the user can swipe their finger instead | ||||
| #: ../js/gdm/util.js:366 | ||||
| #: ../js/gdm/util.js:299 | ||||
| msgid "(or swipe finger)" | ||||
| msgstr "(ή περάστε το δάκτυλο σας)" | ||||
|  | ||||
| #: ../js/gdm/util.js:391 | ||||
| #: ../js/gdm/util.js:324 | ||||
| #, c-format | ||||
| msgid "(e.g., user or %s)" | ||||
| msgstr "(π.χ χρήστης ή %s)" | ||||
|  | ||||
| #: ../js/misc/util.js:97 | ||||
| #: ../js/misc/util.js:94 | ||||
| msgid "Command not found" | ||||
| msgstr "Δε βρέθηκε η εντολή" | ||||
|  | ||||
| #. Replace "Error invoking GLib.shell_parse_argv: " with | ||||
| #. something nicer | ||||
| #: ../js/misc/util.js:130 | ||||
| #: ../js/misc/util.js:127 | ||||
| msgid "Could not parse command:" | ||||
| msgstr "Δεν ήταν δυνατό να επεξεργαστεί η εντολή:" | ||||
|  | ||||
| #: ../js/misc/util.js:138 | ||||
| #: ../js/misc/util.js:135 | ||||
| #, c-format | ||||
| msgid "Execution of '%s' failed:" | ||||
| msgstr "Η εκτέλεση του '%s' απέτυχε:" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:349 | ||||
| #: ../js/ui/appDisplay.js:348 | ||||
| msgid "Frequent" | ||||
| msgstr "Συχνό" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:356 | ||||
| #: ../js/ui/appDisplay.js:355 | ||||
| msgid "All" | ||||
| msgstr "Όλα" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:914 | ||||
| #: ../js/ui/appDisplay.js:913 | ||||
| msgid "New Window" | ||||
| msgstr "Νέο παράθυρο" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:917 ../js/ui/dash.js:284 | ||||
| #: ../js/ui/appDisplay.js:916 ../js/ui/dash.js:284 | ||||
| msgid "Remove from Favorites" | ||||
| msgstr "Αφαίρεση από τα αγαπημένα" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:918 | ||||
| #: ../js/ui/appDisplay.js:917 | ||||
| msgid "Add to Favorites" | ||||
| msgstr "Προσθήκη στα αγαπημένα" | ||||
|  | ||||
| @@ -520,7 +507,7 @@ msgstr "Tο %s προστέθηκε στα αγαπημένα σας." | ||||
| msgid "%s has been removed from your favorites." | ||||
| msgstr "Tο %s αφαιρέθηκε από τα αγαπημένα σας." | ||||
|  | ||||
| #: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:789 | ||||
| #: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:787 | ||||
| msgid "Settings" | ||||
| msgstr "Ρυθμίσεις" | ||||
|  | ||||
| @@ -543,7 +530,7 @@ msgctxt "event list time" | ||||
| msgid "%H\\u2236%M" | ||||
| msgstr "%Ω\\u2236%Λ" | ||||
|  | ||||
| #. Translators: Shown in calendar event list, if 12h format, | ||||
| #. Transators: Shown in calendar event list, if 12h format, | ||||
| #. \u2236 is a ratio character, similar to : and \u2009 is | ||||
| #. a thin space | ||||
| #: ../js/ui/calendar.js:77 | ||||
| @@ -645,35 +632,35 @@ msgid "S" | ||||
| msgstr "Σ" | ||||
|  | ||||
| #. Translators: Text to show if there are no events | ||||
| #: ../js/ui/calendar.js:720 | ||||
| #: ../js/ui/calendar.js:692 | ||||
| msgid "Nothing Scheduled" | ||||
| msgstr "Τίποτα προγραμματισμένο" | ||||
|  | ||||
| #. Translators: Shown on calendar heading when selected day occurs on current year | ||||
| #: ../js/ui/calendar.js:736 | ||||
| #: ../js/ui/calendar.js:708 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%A, %B %d" | ||||
|  | ||||
| #. Translators: Shown on calendar heading when selected day occurs on different year | ||||
| #: ../js/ui/calendar.js:739 | ||||
| #: ../js/ui/calendar.js:711 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d, %Y" | ||||
| msgstr "%A, %B %d, %Y" | ||||
|  | ||||
| #: ../js/ui/calendar.js:749 | ||||
| #: ../js/ui/calendar.js:721 | ||||
| msgid "Today" | ||||
| msgstr "Σήμερα" | ||||
|  | ||||
| #: ../js/ui/calendar.js:753 | ||||
| #: ../js/ui/calendar.js:725 | ||||
| msgid "Tomorrow" | ||||
| msgstr "Αύριο" | ||||
|  | ||||
| #: ../js/ui/calendar.js:764 | ||||
| #: ../js/ui/calendar.js:736 | ||||
| msgid "This week" | ||||
| msgstr "Αυτή η εβδομάδα" | ||||
|  | ||||
| #: ../js/ui/calendar.js:772 | ||||
| #: ../js/ui/calendar.js:744 | ||||
| msgid "Next week" | ||||
| msgstr "Επόμενη εβδομάδα" | ||||
|  | ||||
| @@ -689,12 +676,12 @@ msgstr "Αποσυνδέθηκε εξωτερικός δίσκος" | ||||
| msgid "Removable Devices" | ||||
| msgstr "Αφαιρούμενες συσκευές" | ||||
|  | ||||
| #: ../js/ui/components/autorunManager.js:594 | ||||
| #: ../js/ui/components/autorunManager.js:593 | ||||
| #, c-format | ||||
| msgid "Open with %s" | ||||
| msgstr "Άνοιγμα με %s" | ||||
|  | ||||
| #: ../js/ui/components/autorunManager.js:620 | ||||
| #: ../js/ui/components/autorunManager.js:619 | ||||
| msgid "Eject" | ||||
| msgstr "Εξαγωγή" | ||||
|  | ||||
| @@ -803,7 +790,7 @@ msgid "Sorry, that didn't work. Please try again." | ||||
| msgstr "Συγνώμη, αυτό δεν λειτούργησε. Παρακαλώ προσπαθήστε ξανά." | ||||
|  | ||||
| #. Translators: this is a filename used for screencast recording | ||||
| #: ../js/ui/components/recorder.js:47 | ||||
| #: ../js/ui/components/recorder.js:48 | ||||
| #, no-c-format | ||||
| msgid "Screencast from %d %t" | ||||
| msgstr "Βίντεο οθόνης από %d %t" | ||||
| @@ -1050,7 +1037,7 @@ msgstr "Προβολή λογαριασμού" | ||||
| msgid "Unknown reason" | ||||
| msgstr "Άγνωστος λόγος" | ||||
|  | ||||
| #: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:96 | ||||
| #: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:97 | ||||
| msgid "Windows" | ||||
| msgstr "Παράθυρα" | ||||
|  | ||||
| @@ -1079,7 +1066,7 @@ msgstr "Ρυθμίσεις ημερομηνίας & ώρας" | ||||
| #. 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:215 | ||||
| #: ../js/ui/dateMenu.js:205 | ||||
| msgid "%A %B %e, %Y" | ||||
| msgstr "%A %B %e, %Y" | ||||
|  | ||||
| @@ -1248,6 +1235,7 @@ msgid "Remove" | ||||
| msgstr "Αφαίρεση" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1501 | ||||
| #| msgid "No Messages" | ||||
| msgid "Clear Messages" | ||||
| msgstr "Καθαρισμός μηνυμάτων" | ||||
|  | ||||
| @@ -1255,15 +1243,15 @@ msgstr "Καθαρισμός μηνυμάτων" | ||||
| msgid "Notification Settings" | ||||
| msgstr "Ρυθμίσεις ειδοποιήσεων" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1709 | ||||
| #: ../js/ui/messageTray.js:1707 | ||||
| msgid "No Messages" | ||||
| msgstr "Κανένα μήνυμα" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1785 | ||||
| #: ../js/ui/messageTray.js:1787 | ||||
| msgid "Message Tray" | ||||
| msgstr "Περιοχή ειδοποιήσεων" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:2813 | ||||
| #: ../js/ui/messageTray.js:2864 | ||||
| msgid "System Information" | ||||
| msgstr "Πληροφορίες συστήματος" | ||||
|  | ||||
| @@ -1272,14 +1260,14 @@ msgctxt "program" | ||||
| msgid "Unknown" | ||||
| msgstr "Άγνωστο" | ||||
|  | ||||
| #: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149 | ||||
| #: ../js/ui/overviewControls.js:460 ../js/ui/screenShield.js:153 | ||||
| #, c-format | ||||
| msgid "%d new message" | ||||
| msgid_plural "%d new messages" | ||||
| msgstr[0] "%d νέο μήνυμα" | ||||
| msgstr[1] "%d νέα μηνύματα" | ||||
|  | ||||
| #: ../js/ui/overview.js:84 | ||||
| #: ../js/ui/overview.js:82 | ||||
| msgid "Undo" | ||||
| msgstr "Αναίρεση" | ||||
|  | ||||
| @@ -1291,21 +1279,22 @@ msgstr "Επισκόπηση" | ||||
| #. in the search entry when no search is | ||||
| #. active; it should not exceed ~30 | ||||
| #. characters. | ||||
| #: ../js/ui/overview.js:271 | ||||
| #: ../js/ui/overview.js:284 | ||||
| #| msgid "Type to search..." | ||||
| msgid "Type to search…" | ||||
| msgstr "Πληκτρολογήστε για αναζήτηση…" | ||||
|  | ||||
| #: ../js/ui/panel.js:633 | ||||
| #: ../js/ui/panel.js:613 | ||||
| msgid "Quit" | ||||
| msgstr "Έξοδος" | ||||
|  | ||||
| #. Translators: If there is no suitable word for "Activities" | ||||
| #. in your language, you can use the word for "Overview". | ||||
| #: ../js/ui/panel.js:657 | ||||
| #: ../js/ui/panel.js:642 | ||||
| msgid "Activities" | ||||
| msgstr "Δραστηριότητες" | ||||
|  | ||||
| #: ../js/ui/panel.js:954 | ||||
| #: ../js/ui/panel.js:983 | ||||
| msgid "Top Bar" | ||||
| msgstr "Πάνω μπάρα" | ||||
|  | ||||
| @@ -1318,32 +1307,32 @@ msgstr "Πάνω μπάρα" | ||||
| msgid "toggle-switch-us" | ||||
| msgstr "toggle-switch-intl" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:74 | ||||
| #: ../js/ui/runDialog.js:205 | ||||
| msgid "Enter a Command" | ||||
| msgstr "Εισαγωγή εντολής" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:110 | ||||
| #: ../js/ui/runDialog.js:241 | ||||
| msgid "Close" | ||||
| msgstr "Κλείσιμο" | ||||
|  | ||||
| #. Translators: This is a time format for a date in | ||||
| #. long format | ||||
| #: ../js/ui/screenShield.js:86 | ||||
| #: ../js/ui/screenShield.js:90 | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%A, %B %d" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:151 | ||||
| #: ../js/ui/screenShield.js:155 | ||||
| #, c-format | ||||
| msgid "%d new notification" | ||||
| msgid_plural "%d new notifications" | ||||
| msgstr[0] "%d νέα ειδοποίηση" | ||||
| msgstr[1] "%d νέες ειδοποιήσεις" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:438 ../js/ui/userMenu.js:807 | ||||
| #: ../js/ui/screenShield.js:442 ../js/ui/userMenu.js:805 | ||||
| msgid "Lock" | ||||
| msgstr "Κλείδωμα" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:641 | ||||
| #: ../js/ui/screenShield.js:639 | ||||
| msgid "GNOME needs to lock the screen" | ||||
| msgstr "Το GNOME χρειάζεται να κλειδώσει την οθόνη" | ||||
|  | ||||
| @@ -1354,19 +1343,21 @@ msgstr "Το GNOME χρειάζεται να κλειδώσει την οθόν | ||||
| #. | ||||
| #. XXX: another option is to kick the user into the gdm login | ||||
| #. screen, where we're not affected by grabs | ||||
| #: ../js/ui/screenShield.js:762 ../js/ui/screenShield.js:1198 | ||||
| #: ../js/ui/screenShield.js:758 ../js/ui/screenShield.js:1169 | ||||
| #| msgid "Unable to connect to %s" | ||||
| msgid "Unable to lock" | ||||
| msgstr "Αδυναμία κλειδώματος" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:763 ../js/ui/screenShield.js:1199 | ||||
| #: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1170 | ||||
| msgid "Lock was blocked by an application" | ||||
| msgstr "Το κλείδωμα εμποδίστηκε από μια εφαρμογή" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:453 | ||||
| #: ../js/ui/searchDisplay.js:431 | ||||
| #| msgid "Searching..." | ||||
| msgid "Searching…" | ||||
| msgstr "Αναζήτηση…" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:497 | ||||
| #: ../js/ui/searchDisplay.js:475 | ||||
| msgid "No results." | ||||
| msgstr "Δε βρέθηκαν αποτελέσματα." | ||||
|  | ||||
| @@ -1378,11 +1369,11 @@ msgstr "Αντιγραφή" | ||||
| msgid "Paste" | ||||
| msgstr "Επικόλληση" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:101 | ||||
| #: ../js/ui/shellEntry.js:105 | ||||
| msgid "Show Text" | ||||
| msgstr "Εμφάνιση κειμένου" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:103 | ||||
| #: ../js/ui/shellEntry.js:107 | ||||
| msgid "Hide Text" | ||||
| msgstr "Απόκρυψη κειμένου" | ||||
|  | ||||
| @@ -1394,7 +1385,7 @@ msgstr "Κωδικός" | ||||
| msgid "Remember Password" | ||||
| msgstr "Απομνημόνευση κωδικού" | ||||
|  | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:114 | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:140 | ||||
| msgid "Unlock" | ||||
| msgstr "Ξεκλείδωμα" | ||||
|  | ||||
| @@ -1458,10 +1449,12 @@ msgid "Visibility" | ||||
| msgstr "Ορατότητα" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:59 | ||||
| #| msgid "Send Files to Device..." | ||||
| msgid "Send Files to Device…" | ||||
| msgstr "Αποστολή αρχείων σε συσκευή…" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:60 | ||||
| #| msgid "Set Up a New Device..." | ||||
| msgid "Set Up a New Device…" | ||||
| msgstr "Ρύθμιση νέας συσκευής…" | ||||
|  | ||||
| @@ -1488,6 +1481,7 @@ msgid "connecting..." | ||||
| msgstr "σύνδεση..." | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:239 | ||||
| #| msgid "Send Files..." | ||||
| msgid "Send Files…" | ||||
| msgstr "Αποστολή αρχείων…" | ||||
|  | ||||
| @@ -1700,6 +1694,7 @@ msgstr "Ρυθμίσεις τροφοδοσίας" | ||||
| #. 0 is reported when UPower does not have enough data | ||||
| #. to estimate battery life | ||||
| #: ../js/ui/status/power.js:99 | ||||
| #| msgid "Estimating..." | ||||
| msgid "Estimating…" | ||||
| msgstr "Υπολογισμός…" | ||||
|  | ||||
| @@ -1799,59 +1794,59 @@ msgstr "Ένταση ήχου" | ||||
| msgid "Microphone" | ||||
| msgstr "Μικρόφωνο" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:125 | ||||
| #: ../js/ui/unlockDialog.js:151 | ||||
| msgid "Log in as another user" | ||||
| msgstr "Είσοδος ως άλλος χρήστης" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:146 | ||||
| #: ../js/ui/unlockDialog.js:177 | ||||
| msgid "Unlock Window" | ||||
| msgstr "Ξεκλείδωμα παραθύρου" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:193 | ||||
| #: ../js/ui/userMenu.js:192 | ||||
| msgid "Available" | ||||
| msgstr "Διαθέσιμος-η" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:196 | ||||
| #: ../js/ui/userMenu.js:195 | ||||
| msgid "Busy" | ||||
| msgstr "Απασχολημένος-η" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:199 | ||||
| #: ../js/ui/userMenu.js:198 | ||||
| msgid "Invisible" | ||||
| msgstr "Αόρατος-η" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:202 | ||||
| #: ../js/ui/userMenu.js:201 | ||||
| msgid "Away" | ||||
| msgstr "Απουσιάζει" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:205 | ||||
| #: ../js/ui/userMenu.js:204 | ||||
| msgid "Idle" | ||||
| msgstr "Αδρανής" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:208 | ||||
| #: ../js/ui/userMenu.js:207 | ||||
| msgid "Offline" | ||||
| msgstr "Εκτός σύνδεσης" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:781 | ||||
| #: ../js/ui/userMenu.js:779 | ||||
| msgid "Notifications" | ||||
| msgstr "Ειδοποιήσεις" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:797 | ||||
| #: ../js/ui/userMenu.js:795 | ||||
| msgid "Switch User" | ||||
| msgstr "Αλλαγή χρήστη" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:802 | ||||
| #: ../js/ui/userMenu.js:800 | ||||
| msgid "Log Out" | ||||
| msgstr "Αποσύνδεση" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:822 | ||||
| #: ../js/ui/userMenu.js:820 | ||||
| msgid "Install Updates & Restart" | ||||
| msgstr "Εγκατάσταση ενημερώσεων & επανεκκίνηση" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:840 | ||||
| #: ../js/ui/userMenu.js:838 | ||||
| msgid "Your chat status will be set to busy" | ||||
| msgstr "Η κατάσταση συνομιλίας σας θα ορισθεί σε απασχολημένος" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:841 | ||||
| #: ../js/ui/userMenu.js:839 | ||||
| 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." | ||||
| @@ -1860,36 +1855,34 @@ msgstr "" | ||||
| "κατάσταση σας έχει ορισθεί έτσι ώστε να γίνεται γνωστό ότι πιθανόν να μην " | ||||
| "δείτε τα μηνύματα τους." | ||||
|  | ||||
| #: ../js/ui/userMenu.js:888 | ||||
| #: ../js/ui/userMenu.js:885 | ||||
| msgid "Other users are logged in." | ||||
| msgstr "Και άλλοι χρήστες είναι συνδεμένοι." | ||||
|  | ||||
| #: ../js/ui/userMenu.js:893 | ||||
| #: ../js/ui/userMenu.js:890 | ||||
| msgid "Shutting down might cause them to lose unsaved work." | ||||
| msgstr "" | ||||
| "Κλείνοντας μπορεί να τους προκαλέσετε την απώλεια αναποθήκευτης εργασίας." | ||||
|  | ||||
| #. Translators: Remote here refers to a remote session, like a ssh login | ||||
| #: ../js/ui/userMenu.js:921 | ||||
| #: ../js/ui/userMenu.js:916 | ||||
| #, c-format | ||||
| msgid "%s (remote)" | ||||
| msgstr "%s (απομακρυσμένο)" | ||||
|  | ||||
| #. Translators: Console here refers to a tty like a VT console | ||||
| #: ../js/ui/userMenu.js:924 | ||||
| #: ../js/ui/userMenu.js:918 | ||||
| #, c-format | ||||
| msgid "%s (console)" | ||||
| msgstr "%s (κονσόλα)" | ||||
|  | ||||
| #: ../js/ui/viewSelector.js:100 | ||||
| #: ../js/ui/viewSelector.js:101 | ||||
| msgid "Applications" | ||||
| msgstr "Εφαρμογές" | ||||
|  | ||||
| #: ../js/ui/viewSelector.js:104 | ||||
| #: ../js/ui/viewSelector.js:105 | ||||
| msgid "Search" | ||||
| msgstr "Αναζήτηση" | ||||
|  | ||||
| #: ../js/ui/wanda.js:77 | ||||
| #: ../js/ui/wanda.js:92 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Sorry, no wisdom for you today:\n" | ||||
| @@ -1898,7 +1891,7 @@ msgstr "" | ||||
| "Συγγνώμη, κανένα απόφθεγμα για εσάς σήμερα:\n" | ||||
| "%s" | ||||
|  | ||||
| #: ../js/ui/wanda.js:81 | ||||
| #: ../js/ui/wanda.js:96 | ||||
| #, c-format | ||||
| msgid "%s the Oracle says" | ||||
| msgstr "%s ο Προφήτης λέει" | ||||
|   | ||||
							
								
								
									
										6
									
								
								po/lt.po
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								po/lt.po
									
									
									
									
									
								
							| @@ -461,7 +461,7 @@ msgstr "Nepavyko įvykdyti „%s“:" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:349 | ||||
| msgid "Frequent" | ||||
| msgstr "Dažnai naudojamos" | ||||
| msgstr "Dažniausios" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:356 | ||||
| msgid "All" | ||||
| @@ -1262,7 +1262,7 @@ msgstr "Apžvalga" | ||||
| #. characters. | ||||
| #: ../js/ui/overview.js:271 | ||||
| msgid "Type to search…" | ||||
| msgstr "Rašykite, ko ieškote…" | ||||
| msgstr "Rašykite ko ieškote…" | ||||
|  | ||||
| #: ../js/ui/panel.js:612 | ||||
| msgid "Quit" | ||||
| @@ -1299,7 +1299,7 @@ msgstr "Užverti" | ||||
| #. long format | ||||
| #: ../js/ui/screenShield.js:86 | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%A, %B %d d." | ||||
| msgstr "%A, %B %d" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:151 | ||||
| #, c-format | ||||
|   | ||||
							
								
								
									
										320
									
								
								po/ml.po
									
									
									
									
									
								
							
							
						
						
									
										320
									
								
								po/ml.po
									
									
									
									
									
								
							| @@ -10,9 +10,9 @@ msgstr "" | ||||
| "Project-Id-Version: gnome-shell master\n" | ||||
| "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" | ||||
| "shell&keywords=I18N+L10N&component=general\n" | ||||
| "POT-Creation-Date: 2013-04-24 18:23+0000\n" | ||||
| "PO-Revision-Date: 2013-04-25 00:32+0530\n" | ||||
| "Last-Translator: Balasankar C <c.balasankar@gmail.com>\n" | ||||
| "POT-Creation-Date: 2013-03-23 11:49+0000\n" | ||||
| "PO-Revision-Date: 2013-03-25 14:57+0530\n" | ||||
| "Last-Translator: Ani Peter <peter.ani@gmail.com>\n" | ||||
| "Language-Team: American English <kde-i18n-doc@kde.org>\n" | ||||
| "Language: ml\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| @@ -44,14 +44,10 @@ msgid "Focus the active notification" | ||||
| msgstr "സജീവമായ അറിയിപ്പിനെ കേന്ദ്രീകരിക്കുക" | ||||
|  | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:4 | ||||
| msgid "Show the overview" | ||||
| msgstr "പൊതുവായ അവലോകനം കാണിക്കുക" | ||||
|  | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:5 | ||||
| msgid "Show all applications" | ||||
| msgstr "എല്ലാ പ്രയോഗങ്ങളും കാണിയ്ക്കുക" | ||||
|  | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:6 | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:5 | ||||
| msgid "Open the application menu" | ||||
| msgstr "പ്രയോഗത്തിന്റെ മെനു തുറക്കുക" | ||||
|  | ||||
| @@ -75,7 +71,8 @@ msgstr "ഗ്നോം ഷെല് എക്സ്റ്റെന്ഷ | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:1 | ||||
| msgid "Enable internal tools useful for developers and testers from Alt-F2" | ||||
| msgstr "" | ||||
| "Alt-F2-ല് ഡവലപ്പര്മാര്ക്കും ടെസ്റ്റേര്സിനും പ്രയോജനകരമായ ആന്തരിക പ്രയോഗങ്ങള് പ്രവര്ത്തന " | ||||
| "Alt-F2-ല് ഡവലപ്പര്മാര്ക്കും ടെസ്റ്റേര്സിനും പ്രയോജനകരമായ ആന്തരിക " | ||||
| "പ്രയോഗങ്ങള് പ്രവര്ത്തന " | ||||
| "സജ്ജമാക്കുന്നു" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:2 | ||||
| @@ -83,7 +80,8 @@ msgid "" | ||||
| "Allows access to internal debugging and monitoring tools using the Alt-F2 " | ||||
| "dialog." | ||||
| msgstr "" | ||||
| "Alt-F2 ഡയലോഗ് ഉപയോഗിച്ചു് ആന്തരിക ഡീബഗ്ഗിലേക്കും നീരീക്ഷണ പ്രയോഗങ്ങളിലേക്കും പ്രവേശനം " | ||||
| "Alt-F2 ഡയലോഗ് ഉപയോഗിച്ചു് ആന്തരിക ഡീബഗ്ഗിലേക്കും നീരീക്ഷണ പ്രയോഗങ്ങളിലേക്കും " | ||||
| "പ്രവേശനം " | ||||
| "അനുവദിയ്ക്കുക." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:3 | ||||
| @@ -97,14 +95,19 @@ msgid "" | ||||
| "list. You can also manipulate this list with the EnableExtension and " | ||||
| "DisableExtension DBus methods on org.gnome.Shell." | ||||
| msgstr "" | ||||
| "ഗ്നോം ഷെല് എക്സ്റ്റെന്ഷനുകള്ക്കു് ഒരു യുയുഐഡി വിശേഷതയുണ്ടു്; ലഭ്യമാക്കേണ്ട എക്സ്റ്റെന്ഷനുകള് ഈ കീ പട്ടിക " | ||||
| "ലഭ്യമാക്കുന്നു. ലഭ്യമാക്കേണ്ട ഏതു് എക്സ്റ്റെന്ഷനും ഈ പട്ടികയിലുണ്ടാവണം. org.gnome.Shell-ല് " | ||||
| "നിങ്ങള്ക്കു് EnableExtension, DisableExtension എന്നീ ഡീബസ് രീതികളിലൂടെ ഈ പട്ടിക " | ||||
| "ഗ്നോം ഷെല് എക്സ്റ്റെന്ഷനുകള്ക്കു് ഒരു യുയുഐഡി വിശേഷതയുണ്ടു്; ലഭ്യമാക്കേണ്ട " | ||||
| "എക്സ്റ്റെന്ഷനുകള് ഈ കീ പട്ടിക " | ||||
| "ലഭ്യമാക്കുന്നു. ലഭ്യമാക്കേണ്ട ഏതു് എക്സ്റ്റെന്ഷനും ഈ പട്ടികയിലുണ്ടാവണം. " | ||||
| "org.gnome.Shell-ല് " | ||||
| "നിങ്ങള്ക്കു് EnableExtension, DisableExtension എന്നീ ഡീബസ് രീതികളിലൂടെ ഈ " | ||||
| "പട്ടിക " | ||||
| "കൈകാര്യം ചെയ്യുവാനും സാധിയ്ക്കുന്നു." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:5 | ||||
| msgid "Whether to collect stats about applications usage" | ||||
| msgstr "പ്രയോഗങ്ങളുടെ ഉപയോഗത്തെപ്പറ്റിയുള്ള സ്ഥിതിവിവരക്കണക്കുകള് ശേഖരിയ്ക്കണമോ എന്നു്" | ||||
| msgstr "" | ||||
| "പ്രയോഗങ്ങളുടെ ഉപയോഗത്തെപ്പറ്റിയുള്ള സ്ഥിതിവിവരക്കണക്കുകള് ശേഖരിയ്ക്കണമോ " | ||||
| "എന്നു്" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:6 | ||||
| msgid "" | ||||
| @@ -113,9 +116,12 @@ msgid "" | ||||
| "want to disable this for privacy reasons. Please note that doing so won't " | ||||
| "remove already saved data." | ||||
| msgstr "" | ||||
| "ഏറ്റവും കൂടുതല് തവണ ഉപയോഗിയ്ക്കുന്ന പ്രയോഗങ്ങള് ലഭ്യമാക്കുന്നതിനായി ഷെല് സാധാരണയായി സജീവമായ " | ||||
| "പ്രയോഗങ്ങളെ നിരീക്ഷിയ്ക്കുന്നു. (ഉദാഹരണത്തിനു്, ലോഞ്ചേര്സ്). ഈ ഡേറ്റാ സ്വകാര്യമായി " | ||||
| "സൂക്ഷിയ്ക്കുന്നെങ്കിലും, ചില കാരണങ്ങളാല് ഇതു് പ്രവര്ത്തന രഹിതമാക്കേണ്ടതുണ്ടു്. ഇങ്ങനെ ചെയ്യുന്നതു് " | ||||
| "ഏറ്റവും കൂടുതല് തവണ ഉപയോഗിയ്ക്കുന്ന പ്രയോഗങ്ങള് ലഭ്യമാക്കുന്നതിനായി ഷെല് " | ||||
| "സാധാരണയായി സജീവമായ " | ||||
| "പ്രയോഗങ്ങളെ നിരീക്ഷിയ്ക്കുന്നു. (ഉദാഹരണത്തിനു്, ലോഞ്ചേര്സ്). ഈ ഡേറ്റാ " | ||||
| "സ്വകാര്യമായി " | ||||
| "സൂക്ഷിയ്ക്കുന്നെങ്കിലും, ചില കാരണങ്ങളാല് ഇതു് പ്രവര്ത്തന " | ||||
| "രഹിതമാക്കേണ്ടതുണ്ടു്. ഇങ്ങനെ ചെയ്യുന്നതു് " | ||||
| "നിങ്ങള് സൂക്ഷിച്ച ഡേറ്റയെ ബാധിയ്ക്കുന്നതല്ല." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:7 | ||||
| @@ -126,7 +132,8 @@ msgstr "ഇഷ്ടമുള്ള പ്രയോഗങ്ങള്ക് | ||||
| msgid "" | ||||
| "The applications corresponding to these identifiers will be displayed in the " | ||||
| "favorites area." | ||||
| msgstr "ഈ ഐഡന്റിഫയറുകള്ക്കുള്ള പ്രയോഗങ്ങള് ഉചിതമായ സ്ഥലങ്ങളില് കാണിയ്ക്കുന്നു." | ||||
| msgstr "" | ||||
| "ഈ ഐഡന്റിഫയറുകള്ക്കുള്ള പ്രയോഗങ്ങള് ഉചിതമായ സ്ഥലങ്ങളില് കാണിയ്ക്കുന്നു." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:9 | ||||
| msgid "List of categories that should be displayed as folders" | ||||
| @@ -137,8 +144,8 @@ msgid "" | ||||
| "Each category name in this list will be represented as folder in the " | ||||
| "application view, rather than being displayed inline in the main view." | ||||
| msgstr "" | ||||
| "ഈ പട്ടികയിലുള്ള ഓരോ വിഭാഗത്തിന്റെ പേരും, പ്രധാന കാഴ്ചയില് ഓരോ വരിയായി കാണിയ്ക്കുന്നതിനു് " | ||||
| "പകരം പ്രയോഗങ്ങളുടെ കാഴ്ചയില് ഫോള്ഡറായി കാണിയ്ക്കുന്നു. " | ||||
| "ഈ പട്ടികയിലുള്ള ഓരോ വിഭാഗത്തിന്റെ പേരും, പ്രധാന കാഴ്ചയില് ഓരോ വരിയായി " | ||||
| "കാണിയ്ക്കുന്നതിനു് പകരം പ്രയോഗങ്ങളുടെ കാഴ്ചയില് ഫോള്ഡറായി കാണിയ്ക്കുന്നു. " | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:11 | ||||
| msgid "History for command (Alt-F2) dialog" | ||||
| @@ -153,7 +160,8 @@ msgid "" | ||||
| "Internally used to store the last IM presence explicitly set by the user. " | ||||
| "The value here is from the TpConnectionPresenceType enumeration." | ||||
| msgstr "" | ||||
| "ഉപയോക്താവു് സജ്ജമാക്കിയ അവസാന ഐഎം ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് ഉപയോഗിയ്ക്കുന്നു. മൂല്യം " | ||||
| "ഉപയോക്താവു് സജ്ജമാക്കിയ അവസാന ഐഎം ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് " | ||||
| "ഉപയോഗിയ്ക്കുന്നു. മൂല്യം " | ||||
| "TpConnectionPresenceType തരത്തിലുള്ളതാകുന്നു." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:14 | ||||
| @@ -161,7 +169,8 @@ msgid "" | ||||
| "Internally used to store the last session presence status for the user. The " | ||||
| "value here is from the GsmPresenceStatus enumeration." | ||||
| msgstr "" | ||||
| "ഉപയോക്താവിനുള്ള അവസാന സെഷന് അവസ്ഥ ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് ഉപയോഗിയ്ക്കുന്നു. മൂല്യം " | ||||
| "ഉപയോക്താവിനുള്ള അവസാന സെഷന് അവസ്ഥ ആന്തരികമായി സൂക്ഷിയ്ക്കുന്നതിനു് " | ||||
| "ഉപയോഗിയ്ക്കുന്നു. മൂല്യം " | ||||
| "GsmPresenceStatus തരത്തിലുള്ളതാകുന്നു." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:15 | ||||
| @@ -173,13 +182,15 @@ msgid "" | ||||
| "This key overrides the automatic hiding of the 'Log out' menuitem in single-" | ||||
| "user, single-session situations." | ||||
| msgstr "" | ||||
| "സിംഗിള് യൂസര്, സിംഗിള് സെഷനില് 'ലോഗൌട്ട്' മെനുവസ്തു അദൃശ്യമാക്കുന്നതിനായി ഈ കീ ഉപയോഗിയ്ക്കുന്നു" | ||||
| "സിംഗിള് യൂസര്, സിംഗിള് സെഷനില് 'ലോഗൌട്ട്' മെനുവസ്തു അദൃശ്യമാക്കുന്നതിനായി " | ||||
| "ഈ കീ ഉപയോഗിയ്ക്കുന്നു" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:17 | ||||
| msgid "" | ||||
| "Whether to remember password for mounting encrypted or remote filesystems" | ||||
| msgstr "" | ||||
| "എന്ക്രിപ്റ്റ് ചെയ്തതോ വിദൂരമോ ആയ ഫയല്സിസ്റ്റങ്ങള് മൌണ്ട് ചെയ്യുമ്പോഴുള്ള രഹസ്യവാക്ക് ഓര്മ്മിക്കണോ എന്ന്" | ||||
| "എന്ക്രിപ്റ്റ് ചെയ്തതോ വിദൂരമോ ആയ ഫയല്സിസ്റ്റങ്ങള് മൌണ്ട് ചെയ്യുമ്പോഴുള്ള " | ||||
| "രഹസ്യവാക്ക് ഓര്മ്മിക്കണോ എന്ന്" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:18 | ||||
| msgid "" | ||||
| @@ -188,9 +199,10 @@ msgid "" | ||||
| "'Remember Password' checkbox will be present. This key sets the default " | ||||
| "state of the checkbox." | ||||
| msgstr "" | ||||
| "ഒരു എന്ക്രിപ്റ്റ് ചെയ്ത ഡിവൈസ് അല്ലെങ്കില് വിദൂര ഫയല്സിസ്റ്റം മൌണ്ട് ചെയ്യുമ്പോള് ഷെല് ഒരു രഹസ്യവാക്ക് " | ||||
| "ആവശ്യപ്പെടുന്നു. രഹസ്യവാക്ക് സൂക്ഷിയ്ക്കുവാന് സാധ്യമെങ്കില്,  'രഹസ്യവാക്ക് ഓര്ത്തു്വയ്ക്കുക' ചെക്ക്ബോക്സ് " | ||||
| "കാണാം. ഈ കീ ചെക്ക്ബോക്സിന്റെ സ്വതവേയുള്ള അവസ്ഥ സജ്ജമാക്കുന്നു." | ||||
| "ഒരു എന്ക്രിപ്റ്റ് ചെയ്ത ഡിവൈസ് അല്ലെങ്കില് വിദൂര ഫയല്സിസ്റ്റം മൌണ്ട് " | ||||
| "ചെയ്യുമ്പോള് ഷെല് ഒരു രഹസ്യവാക്ക് ആവശ്യപ്പെടുന്നു. രഹസ്യവാക്ക് " | ||||
| "സൂക്ഷിയ്ക്കുവാന് സാധ്യമെങ്കില്,  'രഹസ്യവാക്ക് ഓര്ത്തു്വയ്ക്കുക' " | ||||
| "ചെക്ക്ബോക്സ് കാണാം. ഈ കീ ചെക്ക്ബോക്സിന്റെ സ്വതവേയുള്ള അവസ്ഥ സജ്ജമാക്കുന്നു." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:19 | ||||
| msgid "Show the week date in the calendar" | ||||
| @@ -216,65 +228,61 @@ msgstr "\"പ്രയോഗങ്ങള് കാണിയ്ക്കുക | ||||
| msgid "" | ||||
| "Keybinding to open the \"Show Applications\" view of the Activities Overview." | ||||
| msgstr "" | ||||
| "പ്രവര്ത്തികളുടെ അവലോകനത്തിന്റെ \"പ്രയോഗങ്ങള് കാണിയ്ക്കുക\" എന്ന കാഴ്ച തുറക്കുന്നതിനുള്ള കീബൈന്ഡിങ്" | ||||
| "പ്രവര്ത്തികളുടെ അവലോകനത്തിന്റെ \"പ്രയോഗങ്ങള് കാണിയ്ക്കുക\" എന്ന കാഴ്ച " | ||||
| "തുറക്കുന്നതിനുള്ള കീബൈന്ഡിങ്" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:25 | ||||
| msgid "Keybinding to open the overview" | ||||
| msgstr "പൊതുവായ അവലോകനം  തുറക്കുന്നതിനുള്ള കീബൈന്ഡിങ്" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:26 | ||||
| msgid "Keybinding to open the Activities Overview." | ||||
| msgstr "പ്രയോഗങ്ങളുടെ പൊതുവായ അവലോകനം എന്ന കാഴ്ച തുറക്കുന്നതിനുള്ള കീബൈന്ഡിങ്" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:27 | ||||
| msgid "Keybinding to toggle the visibility of the message tray" | ||||
| msgstr "സന്ദേശ ട്രേയുടെ ദൃശ്യത ടൊഗ്ഗിള് ചെയ്യുന്നതിനുള്ള കീക്കൂട്ടം" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:28 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:26 | ||||
| msgid "Keybinding to toggle the visibility of the message tray." | ||||
| msgstr "സന്ദേശ ട്രേയുടെ ദൃശ്യത ടൊഗ്ഗിള് ചെയ്യുന്നതിനുള്ള കീക്കൂട്ടം." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:29 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:27 | ||||
| msgid "Keybinding to focus the active notification" | ||||
| msgstr "സജീവമായ അറിയിപ്പിനുള്ള കീബൈന്ഡിങ്" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:30 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:28 | ||||
| msgid "Keybinding to focus the active notification." | ||||
| msgstr "സജീവമായ അറിയിപ്പിനുള്ള കീബൈന്ഡിങ്." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:31 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:29 | ||||
| msgid "Keybinding to toggle the screen recorder" | ||||
| msgstr "സ്ക്രീന് റിക്കോര്ഡര് ടൊഗ്ഗിള് ചെയ്യുന്നതിനുള്ള കീക്കൂട്ടം" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:32 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:30 | ||||
| msgid "Keybinding to start/stop the builtin screen recorder." | ||||
| msgstr "ബിള്ട്ടിന് സ്ക്രീന് റിക്കോര്ഡര് തുടങ്ങുവാന്/നിര്ത്തുന്നതിനുള്ള കീക്കൂട്ടം." | ||||
| msgstr "" | ||||
| "ബിള്ട്ടിന് സ്ക്രീന് റിക്കോര്ഡര് തുടങ്ങുവാന്/നിര്ത്തുന്നതിനുള്ള " | ||||
| "കീക്കൂട്ടം." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:33 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:31 | ||||
| msgid "Which keyboard to use" | ||||
| msgstr "ഏതു് കീബോര്ഡ് ഉപയോഗിയ്ക്കണം" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:34 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:32 | ||||
| msgid "The type of keyboard to use." | ||||
| msgstr "ഏതു് തരം കീബോര്ഡ് ഉപയോഗിയ്ക്കണം." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:35 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:33 | ||||
| msgid "Framerate used for recording screencasts." | ||||
| msgstr "സ്ക്രീന്കാസ്റ്റുകള് റിക്കോര്ഡ് ചെയ്യുന്നതിനുള്ള ഫ്രെയിം റേറ്റ്." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:36 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:34 | ||||
| msgid "" | ||||
| "The framerate of the resulting screencast recordered by GNOME Shell's " | ||||
| "screencast recorder in frames-per-second." | ||||
| msgstr "" | ||||
| "ഗ്നോം ഷെല്ലിന്റെ സ്ക്രീന്കാസ്റ്റ് റിക്കോര്ഡര് റീക്കോര്ഡ് ചെയ്തിട്ടുള്ള സ്ക്രീന്കാസ്റ്റിന്റെ " | ||||
| "ഗ്നോം ഷെല്ലിന്റെ സ്ക്രീന്കാസ്റ്റ് റിക്കോര്ഡര് റീക്കോര്ഡ് ചെയ്തിട്ടുള്ള " | ||||
| "സ്ക്രീന്കാസ്റ്റിന്റെ " | ||||
| "ഫ്രെയിംറേറ്റ്, ഒരു സെക്കന്ഡില് ഒരു ഫ്രെയിം." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:37 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:35 | ||||
| msgid "The gstreamer pipeline used to encode the screencast" | ||||
| msgstr "സ്ക്രീന്കാസ്റ്റ് എന്കോഡ് ചെയ്യുന്നതിനുള്ള gstreamer പൈപ്പ്ലൈന്" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:39 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:37 | ||||
| #, no-c-format | ||||
| msgid "" | ||||
| "Sets the GStreamer pipeline used to encode recordings. It follows the syntax " | ||||
| @@ -288,68 +296,78 @@ msgid "" | ||||
| "threads=%T ! queue ! webmmux' and records to WEBM using the VP8 codec. %T is " | ||||
| "used as a placeholder for a guess at the optimal thread count on the system." | ||||
| msgstr "" | ||||
| "റിക്കോര്ഡിങുകള് എന്കോഡ് ചെയ്യുന്നതിനായി GStreamer പൈപ്പ് ലൈന് ഉപയോഗിയ്ക്കുന്നു. gst-launch-" | ||||
| "നുള്ള സിന്റാക്സ് ഉപയോഗിയ്ക്കുന്നു. കാലിയായി സജ്ജമാക്കുമ്പോള് കാലിയാകുന്നു.ഇതു് നിലവില് 'vp8enc " | ||||
| "റിക്കോര്ഡിങുകള് എന്കോഡ് ചെയ്യുന്നതിനായി GStreamer പൈപ്പ് ലൈന് " | ||||
| "ഉപയോഗിയ്ക്കുന്നു. gst-launch-" | ||||
| "നുള്ള സിന്റാക്സ് ഉപയോഗിയ്ക്കുന്നു. കാലിയായി സജ്ജമാക്കുമ്പോള് " | ||||
| "കാലിയാകുന്നു.ഇതു് നിലവില് 'vp8enc " | ||||
| "min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! " | ||||
| "queue ! webmmux' ആകുന്നുസ WEBM VP8 കോഡ് ഉപയോഗിച്ചു് റിക്കോര്ഡ് ചെയ്യുന്നു." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:40 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:38 | ||||
| msgid "File extension used for storing the screencast" | ||||
| msgstr "സ്ക്രീന്കാസ്റ്റ് സൂക്ഷിയ്ക്കുന്നതിനുള്ള ഫയല് എക്സ്റ്റെന്ഷന്" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:41 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:39 | ||||
| msgid "" | ||||
| "The filename for recorded screencasts will be a unique filename based on the " | ||||
| "current date, and use this extension. It should be changed when recording to " | ||||
| "a different container format." | ||||
| msgstr "" | ||||
| "റിക്കോര്ഡ് ചെയ്ത സ്ക്രീന്കാസ്റ്റുകള്ക്കുള്ള ഫയല്നാമം നിലവിലുള്ള തീയതി, എക്സ്റ്റെന്ഷന് എന്നിവ " | ||||
| "അനുസരിച്ചാകുന്നു. മറ്റൊരു ശൈലിയിലേക്കു് റിക്കോര്ഡ് ചെയ്യുമ്പോള് ഇതു് മാറ്റണം." | ||||
| "റിക്കോര്ഡ് ചെയ്ത സ്ക്രീന്കാസ്റ്റുകള്ക്കുള്ള ഫയല്നാമം നിലവിലുള്ള തീയതി, " | ||||
| "എക്സ്റ്റെന്ഷന് എന്നിവ " | ||||
| "അനുസരിച്ചാകുന്നു. മറ്റൊരു ശൈലിയിലേക്കു് റിക്കോര്ഡ് ചെയ്യുമ്പോള് ഇതു് " | ||||
| "മാറ്റണം." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:42 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:40 | ||||
| msgid "The application icon mode." | ||||
| msgstr "പ്രയോഗത്തിന്റെ ഐക്കണ് മോഡ്." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:43 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:41 | ||||
| msgid "" | ||||
| "Configures how the windows are shown in the switcher. Valid possibilities " | ||||
| "are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-" | ||||
| "only' (shows only the application icon) or 'both'." | ||||
| msgstr "" | ||||
| "സ്വിച്ചറില് ജാലകങ്ങള് എങ്ങനെ കാണിയ്ക്കുന്നു എന്നു് ക്രമീകരിയ്ക്കുന്നു. ശരിയായ സാധ്യതകള്: " | ||||
| "'thumbnail-only' (ജാലകത്തിന്റെ പ്രതിരൂപം കാണിയ്ക്കുന്നു), 'app-icon-" | ||||
| "സ്വിച്ചറില് ജാലകങ്ങള് എങ്ങനെ കാണിയ്ക്കുന്നു എന്നു് ക്രമീകരിയ്ക്കുന്നു. " | ||||
| "ശരിയായ " | ||||
| "സാധ്യതകള്: 'thumbnail-only' (ജാലകത്തിന്റെ പ്രതിരൂപം കാണിയ്ക്കുന്നു), " | ||||
| "'app-icon-" | ||||
| "only' (പ്രയോഗത്തിന്റെ പ്രതിരൂപം കാണിയ്ക്കുന്നു) അല്ലെങ്കില് 'both'." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:44 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:42 | ||||
| msgid "Attach modal dialog to the parent window" | ||||
| msgstr "പേരന്റ് ജാലകത്തിലേക്കു് ഡയലോഗ് ചേര്ക്കുക" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:45 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:43 | ||||
| msgid "" | ||||
| "This key overrides the key in org.gnome.mutter when running GNOME Shell." | ||||
| msgstr "ഗ്നോം ഷെല് പ്രവര്ത്തിയ്ക്കുമ്പോള് org.gnome.mutter-ലുള്ള കീ ഈ കീ തിരുത്തിയെഴുതുന്നു." | ||||
| msgstr "" | ||||
| "ഗ്നോം ഷെല് പ്രവര്ത്തിയ്ക്കുമ്പോള് org.gnome.mutter-ലുള്ള കീ ഈ കീ " | ||||
| "തിരുത്തിയെഴുതുന്നു." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:46 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:44 | ||||
| msgid "Arrangement of buttons on the titlebar" | ||||
| msgstr "തലക്കെട്ടിനുള്ള ബാറില് ബട്ടണുകളുടെ ക്രമീകരണം" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:47 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:45 | ||||
| msgid "" | ||||
| "This key overrides the key in org.gnome.desktop.wm.preferences when running " | ||||
| "GNOME Shell." | ||||
| msgstr "" | ||||
| "ഗ്നോം ഷെല് പ്രവര്ത്തിയ്ക്കുമ്പോള് org.gnome.desktop.wm.preferences-ലുള്ള കീ ഈ കീ " | ||||
| "തിരുത്തിയെഴുതുന്നു." | ||||
| "ഗ്നോം ഷെല് പ്രവര്ത്തിയ്ക്കുമ്പോള് org.gnome.desktop.wm.preferences-ലുള്ള " | ||||
| "കീ ഈ കീ തിരുത്തിയെഴുതുന്നു." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:48 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:46 | ||||
| msgid "Enable edge tiling when dropping windows on screen edges" | ||||
| msgstr "സ്ക്രീന് കോണുകളില് ജാലകങ്ങള് എത്തിയ്ക്കുമ്പോള് കോണ് ചരിയ്ക്കുന്നതിനായി പ്രവര്ത്തന സജ്ജമാക്കുക" | ||||
| msgstr "" | ||||
| "സ്ക്രീന് കോണുകളില് ജാലകങ്ങള് എത്തിയ്ക്കുമ്പോള് കോണ് ചരിയ്ക്കുന്നതിനായി " | ||||
| "പ്രവര്ത്തന സജ്ജമാക്കുക" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:49 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:47 | ||||
| msgid "Workspaces are managed dynamically" | ||||
| msgstr "പണിയിടങ്ങള് ഡയനാമിക്കായി കൈകാര്യം ചെയ്തിരിക്കുന്നു" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:50 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:48 | ||||
| msgid "Workspaces only on primary monitor" | ||||
| msgstr "പ്രധാന മോണിറ്ററില് മാത്രം പണിയിടങ്ങള്" | ||||
|  | ||||
| @@ -364,9 +382,12 @@ msgstr "എക്സ്റ്റെന്ഷന്" | ||||
|  | ||||
| #: ../js/extensionPrefs/main.js:189 | ||||
| msgid "Select an extension to configure using the combobox above." | ||||
| msgstr "മുകളിലുള്ള കോമ്പോ ബോക്സ് ഉപയോഗിച്ചു് ക്രമീകരിയ്ക്കുന്നതിനുള്ളൊരു എക്സ്റ്റെന്ഷന് തെരഞ്ഞെടുക്കുക." | ||||
| msgstr "" | ||||
| "മുകളിലുള്ള കോമ്പോ ബോക്സ് ഉപയോഗിച്ചു് ക്രമീകരിയ്ക്കുന്നതിനുള്ളൊരു " | ||||
| "എക്സ്റ്റെന്ഷന് തെരഞ്ഞെടുക്കുക." | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:405 | ||||
| #| msgid "Session..." | ||||
| msgid "Session…" | ||||
| msgstr "പ്രവര്ത്തനവേള..." | ||||
|  | ||||
| @@ -377,32 +398,32 @@ msgstr "പ്രവര്ത്തനവേള..." | ||||
| msgid "Not listed?" | ||||
| msgstr "ലഭ്യമല്ലേ?" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:787 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:376 | ||||
| #: ../js/gdm/loginDialog.js:786 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 | ||||
| #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:100 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:99 | ||||
| #: ../js/ui/userMenu.js:938 | ||||
| msgid "Cancel" | ||||
| msgstr "വേണ്ട" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:803 | ||||
| #: ../js/gdm/loginDialog.js:802 | ||||
| msgctxt "button" | ||||
| msgid "Sign In" | ||||
| msgstr "അകത്തുകയറുക" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:803 | ||||
| #: ../js/gdm/loginDialog.js:802 | ||||
| msgid "Next" | ||||
| msgstr "അടുത്തത്" | ||||
|  | ||||
| #. 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:918 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/gdm/loginDialog.js:917 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/ui/components/networkAgent.js:278 | ||||
| msgid "Username: " | ||||
| msgstr "ഉപയോക്തൃ നാമം: " | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:1174 | ||||
| #: ../js/gdm/loginDialog.js:1173 | ||||
| msgid "Login Window" | ||||
| msgstr "പ്രവേശന ജാലകം" | ||||
|  | ||||
| @@ -455,23 +476,23 @@ msgstr "ആജ്ഞ പ്രാവര്ത്തികമാക്കാ | ||||
| msgid "Execution of '%s' failed:" | ||||
| msgstr "'%s' നടപ്പിലാക്കുന്നതില് പരാജയപ്പെട്ടു:" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:351 | ||||
| #: ../js/ui/appDisplay.js:349 | ||||
| msgid "Frequent" | ||||
| msgstr "ഇടയ്ക്കിടെ" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:358 | ||||
| #: ../js/ui/appDisplay.js:356 | ||||
| msgid "All" | ||||
| msgstr "എല്ലാം" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:916 | ||||
| #: ../js/ui/appDisplay.js:914 | ||||
| msgid "New Window" | ||||
| msgstr "പുതിയ വിന്ഡോ" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:919 ../js/ui/dash.js:284 | ||||
| #: ../js/ui/appDisplay.js:917 ../js/ui/dash.js:284 | ||||
| msgid "Remove from Favorites" | ||||
| msgstr "ഇഷ്ടപ്പെട്ടവയില് നിന്നും നീക്കം ചെയ്യുക" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:920 | ||||
| #: ../js/ui/appDisplay.js:918 | ||||
| msgid "Add to Favorites" | ||||
| msgstr "ഇഷ്ടപ്പെട്ടവയിലേക്ക് ചേര്ക്കുക" | ||||
|  | ||||
| @@ -508,7 +529,7 @@ msgctxt "event list time" | ||||
| msgid "%H\\u2236%M" | ||||
| msgstr "%H\\u2236%M" | ||||
|  | ||||
| #. Translators: Shown in calendar event list, if 12h format, | ||||
| #. Transators: Shown in calendar event list, if 12h format, | ||||
| #. \u2236 is a ratio character, similar to : and \u2009 is | ||||
| #. a thin space | ||||
| #: ../js/ui/calendar.js:77 | ||||
| @@ -711,7 +732,8 @@ msgid "" | ||||
| "Passwords or encryption keys are required to access the wireless network " | ||||
| "'%s'." | ||||
| msgstr "" | ||||
| "വയര്ലെസ് നെറ്റ്വര്ക്ക് '%s'-ലേക്ക് പ്രവേശിക്കുന്നതിനായി രഹസ്യവാക്കുകള് അല്ലെങ്കില് എന്ക്രിപ്ഷന് കീകള് " | ||||
| "വയര്ലെസ് നെറ്റ്വര്ക്ക് '%s'-ലേക്ക് പ്രവേശിക്കുന്നതിനായി രഹസ്യവാക്കുകള് " | ||||
| "അല്ലെങ്കില് എന്ക്രിപ്ഷന് കീകള് " | ||||
| "ആവശ്യമുണ്ടു്." | ||||
|  | ||||
| #: ../js/ui/components/networkAgent.js:314 | ||||
| @@ -768,7 +790,7 @@ msgid "Sorry, that didn't work. Please try again." | ||||
| msgstr "ക്ഷമിക്കണം, അതു ശരിയല്ല. ദയവായി വീണ്ടും ശ്രമിക്കുക." | ||||
|  | ||||
| #. Translators: this is a filename used for screencast recording | ||||
| #: ../js/ui/components/recorder.js:47 | ||||
| #: ../js/ui/components/recorder.js:48 | ||||
| #, no-c-format | ||||
| msgid "Screencast from %d %t" | ||||
| msgstr "%d-ല് നിന്നുള്ള സ്ക്രീന്കാസ്റ്റ്, %t-ല്" | ||||
| @@ -891,7 +913,8 @@ msgstr "%s നിങ്ങള്ക്കു് %s അയച്ചിരി | ||||
| #: ../js/ui/components/telepathyClient.js:1206 | ||||
| #, c-format | ||||
| msgid "%s would like permission to see when you are online" | ||||
| msgstr "നിങ്ങള് ഓണ്ലൈന് ആകുമ്പോള് കാണുന്നതിനുള്ള അനുമതി %s-നു് ആവശ്യമുണ്ടു്" | ||||
| msgstr "" | ||||
| "നിങ്ങള് ഓണ്ലൈന് ആകുമ്പോള് കാണുന്നതിനുള്ള അനുമതി %s-നു് ആവശ്യമുണ്ടു്" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1298 | ||||
| msgid "Network error" | ||||
| @@ -964,7 +987,9 @@ msgstr "ഈ അക്കൌണ്ട് നിലവില് സര്വ | ||||
| #: ../js/ui/components/telepathyClient.js:1332 | ||||
| msgid "" | ||||
| "Connection has been replaced by a new connection using the same resource" | ||||
| msgstr "അതേ ശ്രോതസ്സ് ഉപയോഗിച്ചു് ഒരു പുതിയ കണക്ഷന് ഉപയോഗിച്ചു് ഈ കണക്ഷന് മാറ്റിസ്ഥാപിയ്ക്കുന്നു" | ||||
| msgstr "" | ||||
| "അതേ ശ്രോതസ്സ് ഉപയോഗിച്ചു് ഒരു പുതിയ കണക്ഷന് ഉപയോഗിച്ചു് ഈ കണക്ഷന് " | ||||
| "മാറ്റിസ്ഥാപിയ്ക്കുന്നു" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1334 | ||||
| msgid "The account already exists on the server" | ||||
| @@ -981,14 +1006,17 @@ msgstr "സമ്മതപത്രം വീണ്ടും ആവശ്യപ | ||||
| #: ../js/ui/components/telepathyClient.js:1340 | ||||
| msgid "" | ||||
| "Certificate uses an insecure cipher algorithm or is cryptographically weak" | ||||
| msgstr "സമ്മതപത്രം സുരക്ഷിതമല്ലാത്തൊരു സിഫര് ആല്ഗോരിഥം ഉപയോഗിയ്ക്കുന്നു അല്ലെങ്കില് ഉചിതമല്ല" | ||||
| msgstr "" | ||||
| "സമ്മതപത്രം സുരക്ഷിതമല്ലാത്തൊരു സിഫര് ആല്ഗോരിഥം ഉപയോഗിയ്ക്കുന്നു " | ||||
| "അല്ലെങ്കില് ഉചിതമല്ല" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1342 | ||||
| msgid "" | ||||
| "The length of the server certificate, or the depth of the server certificate " | ||||
| "chain, exceed the limits imposed by the cryptography library" | ||||
| msgstr "" | ||||
| "സര്വറിന്റെ സമ്മതപത്രത്തിന്റെ വ്യാപ്തി, അല്ലെങ്കില് സര്വര് സമ്മതപത്ര ചെയിന്റെ വ്യാപ്തി, എന്നിവ " | ||||
| "സര്വറിന്റെ സമ്മതപത്രത്തിന്റെ വ്യാപ്തി, അല്ലെങ്കില് സര്വര് സമ്മതപത്ര " | ||||
| "ചെയിന്റെ വ്യാപ്തി, എന്നിവ " | ||||
| "പരിധിയില് കൂടുന്നു" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1344 | ||||
| @@ -1057,7 +1085,8 @@ msgstr "പുറത്ത് കടക്കുക" | ||||
| #: ../js/ui/endSessionDialog.js:65 | ||||
| msgid "Click Log Out to quit these applications and log out of the system." | ||||
| msgstr "" | ||||
| "ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പുറത്തു കടക്കുക ക്ലിക്ക് ചെയ്തു് സിസ്റ്റത്തില് നിന്നും " | ||||
| "ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പുറത്തു കടക്കുക ക്ലിക്ക് " | ||||
| "ചെയ്തു് സിസ്റ്റത്തില് നിന്നും " | ||||
| "പുറത്തു് കടക്കുക." | ||||
|  | ||||
| #: ../js/ui/endSessionDialog.js:67 | ||||
| @@ -1091,7 +1120,8 @@ msgstr "നിര്ത്തുക" | ||||
| #: ../js/ui/endSessionDialog.js:84 | ||||
| msgid "Click Power Off to quit these applications and power off the system." | ||||
| msgstr "" | ||||
| "ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പവര് ഓഫ് ചെയ്യുക ക്ലിക്ക് ചെയ്തു സിസ്റ്റിന്റെ പവര് " | ||||
| "ഈ പ്രയോഗങ്ങളില് നിന്നും പുറത്തു് കടക്കുന്നതിനായി പവര് ഓഫ് ചെയ്യുക ക്ലിക്ക് " | ||||
| "ചെയ്തു സിസ്റ്റിന്റെ പവര് " | ||||
| "ഓഫ് ചെയ്യുക." | ||||
|  | ||||
| #: ../js/ui/endSessionDialog.js:86 | ||||
| @@ -1122,7 +1152,8 @@ msgstr "പുനരാരംഭിക്കുക" | ||||
|  | ||||
| #: ../js/ui/endSessionDialog.js:101 | ||||
| msgid "Click Restart to quit these applications and restart the system." | ||||
| msgstr "ഈ പ്രയോഗങ്ങള് നിറുത്തി സിസ്റ്റം പുനരാരംഭിക്കുവാന് പുനരാരംഭിക്കൂ അമര്ത്തുക" | ||||
| msgstr "" | ||||
| "ഈ പ്രയോഗങ്ങള് നിറുത്തി സിസ്റ്റം പുനരാരംഭിക്കുവാന് പുനരാരംഭിക്കൂ അമര്ത്തുക" | ||||
|  | ||||
| #: ../js/ui/endSessionDialog.js:103 | ||||
| #, c-format | ||||
| @@ -1142,7 +1173,9 @@ msgstr "ഇന്സ്റ്റോള്" | ||||
| #: ../js/ui/extensionDownloader.js:204 | ||||
| #, c-format | ||||
| msgid "Download and install '%s' from extensions.gnome.org?" | ||||
| msgstr "extensions.gnome.org ഇല് നിന്നും '%s' ഡൗണ്ലോട് ചെയ്ത് ഇന്സ്റ്റോള് ചെയ്യേണമോ?" | ||||
| msgstr "" | ||||
| "extensions.gnome.org ഇല് നിന്നും '%s' ഡൗണ്ലോട് ചെയ്ത് ഇന്സ്റ്റോള് " | ||||
| "ചെയ്യേണമോ?" | ||||
|  | ||||
| #: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:314 | ||||
| #: ../js/ui/status/power.js:211 | ||||
| @@ -1171,9 +1204,7 @@ msgstr "പിശകുകള് കാണിക്കുക" | ||||
| msgid "Enabled" | ||||
| msgstr "പ്രവര്ത്തനക്ഷമമാക്കി" | ||||
|  | ||||
| #. translators: | ||||
| #. * The device has been disabled | ||||
| #: ../js/ui/lookingGlass.js:769 ../src/gvc/gvc-mixer-control.c:1830 | ||||
| #: ../js/ui/lookingGlass.js:769 | ||||
| msgid "Disabled" | ||||
| msgstr "പ്രവര്ത്തനരഹിതമാക്കി" | ||||
|  | ||||
| @@ -1206,6 +1237,7 @@ msgid "Remove" | ||||
| msgstr "നീക്കം ചെയ്യുക" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1501 | ||||
| #| msgid "No Messages" | ||||
| msgid "Clear Messages" | ||||
| msgstr "സന്ദേശങ്ങള് വെടിപ്പാക്കുക" | ||||
|  | ||||
| @@ -1213,35 +1245,35 @@ msgstr "സന്ദേശങ്ങള് വെടിപ്പാക്ക | ||||
| msgid "Notification Settings" | ||||
| msgstr "അറിയിപ്പു് ക്രമീകരണങ്ങള്" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1710 | ||||
| #: ../js/ui/messageTray.js:1709 | ||||
| msgid "No Messages" | ||||
| msgstr "സന്ദേശങ്ങളില്ല" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1783 | ||||
| #: ../js/ui/messageTray.js:1782 | ||||
| msgid "Message Tray" | ||||
| msgstr "സന്ദേശത്തിന്റെ ട്രേ" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:2801 | ||||
| #: ../js/ui/messageTray.js:2810 | ||||
| msgid "System Information" | ||||
| msgstr "സിസ്റ്റത്തെക്കുറിച്ചുള്ള വിവരം" | ||||
|  | ||||
| #: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:378 | ||||
| #: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:374 | ||||
| msgctxt "program" | ||||
| msgid "Unknown" | ||||
| msgstr "അജ്ഞാതം" | ||||
|  | ||||
| #: ../js/ui/overviewControls.js:472 ../js/ui/screenShield.js:149 | ||||
| #: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149 | ||||
| #, c-format | ||||
| msgid "%d new message" | ||||
| msgid_plural "%d new messages" | ||||
| msgstr[0] "%d പുതിയ സന്ദേശം" | ||||
| msgstr[1] "%d പുതിയ സന്ദേശങ്ങള്" | ||||
|  | ||||
| #: ../js/ui/overview.js:82 | ||||
| #: ../js/ui/overview.js:84 | ||||
| msgid "Undo" | ||||
| msgstr "വേണ്ട" | ||||
|  | ||||
| #: ../js/ui/overview.js:127 | ||||
| #: ../js/ui/overview.js:129 | ||||
| msgid "Overview" | ||||
| msgstr "അവലോകനം" | ||||
|  | ||||
| @@ -1249,21 +1281,22 @@ msgstr "അവലോകനം" | ||||
| #. in the search entry when no search is | ||||
| #. active; it should not exceed ~30 | ||||
| #. characters. | ||||
| #: ../js/ui/overview.js:260 | ||||
| #: ../js/ui/overview.js:271 | ||||
| #| msgid "Type to search..." | ||||
| msgid "Type to search…" | ||||
| msgstr "തെരയുന്നതിനായി ടൈപ്പ് ചെയ്യുക..." | ||||
|  | ||||
| #: ../js/ui/panel.js:641 | ||||
| #: ../js/ui/panel.js:612 | ||||
| msgid "Quit" | ||||
| msgstr "നിര്ത്തുക" | ||||
|  | ||||
| #. Translators: If there is no suitable word for "Activities" | ||||
| #. in your language, you can use the word for "Overview". | ||||
| #: ../js/ui/panel.js:692 | ||||
| #: ../js/ui/panel.js:636 | ||||
| msgid "Activities" | ||||
| msgstr "പ്രവര്ത്തനങ്ങള്" | ||||
|  | ||||
| #: ../js/ui/panel.js:989 | ||||
| #: ../js/ui/panel.js:933 | ||||
| msgid "Top Bar" | ||||
| msgstr "മുകളിലുള്ള ബാര്" | ||||
|  | ||||
| @@ -1272,15 +1305,15 @@ 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:718 | ||||
| #: ../js/ui/popupMenu.js:727 | ||||
| msgid "toggle-switch-us" | ||||
| msgstr "toggle-switch-us" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:74 | ||||
| #: ../js/ui/runDialog.js:73 | ||||
| msgid "Enter a Command" | ||||
| msgstr "ഒരു കമാന്ഡ് നല്കുക" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:110 | ||||
| #: ../js/ui/runDialog.js:109 | ||||
| msgid "Close" | ||||
| msgstr "അടക്കുക" | ||||
|  | ||||
| @@ -1301,7 +1334,7 @@ msgstr[1] "%d പുതിയ അറിയിപ്പുകള്" | ||||
| msgid "Lock" | ||||
| msgstr "പൂട്ടുക" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:641 | ||||
| #: ../js/ui/screenShield.js:637 | ||||
| msgid "GNOME needs to lock the screen" | ||||
| msgstr "ഗ്നോമിന് സ്ക്രീന് പൂട്ടണം" | ||||
|  | ||||
| @@ -1312,15 +1345,17 @@ msgstr "ഗ്നോമിന് സ്ക്രീന് പൂട്ടണ | ||||
| #. | ||||
| #. XXX: another option is to kick the user into the gdm login | ||||
| #. screen, where we're not affected by grabs | ||||
| #: ../js/ui/screenShield.js:762 ../js/ui/screenShield.js:1198 | ||||
| #: ../js/ui/screenShield.js:758 ../js/ui/screenShield.js:1194 | ||||
| #| msgid "Unable to connect to %s" | ||||
| msgid "Unable to lock" | ||||
| msgstr "പൂട്ടുവാന് സാധ്യമല്ല" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:763 ../js/ui/screenShield.js:1199 | ||||
| #: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1195 | ||||
| msgid "Lock was blocked by an application" | ||||
| msgstr "പൂട്ടുന്ന സംവിധാനം ഒരു പ്രയോഗം തടസ്സപ്പെടുത്തിയിരിയ്ക്കുന്നു" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:453 | ||||
| #| msgid "Searching..." | ||||
| msgid "Searching…" | ||||
| msgstr "തെരയുന്നു..." | ||||
|  | ||||
| @@ -1336,11 +1371,11 @@ msgstr "പകര്ത്തുക" | ||||
| msgid "Paste" | ||||
| msgstr "ഒട്ടിയ്ക്കുക" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:101 | ||||
| #: ../js/ui/shellEntry.js:106 | ||||
| msgid "Show Text" | ||||
| msgstr "പദാവലി കാണിക്കുക" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:103 | ||||
| #: ../js/ui/shellEntry.js:108 | ||||
| msgid "Hide Text" | ||||
| msgstr "പദാവലി മറക്കുക" | ||||
|  | ||||
| @@ -1352,7 +1387,7 @@ msgstr "രഹസ്യവാക്ക്" | ||||
| msgid "Remember Password" | ||||
| msgstr "രഹസ്യവാക്ക് ഓര്ത്തു് വയ്ക്കുക" | ||||
|  | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:114 | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:113 | ||||
| msgid "Unlock" | ||||
| msgstr "പൂട്ട് തുറക്കുക" | ||||
|  | ||||
| @@ -1416,10 +1451,12 @@ msgid "Visibility" | ||||
| msgstr "കാഴ്ച" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:59 | ||||
| #| msgid "Send Files to Device..." | ||||
| msgid "Send Files to Device…" | ||||
| msgstr "ഡിവൈസിലേക്കു് ഫയലുകള് അയയ്ക്കുക..." | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:60 | ||||
| #| msgid "Set Up a New Device..." | ||||
| msgid "Set Up a New Device…" | ||||
| msgstr "പുതിയൊരു ഡിവൈസ് സജ്ജമാക്കുക..." | ||||
|  | ||||
| @@ -1446,6 +1483,7 @@ msgid "connecting..." | ||||
| msgstr "ബന്ധിപ്പിയ്ക്കുന്നു...." | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:239 | ||||
| #| msgid "Send Files..." | ||||
| msgid "Send Files…" | ||||
| msgstr "ഫയലുകള് അയയ്ക്കുക..." | ||||
|  | ||||
| @@ -1658,6 +1696,7 @@ msgstr "ഊര്ജ്ജ ക്രമീകരണങ്ങള്" | ||||
| #. 0 is reported when UPower does not have enough data | ||||
| #. to estimate battery life | ||||
| #: ../js/ui/status/power.js:99 | ||||
| #| msgid "Estimating..." | ||||
| msgid "Estimating…" | ||||
| msgstr "കണക്കുകൂട്ടുന്നു..." | ||||
|  | ||||
| @@ -1757,11 +1796,11 @@ msgstr "ഒച്ച" | ||||
| msgid "Microphone" | ||||
| msgstr "മൈക്രോഫോണ്" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:125 | ||||
| #: ../js/ui/unlockDialog.js:124 | ||||
| msgid "Log in as another user" | ||||
| msgstr "മറ്റൊരു ഉപയോക്താവായി പ്രവേശിയ്ക്കുക" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:146 | ||||
| #: ../js/ui/unlockDialog.js:145 | ||||
| msgid "Unlock Window" | ||||
| msgstr "ജാലകത്തിന്റെ പൂട്ടു തുറക്കുക" | ||||
|  | ||||
| @@ -1814,8 +1853,10 @@ msgid "" | ||||
| "Notifications are now disabled, including chat messages. Your online status " | ||||
| "has been adjusted to let others know that you might not see their messages." | ||||
| msgstr "" | ||||
| "ചാറ്റ് സന്ദേശങ്ങള് എന്ന പോലെ അറിയിപ്പുകള് പ്രവര്ത്തന രഹിതമാക്കുന്നു. മറ്റുള്ളവരുടെ ചാറ്റ് സന്ദേശങ്ങള് " | ||||
| "നിങ്ങള്ക്കു് കാണുവാന് സാധ്യമല്ല എന്നു് നിങ്ങളുടെ ഓണ്ലൈന് അവസ്ഥയില് വ്യക്തമാക്കുന്നു." | ||||
| "ചാറ്റ് സന്ദേശങ്ങള് എന്ന പോലെ അറിയിപ്പുകള് പ്രവര്ത്തന രഹിതമാക്കുന്നു. " | ||||
| "മറ്റുള്ളവരുടെ ചാറ്റ് സന്ദേശങ്ങള് " | ||||
| "നിങ്ങള്ക്കു് കാണുവാന് സാധ്യമല്ല എന്നു് നിങ്ങളുടെ ഓണ്ലൈന് അവസ്ഥയില് " | ||||
| "വ്യക്തമാക്കുന്നു." | ||||
|  | ||||
| #: ../js/ui/userMenu.js:888 | ||||
| msgid "Other users are logged in." | ||||
| @@ -1868,28 +1909,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] "%u ഔട്ട്പുട്ട്" | ||||
| msgstr[1] "%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] "%u ഇന്പുട്ട്" | ||||
| msgstr[1] "%u ഇന്പുട്ടുകള്" | ||||
|  | ||||
| #: ../src/gvc/gvc-mixer-control.c:2371 | ||||
| msgid "System Sounds" | ||||
| msgstr "സിസ്റ്റം ശബ്ദങ്ങള്" | ||||
|  | ||||
| #: ../src/main.c:347 | ||||
| msgid "Print version" | ||||
| msgstr "പ്രിന്റ് ചെയ്യുവാന് സാധിയ്ക്കുന്ന പതിപ്പു്" | ||||
| @@ -1906,7 +1925,7 @@ msgstr "ഒരു പ്രത്യേക മോഡ് ഉപയോഗിയ് | ||||
| msgid "List possible modes" | ||||
| msgstr "സാധ്യമായ മോഡുകള് ലഭ്യമാക്കുക" | ||||
|  | ||||
| #: ../src/shell-app.c:626 | ||||
| #: ../src/shell-app.c:622 | ||||
| #, c-format | ||||
| msgid "Failed to launch '%s'" | ||||
| msgstr "'%s' ലഭ്യമാക്കുന്നതില് പരാജയം" | ||||
| @@ -1936,6 +1955,19 @@ msgstr "ഉപയോക്താവു് ആധികാരികത ഉറപ | ||||
| #~ msgid "More..." | ||||
| #~ msgstr "കൂടുതല്..." | ||||
|  | ||||
| #~ msgid "%u Output" | ||||
| #~ msgid_plural "%u Outputs" | ||||
| #~ msgstr[0] "%u ഔട്ട്പുട്ട്" | ||||
| #~ msgstr[1] "%u ഔട്ട്പുട്ടുകള്" | ||||
|  | ||||
| #~ msgid "%u Input" | ||||
| #~ msgid_plural "%u Inputs" | ||||
| #~ msgstr[0] "%u ഇന്പുട്ട്" | ||||
| #~ msgstr[1] "%u ഇന്പുട്ടുകള്" | ||||
|  | ||||
| #~ msgid "System Sounds" | ||||
| #~ msgstr "സിസ്റ്റം ശബ്ദങ്ങള്" | ||||
|  | ||||
| #~ msgctxt "event list time" | ||||
| #~ msgid "%H:%M" | ||||
| #~ msgstr "%H:%M" | ||||
|   | ||||
							
								
								
									
										401
									
								
								po/sk.po
									
									
									
									
									
								
							
							
						
						
									
										401
									
								
								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-05-24 21:21+0000\n" | ||||
| "PO-Revision-Date: 2013-05-24 23:24+0100\n" | ||||
| "POT-Creation-Date: 2013-03-23 11:49+0000\n" | ||||
| "PO-Revision-Date: 2013-03-23 16:21+0000\n" | ||||
| "Last-Translator: Dušan Kazik <prescott66@gmail.com>\n" | ||||
| "Language-Team: Slovak <gnome-sk-list@gnome.org>\n" | ||||
| "Language: sk\n" | ||||
| @@ -34,30 +34,22 @@ msgstr "Zaznamenať dianie na obrazovke" | ||||
| msgid "System" | ||||
| msgstr "Systém" | ||||
|  | ||||
| # nazov klavesovej skratky | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:2 | ||||
| msgid "Show the message tray" | ||||
| msgstr "Zobraziť lištu správ" | ||||
| msgstr "Zobrazí lištu správ" | ||||
|  | ||||
| # nazov klavesovej skratky | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:3 | ||||
| msgid "Focus the active notification" | ||||
| msgstr "Zamerať aktívne oznámenie" | ||||
|  | ||||
| # nazov klavesovej skratky | ||||
| # tooltip | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:4 | ||||
| msgid "Show the overview" | ||||
| msgstr "Zobraziť prehľad" | ||||
|  | ||||
| # nazov klavesovej skratky | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:5 | ||||
| msgid "Show all applications" | ||||
| msgstr "Zobraziť všetky aplikácie" | ||||
| msgstr "Zobrazí všetky aplikácie" | ||||
|  | ||||
| # nazov klavesovej skratky | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:6 | ||||
| #: ../data/50-gnome-shell-system.xml.in.h:5 | ||||
| msgid "Open the application menu" | ||||
| msgstr "Otvoriť ponuku aplikácií" | ||||
| msgstr "Otvorí ponuku aplikácií" | ||||
|  | ||||
| #: ../data/gnome-shell.desktop.in.in.h:1 | ||||
| msgid "GNOME Shell" | ||||
| @@ -108,10 +100,26 @@ msgstr "" | ||||
| "gnome.Shell." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:5 | ||||
| msgid "Whether to collect stats about applications usage" | ||||
| msgstr "Či sa majú zhromažďovať štatistické údaje o používaní aplikácií" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:6 | ||||
| msgid "" | ||||
| "The shell normally monitors active applications in order to present the most " | ||||
| "used ones (e.g. in launchers). While this data will be kept private, you may " | ||||
| "want to disable this for privacy reasons. Please note that doing so won't " | ||||
| "remove already saved data." | ||||
| msgstr "" | ||||
| "Prostredie shell obvykle sleduje aktívne aplikácie, aby mohlo ponúkať " | ||||
| "najpoužívanejšie z nich (napr. v spúšťačoch). Aj keď sú tieto údaje " | ||||
| "uchovávané v tajnosti, môžete ich kvôli lepšej ochrane súkromia zakázať. Ak " | ||||
| "tak urobíte, údaje, ktoré už boli uložené, zostanú zachované." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:7 | ||||
| msgid "List of desktop file IDs for favorite applications" | ||||
| msgstr "Zoznam identifikátorov súborov plochy pre obľúbené aplikácie" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:6 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:8 | ||||
| msgid "" | ||||
| "The applications corresponding to these identifiers will be displayed in the " | ||||
| "favorites area." | ||||
| @@ -120,29 +128,29 @@ msgstr "" | ||||
| "obľúbenými aplikáciami." | ||||
|  | ||||
| # summary | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:7 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:9 | ||||
| msgid "List of categories that should be displayed as folders" | ||||
| msgstr "Zoznam kategórií, ktoré sa majú zobraziť ako priečinky" | ||||
|  | ||||
| # description | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:8 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:10 | ||||
|  | ||||
| msgid "" | ||||
| "Each category name in this list will be represented as folder in the " | ||||
| "application view, rather than being displayed inline in the main view." | ||||
| msgstr "" | ||||
| "Každá z názvov kategórií v tomto zoznamu bude reprezentovaná ako priečinok v " | ||||
| "zobrazení aplikácií namiesto toho, aby sa zobrazila v hlavnom zobrazení." | ||||
| "Každá z názvov kategórií v tomto zoznamu bude reprezentovaná ako priečinok v zobrazení aplikácií namiesto toho, aby sa zobrazila v hlavnom zobrazení." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:9 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:11 | ||||
| msgid "History for command (Alt-F2) dialog" | ||||
| msgstr "História dialógového okna príkazov (Alt-F2)" | ||||
|  | ||||
| # * https://live.gnome.org/GnomeShell/LookingGlass | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:10 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:12 | ||||
| msgid "History for the looking glass dialog" | ||||
| msgstr "História dialógového okna integrovaného odlaďovača" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:11 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:13 | ||||
| msgid "" | ||||
| "Internally used to store the last IM presence explicitly set by the user. " | ||||
| "The value here is from the TpConnectionPresenceType enumeration." | ||||
| @@ -151,7 +159,7 @@ msgstr "" | ||||
| "komunikátora výlučne nastavenej používateľom. Táto hodnota je z vymenovaných " | ||||
| "hodnôt typu TpConnectionPresenceType." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:12 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:14 | ||||
| msgid "" | ||||
| "Internally used to store the last session presence status for the user. The " | ||||
| "value here is from the GsmPresenceStatus enumeration." | ||||
| @@ -160,11 +168,11 @@ msgstr "" | ||||
| "používateľa. Táto hodnota je z vymenovaných hodnôt typu " | ||||
| "GsmPresenceStatusType." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:13 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:15 | ||||
| msgid "Always show the 'Log out' menuitem in the user menu." | ||||
| msgstr "Vždy zobraziť položku „Odhlásiť sa“ v ponuke používateľa" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:14 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:16 | ||||
| msgid "" | ||||
| "This key overrides the automatic hiding of the 'Log out' menuitem in single-" | ||||
| "user, single-session situations." | ||||
| @@ -173,7 +181,7 @@ msgstr "" | ||||
| "s jedným používateľom alebo jednou reláciou." | ||||
|  | ||||
| # summary | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:15 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:17 | ||||
| msgid "" | ||||
| "Whether to remember password for mounting encrypted or remote filesystems" | ||||
| msgstr "" | ||||
| @@ -181,7 +189,7 @@ msgstr "" | ||||
| "prenosných súborových systémov" | ||||
|  | ||||
| # description | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:16 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:18 | ||||
| msgid "" | ||||
| "The shell will request a password when an encrypted device or a remote " | ||||
| "filesystem is mounted. If the password can be saved for future use a " | ||||
| @@ -193,42 +201,34 @@ msgstr "" | ||||
| "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:17 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:19 | ||||
| msgid "Show the week date in the calendar" | ||||
| msgstr "Zobraziť čísla týždňov v kalendári" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:18 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:20 | ||||
| msgid "If true, display the ISO week date in the calendar." | ||||
| msgstr "" | ||||
| "Ak je true, zobrazí v kalendári poradie dní v týždni podľa štandardu ISO." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:19 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:21 | ||||
| msgid "Keybinding to open the application menu" | ||||
| msgstr "Klávesová skratka na otvorenie ponuky aplikácií" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:20 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:22 | ||||
| msgid "Keybinding to open the application menu." | ||||
| msgstr "Klávesová skratka na otvorenie ponuky aplikácií." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:21 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:23 | ||||
| msgid "Keybinding to open the \"Show Applications\" view" | ||||
| msgstr "Klávesová skratka na otvorenie pohľadu „Zobraziť aplikácie“" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:22 | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:24 | ||||
| msgid "" | ||||
| "Keybinding to open the \"Show Applications\" view of the Activities Overview." | ||||
| msgstr "" | ||||
| "Klávesová skratka na otvorenie pohľadu „Zobraziť aplikácie“ v prehľade " | ||||
| "aktivít." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:23 | ||||
| msgid "Keybinding to open the overview" | ||||
| msgstr "Klávesová skratka na otvorenie prehľadu" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:24 | ||||
| msgid "Keybinding to open the Activities Overview." | ||||
| msgstr "Klávesová skratka na otvorenie prehľadu aktivít." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:25 | ||||
| msgid "Keybinding to toggle the visibility of the message tray" | ||||
| msgstr "Klávesová skratka na prepnutie viditeľnosti lišty správ" | ||||
| @@ -384,7 +384,7 @@ 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:371 | ||||
| #: ../js/gdm/loginDialog.js:405 | ||||
| msgid "Session…" | ||||
| msgstr "Relácia…" | ||||
|  | ||||
| @@ -392,43 +392,36 @@ msgstr "Relácia…" | ||||
| #. 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:601 | ||||
| #: ../js/gdm/loginDialog.js:630 | ||||
| msgid "Not listed?" | ||||
| msgstr "Nie ste v zozname?" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:376 | ||||
| #: ../js/gdm/loginDialog.js:786 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 | ||||
| #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:96 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:99 | ||||
| #: ../js/ui/userMenu.js:938 | ||||
| msgid "Cancel" | ||||
| msgstr "Zrušiť" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:791 | ||||
| #: ../js/gdm/loginDialog.js:802 | ||||
| msgctxt "button" | ||||
| msgid "Sign In" | ||||
| msgstr "Prihlásiť sa" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:791 | ||||
| #: ../js/gdm/loginDialog.js:802 | ||||
| msgid "Next" | ||||
| msgstr "Ďalej" | ||||
|  | ||||
| #. Translators: this message is shown below the username entry field | ||||
| #. to clue the user in on how to login to the local network realm | ||||
| #: ../js/gdm/loginDialog.js:888 | ||||
| #, c-format | ||||
| msgid "(e.g., user or %s)" | ||||
| msgstr "(napr., používateľ alebo %s)" | ||||
|  | ||||
| #. TTLS and PEAP are actually much more complicated, but this complication | ||||
| #. is not visible here since we only care about phase2 authentication | ||||
| #. (and don't even care of which one) | ||||
| #: ../js/gdm/loginDialog.js:892 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/gdm/loginDialog.js:917 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/ui/components/networkAgent.js:278 | ||||
| msgid "Username: " | ||||
| msgstr "Používateľské meno: " | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:1158 | ||||
| #: ../js/gdm/loginDialog.js:1173 | ||||
| msgid "Login Window" | ||||
| msgstr "Prihlasovacie okno" | ||||
|  | ||||
| @@ -451,16 +444,21 @@ msgstr "Reštartovať" | ||||
| msgid "Power Off" | ||||
| msgstr "Vypnúť" | ||||
|  | ||||
| #: ../js/gdm/util.js:247 | ||||
| #: ../js/gdm/util.js:249 | ||||
| msgid "Authentication error" | ||||
| msgstr "Chyba pri overovaní totožnosti" | ||||
|  | ||||
| #. Translators: this message is shown below the password entry field | ||||
| #. to indicate the user can swipe their finger instead | ||||
| #: ../js/gdm/util.js:364 | ||||
| #: ../js/gdm/util.js:366 | ||||
| msgid "(or swipe finger)" | ||||
| msgstr "(alebo prejdite prstom)" | ||||
|  | ||||
| #: ../js/gdm/util.js:391 | ||||
| #, c-format | ||||
| msgid "(e.g., user or %s)" | ||||
| msgstr "(napr., používateľ alebo %s)" | ||||
|  | ||||
| #: ../js/misc/util.js:97 | ||||
| msgid "Command not found" | ||||
| msgstr "Príkaz nebol nájdený" | ||||
| @@ -476,23 +474,23 @@ msgstr "Nepodarilo sa analyzovať príkaz:" | ||||
| msgid "Execution of '%s' failed:" | ||||
| msgstr "Spustenie „%s“ zlyhalo:" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:361 | ||||
| #: ../js/ui/appDisplay.js:349 | ||||
| msgid "Frequent" | ||||
| msgstr "Často používané" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:368 | ||||
| #: ../js/ui/appDisplay.js:356 | ||||
| msgid "All" | ||||
| msgstr "Všetky" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:960 | ||||
| #: ../js/ui/appDisplay.js:914 | ||||
| msgid "New Window" | ||||
| msgstr "Nové okno" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:963 ../js/ui/dash.js:284 | ||||
| #: ../js/ui/appDisplay.js:917 ../js/ui/dash.js:284 | ||||
| msgid "Remove from Favorites" | ||||
| msgstr "Odstrániť z obľúbených" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:964 | ||||
| #: ../js/ui/appDisplay.js:918 | ||||
| msgid "Add to Favorites" | ||||
| msgstr "Pridať do obľúbených" | ||||
|  | ||||
| @@ -529,7 +527,7 @@ msgctxt "event list time" | ||||
| msgid "%H\\u2236%M" | ||||
| msgstr "%H\\u2236%M" | ||||
|  | ||||
| #. Translators: Shown in calendar event list, if 12h format, | ||||
| #. Transators: Shown in calendar event list, if 12h format, | ||||
| #. \u2236 is a ratio character, similar to : and \u2009 is | ||||
| #. a thin space | ||||
| #: ../js/ui/calendar.js:77 | ||||
| @@ -631,35 +629,35 @@ msgid "S" | ||||
| msgstr "So" | ||||
|  | ||||
| #. Translators: Text to show if there are no events | ||||
| #: ../js/ui/calendar.js:735 | ||||
| #: ../js/ui/calendar.js:720 | ||||
| msgid "Nothing Scheduled" | ||||
| msgstr "Žiadne naplánované udalosti" | ||||
|  | ||||
| #. Translators: Shown on calendar heading when selected day occurs on current year | ||||
| #: ../js/ui/calendar.js:751 | ||||
| #: ../js/ui/calendar.js:736 | ||||
| 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:754 | ||||
| #: ../js/ui/calendar.js:739 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d, %Y" | ||||
| msgstr "%A, %e. %B %Y" | ||||
|  | ||||
| #: ../js/ui/calendar.js:764 | ||||
| #: ../js/ui/calendar.js:749 | ||||
| msgid "Today" | ||||
| msgstr "Dnes" | ||||
|  | ||||
| #: ../js/ui/calendar.js:768 | ||||
| #: ../js/ui/calendar.js:753 | ||||
| msgid "Tomorrow" | ||||
| msgstr "Zajtra" | ||||
|  | ||||
| #: ../js/ui/calendar.js:779 | ||||
| #: ../js/ui/calendar.js:764 | ||||
| msgid "This week" | ||||
| msgstr "Tento týždeň" | ||||
|  | ||||
| #: ../js/ui/calendar.js:787 | ||||
| #: ../js/ui/calendar.js:772 | ||||
| msgid "Next week" | ||||
| msgstr "Ďalší týždeň" | ||||
|  | ||||
| @@ -685,11 +683,11 @@ msgstr "Otvoriť pomocou programu %s" | ||||
| msgid "Eject" | ||||
| msgstr "Vysunúť" | ||||
|  | ||||
| #: ../js/ui/components/keyring.js:88 ../js/ui/components/polkitAgent.js:280 | ||||
| #: ../js/ui/components/keyring.js:82 ../js/ui/components/polkitAgent.js:268 | ||||
| msgid "Password:" | ||||
| msgstr "Heslo:" | ||||
|  | ||||
| #: ../js/ui/components/keyring.js:107 | ||||
| #: ../js/ui/components/keyring.js:101 | ||||
| msgid "Type again:" | ||||
| msgstr "Zadajte znovu:" | ||||
|  | ||||
| @@ -769,16 +767,16 @@ msgstr "Heslo k mobilnej sieti" | ||||
| msgid "A password is required to connect to '%s'." | ||||
| msgstr "Na pripojenie k „%s“ sa požaduje heslo." | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:54 | ||||
| #: ../js/ui/components/polkitAgent.js:55 | ||||
| msgid "Authentication Required" | ||||
| msgstr "Požaduje sa overenie totožnosti" | ||||
|  | ||||
| # PŠ: ináč toto je riadna hlúposť, keďže sa pýta heslo používateľa "root" | ||||
| #: ../js/ui/components/polkitAgent.js:92 | ||||
| #: ../js/ui/components/polkitAgent.js:93 | ||||
| msgid "Administrator" | ||||
| msgstr "Správca" | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:170 | ||||
| #: ../js/ui/components/polkitAgent.js:165 | ||||
| msgid "Authenticate" | ||||
| msgstr "Overiť totožnosť" | ||||
|  | ||||
| @@ -786,13 +784,13 @@ 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:266 ../js/ui/shellMountOperation.js:383 | ||||
| #: ../js/ui/components/polkitAgent.js:256 ../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." | ||||
|  | ||||
| # %d je datum, %t je cas | ||||
| #. Translators: this is a filename used for screencast recording | ||||
| #: ../js/ui/components/recorder.js:47 | ||||
| #: ../js/ui/components/recorder.js:48 | ||||
| #, no-c-format | ||||
| msgid "Screencast from %d %t" | ||||
| msgstr "Záznam videa obrazovky dňa %d o %t" | ||||
| @@ -1051,22 +1049,22 @@ msgstr "Zobrazí aplikácie" | ||||
| msgid "Dash" | ||||
| msgstr "Dok" | ||||
|  | ||||
| #: ../js/ui/dateMenu.js:86 | ||||
| #: ../js/ui/dateMenu.js:91 | ||||
| msgid "Open Calendar" | ||||
| msgstr "Otvoriť kalendár" | ||||
|  | ||||
| #: ../js/ui/dateMenu.js:90 | ||||
| #: ../js/ui/dateMenu.js:96 | ||||
| msgid "Open Clocks" | ||||
| msgstr "Otvoriť hodiny" | ||||
|  | ||||
| #: ../js/ui/dateMenu.js:97 | ||||
| #: ../js/ui/dateMenu.js:105 | ||||
| msgid "Date & Time Settings" | ||||
| msgstr "Nastavenia dátumu a času" | ||||
|  | ||||
| #. 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:208 | ||||
| #: ../js/ui/dateMenu.js:215 | ||||
| msgid "%A %B %e, %Y" | ||||
| msgstr "%A, %e. %B %Y" | ||||
|  | ||||
| @@ -1180,52 +1178,50 @@ msgstr "Stiahnuť a nainštalovať „%s“ z extensions.gnome.org?" | ||||
| msgid "Keyboard" | ||||
| msgstr "Klávesnica" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:689 | ||||
| #: ../js/ui/lookingGlass.js:693 | ||||
| msgid "No extensions installed" | ||||
| msgstr "Žiadne nainštalované rozšírenia" | ||||
|  | ||||
| #. Translators: argument is an extension UUID. | ||||
| #: ../js/ui/lookingGlass.js:743 | ||||
| #: ../js/ui/lookingGlass.js:747 | ||||
| #, c-format | ||||
| msgid "%s has not emitted any errors." | ||||
| msgstr "%s nevyslal žiadnu chybu." | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:749 | ||||
| #: ../js/ui/lookingGlass.js:753 | ||||
| msgid "Hide Errors" | ||||
| msgstr "Skryť chyby" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:753 ../js/ui/lookingGlass.js:813 | ||||
| #: ../js/ui/lookingGlass.js:757 ../js/ui/lookingGlass.js:817 | ||||
| msgid "Show Errors" | ||||
| msgstr "Zobraziť chyby" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:762 | ||||
| #: ../js/ui/lookingGlass.js:766 | ||||
| msgid "Enabled" | ||||
| msgstr "Povolené" | ||||
|  | ||||
| #. translators: | ||||
| #. * The device has been disabled | ||||
| #: ../js/ui/lookingGlass.js:765 ../src/gvc/gvc-mixer-control.c:1830 | ||||
| #: ../js/ui/lookingGlass.js:769 | ||||
| msgid "Disabled" | ||||
| msgstr "Zakázané" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:767 | ||||
| #: ../js/ui/lookingGlass.js:771 | ||||
| msgid "Error" | ||||
| msgstr "Chyba" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:769 | ||||
| #: ../js/ui/lookingGlass.js:773 | ||||
| msgid "Out of date" | ||||
| msgstr "Neaktuálne" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:771 | ||||
| #: ../js/ui/lookingGlass.js:775 | ||||
| msgid "Downloading" | ||||
| msgstr "Sťahuje sa" | ||||
|  | ||||
| # PK: ide tu o zdrojovy kod? | ||||
| #: ../js/ui/lookingGlass.js:795 | ||||
| #: ../js/ui/lookingGlass.js:799 | ||||
| msgid "View Source" | ||||
| msgstr "Zobraziť zdroj" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:804 | ||||
| #: ../js/ui/lookingGlass.js:808 | ||||
| msgid "Web Page" | ||||
| msgstr "Webová stránka" | ||||
|  | ||||
| @@ -1245,26 +1241,26 @@ msgstr "Vymazať správy" | ||||
| msgid "Notification Settings" | ||||
| msgstr "Nastavenia oznámení" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1707 | ||||
| #: ../js/ui/messageTray.js:1709 | ||||
| msgid "No Messages" | ||||
| msgstr "Žiadne správy" | ||||
|  | ||||
| # DK: zvazoval som pouzit "Panel správ" | ||||
| # neviem co bude vhodnejsie ako preklad "tray" | ||||
| #: ../js/ui/messageTray.js:1780 | ||||
| #: ../js/ui/messageTray.js:1782 | ||||
| msgid "Message Tray" | ||||
| msgstr "Lišta správ" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:2800 | ||||
| #: ../js/ui/messageTray.js:2810 | ||||
| msgid "System Information" | ||||
| msgstr "Informácie o systéme" | ||||
|  | ||||
| #: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:378 | ||||
| #: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:374 | ||||
| msgctxt "program" | ||||
| msgid "Unknown" | ||||
| msgstr "Neznámy" | ||||
|  | ||||
| #: ../js/ui/overviewControls.js:472 ../js/ui/screenShield.js:150 | ||||
| #: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149 | ||||
| #, c-format | ||||
| msgid "%d new message" | ||||
| msgid_plural "%d new messages" | ||||
| @@ -1272,11 +1268,11 @@ msgstr[0] "%d nových správ" | ||||
| msgstr[1] "%d nová správa" | ||||
| msgstr[2] "%d nové správy" | ||||
|  | ||||
| #: ../js/ui/overview.js:82 | ||||
| #: ../js/ui/overview.js:84 | ||||
| msgid "Undo" | ||||
| msgstr "Vrátiť" | ||||
|  | ||||
| #: ../js/ui/overview.js:127 | ||||
| #: ../js/ui/overview.js:129 | ||||
| msgid "Overview" | ||||
| msgstr "Prehľad" | ||||
|  | ||||
| @@ -1285,21 +1281,21 @@ msgstr "Prehľad" | ||||
| #. in the search entry when no search is | ||||
| #. active; it should not exceed ~30 | ||||
| #. characters. | ||||
| #: ../js/ui/overview.js:258 | ||||
| #: ../js/ui/overview.js:271 | ||||
| msgid "Type to search…" | ||||
| msgstr "Zadajte text na vyhľadanie…" | ||||
|  | ||||
| #: ../js/ui/panel.js:642 | ||||
| #: ../js/ui/panel.js:612 | ||||
| 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:693 | ||||
| #: ../js/ui/panel.js:636 | ||||
| msgid "Activities" | ||||
| msgstr "Aktivity" | ||||
|  | ||||
| #: ../js/ui/panel.js:989 | ||||
| #: ../js/ui/panel.js:933 | ||||
| msgid "Top Bar" | ||||
| msgstr "Horná lišta" | ||||
|  | ||||
| @@ -1308,15 +1304,15 @@ 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:738 | ||||
| #: ../js/ui/popupMenu.js:727 | ||||
| msgid "toggle-switch-us" | ||||
| msgstr "toggle-switch-intl" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:74 | ||||
| #: ../js/ui/runDialog.js:73 | ||||
| msgid "Enter a Command" | ||||
| msgstr "Zadajte príkaz" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:110 | ||||
| #: ../js/ui/runDialog.js:109 | ||||
| msgid "Close" | ||||
| msgstr "Zavrieť" | ||||
|  | ||||
| @@ -1325,11 +1321,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:87 | ||||
| #: ../js/ui/screenShield.js:86 | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%A, %e. %B" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:152 | ||||
| #: ../js/ui/screenShield.js:151 | ||||
| #, c-format | ||||
| msgid "%d new notification" | ||||
| msgid_plural "%d new notifications" | ||||
| @@ -1337,11 +1333,11 @@ msgstr[0] "%d nových oznámení" | ||||
| msgstr[1] "%d nové oznámenie" | ||||
| msgstr[2] "%d nové oznámenia" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:449 ../js/ui/userMenu.js:807 | ||||
| #: ../js/ui/screenShield.js:438 ../js/ui/userMenu.js:807 | ||||
| msgid "Lock" | ||||
| msgstr "Uzamknúť" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:652 | ||||
| #: ../js/ui/screenShield.js:637 | ||||
| msgid "GNOME needs to lock the screen" | ||||
| msgstr "Prostredie GNOME vyžaduje uzamknutie obrazovky" | ||||
|  | ||||
| @@ -1352,11 +1348,11 @@ msgstr "Prostredie GNOME vyžaduje uzamknutie obrazovky" | ||||
| #. | ||||
| #. XXX: another option is to kick the user into the gdm login | ||||
| #. screen, where we're not affected by grabs | ||||
| #: ../js/ui/screenShield.js:773 ../js/ui/screenShield.js:1213 | ||||
| #: ../js/ui/screenShield.js:758 ../js/ui/screenShield.js:1194 | ||||
| msgid "Unable to lock" | ||||
| msgstr "Nepodarilo sa uzamknúť obrazovku" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:774 ../js/ui/screenShield.js:1214 | ||||
| #: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1195 | ||||
| msgid "Lock was blocked by an application" | ||||
| msgstr "Uzamknutie bolo zablokované aplikáciou" | ||||
|  | ||||
| @@ -1368,19 +1364,19 @@ msgstr "Hľadá sa…" | ||||
| msgid "No results." | ||||
| msgstr "Žiadne výsledky." | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:27 | ||||
| #: ../js/ui/shellEntry.js:29 | ||||
| msgid "Copy" | ||||
| msgstr "Kopírovať" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:32 | ||||
| #: ../js/ui/shellEntry.js:34 | ||||
| msgid "Paste" | ||||
| msgstr "Prilepiť" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:99 | ||||
| #: ../js/ui/shellEntry.js:106 | ||||
| msgid "Show Text" | ||||
| msgstr "Zobraziť text" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:101 | ||||
| #: ../js/ui/shellEntry.js:108 | ||||
| msgid "Hide Text" | ||||
| msgstr "Skryť text" | ||||
|  | ||||
| @@ -1392,7 +1388,7 @@ msgstr "Heslo" | ||||
| msgid "Remember Password" | ||||
| msgstr "Zapamätať heslo" | ||||
|  | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:109 | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:113 | ||||
| msgid "Unlock" | ||||
| msgstr "Odblokovať" | ||||
|  | ||||
| @@ -1450,7 +1446,7 @@ msgstr "Veľký text" | ||||
| #: ../js/ui/status/bluetooth.js:28 ../js/ui/status/bluetooth.js:32 | ||||
| #: ../js/ui/status/bluetooth.js:289 ../js/ui/status/bluetooth.js:321 | ||||
| #: ../js/ui/status/bluetooth.js:357 ../js/ui/status/bluetooth.js:388 | ||||
| #: ../js/ui/status/network.js:739 | ||||
| #: ../js/ui/status/network.js:826 | ||||
| msgid "Bluetooth" | ||||
| msgstr "Bluetooth" | ||||
|  | ||||
| @@ -1471,7 +1467,7 @@ msgid "Bluetooth Settings" | ||||
| msgstr "Nastavenia Bluetooth" | ||||
|  | ||||
| #. TRANSLATORS: this means that bluetooth was disabled by hardware rfkill | ||||
| #: ../js/ui/status/bluetooth.js:104 ../js/ui/status/network.js:142 | ||||
| #: ../js/ui/status/bluetooth.js:104 ../js/ui/status/network.js:178 | ||||
| msgid "hardware disabled" | ||||
| msgstr "hardvér zakázaný" | ||||
|  | ||||
| @@ -1479,12 +1475,12 @@ msgstr "hardvér zakázaný" | ||||
| msgid "Connection" | ||||
| msgstr "Pripojenie" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:208 ../js/ui/status/network.js:404 | ||||
| #: ../js/ui/status/bluetooth.js:208 ../js/ui/status/network.js:460 | ||||
| msgid "disconnecting..." | ||||
| msgstr "odpája sa…" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:410 | ||||
| #: ../js/ui/status/network.js:1343 | ||||
| #: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:466 | ||||
| #: ../js/ui/status/network.js:1546 | ||||
| msgid "connecting..." | ||||
| msgstr "pripája sa…" | ||||
|  | ||||
| @@ -1540,9 +1536,8 @@ msgstr "Zariadenie %s sa chce spárovať s týmto počítačom" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:366 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Please confirm whether the Passkey '%06d' matches the one on the device." | ||||
| msgstr "Prosím, potvrďte, či sa heslo „%06d“ zhoduje s tým na zariadení." | ||||
| msgid "Please confirm whether the PIN '%06d' matches the one on the device." | ||||
| msgstr "Prosím, potvrďte, či sa PIN „%06d“ zhoduje s tým na zariadení." | ||||
|  | ||||
| #. Translators: this is the verb, not the noun | ||||
| #: ../js/ui/status/bluetooth.js:369 | ||||
| @@ -1579,91 +1574,117 @@ msgid "Volume, network, battery" | ||||
| msgstr "Hlasitosť, sieť, batéria" | ||||
|  | ||||
| # zariadenie | ||||
| #: ../js/ui/status/network.js:75 | ||||
| #: ../js/ui/status/network.js:104 | ||||
| msgid "<unknown>" | ||||
| msgstr "<neznáme>" | ||||
|  | ||||
| #: ../js/ui/status/network.js:127 | ||||
| msgid "Wi-Fi" | ||||
| msgstr "Wi-Fi" | ||||
|  | ||||
| #. Translators: this indicates that wireless or wwan is disabled by hardware killswitch | ||||
| #: ../js/ui/status/network.js:164 | ||||
| #: ../js/ui/status/network.js:200 | ||||
| msgid "disabled" | ||||
| msgstr "zakázané" | ||||
|  | ||||
| #. Translators: this is for network devices that are physically present but are not | ||||
| #. under NetworkManager's control (and thus cannot be used in the menu) | ||||
| #: ../js/ui/status/network.js:402 | ||||
| #: ../js/ui/status/network.js:458 | ||||
| msgid "unmanaged" | ||||
| msgstr "nespravované" | ||||
|  | ||||
| #. Translators: this is for network connections that require some kind of key or password | ||||
| #: ../js/ui/status/network.js:413 ../js/ui/status/network.js:1346 | ||||
| #: ../js/ui/status/network.js:469 ../js/ui/status/network.js:1549 | ||||
| msgid "authentication required" | ||||
| msgstr "požaduje sa overenie totožnosti" | ||||
|  | ||||
| #. Translators: this is for devices that require some kind of firmware or kernel | ||||
| #. module, which is missing | ||||
| #: ../js/ui/status/network.js:423 | ||||
| #: ../js/ui/status/network.js:479 | ||||
| msgid "firmware missing" | ||||
| msgstr "chýba firmvér" | ||||
|  | ||||
| #. Translators: this is for wired network devices that are physically disconnected | ||||
| #: ../js/ui/status/network.js:430 | ||||
| #: ../js/ui/status/network.js:486 | ||||
| msgid "cable unplugged" | ||||
| msgstr "kábel odpojený" | ||||
|  | ||||
| #. Translators: this is for a network device that cannot be activated (for example it | ||||
| #. is disabled by rfkill, or it has no coverage | ||||
| #: ../js/ui/status/network.js:435 | ||||
| #: ../js/ui/status/network.js:491 | ||||
| msgid "unavailable" | ||||
| msgstr "nedostupné" | ||||
|  | ||||
| #: ../js/ui/status/network.js:437 ../js/ui/status/network.js:1348 | ||||
| #: ../js/ui/status/network.js:493 ../js/ui/status/network.js:1551 | ||||
| msgid "connection failed" | ||||
| msgstr "pripojenie zlyhalo" | ||||
|  | ||||
| #: ../js/ui/status/network.js:490 ../js/ui/status/network.js:1236 | ||||
| #: ../js/ui/status/network.js:1424 | ||||
| #: ../js/ui/status/network.js:552 ../js/ui/status/network.js:1435 | ||||
| #: ../js/ui/status/network.js:1627 | ||||
| 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:518 ../js/ui/status/network.js:1191 | ||||
| #: ../js/ui/status/network.js:588 ../js/ui/status/network.js:1365 | ||||
| msgid "Connected (private)" | ||||
| msgstr "Pripojené (súkromne)" | ||||
|  | ||||
| #: ../js/ui/status/network.js:597 | ||||
| #: ../js/ui/status/network.js:667 | ||||
| msgid "Wired" | ||||
| msgstr "Drôtové pripojenie" | ||||
|  | ||||
| #: ../js/ui/status/network.js:611 | ||||
| #: ../js/ui/status/network.js:668 | ||||
| msgid "Auto Ethernet" | ||||
| msgstr "Automatický ethernet" | ||||
|  | ||||
| #: ../js/ui/status/network.js:695 | ||||
| msgid "Mobile broadband" | ||||
| msgstr "Širokopásmové pripojenie" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1522 | ||||
| #: ../js/ui/status/network.js:728 | ||||
| msgid "Auto broadband" | ||||
| msgstr "Automatické širokopásmové pripojenie" | ||||
|  | ||||
| #: ../js/ui/status/network.js:731 | ||||
| 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:861 ../js/ui/status/network.js:1382 | ||||
| #, c-format | ||||
| msgid "Auto %s" | ||||
| msgstr "Automatické pripojenie %s" | ||||
|  | ||||
| #: ../js/ui/status/network.js:863 | ||||
| msgid "Auto bluetooth" | ||||
| msgstr "Automatický bluetooth" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1384 | ||||
| msgid "Auto wireless" | ||||
| msgstr "Automatická bezdrôtová sieť" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1729 | ||||
| msgid "Enable networking" | ||||
| msgstr "Povoliť sieť" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1583 | ||||
| #: ../js/ui/status/network.js:1771 | ||||
| msgid "Wi-Fi" | ||||
| msgstr "Wi-Fi" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1790 | ||||
| msgid "Network Settings" | ||||
| msgstr "Nastavenia siete" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1600 | ||||
| #: ../js/ui/status/network.js:1807 | ||||
| msgid "Network Manager" | ||||
| msgstr "Správca siete" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1690 | ||||
| #: ../js/ui/status/network.js:1897 | ||||
| msgid "Connection failed" | ||||
| msgstr "Pripojenie zlyhalo" | ||||
|  | ||||
| #: ../js/ui/status/network.js:1691 | ||||
| #: ../js/ui/status/network.js:1898 | ||||
| msgid "Activation of network connection failed" | ||||
| msgstr "Aktivácia pripojenia k sieti zlyhala" | ||||
|  | ||||
| #: ../js/ui/status/network.js:2047 | ||||
| #: ../js/ui/status/network.js:2276 | ||||
| msgid "Networking is disabled" | ||||
| msgstr "Sieť je zakázaná" | ||||
|  | ||||
| @@ -1781,11 +1802,11 @@ msgstr "Hlasitosť" | ||||
| msgid "Microphone" | ||||
| msgstr "Mikrofón" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:120 | ||||
| #: ../js/ui/unlockDialog.js:124 | ||||
| msgid "Log in as another user" | ||||
| msgstr "Prihlásiť ako iný používateľ" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:141 | ||||
| #: ../js/ui/unlockDialog.js:145 | ||||
| msgid "Unlock Window" | ||||
| msgstr "Odomykacie okno" | ||||
|  | ||||
| @@ -1894,56 +1915,32 @@ msgstr "Program „%s“ je pripravený" | ||||
| msgid "Evolution Calendar" | ||||
| msgstr "Kalendár Evolution" | ||||
|  | ||||
| #. 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] "%u výstupov" | ||||
| msgstr[1] "%u výstup" | ||||
| msgstr[2] "%u výstupy" | ||||
|  | ||||
| #. 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] "%u vstupov" | ||||
| msgstr[1] "%u vstup" | ||||
| msgstr[2] "%u vstupy" | ||||
|  | ||||
| #: ../src/gvc/gvc-mixer-control.c:2373 | ||||
| msgid "System Sounds" | ||||
| msgstr "Systémové zvuky" | ||||
|  | ||||
| #: ../src/main.c:372 | ||||
| #: ../src/main.c:347 | ||||
| msgid "Print version" | ||||
| msgstr "Verzia pre tlač" | ||||
|  | ||||
| #: ../src/main.c:378 | ||||
| #: ../src/main.c:353 | ||||
| msgid "Mode used by GDM for login screen" | ||||
| msgstr "Režim používaný GDM pre prihlasovaciu obrazovku" | ||||
|  | ||||
| #: ../src/main.c:384 | ||||
| #: ../src/main.c:359 | ||||
| msgid "Use a specific mode, e.g. \"gdm\" for login screen" | ||||
| msgstr "Použitie zvláštneho režimu, napr. „gdm“  pre prihlasovaciu obrazovku" | ||||
|  | ||||
| #: ../src/main.c:390 | ||||
| #: ../src/main.c:365 | ||||
| msgid "List possible modes" | ||||
| msgstr "Zoznam možných režimov" | ||||
|  | ||||
| #: ../src/shell-app.c:626 | ||||
| #: ../src/shell-app.c:622 | ||||
| #, c-format | ||||
| msgid "Failed to launch '%s'" | ||||
| msgstr "Zlyhalo spustenie „%s“" | ||||
|  | ||||
| #: ../src/shell-keyring-prompt.c:714 | ||||
| #: ../src/shell-keyring-prompt.c:708 | ||||
| msgid "Passwords do not match." | ||||
| msgstr "Heslá sa nezhodujú." | ||||
|  | ||||
| #: ../src/shell-keyring-prompt.c:722 | ||||
| #: ../src/shell-keyring-prompt.c:716 | ||||
| msgid "Password cannot be blank" | ||||
| msgstr "Heslo nemôže byť prázdne" | ||||
|  | ||||
| @@ -1951,35 +1948,3 @@ msgstr "Heslo nemôže byť prázdne" | ||||
| #: ../src/shell-polkit-authentication-agent.c:343 | ||||
| msgid "Authentication dialog was dismissed by the user" | ||||
| msgstr "Dialógové okno overenia totožnosti bolo zatvorené používateľom" | ||||
|  | ||||
| #~ msgid "Whether to collect stats about applications usage" | ||||
| #~ msgstr "Či sa majú zhromažďovať štatistické údaje o používaní aplikácií" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "The shell normally monitors active applications in order to present the " | ||||
| #~ "most used ones (e.g. in launchers). While this data will be kept private, " | ||||
| #~ "you may want to disable this for privacy reasons. Please note that doing " | ||||
| #~ "so won't remove already saved data." | ||||
| #~ msgstr "" | ||||
| #~ "Prostredie shell obvykle sleduje aktívne aplikácie, aby mohlo ponúkať " | ||||
| #~ "najpoužívanejšie z nich (napr. v spúšťačoch). Aj keď sú tieto údaje " | ||||
| #~ "uchovávané v tajnosti, môžete ich kvôli lepšej ochrane súkromia zakázať. " | ||||
| #~ "Ak tak urobíte, údaje, ktoré už boli uložené, zostanú zachované." | ||||
|  | ||||
| #~ msgid "Auto Ethernet" | ||||
| #~ msgstr "Automatický ethernet" | ||||
|  | ||||
| #~ msgid "Auto broadband" | ||||
| #~ msgstr "Automatické širokopásmové pripojenie" | ||||
|  | ||||
| #~ msgid "Auto dial-up" | ||||
| #~ msgstr "Automatické vytáčané pripojenie" | ||||
|  | ||||
| #~ msgid "Auto %s" | ||||
| #~ msgstr "Automatické pripojenie %s" | ||||
|  | ||||
| #~ msgid "Auto bluetooth" | ||||
| #~ msgstr "Automatický bluetooth" | ||||
|  | ||||
| #~ msgid "Auto wireless" | ||||
| #~ msgstr "Automatická bezdrôtová sieť" | ||||
|   | ||||
							
								
								
									
										163
									
								
								po/sr.po
									
									
									
									
									
								
							
							
						
						
									
										163
									
								
								po/sr.po
									
									
									
									
									
								
							| @@ -8,7 +8,7 @@ msgstr "" | ||||
| "Project-Id-Version: gnome-shell master\n" | ||||
| "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" | ||||
| "shell&keywords=I18N+L10N&component=general\n" | ||||
| "POT-Creation-Date: 2013-03-31 01:48+0000\n" | ||||
| "POT-Creation-Date: 2013-03-04 08:38+0000\n" | ||||
| "PO-Revision-Date: 2013-03-08 20:26+0200\n" | ||||
| "Last-Translator: Мирослав Николић <miroslavnikolic@rocketmail.com>\n" | ||||
| "Language-Team: Serbian <gnom@prevod.org>\n" | ||||
| @@ -16,8 +16,8 @@ msgstr "" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : n" | ||||
| "%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" | ||||
| "Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : " | ||||
| "n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" | ||||
| "X-Project-Style: gnome\n" | ||||
|  | ||||
| #: ../data/50-gnome-shell-screenshot.xml.in.h:1 | ||||
| @@ -365,52 +365,53 @@ msgid "Select an extension to configure using the combobox above." | ||||
| msgstr "Изаберите проширење за подешавање користећи прозорче за избор." | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:405 | ||||
| #| msgid "Session..." | ||||
| msgid "Session…" | ||||
| msgstr "Сесија…" | ||||
|  | ||||
| #. 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:630 | ||||
| #: ../js/gdm/loginDialog.js:629 | ||||
| msgid "Not listed?" | ||||
| msgstr "Није на списку?" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:786 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/gdm/loginDialog.js:783 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 | ||||
| #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:99 | ||||
| #: ../js/ui/userMenu.js:938 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:126 | ||||
| #: ../js/ui/userMenu.js:934 | ||||
| msgid "Cancel" | ||||
| msgstr "Откажи" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:802 | ||||
| #: ../js/gdm/loginDialog.js:799 | ||||
| msgctxt "button" | ||||
| msgid "Sign In" | ||||
| msgstr "Пријави ме" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:802 | ||||
| #: ../js/gdm/loginDialog.js:799 | ||||
| msgid "Next" | ||||
| msgstr "Даље" | ||||
|  | ||||
| #. 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:917 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/gdm/loginDialog.js:904 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/ui/components/networkAgent.js:278 | ||||
| msgid "Username: " | ||||
| msgstr "Корисничко име: " | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:1173 | ||||
| #: ../js/gdm/loginDialog.js:1157 | ||||
| msgid "Login Window" | ||||
| msgstr "Прозор за пријављивање" | ||||
|  | ||||
| #. Translators: accessible name of the power menu in the login screen | ||||
| #: ../js/gdm/powerMenu.js:36 | ||||
| msgid "Power" | ||||
| msgstr "Напајање" | ||||
| msgstr "Угаси" | ||||
|  | ||||
| #: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:696 ../js/ui/userMenu.js:700 | ||||
| #: ../js/ui/userMenu.js:816 | ||||
| #: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:695 ../js/ui/userMenu.js:699 | ||||
| #: ../js/ui/userMenu.js:815 | ||||
| msgid "Suspend" | ||||
| msgstr "Обустави" | ||||
|  | ||||
| @@ -418,58 +419,58 @@ msgstr "Обустави" | ||||
| msgid "Restart" | ||||
| msgstr "Поново покрени" | ||||
|  | ||||
| #: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:698 | ||||
| #: ../js/ui/userMenu.js:700 ../js/ui/userMenu.js:815 ../js/ui/userMenu.js:942 | ||||
| #: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:697 | ||||
| #: ../js/ui/userMenu.js:699 ../js/ui/userMenu.js:814 ../js/ui/userMenu.js:938 | ||||
| msgid "Power Off" | ||||
| msgstr "Искључи" | ||||
| msgstr "Угаси" | ||||
|  | ||||
| #: ../js/gdm/util.js:249 | ||||
| #: ../js/gdm/util.js:182 | ||||
| msgid "Authentication error" | ||||
| msgstr "Грешка потврђивања идентитета" | ||||
|  | ||||
| #. Translators: this message is shown below the password entry field | ||||
| #. to indicate the user can swipe their finger instead | ||||
| #: ../js/gdm/util.js:366 | ||||
| #: ../js/gdm/util.js:299 | ||||
| msgid "(or swipe finger)" | ||||
| msgstr "(или лупите прст)" | ||||
|  | ||||
| #: ../js/gdm/util.js:391 | ||||
| #: ../js/gdm/util.js:324 | ||||
| #, c-format | ||||
| msgid "(e.g., user or %s)" | ||||
| msgstr "(нпр., корисник или %s)" | ||||
|  | ||||
| #: ../js/misc/util.js:97 | ||||
| #: ../js/misc/util.js:94 | ||||
| msgid "Command not found" | ||||
| msgstr "Наредба није нађена" | ||||
|  | ||||
| #. Replace "Error invoking GLib.shell_parse_argv: " with | ||||
| #. something nicer | ||||
| #: ../js/misc/util.js:130 | ||||
| #: ../js/misc/util.js:127 | ||||
| msgid "Could not parse command:" | ||||
| msgstr "Не могу да обрадим наредбу:" | ||||
|  | ||||
| #: ../js/misc/util.js:138 | ||||
| #: ../js/misc/util.js:135 | ||||
| #, c-format | ||||
| msgid "Execution of '%s' failed:" | ||||
| msgstr "Није успело покретање „%s“:" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:349 | ||||
| #: ../js/ui/appDisplay.js:348 | ||||
| msgid "Frequent" | ||||
| msgstr "Често" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:356 | ||||
| #: ../js/ui/appDisplay.js:355 | ||||
| msgid "All" | ||||
| msgstr "Све" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:914 | ||||
| #: ../js/ui/appDisplay.js:913 | ||||
| msgid "New Window" | ||||
| msgstr "Нови прозор" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:917 ../js/ui/dash.js:284 | ||||
| #: ../js/ui/appDisplay.js:916 ../js/ui/dash.js:284 | ||||
| msgid "Remove from Favorites" | ||||
| msgstr "Уклони из омиљених" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:918 | ||||
| #: ../js/ui/appDisplay.js:917 | ||||
| msgid "Add to Favorites" | ||||
| msgstr "Додај у омиљене" | ||||
|  | ||||
| @@ -483,7 +484,7 @@ msgstr "„%s“ је додат међу омиљене." | ||||
| msgid "%s has been removed from your favorites." | ||||
| msgstr "„%s“ је уклоњен из омиљених." | ||||
|  | ||||
| #: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:789 | ||||
| #: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:788 | ||||
| msgid "Settings" | ||||
| msgstr "Подешавања" | ||||
|  | ||||
| @@ -506,7 +507,7 @@ msgctxt "event list time" | ||||
| msgid "%H\\u2236%M" | ||||
| msgstr "%H\\u2236%M" | ||||
|  | ||||
| #. Translators: Shown in calendar event list, if 12h format, | ||||
| #. Transators: Shown in calendar event list, if 12h format, | ||||
| #. \u2236 is a ratio character, similar to : and \u2009 is | ||||
| #. a thin space | ||||
| #: ../js/ui/calendar.js:77 | ||||
| @@ -608,35 +609,35 @@ msgid "S" | ||||
| msgstr "Суб" | ||||
|  | ||||
| #. Translators: Text to show if there are no events | ||||
| #: ../js/ui/calendar.js:720 | ||||
| #: ../js/ui/calendar.js:692 | ||||
| msgid "Nothing Scheduled" | ||||
| msgstr "Ништа планирано" | ||||
|  | ||||
| #. Translators: Shown on calendar heading when selected day occurs on current year | ||||
| #: ../js/ui/calendar.js:736 | ||||
| #: ../js/ui/calendar.js:708 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%A, %B %d" | ||||
|  | ||||
| #. Translators: Shown on calendar heading when selected day occurs on different year | ||||
| #: ../js/ui/calendar.js:739 | ||||
| #: ../js/ui/calendar.js:711 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d, %Y" | ||||
| msgstr "%A, %B %d, %Y" | ||||
|  | ||||
| #: ../js/ui/calendar.js:749 | ||||
| #: ../js/ui/calendar.js:721 | ||||
| msgid "Today" | ||||
| msgstr "Данас" | ||||
|  | ||||
| #: ../js/ui/calendar.js:753 | ||||
| #: ../js/ui/calendar.js:725 | ||||
| msgid "Tomorrow" | ||||
| msgstr "Сутра" | ||||
|  | ||||
| #: ../js/ui/calendar.js:764 | ||||
| #: ../js/ui/calendar.js:736 | ||||
| msgid "This week" | ||||
| msgstr "Ове недеље" | ||||
|  | ||||
| #: ../js/ui/calendar.js:772 | ||||
| #: ../js/ui/calendar.js:744 | ||||
| msgid "Next week" | ||||
| msgstr "Следеће недеље" | ||||
|  | ||||
| @@ -652,12 +653,12 @@ msgstr "Спољни уређај је искључен" | ||||
| msgid "Removable Devices" | ||||
| msgstr "Уклоњиви уређаји" | ||||
|  | ||||
| #: ../js/ui/components/autorunManager.js:594 | ||||
| #: ../js/ui/components/autorunManager.js:593 | ||||
| #, c-format | ||||
| msgid "Open with %s" | ||||
| msgstr "Отвори програмом %s" | ||||
|  | ||||
| #: ../js/ui/components/autorunManager.js:620 | ||||
| #: ../js/ui/components/autorunManager.js:619 | ||||
| msgid "Eject" | ||||
| msgstr "Избаци" | ||||
|  | ||||
| @@ -1037,7 +1038,7 @@ msgstr "Подешавања датума и времена" | ||||
| #. 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:215 | ||||
| #: ../js/ui/dateMenu.js:205 | ||||
| msgid "%A %B %e, %Y" | ||||
| msgstr "%A, %e. %b., %R" | ||||
|  | ||||
| @@ -1212,6 +1213,7 @@ msgid "Remove" | ||||
| msgstr "Уклони" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1501 | ||||
| #| msgid "No Messages" | ||||
| msgid "Clear Messages" | ||||
| msgstr "Очисти поруке" | ||||
|  | ||||
| @@ -1219,15 +1221,15 @@ msgstr "Очисти поруке" | ||||
| msgid "Notification Settings" | ||||
| msgstr "Поставке обавештења" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1709 | ||||
| #: ../js/ui/messageTray.js:1707 | ||||
| msgid "No Messages" | ||||
| msgstr "Нема порука" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1782 | ||||
| #: ../js/ui/messageTray.js:1787 | ||||
| msgid "Message Tray" | ||||
| msgstr "Фиока порука" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:2810 | ||||
| #: ../js/ui/messageTray.js:2864 | ||||
| msgid "System Information" | ||||
| msgstr "Подаци о систему" | ||||
|  | ||||
| @@ -1236,7 +1238,7 @@ msgctxt "program" | ||||
| msgid "Unknown" | ||||
| msgstr "Непознат" | ||||
|  | ||||
| #: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149 | ||||
| #: ../js/ui/overviewControls.js:460 ../js/ui/screenShield.js:153 | ||||
| #, c-format | ||||
| msgid "%d new message" | ||||
| msgid_plural "%d new messages" | ||||
| @@ -1245,7 +1247,7 @@ msgstr[1] "%d нове поруке" | ||||
| msgstr[2] "%d нових порука" | ||||
| msgstr[3] "Једна нова порука" | ||||
|  | ||||
| #: ../js/ui/overview.js:84 | ||||
| #: ../js/ui/overview.js:82 | ||||
| msgid "Undo" | ||||
| msgstr "Опозови" | ||||
|  | ||||
| @@ -1257,21 +1259,22 @@ msgstr "Преглед" | ||||
| #. in the search entry when no search is | ||||
| #. active; it should not exceed ~30 | ||||
| #. characters. | ||||
| #: ../js/ui/overview.js:271 | ||||
| #: ../js/ui/overview.js:284 | ||||
| #| msgid "Type to search..." | ||||
| msgid "Type to search…" | ||||
| msgstr "Упишите текст за претрагу…" | ||||
|  | ||||
| #: ../js/ui/panel.js:612 | ||||
| #: ../js/ui/panel.js:613 | ||||
| msgid "Quit" | ||||
| msgstr "Изађи" | ||||
|  | ||||
| #. Translators: If there is no suitable word for "Activities" | ||||
| #. in your language, you can use the word for "Overview". | ||||
| #: ../js/ui/panel.js:636 | ||||
| #: ../js/ui/panel.js:642 | ||||
| msgid "Activities" | ||||
| msgstr "Активности" | ||||
|  | ||||
| #: ../js/ui/panel.js:933 | ||||
| #: ../js/ui/panel.js:983 | ||||
| msgid "Top Bar" | ||||
| msgstr "Горња трака" | ||||
|  | ||||
| @@ -1284,21 +1287,21 @@ msgstr "Горња трака" | ||||
| msgid "toggle-switch-us" | ||||
| msgstr "toggle-switch-intl" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:73 | ||||
| #: ../js/ui/runDialog.js:205 | ||||
| msgid "Enter a Command" | ||||
| msgstr "Унесите наредбу" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:109 | ||||
| #: ../js/ui/runDialog.js:241 | ||||
| msgid "Close" | ||||
| msgstr "Затвори" | ||||
|  | ||||
| #. Translators: This is a time format for a date in | ||||
| #. long format | ||||
| #: ../js/ui/screenShield.js:86 | ||||
| #: ../js/ui/screenShield.js:90 | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%A, %d. %B" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:151 | ||||
| #: ../js/ui/screenShield.js:155 | ||||
| #, c-format | ||||
| msgid "%d new notification" | ||||
| msgid_plural "%d new notifications" | ||||
| @@ -1307,11 +1310,11 @@ msgstr[1] "%d нова обавештења" | ||||
| msgstr[2] "%d нових обавештења" | ||||
| msgstr[3] "Једно ново обавештење" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:438 ../js/ui/userMenu.js:807 | ||||
| #: ../js/ui/screenShield.js:442 ../js/ui/userMenu.js:806 | ||||
| msgid "Lock" | ||||
| msgstr "Закључај" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:640 | ||||
| #: ../js/ui/screenShield.js:639 | ||||
| msgid "GNOME needs to lock the screen" | ||||
| msgstr "Гном мора да закључа екран" | ||||
|  | ||||
| @@ -1322,19 +1325,21 @@ msgstr "Гном мора да закључа екран" | ||||
| #. | ||||
| #. XXX: another option is to kick the user into the gdm login | ||||
| #. screen, where we're not affected by grabs | ||||
| #: ../js/ui/screenShield.js:761 ../js/ui/screenShield.js:1197 | ||||
| #: ../js/ui/screenShield.js:758 ../js/ui/screenShield.js:1169 | ||||
| #| msgid "Unable to connect to %s" | ||||
| msgid "Unable to lock" | ||||
| msgstr "Не могу да закључам" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:762 ../js/ui/screenShield.js:1198 | ||||
| #: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1170 | ||||
| msgid "Lock was blocked by an application" | ||||
| msgstr "Неки програм је блокирао закључавање" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:453 | ||||
| #: ../js/ui/searchDisplay.js:431 | ||||
| #| msgid "Searching..." | ||||
| msgid "Searching…" | ||||
| msgstr "Тражим…" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:497 | ||||
| #: ../js/ui/searchDisplay.js:475 | ||||
| msgid "No results." | ||||
| msgstr "Нема одговарајућих резултата." | ||||
|  | ||||
| @@ -1346,11 +1351,11 @@ msgstr "Умножи" | ||||
| msgid "Paste" | ||||
| msgstr "Убаци" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:106 | ||||
| #: ../js/ui/shellEntry.js:105 | ||||
| msgid "Show Text" | ||||
| msgstr "Прикажи текст" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:108 | ||||
| #: ../js/ui/shellEntry.js:107 | ||||
| msgid "Hide Text" | ||||
| msgstr "Сакриј текст" | ||||
|  | ||||
| @@ -1362,7 +1367,7 @@ msgstr "Лозинка" | ||||
| msgid "Remember Password" | ||||
| msgstr "Запамти лозинку" | ||||
|  | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:113 | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:140 | ||||
| msgid "Unlock" | ||||
| msgstr "Откључај" | ||||
|  | ||||
| @@ -1426,10 +1431,12 @@ msgid "Visibility" | ||||
| msgstr "Видљивост" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:59 | ||||
| #| msgid "Send Files to Device..." | ||||
| msgid "Send Files to Device…" | ||||
| msgstr "Пошаљи датотеке на уређај…" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:60 | ||||
| #| msgid "Set Up a New Device..." | ||||
| msgid "Set Up a New Device…" | ||||
| msgstr "Подеси нови уређај…" | ||||
|  | ||||
| @@ -1456,6 +1463,7 @@ msgid "connecting..." | ||||
| msgstr "повезујем се..." | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:239 | ||||
| #| msgid "Send Files..." | ||||
| msgid "Send Files…" | ||||
| msgstr "Пошаљи датотеке…" | ||||
|  | ||||
| @@ -1668,6 +1676,7 @@ msgstr "Подешавања напајања" | ||||
| #. 0 is reported when UPower does not have enough data | ||||
| #. to estimate battery life | ||||
| #: ../js/ui/status/power.js:99 | ||||
| #| msgid "Estimating..." | ||||
| msgid "Estimating…" | ||||
| msgstr "Приближно…" | ||||
|  | ||||
| @@ -1775,11 +1784,11 @@ msgstr "Јачина звука" | ||||
| msgid "Microphone" | ||||
| msgstr "Микрофон" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:124 | ||||
| #: ../js/ui/unlockDialog.js:151 | ||||
| msgid "Log in as another user" | ||||
| msgstr "Пријавите се као други корсник" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:145 | ||||
| #: ../js/ui/unlockDialog.js:177 | ||||
| msgid "Unlock Window" | ||||
| msgstr "Откључај прозор" | ||||
|  | ||||
| @@ -1807,27 +1816,27 @@ msgstr "Мирује" | ||||
| msgid "Offline" | ||||
| msgstr "Ван мреже" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:781 | ||||
| #: ../js/ui/userMenu.js:780 | ||||
| msgid "Notifications" | ||||
| msgstr "Обавештења" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:797 | ||||
| #: ../js/ui/userMenu.js:796 | ||||
| msgid "Switch User" | ||||
| msgstr "Промени корисника" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:802 | ||||
| #: ../js/ui/userMenu.js:801 | ||||
| msgid "Log Out" | ||||
| msgstr "Одјави ме" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:822 | ||||
| #: ../js/ui/userMenu.js:821 | ||||
| msgid "Install Updates & Restart" | ||||
| msgstr "Инсталирај ажурирања и поново покрени" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:840 | ||||
| #: ../js/ui/userMenu.js:839 | ||||
| msgid "Your chat status will be set to busy" | ||||
| msgstr "Ваше стање ћаскања ће бити постављено на заузето" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:841 | ||||
| #: ../js/ui/userMenu.js:840 | ||||
| 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." | ||||
| @@ -1836,22 +1845,20 @@ msgstr "" | ||||
| "мрежи је подешено тако да ће остали знати да ви не можете видети њихове " | ||||
| "поруке." | ||||
|  | ||||
| #: ../js/ui/userMenu.js:888 | ||||
| #: ../js/ui/userMenu.js:886 | ||||
| msgid "Other users are logged in." | ||||
| msgstr "Други корисници су пријављени." | ||||
|  | ||||
| #: ../js/ui/userMenu.js:893 | ||||
| #: ../js/ui/userMenu.js:891 | ||||
| msgid "Shutting down might cause them to lose unsaved work." | ||||
| msgstr "Искључивање може да доведе до тога да изгубе несачувани рад." | ||||
|  | ||||
| #. Translators: Remote here refers to a remote session, like a ssh login | ||||
| #: ../js/ui/userMenu.js:921 | ||||
| #: ../js/ui/userMenu.js:918 | ||||
| #, c-format | ||||
| msgid "%s (remote)" | ||||
| msgstr "%s (удаљено)" | ||||
|  | ||||
| #. Translators: Console here refers to a tty like a VT console | ||||
| #: ../js/ui/userMenu.js:924 | ||||
| #: ../js/ui/userMenu.js:920 | ||||
| #, c-format | ||||
| msgid "%s (console)" | ||||
| msgstr "%s (љуска)" | ||||
| @@ -1864,7 +1871,7 @@ msgstr "Програми" | ||||
| msgid "Search" | ||||
| msgstr "Тражи" | ||||
|  | ||||
| #: ../js/ui/wanda.js:77 | ||||
| #: ../js/ui/wanda.js:92 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Sorry, no wisdom for you today:\n" | ||||
| @@ -1873,7 +1880,7 @@ msgstr "" | ||||
| "Извините, данас за вас нема мудрости:\n" | ||||
| "%s" | ||||
|  | ||||
| #: ../js/ui/wanda.js:81 | ||||
| #: ../js/ui/wanda.js:96 | ||||
| #, c-format | ||||
| msgid "%s the Oracle says" | ||||
| msgstr "Пророк је рекао %s" | ||||
|   | ||||
							
								
								
									
										163
									
								
								po/sr@latin.po
									
									
									
									
									
								
							
							
						
						
									
										163
									
								
								po/sr@latin.po
									
									
									
									
									
								
							| @@ -8,7 +8,7 @@ msgstr "" | ||||
| "Project-Id-Version: gnome-shell master\n" | ||||
| "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" | ||||
| "shell&keywords=I18N+L10N&component=general\n" | ||||
| "POT-Creation-Date: 2013-03-31 01:48+0000\n" | ||||
| "POT-Creation-Date: 2013-03-04 08:38+0000\n" | ||||
| "PO-Revision-Date: 2013-03-08 20:26+0200\n" | ||||
| "Last-Translator: Miroslav Nikolić <miroslavnikolic@rocketmail.com>\n" | ||||
| "Language-Team: Serbian <gnom@prevod.org>\n" | ||||
| @@ -16,8 +16,8 @@ msgstr "" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : n" | ||||
| "%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" | ||||
| "Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : " | ||||
| "n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" | ||||
| "X-Project-Style: gnome\n" | ||||
|  | ||||
| #: ../data/50-gnome-shell-screenshot.xml.in.h:1 | ||||
| @@ -365,52 +365,53 @@ msgid "Select an extension to configure using the combobox above." | ||||
| msgstr "Izaberite proširenje za podešavanje koristeći prozorče za izbor." | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:405 | ||||
| #| msgid "Session..." | ||||
| msgid "Session…" | ||||
| msgstr "Sesija…" | ||||
|  | ||||
| #. 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:630 | ||||
| #: ../js/gdm/loginDialog.js:629 | ||||
| msgid "Not listed?" | ||||
| msgstr "Nije na spisku?" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:786 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/gdm/loginDialog.js:783 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 | ||||
| #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:99 | ||||
| #: ../js/ui/userMenu.js:938 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:126 | ||||
| #: ../js/ui/userMenu.js:934 | ||||
| msgid "Cancel" | ||||
| msgstr "Otkaži" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:802 | ||||
| #: ../js/gdm/loginDialog.js:799 | ||||
| msgctxt "button" | ||||
| msgid "Sign In" | ||||
| msgstr "Prijavi me" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:802 | ||||
| #: ../js/gdm/loginDialog.js:799 | ||||
| msgid "Next" | ||||
| msgstr "Dalje" | ||||
|  | ||||
| #. 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:917 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/gdm/loginDialog.js:904 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/ui/components/networkAgent.js:278 | ||||
| msgid "Username: " | ||||
| msgstr "Korisničko ime: " | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:1173 | ||||
| #: ../js/gdm/loginDialog.js:1157 | ||||
| msgid "Login Window" | ||||
| msgstr "Prozor za prijavljivanje" | ||||
|  | ||||
| #. Translators: accessible name of the power menu in the login screen | ||||
| #: ../js/gdm/powerMenu.js:36 | ||||
| msgid "Power" | ||||
| msgstr "Napajanje" | ||||
| msgstr "Ugasi" | ||||
|  | ||||
| #: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:696 ../js/ui/userMenu.js:700 | ||||
| #: ../js/ui/userMenu.js:816 | ||||
| #: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:695 ../js/ui/userMenu.js:699 | ||||
| #: ../js/ui/userMenu.js:815 | ||||
| msgid "Suspend" | ||||
| msgstr "Obustavi" | ||||
|  | ||||
| @@ -418,58 +419,58 @@ msgstr "Obustavi" | ||||
| msgid "Restart" | ||||
| msgstr "Ponovo pokreni" | ||||
|  | ||||
| #: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:698 | ||||
| #: ../js/ui/userMenu.js:700 ../js/ui/userMenu.js:815 ../js/ui/userMenu.js:942 | ||||
| #: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:697 | ||||
| #: ../js/ui/userMenu.js:699 ../js/ui/userMenu.js:814 ../js/ui/userMenu.js:938 | ||||
| msgid "Power Off" | ||||
| msgstr "Isključi" | ||||
| msgstr "Ugasi" | ||||
|  | ||||
| #: ../js/gdm/util.js:249 | ||||
| #: ../js/gdm/util.js:182 | ||||
| msgid "Authentication error" | ||||
| msgstr "Greška potvrđivanja identiteta" | ||||
|  | ||||
| #. Translators: this message is shown below the password entry field | ||||
| #. to indicate the user can swipe their finger instead | ||||
| #: ../js/gdm/util.js:366 | ||||
| #: ../js/gdm/util.js:299 | ||||
| msgid "(or swipe finger)" | ||||
| msgstr "(ili lupite prst)" | ||||
|  | ||||
| #: ../js/gdm/util.js:391 | ||||
| #: ../js/gdm/util.js:324 | ||||
| #, c-format | ||||
| msgid "(e.g., user or %s)" | ||||
| msgstr "(npr., korisnik ili %s)" | ||||
|  | ||||
| #: ../js/misc/util.js:97 | ||||
| #: ../js/misc/util.js:94 | ||||
| msgid "Command not found" | ||||
| msgstr "Naredba nije nađena" | ||||
|  | ||||
| #. Replace "Error invoking GLib.shell_parse_argv: " with | ||||
| #. something nicer | ||||
| #: ../js/misc/util.js:130 | ||||
| #: ../js/misc/util.js:127 | ||||
| msgid "Could not parse command:" | ||||
| msgstr "Ne mogu da obradim naredbu:" | ||||
|  | ||||
| #: ../js/misc/util.js:138 | ||||
| #: ../js/misc/util.js:135 | ||||
| #, c-format | ||||
| msgid "Execution of '%s' failed:" | ||||
| msgstr "Nije uspelo pokretanje „%s“:" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:349 | ||||
| #: ../js/ui/appDisplay.js:348 | ||||
| msgid "Frequent" | ||||
| msgstr "Često" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:356 | ||||
| #: ../js/ui/appDisplay.js:355 | ||||
| msgid "All" | ||||
| msgstr "Sve" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:914 | ||||
| #: ../js/ui/appDisplay.js:913 | ||||
| msgid "New Window" | ||||
| msgstr "Novi prozor" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:917 ../js/ui/dash.js:284 | ||||
| #: ../js/ui/appDisplay.js:916 ../js/ui/dash.js:284 | ||||
| msgid "Remove from Favorites" | ||||
| msgstr "Ukloni iz omiljenih" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:918 | ||||
| #: ../js/ui/appDisplay.js:917 | ||||
| msgid "Add to Favorites" | ||||
| msgstr "Dodaj u omiljene" | ||||
|  | ||||
| @@ -483,7 +484,7 @@ msgstr "„%s“ je dodat među omiljene." | ||||
| msgid "%s has been removed from your favorites." | ||||
| msgstr "„%s“ je uklonjen iz omiljenih." | ||||
|  | ||||
| #: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:789 | ||||
| #: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:788 | ||||
| msgid "Settings" | ||||
| msgstr "Podešavanja" | ||||
|  | ||||
| @@ -506,7 +507,7 @@ msgctxt "event list time" | ||||
| msgid "%H\\u2236%M" | ||||
| msgstr "%H\\u2236%M" | ||||
|  | ||||
| #. Translators: Shown in calendar event list, if 12h format, | ||||
| #. Transators: Shown in calendar event list, if 12h format, | ||||
| #. \u2236 is a ratio character, similar to : and \u2009 is | ||||
| #. a thin space | ||||
| #: ../js/ui/calendar.js:77 | ||||
| @@ -608,35 +609,35 @@ msgid "S" | ||||
| msgstr "Sub" | ||||
|  | ||||
| #. Translators: Text to show if there are no events | ||||
| #: ../js/ui/calendar.js:720 | ||||
| #: ../js/ui/calendar.js:692 | ||||
| msgid "Nothing Scheduled" | ||||
| msgstr "Ništa planirano" | ||||
|  | ||||
| #. Translators: Shown on calendar heading when selected day occurs on current year | ||||
| #: ../js/ui/calendar.js:736 | ||||
| #: ../js/ui/calendar.js:708 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%A, %B %d" | ||||
|  | ||||
| #. Translators: Shown on calendar heading when selected day occurs on different year | ||||
| #: ../js/ui/calendar.js:739 | ||||
| #: ../js/ui/calendar.js:711 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d, %Y" | ||||
| msgstr "%A, %B %d, %Y" | ||||
|  | ||||
| #: ../js/ui/calendar.js:749 | ||||
| #: ../js/ui/calendar.js:721 | ||||
| msgid "Today" | ||||
| msgstr "Danas" | ||||
|  | ||||
| #: ../js/ui/calendar.js:753 | ||||
| #: ../js/ui/calendar.js:725 | ||||
| msgid "Tomorrow" | ||||
| msgstr "Sutra" | ||||
|  | ||||
| #: ../js/ui/calendar.js:764 | ||||
| #: ../js/ui/calendar.js:736 | ||||
| msgid "This week" | ||||
| msgstr "Ove nedelje" | ||||
|  | ||||
| #: ../js/ui/calendar.js:772 | ||||
| #: ../js/ui/calendar.js:744 | ||||
| msgid "Next week" | ||||
| msgstr "Sledeće nedelje" | ||||
|  | ||||
| @@ -652,12 +653,12 @@ msgstr "Spoljni uređaj je isključen" | ||||
| msgid "Removable Devices" | ||||
| msgstr "Uklonjivi uređaji" | ||||
|  | ||||
| #: ../js/ui/components/autorunManager.js:594 | ||||
| #: ../js/ui/components/autorunManager.js:593 | ||||
| #, c-format | ||||
| msgid "Open with %s" | ||||
| msgstr "Otvori programom %s" | ||||
|  | ||||
| #: ../js/ui/components/autorunManager.js:620 | ||||
| #: ../js/ui/components/autorunManager.js:619 | ||||
| msgid "Eject" | ||||
| msgstr "Izbaci" | ||||
|  | ||||
| @@ -1037,7 +1038,7 @@ msgstr "Podešavanja datuma i vremena" | ||||
| #. 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:215 | ||||
| #: ../js/ui/dateMenu.js:205 | ||||
| msgid "%A %B %e, %Y" | ||||
| msgstr "%A, %e. %b., %R" | ||||
|  | ||||
| @@ -1212,6 +1213,7 @@ msgid "Remove" | ||||
| msgstr "Ukloni" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1501 | ||||
| #| msgid "No Messages" | ||||
| msgid "Clear Messages" | ||||
| msgstr "Očisti poruke" | ||||
|  | ||||
| @@ -1219,15 +1221,15 @@ msgstr "Očisti poruke" | ||||
| msgid "Notification Settings" | ||||
| msgstr "Postavke obaveštenja" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1709 | ||||
| #: ../js/ui/messageTray.js:1707 | ||||
| msgid "No Messages" | ||||
| msgstr "Nema poruka" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1782 | ||||
| #: ../js/ui/messageTray.js:1787 | ||||
| msgid "Message Tray" | ||||
| msgstr "Fioka poruka" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:2810 | ||||
| #: ../js/ui/messageTray.js:2864 | ||||
| msgid "System Information" | ||||
| msgstr "Podaci o sistemu" | ||||
|  | ||||
| @@ -1236,7 +1238,7 @@ msgctxt "program" | ||||
| msgid "Unknown" | ||||
| msgstr "Nepoznat" | ||||
|  | ||||
| #: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149 | ||||
| #: ../js/ui/overviewControls.js:460 ../js/ui/screenShield.js:153 | ||||
| #, c-format | ||||
| msgid "%d new message" | ||||
| msgid_plural "%d new messages" | ||||
| @@ -1245,7 +1247,7 @@ msgstr[1] "%d nove poruke" | ||||
| msgstr[2] "%d novih poruka" | ||||
| msgstr[3] "Jedna nova poruka" | ||||
|  | ||||
| #: ../js/ui/overview.js:84 | ||||
| #: ../js/ui/overview.js:82 | ||||
| msgid "Undo" | ||||
| msgstr "Opozovi" | ||||
|  | ||||
| @@ -1257,21 +1259,22 @@ msgstr "Pregled" | ||||
| #. in the search entry when no search is | ||||
| #. active; it should not exceed ~30 | ||||
| #. characters. | ||||
| #: ../js/ui/overview.js:271 | ||||
| #: ../js/ui/overview.js:284 | ||||
| #| msgid "Type to search..." | ||||
| msgid "Type to search…" | ||||
| msgstr "Upišite tekst za pretragu…" | ||||
|  | ||||
| #: ../js/ui/panel.js:612 | ||||
| #: ../js/ui/panel.js:613 | ||||
| msgid "Quit" | ||||
| msgstr "Izađi" | ||||
|  | ||||
| #. Translators: If there is no suitable word for "Activities" | ||||
| #. in your language, you can use the word for "Overview". | ||||
| #: ../js/ui/panel.js:636 | ||||
| #: ../js/ui/panel.js:642 | ||||
| msgid "Activities" | ||||
| msgstr "Aktivnosti" | ||||
|  | ||||
| #: ../js/ui/panel.js:933 | ||||
| #: ../js/ui/panel.js:983 | ||||
| msgid "Top Bar" | ||||
| msgstr "Gornja traka" | ||||
|  | ||||
| @@ -1284,21 +1287,21 @@ msgstr "Gornja traka" | ||||
| msgid "toggle-switch-us" | ||||
| msgstr "toggle-switch-intl" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:73 | ||||
| #: ../js/ui/runDialog.js:205 | ||||
| msgid "Enter a Command" | ||||
| msgstr "Unesite naredbu" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:109 | ||||
| #: ../js/ui/runDialog.js:241 | ||||
| msgid "Close" | ||||
| msgstr "Zatvori" | ||||
|  | ||||
| #. Translators: This is a time format for a date in | ||||
| #. long format | ||||
| #: ../js/ui/screenShield.js:86 | ||||
| #: ../js/ui/screenShield.js:90 | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%A, %d. %B" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:151 | ||||
| #: ../js/ui/screenShield.js:155 | ||||
| #, c-format | ||||
| msgid "%d new notification" | ||||
| msgid_plural "%d new notifications" | ||||
| @@ -1307,11 +1310,11 @@ msgstr[1] "%d nova obaveštenja" | ||||
| msgstr[2] "%d novih obaveštenja" | ||||
| msgstr[3] "Jedno novo obaveštenje" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:438 ../js/ui/userMenu.js:807 | ||||
| #: ../js/ui/screenShield.js:442 ../js/ui/userMenu.js:806 | ||||
| msgid "Lock" | ||||
| msgstr "Zaključaj" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:640 | ||||
| #: ../js/ui/screenShield.js:639 | ||||
| msgid "GNOME needs to lock the screen" | ||||
| msgstr "Gnom mora da zaključa ekran" | ||||
|  | ||||
| @@ -1322,19 +1325,21 @@ msgstr "Gnom mora da zaključa ekran" | ||||
| #. | ||||
| #. XXX: another option is to kick the user into the gdm login | ||||
| #. screen, where we're not affected by grabs | ||||
| #: ../js/ui/screenShield.js:761 ../js/ui/screenShield.js:1197 | ||||
| #: ../js/ui/screenShield.js:758 ../js/ui/screenShield.js:1169 | ||||
| #| msgid "Unable to connect to %s" | ||||
| msgid "Unable to lock" | ||||
| msgstr "Ne mogu da zaključam" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:762 ../js/ui/screenShield.js:1198 | ||||
| #: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1170 | ||||
| msgid "Lock was blocked by an application" | ||||
| msgstr "Neki program je blokirao zaključavanje" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:453 | ||||
| #: ../js/ui/searchDisplay.js:431 | ||||
| #| msgid "Searching..." | ||||
| msgid "Searching…" | ||||
| msgstr "Tražim…" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:497 | ||||
| #: ../js/ui/searchDisplay.js:475 | ||||
| msgid "No results." | ||||
| msgstr "Nema odgovarajućih rezultata." | ||||
|  | ||||
| @@ -1346,11 +1351,11 @@ msgstr "Umnoži" | ||||
| msgid "Paste" | ||||
| msgstr "Ubaci" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:106 | ||||
| #: ../js/ui/shellEntry.js:105 | ||||
| msgid "Show Text" | ||||
| msgstr "Prikaži tekst" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:108 | ||||
| #: ../js/ui/shellEntry.js:107 | ||||
| msgid "Hide Text" | ||||
| msgstr "Sakrij tekst" | ||||
|  | ||||
| @@ -1362,7 +1367,7 @@ msgstr "Lozinka" | ||||
| msgid "Remember Password" | ||||
| msgstr "Zapamti lozinku" | ||||
|  | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:113 | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:140 | ||||
| msgid "Unlock" | ||||
| msgstr "Otključaj" | ||||
|  | ||||
| @@ -1426,10 +1431,12 @@ msgid "Visibility" | ||||
| msgstr "Vidljivost" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:59 | ||||
| #| msgid "Send Files to Device..." | ||||
| msgid "Send Files to Device…" | ||||
| msgstr "Pošalji datoteke na uređaj…" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:60 | ||||
| #| msgid "Set Up a New Device..." | ||||
| msgid "Set Up a New Device…" | ||||
| msgstr "Podesi novi uređaj…" | ||||
|  | ||||
| @@ -1456,6 +1463,7 @@ msgid "connecting..." | ||||
| msgstr "povezujem se..." | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:239 | ||||
| #| msgid "Send Files..." | ||||
| msgid "Send Files…" | ||||
| msgstr "Pošalji datoteke…" | ||||
|  | ||||
| @@ -1668,6 +1676,7 @@ msgstr "Podešavanja napajanja" | ||||
| #. 0 is reported when UPower does not have enough data | ||||
| #. to estimate battery life | ||||
| #: ../js/ui/status/power.js:99 | ||||
| #| msgid "Estimating..." | ||||
| msgid "Estimating…" | ||||
| msgstr "Približno…" | ||||
|  | ||||
| @@ -1775,11 +1784,11 @@ msgstr "Jačina zvuka" | ||||
| msgid "Microphone" | ||||
| msgstr "Mikrofon" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:124 | ||||
| #: ../js/ui/unlockDialog.js:151 | ||||
| msgid "Log in as another user" | ||||
| msgstr "Prijavite se kao drugi korsnik" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:145 | ||||
| #: ../js/ui/unlockDialog.js:177 | ||||
| msgid "Unlock Window" | ||||
| msgstr "Otključaj prozor" | ||||
|  | ||||
| @@ -1807,27 +1816,27 @@ msgstr "Miruje" | ||||
| msgid "Offline" | ||||
| msgstr "Van mreže" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:781 | ||||
| #: ../js/ui/userMenu.js:780 | ||||
| msgid "Notifications" | ||||
| msgstr "Obaveštenja" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:797 | ||||
| #: ../js/ui/userMenu.js:796 | ||||
| msgid "Switch User" | ||||
| msgstr "Promeni korisnika" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:802 | ||||
| #: ../js/ui/userMenu.js:801 | ||||
| msgid "Log Out" | ||||
| msgstr "Odjavi me" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:822 | ||||
| #: ../js/ui/userMenu.js:821 | ||||
| msgid "Install Updates & Restart" | ||||
| msgstr "Instaliraj ažuriranja i ponovo pokreni" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:840 | ||||
| #: ../js/ui/userMenu.js:839 | ||||
| msgid "Your chat status will be set to busy" | ||||
| msgstr "Vaše stanje ćaskanja će biti postavljeno na zauzeto" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:841 | ||||
| #: ../js/ui/userMenu.js:840 | ||||
| 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." | ||||
| @@ -1836,22 +1845,20 @@ msgstr "" | ||||
| "mreži je podešeno tako da će ostali znati da vi ne možete videti njihove " | ||||
| "poruke." | ||||
|  | ||||
| #: ../js/ui/userMenu.js:888 | ||||
| #: ../js/ui/userMenu.js:886 | ||||
| msgid "Other users are logged in." | ||||
| msgstr "Drugi korisnici su prijavljeni." | ||||
|  | ||||
| #: ../js/ui/userMenu.js:893 | ||||
| #: ../js/ui/userMenu.js:891 | ||||
| msgid "Shutting down might cause them to lose unsaved work." | ||||
| msgstr "Isključivanje može da dovede do toga da izgube nesačuvani rad." | ||||
|  | ||||
| #. Translators: Remote here refers to a remote session, like a ssh login | ||||
| #: ../js/ui/userMenu.js:921 | ||||
| #: ../js/ui/userMenu.js:918 | ||||
| #, c-format | ||||
| msgid "%s (remote)" | ||||
| msgstr "%s (udaljeno)" | ||||
|  | ||||
| #. Translators: Console here refers to a tty like a VT console | ||||
| #: ../js/ui/userMenu.js:924 | ||||
| #: ../js/ui/userMenu.js:920 | ||||
| #, c-format | ||||
| msgid "%s (console)" | ||||
| msgstr "%s (ljuska)" | ||||
| @@ -1864,7 +1871,7 @@ msgstr "Programi" | ||||
| msgid "Search" | ||||
| msgstr "Traži" | ||||
|  | ||||
| #: ../js/ui/wanda.js:77 | ||||
| #: ../js/ui/wanda.js:92 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Sorry, no wisdom for you today:\n" | ||||
| @@ -1873,7 +1880,7 @@ msgstr "" | ||||
| "Izvinite, danas za vas nema mudrosti:\n" | ||||
| "%s" | ||||
|  | ||||
| #: ../js/ui/wanda.js:81 | ||||
| #: ../js/ui/wanda.js:96 | ||||
| #, c-format | ||||
| msgid "%s the Oracle says" | ||||
| msgstr "Prorok je rekao %s" | ||||
|   | ||||
							
								
								
									
										442
									
								
								po/vi.po
									
									
									
									
									
								
							
							
						
						
									
										442
									
								
								po/vi.po
									
									
									
									
									
								
							| @@ -1,19 +1,18 @@ | ||||
| # Vietnamese translation for gnome-shell. | ||||
| # Copyright (C) 2013 GNOME i18n Project for Vietnamese. | ||||
| # Copyright (C) 2010 GNOME i18n Project for Vietnamese. | ||||
| # This file is distributed under the same license as the gnome-shell package. | ||||
| # Nguyễn Thái Ngọc Duy <pclouds@gmail.com>, 2010-2013. | ||||
| # Ngô Chin <ndtrung4419@gmail.com>, 2011. | ||||
| # Trần Ngọc Quân <vnwildman@gmail.com>, 2013. | ||||
| # | ||||
| msgid "" | ||||
| 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-03-23 11:49+0000\n" | ||||
| "PO-Revision-Date: 2013-04-13 17:51+1000\n" | ||||
| "Last-Translator: Trần Ngọc Quân <vnwildman@gmail.com>\n" | ||||
| "Language-Team: Vietnamese <translation-team-vi@lists.sourceforge.net>\n" | ||||
| "POT-Creation-Date: 2013-03-02 23:02+0000\n" | ||||
| "PO-Revision-Date: 2013-03-03 11:13+0700\n" | ||||
| "Last-Translator: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n" | ||||
| "Language-Team: Vietnamese <vi-VN@googlegroups.com>\n" | ||||
| "Language: vi\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| @@ -50,7 +49,7 @@ msgstr "Mở trình đơn ứng dụng" | ||||
|  | ||||
| #: ../data/gnome-shell.desktop.in.in.h:1 | ||||
| msgid "GNOME Shell" | ||||
| msgstr "Hệ vỏ GNOME" | ||||
| msgstr "GNOME Shell" | ||||
|  | ||||
| #: ../data/gnome-shell.desktop.in.in.h:2 | ||||
| msgid "Window management and application launching" | ||||
| @@ -59,11 +58,11 @@ msgstr "Quản lý cửa sổ và chạy ứng dụng" | ||||
| #: ../data/gnome-shell-extension-prefs.desktop.in.in.h:1 | ||||
| #: ../js/extensionPrefs/main.js:153 | ||||
| msgid "GNOME Shell Extension Preferences" | ||||
| msgstr "Cá nhân hóa phần mở rộng hệ vỏ GNOME" | ||||
| msgstr "Tuỳ thích phần mở rộng GNOME Shell" | ||||
|  | ||||
| #: ../data/gnome-shell-extension-prefs.desktop.in.in.h:2 | ||||
| msgid "Configure GNOME Shell Extensions" | ||||
| msgstr "Cấu hình phần mở rộng Hệ vỏ GNOME" | ||||
| msgstr "Cấu hình phần mở rộng GNOME Shell" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:1 | ||||
| msgid "Enable internal tools useful for developers and testers from Alt-F2" | ||||
| @@ -88,7 +87,7 @@ msgid "" | ||||
| "list. You can also manipulate this list with the EnableExtension and " | ||||
| "DisableExtension DBus methods on org.gnome.Shell." | ||||
| msgstr "" | ||||
| "Phần mở rộng Hệ vỏ GNOME có thuộc tính uuid; khóa này liệt kê danh sách phần " | ||||
| "Phần mở rộng GNOME Shell có thuộc tính uuid. Khoá này liệt kê danh sách phần " | ||||
| "mở rộng nên nạp. Bất kỳ phần mở rộng nào muốn nạp phải nằm trong danh sách " | ||||
| "này. Bạn có thể thao tác trên danh sách này với phương thức DBus " | ||||
| "EnableExtension và DisableExtension trên org.gnome.Shell." | ||||
| @@ -121,15 +120,13 @@ msgstr "" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:9 | ||||
| msgid "List of categories that should be displayed as folders" | ||||
| msgstr "Liệt kê các các-ta-lốc mà nó có thể hiển thị như một thư mục" | ||||
| msgstr "" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:10 | ||||
| msgid "" | ||||
| "Each category name in this list will be represented as folder in the " | ||||
| "application view, rather than being displayed inline in the main view." | ||||
| msgstr "" | ||||
| "Mỗi tên các-ta-lốc trong danh sách này sẽ được xuất hiện như là một thư mục " | ||||
| "trong trình bày ứng dụng, thay vì hiển thị  cùng dòng trong trình bày chính. " | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:11 | ||||
| msgid "History for command (Alt-F2) dialog" | ||||
| @@ -157,22 +154,18 @@ msgstr "" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:15 | ||||
| msgid "Always show the 'Log out' menuitem in the user menu." | ||||
| msgstr "Luôn hiện mục “Đăng xuất” trên trình đơn người dùng." | ||||
| msgstr "Luôn hiện mục \"Đăng xuất\" trên trình đơn người dùng." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:16 | ||||
| msgid "" | ||||
| "This key overrides the automatic hiding of the 'Log out' menuitem in single-" | ||||
| "user, single-session situations." | ||||
| msgstr "" | ||||
| "Khóa này sẽ đè lên việc tự động ẩn trình đơn 'Đăng xuất' ở chế độ đơn-người-" | ||||
| "dùng, đơn-phiên-làm-việc. " | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:17 | ||||
| msgid "" | ||||
| "Whether to remember password for mounting encrypted or remote filesystems" | ||||
| msgstr "" | ||||
| "Hoặc là ghi nhớ mật khẩu dành cho việc gắn hệ thống tập tin đã mã hóa hoặc " | ||||
| "hệ thống tập tin trên máy chủ" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:18 | ||||
| msgid "" | ||||
| @@ -181,10 +174,6 @@ msgid "" | ||||
| "'Remember Password' checkbox will be present. This key sets the default " | ||||
| "state of the checkbox." | ||||
| msgstr "" | ||||
| "Hệ vỏ sẽ yêu cầu mật khẩu khi có thư mục được mã hóa hay hệ thống tập tin " | ||||
| "máy mạng được gắn. Nếu mật khẩu có thể ghi lại để dùng trong lần sau, hộp " | ||||
| "dấu kiểm “Nhớ mật khẩu” sẽ xuất hiện. Khóa này đặt trạng thái mặc định cho " | ||||
| "hộp dấu kiểm." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:19 | ||||
| msgid "Show the week date in the calendar" | ||||
| @@ -237,27 +226,27 @@ msgstr "Phím chạy hoặc ngừng trình thu màn hình." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:31 | ||||
| msgid "Which keyboard to use" | ||||
| msgstr "Bàn phím cần dùng" | ||||
| msgstr "Loại bàn phím cần dùng" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:32 | ||||
| msgid "The type of keyboard to use." | ||||
| msgstr "Kiểu bàn phím cần dùng." | ||||
| msgstr "Loại bàn phím cần dùng." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:33 | ||||
| msgid "Framerate used for recording screencasts." | ||||
| msgstr "Tốc độ khung hình sẽ dùng khi ghi screencast." | ||||
| msgstr "Tốc độ khung dùng lưu screencast." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:34 | ||||
| msgid "" | ||||
| "The framerate of the resulting screencast recordered by GNOME Shell's " | ||||
| "screencast recorder in frames-per-second." | ||||
| msgstr "" | ||||
| "Tốc độ khung hình của screencast được ghi bởi bộ thu Hệ vỏ GNOME tính theo " | ||||
| "số khung mỗi giây." | ||||
| "Tốc độ khung của screencast lưu bởi bộ thu GNOME Shell theo số khung mỗi " | ||||
| "giây." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:35 | ||||
| msgid "The gstreamer pipeline used to encode the screencast" | ||||
| msgstr "Ống dẫn gstreamer dùng để thu screencast" | ||||
| msgstr "Ống dẫn gstreamer để thu screencast" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:37 | ||||
| #, no-c-format | ||||
| @@ -278,9 +267,9 @@ msgstr "" | ||||
| "source pad không kết nối; đầu ra từ pad sẽ được ghi vào tập tin kết quả. Tuy " | ||||
| "nhiên ống dẫn có thể tự lưu đầu ra riêng - có thể hữu dụng để gửi kết quả " | ||||
| "đến máy chủ icecast thông qua shout2send hoặc tương tự. Nếu bỏ chọn hoặc đặt " | ||||
| "giá trị rỗng, ống dẫn mặc định sẽ được dùng, hiện thời là “vp8enc " | ||||
| "giá trị rỗng, ống dẫn mặc định sẽ được dùng, hiện thời là 'vp8enc " | ||||
| "min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! " | ||||
| "queue ! webmmux” và lưu ở dạng WEBM dùng VP8 codec. %T được dùng để thế chỗ " | ||||
| "queue ! webmmux' và lưu ở dạng WEBM dùng VP8 codec. %T được dùng để thế chỗ " | ||||
| "cho số thread dự đoán tối ưu cho hệ thống." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:38 | ||||
| @@ -307,31 +296,25 @@ msgid "" | ||||
| "are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-" | ||||
| "only' (shows only the application icon) or 'both'." | ||||
| msgstr "" | ||||
| "Cấu hình về cách hiển thị các cửa sổ ở bảng chuyển đổi. Các kiểu có thể là " | ||||
| "'thumbnail-only' (hiển thị ảnh thu nhỏ của cửa sổ), 'app-icon-only' (chỉ " | ||||
| "hiển thị biểu tượng của ứng dụng) hoặc 'both' (cả hai)." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:42 | ||||
| msgid "Attach modal dialog to the parent window" | ||||
| msgstr "Gắn hộp thoại dạng modal vào cửa sổ mẹ" | ||||
| msgstr "" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:43 | ||||
| msgid "" | ||||
| "This key overrides the key in org.gnome.mutter when running GNOME Shell." | ||||
| msgstr "" | ||||
| "Khóa này sẽ đè lên khóa có trong org.gnome.mutter khi chạy hệ vỏ GNOME." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:44 | ||||
| msgid "Arrangement of buttons on the titlebar" | ||||
| msgstr "Sắp đặt các nút trên thanh tiêu đề" | ||||
| msgstr "" | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:45 | ||||
| msgid "" | ||||
| "This key overrides the key in org.gnome.desktop.wm.preferences when running " | ||||
| "GNOME Shell." | ||||
| msgstr "" | ||||
| "Khóa này đè lên khóa có trong org.gnome.desktop.wm.preferences khi chạy hệ " | ||||
| "vỏ GNOME." | ||||
|  | ||||
| #: ../data/org.gnome.shell.gschema.xml.in.in.h:46 | ||||
| msgid "Enable edge tiling when dropping windows on screen edges" | ||||
| @@ -365,46 +348,46 @@ msgstr "Phiên làm việc…" | ||||
| #. 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:630 | ||||
| #: ../js/gdm/loginDialog.js:629 | ||||
| msgid "Not listed?" | ||||
| msgstr "Không có trong danh sách?" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:786 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/gdm/loginDialog.js:783 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 | ||||
| #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:99 | ||||
| #: ../js/ui/userMenu.js:938 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:126 | ||||
| #: ../js/ui/userMenu.js:932 | ||||
| msgid "Cancel" | ||||
| msgstr "Thôi" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:802 | ||||
| #: ../js/gdm/loginDialog.js:799 | ||||
| msgctxt "button" | ||||
| msgid "Sign In" | ||||
| msgstr "Đăng nhập" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:802 | ||||
| #: ../js/gdm/loginDialog.js:799 | ||||
| msgid "Next" | ||||
| msgstr "Kế tiếp" | ||||
| msgstr "Tới" | ||||
|  | ||||
| #. 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:917 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/gdm/loginDialog.js:904 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/ui/components/networkAgent.js:278 | ||||
| msgid "Username: " | ||||
| msgstr "Tài khoản: " | ||||
| msgstr "Tên người dùng: " | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:1173 | ||||
| #: ../js/gdm/loginDialog.js:1157 | ||||
| msgid "Login Window" | ||||
| msgstr "Cửa sổ đăng nhập" | ||||
| msgstr "Cửa sổ đặt nhập" | ||||
|  | ||||
| #. Translators: accessible name of the power menu in the login screen | ||||
| #: ../js/gdm/powerMenu.js:36 | ||||
| msgid "Power" | ||||
| msgstr "Nguồn" | ||||
|  | ||||
| #: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:696 ../js/ui/userMenu.js:700 | ||||
| #: ../js/ui/userMenu.js:816 | ||||
| #: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:694 ../js/ui/userMenu.js:698 | ||||
| #: ../js/ui/userMenu.js:814 | ||||
| msgid "Suspend" | ||||
| msgstr "Ngưng" | ||||
|  | ||||
| @@ -412,58 +395,58 @@ msgstr "Ngưng" | ||||
| msgid "Restart" | ||||
| msgstr "Khởi động lại" | ||||
|  | ||||
| #: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:698 | ||||
| #: ../js/ui/userMenu.js:700 ../js/ui/userMenu.js:815 ../js/ui/userMenu.js:942 | ||||
| #: ../js/gdm/powerMenu.js:103 ../js/ui/userMenu.js:696 | ||||
| #: ../js/ui/userMenu.js:698 ../js/ui/userMenu.js:813 ../js/ui/userMenu.js:936 | ||||
| msgid "Power Off" | ||||
| msgstr "Tắt máy" | ||||
|  | ||||
| #: ../js/gdm/util.js:249 | ||||
| #: ../js/gdm/util.js:182 | ||||
| msgid "Authentication error" | ||||
| msgstr "Lỗi xác thực" | ||||
|  | ||||
| #. Translators: this message is shown below the password entry field | ||||
| #. to indicate the user can swipe their finger instead | ||||
| #: ../js/gdm/util.js:366 | ||||
| #: ../js/gdm/util.js:299 | ||||
| msgid "(or swipe finger)" | ||||
| msgstr "(hoặc quẹt ngón tay)" | ||||
|  | ||||
| #: ../js/gdm/util.js:391 | ||||
| #: ../js/gdm/util.js:324 | ||||
| #, c-format | ||||
| msgid "(e.g., user or %s)" | ||||
| msgstr "(ví dụ: tài khoản hoặc %s)" | ||||
| msgstr "(ví dụ người dùng hoặc %s)" | ||||
|  | ||||
| #: ../js/misc/util.js:97 | ||||
| #: ../js/misc/util.js:94 | ||||
| msgid "Command not found" | ||||
| msgstr "Không tìm thấy lệnh" | ||||
|  | ||||
| #. Replace "Error invoking GLib.shell_parse_argv: " with | ||||
| #. something nicer | ||||
| #: ../js/misc/util.js:130 | ||||
| #: ../js/misc/util.js:127 | ||||
| msgid "Could not parse command:" | ||||
| msgstr "Không thể phân tích lệnh:" | ||||
|  | ||||
| #: ../js/misc/util.js:138 | ||||
| #: ../js/misc/util.js:135 | ||||
| #, c-format | ||||
| msgid "Execution of '%s' failed:" | ||||
| msgstr "Lỗi thực hiện “%s”:" | ||||
| msgstr "Lỗi thực hiện '%s':" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:349 | ||||
| #: ../js/ui/appDisplay.js:348 | ||||
| msgid "Frequent" | ||||
| msgstr "Thường dùng" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:356 | ||||
| #: ../js/ui/appDisplay.js:355 | ||||
| msgid "All" | ||||
| msgstr "Tất cả" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:914 | ||||
| #: ../js/ui/appDisplay.js:913 | ||||
| msgid "New Window" | ||||
| msgstr "Cửa sổ mới" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:917 ../js/ui/dash.js:284 | ||||
| #: ../js/ui/appDisplay.js:916 ../js/ui/dash.js:284 | ||||
| msgid "Remove from Favorites" | ||||
| msgstr "Bỏ đánh dấu ưa thích" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:918 | ||||
| #: ../js/ui/appDisplay.js:917 | ||||
| msgid "Add to Favorites" | ||||
| msgstr "Đánh dấu ưa thích" | ||||
|  | ||||
| @@ -477,13 +460,13 @@ msgstr "Đã được đánh dấu ưa thích cho %s." | ||||
| msgid "%s has been removed from your favorites." | ||||
| msgstr "Đã bỏ đánh dấu ưa thích cho %s" | ||||
|  | ||||
| #: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:789 | ||||
| #: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:787 | ||||
| msgid "Settings" | ||||
| msgstr "Cài đặt" | ||||
| msgstr "Thiết lập" | ||||
|  | ||||
| #: ../js/ui/backgroundMenu.js:21 | ||||
| msgid "Change Background…" | ||||
| msgstr "Đổi ảnh nền…" | ||||
| msgstr "Thay đổi nền…" | ||||
|  | ||||
| #. Translators: Shown in calendar event list for all day events | ||||
| #. * Keep it short, best if you can use less then 10 characters | ||||
| @@ -602,35 +585,35 @@ msgid "S" | ||||
| msgstr "T7" | ||||
|  | ||||
| #. Translators: Text to show if there are no events | ||||
| #: ../js/ui/calendar.js:720 | ||||
| #: ../js/ui/calendar.js:692 | ||||
| msgid "Nothing Scheduled" | ||||
| msgstr "Không có lịch hẹn" | ||||
|  | ||||
| #. Translators: Shown on calendar heading when selected day occurs on current year | ||||
| #: ../js/ui/calendar.js:736 | ||||
| #: ../js/ui/calendar.js:708 | ||||
| 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:739 | ||||
| #: ../js/ui/calendar.js:711 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d, %Y" | ||||
| msgstr "%A, %d %B %Y" | ||||
|  | ||||
| #: ../js/ui/calendar.js:749 | ||||
| #: ../js/ui/calendar.js:721 | ||||
| msgid "Today" | ||||
| msgstr "Hôm nay" | ||||
|  | ||||
| #: ../js/ui/calendar.js:753 | ||||
| #: ../js/ui/calendar.js:725 | ||||
| msgid "Tomorrow" | ||||
| msgstr "Ngày mai" | ||||
|  | ||||
| #: ../js/ui/calendar.js:764 | ||||
| #: ../js/ui/calendar.js:736 | ||||
| msgid "This week" | ||||
| msgstr "Tuần này" | ||||
|  | ||||
| #: ../js/ui/calendar.js:772 | ||||
| #: ../js/ui/calendar.js:744 | ||||
| msgid "Next week" | ||||
| msgstr "Tuần tới" | ||||
|  | ||||
| @@ -646,12 +629,12 @@ msgstr "Ổ ngoài đã ngắt kết nối" | ||||
| msgid "Removable Devices" | ||||
| msgstr "Thiết bị di động" | ||||
|  | ||||
| #: ../js/ui/components/autorunManager.js:594 | ||||
| #: ../js/ui/components/autorunManager.js:593 | ||||
| #, c-format | ||||
| msgid "Open with %s" | ||||
| msgstr "Mở bằng %s" | ||||
|  | ||||
| #: ../js/ui/components/autorunManager.js:620 | ||||
| #: ../js/ui/components/autorunManager.js:619 | ||||
| msgid "Eject" | ||||
| msgstr "Đẩy ra" | ||||
|  | ||||
| @@ -702,7 +685,7 @@ msgstr "Mạng không dây cần xác thực" | ||||
| msgid "" | ||||
| "Passwords or encryption keys are required to access the wireless network " | ||||
| "'%s'." | ||||
| msgstr "Cần mật mã hoặc khoá mã để truy cập mạng không dây “%s”" | ||||
| msgstr "Cần mật mã hoặc khoá mã để truy cập mạng không dây '%s'" | ||||
|  | ||||
| #: ../js/ui/components/networkAgent.js:314 | ||||
| msgid "Wired 802.1X authentication" | ||||
| @@ -735,7 +718,7 @@ msgstr "Mật khẩu mạng băng thông rộng" | ||||
| #: ../js/ui/components/networkAgent.js:337 | ||||
| #, c-format | ||||
| msgid "A password is required to connect to '%s'." | ||||
| msgstr "Cần mật khẩu để kết nối đến “%s”." | ||||
| msgstr "Cần mật khẩu để kết nối đến '%s'." | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:55 | ||||
| msgid "Authentication Required" | ||||
| @@ -789,7 +772,7 @@ msgstr "Ngừng im lặng" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:480 | ||||
| msgid "Mute" | ||||
| msgstr "Câm" | ||||
| msgstr "Im lặng" | ||||
|  | ||||
| #. Translators: this is the word "Yesterday" followed by a time string. i.e. "Yesterday, 14:30" | ||||
| #: ../js/ui/components/telepathyClient.js:942 | ||||
| @@ -1000,7 +983,7 @@ msgstr "Xem tài khoản" | ||||
| msgid "Unknown reason" | ||||
| msgstr "Lý do không biết" | ||||
|  | ||||
| #: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:96 | ||||
| #: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:97 | ||||
| msgid "Windows" | ||||
| msgstr "Cửa sổ" | ||||
|  | ||||
| @@ -1029,7 +1012,7 @@ msgstr "Thiết lập ngày giờ" | ||||
| #. 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:215 | ||||
| #: ../js/ui/dateMenu.js:205 | ||||
| msgid "%A %B %e, %Y" | ||||
| msgstr "%A %e %B, %Y" | ||||
|  | ||||
| @@ -1125,7 +1108,7 @@ msgstr "Cài đặt" | ||||
| #: ../js/ui/extensionDownloader.js:204 | ||||
| #, c-format | ||||
| msgid "Download and install '%s' from extensions.gnome.org?" | ||||
| msgstr "Tải và cài đặt “%s” từ extensions.gnome.org chứ?" | ||||
| msgstr "Tải và cài đặt '%s' từ extensions.gnome.org chứ?" | ||||
|  | ||||
| #: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:314 | ||||
| #: ../js/ui/status/power.js:211 | ||||
| @@ -1154,7 +1137,9 @@ msgstr "Hiện lỗi" | ||||
| msgid "Enabled" | ||||
| msgstr "Bật" | ||||
|  | ||||
| #: ../js/ui/lookingGlass.js:769 | ||||
| #. translators: | ||||
| #. * The device has been disabled | ||||
| #: ../js/ui/lookingGlass.js:769 ../src/gvc/gvc-mixer-control.c:1830 | ||||
| msgid "Disabled" | ||||
| msgstr "Tắt" | ||||
|  | ||||
| @@ -1194,15 +1179,15 @@ msgstr "Xoá thông báo" | ||||
| msgid "Notification Settings" | ||||
| msgstr "Thiết lập thông báo" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1709 | ||||
| #: ../js/ui/messageTray.js:1707 | ||||
| msgid "No Messages" | ||||
| msgstr "Không có thông báo" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1782 | ||||
| #: ../js/ui/messageTray.js:1787 | ||||
| msgid "Message Tray" | ||||
| msgstr "Khay thông báo" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:2810 | ||||
| #: ../js/ui/messageTray.js:2864 | ||||
| msgid "System Information" | ||||
| msgstr "Thông tin hệ thống" | ||||
|  | ||||
| @@ -1211,13 +1196,13 @@ msgctxt "program" | ||||
| msgid "Unknown" | ||||
| msgstr "Không biết" | ||||
|  | ||||
| #: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149 | ||||
| #: ../js/ui/overviewControls.js:460 ../js/ui/screenShield.js:153 | ||||
| #, c-format | ||||
| msgid "%d new message" | ||||
| msgid_plural "%d new messages" | ||||
| msgstr[0] "%d tin nhắn mới" | ||||
|  | ||||
| #: ../js/ui/overview.js:84 | ||||
| #: ../js/ui/overview.js:82 | ||||
| msgid "Undo" | ||||
| msgstr "Hoàn lại" | ||||
|  | ||||
| @@ -1229,21 +1214,21 @@ msgstr "Tổng quan" | ||||
| #. in the search entry when no search is | ||||
| #. active; it should not exceed ~30 | ||||
| #. characters. | ||||
| #: ../js/ui/overview.js:271 | ||||
| #: ../js/ui/overview.js:284 | ||||
| msgid "Type to search…" | ||||
| msgstr "Nhập để tìm…" | ||||
|  | ||||
| #: ../js/ui/panel.js:612 | ||||
| #: ../js/ui/panel.js:613 | ||||
| msgid "Quit" | ||||
| msgstr "Thoát" | ||||
|  | ||||
| #. Translators: If there is no suitable word for "Activities" | ||||
| #. in your language, you can use the word for "Overview". | ||||
| #: ../js/ui/panel.js:636 | ||||
| #: ../js/ui/panel.js:642 | ||||
| msgid "Activities" | ||||
| msgstr "Hoạt động" | ||||
|  | ||||
| #: ../js/ui/panel.js:933 | ||||
| #: ../js/ui/panel.js:983 | ||||
| msgid "Top Bar" | ||||
| msgstr "Thanh đỉnh" | ||||
|  | ||||
| @@ -1256,31 +1241,31 @@ msgstr "Thanh đỉnh" | ||||
| msgid "toggle-switch-us" | ||||
| msgstr "toggle-switch-intl" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:73 | ||||
| #: ../js/ui/runDialog.js:205 | ||||
| msgid "Enter a Command" | ||||
| msgstr "Nhập lệnh" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:109 | ||||
| #: ../js/ui/runDialog.js:241 | ||||
| msgid "Close" | ||||
| msgstr "Đóng" | ||||
|  | ||||
| #. Translators: This is a time format for a date in | ||||
| #. long format | ||||
| #: ../js/ui/screenShield.js:86 | ||||
| #: ../js/ui/screenShield.js:90 | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%A, %d %B" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:151 | ||||
| #: ../js/ui/screenShield.js:155 | ||||
| #, c-format | ||||
| msgid "%d new notification" | ||||
| msgid_plural "%d new notifications" | ||||
| msgstr[0] "%d thông báo mới" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:438 ../js/ui/userMenu.js:807 | ||||
| #: ../js/ui/screenShield.js:442 ../js/ui/userMenu.js:805 | ||||
| msgid "Lock" | ||||
| msgstr "Khoá" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:637 | ||||
| #: ../js/ui/screenShield.js:639 | ||||
| msgid "GNOME needs to lock the screen" | ||||
| msgstr "GNOME cần khoá màn hình" | ||||
|  | ||||
| @@ -1291,19 +1276,19 @@ msgstr "GNOME cần khoá màn hình" | ||||
| #. | ||||
| #. XXX: another option is to kick the user into the gdm login | ||||
| #. screen, where we're not affected by grabs | ||||
| #: ../js/ui/screenShield.js:758 ../js/ui/screenShield.js:1194 | ||||
| #: ../js/ui/screenShield.js:758 ../js/ui/screenShield.js:1169 | ||||
| msgid "Unable to lock" | ||||
| msgstr "Không thể khoá" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1195 | ||||
| #: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1170 | ||||
| msgid "Lock was blocked by an application" | ||||
| msgstr "Một ứng dụng đã ngăn cản khoá" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:453 | ||||
| #: ../js/ui/searchDisplay.js:431 | ||||
| msgid "Searching…" | ||||
| msgstr "Đang tìm…" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:497 | ||||
| #: ../js/ui/searchDisplay.js:475 | ||||
| msgid "No results." | ||||
| msgstr "Không có kết quả." | ||||
|  | ||||
| @@ -1315,11 +1300,11 @@ msgstr "Chép" | ||||
| msgid "Paste" | ||||
| msgstr "Dán" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:106 | ||||
| #: ../js/ui/shellEntry.js:105 | ||||
| msgid "Show Text" | ||||
| msgstr "Hiện chữ" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:108 | ||||
| #: ../js/ui/shellEntry.js:107 | ||||
| msgid "Hide Text" | ||||
| msgstr "Ẩn chữ" | ||||
|  | ||||
| @@ -1331,7 +1316,7 @@ msgstr "Mật khẩu" | ||||
| msgid "Remember Password" | ||||
| msgstr "Nhớ mật khẩu" | ||||
|  | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:113 | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:140 | ||||
| msgid "Unlock" | ||||
| msgstr "Bỏ khoá" | ||||
|  | ||||
| @@ -1448,7 +1433,7 @@ msgstr "Yêu cầu cấp quyền từ %s" | ||||
| #: ../js/ui/status/bluetooth.js:328 | ||||
| #, c-format | ||||
| msgid "Device %s wants access to the service '%s'" | ||||
| msgstr "Thiết bị %s muốn truy cập dịch vụ “%s”" | ||||
| msgstr "Thiết bị %s muốn truy cập dịch vụ '%s'" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:330 | ||||
| msgid "Always grant access" | ||||
| @@ -1476,7 +1461,7 @@ msgstr "Thiết bị %s muốn kết nối với máy tính này" | ||||
| #: ../js/ui/status/bluetooth.js:366 | ||||
| #, c-format | ||||
| msgid "Please confirm whether the PIN '%06d' matches the one on the device." | ||||
| msgstr "Vui lòng xác nhận PIN “%06d” khớp với số trên thiết bị." | ||||
| msgstr "Vui lòng xác nhận PIN '%06d' khớp với số trên thiết bị." | ||||
|  | ||||
| #. Translators: this is the verb, not the noun | ||||
| #: ../js/ui/status/bluetooth.js:369 | ||||
| @@ -1732,59 +1717,59 @@ msgstr "Âm lượng" | ||||
| msgid "Microphone" | ||||
| msgstr "Micrô" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:124 | ||||
| #: ../js/ui/unlockDialog.js:151 | ||||
| msgid "Log in as another user" | ||||
| msgstr "Đăng nhập người dùng khác" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:145 | ||||
| #: ../js/ui/unlockDialog.js:177 | ||||
| msgid "Unlock Window" | ||||
| msgstr "Bỏ khoá cửa sổ" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:193 | ||||
| #: ../js/ui/userMenu.js:192 | ||||
| msgid "Available" | ||||
| msgstr "Có mặt" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:196 | ||||
| #: ../js/ui/userMenu.js:195 | ||||
| msgid "Busy" | ||||
| msgstr "Bận" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:199 | ||||
| #: ../js/ui/userMenu.js:198 | ||||
| msgid "Invisible" | ||||
| msgstr "Giấu mặt" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:202 | ||||
| #: ../js/ui/userMenu.js:201 | ||||
| msgid "Away" | ||||
| msgstr "Vắng mặt" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:205 | ||||
| #: ../js/ui/userMenu.js:204 | ||||
| msgid "Idle" | ||||
| msgstr "Nhàn rỗi" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:208 | ||||
| #: ../js/ui/userMenu.js:207 | ||||
| msgid "Offline" | ||||
| msgstr "Ngoại tuyến" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:781 | ||||
| #: ../js/ui/userMenu.js:779 | ||||
| msgid "Notifications" | ||||
| msgstr "Thông báo" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:797 | ||||
| #: ../js/ui/userMenu.js:795 | ||||
| msgid "Switch User" | ||||
| msgstr "Chuyển người dùng" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:802 | ||||
| #: ../js/ui/userMenu.js:800 | ||||
| msgid "Log Out" | ||||
| msgstr "Đăng xuất" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:822 | ||||
| #: ../js/ui/userMenu.js:820 | ||||
| msgid "Install Updates & Restart" | ||||
| msgstr "Cài đặt bản cập nhật và khởi động lại" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:840 | ||||
| #: ../js/ui/userMenu.js:838 | ||||
| msgid "Your chat status will be set to busy" | ||||
| msgstr "Trạng thái nhắn tin của bạn sẽ được đặt là bận" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:841 | ||||
| #: ../js/ui/userMenu.js:839 | ||||
| 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." | ||||
| @@ -1792,35 +1777,33 @@ msgstr "" | ||||
| "Thông báo đã bị tắt, bao gồm tin nhắn. Trạng thái trực tuyến của bạn đã được " | ||||
| "điều chỉnh để mọi người biết bạn sẽ không xem tin nhắn họ gửi đến." | ||||
|  | ||||
| #: ../js/ui/userMenu.js:888 | ||||
| #: ../js/ui/userMenu.js:885 | ||||
| msgid "Other users are logged in." | ||||
| msgstr "Người dùng khác đang đăng nhập." | ||||
|  | ||||
| #: ../js/ui/userMenu.js:893 | ||||
| #: ../js/ui/userMenu.js:890 | ||||
| msgid "Shutting down might cause them to lose unsaved work." | ||||
| msgstr "Tắt sẽ làm mất những kết quả chưa được lưu." | ||||
|  | ||||
| #. Translators: Remote here refers to a remote session, like a ssh login | ||||
| #: ../js/ui/userMenu.js:921 | ||||
| #: ../js/ui/userMenu.js:916 | ||||
| #, c-format | ||||
| msgid "%s (remote)" | ||||
| msgstr "%s (ở xa)" | ||||
|  | ||||
| #. Translators: Console here refers to a tty like a VT console | ||||
| #: ../js/ui/userMenu.js:924 | ||||
| #: ../js/ui/userMenu.js:918 | ||||
| #, c-format | ||||
| msgid "%s (console)" | ||||
| msgstr "%s (console)" | ||||
|  | ||||
| #: ../js/ui/viewSelector.js:100 | ||||
| #: ../js/ui/viewSelector.js:101 | ||||
| msgid "Applications" | ||||
| msgstr "Ứng dụng" | ||||
|  | ||||
| #: ../js/ui/viewSelector.js:104 | ||||
| #: ../js/ui/viewSelector.js:105 | ||||
| msgid "Search" | ||||
| msgstr "Tìm" | ||||
|  | ||||
| #: ../js/ui/wanda.js:77 | ||||
| #: ../js/ui/wanda.js:92 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Sorry, no wisdom for you today:\n" | ||||
| @@ -1829,7 +1812,7 @@ msgstr "" | ||||
| "Rất tiếc, không có lời thông thái nào hôm nay:\n" | ||||
| "%s" | ||||
|  | ||||
| #: ../js/ui/wanda.js:81 | ||||
| #: ../js/ui/wanda.js:96 | ||||
| #, c-format | ||||
| msgid "%s the Oracle says" | ||||
| msgstr "Nhà tiên tri %s nói" | ||||
| @@ -1837,12 +1820,32 @@ msgstr "Nhà tiên tri %s nói" | ||||
| #: ../js/ui/windowAttentionHandler.js:19 | ||||
| #, c-format | ||||
| msgid "'%s' is ready" | ||||
| msgstr "“%s” đã sẵn sàng" | ||||
| msgstr "'%s' đã sẵn sàng" | ||||
|  | ||||
| #: ../src/calendar-server/evolution-calendar.desktop.in.in.h:1 | ||||
| msgid "Evolution Calendar" | ||||
| msgstr "Lịch Evolution" | ||||
|  | ||||
| #. 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] "%u đầu ra" | ||||
|  | ||||
| #. 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] "%u đầu vào" | ||||
|  | ||||
| #: ../src/gvc/gvc-mixer-control.c:2371 | ||||
| msgid "System Sounds" | ||||
| msgstr "Âm thanh hệ thống" | ||||
|  | ||||
| #: ../src/main.c:347 | ||||
| msgid "Print version" | ||||
| msgstr "In phiên bản" | ||||
| @@ -1853,7 +1856,7 @@ msgstr "Chể độ dùng bởi GDM cho màn hình đăng nhập" | ||||
|  | ||||
| #: ../src/main.c:359 | ||||
| msgid "Use a specific mode, e.g. \"gdm\" for login screen" | ||||
| msgstr "Dùng chế độ đặc biệt, ví dụ “gdm” cho màn hình đăng nhập" | ||||
| msgstr "Dùng chế độ đặc biệt, ví dụ \"gdm\" cho màn hình đăng nhập" | ||||
|  | ||||
| #: ../src/main.c:365 | ||||
| msgid "List possible modes" | ||||
| @@ -1862,7 +1865,7 @@ msgstr "Danh sách chế độ" | ||||
| #: ../src/shell-app.c:622 | ||||
| #, c-format | ||||
| msgid "Failed to launch '%s'" | ||||
| msgstr "Lỗi chạy “%s”" | ||||
| msgstr "Lỗi chạy '%s'" | ||||
|  | ||||
| #: ../src/shell-keyring-prompt.c:708 | ||||
| msgid "Passwords do not match." | ||||
| @@ -1876,17 +1879,6 @@ msgstr "Mật khẩu không thể không có" | ||||
| msgid "Authentication dialog was dismissed by the user" | ||||
| msgstr "Hộp thoại xác thực bị người dùng bỏ qua" | ||||
|  | ||||
| #~ msgid "%u Output" | ||||
| #~ msgid_plural "%u Outputs" | ||||
| #~ msgstr[0] "%u đầu ra" | ||||
|  | ||||
| #~ msgid "%u Input" | ||||
| #~ msgid_plural "%u Inputs" | ||||
| #~ msgstr[0] "%u đầu vào" | ||||
|  | ||||
| #~ msgid "System Sounds" | ||||
| #~ msgstr "Âm thanh hệ thống" | ||||
|  | ||||
| #~ msgctxt "title" | ||||
| #~ msgid "Sign In" | ||||
| #~ msgstr "Đăng nhập" | ||||
| @@ -1918,7 +1910,7 @@ msgstr "Hộp thoại xác thực bị người dùng bỏ qua" | ||||
| #~ msgstr "%l:%M %p" | ||||
|  | ||||
| #~ msgid "Failed to unmount '%s'" | ||||
| #~ msgstr "Lỗi bỏ gắn kết “%s”" | ||||
| #~ msgstr "Lỗi bỏ gắn kết '%s'" | ||||
|  | ||||
| #~ msgid "Retry" | ||||
| #~ msgstr "Thử lại" | ||||
| @@ -1933,7 +1925,7 @@ msgstr "Hộp thoại xác thực bị người dùng bỏ qua" | ||||
| #~ msgstr "Lỗi duyệt tập tin" | ||||
|  | ||||
| #~ msgid "The requested device cannot be browsed, error is '%s'" | ||||
| #~ msgstr "Không thể duyệt thiết bị yêu cầu , lỗi là “%s”" | ||||
| #~ msgstr "Không thể duyệt thiết bị yêu cầu , lỗi là '%s'" | ||||
|  | ||||
| #~ msgid "Wireless" | ||||
| #~ msgstr "Mạng không dây" | ||||
| @@ -2078,3 +2070,155 @@ msgstr "Hộp thoại xác thực bị người dùng bỏ qua" | ||||
|  | ||||
| #~ msgid "Show password" | ||||
| #~ msgstr "Hiện mật khẩu" | ||||
|  | ||||
| #~| msgid "If true, display seconds in time." | ||||
| #~ msgid "If true, display onscreen keyboard." | ||||
| #~ msgstr "Nếu đúng (true), hiện bàn phím màn hình." | ||||
|  | ||||
| #~| msgid "Screen Keyboard" | ||||
| #~ msgid "Show the onscreen keyboard" | ||||
| #~ msgstr "Hiện bàn phím màn hình" | ||||
|  | ||||
| #~ msgid "%s has finished starting" | ||||
| #~ msgstr "%s đã hoàn tất khởi chạy" | ||||
|  | ||||
| #~ msgid "Uuids of extensions to disable" | ||||
| #~ msgstr "UUID của phần mở rộng cần tắt" | ||||
|  | ||||
| #~ msgid "You're now connected to mobile broadband connection '%s'" | ||||
| #~ msgstr "Đã nối mạng '%s' (băng thông rộng)" | ||||
|  | ||||
| #~ msgid "You're now connected to wireless network '%s'" | ||||
| #~ msgstr "Đã nối mạng '%s' (không dây)" | ||||
|  | ||||
| #~ msgid "You're now connected to wired network '%s'" | ||||
| #~ msgstr "Đã nối mạng '%s' (dây)" | ||||
|  | ||||
| #~ msgid "You're now connected to VPN network '%s'" | ||||
| #~ msgstr "Đã nối mạng VPN '%s'" | ||||
|  | ||||
| #~ msgid "Localization Settings" | ||||
| #~ msgstr "Thiết lập bản địa hoá" | ||||
|  | ||||
| #~ msgid "Less than a minute ago" | ||||
| #~ msgstr "Chưa đến một phút" | ||||
|  | ||||
| #~ msgid "%d minute ago" | ||||
| #~ msgid_plural "%d minutes ago" | ||||
| #~ msgstr[0] "%d phút trước" | ||||
|  | ||||
| #~ msgid "%d hour ago" | ||||
| #~ msgid_plural "%d hours ago" | ||||
| #~ msgstr[0] "%d giờ trước" | ||||
|  | ||||
| #~ msgid "%d day ago" | ||||
| #~ msgid_plural "%d days ago" | ||||
| #~ msgstr[0] "%d ngày trước" | ||||
|  | ||||
| #~ msgid "%d week ago" | ||||
| #~ msgid_plural "%d weeks ago" | ||||
| #~ msgstr[0] "%d tuần trước" | ||||
|  | ||||
| #~ msgid "Shut Down" | ||||
| #~ msgstr "Tắt máy" | ||||
|  | ||||
| #~ msgid "Click Shut Down to quit these applications and shut down the system." | ||||
| #~ msgstr "Nhấn Tắt máy để thoát những ứng dụng này và tắt hệ thống." | ||||
|  | ||||
| #~ msgid "The system will shut down automatically in %d seconds." | ||||
| #~ msgstr "Hệ thống sẽ tự động tắt sau %d giây." | ||||
|  | ||||
| #~ msgid "Shutting down the system." | ||||
| #~ msgstr "Tắt hệ thống." | ||||
|  | ||||
| #~ msgid "Confirm" | ||||
| #~ msgstr "Xác nhận" | ||||
|  | ||||
| #~ msgid "Clip the crosshairs at the center" | ||||
| #~ msgstr "Cắt lưới chéo ở giữa" | ||||
|  | ||||
| #~ msgid "Color of the crosshairs" | ||||
| #~ msgstr "Màu lưới chéo" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Determines the length of the vertical and horizontal lines that make up " | ||||
| #~ "the crosshairs." | ||||
| #~ msgstr "Xác định độ dài và rộng của những dòng tạo nên lưới chéo." | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Determines the transparency of the crosshairs, from fully opaque to fully " | ||||
| #~ "transparent." | ||||
| #~ msgstr "Xác định độ trong suốt của lưới chéo, từ đặc đến trong suốt." | ||||
|  | ||||
| #~ msgid "Enable lens mode" | ||||
| #~ msgstr "Bật chế độ gương" | ||||
|  | ||||
| #~ msgid "Show or hide crosshairs" | ||||
| #~ msgstr "Hiện hoặc ẩn lưới chéo" | ||||
|  | ||||
| #~ msgid "Show or hide the magnifier" | ||||
| #~ msgstr "Hiện hoặc ẩn kính lúp" | ||||
|  | ||||
| #~ msgid "Thickness of the crosshairs" | ||||
| #~ msgstr "Độ dày lưới chéo" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Width of the vertical and horizontal lines that make up the crosshairs." | ||||
| #~ msgstr "Độ rộng của đường dọc/ngang hình thành dấu gạch chéo." | ||||
|  | ||||
| #~ msgid "PREFERENCES" | ||||
| #~ msgstr "TUỲ THÍCH" | ||||
|  | ||||
| #~ msgid "Shut Down..." | ||||
| #~ msgstr "Tắt máy..." | ||||
|  | ||||
| #~ msgid "Search your computer" | ||||
| #~ msgstr "Tìm trong máy" | ||||
|  | ||||
| #~ msgid "Customize the panel clock" | ||||
| #~ msgstr "Tuỳ biến đồng hồ" | ||||
|  | ||||
| #~ msgid "Clock Format" | ||||
| #~ msgstr "Dạng đồng hồ" | ||||
|  | ||||
| #~| msgid "System Preferences..." | ||||
| #~ msgid "Clock Preferences" | ||||
| #~ msgstr "Thiết lập đồng hồ" | ||||
|  | ||||
| #~ msgid "Panel Display" | ||||
| #~ msgstr "Khung hiển thị" | ||||
|  | ||||
| #~ msgid "Show seco_nds" | ||||
| #~ msgstr "Hiện _giây" | ||||
|  | ||||
| #~ msgid "_12 hour format" | ||||
| #~ msgstr "Dạng _12 giờ" | ||||
|  | ||||
| #~ msgid "_24 hour format" | ||||
| #~ msgstr "Dạng _24 giờ" | ||||
|  | ||||
| #~| msgid "System Preferences..." | ||||
| #~ msgid "Preferences" | ||||
| #~ msgstr "Thiết lập" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Can't add a new workspace because maximum workspaces limit has been " | ||||
| #~ "reached." | ||||
| #~ msgstr "" | ||||
| #~ "Không thể thêm vùng làm việc mới vì đã đạt giới hạn số vùng làm việc tối " | ||||
| #~ "đa." | ||||
|  | ||||
| #~ msgid "Can't remove the first workspace." | ||||
| #~ msgstr "Không thể bỏ vùng làm việc đầu tiên." | ||||
|  | ||||
| #~ msgid "Drag here to add favorites" | ||||
| #~ msgstr "Kéo vào đây để thêm vào danh mục ưa thích" | ||||
|  | ||||
| #~ msgid "Find..." | ||||
| #~ msgstr "Tìm" | ||||
|  | ||||
| #~ msgid "Sidebar" | ||||
| #~ msgstr "Thanh bên" | ||||
|  | ||||
| #~ msgid "Recent Documents" | ||||
| #~ msgstr "Tài liệu gần đây" | ||||
|   | ||||
							
								
								
									
										666
									
								
								po/zh_CN.po
									
									
									
									
									
								
							
							
						
						
									
										666
									
								
								po/zh_CN.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										435
									
								
								po/zh_HK.po
									
									
									
									
									
								
							
							
						
						
									
										435
									
								
								po/zh_HK.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										438
									
								
								po/zh_TW.po
									
									
									
									
									
								
							
							
						
						
									
										438
									
								
								po/zh_TW.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -129,18 +129,13 @@ shell_public_headers_h =		\ | ||||
| 	shell-wm.h			\ | ||||
| 	shell-xfixes-cursor.h | ||||
|  | ||||
| shell_private_sources = 		\ | ||||
| 	gtkactionmuxer.h		\ | ||||
| 	gtkactionmuxer.c		\ | ||||
| 	gtkactionobservable.h		\ | ||||
| 	gtkactionobservable.c		\ | ||||
| 	gtkactionobserver.h		\ | ||||
| 	gtkactionobserver.c		\ | ||||
| 	gtkmenutrackeritem.c		\ | ||||
| 	gtkmenutrackeritem.h		\ | ||||
| 	gtkmenutracker.c		\ | ||||
| 	gtkmenutracker.h		\ | ||||
| 	$(NULL) | ||||
| shell_private_sources = \ | ||||
| 	gactionmuxer.h			\ | ||||
| 	gactionmuxer.c			\ | ||||
| 	gactionobservable.h		\ | ||||
| 	gactionobservable.c		\ | ||||
| 	gactionobserver.h		\ | ||||
| 	gactionobserver.c | ||||
|  | ||||
| libgnome_shell_la_SOURCES =		\ | ||||
| 	$(shell_built_sources)		\ | ||||
| @@ -163,8 +158,6 @@ libgnome_shell_la_SOURCES =		\ | ||||
| 	shell-invert-lightness-effect.c	\ | ||||
| 	shell-keyring-prompt.h		\ | ||||
| 	shell-keyring-prompt.c		\ | ||||
| 	shell-menu-tracker.c		\ | ||||
| 	shell-menu-tracker.h		\ | ||||
| 	shell-mount-operation.c		\ | ||||
| 	shell-network-agent.c		\ | ||||
| 	shell-perf-log.c		\ | ||||
| @@ -293,34 +286,12 @@ libgnome_shell_la_LIBADD =		\ | ||||
|  | ||||
| libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags) | ||||
|  | ||||
| ShellMenu-0.1.gir: libgnome-shell.la | ||||
| ShellMenu_0_1_gir_INCLUDES = Gio-2.0 | ||||
| ShellMenu_0_1_gir_CFLAGS = $(libgnome_shell_la_CPPFLAGS) -I $(srcdir) | ||||
| ShellMenu_0_1_gir_LIBS = libgnome-shell.la | ||||
| ShellMenu_0_1_gir_FILES = \ | ||||
| 	gtkactionmuxer.h		\ | ||||
| 	gtkactionmuxer.c		\ | ||||
| 	gtkactionobservable.h		\ | ||||
| 	gtkactionobservable.c		\ | ||||
| 	gtkactionobserver.h		\ | ||||
| 	gtkactionobserver.c		\ | ||||
| 	gtkmenutrackeritem.c		\ | ||||
| 	gtkmenutrackeritem.h		\ | ||||
| 	$(NULL) | ||||
| ShellMenu_0_1_gir_SCANNERFLAGS = 	\ | ||||
| 	--namespace=ShellMenu --identifier-prefix=Gtk \ | ||||
| 	$(if $(BLUETOOTH_DIR),-L $(BLUETOOTH_DIR),) | ||||
| INTROSPECTION_GIRS += ShellMenu-0.1.gir | ||||
| CLEANFILES += ShellMenu-0.1.gir | ||||
|  | ||||
| Shell-0.1.gir: libgnome-shell.la St-1.0.gir ShellMenu-0.1.gir | ||||
| 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 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) | ||||
| Shell_0_1_gir_SCANNERFLAGS =	\ | ||||
| 	--include-uninstalled=$(builddir)/St-1.0.gir \ | ||||
| 	--include-uninstalled=$(builddir)/ShellMenu-0.1.gir \ | ||||
| Shell_0_1_gir_SCANNERFLAGS = --include-uninstalled=$(builddir)/St-1.0.gir \ | ||||
| 	--add-include-path=$(MUTTER_GIR_DIR) $(if $(BLUETOOTH_DIR),-L $(BLUETOOTH_DIR),) | ||||
| INTROSPECTION_GIRS += Shell-0.1.gir | ||||
| CLEANFILES += Shell-0.1.gir | ||||
|   | ||||
							
								
								
									
										546
									
								
								src/gactionmuxer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										546
									
								
								src/gactionmuxer.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,546 @@ | ||||
| /* | ||||
|  * Copyright © 2011 Canonical Limited | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2 of the licence, or (at your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library; if not, write to the | ||||
|  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  * Author: Ryan Lortie <desrt@desrt.ca> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "gactionmuxer.h" | ||||
|  | ||||
| #include "gactionobservable.h" | ||||
| #include "gactionobserver.h" | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| /* | ||||
|  * SECTION:gactionmuxer | ||||
|  * @short_description: Aggregate and monitor several action groups | ||||
|  * | ||||
|  * #GActionMuxer is a #GActionGroup and #GActionObservable that is | ||||
|  * capable of containing other #GActionGroup instances. | ||||
|  * | ||||
|  * The typical use is aggregating all of the actions applicable to a | ||||
|  * particular context into a single action group, with namespacing. | ||||
|  * | ||||
|  * Consider the case of two action groups -- one containing actions | ||||
|  * applicable to an entire application (such as 'quit') and one | ||||
|  * containing actions applicable to a particular window in the | ||||
|  * application (such as 'fullscreen'). | ||||
|  * | ||||
|  * In this case, each of these action groups could be added to a | ||||
|  * #GActionMuxer with the prefixes "app" and "win", respectively.  This | ||||
|  * would expose the actions as "app.quit" and "win.fullscreen" on the | ||||
|  * #GActionGroup interface presented by the #GActionMuxer. | ||||
|  * | ||||
|  * Activations and state change requests on the #GActionMuxer are wired | ||||
|  * through to the underlying action group in the expected way. | ||||
|  * | ||||
|  * This class is typically only used at the site of "consumption" of | ||||
|  * actions (eg: when displaying a menu that contains many actions on | ||||
|  * different objects). | ||||
|  */ | ||||
|  | ||||
| static void     g_action_muxer_group_iface_init         (GActionGroupInterface      *iface); | ||||
| static void     g_action_muxer_observable_iface_init    (GActionObservableInterface *iface); | ||||
|  | ||||
| typedef GObjectClass GActionMuxerClass; | ||||
|  | ||||
| struct _GActionMuxer | ||||
| { | ||||
|   GObject parent_instance; | ||||
|  | ||||
|   GHashTable *actions; | ||||
|   GHashTable *groups; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (GActionMuxer, g_action_muxer, G_TYPE_OBJECT, | ||||
|                          G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, g_action_muxer_group_iface_init) | ||||
|                          G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_OBSERVABLE, g_action_muxer_observable_iface_init)) | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   GActionMuxer *muxer; | ||||
|   GSList       *watchers; | ||||
|   gchar        *fullname; | ||||
| } Action; | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   GActionMuxer *muxer; | ||||
|   GActionGroup *group; | ||||
|   gchar        *prefix; | ||||
|   gulong        handler_ids[4]; | ||||
| } Group; | ||||
|  | ||||
| static gchar ** | ||||
| g_action_muxer_list_actions (GActionGroup *action_group) | ||||
| { | ||||
|   GActionMuxer *muxer = G_ACTION_MUXER (action_group); | ||||
|   GHashTableIter iter; | ||||
|   gchar *key; | ||||
|   gchar **keys; | ||||
|   gsize i; | ||||
|  | ||||
|   keys = g_new (gchar *, g_hash_table_size (muxer->actions) + 1); | ||||
|  | ||||
|   i = 0; | ||||
|   g_hash_table_iter_init (&iter, muxer->actions); | ||||
|   while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) | ||||
|     keys[i++] = g_strdup (key); | ||||
|   keys[i] = NULL; | ||||
|  | ||||
|   return keys; | ||||
| } | ||||
|  | ||||
| static Group * | ||||
| g_action_muxer_find_group (GActionMuxer  *muxer, | ||||
|                               const gchar     **name) | ||||
| { | ||||
|   const gchar *dot; | ||||
|   gchar *prefix; | ||||
|   Group *group; | ||||
|  | ||||
|   dot = strchr (*name, '.'); | ||||
|  | ||||
|   if (!dot) | ||||
|     return NULL; | ||||
|  | ||||
|   prefix = g_strndup (*name, dot - *name); | ||||
|   group = g_hash_table_lookup (muxer->groups, prefix); | ||||
|   g_free (prefix); | ||||
|  | ||||
|   *name = dot + 1; | ||||
|  | ||||
|   return group; | ||||
| } | ||||
|  | ||||
| static Action * | ||||
| g_action_muxer_lookup_action (GActionMuxer  *muxer, | ||||
|                               const gchar   *prefix, | ||||
|                               const gchar   *action_name, | ||||
|                               gchar        **fullname) | ||||
| { | ||||
|   Action *action; | ||||
|  | ||||
|   *fullname = g_strconcat (prefix, ".", action_name, NULL); | ||||
|   action = g_hash_table_lookup (muxer->actions, *fullname); | ||||
|  | ||||
|   return action; | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_action_enabled_changed (GActionGroup *action_group, | ||||
|                                        const gchar  *action_name, | ||||
|                                        gboolean      enabled, | ||||
|                                        gpointer      user_data) | ||||
| { | ||||
|   Group *group = user_data; | ||||
|   gchar *fullname; | ||||
|   Action *action; | ||||
|   GSList *node; | ||||
|  | ||||
|   action = g_action_muxer_lookup_action (group->muxer, group->prefix, action_name, &fullname); | ||||
|   for (node = action ? action->watchers : NULL; node; node = node->next) | ||||
|     g_action_observer_action_enabled_changed (node->data, G_ACTION_OBSERVABLE (group->muxer), fullname, enabled); | ||||
|   g_action_group_action_enabled_changed (G_ACTION_GROUP (group->muxer), fullname, enabled); | ||||
|   g_free (fullname); | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_action_state_changed (GActionGroup *action_group, | ||||
|                                      const gchar  *action_name, | ||||
|                                      GVariant     *state, | ||||
|                                      gpointer      user_data) | ||||
| { | ||||
|   Group *group = user_data; | ||||
|   gchar *fullname; | ||||
|   Action *action; | ||||
|   GSList *node; | ||||
|  | ||||
|   action = g_action_muxer_lookup_action (group->muxer, group->prefix, action_name, &fullname); | ||||
|   for (node = action ? action->watchers : NULL; node; node = node->next) | ||||
|     g_action_observer_action_state_changed (node->data, G_ACTION_OBSERVABLE (group->muxer), fullname, state); | ||||
|   g_action_group_action_state_changed (G_ACTION_GROUP (group->muxer), fullname, state); | ||||
|   g_free (fullname); | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_action_added (GActionGroup *action_group, | ||||
|                              const gchar  *action_name, | ||||
|                              gpointer      user_data) | ||||
| { | ||||
|   const GVariantType *parameter_type; | ||||
|   Group *group = user_data; | ||||
|   gboolean enabled; | ||||
|   GVariant *state; | ||||
|  | ||||
|   if (g_action_group_query_action (group->group, action_name, &enabled, ¶meter_type, NULL, NULL, &state)) | ||||
|     { | ||||
|       gchar *fullname; | ||||
|       Action *action; | ||||
|       GSList *node; | ||||
|  | ||||
|       action = g_action_muxer_lookup_action (group->muxer, group->prefix, action_name, &fullname); | ||||
|  | ||||
|       for (node = action ? action->watchers : NULL; node; node = node->next) | ||||
|         g_action_observer_action_added (node->data, | ||||
|                                         G_ACTION_OBSERVABLE (group->muxer), | ||||
|                                         fullname, parameter_type, enabled, state); | ||||
|  | ||||
|       g_action_group_action_added (G_ACTION_GROUP (group->muxer), fullname); | ||||
|  | ||||
|       if (state) | ||||
|         g_variant_unref (state); | ||||
|  | ||||
|       g_free (fullname); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_action_removed (GActionGroup *action_group, | ||||
|                                const gchar  *action_name, | ||||
|                                gpointer      user_data) | ||||
| { | ||||
|   Group *group = user_data; | ||||
|   gchar *fullname; | ||||
|   Action *action; | ||||
|   GSList *node; | ||||
|  | ||||
|   action = g_action_muxer_lookup_action (group->muxer, group->prefix, action_name, &fullname); | ||||
|   for (node = action ? action->watchers : NULL; node; node = node->next) | ||||
|     g_action_observer_action_removed (node->data, G_ACTION_OBSERVABLE (group->muxer), fullname); | ||||
|   g_action_group_action_removed (G_ACTION_GROUP (group->muxer), fullname); | ||||
|   g_free (fullname); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| g_action_muxer_query_action (GActionGroup        *action_group, | ||||
|                              const gchar         *action_name, | ||||
|                              gboolean            *enabled, | ||||
|                              const GVariantType **parameter_type, | ||||
|                              const GVariantType **state_type, | ||||
|                              GVariant           **state_hint, | ||||
|                              GVariant           **state) | ||||
| { | ||||
|   GActionMuxer *muxer = G_ACTION_MUXER (action_group); | ||||
|   Group *group; | ||||
|  | ||||
|   group = g_action_muxer_find_group (muxer, &action_name); | ||||
|  | ||||
|   if (!group) | ||||
|     return FALSE; | ||||
|  | ||||
|   return g_action_group_query_action (group->group, action_name, enabled, | ||||
|                                       parameter_type, state_type, state_hint, state); | ||||
| } | ||||
|  | ||||
| static GVariant * | ||||
| get_platform_data (void) | ||||
| { | ||||
|   gchar time[32]; | ||||
|   GVariantBuilder *builder; | ||||
|   GVariant *result; | ||||
|  | ||||
|   g_snprintf (time, 32, "_TIME%d", clutter_get_current_event_time ()); | ||||
|  | ||||
|   builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); | ||||
|  | ||||
|   g_variant_builder_add (builder, "{sv}", "desktop-startup-id", | ||||
|                          g_variant_new_string (time)); | ||||
|  | ||||
|   result = g_variant_builder_end (builder); | ||||
|   g_variant_builder_unref (builder); | ||||
|  | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_activate_action (GActionGroup *action_group, | ||||
|                                 const gchar  *action_name, | ||||
|                                 GVariant     *parameter) | ||||
| { | ||||
|   GActionMuxer *muxer = G_ACTION_MUXER (action_group); | ||||
|   Group *group; | ||||
|  | ||||
|   group = g_action_muxer_find_group (muxer, &action_name); | ||||
|  | ||||
|   if (group) | ||||
|     { | ||||
|       if (G_IS_REMOTE_ACTION_GROUP (group->group)) | ||||
|         g_remote_action_group_activate_action_full (G_REMOTE_ACTION_GROUP (group->group), | ||||
|                                                     action_name, | ||||
|                                                     parameter, | ||||
|                                                     get_platform_data ()); | ||||
|       else | ||||
|         g_action_group_activate_action (group->group, action_name, parameter); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_change_action_state (GActionGroup *action_group, | ||||
|                                     const gchar  *action_name, | ||||
|                                     GVariant     *state) | ||||
| { | ||||
|   GActionMuxer *muxer = G_ACTION_MUXER (action_group); | ||||
|   Group *group; | ||||
|  | ||||
|   group = g_action_muxer_find_group (muxer, &action_name); | ||||
|  | ||||
|   if (group) | ||||
|     { | ||||
|       if (G_IS_REMOTE_ACTION_GROUP (group->group)) | ||||
|         g_remote_action_group_change_action_state_full (G_REMOTE_ACTION_GROUP (group->group), | ||||
|                                                         action_name, | ||||
|                                                         state, | ||||
|                                                         get_platform_data ()); | ||||
|       else | ||||
|         g_action_group_change_action_state (group->group, action_name, state); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_unregister_internal (Action   *action, | ||||
|                                     gpointer  observer) | ||||
| { | ||||
|   GActionMuxer *muxer = action->muxer; | ||||
|   GSList **ptr; | ||||
|  | ||||
|   for (ptr = &action->watchers; *ptr; ptr = &(*ptr)->next) | ||||
|     if ((*ptr)->data == observer) | ||||
|       { | ||||
|         *ptr = g_slist_remove (*ptr, observer); | ||||
|  | ||||
|         if (action->watchers == NULL) | ||||
|           { | ||||
|             g_hash_table_remove (muxer->actions, action->fullname); | ||||
|             g_free (action->fullname); | ||||
|  | ||||
|             g_slice_free (Action, action); | ||||
|  | ||||
|             g_object_unref (muxer); | ||||
|           } | ||||
|  | ||||
|         break; | ||||
|       } | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_weak_notify (gpointer  data, | ||||
|                             GObject  *where_the_object_was) | ||||
| { | ||||
|   Action *action = data; | ||||
|  | ||||
|   g_action_muxer_unregister_internal (action, where_the_object_was); | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_register_observer (GActionObservable *observable, | ||||
|                                   const gchar       *name, | ||||
|                                   GActionObserver   *observer) | ||||
| { | ||||
|   GActionMuxer *muxer = G_ACTION_MUXER (observable); | ||||
|   Action *action; | ||||
|  | ||||
|   action = g_hash_table_lookup (muxer->actions, name); | ||||
|  | ||||
|   if (action == NULL) | ||||
|     { | ||||
|       action = g_slice_new (Action); | ||||
|       action->muxer = g_object_ref (muxer); | ||||
|       action->fullname = g_strdup (name); | ||||
|       action->watchers = NULL; | ||||
|  | ||||
|       g_hash_table_insert (muxer->actions, action->fullname, action); | ||||
|     } | ||||
|  | ||||
|   action->watchers = g_slist_prepend (action->watchers, observer); | ||||
|   g_object_weak_ref (G_OBJECT (observer), g_action_muxer_weak_notify, action); | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_unregister_observer (GActionObservable *observable, | ||||
|                                     const gchar       *name, | ||||
|                                     GActionObserver   *observer) | ||||
| { | ||||
|   GActionMuxer *muxer = G_ACTION_MUXER (observable); | ||||
|   Action *action; | ||||
|  | ||||
|   action = g_hash_table_lookup (muxer->actions, name); | ||||
|   g_object_weak_unref (G_OBJECT (observer), g_action_muxer_weak_notify, action); | ||||
|   g_action_muxer_unregister_internal (action, observer); | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_free_group (gpointer data) | ||||
| { | ||||
|   Group *group = data; | ||||
|   gint i; | ||||
|  | ||||
|   /* 'for loop' or 'four loop'? */ | ||||
|   for (i = 0; i < 4; i++) | ||||
|     g_signal_handler_disconnect (group->group, group->handler_ids[i]); | ||||
|  | ||||
|   g_object_unref (group->group); | ||||
|   g_free (group->prefix); | ||||
|  | ||||
|   g_slice_free (Group, group); | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_finalize (GObject *object) | ||||
| { | ||||
|   GActionMuxer *muxer = G_ACTION_MUXER (object); | ||||
|  | ||||
|   g_assert_cmpint (g_hash_table_size (muxer->actions), ==, 0); | ||||
|   g_hash_table_unref (muxer->actions); | ||||
|   g_hash_table_unref (muxer->groups); | ||||
|  | ||||
|   G_OBJECT_CLASS (g_action_muxer_parent_class) | ||||
|     ->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_init (GActionMuxer *muxer) | ||||
| { | ||||
|   muxer->actions = g_hash_table_new (g_str_hash, g_str_equal); | ||||
|   muxer->groups = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_action_muxer_free_group); | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_observable_iface_init (GActionObservableInterface *iface) | ||||
| { | ||||
|   iface->register_observer = g_action_muxer_register_observer; | ||||
|   iface->unregister_observer = g_action_muxer_unregister_observer; | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_group_iface_init (GActionGroupInterface *iface) | ||||
| { | ||||
|   iface->list_actions = g_action_muxer_list_actions; | ||||
|   iface->query_action = g_action_muxer_query_action; | ||||
|   iface->activate_action = g_action_muxer_activate_action; | ||||
|   iface->change_action_state = g_action_muxer_change_action_state; | ||||
| } | ||||
|  | ||||
| static void | ||||
| g_action_muxer_class_init (GObjectClass *class) | ||||
| { | ||||
|   class->finalize = g_action_muxer_finalize; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * g_action_muxer_insert: | ||||
|  * @muxer: a #GActionMuxer | ||||
|  * @prefix: the prefix string for the action group | ||||
|  * @action_group: a #GActionGroup | ||||
|  * | ||||
|  * Adds the actions in @action_group to the list of actions provided by | ||||
|  * @muxer.  @prefix is prefixed to each action name, such that for each | ||||
|  * action <varname>x</varname> in @action_group, there is an equivalent | ||||
|  * action @prefix<literal>.</literal><varname>x</varname> in @muxer. | ||||
|  * | ||||
|  * For example, if @prefix is "<literal>app</literal>" and @action_group | ||||
|  * contains an action called "<literal>quit</literal>", then @muxer will | ||||
|  * now contain an action called "<literal>app.quit</literal>". | ||||
|  * | ||||
|  * If any #GActionObservers are registered for actions in the group, | ||||
|  * "action_added" notifications will be emitted, as appropriate. | ||||
|  * | ||||
|  * @prefix must not contain a dot ('.'). | ||||
|  */ | ||||
| void | ||||
| g_action_muxer_insert (GActionMuxer *muxer, | ||||
|                        const gchar  *prefix, | ||||
|                        GActionGroup *action_group) | ||||
| { | ||||
|   gchar **actions; | ||||
|   Group *group; | ||||
|   gint i; | ||||
|  | ||||
|   /* TODO: diff instead of ripout and replace */ | ||||
|   g_action_muxer_remove (muxer, prefix); | ||||
|  | ||||
|   group = g_slice_new (Group); | ||||
|   group->muxer = muxer; | ||||
|   group->group = g_object_ref (action_group); | ||||
|   group->prefix = g_strdup (prefix); | ||||
|  | ||||
|   g_hash_table_insert (muxer->groups, group->prefix, group); | ||||
|  | ||||
|   actions = g_action_group_list_actions (group->group); | ||||
|   for (i = 0; actions[i]; i++) | ||||
|     g_action_muxer_action_added (group->group, actions[i], group); | ||||
|   g_strfreev (actions); | ||||
|  | ||||
|   group->handler_ids[0] = g_signal_connect (group->group, "action-added", | ||||
|                                             G_CALLBACK (g_action_muxer_action_added), group); | ||||
|   group->handler_ids[1] = g_signal_connect (group->group, "action-removed", | ||||
|                                             G_CALLBACK (g_action_muxer_action_removed), group); | ||||
|   group->handler_ids[2] = g_signal_connect (group->group, "action-enabled-changed", | ||||
|                                             G_CALLBACK (g_action_muxer_action_enabled_changed), group); | ||||
|   group->handler_ids[3] = g_signal_connect (group->group, "action-state-changed", | ||||
|                                             G_CALLBACK (g_action_muxer_action_state_changed), group); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * g_action_muxer_remove: | ||||
|  * @muxer: a #GActionMuxer | ||||
|  * @prefix: the prefix of the action group to remove | ||||
|  * | ||||
|  * Removes a #GActionGroup from the #GActionMuxer. | ||||
|  * | ||||
|  * If any #GActionObservers are registered for actions in the group, | ||||
|  * "action_removed" notifications will be emitted, as appropriate. | ||||
|  */ | ||||
| void | ||||
| g_action_muxer_remove (GActionMuxer *muxer, | ||||
|                        const gchar  *prefix) | ||||
| { | ||||
|   Group *group; | ||||
|  | ||||
|   group = g_hash_table_lookup (muxer->groups, prefix); | ||||
|  | ||||
|   if (group != NULL) | ||||
|     { | ||||
|       gchar **actions; | ||||
|       gint i; | ||||
|  | ||||
|       g_hash_table_steal (muxer->groups, prefix); | ||||
|  | ||||
|       actions = g_action_group_list_actions (group->group); | ||||
|       for (i = 0; actions[i]; i++) | ||||
|         g_action_muxer_action_removed (group->group, actions[i], group); | ||||
|       g_strfreev (actions); | ||||
|  | ||||
|       g_action_muxer_free_group (group); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * g_action_muxer_new: | ||||
|  * | ||||
|  * Creates a new #GActionMuxer. | ||||
|  */ | ||||
| GActionMuxer * | ||||
| g_action_muxer_new (void) | ||||
| { | ||||
|   return g_object_new (G_TYPE_ACTION_MUXER, NULL); | ||||
| } | ||||
							
								
								
									
										53
									
								
								src/gactionmuxer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/gactionmuxer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| /* | ||||
|  * Copyright © 2011 Canonical Limited | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2 of the licence, or (at your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library; if not, write to the | ||||
|  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||||
|  * Boston, MA 02111-1307, USA. | ||||
|  * | ||||
|  * Author: Ryan Lortie <desrt@desrt.ca> | ||||
|  */ | ||||
|  | ||||
| #ifndef __G_ACTION_MUXER_H__ | ||||
| #define __G_ACTION_MUXER_H__ | ||||
|  | ||||
| #include <gio/gio.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define G_TYPE_ACTION_MUXER                                 (g_action_muxer_get_type ()) | ||||
| #define G_ACTION_MUXER(inst)                                (G_TYPE_CHECK_INSTANCE_CAST ((inst),                     \ | ||||
|                                                              G_TYPE_ACTION_MUXER, GActionMuxer)) | ||||
| #define G_IS_ACTION_MUXER(inst)                             (G_TYPE_CHECK_INSTANCE_TYPE ((inst),                     \ | ||||
|                                                              G_TYPE_ACTION_MUXER)) | ||||
|  | ||||
| typedef struct _GActionMuxer                                GActionMuxer; | ||||
|  | ||||
| G_GNUC_INTERNAL | ||||
| GType                   g_action_muxer_get_type                         (void); | ||||
| G_GNUC_INTERNAL | ||||
| GActionMuxer *          g_action_muxer_new                              (void); | ||||
|  | ||||
| G_GNUC_INTERNAL | ||||
| void                    g_action_muxer_insert                           (GActionMuxer *muxer, | ||||
|                                                                          const gchar  *prefix, | ||||
|                                                                          GActionGroup *group); | ||||
|  | ||||
| G_GNUC_INTERNAL | ||||
| void                    g_action_muxer_remove                           (GActionMuxer *muxer, | ||||
|                                                                          const gchar  *prefix); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __G_ACTION_MUXER_H__ */ | ||||
							
								
								
									
										80
									
								
								src/gactionobservable.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/gactionobservable.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| /* | ||||
|  * Copyright © 2011 Canonical Limited | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * licence or (at your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, | ||||
|  * USA. | ||||
|  * | ||||
|  * Authors: Ryan Lortie <desrt@desrt.ca> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "gactionobservable.h" | ||||
|  | ||||
| G_DEFINE_INTERFACE (GActionObservable, g_action_observable, G_TYPE_OBJECT) | ||||
|  | ||||
| /* | ||||
|  * SECTION:gactionobserable | ||||
|  * @short_description: an interface implemented by objects that report | ||||
|  *                     changes to actions | ||||
|  */ | ||||
|  | ||||
| void | ||||
| g_action_observable_default_init (GActionObservableInterface *iface) | ||||
| { | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * g_action_observable_register_observer: | ||||
|  * @observable: a #GActionObservable | ||||
|  * @action_name: the name of the action | ||||
|  * @observer: the #GActionObserver to which the events will be reported | ||||
|  * | ||||
|  * Registers @observer as being interested in changes to @action_name on | ||||
|  * @observable. | ||||
|  */ | ||||
| void | ||||
| g_action_observable_register_observer (GActionObservable *observable, | ||||
|                                        const gchar       *action_name, | ||||
|                                        GActionObserver   *observer) | ||||
| { | ||||
|   g_return_if_fail (G_IS_ACTION_OBSERVABLE (observable)); | ||||
|  | ||||
|   G_ACTION_OBSERVABLE_GET_IFACE (observable) | ||||
|     ->register_observer (observable, action_name, observer); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * g_action_observable_unregister_observer: | ||||
|  * @observable: a #GActionObservable | ||||
|  * @action_name: the name of the action | ||||
|  * @observer: the #GActionObserver to which the events will be reported | ||||
|  * | ||||
|  * Removes the registration of @observer as being interested in changes | ||||
|  * to @action_name on @observable. | ||||
|  * | ||||
|  * If the observer was registered multiple times, it must be | ||||
|  * unregistered an equal number of times. | ||||
|  */ | ||||
| void | ||||
| g_action_observable_unregister_observer (GActionObservable *observable, | ||||
|                                          const gchar       *action_name, | ||||
|                                          GActionObserver   *observer) | ||||
| { | ||||
|   g_return_if_fail (G_IS_ACTION_OBSERVABLE (observable)); | ||||
|  | ||||
|   G_ACTION_OBSERVABLE_GET_IFACE (observable) | ||||
|     ->unregister_observer (observable, action_name, observer); | ||||
| } | ||||
							
								
								
									
										64
									
								
								src/gactionobservable.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/gactionobservable.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| /* | ||||
|  * Copyright © 2011 Canonical Limited | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * licence or (at your option) any later version. | ||||
|  * | ||||
|  * This library is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, | ||||
|  * USA. | ||||
|  * | ||||
|  * Authors: Ryan Lortie <desrt@desrt.ca> | ||||
|  */ | ||||
|  | ||||
| #ifndef __G_ACTION_OBSERVABLE_H__ | ||||
| #define __G_ACTION_OBSERVABLE_H__ | ||||
|  | ||||
| #include "gactionobserver.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define G_TYPE_ACTION_OBSERVABLE                            (g_action_observable_get_type ()) | ||||
| #define G_ACTION_OBSERVABLE(inst)                           (G_TYPE_CHECK_INSTANCE_CAST ((inst),                     \ | ||||
|                                                              G_TYPE_ACTION_OBSERVABLE, GActionObservable)) | ||||
| #define G_IS_ACTION_OBSERVABLE(inst)                        (G_TYPE_CHECK_INSTANCE_TYPE ((inst),                     \ | ||||
|                                                              G_TYPE_ACTION_OBSERVABLE)) | ||||
| #define G_ACTION_OBSERVABLE_GET_IFACE(inst)                 (G_TYPE_INSTANCE_GET_INTERFACE ((inst),                  \ | ||||
|                                                              G_TYPE_ACTION_OBSERVABLE, GActionObservableInterface)) | ||||
|  | ||||
| typedef struct _GActionObservableInterface                  GActionObservableInterface; | ||||
|  | ||||
| struct _GActionObservableInterface | ||||
| { | ||||
|   GTypeInterface g_iface; | ||||
|  | ||||
|   void (* register_observer)   (GActionObservable *observable, | ||||
|                                 const gchar       *action_name, | ||||
|                                 GActionObserver   *observer); | ||||
|   void (* unregister_observer) (GActionObservable *observable, | ||||
|                                 const gchar       *action_name, | ||||
|                                 GActionObserver   *observer); | ||||
| }; | ||||
|  | ||||
| G_GNUC_INTERNAL | ||||
| GType                   g_action_observable_get_type                    (void); | ||||
| G_GNUC_INTERNAL | ||||
| void                    g_action_observable_register_observer           (GActionObservable  *observable, | ||||
|                                                                          const gchar        *action_name, | ||||
|                                                                          GActionObserver    *observer); | ||||
| G_GNUC_INTERNAL | ||||
| void                    g_action_observable_unregister_observer         (GActionObservable  *observable, | ||||
|                                                                          const gchar        *action_name, | ||||
|                                                                          GActionObserver    *observer); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __G_ACTION_OBSERVABLE_H__ */ | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user