Compare commits
	
		
			157 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | c64f195e96 | ||
|   | 247546d531 | ||
|   | 44252b052d | ||
|   | 226032d2e1 | ||
|   | 53f28074ad | ||
|   | 2993e02c33 | ||
|   | 628bfc8311 | ||
|   | 27bfaf9b35 | ||
|   | e4e87d03c5 | ||
|   | 956d89fbec | ||
|   | 1ad62527ea | ||
|   | 1d79d74e97 | ||
|   | b90183665f | ||
|   | 73fde364c8 | ||
|   | 21b05e8150 | ||
|   | e8391a726d | ||
|   | fb85a476a1 | ||
|   | 047acb887e | ||
|   | eaadeb8ef4 | ||
|   | 03946a9621 | ||
|   | 820f689f77 | ||
|   | 724f99cc62 | ||
|   | 83125c4849 | ||
|   | d8a1ce0871 | ||
|   | e156e1a438 | ||
|   | 83f3084415 | ||
|   | 81e93d083e | ||
|   | 542353b8d8 | ||
|   | 8868d3aa6d | ||
|   | c419649fe7 | ||
|   | 130c726fff | ||
|   | ac478727cc | ||
|   | 331c73002f | ||
|   | 95a587e81b | ||
|   | 38a45b4f0f | ||
|   | c730cd3296 | ||
|   | c10a18ab71 | ||
|   | ca2f7597b4 | ||
|   | 3c70435969 | ||
|   | 0a1b9867fc | ||
|   | d8177a8f3b | ||
|   | 52417a8363 | ||
|   | 8191e10665 | ||
|   | a6f39a12d7 | ||
|   | 79a42e097d | ||
|   | 4a5e276551 | ||
|   | 35abf39971 | ||
|   | c1d107a682 | ||
|   | 31f67d9142 | ||
|   | 3a0197c8db | ||
|   | c4f744d7ec | ||
|   | 61b1679719 | ||
|   | cdbb1bb665 | ||
|   | 1020d8a0f8 | ||
|   | 1f6811ca06 | ||
|   | c256154190 | ||
|   | 60225ef86d | ||
|   | 48498d83d3 | ||
|   | 14757dbd6c | ||
|   | df89d4dc59 | ||
|   | ace549c1bf | ||
|   | 1198ffd297 | ||
|   | 1aac5c43e4 | ||
|   | 4d785d249f | ||
|   | efbf102b63 | ||
|   | 4d1668b01c | ||
|   | cad6f31c1a | ||
|   | 294f59103f | ||
|   | f88f51dd99 | ||
|   | c1eaf97bc6 | ||
|   | 1420f62dfa | ||
|   | 3ff194247a | ||
|   | 36b1cd13c9 | ||
|   | bcede26d77 | ||
|   | fbf1ee8a01 | ||
|   | 1360747c9e | ||
|   | 1d95841da0 | ||
|   | 494fcfecf8 | ||
|   | 75705b45ef | ||
|   | 1ad1e48741 | ||
|   | ddb682e4fe | ||
|   | 5216b77600 | ||
|   | c93d91d80b | ||
|   | f9e3467b70 | ||
|   | 13bea1a01b | ||
|   | 76c930e471 | ||
|   | 9f6cd75170 | ||
|   | c107882828 | ||
|   | d18e084cd5 | ||
|   | 2eb779740c | ||
|   | 3ce20568d0 | ||
|   | d45ab6f15e | ||
|   | cd7197e605 | ||
|   | 3f6c1aadef | ||
|   | 29e8290b65 | ||
|   | 3074e48405 | ||
|   | 12c2939b64 | ||
|   | c7eed59562 | ||
|   | 73903400c5 | ||
|   | dc7cc9b517 | ||
|   | b18c239240 | ||
|   | 3c66f1a4d9 | ||
|   | 1dff5fb5b2 | ||
|   | e2561d15b5 | ||
|   | 326c3732b8 | ||
|   | 5dd020f2e2 | ||
|   | b6edbd46b9 | ||
|   | c330036fef | ||
|   | d0a864b9b9 | ||
|   | 9bed5b725e | ||
|   | f374ecfc75 | ||
|   | dd8ca02425 | ||
|   | ff3f9bdd7d | ||
|   | fab02ae82f | ||
|   | d43c5ec27a | ||
|   | f7de35b852 | ||
|   | cde0045851 | ||
|   | f844613292 | ||
|   | ff2e44de53 | ||
|   | 17aa8e0488 | ||
|   | a33df9b046 | ||
|   | c25f399f7c | ||
|   | bd47d07fbc | ||
|   | 72282237e1 | ||
|   | dfb44aa51d | ||
|   | 5516cad087 | ||
|   | ab60c31629 | ||
|   | 52dd030087 | ||
|   | 98240c2857 | ||
|   | 65bfd6c6d2 | ||
|   | 1034e33c35 | ||
|   | d7528b878c | ||
|   | eb2e66c539 | ||
|   | 30e9a2a7d0 | ||
|   | e842694316 | ||
|   | b33d87a762 | ||
|   | 0ff3599d91 | ||
|   | 28d79a1235 | ||
|   | 522d21154b | ||
|   | 7c231916c1 | ||
|   | a40bb67fc6 | ||
|   | 4c350b90c7 | ||
|   | 47dee22b05 | ||
|   | 13c0e575f6 | ||
|   | ea8736b13a | ||
|   | 303d53e7f5 | ||
|   | 31295dfe83 | ||
|   | 69ea4553cb | ||
|   | 0d8d77356e | ||
|   | 8b78032248 | ||
|   | ad277a563c | ||
|   | db26fb201e | ||
|   | 9f00be50d6 | ||
|   | 77d21e53d0 | ||
|   | ba0b4ba590 | ||
|   | b9fc7a3050 | ||
|   | aa053a906d | 
							
								
								
									
										93
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										93
									
								
								NEWS
									
									
									
									
									
								
							| @@ -1,3 +1,96 @@ | ||||
| 3.8.4 | ||||
| ===== | ||||
| * Fix initial text in logout dialog [Matthias; #702056] | ||||
| * Clear login messages when the user answers [John; #702458] | ||||
| * Align the "Not Listed?" label properly in the login screen [Mathieu; #702307] | ||||
| * Workaround crash causing bugs in code [Florian; #610279] | ||||
| * Improve time stamp in chat messages (frequency and formatting) | ||||
|   [Carlos; #687809, #687809] | ||||
| * Fix unlock screen after prematurely stopping curtain drag [Lionel; #703126] | ||||
| * Fix autorun notification [Matthis; 703418 | ||||
| * Fix background occasionally turning solid blue on monitor changes [Lionel: #703001] | ||||
| * Increase message tray performance [Giovanni; #700194] | ||||
| * Fix focus of notifications after they're expanded [Jasper; #698778] | ||||
| * Fix orientation of gradient on app menu in RTL locales [Jasper; #704583] | ||||
| * Support filenames in addition to file uris for background | ||||
|   [Giovanni, Ray; #702121] | ||||
| * misc bug fixes [Adel, Florian, Emilio, Alban, Jasper; #702338, #704265, | ||||
|   #698863, #698484] | ||||
|  | ||||
| Contributors: | ||||
|   Mathieu Bridon, Alban Browaeys, Giovanni Campagna, Matthias Clasen, Adel Gadllah, | ||||
|   Emilio Pozuelo Monfort, Linonel Landwerlin, Carlos Soriano, Ray Strode, | ||||
|   John Wendell | ||||
|  | ||||
| 3.8.3 | ||||
| ===== | ||||
| * Fix child menu regression introduced in 3.8.2 [Florian; #699678] | ||||
| * Fix alt-tab not always switching back to the previous window [Florian; #700356] | ||||
| * Fix VPN network icon regression introduced in 3.8.2 [Florian; #700394] | ||||
| * Allow switch-to-workspace-n keybindings in overview [Florian; #649977] | ||||
| * Update man page [Matthias; #700339] | ||||
| * Add FocusSearch DBus method [Florian; #700536] | ||||
| * gdm: Update the session chooser style [Allan; #695742] | ||||
| * Fix some app folders getting truncated at the top [Florian; #694371] | ||||
| * Fix duplicate cursors in screenshots with magnification [Florian; #700488] | ||||
| * popupMenu: Allow for an optional border for slider handle [Florian; #697917] | ||||
| * 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] | ||||
| * Tweak timeout for activating windows during XDND [Adel; #700150] | ||||
| * Fix fullscreen windows not being unredirected when legacy tray icons | ||||
|   are around [Adel; #701224] | ||||
| * 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] | ||||
| * Fix incomplete app menu if multiple actions only become available later | ||||
|   [Xavier; #694612] | ||||
| * Fix showing the OSD when a fullscreen app is unredirected [Adel, #701224] | ||||
| * window-switcher: Only show windows from current workspace by default | ||||
|   [Florian; #701214 | ||||
| * Misc bug fixes [Florian, Rui, Giovanni, Stef; #700409, #700625, #700807, | ||||
|   #700842, #700900, #700944, #700190, #700972, #700877] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Xavier Claessens, Matthias Clasen, Allan Day, | ||||
|   Adel Gadllah, Rui Matos, Florian Müllner, Carlos Soriano, Stef Walter | ||||
|  | ||||
| Translations: | ||||
|   Cheng-Chia Tseng [zh_HK, zh_TW], eternalhui [zh_CN] | ||||
|  | ||||
| 3.8.2 | ||||
| ===== | ||||
| * 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] | ||||
| * ctrlAltTab: Use symbolic icons for desktop windows [Matthias; #697914] | ||||
| * gdm: Fix regression where domain login hint not shown [Stef; #698200] | ||||
| * 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] | ||||
| * Provide a DBus API for screencasting [Florian; #696247] | ||||
| * Implement app folder keynav and shortcuts [Florian; #695314] | ||||
| * polkitAgent: Allow retrying after mistyped passwords [Stef; #684431] | ||||
| * Add input purpose and hints to StEntry and StIMText [Daiki; #691392] | ||||
| * Set input-purpose property for password entries [Rui; #700043] | ||||
| * Misc fixes and cleanups [Jasper, Florian, Giovanni, Tim, Rui; #697203, | ||||
|   #698959, #696720, #698531, #676285, #698812, #699189] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Matthias Clasen, Lionel Landwerlin, Tim Lunn, Rui Matos, | ||||
|   Simon McVittie, Marta Milakovic, Florian Müllner, Jasper St. Pierre, | ||||
|   Daiki Ueno, Stef Walter | ||||
|  | ||||
| Translations: | ||||
|   Muhammet Kara [tr], Nik Kalach [ia], Žygimantas Beručka [lt], | ||||
|   Kjartan Maraas [nb] | ||||
|  | ||||
| 3.8.1 | ||||
| ===== | ||||
| * Clip window group during startup animation [Jasper; #696323] | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| AC_PREREQ(2.63) | ||||
| AC_INIT([gnome-shell],[3.8.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell]) | ||||
| AC_INIT([gnome-shell],[3.8.4],[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,7 +63,7 @@ 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.8.1 | ||||
| MUTTER_MIN_VERSION=3.8.3 | ||||
| GTK_MIN_VERSION=3.7.9 | ||||
| GIO_MIN_VERSION=2.35.0 | ||||
| LIBECAL_MIN_VERSION=3.5.3 | ||||
| @@ -71,7 +71,7 @@ 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.3.90 | ||||
| GCR_MIN_VERSION=3.7.5 | ||||
| GNOME_DESKTOP_REQUIRED_VERSION=3.7.90 | ||||
| GNOME_MENUS_REQUIRED_VERSION=3.5.3 | ||||
| NETWORKMANAGER_MIN_VERSION=0.9.6 | ||||
| @@ -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-3 >= $GCR_MIN_VERSION) | ||||
|                                libsecret-unstable gcr-base-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) | ||||
|   | ||||
| @@ -15,6 +15,7 @@ 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 | ||||
|   | ||||
							
								
								
									
										96
									
								
								data/org.gnome.Shell.Screencast.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								data/org.gnome.Shell.Screencast.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| <!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> | ||||
| @@ -207,7 +207,7 @@ value here is from the GsmPresenceStatus enumeration.</_summary> | ||||
|       </_description> | ||||
|     </key> | ||||
|     <key type="b" name="current-workspace-only"> | ||||
|       <default>false</default> | ||||
|       <default>true</default> | ||||
|       <summary>Limit switcher to current workspace.</summary> | ||||
|       <description> | ||||
| 	If true, only windows from the current workspace are shown in the switcher. | ||||
|   | ||||
| @@ -800,6 +800,11 @@ StScrollBar StButton#vhandle:active { | ||||
|     height: 24px; | ||||
| } | ||||
|  | ||||
| .empty-dash-drop-target { | ||||
|     width: 24px; | ||||
|     height: 24px; | ||||
| } | ||||
|  | ||||
| /* Search Box */ | ||||
|  | ||||
| #searchEntry { | ||||
| @@ -887,12 +892,11 @@ StScrollBar StButton#vhandle:active { | ||||
| } | ||||
|  | ||||
| .app-view-controls { | ||||
|     width: 250px; | ||||
|     padding-bottom: 32px; | ||||
| } | ||||
|  | ||||
| .app-view-control { | ||||
|     padding: 4px 16px; | ||||
|     padding: 4px 32px; | ||||
| } | ||||
|  | ||||
| .search-display > StBoxLayout, | ||||
| @@ -2308,6 +2312,7 @@ 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, | ||||
| @@ -2338,52 +2343,47 @@ StScrollBar StButton#vhandle:active { | ||||
|     width: 15em; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list { | ||||
|     color: #ffffff; | ||||
|     font-size: 10.5pt; | ||||
| .login-dialog-session-list, | ||||
| .login-dialog-session-list-item { | ||||
|     color: #babdb6; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-button:focus, | ||||
| .login-dialog-session-list-button:active, | ||||
| .login-dialog-session-list-button:hover, | ||||
| .login-dialog-session-list-item:focus, | ||||
| .login-dialog-session-list-item:hover { | ||||
|     color: white; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-button { | ||||
|     padding: 4px; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-button:focus { | ||||
|     background-color: #4c4c4c; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-button:active { | ||||
|     background-color: #4c4c4c; | ||||
| } | ||||
|  | ||||
| .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; | ||||
|     padding: 6px; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-item:focus { | ||||
|     background-color: #666666; | ||||
| .login-dialog-session-list-item { | ||||
|     padding-bottom: 6px; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-triangle { | ||||
|     padding-right: .5em; | ||||
|     padding-right: 6px; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-item-box { | ||||
|     spacing: .25em; | ||||
|     padding-left: 6px; | ||||
|     spacing: 6px; | ||||
| } | ||||
|  | ||||
| .login-dialog-session-list-item-dot { | ||||
|     width: .75em; | ||||
|     height: .75em; | ||||
|     width: 10px; | ||||
|     height: 10px; | ||||
| } | ||||
|  | ||||
| .login-dialog-logo-bin { | ||||
|     padding: 24px 0px; | ||||
| } | ||||
|  | ||||
| .login-dialog .modal-dialog-button-box { | ||||
|   | ||||
| @@ -46,6 +46,7 @@ | ||||
|     <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"/> | ||||
|   | ||||
| @@ -78,6 +78,7 @@ nobase_dist_js_DATA = 	\ | ||||
| 	ui/popupMenu.js		\ | ||||
| 	ui/remoteSearch.js	\ | ||||
| 	ui/runDialog.js		\ | ||||
| 	ui/screencast.js	\ | ||||
| 	ui/screenshot.js	\ | ||||
|         ui/screenShield.js	\ | ||||
| 	ui/scripting.js		\ | ||||
|   | ||||
| @@ -28,6 +28,7 @@ const Mainloop = imports.mainloop; | ||||
| const Meta = imports.gi.Meta; | ||||
| const Lang = imports.lang; | ||||
| const Pango = imports.gi.Pango; | ||||
| const Realmd = imports.gdm.realmd; | ||||
| const Signals = imports.signals; | ||||
| const Shell = imports.gi.Shell; | ||||
| const St = imports.gi.St; | ||||
| @@ -39,7 +40,6 @@ const GdmUtil = imports.gdm.util; | ||||
| const Lightbox = imports.ui.lightbox; | ||||
| const Main = imports.ui.main; | ||||
| const ModalDialog = imports.ui.modalDialog; | ||||
| const Panel = imports.ui.panel; | ||||
| const PanelMenu = imports.ui.panelMenu; | ||||
| const Tweener = imports.ui.tweener; | ||||
| const UserMenu = imports.ui.userMenu; | ||||
| @@ -48,44 +48,10 @@ const UserWidget = imports.ui.userWidget; | ||||
| const _FADE_ANIMATION_TIME = 0.25; | ||||
| const _SCROLL_ANIMATION_TIME = 0.5; | ||||
| const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0; | ||||
| const _LOGO_ICON_HEIGHT = 16; | ||||
|  | ||||
| const WORK_SPINNER_ICON_SIZE = 24; | ||||
| const WORK_SPINNER_ANIMATION_DELAY = 1.0; | ||||
| const WORK_SPINNER_ANIMATION_TIME = 0.3; | ||||
| const _LOGO_ICON_HEIGHT = 48; | ||||
|  | ||||
| let _loginDialog = null; | ||||
|  | ||||
| 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', | ||||
|  | ||||
| @@ -552,6 +518,12 @@ 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 }); | ||||
| @@ -609,7 +581,6 @@ const LoginDialog = new Lang.Class({ | ||||
|         this._promptBox.add(this._promptLoginHint); | ||||
|  | ||||
|         this._signInButton = null; | ||||
|         this._workSpinner = null; | ||||
|  | ||||
|         this._sessionList = new SessionList(); | ||||
|         this._sessionList.connect('session-activated', | ||||
| @@ -644,6 +615,11 @@ const LoginDialog = new Lang.Class({ | ||||
|                                      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.backgroundStack.add_actor(this._logoBin); | ||||
|         this._updateLogo(); | ||||
|  | ||||
|         if (!this._userManager.is_loaded) | ||||
|             this._userManagerLoadedId = this._userManager.connect('notify::is-loaded', | ||||
|                                                                   Lang.bind(this, function() { | ||||
| @@ -690,6 +666,24 @@ 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(); | ||||
|  | ||||
| @@ -708,7 +702,7 @@ const LoginDialog = new Lang.Class({ | ||||
|         this._promptEntry.text = ''; | ||||
|  | ||||
|         this._updateSensitivity(true); | ||||
|         this._setWorking(false); | ||||
|         this.setWorking(false); | ||||
|     }, | ||||
|  | ||||
|     _onDefaultSessionChanged: function(client, sessionId) { | ||||
| @@ -774,11 +768,6 @@ const LoginDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _prepareDialog: function(forSecret, hold) { | ||||
|         let spinnerIcon = global.datadir + '/theme/process-working.svg'; | ||||
|         this._workSpinner = new Panel.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE); | ||||
|         this._workSpinner.actor.opacity = 0; | ||||
|         this._workSpinner.actor.show(); | ||||
|  | ||||
|         this.buttonLayout.visible = true; | ||||
|         this.clearButtons(); | ||||
|  | ||||
| @@ -791,12 +780,11 @@ const LoginDialog = new Lang.Class({ | ||||
|                              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.placeSpinner({ 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(); | ||||
|                                                       }), | ||||
| @@ -849,7 +837,7 @@ const LoginDialog = new Lang.Class({ | ||||
|             this._promptEntryActivateId = 0; | ||||
|         } | ||||
|  | ||||
|         this._setWorking(false); | ||||
|         this.setWorking(false); | ||||
|         this._promptBox.hide(); | ||||
|         this._promptLoginHint.hide(); | ||||
|  | ||||
| @@ -862,36 +850,9 @@ const LoginDialog = new Lang.Class({ | ||||
|         this._promptLoginHint.hide(); | ||||
|  | ||||
|         this.clearButtons(); | ||||
|         this._workSpinner = null; | ||||
|         this._signInButton = 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) { | ||||
|         this._promptLabel.set_text(question); | ||||
|  | ||||
| @@ -906,7 +867,7 @@ const LoginDialog = new Lang.Class({ | ||||
|                      function() { | ||||
|                          let text = this._promptEntry.get_text(); | ||||
|                          this._updateSensitivity(false); | ||||
|                          this._setWorking(true); | ||||
|                          this.setWorking(true); | ||||
|                          this._userVerifier.answerQuery(serviceName, text); | ||||
|                      }]; | ||||
|  | ||||
| @@ -914,17 +875,40 @@ 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); | ||||
|   | ||||
| @@ -63,7 +63,7 @@ const Manager = new Lang.Class({ | ||||
|                                            Lang.bind(this, this._reloadRealms)) | ||||
|         this._realms = {}; | ||||
|  | ||||
|         this._aggregateProvider.connect('g-properties-changed', | ||||
|         this._signalId = 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(); | ||||
|                                     this._reloadRealm(realm); | ||||
|                                 })); | ||||
|     }, | ||||
|  | ||||
| @@ -134,6 +134,18 @@ 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,7 +9,6 @@ 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; | ||||
| @@ -117,7 +116,6 @@ 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; | ||||
| @@ -166,6 +164,7 @@ 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', | ||||
| @@ -377,30 +376,11 @@ 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, ''); | ||||
|     }, | ||||
|  | ||||
| @@ -476,11 +456,6 @@ 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,6 +58,7 @@ const Map = new Lang.Class({ | ||||
|  | ||||
|     _init: function(iterable) { | ||||
|         this._pool = { }; | ||||
|         this._size = 0; | ||||
|  | ||||
|         if (iterable) { | ||||
|             for (let i = 0; i < iterable.length; i++) { | ||||
| @@ -99,6 +100,7 @@ const Map = new Lang.Class({ | ||||
|             node.value = value; | ||||
|         } else { | ||||
|             this._pool[hash] = { key: key, value: value }; | ||||
|             this._size++; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -108,6 +110,7 @@ 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]; | ||||
| @@ -136,6 +139,6 @@ const Map = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     size: function() { | ||||
|         return Object.getOwnPropertyNames(this._pool).length; | ||||
|         return this._size; | ||||
|     }, | ||||
| }); | ||||
|   | ||||
| @@ -234,7 +234,7 @@ const AppSwitcherPopup = new Lang.Class({ | ||||
|     _finish : function(timestamp) { | ||||
|         let appIcon = this._items[this._selectedIndex]; | ||||
|         if (this._currentWindow < 0) | ||||
|             appIcon.app.activate_full(-1, timestamp); | ||||
|             appIcon.app.activate_window(appIcon.cachedWindows[0], timestamp); | ||||
|         else | ||||
|             Main.activateWindow(appIcon.cachedWindows[this._currentWindow], timestamp); | ||||
|  | ||||
|   | ||||
| @@ -187,6 +187,9 @@ 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); | ||||
| @@ -276,8 +279,12 @@ 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; | ||||
|                 } | ||||
|             })); | ||||
|     }, | ||||
|  | ||||
| @@ -327,6 +334,42 @@ 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', | ||||
|  | ||||
| @@ -367,9 +410,9 @@ const AppDisplay = new Lang.Class({ | ||||
|                                           x_expand: true, y_expand: true }); | ||||
|         this.actor.add(this._viewStack, { expand: true }); | ||||
|  | ||||
|         let layout = new Clutter.BoxLayout({ homogeneous: true }); | ||||
|         this._controls = new St.Widget({ style_class: 'app-view-controls', | ||||
|                                          layout_manager: layout }); | ||||
|         let layout = new ControlsBoxLayout({ homogeneous: true }); | ||||
|         this._controls = new St.Widget({ style_class: 'app-view-controls' }); | ||||
|         this._controls.set_layout_manager(layout); | ||||
|         this.actor.add(new St.Bin({ child: this._controls })); | ||||
|  | ||||
|  | ||||
| @@ -572,7 +615,11 @@ const FolderIcon = new Lang.Class({ | ||||
|         // Position the popup above or below the source icon | ||||
|         if (side == St.Side.BOTTOM) { | ||||
|             this._popup.actor.show(); | ||||
|             this._popup.actor.y = this.actor.y - this._popup.actor.height; | ||||
|             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.hide(); | ||||
|         } else { | ||||
|             this._popup.actor.y = this.actor.y + this.actor.height; | ||||
| @@ -595,6 +642,7 @@ 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, | ||||
| @@ -618,17 +666,31 @@ const AppFolderPopup = new Lang.Class({ | ||||
|         this.actor.add_actor(this._boxPointer.actor); | ||||
|         this._boxPointer.bin.set_child(this._view.actor); | ||||
|  | ||||
|         let closeButton = Util.makeCloseButton(); | ||||
|         closeButton.connect('clicked', Lang.bind(this, this.popdown)); | ||||
|         this.actor.add_actor(closeButton); | ||||
|         this.closeButton = Util.makeCloseButton(); | ||||
|         this.closeButton.connect('clicked', Lang.bind(this, this.popdown)); | ||||
|         this.actor.add_actor(this.closeButton); | ||||
|  | ||||
|         this._boxPointer.actor.bind_property('opacity', closeButton, 'opacity', | ||||
|         this._boxPointer.actor.bind_property('opacity', this.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() { | ||||
| @@ -643,6 +705,7 @@ 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 | | ||||
|   | ||||
| @@ -318,9 +318,9 @@ const Background = new Lang.Class({ | ||||
|         this._cancellable = new Gio.Cancellable(); | ||||
|         this.isLoaded = false; | ||||
|  | ||||
|         this._settings.connect('changed', Lang.bind(this, function() { | ||||
|                                    this.emit('changed'); | ||||
|                                })); | ||||
|         this._settingsChangedSignalId = this._settings.connect('changed', Lang.bind(this, function() { | ||||
|                                             this.emit('changed'); | ||||
|                                         })); | ||||
|  | ||||
|         this._load(); | ||||
|     }, | ||||
| @@ -361,6 +361,10 @@ const Background = new Lang.Class({ | ||||
|  | ||||
|         this.actor.disconnect(this._destroySignalId); | ||||
|         this._destroySignalId = 0; | ||||
|  | ||||
|         if (this._settingsChangedSignalId != 0) | ||||
|             this._settings.disconnect(this._settingsChangedSignalId); | ||||
|         this._settingsChangedSignalId = 0; | ||||
|     }, | ||||
|  | ||||
|     _setLoaded: function() { | ||||
| @@ -571,7 +575,16 @@ const Background = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         let uri = this._settings.get_string(PICTURE_URI_KEY); | ||||
|         let filename = Gio.File.new_for_uri(uri).get_path(); | ||||
|         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; | ||||
|         } | ||||
|  | ||||
|         this._loadFile(filename); | ||||
|     }, | ||||
|   | ||||
| @@ -46,8 +46,10 @@ 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) { | ||||
|   | ||||
| @@ -589,12 +589,12 @@ const BoxPointer = new Lang.Class({ | ||||
|                 return St.Side.TOP; | ||||
|             break; | ||||
|         case St.Side.LEFT: | ||||
|             if (sourceAllocation.y2 + boxWidth > monitor.x + monitor.width && | ||||
|             if (sourceAllocation.x2 + boxWidth > monitor.x + monitor.width && | ||||
|                 boxWidth < sourceAllocation.x1 - monitor.x) | ||||
|                 return St.Side.RIGHT; | ||||
|             break; | ||||
|         case St.Side.RIGHT: | ||||
|             if (sourceAllocation.y1 - boxWidth < monitor.x && | ||||
|             if (sourceAllocation.x1 - boxWidth < monitor.x && | ||||
|                 boxWidth < monitor.x + monitor.width - sourceAllocation.x2) | ||||
|                 return St.Side.LEFT; | ||||
|             break; | ||||
|   | ||||
| @@ -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('hide-prompt', Lang.bind(this, this._onHidePrompt)); | ||||
|         this.prompt.connect('prompt-close', Lang.bind(this, this._onHidePrompt)); | ||||
|  | ||||
|         let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout', | ||||
|                                                 vertical: false }); | ||||
| @@ -63,11 +63,17 @@ const KeyringDialog = new Lang.Class({ | ||||
|  | ||||
|         this._cancelButton = this.addButton({ label: '', | ||||
|                                               action: Lang.bind(this, this._onCancelButton), | ||||
|                                               key: Clutter.Escape }); | ||||
|                                               key: Clutter.Escape }, | ||||
|                                             { expand: true, x_fill: false, x_align: St.Align.START }); | ||||
|         this.placeSpinner({ expand: false, | ||||
|                             x_fill: false, | ||||
|                             y_fill: false, | ||||
|                             x_align: St.Align.END, | ||||
|                             y_align: St.Align.MIDDLE }); | ||||
|         this._continueButton = this.addButton({ label: '', | ||||
|                                                 action: Lang.bind(this, this._onContinueButton), | ||||
|                                                 default: true }, | ||||
|                                               { expand: true, x_fill: false, x_align: St.Align.END }); | ||||
|                                               { expand: false, 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); | ||||
| @@ -143,11 +149,19 @@ const KeyringDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _updateSensitivity: function(sensitive) { | ||||
|         this._passwordEntry.reactive = sensitive; | ||||
|         this._passwordEntry.clutter_text.editable = 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._continueButton.can_focus = sensitive; | ||||
|         this._continueButton.reactive = sensitive; | ||||
|         this.setWorking(!sensitive); | ||||
|     }, | ||||
|  | ||||
|     _ensureOpen: function() { | ||||
|   | ||||
| @@ -31,7 +31,6 @@ 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 }); | ||||
| @@ -161,26 +160,32 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|  | ||||
|         this._cancelButton = this.addButton({ label: _("Cancel"), | ||||
|                                               action: Lang.bind(this, this.cancel), | ||||
|                                               key: Clutter.Escape }); | ||||
|                                               key: Clutter.Escape }, | ||||
|                                             { expand: true, x_fill: false, x_align: St.Align.START }); | ||||
|         this.placeSpinner({ expand: false, | ||||
|                             x_fill: false, | ||||
|                             y_fill: false, | ||||
|                             x_align: St.Align.END, | ||||
|                             y_align: St.Align.MIDDLE }); | ||||
|         this._okButton = this.addButton({ label:  _("Authenticate"), | ||||
|                                           action: Lang.bind(this, this._onAuthenticateButtonPressed), | ||||
|                                           default: true }, | ||||
|                                         { expand: true, x_fill: false, x_align: St.Align.END }); | ||||
|                                         { expand: false, 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(); | ||||
|     }, | ||||
|  | ||||
| @@ -202,14 +207,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(false, true); | ||||
|             this._emitDone(true); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _emitDone: function(keepVisible, dismissed) { | ||||
|     _emitDone: function(dismissed) { | ||||
|         if (!this._doneEmitted) { | ||||
|             this._doneEmitted = true; | ||||
|             this.emit('done', keepVisible, dismissed); | ||||
|             this.emit('done', dismissed); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -219,6 +224,7 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|  | ||||
|         this._okButton.can_focus = sensitive; | ||||
|         this._okButton.reactive = sensitive; | ||||
|         this.setWorking(!sensitive); | ||||
|     }, | ||||
|  | ||||
|     _onEntryActivate: function() { | ||||
| @@ -237,12 +243,16 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _onSessionCompleted: function(session, gainedAuthorization) { | ||||
|         if (this._completed) | ||||
|         if (this._completed || this._doneEmitted) | ||||
|             return; | ||||
|  | ||||
|         this._completed = true; | ||||
|  | ||||
|         if (!gainedAuthorization) { | ||||
|         /* Yay, all done */ | ||||
|         if (gainedAuthorization) { | ||||
|             this._emitDone(false); | ||||
|  | ||||
|         } else { | ||||
|             /* 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), | ||||
| @@ -258,8 +268,10 @@ 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) { | ||||
| @@ -303,6 +315,7 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|         if (this._session) { | ||||
|             if (!this._completed) | ||||
|                 this._session.cancel(); | ||||
|             this._completed = false; | ||||
|             this._session = null; | ||||
|         } | ||||
|     }, | ||||
| @@ -317,7 +330,7 @@ const AuthenticationDialog = new Lang.Class({ | ||||
|     cancel: function() { | ||||
|         this._wasDismissed = true; | ||||
|         this.close(global.get_current_time()); | ||||
|         this._emitDone(false, true); | ||||
|         this._emitDone(true); | ||||
|     }, | ||||
| }); | ||||
| Signals.addSignalMethods(AuthenticationDialog.prototype); | ||||
| @@ -327,7 +340,6 @@ 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)); | ||||
| @@ -364,45 +376,24 @@ const AuthenticationAgent = new Lang.Class({ | ||||
|         // discussion. | ||||
|  | ||||
|         this._currentDialog.connect('done', Lang.bind(this, this._onDialogDone)); | ||||
|         this._currentDialog.startAuthentication(); | ||||
|         this._currentDialog.performAuthentication(); | ||||
|     }, | ||||
|  | ||||
|     _onCancel: function(nativeAgent) { | ||||
|         this._completeRequest(false, false); | ||||
|         this._completeRequest(false); | ||||
|     }, | ||||
|  | ||||
|     _onDialogDone: function(dialog, keepVisible, dismissed) { | ||||
|         this._completeRequest(keepVisible, dismissed); | ||||
|     _onDialogDone: function(dialog, dismissed) { | ||||
|         this._completeRequest(dismissed); | ||||
|     }, | ||||
|  | ||||
|     _reallyCompleteRequest: function(dismissed) { | ||||
|     _completeRequest: 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; | ||||
|   | ||||
| @@ -18,7 +18,7 @@ const Params = imports.misc.params; | ||||
| const PopupMenu = imports.ui.popupMenu; | ||||
|  | ||||
| // See Notification.appendMessage | ||||
| const SCROLLBACK_IMMEDIATE_TIME = 60; // 1 minute | ||||
| const SCROLLBACK_IMMEDIATE_TIME = 3 * 60; // 3 minutes | ||||
| const SCROLLBACK_RECENT_TIME = 15 * 60; // 15 minutes | ||||
| const SCROLLBACK_RECENT_LENGTH = 20; | ||||
| const SCROLLBACK_IDLE_LENGTH = 5; | ||||
| @@ -967,7 +967,8 @@ 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 }, | ||||
|                                        childProps: { expand: true, x_fill: false, | ||||
|                                                      x_align: St.Align.END }, | ||||
|                                        noTimestamp: true, | ||||
|                                        timestamp: lastMessageTime }); | ||||
|  | ||||
|   | ||||
| @@ -89,19 +89,25 @@ 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.overview.visible) { | ||||
|         if (Main.sessionMode.hasWindows && !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; | ||||
|                 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 = 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'); | ||||
|                 } | ||||
|  | ||||
|                 items.push({ name: windows[i].title, | ||||
|                              proxy: windows[i].get_compositor_private(), | ||||
|                              focusCallback: Lang.bind(windows[i], | ||||
| @@ -109,6 +115,7 @@ const CtrlAltTabManager = new Lang.Class({ | ||||
|                                      Main.activateWindow(this, timestamp); | ||||
|                                  }), | ||||
|                              iconActor: icon, | ||||
|                              iconName: iconName, | ||||
|                              sortGroup: SortGroup.MIDDLE }); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -326,6 +326,16 @@ 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, | ||||
| @@ -441,6 +451,12 @@ 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() { | ||||
| @@ -457,6 +473,7 @@ const Dash = new Lang.Class({ | ||||
|  | ||||
|     _endDrag: function() { | ||||
|         this._clearDragPlaceholder(); | ||||
|         this._clearEmptyDropTarget(); | ||||
|         this._showAppsIcon.setDragApp(null); | ||||
|         DND.removeDragMonitor(this._dragMonitor); | ||||
|     }, | ||||
| @@ -797,9 +814,21 @@ 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; | ||||
|         } | ||||
|         this._dragPlaceholderPos = -1; | ||||
|     }, | ||||
|  | ||||
|     _clearEmptyDropTarget: function() { | ||||
|         if (this._emptyDropTarget) { | ||||
|             this._emptyDropTarget.animateOutAndDestroy(); | ||||
|             this._emptyDropTarget = null; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
| @@ -827,23 +856,18 @@ const Dash = new Lang.Class({ | ||||
|             numChildren--; | ||||
|         } | ||||
|  | ||||
|         let pos = Math.floor(y * numChildren / boxHeight); | ||||
|         let pos; | ||||
|         if (!this._emptyDropTarget) | ||||
|             pos = Math.floor(y * numChildren / boxHeight); | ||||
|         else | ||||
|             pos = 0; // always insert at the top when dash is empty | ||||
|  | ||||
|         if (pos != this._dragPlaceholderPos && pos <= numFavorites && this._animatingPlaceholdersCount == 0) { | ||||
|             this._dragPlaceholderPos = pos; | ||||
|  | ||||
|             // Don't allow positioning before or after self | ||||
|             if (favPos != -1 && (pos == favPos || pos == favPos + 1)) { | ||||
|                 if (this._dragPlaceholder) { | ||||
|                     this._dragPlaceholder.animateOutAndDestroy(); | ||||
|                     this._animatingPlaceholdersCount++; | ||||
|                     this._dragPlaceholder.connect('destroy', | ||||
|                         Lang.bind(this, function() { | ||||
|                             this._animatingPlaceholdersCount--; | ||||
|                         })); | ||||
|                 } | ||||
|                 this._dragPlaceholder = null; | ||||
|  | ||||
|                 this._clearDragPlaceholder(); | ||||
|                 return DND.DragMotionResult.CONTINUE; | ||||
|             } | ||||
|  | ||||
| @@ -868,9 +892,9 @@ const Dash = new Lang.Class({ | ||||
|  | ||||
|         // Remove the drag placeholder if we are not in the | ||||
|         // "favorites zone" | ||||
|         if (pos > numFavorites && this._dragPlaceholder) { | ||||
|         if (pos > numFavorites) | ||||
|             this._clearDragPlaceholder(); | ||||
|         } | ||||
|  | ||||
|         if (!this._dragPlaceholder) | ||||
|             return DND.DragMotionResult.NO_DROP; | ||||
|  | ||||
|   | ||||
| @@ -100,7 +100,6 @@ const DateMenuButton = new Lang.Class({ | ||||
|  | ||||
|         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) { | ||||
| @@ -157,14 +156,16 @@ const DateMenuButton = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _appInstalledChanged: function() { | ||||
|         let app = Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop'); | ||||
|         this._openClocksItem.actor.visible = app !== null; | ||||
|         this._calendarApp = undefined; | ||||
|         this._updateEventsVisibility(); | ||||
|     }, | ||||
|  | ||||
|     _updateEventsVisibility: function() { | ||||
|         let visible = this._eventSource.hasCalendars; | ||||
|         this._openCalendarItem.actor.visible = visible; | ||||
|         this._openClocksItem.actor.visible = visible; | ||||
|         this._openCalendarItem.actor.visible = visible && | ||||
|             (this._getCalendarApp() != null); | ||||
|         this._openClocksItem.actor.visible = visible && | ||||
|             (this._getClockApp() != null); | ||||
|         this._separator.visible = visible; | ||||
|         if (visible) { | ||||
|           let alignment = 0.25; | ||||
| @@ -217,18 +218,34 @@ 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 = Gio.AppInfo.get_default_for_type('text/calendar', false); | ||||
|         if (app.get_id() == 'evolution') | ||||
|             app = Gio.DesktopAppInfo.new('evolution-calendar'); | ||||
|         let app = this._getCalendarApp(); | ||||
|         if (app.get_id() == 'evolution.desktop') | ||||
|             app = Gio.DesktopAppInfo.new('evolution-calendar.desktop'); | ||||
|         app.launch([], global.create_app_launch_context()); | ||||
|     }, | ||||
|  | ||||
|     _onOpenClocksActivate: function() { | ||||
|         this.menu.close(); | ||||
|         let app = Shell.AppSystem.get_default().lookup_app('gnome-clocks.desktop'); | ||||
|         let app = this._getClockApp(); | ||||
|         app.activate(); | ||||
|     } | ||||
| }); | ||||
|   | ||||
| @@ -149,16 +149,16 @@ const _Draggable = new Lang.Class({ | ||||
|  | ||||
|     _grabEvents: function() { | ||||
|         if (!this._eventsGrabbed) { | ||||
|             Clutter.grab_pointer(_getEventHandlerActor()); | ||||
|             Clutter.grab_keyboard(_getEventHandlerActor()); | ||||
|             this._eventsGrabbed = true; | ||||
|             this._eventsGrabbed = Main.pushModal(_getEventHandlerActor()); | ||||
|             if (this._eventsGrabbed) | ||||
|                 Clutter.grab_pointer(_getEventHandlerActor()); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _ungrabEvents: function() { | ||||
|         if (this._eventsGrabbed) { | ||||
|             Clutter.ungrab_pointer(); | ||||
|             Clutter.ungrab_keyboard(); | ||||
|             Main.popModal(_getEventHandlerActor()); | ||||
|             this._eventsGrabbed = false; | ||||
|         } | ||||
|     }, | ||||
|   | ||||
| @@ -420,6 +420,7 @@ 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() { | ||||
|   | ||||
| @@ -5,6 +5,8 @@ imports.gi.versions.Gio = '2.0'; | ||||
| imports.gi.versions.Gdk = '3.0'; | ||||
| imports.gi.versions.GdkPixbuf = '2.0'; | ||||
| imports.gi.versions.Gtk = '3.0'; | ||||
| imports.gi.versions.TelepathyGLib = '0.12'; | ||||
| imports.gi.versions.TelepathyLogger = '0.2'; | ||||
|  | ||||
| const Clutter = imports.gi.Clutter;; | ||||
| const Gettext = imports.gettext; | ||||
|   | ||||
| @@ -347,7 +347,7 @@ const LayoutManager = new Lang.Class({ | ||||
|                               BackgroundMenu.addBackgroundMenu(bgManager.background.actor); | ||||
|                           })); | ||||
|  | ||||
|         this._bgManagers.push(bgManager); | ||||
|         this._bgManagers[monitorIndex] = bgManager; | ||||
|  | ||||
|         return bgManager.background; | ||||
|     }, | ||||
| @@ -728,6 +728,8 @@ 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); | ||||
|     }, | ||||
|  | ||||
| @@ -1092,12 +1094,21 @@ const HotCorner = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         if (size > 0) { | ||||
|             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 }); | ||||
|             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._pressureBarrier.addBarrier(this._verticalBarrier); | ||||
|             this._pressureBarrier.addBarrier(this._horizontalBarrier); | ||||
|   | ||||
| @@ -38,7 +38,6 @@ 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); | ||||
|  | ||||
| let componentManager = null; | ||||
| @@ -68,7 +67,7 @@ let layoutManager = null; | ||||
| let _startDate; | ||||
| let _defaultCssStylesheet = null; | ||||
| let _cssStylesheet = null; | ||||
| let _overridesSettings = null; | ||||
| let _workspacesSettings = null; | ||||
|  | ||||
| function _sessionUpdated() { | ||||
|     _loadDefaultStylesheet(); | ||||
| @@ -106,6 +105,7 @@ function start() { | ||||
|  | ||||
| function _sessionsLoaded() { | ||||
|     sessionMode.connect('updated', _sessionUpdated); | ||||
|     _initializePrefs(); | ||||
|     _initializeUI(); | ||||
|  | ||||
|     shellDBusService = new ShellDBus.GnomeShell(); | ||||
| @@ -114,6 +114,21 @@ 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); | ||||
|  | ||||
|     let workspacesSchema; | ||||
|     if (keys.indexOf('dynamic-workspaces') > -1) | ||||
|         workspacesSchema = sessionMode.overridesSchema; | ||||
|     else | ||||
|         workspacesSchema = 'org.gnome.mutter'; | ||||
|  | ||||
|      _workspacesSettings = new Gio.Settings({ schema: workspacesSchema }); | ||||
|      _workspacesSettings.connect('changed::dynamic-workspaces', _queueCheckWorkspaces); | ||||
| } | ||||
|  | ||||
| function _initializeUI() { | ||||
|     // Ensure ShellWindowTracker and ShellAppUsage are initialized; this will | ||||
|     // also initialize ShellAppSystem first.  ShellAppSystem | ||||
| @@ -179,9 +194,6 @@ 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); | ||||
|   | ||||
| @@ -1530,11 +1530,7 @@ const MessageTrayContextMenu = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _updateClearSensitivity: function() { | ||||
|         let sources = this._tray.getSources(); | ||||
|         sources = sources.filter(function(source) { | ||||
|             return !source.trayIcon && !source.isChat && !source.resident; | ||||
|         }); | ||||
|         this._clearItem.setSensitive(sources.length > 0); | ||||
|         this._clearItem.setSensitive(this._tray.clearableCount > 0); | ||||
|     }, | ||||
|  | ||||
|     setPosition: function(x, y) { | ||||
| @@ -1661,6 +1657,8 @@ const MessageTray = new Lang.Class({ | ||||
|         this._desktopClone = null; | ||||
|         this._inCtrlAltTab = false; | ||||
|  | ||||
|         this.clearableCount = 0; | ||||
|  | ||||
|         this._lightbox = new Lightbox.Lightbox(global.overlay_group, | ||||
|                                                { inhibitEvents: true, | ||||
|                                                  fadeInTime: ANIMATION_TIME, | ||||
| @@ -1899,6 +1897,9 @@ 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)); | ||||
| @@ -1940,6 +1941,9 @@ 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); | ||||
| @@ -2245,10 +2249,15 @@ 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 = (this._clickedSummaryItemMouseButton == 1 && this._clickedSummaryItem.source.notifications.length == 0); | ||||
|         let wrongSummaryNotificationStack = (this._clickedSummaryItemMouseButton == 1 && | ||||
|         let requestedNotificationStackIsEmpty = (haveClickedSummaryItem && | ||||
|                                                  this._clickedSummaryItemMouseButton == 1 && | ||||
|                                                  this._clickedSummaryItem.source.notifications.length == 0); | ||||
|         let wrongSummaryNotificationStack = (haveClickedSummaryItem && | ||||
|                                              this._clickedSummaryItemMouseButton == 1 && | ||||
|                                              this._summaryBoxPointer.bin.child != this._clickedSummaryItem.notificationStackWidget); | ||||
|         let wrongSummaryRightClickMenu = (this._clickedSummaryItemMouseButton == 3 && | ||||
|         let wrongSummaryRightClickMenu = (haveClickedSummaryItem && | ||||
|                                           this._clickedSummaryItemMouseButton == 3 && | ||||
|                                           this._clickedSummaryItem.rightClickMenu != null && | ||||
|                                           this._summaryBoxPointer.bin.child != this._clickedSummaryItem.rightClickMenu); | ||||
|         let wrongSummaryBoxPointer = (haveClickedSummaryItem && | ||||
|                                       (wrongSummaryNotificationStack || wrongSummaryRightClickMenu)); | ||||
| @@ -2595,16 +2604,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() { | ||||
|   | ||||
| @@ -22,6 +22,10 @@ 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, | ||||
| @@ -65,7 +69,9 @@ 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._backgroundBin = new St.Bin(); | ||||
|         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._monitorConstraint = new Layout.MonitorConstraint(); | ||||
|         this._backgroundBin.add_constraint(this._monitorConstraint); | ||||
|         this._group.add_actor(this._backgroundBin); | ||||
| @@ -81,15 +87,10 @@ 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 }); | ||||
|             stack.add_actor(this._eventBlocker); | ||||
|             stack.add_actor(this.dialogLayout); | ||||
|         } else { | ||||
|             this._backgroundBin.child = this.dialogLayout; | ||||
|             this.backgroundStack.add_actor(this._eventBlocker); | ||||
|         } | ||||
|         this.backgroundStack.add_actor(this.dialogLayout); | ||||
|  | ||||
|  | ||||
|         this.contentLayout = new St.BoxLayout({ vertical: true }); | ||||
| @@ -110,6 +111,8 @@ const ModalDialog = new Lang.Class({ | ||||
|         this._initialKeyFocus = this.dialogLayout; | ||||
|         this._initialKeyFocusDestroyId = 0; | ||||
|         this._savedKeyFocus = null; | ||||
|  | ||||
|         this._workSpinner = null; | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
| @@ -183,6 +186,44 @@ const ModalDialog = new Lang.Class({ | ||||
|         return button; | ||||
|     }, | ||||
|  | ||||
|     placeSpinner: function(layoutInfo) { | ||||
|         /* This is here because of recursive imports */ | ||||
|         const Panel = imports.ui.panel; | ||||
|         let spinnerIcon = global.datadir + '/theme/process-working.svg'; | ||||
|         this._workSpinner = new Panel.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,6 +8,7 @@ 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; | ||||
| @@ -71,6 +72,7 @@ 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, | ||||
| @@ -80,6 +82,15 @@ 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 }); | ||||
|  | ||||
| @@ -125,8 +136,10 @@ 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, | ||||
| @@ -154,7 +167,11 @@ const OsdWindow = new Lang.Class({ | ||||
|                          { opacity: 0, | ||||
|                            time: FADE_TIME, | ||||
|                            transition: 'easeOutQuad', | ||||
|                            onComplete: Lang.bind(this, this._reset) }); | ||||
|                            onComplete: Lang.bind(this, function() { | ||||
|                               this._reset(); | ||||
|                               Meta.enable_unredirect_for_screen(global.screen); | ||||
|                            }) | ||||
|                          }); | ||||
|     }, | ||||
|  | ||||
|     _reset: function() { | ||||
| @@ -169,11 +186,25 @@ const OsdWindow = new Lang.Class({ | ||||
|         let scalew = monitor.width / 640.0; | ||||
|         let scaleh = monitor.height / 480.0; | ||||
|         let scale = Math.min(scalew, scaleh); | ||||
|         let size = 110 * Math.max(1, scale); | ||||
|         this._popupSize = 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(); | ||||
|     }, | ||||
|  | ||||
|         this._icon.icon_size = size / 2; | ||||
|     _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)); | ||||
|     } | ||||
| }); | ||||
|   | ||||
| @@ -31,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 = 1250; | ||||
| const DND_WINDOW_SWITCH_TIMEOUT = 750; | ||||
|  | ||||
| const OVERVIEW_ACTIVATION_TIMEOUT = 0.5; | ||||
|  | ||||
| @@ -461,6 +461,7 @@ const Overview = new Lang.Class({ | ||||
|  | ||||
|     beginItemDrag: function(source) { | ||||
|         this.emit('item-drag-begin'); | ||||
|         this._inDrag = true; | ||||
|     }, | ||||
|  | ||||
|     cancelledItemDrag: function(source) { | ||||
| @@ -469,10 +470,12 @@ 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) { | ||||
| @@ -481,6 +484,7 @@ const Overview = new Lang.Class({ | ||||
|  | ||||
|     endWindowDrag: function(source) { | ||||
|         this.emit('window-drag-end'); | ||||
|         this._inDrag = false; | ||||
|     }, | ||||
|  | ||||
|     // show: | ||||
| @@ -499,6 +503,11 @@ const Overview = new Lang.Class({ | ||||
|         this._animateVisible(); | ||||
|     }, | ||||
|  | ||||
|     focusSearch: function() { | ||||
|         this.show(); | ||||
|         this._searchEntry.grab_key_focus(); | ||||
|     }, | ||||
|  | ||||
|     fadeInDesktop: function() { | ||||
|             this._desktopFade.opacity = 0; | ||||
|             this._desktopFade.show(); | ||||
| @@ -604,6 +613,8 @@ 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; | ||||
|   | ||||
| @@ -289,10 +289,10 @@ const AppMenuButton = new Lang.Class({ | ||||
|         this._visible = !Main.overview.visible; | ||||
|         if (!this._visible) | ||||
|             this.actor.hide(); | ||||
|         Main.overview.connect('hiding', Lang.bind(this, function () { | ||||
|         this._overviewHidingId = Main.overview.connect('hiding', Lang.bind(this, function () { | ||||
|             this.show(); | ||||
|         })); | ||||
|         Main.overview.connect('showing', Lang.bind(this, function () { | ||||
|         this._overviewShowingId = Main.overview.connect('showing', Lang.bind(this, function () { | ||||
|             this.hide(); | ||||
|         })); | ||||
|  | ||||
| @@ -302,10 +302,12 @@ const AppMenuButton = new Lang.Class({ | ||||
|  | ||||
|         let tracker = Shell.WindowTracker.get_default(); | ||||
|         let appSys = Shell.AppSystem.get_default(); | ||||
|         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._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)); | ||||
|  | ||||
|         this._sync(); | ||||
|     }, | ||||
| @@ -369,13 +371,16 @@ const AppMenuButton = new Lang.Class({ | ||||
|         this._updateIconBoxClip(); | ||||
|     }, | ||||
|  | ||||
|     _syncIcon: function() { | ||||
|         let icon = this._targetApp.get_faded_icon(2 * PANEL_ICON_SIZE, this._iconBox.text_direction); | ||||
|         this._iconBox.set_child(icon); | ||||
|     }, | ||||
|  | ||||
|     _onIconThemeChanged: function() { | ||||
|         if (this._iconBox.child == null) | ||||
|             return; | ||||
|  | ||||
|         this._iconBox.child.destroy(); | ||||
|         let icon = this._targetApp.get_faded_icon(2 * PANEL_ICON_SIZE); | ||||
|         this._iconBox.set_child(icon); | ||||
|         this._syncIcon(); | ||||
|     }, | ||||
|  | ||||
|     _updateIconBoxClip: function() { | ||||
| @@ -593,12 +598,10 @@ const AppMenuButton = new Lang.Class({ | ||||
|         } | ||||
|  | ||||
|         this._targetApp = targetApp; | ||||
|         let icon = targetApp.get_faded_icon(2 * PANEL_ICON_SIZE); | ||||
|  | ||||
|         this._label.setText(targetApp.get_name()); | ||||
|         this.setName(targetApp.get_name()); | ||||
|  | ||||
|         this._iconBox.set_child(icon); | ||||
|         this._syncIcon(); | ||||
|         this._iconBox.show(); | ||||
|  | ||||
|         if (targetApp.get_state() == Shell.AppState.STARTING) | ||||
| @@ -637,6 +640,33 @@ 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(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| @@ -894,7 +924,6 @@ 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 | ||||
| @@ -923,7 +952,7 @@ const Panel = new Lang.Class({ | ||||
|  | ||||
|         this.statusArea = {}; | ||||
|  | ||||
|         this.menuManager = new PopupMenu.PopupMenuManager(this); | ||||
|         this.menuManager = new PopupMenu.PopupMenuManager(this, { keybindingMode: Shell.KeyBindingMode.TOPBAR_POPUP }); | ||||
|  | ||||
|         this._leftBox = new St.BoxLayout({ name: 'panelLeft' }); | ||||
|         this.actor.add_actor(this._leftBox); | ||||
| @@ -1077,17 +1106,18 @@ const Panel = new Lang.Class({ | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     openAppMenu: function() { | ||||
|     toggleAppMenu: function() { | ||||
|         let indicator = this.statusArea.appMenu; | ||||
|         if (!indicator) // appMenu not supported by current session mode | ||||
|             return; | ||||
|  | ||||
|         let menu = indicator.menu; | ||||
|         if (!indicator.actor.reactive || menu.isOpen) | ||||
|         if (!indicator.actor.reactive) | ||||
|             return; | ||||
|  | ||||
|         menu.open(); | ||||
|         menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); | ||||
|         menu.toggle(); | ||||
|         if (menu.isOpen) | ||||
|             menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); | ||||
|     }, | ||||
|  | ||||
|     set boxOpacity(value) { | ||||
|   | ||||
| @@ -553,6 +553,10 @@ const PopupSliderMenuItem = new Lang.Class({ | ||||
|  | ||||
|         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 sliderWidth = width - 2 * handleRadius; | ||||
|         let sliderHeight = themeNode.get_length('-slider-height'); | ||||
|  | ||||
| @@ -604,7 +608,16 @@ const PopupSliderMenuItem = new Lang.Class({ | ||||
|             color.blue / 255, | ||||
|             color.alpha / 255); | ||||
|         cr.arc(handleX, handleY, handleRadius, 0, 2 * Math.PI); | ||||
|         cr.fill(); | ||||
|         cr.fillPreserve(); | ||||
|         if (hasHandleColor && handleBorderWidth) { | ||||
|           cr.setSourceRGBA( | ||||
|               handleBorderColor.red / 255, | ||||
|               handleBorderColor.green / 255, | ||||
|               handleBorderColor.blue / 255, | ||||
|               handleBorderColor.alpha / 255); | ||||
|           cr.setLineWidth(handleBorderWidth); | ||||
|           cr.stroke(); | ||||
|         } | ||||
|         cr.$dispose(); | ||||
|     }, | ||||
|  | ||||
| @@ -1813,6 +1826,8 @@ const RemoteMenu = new Lang.Class({ | ||||
|  | ||||
|         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)); | ||||
|  | ||||
|         this._skipSignalConnection = false; | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
| @@ -1860,7 +1875,7 @@ const RemoteMenu = new Lang.Class({ | ||||
|         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']; | ||||
|             return [null, false, 'action-added::' + action_id]; | ||||
|         } | ||||
|  | ||||
|         if (!this._actions[action_id]) | ||||
| @@ -1897,7 +1912,7 @@ const RemoteMenu = new Lang.Class({ | ||||
|                 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']; | ||||
|                 return [null, false, 'action-state-changed::' + action_id]; | ||||
|             } | ||||
|         } else { | ||||
|             target = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null); | ||||
| @@ -1973,13 +1988,16 @@ const RemoteMenu = new Lang.Class({ | ||||
|                     target.addMenuItem(separator, k+1); | ||||
|                     k++; | ||||
|                 } | ||||
|             } else if (changeSignal) { | ||||
|             } else if (changeSignal && !this._skipSignalConnection) { | ||||
|                 let signalId = this.actionGroup.connect(changeSignal, Lang.bind(this, function(actionGroup, actionName) { | ||||
|                     actionGroup.disconnect(signalId); | ||||
|                     if (this._actions[actionName]) return; | ||||
|  | ||||
|                     // force a full update | ||||
|                     /* force a full update but do not reconnect signals if other | ||||
|                      * actions are missing */ | ||||
|                     this._skipSignalConnection = true; | ||||
|                     this._modelChanged(model, 0, -1, model.get_n_items(), target); | ||||
|                     this._skipSignalConnection = false; | ||||
|                 })); | ||||
|             } | ||||
|         } | ||||
| @@ -2052,9 +2070,9 @@ const RemoteMenu = new Lang.Class({ | ||||
| const PopupMenuManager = new Lang.Class({ | ||||
|     Name: 'PopupMenuManager', | ||||
|  | ||||
|     _init: function(owner) { | ||||
|     _init: function(owner, grabParams) { | ||||
|         this._owner = owner; | ||||
|         this._grabHelper = new GrabHelper.GrabHelper(owner.actor); | ||||
|         this._grabHelper = new GrabHelper.GrabHelper(owner.actor, grabParams); | ||||
|         this._menus = []; | ||||
|     }, | ||||
|  | ||||
| @@ -2088,7 +2106,7 @@ const PopupMenuManager = new Lang.Class({ | ||||
|  | ||||
|     removeMenu: function(menu) { | ||||
|         if (menu == this.activeMenu) | ||||
|             this._closeMenu(menu); | ||||
|             this._closeMenu(false, menu); | ||||
|  | ||||
|         let position = this._findMenu(menu); | ||||
|         if (position == -1) // not a menu we manage | ||||
| @@ -2124,6 +2142,8 @@ 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 { | ||||
| @@ -2140,13 +2160,8 @@ const PopupMenuManager = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _changeMenu: function(newMenu) { | ||||
|         let oldMenu = this.activeMenu; | ||||
|         if (oldMenu) { | ||||
|             oldMenu.close(BoxPointer.PopupAnimation.FADE); | ||||
|             newMenu.open(BoxPointer.PopupAnimation.FADE); | ||||
|         } else { | ||||
|             newMenu.open(BoxPointer.PopupAnimation.FULL); | ||||
|         } | ||||
|         newMenu.open(this.activeMenu ? BoxPointer.PopupAnimation.FADE | ||||
|                                      : BoxPointer.PopupAnimation.FULL); | ||||
|     }, | ||||
|  | ||||
|     _onMenuSourceEnter: function(menu) { | ||||
|   | ||||
| @@ -478,6 +478,7 @@ const ScreenShield = new Lang.Class({ | ||||
|  | ||||
|         this._lockDialogGroup = new St.Widget({ x_expand: true, | ||||
|                                                 y_expand: true, | ||||
|                                                 reactive: true, | ||||
|                                                 opacity: 0, | ||||
|                                                 pivot_point: new Clutter.Point({ x: 0.5, y: 0.5 }), | ||||
|                                                 name: 'lockDialogGroup' }); | ||||
| @@ -709,6 +710,8 @@ 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); | ||||
| @@ -1115,6 +1118,9 @@ 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') | ||||
| @@ -1131,9 +1137,6 @@ const ScreenShield = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _completeDeactivate: function() { | ||||
|         if (this._hasLockScreen) | ||||
|             this._clearLockScreen(); | ||||
|  | ||||
|         if (this._dialog && !this._isGreeter) { | ||||
|             this._dialog.destroy(); | ||||
|             this._dialog = null; | ||||
| @@ -1200,6 +1203,12 @@ 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); | ||||
|  | ||||
|   | ||||
							
								
								
									
										140
									
								
								js/ui/screencast.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								js/ui/screencast.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | ||||
| // -*- 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])); | ||||
|     } | ||||
| }); | ||||
| @@ -16,6 +16,7 @@ const _modes = { | ||||
|     'restrictive': { | ||||
|         parentMode: null, | ||||
|         stylesheetName: 'gnome-shell.css', | ||||
|         overridesSchema: 'org.gnome.shell.overrides', | ||||
|         hasOverview: false, | ||||
|         showCalendarEvents: false, | ||||
|         allowSettings: false, | ||||
| @@ -45,7 +46,7 @@ const _modes = { | ||||
|         unlockDialog: imports.gdm.loginDialog.LoginDialog, | ||||
|         components: ['polkitAgent'], | ||||
|         panel: { | ||||
|             left: ['logo'], | ||||
|             left: [], | ||||
|             center: ['dateMenu'], | ||||
|             right: ['a11yGreeter', 'display', 'keyboard', | ||||
|                     'volume', 'battery', 'powerMenu'] | ||||
| @@ -195,6 +196,10 @@ 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,6 +12,7 @@ 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"> | ||||
| @@ -20,6 +21,7 @@ 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> | ||||
| @@ -70,6 +72,7 @@ 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(); | ||||
| @@ -97,7 +100,7 @@ const GnomeShell = new Lang.Class({ | ||||
|      */ | ||||
|     Eval: function(code) { | ||||
|         if (!global.settings.get_boolean('development-tools')) | ||||
|             return [false, null]; | ||||
|             return [false, '']; | ||||
|  | ||||
|         let returnValue; | ||||
|         let success; | ||||
| @@ -114,6 +117,10 @@ 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,9 +14,7 @@ const EntryMenu = new Lang.Class({ | ||||
|     Name: 'ShellEntryMenu', | ||||
|     Extends: PopupMenu.PopupMenu, | ||||
|  | ||||
|     _init: function(entry, params) { | ||||
|         params = Params.parse (params, { isPassword: false }); | ||||
|  | ||||
|     _init: function(entry) { | ||||
|         this.parent(entry, 0, St.Side.TOP); | ||||
|  | ||||
|         this.actor.add_style_class_name('entry-context-menu'); | ||||
| @@ -37,8 +35,6 @@ 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(); | ||||
| @@ -53,19 +49,21 @@ 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(); | ||||
| 	else { | ||||
| 	    this._passwordItem.destroy(); | ||||
| 	    this._passwordItem = null; | ||||
| 	} | ||||
|         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; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     open: function(animate) { | ||||
| @@ -155,7 +153,10 @@ function addContextMenu(entry, params) { | ||||
|     if (entry.menu) | ||||
|         return; | ||||
|  | ||||
|     entry.menu = new EntryMenu(entry, params); | ||||
|     params = Params.parse (params, { isPassword: false }); | ||||
|  | ||||
|     entry.menu = new EntryMenu(entry); | ||||
|     entry.menu.isPassword = params.isPassword; | ||||
|     entry._menuManager = new PopupMenu.PopupMenuManager({ actor: entry }); | ||||
|     entry._menuManager.addMenu(entry.menu); | ||||
|  | ||||
|   | ||||
| @@ -33,6 +33,33 @@ 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 | ||||
| // source is active. | ||||
| const MAX_INPUT_SOURCE_ACTIVATION_TIME = 4000; // ms | ||||
|  | ||||
| const BUS_NAME = 'org.gnome.SettingsDaemon.Keyboard'; | ||||
| const OBJECT_PATH = '/org/gnome/SettingsDaemon/Keyboard'; | ||||
|  | ||||
| const KeyboardManagerInterface = | ||||
| <interface name="org.gnome.SettingsDaemon.Keyboard"> | ||||
| <method name="SetInputSource"> | ||||
|     <arg type="u" direction="in" /> | ||||
| </method> | ||||
| </interface>; | ||||
|  | ||||
| const KeyboardManagerProxy = Gio.DBusProxy.makeProxyWrapper(KeyboardManagerInterface); | ||||
|  | ||||
| function releaseKeyboard() { | ||||
|     if (Main.modalCount > 0) | ||||
|         global.display.unfreeze_keyboard(global.get_current_time()); | ||||
|     else | ||||
|         global.display.ungrab_keyboard(global.get_current_time()); | ||||
| } | ||||
|  | ||||
| function holdKeyboard() { | ||||
|     global.freeze_keyboard(global.get_current_time()); | ||||
| } | ||||
|  | ||||
| const IBusManager = new Lang.Class({ | ||||
|     Name: 'IBusManager', | ||||
|  | ||||
| @@ -45,26 +72,24 @@ 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._nameWatcherId = Gio.DBus.session.watch_name(IBus.SERVICE_IBUS, | ||||
|                                                           Gio.BusNameWatcherFlags.NONE, | ||||
|                                                           Lang.bind(this, this._onNameAppeared), | ||||
|                                                           Lang.bind(this, this._clear)); | ||||
|         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)); | ||||
|     }, | ||||
|  | ||||
|     _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 = {}; | ||||
| @@ -76,18 +101,12 @@ 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) { | ||||
| @@ -109,9 +128,6 @@ 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) { | ||||
| @@ -140,6 +156,9 @@ const IBusManager = new Lang.Class({ | ||||
|     }, | ||||
|  | ||||
|     _engineChanged: function(bus, engineName) { | ||||
|         if (!this._ready) | ||||
|             return; | ||||
|  | ||||
|         this._currentEngineName = engineName; | ||||
|  | ||||
|         if (this._registerPropertiesId != 0) | ||||
| @@ -337,14 +356,14 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|             Main.wm.addKeybinding('switch-input-source', | ||||
|                                   new Gio.Settings({ schema: "org.gnome.desktop.wm.keybindings" }), | ||||
|                                   Meta.KeyBindingFlags.REVERSES, | ||||
|                                   Shell.KeyBindingMode.ALL & ~Shell.KeyBindingMode.MESSAGE_TRAY, | ||||
|                                   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, | ||||
|                                   Shell.KeyBindingMode.ALL & ~Shell.KeyBindingMode.MESSAGE_TRAY, | ||||
|                                   Shell.KeyBindingMode.ALL, | ||||
|                                   Lang.bind(this, this._switchInputSource)); | ||||
|         this._settings = new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_SCHEMA }); | ||||
|         this._settings.connect('changed::' + KEY_CURRENT_INPUT_SOURCE, Lang.bind(this, this._currentInputSourceChanged)); | ||||
| @@ -364,6 +383,15 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|         this._ibusManager.connect('property-updated', Lang.bind(this, this._ibusPropertyUpdated)); | ||||
|         this._inputSourcesChanged(); | ||||
|  | ||||
|         this._keyboardManager = new KeyboardManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH, | ||||
|                                                          function(proxy, error) { | ||||
|                                                              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()); | ||||
|         this._showLayoutItem = this.menu.addAction(_("Show Keyboard Layout"), Lang.bind(this, this._showLayout)); | ||||
|  | ||||
| @@ -397,10 +425,43 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|         this._inputSourcesChanged(); | ||||
|     }, | ||||
|  | ||||
|     _modifiersSwitcher: function() { | ||||
|         let sourceIndexes = Object.keys(this._inputSources); | ||||
|         if (sourceIndexes.length == 0) { | ||||
|             releaseKeyboard(); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         let is = this._currentSource; | ||||
|         if (!is) | ||||
|             is = this._inputSources[sourceIndexes[0]]; | ||||
|  | ||||
|         let nextIndex = is.index + 1; | ||||
|         if (nextIndex > sourceIndexes[sourceIndexes.length - 1]) | ||||
|             nextIndex = 0; | ||||
|  | ||||
|         while (!(is = this._inputSources[nextIndex])) | ||||
|             nextIndex += 1; | ||||
|  | ||||
|         is.activate(); | ||||
|         return true; | ||||
|     }, | ||||
|  | ||||
|     _switchInputSource: function(display, screen, window, binding) { | ||||
|         if (this._mruSources.length < 2) | ||||
|             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 | ||||
|         // https://bugzilla.gnome.org/show_bug.cgi?id=695143 . | ||||
|         if (Main.keybindingMode == Shell.KeyBindingMode.MESSAGE_TRAY || | ||||
|             Main.keybindingMode == Shell.KeyBindingMode.TOPBAR_POPUP) { | ||||
|             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; | ||||
| @@ -459,6 +520,7 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|  | ||||
|         this._inputSources = {}; | ||||
|         this._ibusSources = {}; | ||||
|         this._currentSource = null; | ||||
|  | ||||
|         let inputSourcesByShortName = {}; | ||||
|  | ||||
| @@ -487,10 +549,8 @@ const InputSourceIndicator = new Lang.Class({ | ||||
|             let is = new InputSource(type, id, displayName, shortName, i); | ||||
|  | ||||
|             is.connect('activate', Lang.bind(this, function() { | ||||
|                 if (this._currentSource && this._currentSource.index == is.index) | ||||
|                     return; | ||||
|                 this._settings.set_value(KEY_CURRENT_INPUT_SOURCE, | ||||
|                                          GLib.Variant.new_uint32(is.index)); | ||||
|                 holdKeyboard(); | ||||
|                 this._keyboardManager.SetInputSourceRemote(is.index, releaseKeyboard); | ||||
|             })); | ||||
|  | ||||
|             if (!(is.shortName in inputSourcesByShortName)) | ||||
|   | ||||
| @@ -2047,6 +2047,7 @@ const NMApplet = new Lang.Class({ | ||||
|         let default_ip4 = null; | ||||
|         let default_ip6 = null; | ||||
|         let active_vpn = null; | ||||
|         let active_any = null; | ||||
|         for (let i = 0; i < this._activeConnections.length; i++) { | ||||
|             let a = this._activeConnections[i]; | ||||
|  | ||||
| @@ -2077,10 +2078,15 @@ const NMApplet = new Lang.Class({ | ||||
|             if (a.default6) | ||||
|                 default_ip6 = a; | ||||
|  | ||||
|             if (a._type == 'vpn') | ||||
|                 active_vpn = a; | ||||
|             else if (a.state == NetworkManager.ActiveConnectionState.ACTIVATING) | ||||
|             if (a.state == NetworkManager.ActiveConnectionState.ACTIVATING) | ||||
|                 activating = a; | ||||
|             else if (a.state == NetworkManager.ActiveConnectionState.ACTIVATED) | ||||
|                 active_any = a; | ||||
|  | ||||
|             if (a._type == 'vpn' && | ||||
|                 (a.state == NetworkManager.ActiveConnectionState.ACTIVATING || | ||||
|                  a.state == NetworkManager.ActiveConnectionState.ACTIVATED)) | ||||
|                 active_vpn = a; | ||||
|  | ||||
|             if (!a._primaryDevice) { | ||||
|                 if (a._type != NetworkManager.SETTING_VPN_SETTING_NAME) { | ||||
| @@ -2108,7 +2114,7 @@ const NMApplet = new Lang.Class({ | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         this._mainConnection = activating || default_ip4 || default_ip6 || this._activeConnections[0] || null; | ||||
|         this._mainConnection = activating || default_ip4 || default_ip6 || active_any || null; | ||||
|         this._vpnConnection = active_vpn; | ||||
|     }, | ||||
|  | ||||
|   | ||||
| @@ -307,7 +307,7 @@ const Indicator = new Lang.Class({ | ||||
|             this._headphoneIcon.visible = value; | ||||
|         })); | ||||
|  | ||||
|         this._headphoneIcon = this.addIcon(new Gio.ThemedIcon({ name: 'headphones-symbolic' })); | ||||
|         this._headphoneIcon = this.addIcon(new Gio.ThemedIcon({ name: 'audio-headphones-symbolic' })); | ||||
|         this._headphoneIcon.visible = false; | ||||
|  | ||||
|         this.menu.addMenuItem(this._volumeMenu); | ||||
|   | ||||
| @@ -91,10 +91,6 @@ const UnlockDialog = new Lang.Class({ | ||||
|         this._promptLoginHint.hide(); | ||||
|         this.contentLayout.add_actor(this._promptLoginHint); | ||||
|  | ||||
|         let spinnerIcon = global.datadir + '/theme/process-working.svg'; | ||||
|         this._workSpinner = new Panel.AnimatedIcon(spinnerIcon, LoginDialog.WORK_SPINNER_ICON_SIZE); | ||||
|         this._workSpinner.actor.opacity = 0; | ||||
|  | ||||
|         this.allowCancel = false; | ||||
|         this.buttonLayout.visible = true; | ||||
|         this.addButton({ label: _("Cancel"), | ||||
| @@ -105,12 +101,11 @@ const UnlockDialog = new Lang.Class({ | ||||
|                          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.placeSpinner({ 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 }, | ||||
| @@ -164,28 +159,6 @@ 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; | ||||
| @@ -216,7 +189,7 @@ const UnlockDialog = new Lang.Class({ | ||||
|  | ||||
|         this._currentQuery = serviceName; | ||||
|         this._updateSensitivity(true); | ||||
|         this._setWorking(false); | ||||
|         this.setWorking(false); | ||||
|     }, | ||||
|  | ||||
|     _showLoginHint: function(verifier, message) { | ||||
| @@ -235,7 +208,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; | ||||
|         } | ||||
|  | ||||
| @@ -246,7 +219,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); | ||||
|     }, | ||||
| @@ -286,7 +259,7 @@ const UnlockDialog = new Lang.Class({ | ||||
|         this._promptEntry.menu.isPassword = true; | ||||
|  | ||||
|         this._updateSensitivity(false); | ||||
|         this._setWorking(false); | ||||
|         this.setWorking(false); | ||||
|     }, | ||||
|  | ||||
|     _escape: function() { | ||||
|   | ||||
| @@ -16,6 +16,7 @@ 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 UserMenu.UserAvatarWidget(user); | ||||
|         this.actor.add(this._avatar.actor, | ||||
| @@ -36,7 +37,7 @@ const UserWidget = new Lang.Class({ | ||||
|             this._updateUser(); | ||||
|     }, | ||||
|  | ||||
|     destroy: function() { | ||||
|     _onDestroy: function() { | ||||
|         if (this._userLoadedId != 0) { | ||||
|             this._user.disconnect(this._userLoadedId); | ||||
|             this._userLoadedId = 0; | ||||
| @@ -46,8 +47,6 @@ const UserWidget = new Lang.Class({ | ||||
|             this._user.disconnect(this._userChangedId); | ||||
|             this._userChangedId = 0; | ||||
|         } | ||||
|  | ||||
|         this.actor.destroy(); | ||||
|     }, | ||||
|  | ||||
|     _updateUser: function() { | ||||
|   | ||||
| @@ -136,6 +136,42 @@ const WindowManager = new Lang.Class({ | ||||
|                                         Shell.KeyBindingMode.NORMAL | | ||||
|                                         Shell.KeyBindingMode.OVERVIEW, | ||||
|                                         Lang.bind(this, this._showWorkspaceSwitcher)); | ||||
|         this.allowKeybinding('switch-to-workspace-1', | ||||
|                              Shell.KeyBindingMode.NORMAL | | ||||
|                              Shell.KeyBindingMode.OVERVIEW); | ||||
|         this.allowKeybinding('switch-to-workspace-2', | ||||
|                              Shell.KeyBindingMode.NORMAL | | ||||
|                              Shell.KeyBindingMode.OVERVIEW); | ||||
|         this.allowKeybinding('switch-to-workspace-3', | ||||
|                              Shell.KeyBindingMode.NORMAL | | ||||
|                              Shell.KeyBindingMode.OVERVIEW); | ||||
|         this.allowKeybinding('switch-to-workspace-4', | ||||
|                              Shell.KeyBindingMode.NORMAL | | ||||
|                              Shell.KeyBindingMode.OVERVIEW); | ||||
|         this.allowKeybinding('switch-to-workspace-5', | ||||
|                              Shell.KeyBindingMode.NORMAL | | ||||
|                              Shell.KeyBindingMode.OVERVIEW); | ||||
|         this.allowKeybinding('switch-to-workspace-6', | ||||
|                              Shell.KeyBindingMode.NORMAL | | ||||
|                              Shell.KeyBindingMode.OVERVIEW); | ||||
|         this.allowKeybinding('switch-to-workspace-7', | ||||
|                              Shell.KeyBindingMode.NORMAL | | ||||
|                              Shell.KeyBindingMode.OVERVIEW); | ||||
|         this.allowKeybinding('switch-to-workspace-8', | ||||
|                              Shell.KeyBindingMode.NORMAL | | ||||
|                              Shell.KeyBindingMode.OVERVIEW); | ||||
|         this.allowKeybinding('switch-to-workspace-9', | ||||
|                              Shell.KeyBindingMode.NORMAL | | ||||
|                              Shell.KeyBindingMode.OVERVIEW); | ||||
|         this.allowKeybinding('switch-to-workspace-10', | ||||
|                              Shell.KeyBindingMode.NORMAL | | ||||
|                              Shell.KeyBindingMode.OVERVIEW); | ||||
|         this.allowKeybinding('switch-to-workspace-11', | ||||
|                              Shell.KeyBindingMode.NORMAL | | ||||
|                              Shell.KeyBindingMode.OVERVIEW); | ||||
|         this.allowKeybinding('switch-to-workspace-12', | ||||
|                              Shell.KeyBindingMode.NORMAL | | ||||
|                              Shell.KeyBindingMode.OVERVIEW); | ||||
|         this.setCustomKeybindingHandler('switch-applications', | ||||
|                                         Shell.KeyBindingMode.NORMAL, | ||||
|                                         Lang.bind(this, this._startAppSwitcher)); | ||||
| @@ -172,8 +208,9 @@ const WindowManager = new Lang.Class({ | ||||
|         this.addKeybinding('open-application-menu', | ||||
|                            new Gio.Settings({ schema: SHELL_KEYBINDINGS_SCHEMA }), | ||||
|                            Meta.KeyBindingFlags.NONE, | ||||
|                            Shell.KeyBindingMode.NORMAL, | ||||
|                            Lang.bind(this, this._openAppMenu)); | ||||
|                            Shell.KeyBindingMode.NORMAL | | ||||
|                            Shell.KeyBindingMode.TOPBAR_POPUP, | ||||
|                            Lang.bind(this, this._toggleAppMenu)); | ||||
|  | ||||
|         Main.overview.connect('showing', Lang.bind(this, function() { | ||||
|             for (let i = 0; i < this._dimmedWindows.length; i++) | ||||
| @@ -679,8 +716,8 @@ const WindowManager = new Lang.Class({ | ||||
|         Main.ctrlAltTabManager.popup(backwards, binding.get_name(), binding.get_mask()); | ||||
|     }, | ||||
|  | ||||
|     _openAppMenu : function(display, screen, window, event, binding) { | ||||
|         Main.panel.openAppMenu(); | ||||
|     _toggleAppMenu : function(display, screen, window, event, binding) { | ||||
|         Main.panel.toggleAppMenu(); | ||||
|     }, | ||||
|  | ||||
|     _showWorkspaceSwitcher : function(display, screen, window, binding) { | ||||
|   | ||||
| @@ -1094,6 +1094,7 @@ const Workspace = new Lang.Class({ | ||||
|                 Tweener.removeTweens(clone.actor); | ||||
|                 clone.actor.set_position(x, y); | ||||
|                 clone.actor.set_scale(scale, scale); | ||||
|                 clone.actor.set_opacity(255); | ||||
|                 clone.overlay.relayout(false); | ||||
|                 this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace); | ||||
|             } | ||||
|   | ||||
| @@ -125,6 +125,12 @@ | ||||
|                                 <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,6 +28,7 @@ gu | ||||
| he | ||||
| hi | ||||
| hu | ||||
| ia | ||||
| id | ||||
| it | ||||
| ja | ||||
| @@ -45,6 +46,7 @@ ms | ||||
| nb | ||||
| nl | ||||
| nn | ||||
| oc | ||||
| or | ||||
| pa | ||||
| pl | ||||
|   | ||||
							
								
								
									
										2
									
								
								po/eu.po
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								po/eu.po
									
									
									
									
									
								
							| @@ -1244,7 +1244,7 @@ msgstr "Ezezaguna" | ||||
| #, c-format | ||||
| msgid "%d new message" | ||||
| msgid_plural "%d new messages" | ||||
| msgstr[0] "Mezu berri &d" | ||||
| msgstr[0] "Mezu berri %d" | ||||
| msgstr[1] "%d mezu berri" | ||||
|  | ||||
| #: ../js/ui/overview.js:84 | ||||
|   | ||||
							
								
								
									
										279
									
								
								po/lt.po
									
									
									
									
									
								
							
							
						
						
									
										279
									
								
								po/lt.po
									
									
									
									
									
								
							| @@ -11,9 +11,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-03-23 11:49+0000\n" | ||||
| "PO-Revision-Date: 2013-03-26 22:43+0200\n" | ||||
| "Last-Translator: Mantas Kriaučiūnas <mantas@akl.lt>\n" | ||||
| "POT-Creation-Date: 2013-12-20 16:10+0000\n" | ||||
| "PO-Revision-Date: 2013-12-21 16:31+0200\n" | ||||
| "Last-Translator: Aurimas Černius <aurisc4@gmail.com>\n" | ||||
| "Language-Team: Lietuvių <gnome-lt@lists.akl.lt>\n" | ||||
| "Language: lt\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| @@ -360,7 +360,7 @@ msgstr "Darbalaukiai tik pagrindiniame monitoriuje" | ||||
| #: ../js/extensionPrefs/main.js:125 | ||||
| #, c-format | ||||
| msgid "There was an error loading the preferences dialog for %s:" | ||||
| msgstr "Įvyko klaida įkeliant %s nustatymų dialogą:" | ||||
| msgstr "Kilo klaida įkeliant %s nustatymų dialogą:" | ||||
|  | ||||
| #: ../js/extensionPrefs/main.js:165 | ||||
| msgid "Extension" | ||||
| @@ -370,43 +370,50 @@ msgstr "Plėtinys" | ||||
| msgid "Select an extension to configure using the combobox above." | ||||
| msgstr "Išskleidžiamajame sąraše pasirinkite konfigūruotiną plėtinį." | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:405 | ||||
| #: ../js/gdm/loginDialog.js:371 | ||||
| msgid "Session…" | ||||
| msgstr "Seansas…" | ||||
|  | ||||
| #. 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:601 | ||||
| msgid "Not listed?" | ||||
| msgstr "Nėra sąraše?" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:786 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 | ||||
| #: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:376 | ||||
| #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:99 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:96 | ||||
| #: ../js/ui/userMenu.js:938 | ||||
| msgid "Cancel" | ||||
| msgstr "Atsisakyti" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:802 | ||||
| #: ../js/gdm/loginDialog.js:791 | ||||
| msgctxt "button" | ||||
| msgid "Sign In" | ||||
| msgstr "Prisijungti" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:802 | ||||
| #: ../js/gdm/loginDialog.js:791 | ||||
| msgid "Next" | ||||
| msgstr "Kitas" | ||||
|  | ||||
| #. 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 "(pvz., naudotojas arba %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:917 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/gdm/loginDialog.js:892 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/ui/components/networkAgent.js:278 | ||||
| msgid "Username: " | ||||
| msgstr "Naudotojo vardas: " | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:1173 | ||||
| #: ../js/gdm/loginDialog.js:1158 | ||||
| msgid "Login Window" | ||||
| msgstr "Prisijungimo langas" | ||||
|  | ||||
| @@ -429,21 +436,16 @@ msgstr "Paleisti iš naujo" | ||||
| msgid "Power Off" | ||||
| msgstr "Išjungti" | ||||
|  | ||||
| #: ../js/gdm/util.js:249 | ||||
| #: ../js/gdm/util.js:248 | ||||
| msgid "Authentication error" | ||||
| msgstr "Tapatybės patvirtinimo klaida" | ||||
|  | ||||
| #. 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:365 | ||||
| msgid "(or swipe finger)" | ||||
| msgstr "(arba perbraukite pirštu)" | ||||
|  | ||||
| #: ../js/gdm/util.js:391 | ||||
| #, c-format | ||||
| msgid "(e.g., user or %s)" | ||||
| msgstr "(pvz., naudotojas arba %s)" | ||||
|  | ||||
| #: ../js/misc/util.js:97 | ||||
| msgid "Command not found" | ||||
| msgstr "Komanda nerasta" | ||||
| @@ -459,23 +461,23 @@ msgstr "Nepavyko perskaityti komandos:" | ||||
| msgid "Execution of '%s' failed:" | ||||
| msgstr "Nepavyko įvykdyti „%s“:" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:349 | ||||
| #: ../js/ui/appDisplay.js:392 | ||||
| msgid "Frequent" | ||||
| msgstr "Dažniausios" | ||||
| msgstr "Dažnai naudojamos" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:356 | ||||
| #: ../js/ui/appDisplay.js:399 | ||||
| msgid "All" | ||||
| msgstr "Visos" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:914 | ||||
| #: ../js/ui/appDisplay.js:977 | ||||
| msgid "New Window" | ||||
| msgstr "Naujas langas" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:917 ../js/ui/dash.js:284 | ||||
| #: ../js/ui/appDisplay.js:980 ../js/ui/dash.js:284 | ||||
| msgid "Remove from Favorites" | ||||
| msgstr "Pašalinti iš mėgstamų" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:918 | ||||
| #: ../js/ui/appDisplay.js:981 | ||||
| msgid "Add to Favorites" | ||||
| msgstr "Pridėti prie mėgstamų" | ||||
|  | ||||
| @@ -512,7 +514,7 @@ msgctxt "event list time" | ||||
| msgid "%H\\u2236%M" | ||||
| msgstr "%H\\u2236%M" | ||||
|  | ||||
| #. Transators: Shown in calendar event list, if 12h format, | ||||
| #. Translators: Shown in calendar event list, if 12h format, | ||||
| #. \u2236 is a ratio character, similar to : and \u2009 is | ||||
| #. a thin space | ||||
| #: ../js/ui/calendar.js:77 | ||||
| @@ -667,11 +669,11 @@ msgstr "Atverti su %s" | ||||
| msgid "Eject" | ||||
| msgstr "Išimti" | ||||
|  | ||||
| #: ../js/ui/components/keyring.js:82 ../js/ui/components/polkitAgent.js:268 | ||||
| #: ../js/ui/components/keyring.js:88 ../js/ui/components/polkitAgent.js:280 | ||||
| msgid "Password:" | ||||
| msgstr "Slaptažodis:" | ||||
|  | ||||
| #: ../js/ui/components/keyring.js:101 | ||||
| #: ../js/ui/components/keyring.js:107 | ||||
| msgid "Type again:" | ||||
| msgstr "Įveskite dar kartą:" | ||||
|  | ||||
| @@ -751,15 +753,15 @@ msgstr "Mobiliojo plačiajuosčio tinklo slaptažodis" | ||||
| msgid "A password is required to connect to '%s'." | ||||
| msgstr "Būtinas slaptažodis norint prisijungti prie „%s“" | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:55 | ||||
| #: ../js/ui/components/polkitAgent.js:54 | ||||
| msgid "Authentication Required" | ||||
| msgstr "Reikia patvirtinti tapatybę" | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:93 | ||||
| #: ../js/ui/components/polkitAgent.js:92 | ||||
| msgid "Administrator" | ||||
| msgstr "Administratorius" | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:165 | ||||
| #: ../js/ui/components/polkitAgent.js:170 | ||||
| msgid "Authenticate" | ||||
| msgstr "Patvirtinti tapatybę" | ||||
|  | ||||
| @@ -767,12 +769,12 @@ msgstr "Patvirtinti tapatybę" | ||||
| #. * requested authentication was not gained; this can happen | ||||
| #. * because of an authentication error (like invalid password), | ||||
| #. * for instance. | ||||
| #: ../js/ui/components/polkitAgent.js:256 ../js/ui/shellMountOperation.js:383 | ||||
| #: ../js/ui/components/polkitAgent.js:266 ../js/ui/shellMountOperation.js:383 | ||||
| msgid "Sorry, that didn't work. Please try again." | ||||
| msgstr "Atsiprašome, tai nesuveikė. Bandykite dar kartą." | ||||
|  | ||||
| #. Translators: this is a filename used for screencast recording | ||||
| #: ../js/ui/components/recorder.js:48 | ||||
| #: ../js/ui/components/recorder.js:47 | ||||
| #, no-c-format | ||||
| msgid "Screencast from %d %t" | ||||
| msgstr "Ekrano vaizdo įrašas iš %d %t" | ||||
| @@ -831,14 +833,14 @@ msgstr "<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> " | ||||
|  | ||||
| #. Translators: this is the other person changing their old IM name to their new | ||||
| #. IM name. | ||||
| #: ../js/ui/components/telepathyClient.js:985 | ||||
| #: ../js/ui/components/telepathyClient.js:986 | ||||
| #, c-format | ||||
| msgid "%s is now known as %s" | ||||
| msgstr "%s nuo šiol vadinasi %s" | ||||
|  | ||||
| #. translators: argument is a room name like | ||||
| #. * room@jabber.org for example. | ||||
| #: ../js/ui/components/telepathyClient.js:1088 | ||||
| #: ../js/ui/components/telepathyClient.js:1089 | ||||
| #, c-format | ||||
| msgid "Invitation to %s" | ||||
| msgstr "Kvietimas į %s" | ||||
| @@ -846,38 +848,38 @@ msgstr "Kvietimas į %s" | ||||
| #. translators: first argument is the name of a contact and the second | ||||
| #. * one the name of a room. "Alice is inviting you to join room@jabber.org | ||||
| #. * for example. | ||||
| #: ../js/ui/components/telepathyClient.js:1096 | ||||
| #: ../js/ui/components/telepathyClient.js:1097 | ||||
| #, c-format | ||||
| msgid "%s is inviting you to join %s" | ||||
| msgstr "%s jus kviečia prisijungti prie %s" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1098 | ||||
| #: ../js/ui/components/telepathyClient.js:1137 | ||||
| #: ../js/ui/components/telepathyClient.js:1177 | ||||
| #: ../js/ui/components/telepathyClient.js:1240 | ||||
| #: ../js/ui/components/telepathyClient.js:1099 | ||||
| #: ../js/ui/components/telepathyClient.js:1138 | ||||
| #: ../js/ui/components/telepathyClient.js:1178 | ||||
| #: ../js/ui/components/telepathyClient.js:1241 | ||||
| msgid "Decline" | ||||
| msgstr "Atmesti" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1099 | ||||
| #: ../js/ui/components/telepathyClient.js:1178 | ||||
| #: ../js/ui/components/telepathyClient.js:1241 | ||||
| #: ../js/ui/components/telepathyClient.js:1100 | ||||
| #: ../js/ui/components/telepathyClient.js:1179 | ||||
| #: ../js/ui/components/telepathyClient.js:1242 | ||||
| msgid "Accept" | ||||
| msgstr "Priimti" | ||||
|  | ||||
| #. translators: argument is a contact name like Alice for example. | ||||
| #: ../js/ui/components/telepathyClient.js:1129 | ||||
| #: ../js/ui/components/telepathyClient.js:1130 | ||||
| #, c-format | ||||
| msgid "Video call from %s" | ||||
| msgstr "Vaizdo skambutis nuo %s" | ||||
|  | ||||
| #. translators: argument is a contact name like Alice for example. | ||||
| #: ../js/ui/components/telepathyClient.js:1132 | ||||
| #: ../js/ui/components/telepathyClient.js:1133 | ||||
| #, c-format | ||||
| msgid "Call from %s" | ||||
| msgstr "Skambutis nuo %s" | ||||
|  | ||||
| #. translators: this is a button label (verb), not a noun | ||||
| #: ../js/ui/components/telepathyClient.js:1139 | ||||
| #: ../js/ui/components/telepathyClient.js:1140 | ||||
| msgid "Answer" | ||||
| msgstr "Atsiliepti" | ||||
|  | ||||
| @@ -886,110 +888,110 @@ msgstr "Atsiliepti" | ||||
| #. * file name. The string will be something | ||||
| #. * like: "Alice is sending you test.ogg" | ||||
| #. | ||||
| #: ../js/ui/components/telepathyClient.js:1171 | ||||
| #: ../js/ui/components/telepathyClient.js:1172 | ||||
| #, c-format | ||||
| msgid "%s is sending you %s" | ||||
| msgstr "%s jums siunčia %s" | ||||
|  | ||||
| #. To translators: The parameter is the contact's alias | ||||
| #: ../js/ui/components/telepathyClient.js:1206 | ||||
| #: ../js/ui/components/telepathyClient.js:1207 | ||||
| #, c-format | ||||
| msgid "%s would like permission to see when you are online" | ||||
| msgstr "%s pageidauja matyti, kai esate prisijungę prie interneto" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1298 | ||||
| #: ../js/ui/components/telepathyClient.js:1299 | ||||
| msgid "Network error" | ||||
| msgstr "Tinklo klaida" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1300 | ||||
| #: ../js/ui/components/telepathyClient.js:1301 | ||||
| msgid "Authentication failed" | ||||
| msgstr "Nepavyko patvirtinti tapatybės" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1302 | ||||
| #: ../js/ui/components/telepathyClient.js:1303 | ||||
| msgid "Encryption error" | ||||
| msgstr "Šifravimo klaida" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1304 | ||||
| #: ../js/ui/components/telepathyClient.js:1305 | ||||
| msgid "Certificate not provided" | ||||
| msgstr "Liudijimas nepateiktas" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1306 | ||||
| #: ../js/ui/components/telepathyClient.js:1307 | ||||
| msgid "Certificate untrusted" | ||||
| msgstr "Liudijimas nepatikimas" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1308 | ||||
| #: ../js/ui/components/telepathyClient.js:1309 | ||||
| msgid "Certificate expired" | ||||
| msgstr "Liudijimo galiojimas pasibaigęs" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1310 | ||||
| #: ../js/ui/components/telepathyClient.js:1311 | ||||
| msgid "Certificate not activated" | ||||
| msgstr "Liudijimas neaktyvuotas" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1312 | ||||
| #: ../js/ui/components/telepathyClient.js:1313 | ||||
| msgid "Certificate hostname mismatch" | ||||
| msgstr "Liudijimo serverio vardo nesutapimas" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1314 | ||||
| #: ../js/ui/components/telepathyClient.js:1315 | ||||
| msgid "Certificate fingerprint mismatch" | ||||
| msgstr "Liudijimo piršto atspaudo nesutapimas" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1316 | ||||
| #: ../js/ui/components/telepathyClient.js:1317 | ||||
| msgid "Certificate self-signed" | ||||
| msgstr "Liudijimas pačių pasirašytas" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1318 | ||||
| #: ../js/ui/components/telepathyClient.js:1319 | ||||
| msgid "Status is set to offline" | ||||
| msgstr "Nustatyta atsijungimo būsena" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1320 | ||||
| #: ../js/ui/components/telepathyClient.js:1321 | ||||
| msgid "Encryption is not available" | ||||
| msgstr "Šifravimas negalimas" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1322 | ||||
| #: ../js/ui/components/telepathyClient.js:1323 | ||||
| msgid "Certificate is invalid" | ||||
| msgstr "Liudijimas netinkamas" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1324 | ||||
| #: ../js/ui/components/telepathyClient.js:1325 | ||||
| msgid "Connection has been refused" | ||||
| msgstr "Ryšys atmestas" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1326 | ||||
| #: ../js/ui/components/telepathyClient.js:1327 | ||||
| msgid "Connection can't be established" | ||||
| msgstr "Nepavyko užmegzti ryšio" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1328 | ||||
| #: ../js/ui/components/telepathyClient.js:1329 | ||||
| msgid "Connection has been lost" | ||||
| msgstr "Ryšys nutrūko" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1330 | ||||
| #: ../js/ui/components/telepathyClient.js:1331 | ||||
| msgid "This account is already connected to the server" | ||||
| msgstr "Ši paskyra jau prijungta prie serverio" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1332 | ||||
| #: ../js/ui/components/telepathyClient.js:1333 | ||||
| msgid "" | ||||
| "Connection has been replaced by a new connection using the same resource" | ||||
| msgstr "Ryšys pakeistas nauju ryšiu naudojant tą patį išteklių" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1334 | ||||
| #: ../js/ui/components/telepathyClient.js:1335 | ||||
| msgid "The account already exists on the server" | ||||
| msgstr "Tokia paskyra serveryje jau yra" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1336 | ||||
| #: ../js/ui/components/telepathyClient.js:1337 | ||||
| msgid "Server is currently too busy to handle the connection" | ||||
| msgstr "Šiuo metu serveris per daug užimtas šiai užklausai apdoroti" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1338 | ||||
| #: ../js/ui/components/telepathyClient.js:1339 | ||||
| msgid "Certificate has been revoked" | ||||
| msgstr "Liudijimas atšauktas" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1340 | ||||
| #: ../js/ui/components/telepathyClient.js:1341 | ||||
| msgid "" | ||||
| "Certificate uses an insecure cipher algorithm or is cryptographically weak" | ||||
| msgstr "" | ||||
| "Liudijimui naudojamas nesaugus šifravimo algoritmas arba jis kriptografiškai " | ||||
| "silpnas" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1342 | ||||
| #: ../js/ui/components/telepathyClient.js:1343 | ||||
| msgid "" | ||||
| "The length of the server certificate, or the depth of the server certificate " | ||||
| "chain, exceed the limits imposed by the cryptography library" | ||||
| @@ -997,22 +999,22 @@ msgstr "" | ||||
| "Serverio liudijimo ilgis arba liudijimų eilės dydis viršija kriptografijos " | ||||
| "bibliotekos apribojimus" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1344 | ||||
| #: ../js/ui/components/telepathyClient.js:1345 | ||||
| msgid "Internal error" | ||||
| msgstr "Vidinė klaida" | ||||
|  | ||||
| #. translators: argument is the account name, like | ||||
| #. * name@jabber.org for example. | ||||
| #: ../js/ui/components/telepathyClient.js:1354 | ||||
| #: ../js/ui/components/telepathyClient.js:1355 | ||||
| #, c-format | ||||
| msgid "Unable to connect to %s" | ||||
| msgstr "Nepavyksta prisijungti prie %s" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1359 | ||||
| #: ../js/ui/components/telepathyClient.js:1360 | ||||
| msgid "View account" | ||||
| msgstr "Rodyti paskyrą" | ||||
|  | ||||
| #: ../js/ui/components/telepathyClient.js:1398 | ||||
| #: ../js/ui/components/telepathyClient.js:1399 | ||||
| msgid "Unknown reason" | ||||
| msgstr "Nežinoma priežastis" | ||||
|  | ||||
| @@ -1026,7 +1028,7 @@ msgstr "Paleisti programas" | ||||
|  | ||||
| #. Translators: this is the name of the dock/favorites area on | ||||
| #. the left of the overview | ||||
| #: ../js/ui/dash.js:435 | ||||
| #: ../js/ui/dash.js:445 | ||||
| msgid "Dash" | ||||
| msgstr "Paleidimo sritis" | ||||
|  | ||||
| @@ -1038,14 +1040,14 @@ msgstr "Atverti kalendorių" | ||||
| msgid "Open Clocks" | ||||
| msgstr "Atverti laikrodžius" | ||||
|  | ||||
| #: ../js/ui/dateMenu.js:105 | ||||
| #: ../js/ui/dateMenu.js:104 | ||||
| msgid "Date & Time Settings" | ||||
| msgstr "Datos ir laiko nustatymai" | ||||
|  | ||||
| #. 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:216 | ||||
| msgid "%A %B %e, %Y" | ||||
| msgstr "%A, %Y m. %B %d d." | ||||
|  | ||||
| @@ -1156,7 +1158,7 @@ msgstr "Įdiegti" | ||||
| msgid "Download and install '%s' from extensions.gnome.org?" | ||||
| msgstr "Atsiųsti ir įdiegti „%s“ iš extensions.gnome.org?" | ||||
|  | ||||
| #: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:314 | ||||
| #: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:333 | ||||
| #: ../js/ui/status/power.js:211 | ||||
| msgid "Keyboard" | ||||
| msgstr "Klaviatūra" | ||||
| @@ -1183,7 +1185,9 @@ msgstr "Rodyti klaidas" | ||||
| msgid "Enabled" | ||||
| msgstr "Įjungta" | ||||
|  | ||||
| #: ../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 "Išjungta" | ||||
|  | ||||
| @@ -1223,19 +1227,19 @@ msgstr "Išvalyti pranešimus" | ||||
| msgid "Notification Settings" | ||||
| msgstr "Pranešimų nustatymai" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1709 | ||||
| #: ../js/ui/messageTray.js:1707 | ||||
| msgid "No Messages" | ||||
| msgstr "Nėra pranešimų" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1782 | ||||
| #: ../js/ui/messageTray.js:1783 | ||||
| msgid "Message Tray" | ||||
| msgstr "Pranešimų juosta" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:2810 | ||||
| #: ../js/ui/messageTray.js:2822 | ||||
| msgid "System Information" | ||||
| msgstr "Sistemos informacija" | ||||
|  | ||||
| #: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:374 | ||||
| #: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:392 | ||||
| msgctxt "program" | ||||
| msgid "Unknown" | ||||
| msgstr "Nežinoma" | ||||
| @@ -1262,19 +1266,19 @@ 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 | ||||
| #: ../js/ui/panel.js:636 | ||||
| msgid "Quit" | ||||
| msgstr "Užverti" | ||||
|  | ||||
| #. 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:687 | ||||
| msgid "Activities" | ||||
| msgstr "Apžvalga" | ||||
|  | ||||
| #: ../js/ui/panel.js:933 | ||||
| #: ../js/ui/panel.js:983 | ||||
| msgid "Top Bar" | ||||
| msgstr "Viršutinė juosta" | ||||
|  | ||||
| @@ -1283,15 +1287,15 @@ msgstr "Viršutinė juosta" | ||||
| #. "ON" and "OFF") or "toggle-switch-intl" (for toggle | ||||
| #. switches containing "◯" and "|"). Other values will | ||||
| #. simply result in invisible toggle switches. | ||||
| #: ../js/ui/popupMenu.js:727 | ||||
| #: ../js/ui/popupMenu.js:740 | ||||
| msgid "toggle-switch-us" | ||||
| msgstr "toggle-switch-intl" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:73 | ||||
| #: ../js/ui/runDialog.js:74 | ||||
| msgid "Enter a Command" | ||||
| msgstr "Įveskite komandą" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:109 | ||||
| #: ../js/ui/runDialog.js:110 | ||||
| msgid "Close" | ||||
| msgstr "Užverti" | ||||
|  | ||||
| @@ -1299,7 +1303,7 @@ msgstr "Užverti" | ||||
| #. long format | ||||
| #: ../js/ui/screenShield.js:86 | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%A, %B %d" | ||||
| msgstr "%A, %B %d d." | ||||
|  | ||||
| #: ../js/ui/screenShield.js:151 | ||||
| #, c-format | ||||
| @@ -1313,7 +1317,7 @@ msgstr[2] "%d naujų pranešimų" | ||||
| msgid "Lock" | ||||
| msgstr "Užrakinti" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:637 | ||||
| #: ../js/ui/screenShield.js:642 | ||||
| msgid "GNOME needs to lock the screen" | ||||
| msgstr "GNOME aplinkai reikia užrakinti ekraną" | ||||
|  | ||||
| @@ -1324,11 +1328,11 @@ msgstr "GNOME aplinkai reikia užrakinti 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:758 ../js/ui/screenShield.js:1194 | ||||
| #: ../js/ui/screenShield.js:765 ../js/ui/screenShield.js:1201 | ||||
| msgid "Unable to lock" | ||||
| msgstr "Nepavyksta užrakinti" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1195 | ||||
| #: ../js/ui/screenShield.js:766 ../js/ui/screenShield.js:1202 | ||||
| msgid "Lock was blocked by an application" | ||||
| msgstr "Programa užblokavo užrakinimą" | ||||
|  | ||||
| @@ -1340,19 +1344,19 @@ msgstr "Ieškoma…" | ||||
| msgid "No results." | ||||
| msgstr "Nerasta atitikmenų." | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:29 | ||||
| #: ../js/ui/shellEntry.js:27 | ||||
| msgid "Copy" | ||||
| msgstr "Kopijuoti" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:34 | ||||
| #: ../js/ui/shellEntry.js:32 | ||||
| msgid "Paste" | ||||
| msgstr "Įdėti" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:106 | ||||
| #: ../js/ui/shellEntry.js:99 | ||||
| msgid "Show Text" | ||||
| msgstr "Rodyti tekstą" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:108 | ||||
| #: ../js/ui/shellEntry.js:101 | ||||
| msgid "Hide Text" | ||||
| msgstr "Slėpti tekstą" | ||||
|  | ||||
| @@ -1364,7 +1368,7 @@ msgstr "Slaptažodis" | ||||
| msgid "Remember Password" | ||||
| msgstr "Atsiminti slaptažodį" | ||||
|  | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:113 | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:109 | ||||
| msgid "Unlock" | ||||
| msgstr "Atrakinti" | ||||
|  | ||||
| @@ -1533,11 +1537,12 @@ msgstr "Įveskite PIN, nurodytą įrenginyje." | ||||
| msgid "OK" | ||||
| msgstr "Gerai" | ||||
|  | ||||
| #: ../js/ui/status/keyboard.js:368 | ||||
| #: ../js/ui/status/keyboard.js:396 | ||||
| msgid "Show Keyboard Layout" | ||||
| msgstr "Rodyti klaviatūros išdėstymą" | ||||
|  | ||||
| #: ../js/ui/status/keyboard.js:373 | ||||
| #: ../js/ui/status/keyboard.js:401 | ||||
| #| msgid "Date & Time Settings" | ||||
| msgid "Region & Language Settings" | ||||
| msgstr "Regiono ir kalbos nustatymai" | ||||
|  | ||||
| @@ -1655,7 +1660,7 @@ msgstr "Nepavyko prisijungti" | ||||
| msgid "Activation of network connection failed" | ||||
| msgstr "Tinklo ryšio nepavyko aktyvuoti" | ||||
|  | ||||
| #: ../js/ui/status/network.js:2276 | ||||
| #: ../js/ui/status/network.js:2282 | ||||
| msgid "Networking is disabled" | ||||
| msgstr "Tinklas išjungtas" | ||||
|  | ||||
| @@ -1773,11 +1778,11 @@ msgstr "Garsumas" | ||||
| msgid "Microphone" | ||||
| msgstr "Mikrofonas" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:124 | ||||
| #: ../js/ui/unlockDialog.js:120 | ||||
| msgid "Log in as another user" | ||||
| msgstr "Prisijungti kitu naudotoju" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:145 | ||||
| #: ../js/ui/unlockDialog.js:141 | ||||
| msgid "Unlock Window" | ||||
| msgstr "Atrakinimo langas" | ||||
|  | ||||
| @@ -1885,32 +1890,56 @@ msgstr "„%s“ yra pasirengusi" | ||||
| msgid "Evolution Calendar" | ||||
| msgstr "Evolution kalendorius" | ||||
|  | ||||
| #: ../src/main.c:347 | ||||
| #. 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 išvestis" | ||||
| msgstr[1] "%u išvestys" | ||||
| msgstr[2] "%u išvesčių" | ||||
|  | ||||
| #. 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 įvestis" | ||||
| msgstr[1] "%u įvestys" | ||||
| msgstr[2] "%u įvesčių" | ||||
|  | ||||
| #: ../src/gvc/gvc-mixer-control.c:2373 | ||||
| msgid "System Sounds" | ||||
| msgstr "Sistemos garsai" | ||||
|  | ||||
| #: ../src/main.c:328 | ||||
| msgid "Print version" | ||||
| msgstr "Išvesti versijos numerį" | ||||
|  | ||||
| #: ../src/main.c:353 | ||||
| #: ../src/main.c:334 | ||||
| msgid "Mode used by GDM for login screen" | ||||
| msgstr "Veiksena, naudojama GDM prisijungimo ekrane" | ||||
|  | ||||
| #: ../src/main.c:359 | ||||
| #: ../src/main.c:340 | ||||
| msgid "Use a specific mode, e.g. \"gdm\" for login screen" | ||||
| msgstr "Naudoti konkrečią veikseną, pvz., „gdm“ prisijungimo ekranui" | ||||
|  | ||||
| #: ../src/main.c:365 | ||||
| #: ../src/main.c:346 | ||||
| msgid "List possible modes" | ||||
| msgstr "Išvardinti galimas veiksenas" | ||||
|  | ||||
| #: ../src/shell-app.c:622 | ||||
| #: ../src/shell-app.c:640 | ||||
| #, c-format | ||||
| msgid "Failed to launch '%s'" | ||||
| msgstr "Nepavyko paleisti „%s“" | ||||
|  | ||||
| #: ../src/shell-keyring-prompt.c:708 | ||||
| #: ../src/shell-keyring-prompt.c:714 | ||||
| msgid "Passwords do not match." | ||||
| msgstr "Slaptažodžiai nesutampa." | ||||
|  | ||||
| #: ../src/shell-keyring-prompt.c:716 | ||||
| #: ../src/shell-keyring-prompt.c:722 | ||||
| msgid "Password cannot be blank" | ||||
| msgstr "Slaptažodis negali būti tuščias" | ||||
|  | ||||
| @@ -1918,17 +1947,17 @@ msgstr "Slaptažodis negali būti tuščias" | ||||
| msgid "Authentication dialog was dismissed by the user" | ||||
| msgstr "Naudotojas užvėrė tapatybės patvirtinimo dialogą" | ||||
|  | ||||
| #~ msgid "%u Output" | ||||
| #~ msgid_plural "%u Outputs" | ||||
| #~ msgstr[0] "%u išvestis" | ||||
| #~ msgstr[1] "%u išvestys" | ||||
| #~ msgstr[2] "%u išvesčių" | ||||
| #~ msgctxt "event list time" | ||||
| #~ msgid "%H∶%M" | ||||
| #~ msgstr "%H∶%M" | ||||
|  | ||||
| #~ msgid "%u Input" | ||||
| #~ msgid_plural "%u Inputs" | ||||
| #~ msgstr[0] "%u įvestis" | ||||
| #~ msgstr[1] "%u įvestys" | ||||
| #~ msgstr[2] "%u įvesčių" | ||||
| #~ msgctxt "event list time" | ||||
| #~ msgid "%l∶%M %p" | ||||
| #~ msgstr "%l∶%M" | ||||
|  | ||||
| #~ msgid "System Sounds" | ||||
| #~ msgstr "Sistemos garsai" | ||||
| #~ msgid "calendar:MY" | ||||
| #~ msgstr "calendar:YM" | ||||
|  | ||||
| #~| msgid "Network error" | ||||
| #~ msgid "Network" | ||||
| #~ msgstr "Tinklas" | ||||
|   | ||||
							
								
								
									
										86
									
								
								po/nb.po
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								po/nb.po
									
									
									
									
									
								
							| @@ -8,7 +8,7 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: gnome-shell 3.8.x\n" | ||||
| "Report-Msgid-Bugs-To: \n" | ||||
| "POT-Creation-Date: 2013-04-03 13:31+0200\n" | ||||
| "POT-Creation-Date: 2013-05-13 09:47+0200\n" | ||||
| "PO-Revision-Date: 2013-04-03 13:31+0200\n" | ||||
| "Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n" | ||||
| "Language-Team: Norwegian bokmål <i18n-nb@lister.ping.uio.no>\n" | ||||
| @@ -335,43 +335,50 @@ msgstr "Utvidelse" | ||||
| msgid "Select an extension to configure using the combobox above." | ||||
| msgstr "Velg en utvidelse som skal konfigureres med komboboksen over." | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:405 | ||||
| #: ../js/gdm/loginDialog.js:371 | ||||
| msgid "Session…" | ||||
| msgstr "Økt …" | ||||
|  | ||||
| #. 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:601 | ||||
| msgid "Not listed?" | ||||
| msgstr "Ikke listet?" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:786 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 | ||||
| #: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:376 | ||||
| #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:99 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:96 | ||||
| #: ../js/ui/userMenu.js:938 | ||||
| msgid "Cancel" | ||||
| msgstr "Avbryt" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:802 | ||||
| #: ../js/gdm/loginDialog.js:791 | ||||
| msgctxt "button" | ||||
| msgid "Sign In" | ||||
| msgstr "Logg inn" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:802 | ||||
| #: ../js/gdm/loginDialog.js:791 | ||||
| msgid "Next" | ||||
| msgstr "Neste" | ||||
|  | ||||
| #. 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 "(f.eks. bruker eller %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:917 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/gdm/loginDialog.js:892 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/ui/components/networkAgent.js:278 | ||||
| msgid "Username: " | ||||
| msgstr "Brukernavn: " | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:1173 | ||||
| #: ../js/gdm/loginDialog.js:1158 | ||||
| msgid "Login Window" | ||||
| msgstr "Innloggingsvindu" | ||||
|  | ||||
| @@ -394,21 +401,16 @@ msgstr "Start på nytt" | ||||
| msgid "Power Off" | ||||
| msgstr "Slå av" | ||||
|  | ||||
| #: ../js/gdm/util.js:249 | ||||
| #: ../js/gdm/util.js:247 | ||||
| msgid "Authentication error" | ||||
| msgstr "Autentiseringsfeil" | ||||
|  | ||||
| #. Translators: this message is shown below the password entry field | ||||
| #. to indicate the user can swipe their finger instead | ||||
| #: ../js/gdm/util.js:366 | ||||
| #: ../js/gdm/util.js:364 | ||||
| msgid "(or swipe finger)" | ||||
| msgstr "(eller dra finger)" | ||||
|  | ||||
| #: ../js/gdm/util.js:391 | ||||
| #, c-format | ||||
| msgid "(e.g., user or %s)" | ||||
| msgstr "(f.eks. bruker eller %s)" | ||||
|  | ||||
| #: ../js/misc/util.js:97 | ||||
| msgid "Command not found" | ||||
| msgstr "Kommando ikke funnet" | ||||
| @@ -632,11 +634,11 @@ msgstr "Åpne med %s" | ||||
| msgid "Eject" | ||||
| msgstr "Løs ut" | ||||
|  | ||||
| #: ../js/ui/components/keyring.js:82 ../js/ui/components/polkitAgent.js:268 | ||||
| #: ../js/ui/components/keyring.js:88 ../js/ui/components/polkitAgent.js:275 | ||||
| msgid "Password:" | ||||
| msgstr "Passord:" | ||||
|  | ||||
| #: ../js/ui/components/keyring.js:101 | ||||
| #: ../js/ui/components/keyring.js:107 | ||||
| msgid "Type again:" | ||||
| msgstr "Skriv på nytt:" | ||||
|  | ||||
| @@ -724,7 +726,7 @@ msgstr "Autentisering kreves" | ||||
| msgid "Administrator" | ||||
| msgstr "Administrator" | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:165 | ||||
| #: ../js/ui/components/polkitAgent.js:171 | ||||
| msgid "Authenticate" | ||||
| msgstr "Autentiser" | ||||
|  | ||||
| @@ -732,12 +734,12 @@ msgstr "Autentiser" | ||||
| #. * requested authentication was not gained; this can happen | ||||
| #. * because of an authentication error (like invalid password), | ||||
| #. * for instance. | ||||
| #: ../js/ui/components/polkitAgent.js:256 ../js/ui/shellMountOperation.js:383 | ||||
| #: ../js/ui/components/polkitAgent.js:263 ../js/ui/shellMountOperation.js:383 | ||||
| msgid "Sorry, that didn't work. Please try again." | ||||
| msgstr "Beklager, det virket ikke. Vennligst prøv igjen." | ||||
|  | ||||
| #. Translators: this is a filename used for screencast recording | ||||
| #: ../js/ui/components/recorder.js:48 | ||||
| #: ../js/ui/components/recorder.js:47 | ||||
| #, no-c-format | ||||
| msgid "Screencast from %d %t" | ||||
| msgstr "Skjermvideo fra %d %t" | ||||
| @@ -1003,14 +1005,14 @@ msgstr "Åpne kalender" | ||||
| msgid "Open Clocks" | ||||
| msgstr "Åpne Klokker" | ||||
|  | ||||
| #: ../js/ui/dateMenu.js:105 | ||||
| #: ../js/ui/dateMenu.js:104 | ||||
| msgid "Date & Time Settings" | ||||
| msgstr "Innstillinger for dato og klokkeslett" | ||||
|  | ||||
| #. 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:216 | ||||
| msgid "%A %B %e, %Y" | ||||
| msgstr "%a %e %B, %Y" | ||||
|  | ||||
| @@ -1188,11 +1190,11 @@ msgstr "Innstillinger for varsling" | ||||
| msgid "No Messages" | ||||
| msgstr "Ingen meldinger" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1782 | ||||
| #: ../js/ui/messageTray.js:1785 | ||||
| msgid "Message Tray" | ||||
| msgstr "Meldingstrau" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:2810 | ||||
| #: ../js/ui/messageTray.js:2813 | ||||
| msgid "System Information" | ||||
| msgstr "Systeminformasjon" | ||||
|  | ||||
| @@ -1224,17 +1226,17 @@ msgstr "Oversikt" | ||||
| msgid "Type to search…" | ||||
| msgstr "Skriv for å søke …" | ||||
|  | ||||
| #: ../js/ui/panel.js:612 | ||||
| #: ../js/ui/panel.js:635 | ||||
| msgid "Quit" | ||||
| msgstr "Avslutt" | ||||
|  | ||||
| #. Translators: If there is no suitable word for "Activities" | ||||
| #. in your language, you can use the word for "Overview". | ||||
| #: ../js/ui/panel.js:636 | ||||
| #: ../js/ui/panel.js:686 | ||||
| msgid "Activities" | ||||
| msgstr "Aktiviteter" | ||||
|  | ||||
| #: ../js/ui/panel.js:933 | ||||
| #: ../js/ui/panel.js:982 | ||||
| msgid "Top Bar" | ||||
| msgstr "Topp-panel" | ||||
|  | ||||
| @@ -1247,11 +1249,11 @@ msgstr "Topp-panel" | ||||
| msgid "toggle-switch-us" | ||||
| msgstr "toggle-switch-intl" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:73 | ||||
| #: ../js/ui/runDialog.js:74 | ||||
| msgid "Enter a Command" | ||||
| msgstr "Oppgi en kommando" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:109 | ||||
| #: ../js/ui/runDialog.js:110 | ||||
| msgid "Close" | ||||
| msgstr "Lukk" | ||||
|  | ||||
| @@ -1272,7 +1274,7 @@ msgstr[1] "%d nye varslinger" | ||||
| msgid "Lock" | ||||
| msgstr "Lås" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:640 | ||||
| #: ../js/ui/screenShield.js:641 | ||||
| msgid "GNOME needs to lock the screen" | ||||
| msgstr "GNOME må låse skjermen" | ||||
|  | ||||
| @@ -1283,11 +1285,11 @@ msgstr "GNOME må låse skjermen" | ||||
| #. | ||||
| #. 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:762 ../js/ui/screenShield.js:1198 | ||||
| msgid "Unable to lock" | ||||
| msgstr "Kan ikke låse" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:762 ../js/ui/screenShield.js:1198 | ||||
| #: ../js/ui/screenShield.js:763 ../js/ui/screenShield.js:1199 | ||||
| msgid "Lock was blocked by an application" | ||||
| msgstr "Låsing ble stoppet av et program" | ||||
|  | ||||
| @@ -1307,11 +1309,11 @@ msgstr "Kopier" | ||||
| msgid "Paste" | ||||
| msgstr "Lim inn" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:106 | ||||
| #: ../js/ui/shellEntry.js:101 | ||||
| msgid "Show Text" | ||||
| msgstr "Vis tekst" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:108 | ||||
| #: ../js/ui/shellEntry.js:103 | ||||
| msgid "Hide Text" | ||||
| msgstr "Skjul tekst" | ||||
|  | ||||
| @@ -1323,7 +1325,7 @@ msgstr "Passord" | ||||
| msgid "Remember Password" | ||||
| msgstr "Husk passord" | ||||
|  | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:113 | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:109 | ||||
| msgid "Unlock" | ||||
| msgstr "Lås opp" | ||||
|  | ||||
| @@ -1614,7 +1616,7 @@ msgstr "Tilkobling feilet" | ||||
| msgid "Activation of network connection failed" | ||||
| msgstr "Aktivering av nettverkstilkobling feilet" | ||||
|  | ||||
| #: ../js/ui/status/network.js:2276 | ||||
| #: ../js/ui/status/network.js:2282 | ||||
| msgid "Networking is disabled" | ||||
| msgstr "Nettverk er slått av" | ||||
|  | ||||
| @@ -1728,11 +1730,11 @@ msgstr "Volum" | ||||
| msgid "Microphone" | ||||
| msgstr "Mikrofon" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:124 | ||||
| #: ../js/ui/unlockDialog.js:120 | ||||
| msgid "Log in as another user" | ||||
| msgstr "Logg inn som en annen bruker" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:145 | ||||
| #: ../js/ui/unlockDialog.js:141 | ||||
| msgid "Unlock Window" | ||||
| msgstr "Lås opp vindu" | ||||
|  | ||||
| @@ -1885,11 +1887,11 @@ msgstr "Vis mulige modi" | ||||
| msgid "Failed to launch '%s'" | ||||
| msgstr "Klarte ikke å starte «%s»" | ||||
|  | ||||
| #: ../src/shell-keyring-prompt.c:708 | ||||
| #: ../src/shell-keyring-prompt.c:714 | ||||
| msgid "Passwords do not match." | ||||
| msgstr "Passordene er ikke like." | ||||
|  | ||||
| #: ../src/shell-keyring-prompt.c:716 | ||||
| #: ../src/shell-keyring-prompt.c:722 | ||||
| msgid "Password cannot be blank" | ||||
| msgstr "Passordet kan ikke være tomt" | ||||
|  | ||||
|   | ||||
							
								
								
									
										569
									
								
								po/pt_BR.po
									
									
									
									
									
								
							
							
						
						
									
										569
									
								
								po/pt_BR.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										522
									
								
								po/sr@latin.po
									
									
									
									
									
								
							
							
						
						
									
										522
									
								
								po/sr@latin.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1027
									
								
								po/zh_CN.po
									
									
									
									
									
								
							
							
						
						
									
										1027
									
								
								po/zh_CN.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										214
									
								
								po/zh_HK.po
									
									
									
									
									
								
							
							
						
						
									
										214
									
								
								po/zh_HK.po
									
									
									
									
									
								
							| @@ -9,15 +9,16 @@ msgstr "" | ||||
| "Project-Id-Version: gnome-shell 3.3.90\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-04 08:38+0000\n" | ||||
| "PO-Revision-Date: 2013-03-06 19:06+0800\n" | ||||
| "Last-Translator: Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>\n" | ||||
| "POT-Creation-Date: 2013-05-31 18:55+0000\n" | ||||
| "PO-Revision-Date: 2013-06-04 21:50+0800\n" | ||||
| "Last-Translator: Cheng-Chia Tseng <pswo10680@gmail.com>\n" | ||||
| "Language-Team: Chinese (Hong Kong) <community@linuxhall.org>\n" | ||||
| "Language: \n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=1; plural=0;\n" | ||||
| "X-Generator: Poedit 1.5.3\n" | ||||
| "X-Generator: Poedit 1.5.4\n" | ||||
|  | ||||
| #: ../data/50-gnome-shell-screenshot.xml.in.h:1 | ||||
| msgid "Screenshots" | ||||
| @@ -313,44 +314,50 @@ msgstr "擴充功能" | ||||
| msgid "Select an extension to configure using the combobox above." | ||||
| msgstr "使用上面的組合方塊選擇要設定的擴充功能。" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:405 | ||||
| #| msgid "Session..." | ||||
| #: ../js/gdm/loginDialog.js:371 | ||||
| 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:629 | ||||
| #: ../js/gdm/loginDialog.js:601 | ||||
| msgid "Not listed?" | ||||
| msgstr "沒有列出來?" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:783 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 | ||||
| #: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:376 | ||||
| #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:126 | ||||
| #: ../js/ui/userMenu.js:934 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:96 | ||||
| #: ../js/ui/userMenu.js:938 | ||||
| msgid "Cancel" | ||||
| msgstr "取消" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:799 | ||||
| #: ../js/gdm/loginDialog.js:791 | ||||
| msgctxt "button" | ||||
| msgid "Sign In" | ||||
| msgstr "登入" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:799 | ||||
| #: ../js/gdm/loginDialog.js:791 | ||||
| msgid "Next" | ||||
| msgstr "下一個" | ||||
|  | ||||
| #. 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 "(例如: user 或 %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:904 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/gdm/loginDialog.js:892 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/ui/components/networkAgent.js:278 | ||||
| msgid "Username: " | ||||
| msgstr "使用者名稱:" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:1157 | ||||
| #: ../js/gdm/loginDialog.js:1158 | ||||
| msgid "Login Window" | ||||
| msgstr "登入視窗" | ||||
|  | ||||
| @@ -359,8 +366,8 @@ msgstr "登入視窗" | ||||
| msgid "Power" | ||||
| msgstr "電源" | ||||
|  | ||||
| #: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:695 ../js/ui/userMenu.js:699 | ||||
| #: ../js/ui/userMenu.js:815 | ||||
| #: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:696 ../js/ui/userMenu.js:700 | ||||
| #: ../js/ui/userMenu.js:816 | ||||
| msgid "Suspend" | ||||
| msgstr "暫停" | ||||
|  | ||||
| @@ -368,58 +375,53 @@ msgstr "暫停" | ||||
| msgid "Restart" | ||||
| msgstr "重新啟動" | ||||
|  | ||||
| #: ../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 | ||||
| #: ../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 | ||||
| msgid "Power Off" | ||||
| msgstr "關閉電源" | ||||
|  | ||||
| #: ../js/gdm/util.js:182 | ||||
| #: ../js/gdm/util.js:247 | ||||
| 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:299 | ||||
| #: ../js/gdm/util.js:364 | ||||
| msgid "(or swipe finger)" | ||||
| msgstr "(或是滑過手指)" | ||||
|  | ||||
| #: ../js/gdm/util.js:324 | ||||
| #, c-format | ||||
| msgid "(e.g., user or %s)" | ||||
| msgstr "(例如: user 或 %s)" | ||||
|  | ||||
| #: ../js/misc/util.js:94 | ||||
| #: ../js/misc/util.js:97 | ||||
| msgid "Command not found" | ||||
| msgstr "找不到指令" | ||||
|  | ||||
| #. Replace "Error invoking GLib.shell_parse_argv: " with | ||||
| #. something nicer | ||||
| #: ../js/misc/util.js:127 | ||||
| #: ../js/misc/util.js:130 | ||||
| msgid "Could not parse command:" | ||||
| msgstr "無法分析指令:" | ||||
|  | ||||
| #: ../js/misc/util.js:135 | ||||
| #: ../js/misc/util.js:138 | ||||
| #, c-format | ||||
| msgid "Execution of '%s' failed:" | ||||
| msgstr "執行「%s」失敗:" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:348 | ||||
| #: ../js/ui/appDisplay.js:356 | ||||
| msgid "Frequent" | ||||
| msgstr "頻率" | ||||
| msgstr "常用" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:355 | ||||
| #: ../js/ui/appDisplay.js:363 | ||||
| msgid "All" | ||||
| msgstr "全部" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:913 | ||||
| #: ../js/ui/appDisplay.js:941 | ||||
| msgid "New Window" | ||||
| msgstr "新視窗" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:916 ../js/ui/dash.js:284 | ||||
| #: ../js/ui/appDisplay.js:944 ../js/ui/dash.js:284 | ||||
| msgid "Remove from Favorites" | ||||
| msgstr "自喜好中移除" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:917 | ||||
| #: ../js/ui/appDisplay.js:945 | ||||
| msgid "Add to Favorites" | ||||
| msgstr "加入喜好" | ||||
|  | ||||
| @@ -433,7 +435,7 @@ msgstr "%s 已加入你的喜好中。" | ||||
| msgid "%s has been removed from your favorites." | ||||
| msgstr "%s 已經從你的喜好中移除。" | ||||
|  | ||||
| #: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:788 | ||||
| #: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:789 | ||||
| msgid "Settings" | ||||
| msgstr "設定值" | ||||
|  | ||||
| @@ -456,7 +458,7 @@ msgctxt "event list time" | ||||
| msgid "%H\\u2236%M" | ||||
| msgstr "%H\\u2236%M" | ||||
|  | ||||
| #. Transators: Shown in calendar event list, if 12h format, | ||||
| #. Translators: Shown in calendar event list, if 12h format, | ||||
| #. \u2236 is a ratio character, similar to : and \u2009 is | ||||
| #. a thin space | ||||
| #: ../js/ui/calendar.js:77 | ||||
| @@ -558,35 +560,35 @@ msgid "S" | ||||
| msgstr "六" | ||||
|  | ||||
| #. Translators: Text to show if there are no events | ||||
| #: ../js/ui/calendar.js:692 | ||||
| #: ../js/ui/calendar.js:720 | ||||
| msgid "Nothing Scheduled" | ||||
| msgstr "沒有預訂行程" | ||||
|  | ||||
| #. Translators: Shown on calendar heading when selected day occurs on current year | ||||
| #: ../js/ui/calendar.js:708 | ||||
| #: ../js/ui/calendar.js:736 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%m月%d日%A" | ||||
|  | ||||
| #. Translators: Shown on calendar heading when selected day occurs on different year | ||||
| #: ../js/ui/calendar.js:711 | ||||
| #: ../js/ui/calendar.js:739 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d, %Y" | ||||
| msgstr "%Y年%m月%d日%A" | ||||
|  | ||||
| #: ../js/ui/calendar.js:721 | ||||
| #: ../js/ui/calendar.js:749 | ||||
| msgid "Today" | ||||
| msgstr "今天" | ||||
|  | ||||
| #: ../js/ui/calendar.js:725 | ||||
| #: ../js/ui/calendar.js:753 | ||||
| msgid "Tomorrow" | ||||
| msgstr "明天" | ||||
|  | ||||
| #: ../js/ui/calendar.js:736 | ||||
| #: ../js/ui/calendar.js:764 | ||||
| msgid "This week" | ||||
| msgstr "本週" | ||||
|  | ||||
| #: ../js/ui/calendar.js:744 | ||||
| #: ../js/ui/calendar.js:772 | ||||
| msgid "Next week" | ||||
| msgstr "下週" | ||||
|  | ||||
| @@ -602,20 +604,20 @@ msgstr "外部裝置已拔除" | ||||
| msgid "Removable Devices" | ||||
| msgstr "可移除式裝置" | ||||
|  | ||||
| #: ../js/ui/components/autorunManager.js:593 | ||||
| #: ../js/ui/components/autorunManager.js:594 | ||||
| #, c-format | ||||
| msgid "Open with %s" | ||||
| msgstr "用 %s 開啟" | ||||
|  | ||||
| #: ../js/ui/components/autorunManager.js:619 | ||||
| #: ../js/ui/components/autorunManager.js:620 | ||||
| msgid "Eject" | ||||
| msgstr "退出" | ||||
|  | ||||
| #: ../js/ui/components/keyring.js:82 ../js/ui/components/polkitAgent.js:268 | ||||
| #: ../js/ui/components/keyring.js:88 ../js/ui/components/polkitAgent.js:280 | ||||
| msgid "Password:" | ||||
| msgstr "密碼: " | ||||
|  | ||||
| #: ../js/ui/components/keyring.js:101 | ||||
| #: ../js/ui/components/keyring.js:107 | ||||
| msgid "Type again:" | ||||
| msgstr "再輸入一次:" | ||||
|  | ||||
| @@ -693,15 +695,15 @@ msgstr "流動寬頻網絡密碼" | ||||
| msgid "A password is required to connect to '%s'." | ||||
| msgstr "連線至「%s」需要密碼。" | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:55 | ||||
| #: ../js/ui/components/polkitAgent.js:54 | ||||
| msgid "Authentication Required" | ||||
| msgstr "要求驗證" | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:93 | ||||
| #: ../js/ui/components/polkitAgent.js:92 | ||||
| msgid "Administrator" | ||||
| msgstr "系統管理員" | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:165 | ||||
| #: ../js/ui/components/polkitAgent.js:170 | ||||
| msgid "Authenticate" | ||||
| msgstr "驗證" | ||||
|  | ||||
| @@ -709,12 +711,12 @@ msgstr "驗證" | ||||
| #. * requested authentication was not gained; this can happen | ||||
| #. * because of an authentication error (like invalid password), | ||||
| #. * for instance. | ||||
| #: ../js/ui/components/polkitAgent.js:256 ../js/ui/shellMountOperation.js:383 | ||||
| #: ../js/ui/components/polkitAgent.js:266 ../js/ui/shellMountOperation.js:383 | ||||
| msgid "Sorry, that didn't work. Please try again." | ||||
| msgstr "抱歉,那樣無法運作。請再試一次。" | ||||
|  | ||||
| #. Translators: this is a filename used for screencast recording | ||||
| #: ../js/ui/components/recorder.js:48 | ||||
| #: ../js/ui/components/recorder.js:47 | ||||
| #, no-c-format | ||||
| msgid "Screencast from %d %t" | ||||
| msgstr "Screencast from %d %t" | ||||
| @@ -976,14 +978,14 @@ msgstr "開啟行事曆" | ||||
| msgid "Open Clocks" | ||||
| msgstr "開啟時鐘" | ||||
|  | ||||
| #: ../js/ui/dateMenu.js:105 | ||||
| #: ../js/ui/dateMenu.js:104 | ||||
| msgid "Date & Time Settings" | ||||
| 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:205 | ||||
| #: ../js/ui/dateMenu.js:216 | ||||
| msgid "%A %B %e, %Y" | ||||
| msgstr "%Y年%m月%e日%A" | ||||
|  | ||||
| @@ -1080,7 +1082,7 @@ msgstr "安裝" | ||||
| msgid "Download and install '%s' from extensions.gnome.org?" | ||||
| msgstr "是否從 extensions.gnome.org 下載並安裝「%s」?" | ||||
|  | ||||
| #: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:314 | ||||
| #: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:333 | ||||
| #: ../js/ui/status/power.js:211 | ||||
| msgid "Keyboard" | ||||
| msgstr "鍵盤" | ||||
| @@ -1142,7 +1144,6 @@ msgid "Remove" | ||||
| msgstr "移除" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1501 | ||||
| #| msgid "No Messages" | ||||
| msgid "Clear Messages" | ||||
| msgstr "清除訊息" | ||||
|  | ||||
| @@ -1150,15 +1151,15 @@ msgstr "清除訊息" | ||||
| msgid "Notification Settings" | ||||
| msgstr "通知設定值" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1707 | ||||
| #: ../js/ui/messageTray.js:1709 | ||||
| msgid "No Messages" | ||||
| msgstr "沒有訊息" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1787 | ||||
| #: ../js/ui/messageTray.js:1785 | ||||
| msgid "Message Tray" | ||||
| msgstr "訊息匣" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:2864 | ||||
| #: ../js/ui/messageTray.js:2818 | ||||
| msgid "System Information" | ||||
| msgstr "系統資訊" | ||||
|  | ||||
| @@ -1167,13 +1168,13 @@ msgctxt "program" | ||||
| msgid "Unknown" | ||||
| msgstr "不明" | ||||
|  | ||||
| #: ../js/ui/overviewControls.js:460 ../js/ui/screenShield.js:153 | ||||
| #: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149 | ||||
| #, c-format | ||||
| msgid "%d new message" | ||||
| msgid_plural "%d new messages" | ||||
| msgstr[0] "%d 個新訊息" | ||||
|  | ||||
| #: ../js/ui/overview.js:82 | ||||
| #: ../js/ui/overview.js:84 | ||||
| msgid "Undo" | ||||
| msgstr "復原" | ||||
|  | ||||
| @@ -1185,22 +1186,21 @@ msgstr "概覽" | ||||
| #. in the search entry when no search is | ||||
| #. active; it should not exceed ~30 | ||||
| #. characters. | ||||
| #: ../js/ui/overview.js:284 | ||||
| #| msgid "Type to search..." | ||||
| #: ../js/ui/overview.js:271 | ||||
| msgid "Type to search…" | ||||
| msgstr "輸入以搜尋…" | ||||
|  | ||||
| #: ../js/ui/panel.js:613 | ||||
| #: ../js/ui/panel.js:635 | ||||
| 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:642 | ||||
| #: ../js/ui/panel.js:686 | ||||
| msgid "Activities" | ||||
| msgstr "概覽 " | ||||
|  | ||||
| #: ../js/ui/panel.js:983 | ||||
| #: ../js/ui/panel.js:982 | ||||
| msgid "Top Bar" | ||||
| msgstr "頂端列" | ||||
|  | ||||
| @@ -1209,35 +1209,35 @@ 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:727 | ||||
| #: ../js/ui/popupMenu.js:740 | ||||
| msgid "toggle-switch-us" | ||||
| msgstr "toggle-switch-us" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:205 | ||||
| #: ../js/ui/runDialog.js:74 | ||||
| msgid "Enter a Command" | ||||
| msgstr "請輸入指令" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:241 | ||||
| #: ../js/ui/runDialog.js:110 | ||||
| msgid "Close" | ||||
| msgstr "關閉" | ||||
|  | ||||
| #. Translators: This is a time format for a date in | ||||
| #. long format | ||||
| #: ../js/ui/screenShield.js:90 | ||||
| #: ../js/ui/screenShield.js:86 | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%m月%d日%A" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:155 | ||||
| #: ../js/ui/screenShield.js:151 | ||||
| #, c-format | ||||
| msgid "%d new notification" | ||||
| msgid_plural "%d new notifications" | ||||
| msgstr[0] "%d 個新通知" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:442 ../js/ui/userMenu.js:806 | ||||
| #: ../js/ui/screenShield.js:438 ../js/ui/userMenu.js:807 | ||||
| msgid "Lock" | ||||
| msgstr "鎖定" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:639 | ||||
| #: ../js/ui/screenShield.js:641 | ||||
| msgid "GNOME needs to lock the screen" | ||||
| msgstr "GNOME 需要鎖定螢幕" | ||||
|  | ||||
| @@ -1248,37 +1248,35 @@ 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:758 ../js/ui/screenShield.js:1169 | ||||
| #| msgid "Unable to connect to %s" | ||||
| #: ../js/ui/screenShield.js:762 ../js/ui/screenShield.js:1198 | ||||
| msgid "Unable to lock" | ||||
| msgstr "無法鎖定" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1170 | ||||
| #: ../js/ui/screenShield.js:763 ../js/ui/screenShield.js:1199 | ||||
| msgid "Lock was blocked by an application" | ||||
| msgstr "鎖定被應用程式阻擋" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:431 | ||||
| #| msgid "Searching..." | ||||
| #: ../js/ui/searchDisplay.js:453 | ||||
| msgid "Searching…" | ||||
| msgstr "搜尋…" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:475 | ||||
| #: ../js/ui/searchDisplay.js:497 | ||||
| msgid "No results." | ||||
| msgstr "沒有結果。" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:29 | ||||
| #: ../js/ui/shellEntry.js:27 | ||||
| msgid "Copy" | ||||
| msgstr "複製" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:34 | ||||
| #: ../js/ui/shellEntry.js:32 | ||||
| msgid "Paste" | ||||
| msgstr "貼上" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:105 | ||||
| #: ../js/ui/shellEntry.js:99 | ||||
| msgid "Show Text" | ||||
| msgstr "顯示文字" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:107 | ||||
| #: ../js/ui/shellEntry.js:101 | ||||
| msgid "Hide Text" | ||||
| msgstr "隱藏文字" | ||||
|  | ||||
| @@ -1290,7 +1288,7 @@ msgstr "密碼" | ||||
| msgid "Remember Password" | ||||
| msgstr "記住密碼" | ||||
|  | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:140 | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:109 | ||||
| msgid "Unlock" | ||||
| msgstr "解鎖" | ||||
|  | ||||
| @@ -1354,12 +1352,10 @@ 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 "設定新的裝置…" | ||||
|  | ||||
| @@ -1386,7 +1382,6 @@ msgid "connecting..." | ||||
| msgstr "連線中…" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:239 | ||||
| #| msgid "Send Files..." | ||||
| msgid "Send Files…" | ||||
| msgstr "傳送檔案…" | ||||
|  | ||||
| @@ -1462,11 +1457,11 @@ msgstr "請輸入裝置所提及的 PIN。" | ||||
| msgid "OK" | ||||
| msgstr "確定" | ||||
|  | ||||
| #: ../js/ui/status/keyboard.js:368 | ||||
| #: ../js/ui/status/keyboard.js:396 | ||||
| msgid "Show Keyboard Layout" | ||||
| msgstr "顯示鍵盤配置" | ||||
|  | ||||
| #: ../js/ui/status/keyboard.js:373 | ||||
| #: ../js/ui/status/keyboard.js:401 | ||||
| msgid "Region & Language Settings" | ||||
| msgstr "地區和語言設定值" | ||||
|  | ||||
| @@ -1584,7 +1579,7 @@ msgstr "連線失敗" | ||||
| msgid "Activation of network connection failed" | ||||
| msgstr "啟動網絡連線失敗" | ||||
|  | ||||
| #: ../js/ui/status/network.js:2276 | ||||
| #: ../js/ui/status/network.js:2282 | ||||
| msgid "Networking is disabled" | ||||
| msgstr "網絡已停用" | ||||
|  | ||||
| @@ -1599,7 +1594,6 @@ 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 "評估中…" | ||||
|  | ||||
| @@ -1695,11 +1689,11 @@ msgstr "音量" | ||||
| msgid "Microphone" | ||||
| msgstr "麥克風" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:151 | ||||
| #: ../js/ui/unlockDialog.js:120 | ||||
| msgid "Log in as another user" | ||||
| msgstr "以另一個使用者身分登入" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:177 | ||||
| #: ../js/ui/unlockDialog.js:141 | ||||
| msgid "Unlock Window" | ||||
| msgstr "解鎖視窗" | ||||
|  | ||||
| @@ -1727,46 +1721,48 @@ msgstr "閒置" | ||||
| msgid "Offline" | ||||
| msgstr "離線" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:780 | ||||
| #: ../js/ui/userMenu.js:781 | ||||
| msgid "Notifications" | ||||
| msgstr "通知" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:796 | ||||
| #: ../js/ui/userMenu.js:797 | ||||
| msgid "Switch User" | ||||
| msgstr "切換使用者" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:801 | ||||
| #: ../js/ui/userMenu.js:802 | ||||
| msgid "Log Out" | ||||
| msgstr "登出" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:821 | ||||
| #: ../js/ui/userMenu.js:822 | ||||
| msgid "Install Updates & Restart" | ||||
| msgstr "安裝更新 & 重新啟動" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:839 | ||||
| #: ../js/ui/userMenu.js:840 | ||||
| msgid "Your chat status will be set to busy" | ||||
| msgstr "你的聊天狀態會設為忙碌" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:840 | ||||
| #: ../js/ui/userMenu.js:841 | ||||
| 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:886 | ||||
| #: ../js/ui/userMenu.js:888 | ||||
| msgid "Other users are logged in." | ||||
| msgstr "其他使用者已登入。" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:891 | ||||
| #: ../js/ui/userMenu.js:893 | ||||
| msgid "Shutting down might cause them to lose unsaved work." | ||||
| msgstr "關機可能使它們失去未儲存的工作。" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:918 | ||||
| #. Translators: Remote here refers to a remote session, like a ssh login | ||||
| #: ../js/ui/userMenu.js:921 | ||||
| #, c-format | ||||
| msgid "%s (remote)" | ||||
| msgstr "%s (遠端)" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:920 | ||||
| #. Translators: Console here refers to a tty like a VT console | ||||
| #: ../js/ui/userMenu.js:924 | ||||
| #, c-format | ||||
| msgid "%s (console)" | ||||
| msgstr "%s (主控臺)" | ||||
| @@ -1779,7 +1775,7 @@ msgstr "應用程式" | ||||
| msgid "Search" | ||||
| msgstr "搜尋" | ||||
|  | ||||
| #: ../js/ui/wanda.js:92 | ||||
| #: ../js/ui/wanda.js:77 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Sorry, no wisdom for you today:\n" | ||||
| @@ -1788,7 +1784,7 @@ msgstr "" | ||||
| "抱歉,今天可能有些問題:\n" | ||||
| "%s" | ||||
|  | ||||
| #: ../js/ui/wanda.js:96 | ||||
| #: ../js/ui/wanda.js:81 | ||||
| #, c-format | ||||
| msgid "%s the Oracle says" | ||||
| msgstr "%s Oracle 說:" | ||||
| @@ -1818,7 +1814,7 @@ msgid "%u Input" | ||||
| msgid_plural "%u Inputs" | ||||
| msgstr[0] "%u 輸入" | ||||
|  | ||||
| #: ../src/gvc/gvc-mixer-control.c:2371 | ||||
| #: ../src/gvc/gvc-mixer-control.c:2373 | ||||
| msgid "System Sounds" | ||||
| msgstr "系統音效" | ||||
|  | ||||
| @@ -1843,11 +1839,11 @@ msgstr "列出可能的模式" | ||||
| msgid "Failed to launch '%s'" | ||||
| msgstr "無法啟動「%s」" | ||||
|  | ||||
| #: ../src/shell-keyring-prompt.c:708 | ||||
| #: ../src/shell-keyring-prompt.c:714 | ||||
| msgid "Passwords do not match." | ||||
| msgstr "密碼不相符。" | ||||
|  | ||||
| #: ../src/shell-keyring-prompt.c:716 | ||||
| #: ../src/shell-keyring-prompt.c:722 | ||||
| msgid "Password cannot be blank" | ||||
| msgstr "密碼不能為空白" | ||||
|  | ||||
|   | ||||
							
								
								
									
										214
									
								
								po/zh_TW.po
									
									
									
									
									
								
							
							
						
						
									
										214
									
								
								po/zh_TW.po
									
									
									
									
									
								
							| @@ -9,15 +9,16 @@ msgstr "" | ||||
| "Project-Id-Version: gnome-shell 3.3.90\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-04 08:38+0000\n" | ||||
| "PO-Revision-Date: 2013-03-05 19:49+0800\n" | ||||
| "Last-Translator: Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>\n" | ||||
| "POT-Creation-Date: 2013-05-31 18:55+0000\n" | ||||
| "PO-Revision-Date: 2013-04-27 00:04+0800\n" | ||||
| "Last-Translator: Cheng-Chia Tseng <pswo10680@gmail.com>\n" | ||||
| "Language-Team: Chinese (Taiwan) <zh-l10n@lists.linux.org.tw>\n" | ||||
| "Language: \n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=1; plural=0;\n" | ||||
| "X-Generator: Poedit 1.5.3\n" | ||||
| "X-Generator: Poedit 1.5.4\n" | ||||
|  | ||||
| #: ../data/50-gnome-shell-screenshot.xml.in.h:1 | ||||
| msgid "Screenshots" | ||||
| @@ -343,44 +344,50 @@ msgstr "擴充功能" | ||||
| msgid "Select an extension to configure using the combobox above." | ||||
| msgstr "使用上面的組合方塊選擇要設定的擴充功能。" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:405 | ||||
| #| msgid "Session..." | ||||
| #: ../js/gdm/loginDialog.js:371 | ||||
| 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:629 | ||||
| #: ../js/gdm/loginDialog.js:601 | ||||
| msgid "Not listed?" | ||||
| msgstr "沒有列出來?" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:783 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:162 ../js/ui/endSessionDialog.js:375 | ||||
| #: ../js/gdm/loginDialog.js:776 ../js/ui/components/networkAgent.js:137 | ||||
| #: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:376 | ||||
| #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:126 | ||||
| #: ../js/ui/userMenu.js:934 | ||||
| #: ../js/ui/status/bluetooth.js:415 ../js/ui/unlockDialog.js:96 | ||||
| #: ../js/ui/userMenu.js:938 | ||||
| msgid "Cancel" | ||||
| msgstr "取消" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:799 | ||||
| #: ../js/gdm/loginDialog.js:791 | ||||
| msgctxt "button" | ||||
| msgid "Sign In" | ||||
| msgstr "登入" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:799 | ||||
| #: ../js/gdm/loginDialog.js:791 | ||||
| msgid "Next" | ||||
| msgstr "下一個" | ||||
|  | ||||
| #. 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 "(例如: user 或 %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:904 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/gdm/loginDialog.js:892 ../js/ui/components/networkAgent.js:260 | ||||
| #: ../js/ui/components/networkAgent.js:278 | ||||
| msgid "Username: " | ||||
| msgstr "使用者名稱:" | ||||
|  | ||||
| #: ../js/gdm/loginDialog.js:1157 | ||||
| #: ../js/gdm/loginDialog.js:1158 | ||||
| msgid "Login Window" | ||||
| msgstr "登入視窗" | ||||
|  | ||||
| @@ -389,8 +396,8 @@ msgstr "登入視窗" | ||||
| msgid "Power" | ||||
| msgstr "電源" | ||||
|  | ||||
| #: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:695 ../js/ui/userMenu.js:699 | ||||
| #: ../js/ui/userMenu.js:815 | ||||
| #: ../js/gdm/powerMenu.js:93 ../js/ui/userMenu.js:696 ../js/ui/userMenu.js:700 | ||||
| #: ../js/ui/userMenu.js:816 | ||||
| msgid "Suspend" | ||||
| msgstr "暫停" | ||||
|  | ||||
| @@ -398,58 +405,53 @@ msgstr "暫停" | ||||
| msgid "Restart" | ||||
| msgstr "重新啟動" | ||||
|  | ||||
| #: ../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 | ||||
| #: ../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 | ||||
| msgid "Power Off" | ||||
| msgstr "關閉電源" | ||||
|  | ||||
| #: ../js/gdm/util.js:182 | ||||
| #: ../js/gdm/util.js:247 | ||||
| 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:299 | ||||
| #: ../js/gdm/util.js:364 | ||||
| msgid "(or swipe finger)" | ||||
| msgstr "(或是滑過手指)" | ||||
|  | ||||
| #: ../js/gdm/util.js:324 | ||||
| #, c-format | ||||
| msgid "(e.g., user or %s)" | ||||
| msgstr "(例如: user 或 %s)" | ||||
|  | ||||
| #: ../js/misc/util.js:94 | ||||
| #: ../js/misc/util.js:97 | ||||
| msgid "Command not found" | ||||
| msgstr "找不到指令" | ||||
|  | ||||
| #. Replace "Error invoking GLib.shell_parse_argv: " with | ||||
| #. something nicer | ||||
| #: ../js/misc/util.js:127 | ||||
| #: ../js/misc/util.js:130 | ||||
| msgid "Could not parse command:" | ||||
| msgstr "無法分析指令:" | ||||
|  | ||||
| #: ../js/misc/util.js:135 | ||||
| #: ../js/misc/util.js:138 | ||||
| #, c-format | ||||
| msgid "Execution of '%s' failed:" | ||||
| msgstr "執行「%s」失敗:" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:348 | ||||
| #: ../js/ui/appDisplay.js:356 | ||||
| msgid "Frequent" | ||||
| msgstr "頻率" | ||||
| msgstr "常用" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:355 | ||||
| #: ../js/ui/appDisplay.js:363 | ||||
| msgid "All" | ||||
| msgstr "全部" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:913 | ||||
| #: ../js/ui/appDisplay.js:941 | ||||
| msgid "New Window" | ||||
| msgstr "新視窗" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:916 ../js/ui/dash.js:284 | ||||
| #: ../js/ui/appDisplay.js:944 ../js/ui/dash.js:284 | ||||
| msgid "Remove from Favorites" | ||||
| msgstr "自喜好中移除" | ||||
|  | ||||
| #: ../js/ui/appDisplay.js:917 | ||||
| #: ../js/ui/appDisplay.js:945 | ||||
| msgid "Add to Favorites" | ||||
| msgstr "加入喜好" | ||||
|  | ||||
| @@ -463,7 +465,7 @@ msgstr "%s 已加入您的喜好中。" | ||||
| msgid "%s has been removed from your favorites." | ||||
| msgstr "%s 已經從您的喜好中移除。" | ||||
|  | ||||
| #: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:788 | ||||
| #: ../js/ui/backgroundMenu.js:19 ../js/ui/userMenu.js:789 | ||||
| msgid "Settings" | ||||
| msgstr "設定值" | ||||
|  | ||||
| @@ -486,7 +488,7 @@ msgctxt "event list time" | ||||
| msgid "%H\\u2236%M" | ||||
| msgstr "%H\\u2236%M" | ||||
|  | ||||
| #. Transators: Shown in calendar event list, if 12h format, | ||||
| #. Translators: Shown in calendar event list, if 12h format, | ||||
| #. \u2236 is a ratio character, similar to : and \u2009 is | ||||
| #. a thin space | ||||
| #: ../js/ui/calendar.js:77 | ||||
| @@ -588,35 +590,35 @@ msgid "S" | ||||
| msgstr "六" | ||||
|  | ||||
| #. Translators: Text to show if there are no events | ||||
| #: ../js/ui/calendar.js:692 | ||||
| #: ../js/ui/calendar.js:720 | ||||
| msgid "Nothing Scheduled" | ||||
| msgstr "沒有預訂行程" | ||||
|  | ||||
| #. Translators: Shown on calendar heading when selected day occurs on current year | ||||
| #: ../js/ui/calendar.js:708 | ||||
| #: ../js/ui/calendar.js:736 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%m月%d日%A" | ||||
|  | ||||
| #. Translators: Shown on calendar heading when selected day occurs on different year | ||||
| #: ../js/ui/calendar.js:711 | ||||
| #: ../js/ui/calendar.js:739 | ||||
| msgctxt "calendar heading" | ||||
| msgid "%A, %B %d, %Y" | ||||
| msgstr "%Y年%m月%d日%A" | ||||
|  | ||||
| #: ../js/ui/calendar.js:721 | ||||
| #: ../js/ui/calendar.js:749 | ||||
| msgid "Today" | ||||
| msgstr "今天" | ||||
|  | ||||
| #: ../js/ui/calendar.js:725 | ||||
| #: ../js/ui/calendar.js:753 | ||||
| msgid "Tomorrow" | ||||
| msgstr "明天" | ||||
|  | ||||
| #: ../js/ui/calendar.js:736 | ||||
| #: ../js/ui/calendar.js:764 | ||||
| msgid "This week" | ||||
| msgstr "本週" | ||||
|  | ||||
| #: ../js/ui/calendar.js:744 | ||||
| #: ../js/ui/calendar.js:772 | ||||
| msgid "Next week" | ||||
| msgstr "下週" | ||||
|  | ||||
| @@ -632,20 +634,20 @@ msgstr "外部裝置已拔除" | ||||
| msgid "Removable Devices" | ||||
| msgstr "可移除式裝置" | ||||
|  | ||||
| #: ../js/ui/components/autorunManager.js:593 | ||||
| #: ../js/ui/components/autorunManager.js:594 | ||||
| #, c-format | ||||
| msgid "Open with %s" | ||||
| msgstr "用 %s 開啟" | ||||
|  | ||||
| #: ../js/ui/components/autorunManager.js:619 | ||||
| #: ../js/ui/components/autorunManager.js:620 | ||||
| msgid "Eject" | ||||
| msgstr "退出" | ||||
|  | ||||
| #: ../js/ui/components/keyring.js:82 ../js/ui/components/polkitAgent.js:268 | ||||
| #: ../js/ui/components/keyring.js:88 ../js/ui/components/polkitAgent.js:280 | ||||
| msgid "Password:" | ||||
| msgstr "密碼: " | ||||
|  | ||||
| #: ../js/ui/components/keyring.js:101 | ||||
| #: ../js/ui/components/keyring.js:107 | ||||
| msgid "Type again:" | ||||
| msgstr "再輸入一次:" | ||||
|  | ||||
| @@ -723,15 +725,15 @@ msgstr "行動寬頻網路密碼" | ||||
| msgid "A password is required to connect to '%s'." | ||||
| msgstr "連線至「%s」需要密碼。" | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:55 | ||||
| #: ../js/ui/components/polkitAgent.js:54 | ||||
| msgid "Authentication Required" | ||||
| msgstr "要求驗證" | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:93 | ||||
| #: ../js/ui/components/polkitAgent.js:92 | ||||
| msgid "Administrator" | ||||
| msgstr "系統管理員" | ||||
|  | ||||
| #: ../js/ui/components/polkitAgent.js:165 | ||||
| #: ../js/ui/components/polkitAgent.js:170 | ||||
| msgid "Authenticate" | ||||
| msgstr "驗證" | ||||
|  | ||||
| @@ -739,12 +741,12 @@ msgstr "驗證" | ||||
| #. * requested authentication was not gained; this can happen | ||||
| #. * because of an authentication error (like invalid password), | ||||
| #. * for instance. | ||||
| #: ../js/ui/components/polkitAgent.js:256 ../js/ui/shellMountOperation.js:383 | ||||
| #: ../js/ui/components/polkitAgent.js:266 ../js/ui/shellMountOperation.js:383 | ||||
| msgid "Sorry, that didn't work. Please try again." | ||||
| msgstr "抱歉,那樣無法運作。請再試一次。" | ||||
|  | ||||
| #. Translators: this is a filename used for screencast recording | ||||
| #: ../js/ui/components/recorder.js:48 | ||||
| #: ../js/ui/components/recorder.js:47 | ||||
| #, no-c-format | ||||
| msgid "Screencast from %d %t" | ||||
| msgstr "Screencast from %d %t" | ||||
| @@ -1006,14 +1008,14 @@ msgstr "開啟行事曆" | ||||
| msgid "Open Clocks" | ||||
| msgstr "開啟時鐘" | ||||
|  | ||||
| #: ../js/ui/dateMenu.js:105 | ||||
| #: ../js/ui/dateMenu.js:104 | ||||
| msgid "Date & Time Settings" | ||||
| 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:205 | ||||
| #: ../js/ui/dateMenu.js:216 | ||||
| msgid "%A %B %e, %Y" | ||||
| msgstr "%Y年%m月%e日%A" | ||||
|  | ||||
| @@ -1110,7 +1112,7 @@ msgstr "安裝" | ||||
| msgid "Download and install '%s' from extensions.gnome.org?" | ||||
| msgstr "是否從 extensions.gnome.org 下載並安裝「%s」?" | ||||
|  | ||||
| #: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:314 | ||||
| #: ../js/ui/keyboard.js:619 ../js/ui/status/keyboard.js:333 | ||||
| #: ../js/ui/status/power.js:211 | ||||
| msgid "Keyboard" | ||||
| msgstr "鍵盤" | ||||
| @@ -1172,7 +1174,6 @@ msgid "Remove" | ||||
| msgstr "移除" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1501 | ||||
| #| msgid "No Messages" | ||||
| msgid "Clear Messages" | ||||
| msgstr "清除訊息" | ||||
|  | ||||
| @@ -1180,15 +1181,15 @@ msgstr "清除訊息" | ||||
| msgid "Notification Settings" | ||||
| msgstr "通知設定值" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1707 | ||||
| #: ../js/ui/messageTray.js:1709 | ||||
| msgid "No Messages" | ||||
| msgstr "沒有訊息" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:1787 | ||||
| #: ../js/ui/messageTray.js:1785 | ||||
| msgid "Message Tray" | ||||
| msgstr "訊息匣" | ||||
|  | ||||
| #: ../js/ui/messageTray.js:2864 | ||||
| #: ../js/ui/messageTray.js:2818 | ||||
| msgid "System Information" | ||||
| msgstr "系統資訊" | ||||
|  | ||||
| @@ -1197,13 +1198,13 @@ msgctxt "program" | ||||
| msgid "Unknown" | ||||
| msgstr "不明" | ||||
|  | ||||
| #: ../js/ui/overviewControls.js:460 ../js/ui/screenShield.js:153 | ||||
| #: ../js/ui/overviewControls.js:463 ../js/ui/screenShield.js:149 | ||||
| #, c-format | ||||
| msgid "%d new message" | ||||
| msgid_plural "%d new messages" | ||||
| msgstr[0] "%d 個新訊息" | ||||
|  | ||||
| #: ../js/ui/overview.js:82 | ||||
| #: ../js/ui/overview.js:84 | ||||
| msgid "Undo" | ||||
| msgstr "復原" | ||||
|  | ||||
| @@ -1215,22 +1216,21 @@ msgstr "概覽" | ||||
| #. in the search entry when no search is | ||||
| #. active; it should not exceed ~30 | ||||
| #. characters. | ||||
| #: ../js/ui/overview.js:284 | ||||
| #| msgid "Type to search..." | ||||
| #: ../js/ui/overview.js:271 | ||||
| msgid "Type to search…" | ||||
| msgstr "輸入以搜尋…" | ||||
|  | ||||
| #: ../js/ui/panel.js:613 | ||||
| #: ../js/ui/panel.js:635 | ||||
| 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:642 | ||||
| #: ../js/ui/panel.js:686 | ||||
| msgid "Activities" | ||||
| msgstr "概覽 " | ||||
|  | ||||
| #: ../js/ui/panel.js:983 | ||||
| #: ../js/ui/panel.js:982 | ||||
| msgid "Top Bar" | ||||
| msgstr "頂端列" | ||||
|  | ||||
| @@ -1239,35 +1239,35 @@ 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:727 | ||||
| #: ../js/ui/popupMenu.js:740 | ||||
| msgid "toggle-switch-us" | ||||
| msgstr "toggle-switch-us" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:205 | ||||
| #: ../js/ui/runDialog.js:74 | ||||
| msgid "Enter a Command" | ||||
| msgstr "請輸入指令" | ||||
|  | ||||
| #: ../js/ui/runDialog.js:241 | ||||
| #: ../js/ui/runDialog.js:110 | ||||
| msgid "Close" | ||||
| msgstr "關閉" | ||||
|  | ||||
| #. Translators: This is a time format for a date in | ||||
| #. long format | ||||
| #: ../js/ui/screenShield.js:90 | ||||
| #: ../js/ui/screenShield.js:86 | ||||
| msgid "%A, %B %d" | ||||
| msgstr "%m月%d日%A" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:155 | ||||
| #: ../js/ui/screenShield.js:151 | ||||
| #, c-format | ||||
| msgid "%d new notification" | ||||
| msgid_plural "%d new notifications" | ||||
| msgstr[0] "%d 個新通知" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:442 ../js/ui/userMenu.js:806 | ||||
| #: ../js/ui/screenShield.js:438 ../js/ui/userMenu.js:807 | ||||
| msgid "Lock" | ||||
| msgstr "鎖定" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:639 | ||||
| #: ../js/ui/screenShield.js:641 | ||||
| msgid "GNOME needs to lock the screen" | ||||
| msgstr "GNOME 需要鎖定螢幕" | ||||
|  | ||||
| @@ -1278,37 +1278,35 @@ 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:758 ../js/ui/screenShield.js:1169 | ||||
| #| msgid "Unable to connect to %s" | ||||
| #: ../js/ui/screenShield.js:762 ../js/ui/screenShield.js:1198 | ||||
| msgid "Unable to lock" | ||||
| msgstr "無法鎖定" | ||||
|  | ||||
| #: ../js/ui/screenShield.js:759 ../js/ui/screenShield.js:1170 | ||||
| #: ../js/ui/screenShield.js:763 ../js/ui/screenShield.js:1199 | ||||
| msgid "Lock was blocked by an application" | ||||
| msgstr "鎖定被應用程式阻擋" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:431 | ||||
| #| msgid "Searching..." | ||||
| #: ../js/ui/searchDisplay.js:453 | ||||
| msgid "Searching…" | ||||
| msgstr "搜尋…" | ||||
|  | ||||
| #: ../js/ui/searchDisplay.js:475 | ||||
| #: ../js/ui/searchDisplay.js:497 | ||||
| msgid "No results." | ||||
| msgstr "沒有結果。" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:29 | ||||
| #: ../js/ui/shellEntry.js:27 | ||||
| msgid "Copy" | ||||
| msgstr "複製" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:34 | ||||
| #: ../js/ui/shellEntry.js:32 | ||||
| msgid "Paste" | ||||
| msgstr "貼上" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:105 | ||||
| #: ../js/ui/shellEntry.js:99 | ||||
| msgid "Show Text" | ||||
| msgstr "顯示文字" | ||||
|  | ||||
| #: ../js/ui/shellEntry.js:107 | ||||
| #: ../js/ui/shellEntry.js:101 | ||||
| msgid "Hide Text" | ||||
| msgstr "隱藏文字" | ||||
|  | ||||
| @@ -1320,7 +1318,7 @@ msgstr "密碼" | ||||
| msgid "Remember Password" | ||||
| msgstr "記住密碼" | ||||
|  | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:140 | ||||
| #: ../js/ui/shellMountOperation.js:403 ../js/ui/unlockDialog.js:109 | ||||
| msgid "Unlock" | ||||
| msgstr "解鎖" | ||||
|  | ||||
| @@ -1384,12 +1382,10 @@ 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 "設定新的裝置…" | ||||
|  | ||||
| @@ -1416,7 +1412,6 @@ msgid "connecting..." | ||||
| msgstr "連線中…" | ||||
|  | ||||
| #: ../js/ui/status/bluetooth.js:239 | ||||
| #| msgid "Send Files..." | ||||
| msgid "Send Files…" | ||||
| msgstr "傳送檔案…" | ||||
|  | ||||
| @@ -1492,11 +1487,11 @@ msgstr "請輸入裝置所提及的 PIN。" | ||||
| msgid "OK" | ||||
| msgstr "確定" | ||||
|  | ||||
| #: ../js/ui/status/keyboard.js:368 | ||||
| #: ../js/ui/status/keyboard.js:396 | ||||
| msgid "Show Keyboard Layout" | ||||
| msgstr "顯示鍵盤配置" | ||||
|  | ||||
| #: ../js/ui/status/keyboard.js:373 | ||||
| #: ../js/ui/status/keyboard.js:401 | ||||
| msgid "Region & Language Settings" | ||||
| msgstr "地區和語言設定值" | ||||
|  | ||||
| @@ -1614,7 +1609,7 @@ msgstr "連線失敗" | ||||
| msgid "Activation of network connection failed" | ||||
| msgstr "啟動網路連線失敗" | ||||
|  | ||||
| #: ../js/ui/status/network.js:2276 | ||||
| #: ../js/ui/status/network.js:2282 | ||||
| msgid "Networking is disabled" | ||||
| msgstr "網路已停用" | ||||
|  | ||||
| @@ -1629,7 +1624,6 @@ 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 "評估中…" | ||||
|  | ||||
| @@ -1725,11 +1719,11 @@ msgstr "音量" | ||||
| msgid "Microphone" | ||||
| msgstr "麥克風" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:151 | ||||
| #: ../js/ui/unlockDialog.js:120 | ||||
| msgid "Log in as another user" | ||||
| msgstr "以另一個使用者身分登入" | ||||
|  | ||||
| #: ../js/ui/unlockDialog.js:177 | ||||
| #: ../js/ui/unlockDialog.js:141 | ||||
| msgid "Unlock Window" | ||||
| msgstr "解鎖視窗" | ||||
|  | ||||
| @@ -1757,27 +1751,27 @@ msgstr "閒置" | ||||
| msgid "Offline" | ||||
| msgstr "離線" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:780 | ||||
| #: ../js/ui/userMenu.js:781 | ||||
| msgid "Notifications" | ||||
| msgstr "通知" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:796 | ||||
| #: ../js/ui/userMenu.js:797 | ||||
| msgid "Switch User" | ||||
| msgstr "切換使用者" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:801 | ||||
| #: ../js/ui/userMenu.js:802 | ||||
| msgid "Log Out" | ||||
| msgstr "登出" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:821 | ||||
| #: ../js/ui/userMenu.js:822 | ||||
| msgid "Install Updates & Restart" | ||||
| msgstr "安裝更新 & 重新啟動" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:839 | ||||
| #: ../js/ui/userMenu.js:840 | ||||
| msgid "Your chat status will be set to busy" | ||||
| msgstr "您的聊天狀態會設為忙碌" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:840 | ||||
| #: ../js/ui/userMenu.js:841 | ||||
| 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." | ||||
| @@ -1785,20 +1779,22 @@ msgstr "" | ||||
| "通知現在已被停用,包含聊天訊息。您的上線狀態也調整為讓其他人知道您沒時間看他" | ||||
| "們的訊息。" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:886 | ||||
| #: ../js/ui/userMenu.js:888 | ||||
| msgid "Other users are logged in." | ||||
| msgstr "其他使用者已登入。" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:891 | ||||
| #: ../js/ui/userMenu.js:893 | ||||
| msgid "Shutting down might cause them to lose unsaved work." | ||||
| msgstr "關機可能使它們失去未儲存的工作。" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:918 | ||||
| #. Translators: Remote here refers to a remote session, like a ssh login | ||||
| #: ../js/ui/userMenu.js:921 | ||||
| #, c-format | ||||
| msgid "%s (remote)" | ||||
| msgstr "%s (遠端)" | ||||
|  | ||||
| #: ../js/ui/userMenu.js:920 | ||||
| #. Translators: Console here refers to a tty like a VT console | ||||
| #: ../js/ui/userMenu.js:924 | ||||
| #, c-format | ||||
| msgid "%s (console)" | ||||
| msgstr "%s (主控臺)" | ||||
| @@ -1811,7 +1807,7 @@ msgstr "應用程式" | ||||
| msgid "Search" | ||||
| msgstr "搜尋" | ||||
|  | ||||
| #: ../js/ui/wanda.js:92 | ||||
| #: ../js/ui/wanda.js:77 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Sorry, no wisdom for you today:\n" | ||||
| @@ -1820,7 +1816,7 @@ msgstr "" | ||||
| "抱歉,今天可能有些問題:\n" | ||||
| "%s" | ||||
|  | ||||
| #: ../js/ui/wanda.js:96 | ||||
| #: ../js/ui/wanda.js:81 | ||||
| #, c-format | ||||
| msgid "%s the Oracle says" | ||||
| msgstr "%s Oracle 說:" | ||||
| @@ -1850,7 +1846,7 @@ msgid "%u Input" | ||||
| msgid_plural "%u Inputs" | ||||
| msgstr[0] "%u 輸入" | ||||
|  | ||||
| #: ../src/gvc/gvc-mixer-control.c:2371 | ||||
| #: ../src/gvc/gvc-mixer-control.c:2373 | ||||
| msgid "System Sounds" | ||||
| msgstr "系統音效" | ||||
|  | ||||
| @@ -1875,11 +1871,11 @@ msgstr "列出可能的模式" | ||||
| msgid "Failed to launch '%s'" | ||||
| msgstr "無法啟動「%s」" | ||||
|  | ||||
| #: ../src/shell-keyring-prompt.c:708 | ||||
| #: ../src/shell-keyring-prompt.c:714 | ||||
| msgid "Passwords do not match." | ||||
| msgstr "密碼不相符。" | ||||
|  | ||||
| #: ../src/shell-keyring-prompt.c:716 | ||||
| #: ../src/shell-keyring-prompt.c:722 | ||||
| msgid "Password cannot be blank" | ||||
| msgstr "密碼不能為空白" | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								src/gvc
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								src/gvc
									
									
									
									
									
								
							 Submodule src/gvc updated: 03894efbcd...3d6aac673b
									
								
							
							
								
								
									
										20
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/main.c
									
									
									
									
									
								
							| @@ -36,8 +36,6 @@ extern GType gnome_shell_plugin_get_type (void); | ||||
| #define SHELL_DBUS_SERVICE "org.gnome.Shell" | ||||
| #define MAGNIFIER_DBUS_SERVICE "org.gnome.Magnifier" | ||||
|  | ||||
| #define OVERRIDES_SCHEMA "org.gnome.shell.overrides" | ||||
|  | ||||
| #define WM_NAME "GNOME Shell" | ||||
| #define GNOME_WM_KEYBINDINGS "Mutter,GNOME Shell" | ||||
|  | ||||
| @@ -166,23 +164,6 @@ shell_dbus_init (gboolean replace) | ||||
|   g_object_unref (session); | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_prefs_init (void) | ||||
| { | ||||
|   meta_prefs_override_preference_schema ("attach-modal-dialogs", | ||||
|                                          OVERRIDES_SCHEMA); | ||||
|   meta_prefs_override_preference_schema ("dynamic-workspaces", | ||||
|                                          OVERRIDES_SCHEMA); | ||||
|   meta_prefs_override_preference_schema ("workspaces-only-on-primary", | ||||
|                                          OVERRIDES_SCHEMA); | ||||
|   meta_prefs_override_preference_schema ("button-layout", | ||||
|                                          OVERRIDES_SCHEMA); | ||||
|   meta_prefs_override_preference_schema ("edge-tiling", | ||||
|                                          OVERRIDES_SCHEMA); | ||||
|   meta_prefs_override_preference_schema ("focus-change-on-pointer-rest", | ||||
|                                          OVERRIDES_SCHEMA); | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_introspection_init (void) | ||||
| { | ||||
| @@ -409,7 +390,6 @@ main (int argc, char **argv) | ||||
|   shell_dbus_init (meta_get_replace_current_wm ()); | ||||
|   shell_a11y_init (); | ||||
|   shell_perf_log_init (); | ||||
|   shell_prefs_init (); | ||||
|   shell_introspection_init (); | ||||
|   shell_fonts_init (); | ||||
|  | ||||
|   | ||||
| @@ -210,6 +210,7 @@ shell_app_create_icon_texture (ShellApp   *app, | ||||
| typedef struct { | ||||
|   ShellApp *app; | ||||
|   int size; | ||||
|   ClutterTextDirection direction; | ||||
| } CreateFadedIconData; | ||||
|  | ||||
| static CoglHandle | ||||
| @@ -227,7 +228,7 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache, | ||||
|   guint8 n_channels; | ||||
|   gboolean have_alpha; | ||||
|   gint fade_start; | ||||
|   gint fade_range; | ||||
|   gint fade_end; | ||||
|   guint i, j; | ||||
|   guint pixbuf_byte_size; | ||||
|   guint8 *orig_pixels; | ||||
| @@ -279,14 +280,26 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache, | ||||
|   pixels = g_malloc0 (rowstride * height); | ||||
|   memcpy (pixels, orig_pixels, pixbuf_byte_size); | ||||
|  | ||||
|   fade_start = width / 2; | ||||
|   fade_range = width - fade_start; | ||||
|   for (i = fade_start; i < width; i++) | ||||
|   /* fade on the right side for LTR, left side for RTL */ | ||||
|   if (data->direction == CLUTTER_TEXT_DIRECTION_LTR) | ||||
|     { | ||||
|       fade_start = width / 2; | ||||
|       fade_end = width; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       fade_start = 0; | ||||
|       fade_end = width / 2; | ||||
|     } | ||||
|  | ||||
|   for (i = fade_start; i < fade_end; i++) | ||||
|     { | ||||
|       for (j = 0; j < height; j++) | ||||
|         { | ||||
|           guchar *pixel = &pixels[j * rowstride + i * n_channels]; | ||||
|           float fade = 1.0 - ((float) i - fade_start) / fade_range; | ||||
|           float fade = ((float) i - fade_start) / (fade_end - fade_start); | ||||
|           if (data->direction == CLUTTER_TEXT_DIRECTION_LTR) | ||||
|             fade = 1.0 - fade; | ||||
|           pixel[0] = 0.5 + pixel[0] * fade; | ||||
|           pixel[1] = 0.5 + pixel[1] * fade; | ||||
|           pixel[2] = 0.5 + pixel[2] * fade; | ||||
| @@ -312,13 +325,14 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache, | ||||
|  * shell_app_get_faded_icon: | ||||
|  * @app: A #ShellApp | ||||
|  * @size: Size in pixels | ||||
|  * @direction: Whether to fade on the left or right | ||||
|  * | ||||
|  * Return an actor with a horizontally faded look. | ||||
|  * | ||||
|  * Return value: (transfer none): A floating #ClutterActor, or %NULL if no icon | ||||
|  */ | ||||
| ClutterActor * | ||||
| shell_app_get_faded_icon (ShellApp *app, int size) | ||||
| shell_app_get_faded_icon (ShellApp *app, int size, ClutterTextDirection direction) | ||||
| { | ||||
|   CoglHandle texture; | ||||
|   ClutterActor *result; | ||||
| @@ -334,9 +348,13 @@ shell_app_get_faded_icon (ShellApp *app, int size) | ||||
|  | ||||
|   /* Use icon: prefix so that we get evicted from the cache on | ||||
|    * icon theme changes. */ | ||||
|   cache_key = g_strdup_printf ("icon:%s,size=%d,faded", shell_app_get_id (app), size); | ||||
|   cache_key = g_strdup_printf ("icon:%s,size=%d,faded-%s", | ||||
|                                shell_app_get_id (app), | ||||
|                                size, | ||||
|                                direction == CLUTTER_TEXT_DIRECTION_RTL ? "rtl" : "ltr"); | ||||
|   data.app = app; | ||||
|   data.size = size; | ||||
|   data.direction = direction; | ||||
|   texture = st_texture_cache_load (st_texture_cache_get_default (), | ||||
|                                    cache_key, | ||||
|                                    ST_TEXTURE_CACHE_POLICY_FOREVER, | ||||
|   | ||||
| @@ -42,7 +42,7 @@ GMenuTreeEntry *shell_app_get_tree_entry (ShellApp *app); | ||||
| GDesktopAppInfo *shell_app_get_app_info (ShellApp *app); | ||||
|  | ||||
| ClutterActor *shell_app_create_icon_texture (ShellApp *app, int size); | ||||
| ClutterActor *shell_app_get_faded_icon (ShellApp *app, int size); | ||||
| ClutterActor *shell_app_get_faded_icon (ShellApp *app, int size, ClutterTextDirection direction); | ||||
| const char *shell_app_get_name (ShellApp *app); | ||||
| const char *shell_app_get_description (ShellApp *app); | ||||
| gboolean shell_app_is_window_backed (ShellApp *app); | ||||
|   | ||||
| @@ -1009,6 +1009,13 @@ shell_global_end_modal (ShellGlobal *global, | ||||
|   meta_plugin_end_modal (global->plugin, timestamp); | ||||
| } | ||||
|  | ||||
| void | ||||
| shell_global_freeze_keyboard (ShellGlobal *global, | ||||
|                               guint32      timestamp) | ||||
| { | ||||
|   meta_display_freeze_keyboard (global->meta_display, global->stage_xwindow, timestamp); | ||||
| } | ||||
|  | ||||
| /* Code to close all file descriptors before we exec; copied from gspawn.c in GLib. | ||||
|  * | ||||
|  * Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering | ||||
|   | ||||
| @@ -44,6 +44,8 @@ gboolean shell_global_begin_modal            (ShellGlobal         *global, | ||||
|                                               MetaModalOptions    options); | ||||
| void     shell_global_end_modal              (ShellGlobal         *global, | ||||
|                                               guint32              timestamp); | ||||
| void     shell_global_freeze_keyboard        (ShellGlobal         *global, | ||||
|                                               guint32              timestamp); | ||||
|  | ||||
| typedef enum { | ||||
|   SHELL_STAGE_INPUT_MODE_NONREACTIVE, | ||||
|   | ||||
| @@ -106,6 +106,8 @@ shell_gtk_embed_window_created_cb (MetaDisplay   *display, | ||||
|                                              0, 0 /* offset x/y */); | ||||
|       cairo_region_destroy (empty_region); | ||||
|  | ||||
|       gdk_window_lower (gdk_window); | ||||
|  | ||||
|       /* Now that we've found the window we don't need to listen for | ||||
|          new windows anymore */ | ||||
|       g_signal_handler_disconnect (display, | ||||
|   | ||||
| @@ -15,6 +15,8 @@ | ||||
|  * @SHELL_KEYBINDING_MODE_SYSTEM_MODAL: allow keybinding when a system modal | ||||
|  *     dialog (e.g. authentification or session dialogs) is open | ||||
|  * @SHELL_KEYBINDING_MODE_LOOKING_GLASS: allow keybinding in looking glass | ||||
|  * @SHELL_KEYBINDING_MODE_TOPBAR_POPUP: allow keybinding while a top bar menu | ||||
|  *     is open | ||||
|  * @SHELL_KEYBINDING_MODE_ALL: always allow keybinding | ||||
|  * | ||||
|  * Controls in which GNOME Shell states a keybinding should be handled. | ||||
| @@ -29,6 +31,7 @@ typedef enum { | ||||
|   SHELL_KEYBINDING_MODE_MESSAGE_TRAY  = 1 << 5, | ||||
|   SHELL_KEYBINDING_MODE_SYSTEM_MODAL  = 1 << 6, | ||||
|   SHELL_KEYBINDING_MODE_LOOKING_GLASS = 1 << 7, | ||||
|   SHELL_KEYBINDING_MODE_TOPBAR_POPUP  = 1 << 8, | ||||
|  | ||||
|   SHELL_KEYBINDING_MODE_ALL = ~0, | ||||
| } ShellKeyBindingMode; | ||||
|   | ||||
| @@ -100,7 +100,6 @@ G_DEFINE_TYPE_WITH_CODE (ShellKeyringPrompt, shell_keyring_prompt, G_TYPE_OBJECT | ||||
| enum { | ||||
|   SIGNAL_SHOW_PASSWORD, | ||||
|   SIGNAL_SHOW_CONFIRM, | ||||
|   SIGNAL_HIDE_PROMPT, | ||||
|   SIGNAL_LAST | ||||
| }; | ||||
|  | ||||
| @@ -258,10 +257,8 @@ shell_keyring_prompt_dispose (GObject *obj) | ||||
| { | ||||
|   ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (obj); | ||||
|  | ||||
|   if (self->shown) { | ||||
|     self->shown = FALSE; | ||||
|     g_signal_emit (self, signals[SIGNAL_HIDE_PROMPT], 0); | ||||
|   } | ||||
|   if (self->shown) | ||||
|     gcr_prompt_close (GCR_PROMPT (self)); | ||||
|  | ||||
|   if (self->async_result) | ||||
|     shell_keyring_prompt_cancel (self); | ||||
| @@ -384,11 +381,6 @@ shell_keyring_prompt_class_init (ShellKeyringPromptClass *klass) | ||||
|                                                 0, 0, NULL, NULL, | ||||
|                                                 g_cclosure_marshal_VOID__VOID, | ||||
|                                                 G_TYPE_NONE, 0); | ||||
|  | ||||
|   signals[SIGNAL_HIDE_PROMPT] =  g_signal_new ("hide-prompt", G_TYPE_FROM_CLASS (klass), | ||||
|                                                0, 0, NULL, NULL, | ||||
|                                                g_cclosure_marshal_VOID__VOID, | ||||
|                                                G_TYPE_NONE, 0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -482,6 +474,19 @@ shell_keyring_prompt_confirm_finish (GcrPrompt    *prompt, | ||||
|   return self->last_reply; | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_keyring_prompt_close (GcrPrompt *prompt) | ||||
| { | ||||
|   ShellKeyringPrompt *self = SHELL_KEYRING_PROMPT (prompt); | ||||
|  | ||||
|   /* | ||||
|    * We expect keyring.js to connect to this signal and do the | ||||
|    * actual work of closing the prompt. | ||||
|    */ | ||||
|  | ||||
|   self->shown = FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_keyring_prompt_iface (GcrPromptIface *iface) | ||||
| { | ||||
| @@ -489,6 +494,7 @@ shell_keyring_prompt_iface (GcrPromptIface *iface) | ||||
|   iface->prompt_password_finish = shell_keyring_prompt_password_finish; | ||||
|   iface->prompt_confirm_async = shell_keyring_prompt_confirm_async; | ||||
|   iface->prompt_confirm_finish = shell_keyring_prompt_confirm_finish; | ||||
|   iface->prompt_close = shell_keyring_prompt_close; | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -746,9 +752,19 @@ shell_keyring_prompt_cancel (ShellKeyringPrompt *self) | ||||
|   GSimpleAsyncResult *res; | ||||
|  | ||||
|   g_return_if_fail (SHELL_IS_KEYRING_PROMPT (self)); | ||||
|   g_return_if_fail (self->mode != PROMPTING_NONE); | ||||
|   g_return_if_fail (self->async_result != NULL); | ||||
|  | ||||
|   /* | ||||
|    * If cancelled while not prompting, we should just close the prompt, | ||||
|    * the user wants it to go away. | ||||
|    */ | ||||
|   if (self->mode == PROMPTING_NONE) | ||||
|     { | ||||
|       if (self->shown) | ||||
|         gcr_prompt_close (GCR_PROMPT (self)); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   g_return_if_fail (self->async_result != NULL); | ||||
|   self->last_reply = GCR_PROMPT_REPLY_CANCEL; | ||||
|  | ||||
|   res = self->async_result; | ||||
|   | ||||
| @@ -25,6 +25,9 @@ | ||||
| /* This is also hard-coded in mutter and GDK */ | ||||
| #define VIRTUAL_CORE_POINTER_ID 2 | ||||
|  | ||||
| #define A11Y_APPS_SCHEMA "org.gnome.desktop.a11y.applications" | ||||
| #define MAGNIFIER_ACTIVE_KEY "screen-magnifier-enabled" | ||||
|  | ||||
| typedef enum { | ||||
|   RECORDER_STATE_CLOSED, | ||||
|   RECORDER_STATE_RECORDING | ||||
| @@ -50,6 +53,8 @@ struct _ShellRecorder { | ||||
|   RecorderState state; | ||||
|  | ||||
|   ClutterStage *stage; | ||||
|   gboolean custom_area; | ||||
|   cairo_rectangle_int_t area; | ||||
|   int stage_width; | ||||
|   int stage_height; | ||||
|  | ||||
| @@ -66,6 +71,8 @@ struct _ShellRecorder { | ||||
|  | ||||
|   CoglHandle recording_icon; /* icon shown while playing */ | ||||
|  | ||||
|   GSettings *a11y_settings; | ||||
|   gboolean draw_cursor; | ||||
|   cairo_surface_t *cursor_image; | ||||
|   int cursor_hot_x; | ||||
|   int cursor_hot_y; | ||||
| @@ -110,6 +117,8 @@ static void recorder_set_pipeline (ShellRecorder *recorder, | ||||
|                                    const char    *pipeline); | ||||
| static void recorder_set_file_template (ShellRecorder *recorder, | ||||
|                                         const char    *file_template); | ||||
| static void recorder_set_draw_cursor (ShellRecorder *recorder, | ||||
|                                       gboolean       draw_cursor); | ||||
|  | ||||
| static void recorder_pipeline_set_caps (RecorderPipeline *pipeline); | ||||
| static void recorder_pipeline_closed   (RecorderPipeline *pipeline); | ||||
| @@ -119,7 +128,8 @@ enum { | ||||
|   PROP_STAGE, | ||||
|   PROP_FRAMERATE, | ||||
|   PROP_PIPELINE, | ||||
|   PROP_FILE_TEMPLATE | ||||
|   PROP_FILE_TEMPLATE, | ||||
|   PROP_DRAW_CURSOR | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE(ShellRecorder, shell_recorder, G_TYPE_OBJECT); | ||||
| @@ -271,8 +281,11 @@ shell_recorder_init (ShellRecorder *recorder) | ||||
|   recorder->recording_icon = create_recording_icon (); | ||||
|   recorder->memory_target = get_memory_target(); | ||||
|  | ||||
|   recorder->a11y_settings = g_settings_new (A11Y_APPS_SCHEMA); | ||||
|  | ||||
|   recorder->state = RECORDER_STATE_CLOSED; | ||||
|   recorder->framerate = DEFAULT_FRAMES_PER_SECOND; | ||||
|   recorder->draw_cursor = TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -292,6 +305,8 @@ shell_recorder_finalize (GObject  *object) | ||||
|  | ||||
|   cogl_handle_unref (recorder->recording_icon); | ||||
|  | ||||
|   g_clear_object (&recorder->a11y_settings); | ||||
|  | ||||
|   G_OBJECT_CLASS (shell_recorder_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| @@ -429,10 +444,10 @@ recorder_draw_cursor (ShellRecorder *recorder, | ||||
|   /* We don't show a cursor unless the hot spot is in the frame; this | ||||
|    * means that sometimes we aren't going to draw a cursor even when | ||||
|    * there is a little bit overlapping within the stage */ | ||||
|   if (recorder->pointer_x < 0 || | ||||
|       recorder->pointer_y < 0 || | ||||
|       recorder->pointer_x >= recorder->stage_width || | ||||
|       recorder->pointer_y >= recorder->stage_height) | ||||
|   if (recorder->pointer_x < recorder->area.x || | ||||
|       recorder->pointer_y < recorder->area.y || | ||||
|       recorder->pointer_x >= recorder->area.x + recorder->area.width || | ||||
|       recorder->pointer_y >= recorder->area.y + recorder->area.height) | ||||
|     return; | ||||
|  | ||||
|   if (!recorder->cursor_image) | ||||
| @@ -444,15 +459,15 @@ recorder_draw_cursor (ShellRecorder *recorder, | ||||
|   gst_buffer_map (buffer, &info, GST_MAP_WRITE); | ||||
|   surface = cairo_image_surface_create_for_data (info.data, | ||||
|                                                  CAIRO_FORMAT_ARGB32, | ||||
|                                                  recorder->stage_width, | ||||
|                                                  recorder->stage_height, | ||||
|                                                  recorder->stage_width * 4); | ||||
|                                                  recorder->area.width, | ||||
|                                                  recorder->area.height, | ||||
|                                                  recorder->area.width * 4); | ||||
|  | ||||
|   cr = cairo_create (surface); | ||||
|   cairo_set_source_surface (cr, | ||||
|                             recorder->cursor_image, | ||||
|                             recorder->pointer_x - recorder->cursor_hot_x, | ||||
|                             recorder->pointer_y - recorder->cursor_hot_y); | ||||
|                             recorder->pointer_x - recorder->cursor_hot_x - recorder->area.x, | ||||
|                             recorder->pointer_y - recorder->cursor_hot_y - recorder->area.y); | ||||
|   cairo_paint (cr); | ||||
|  | ||||
|   cairo_destroy (cr); | ||||
| @@ -470,7 +485,7 @@ recorder_draw_buffer_meter (ShellRecorder *recorder) | ||||
|   GdkRectangle primary_monitor; | ||||
|   float rects[16]; | ||||
|  | ||||
|   gdk_screen_get_monitor_geometry (recorder->gdk_screen, | ||||
|   gdk_screen_get_monitor_workarea (recorder->gdk_screen, | ||||
|                                    gdk_screen_get_primary_monitor (recorder->gdk_screen), | ||||
|                                    &primary_monitor); | ||||
|  | ||||
| @@ -555,12 +570,13 @@ recorder_record_frame (ShellRecorder *recorder) | ||||
|  | ||||
|   recorder->last_frame_time = now; | ||||
|  | ||||
|   size = recorder->stage_width * recorder->stage_height * 4; | ||||
|   size = recorder->area.width * recorder->area.height * 4; | ||||
|  | ||||
|   data = g_malloc (recorder->stage_width * 4 * recorder->stage_height); | ||||
|   cogl_read_pixels (0, 0, /* x/y */ | ||||
|                     recorder->stage_width, | ||||
|                     recorder->stage_height, | ||||
|   data = g_malloc (recorder->area.width * 4 * recorder->area.height); | ||||
|   cogl_read_pixels (recorder->area.x, | ||||
|                     recorder->area.y, | ||||
|                     recorder->area.width, | ||||
|                     recorder->area.height, | ||||
|                     COGL_READ_PIXELS_COLOR_BUFFER, | ||||
|                     CLUTTER_CAIRO_FORMAT_ARGB32, | ||||
|                     data); | ||||
| @@ -572,7 +588,9 @@ recorder_record_frame (ShellRecorder *recorder) | ||||
|  | ||||
|   GST_BUFFER_PTS(buffer) = now - recorder->start_time; | ||||
|  | ||||
|   recorder_draw_cursor (recorder, buffer); | ||||
|   if (recorder->draw_cursor && | ||||
|       !g_settings_get_boolean (recorder->a11y_settings, MAGNIFIER_ACTIVE_KEY)) | ||||
|     recorder_draw_cursor (recorder, buffer); | ||||
|  | ||||
|   shell_recorder_src_add_buffer (SHELL_RECORDER_SRC (recorder->current_pipeline->src), buffer); | ||||
|   gst_buffer_unref (buffer); | ||||
| @@ -593,7 +611,7 @@ recorder_on_stage_paint (ClutterActor  *actor, | ||||
|     { | ||||
|       GdkRectangle primary_monitor; | ||||
|  | ||||
|       gdk_screen_get_monitor_geometry (recorder->gdk_screen, | ||||
|       gdk_screen_get_monitor_workarea (recorder->gdk_screen, | ||||
|                                        gdk_screen_get_primary_monitor (recorder->gdk_screen), | ||||
|                                        &primary_monitor); | ||||
|       if (!recorder->only_paint) | ||||
| @@ -616,6 +634,14 @@ recorder_update_size (ShellRecorder *recorder) | ||||
|   clutter_actor_get_allocation_box (CLUTTER_ACTOR (recorder->stage), &allocation); | ||||
|   recorder->stage_width = (int)(0.5 + allocation.x2 - allocation.x1); | ||||
|   recorder->stage_height = (int)(0.5 + allocation.y2 - allocation.y1); | ||||
|  | ||||
|   if (!recorder->custom_area) | ||||
|     { | ||||
|       recorder->area.x = 0; | ||||
|       recorder->area.y = 0; | ||||
|       recorder->area.width = recorder->stage_width; | ||||
|       recorder->area.height = recorder->stage_height; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -1006,6 +1032,18 @@ recorder_set_file_template (ShellRecorder *recorder, | ||||
|   g_object_notify (G_OBJECT (recorder), "file-template"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| recorder_set_draw_cursor (ShellRecorder *recorder, | ||||
|                           gboolean       draw_cursor) | ||||
| { | ||||
|   if (draw_cursor == recorder->draw_cursor) | ||||
|     return; | ||||
|  | ||||
|   recorder->draw_cursor = draw_cursor; | ||||
|  | ||||
|   g_object_notify (G_OBJECT (recorder), "draw-cursor"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| shell_recorder_set_property (GObject      *object, | ||||
|                              guint         prop_id, | ||||
| @@ -1028,6 +1066,9 @@ shell_recorder_set_property (GObject      *object, | ||||
|     case PROP_FILE_TEMPLATE: | ||||
|       recorder_set_file_template (recorder, g_value_get_string (value)); | ||||
|       break; | ||||
|     case PROP_DRAW_CURSOR: | ||||
|       recorder_set_draw_cursor (recorder, g_value_get_boolean (value)); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
| @@ -1056,6 +1097,9 @@ shell_recorder_get_property (GObject         *object, | ||||
|     case PROP_FILE_TEMPLATE: | ||||
|       g_value_set_string (value, recorder->file_template); | ||||
|       break; | ||||
|     case PROP_DRAW_CURSOR: | ||||
|       g_value_set_boolean (value, recorder->draw_cursor); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
| @@ -1104,6 +1148,14 @@ shell_recorder_class_init (ShellRecorderClass *klass) | ||||
|                                                         "The filename template to use for output files", | ||||
|                                                         NULL, | ||||
|                                                         G_PARAM_READWRITE)); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_DRAW_CURSOR, | ||||
|                                    g_param_spec_boolean ("draw-cursor", | ||||
|                                                          "Draw Cursor", | ||||
|                                                          "Whether to record the cursor", | ||||
|                                                          TRUE, | ||||
|                                                          G_PARAM_READWRITE)); | ||||
| } | ||||
|  | ||||
| /* Sets the GstCaps (video format, in this case) on the stream | ||||
| @@ -1126,8 +1178,8 @@ recorder_pipeline_set_caps (RecorderPipeline *pipeline) | ||||
|                               "bpp", G_TYPE_INT, 32, | ||||
|                               "depth", G_TYPE_INT, 24, | ||||
|                               "framerate", GST_TYPE_FRACTION, pipeline->recorder->framerate, 1, | ||||
|                               "width", G_TYPE_INT, pipeline->recorder->stage_width, | ||||
|                               "height", G_TYPE_INT, pipeline->recorder->stage_height, | ||||
|                               "width", G_TYPE_INT, pipeline->recorder->area.width, | ||||
|                               "height", G_TYPE_INT, pipeline->recorder->area.height, | ||||
|                               NULL); | ||||
|   g_object_set (pipeline->src, "caps", caps, NULL); | ||||
|   gst_caps_unref (caps); | ||||
| @@ -1678,6 +1730,15 @@ shell_recorder_set_file_template (ShellRecorder *recorder, | ||||
|  | ||||
| } | ||||
|  | ||||
| void | ||||
| shell_recorder_set_draw_cursor (ShellRecorder *recorder, | ||||
|                                 gboolean       draw_cursor) | ||||
| { | ||||
|   g_return_if_fail (SHELL_IS_RECORDER (recorder)); | ||||
|  | ||||
|   recorder_set_draw_cursor (recorder, draw_cursor); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * shell_recorder_set_pipeline: | ||||
|  * @recorder: the #ShellRecorder | ||||
| @@ -1705,9 +1766,35 @@ shell_recorder_set_pipeline (ShellRecorder *recorder, | ||||
|   recorder_set_pipeline (recorder, pipeline); | ||||
| } | ||||
|  | ||||
| void | ||||
| shell_recorder_set_area (ShellRecorder *recorder, | ||||
|                          int            x, | ||||
|                          int            y, | ||||
|                          int            width, | ||||
|                          int            height) | ||||
| { | ||||
|   g_return_if_fail (SHELL_IS_RECORDER (recorder)); | ||||
|  | ||||
|   recorder->custom_area = TRUE; | ||||
|   recorder->area.x = CLAMP (x, 0, recorder->stage_width); | ||||
|   recorder->area.y = CLAMP (y, 0, recorder->stage_height); | ||||
|   recorder->area.width = CLAMP (width, | ||||
|                                 0, recorder->stage_width - recorder->area.x); | ||||
|   recorder->area.height = CLAMP (height, | ||||
|                                  0, recorder->stage_height - recorder->area.y); | ||||
|  | ||||
|   /* This breaks the recording but tweaking the GStreamer pipeline a bit | ||||
|    * might make it work, at least if the codec can handle a stream where | ||||
|    * the frame size changes in the middle. | ||||
|    */ | ||||
|   if (recorder->current_pipeline) | ||||
|     recorder_pipeline_set_caps (recorder->current_pipeline); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * shell_recorder_record: | ||||
|  * @recorder: the #ShellRecorder | ||||
|  * @filename_used: (out) (allow-none): actual filename used for recording | ||||
|  * | ||||
|  * Starts recording, Starting the recording may fail if the output file | ||||
|  * cannot be opened, or if the output stream cannot be created | ||||
| @@ -1724,7 +1811,8 @@ shell_recorder_set_pipeline (ShellRecorder *recorder, | ||||
|  * Return value: %TRUE if recording was succesfully started | ||||
|  */ | ||||
| gboolean | ||||
| shell_recorder_record (ShellRecorder *recorder) | ||||
| shell_recorder_record (ShellRecorder  *recorder, | ||||
|                        char          **filename_used) | ||||
| { | ||||
|   g_return_val_if_fail (SHELL_IS_RECORDER (recorder), FALSE); | ||||
|   g_return_val_if_fail (recorder->stage != NULL, FALSE); | ||||
| @@ -1733,6 +1821,9 @@ shell_recorder_record (ShellRecorder *recorder) | ||||
|   if (!recorder_open_pipeline (recorder)) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (filename_used) | ||||
|     *filename_used = g_strdup (recorder->current_pipeline->filename); | ||||
|  | ||||
|   recorder_connect_stage_callbacks (recorder); | ||||
|  | ||||
|   recorder->start_time = get_wall_time(); | ||||
|   | ||||
| @@ -36,7 +36,15 @@ void               shell_recorder_set_file_template (ShellRecorder *recorder, | ||||
|                                                      const char    *file_template); | ||||
| void               shell_recorder_set_pipeline (ShellRecorder *recorder, | ||||
| 						const char    *pipeline); | ||||
| gboolean           shell_recorder_record       (ShellRecorder *recorder); | ||||
| void               shell_recorder_set_draw_cursor (ShellRecorder *recorder, | ||||
|                                                    gboolean       draw_cursor); | ||||
| void               shell_recorder_set_area     (ShellRecorder *recorder, | ||||
|                                                 int            x, | ||||
|                                                 int            y, | ||||
|                                                 int            width, | ||||
|                                                 int            height); | ||||
| gboolean           shell_recorder_record       (ShellRecorder  *recorder, | ||||
|                                                 char          **filename_used); | ||||
| void               shell_recorder_close        (ShellRecorder *recorder); | ||||
| void               shell_recorder_pause        (ShellRecorder *recorder); | ||||
| gboolean           shell_recorder_is_recording (ShellRecorder *recorder); | ||||
|   | ||||
| @@ -15,6 +15,9 @@ | ||||
| #include "shell-global.h" | ||||
| #include "shell-screenshot.h" | ||||
|  | ||||
| #define A11Y_APPS_SCHEMA "org.gnome.desktop.a11y.applications" | ||||
| #define MAGNIFIER_ACTIVE_KEY "screen-magnifier-enabled" | ||||
|  | ||||
| struct _ShellScreenshotClass | ||||
| { | ||||
|   GObjectClass parent_class; | ||||
| @@ -304,6 +307,7 @@ grab_screenshot (ClutterActor *stage, | ||||
|   MetaScreen *screen = shell_global_get_screen (screenshot_data->screenshot->global); | ||||
|   int width, height; | ||||
|   GSimpleAsyncResult *result; | ||||
|   GSettings *settings; | ||||
|  | ||||
|   meta_screen_get_size (screen, &width, &height); | ||||
|  | ||||
| @@ -352,8 +356,11 @@ grab_screenshot (ClutterActor *stage, | ||||
|   screenshot_data->screenshot_area.width = width; | ||||
|   screenshot_data->screenshot_area.height = height; | ||||
|  | ||||
|   if (screenshot_data->include_cursor) | ||||
|   settings = g_settings_new (A11Y_APPS_SCHEMA); | ||||
|   if (screenshot_data->include_cursor && | ||||
|       !g_settings_get_boolean (settings, MAGNIFIER_ACTIVE_KEY)) | ||||
|     _draw_cursor_image (screenshot_data->image, screenshot_data->screenshot_area); | ||||
|   g_object_unref (settings); | ||||
|  | ||||
|   g_signal_handlers_disconnect_by_func (stage, (void *)grab_screenshot, (gpointer)screenshot_data); | ||||
|  | ||||
| @@ -476,6 +483,7 @@ shell_screenshot_screenshot_window (ShellScreenshot *screenshot, | ||||
|                                     ShellScreenshotCallback callback) | ||||
| { | ||||
|   GSimpleAsyncResult *result; | ||||
|   GSettings *settings; | ||||
|  | ||||
|   _screenshot_data *screenshot_data = g_new0 (_screenshot_data, 1); | ||||
|  | ||||
| @@ -492,6 +500,17 @@ shell_screenshot_screenshot_window (ShellScreenshot *screenshot, | ||||
|   screenshot_data->filename = g_strdup (filename); | ||||
|   screenshot_data->callback = callback; | ||||
|  | ||||
|   if (!window) | ||||
|     { | ||||
|       screenshot_data->filename_used = g_strdup (""); | ||||
|       result = g_simple_async_result_new (NULL, on_screenshot_written, (gpointer)screenshot_data, shell_screenshot_screenshot_window); | ||||
|       g_simple_async_result_set_op_res_gboolean (result, FALSE); | ||||
|       g_simple_async_result_complete (result); | ||||
|       g_object_unref (result); | ||||
|  | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window)); | ||||
|   clutter_actor_get_position (window_actor, &actor_x, &actor_y); | ||||
|  | ||||
| @@ -522,8 +541,10 @@ shell_screenshot_screenshot_window (ShellScreenshot *screenshot, | ||||
|   stex = META_SHAPED_TEXTURE (meta_window_actor_get_texture (META_WINDOW_ACTOR (window_actor))); | ||||
|   screenshot_data->image = meta_shaped_texture_get_image (stex, &clip); | ||||
|  | ||||
|   if (include_cursor) | ||||
|   settings = g_settings_new (A11Y_APPS_SCHEMA); | ||||
|   if (include_cursor && !g_settings_get_boolean (settings, MAGNIFIER_ACTIVE_KEY)) | ||||
|     _draw_cursor_image (screenshot_data->image, screenshot_data->screenshot_area); | ||||
|   g_object_unref (settings); | ||||
|  | ||||
|   result = g_simple_async_result_new (NULL, on_screenshot_written, (gpointer)screenshot_data, shell_screenshot_screenshot_window); | ||||
|   g_simple_async_result_run_in_thread (result, write_screenshot_thread, G_PRIORITY_DEFAULT, NULL); | ||||
|   | ||||
| @@ -82,6 +82,8 @@ enum | ||||
|   PROP_CLUTTER_TEXT, | ||||
|   PROP_HINT_TEXT, | ||||
|   PROP_TEXT, | ||||
|   PROP_INPUT_PURPOSE, | ||||
|   PROP_INPUT_HINTS, | ||||
| }; | ||||
|  | ||||
| /* signals */ | ||||
| @@ -136,6 +138,14 @@ st_entry_set_property (GObject      *gobject, | ||||
|       st_entry_set_text (entry, g_value_get_string (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_INPUT_PURPOSE: | ||||
|       st_entry_set_input_purpose (entry, g_value_get_enum (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_INPUT_HINTS: | ||||
|       st_entry_set_input_hints (entry, g_value_get_flags (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
| @@ -164,6 +174,14 @@ st_entry_get_property (GObject    *gobject, | ||||
|       g_value_set_string (value, clutter_text_get_text (CLUTTER_TEXT (priv->entry))); | ||||
|       break; | ||||
|  | ||||
|     case PROP_INPUT_PURPOSE: | ||||
|       g_value_set_enum (value, st_im_text_get_input_purpose (ST_IM_TEXT (priv->entry))); | ||||
|       break; | ||||
|  | ||||
|     case PROP_INPUT_HINTS: | ||||
|       g_value_set_flags (value, st_im_text_get_input_hints (ST_IM_TEXT (priv->entry))); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
| @@ -759,6 +777,26 @@ st_entry_class_init (StEntryClass *klass) | ||||
|                                NULL, G_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_TEXT, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_enum ("input-purpose", | ||||
|                              "Purpose", | ||||
|                              "Purpose of the text field", | ||||
|                              GTK_TYPE_INPUT_PURPOSE, | ||||
|                              GTK_INPUT_PURPOSE_FREE_FORM, | ||||
|                              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_INPUT_PURPOSE, | ||||
|                                    pspec); | ||||
|  | ||||
|   pspec = g_param_spec_flags ("input-hints", | ||||
|                               "hints", | ||||
|                               "Hints for the text field behaviour", | ||||
|                               GTK_TYPE_INPUT_HINTS, | ||||
|                               GTK_INPUT_HINT_NONE, | ||||
|                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_INPUT_HINTS, | ||||
|                                    pspec); | ||||
|  | ||||
|   /* signals */ | ||||
|   /** | ||||
|    * StEntry::primary-icon-clicked: | ||||
| @@ -966,6 +1004,87 @@ st_entry_get_hint_text (StEntry *entry) | ||||
|   return entry->priv->hint; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_entry_set_input_purpose: | ||||
|  * @entry: a #StEntry | ||||
|  * @purpose: the purpose | ||||
|  * | ||||
|  * Sets the #StEntry:input-purpose property which | ||||
|  * can be used by on-screen keyboards and other input | ||||
|  * methods to adjust their behaviour. | ||||
|  */ | ||||
| void | ||||
| st_entry_set_input_purpose (StEntry        *entry, | ||||
|                             GtkInputPurpose purpose) | ||||
| { | ||||
|   StIMText *imtext; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_ENTRY (entry)); | ||||
|  | ||||
|   imtext = ST_IM_TEXT (entry->priv->entry); | ||||
|  | ||||
|   if (st_im_text_get_input_purpose (imtext) != purpose) | ||||
|     { | ||||
|       st_im_text_set_input_purpose (imtext, purpose); | ||||
|  | ||||
|       g_object_notify (G_OBJECT (entry), "input-purpose"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_entry_get_input_purpose: | ||||
|  * @entry: a #StEntry | ||||
|  * | ||||
|  * Gets the value of the #StEntry:input-purpose property. | ||||
|  */ | ||||
| GtkInputPurpose | ||||
| st_entry_get_input_purpose (StEntry *entry) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_ENTRY (entry), GTK_INPUT_PURPOSE_FREE_FORM); | ||||
|  | ||||
|   return st_im_text_get_input_purpose (ST_IM_TEXT (entry->priv->entry)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_entry_set_input_hints: | ||||
|  * @entry: a #StEntry | ||||
|  * @hints: the hints | ||||
|  * | ||||
|  * Sets the #StEntry:input-hints property, which | ||||
|  * allows input methods to fine-tune their behaviour. | ||||
|  */ | ||||
| void | ||||
| st_entry_set_input_hints (StEntry      *entry, | ||||
|                           GtkInputHints hints) | ||||
| { | ||||
|   StIMText *imtext; | ||||
|  | ||||
|   g_return_if_fail (ST_IS_ENTRY (entry)); | ||||
|  | ||||
|   imtext = ST_IM_TEXT (entry->priv->entry); | ||||
|  | ||||
|   if (st_im_text_get_input_hints (imtext) != hints) | ||||
|     { | ||||
|       st_im_text_set_input_hints (imtext, hints); | ||||
|  | ||||
|       g_object_notify (G_OBJECT (entry), "input-hints"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_entry_get_input_hints: | ||||
|  * @entry: a #StEntry | ||||
|  * | ||||
|  * Gets the value of the #StEntry:input-hints property. | ||||
|  */ | ||||
| GtkInputHints | ||||
| st_entry_get_input_hints (StEntry *entry) | ||||
| { | ||||
|   g_return_val_if_fail (ST_IS_ENTRY (entry), GTK_INPUT_HINT_NONE); | ||||
|  | ||||
|   return st_im_text_get_input_hints (ST_IM_TEXT (entry->priv->entry)); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| _st_entry_icon_press_cb (ClutterActor       *actor, | ||||
|                          ClutterButtonEvent *event, | ||||
|   | ||||
| @@ -64,20 +64,27 @@ struct _StEntryClass | ||||
|  | ||||
| GType st_entry_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| StWidget *            st_entry_new              (const gchar *text); | ||||
| const gchar *         st_entry_get_text         (StEntry     *entry); | ||||
| void                  st_entry_set_text         (StEntry     *entry, | ||||
|                                                  const gchar *text); | ||||
| ClutterActor*         st_entry_get_clutter_text (StEntry     *entry); | ||||
| StWidget       *st_entry_new                (const gchar    *text); | ||||
| const gchar    *st_entry_get_text           (StEntry        *entry); | ||||
| void            st_entry_set_text           (StEntry        *entry, | ||||
|                                              const gchar    *text); | ||||
| ClutterActor   *st_entry_get_clutter_text   (StEntry        *entry); | ||||
|  | ||||
| void                  st_entry_set_hint_text    (StEntry     *entry, | ||||
|                                                  const gchar *text); | ||||
| const gchar *         st_entry_get_hint_text    (StEntry     *entry); | ||||
| void            st_entry_set_hint_text      (StEntry        *entry, | ||||
|                                              const gchar    *text); | ||||
| const gchar    *st_entry_get_hint_text      (StEntry        *entry); | ||||
|  | ||||
| void st_entry_set_primary_icon             (StEntry      *entry, | ||||
|                                             ClutterActor *icon); | ||||
| void st_entry_set_secondary_icon           (StEntry      *entry, | ||||
|                                             ClutterActor *icon); | ||||
| void            st_entry_set_input_purpose  (StEntry        *entry, | ||||
|                                              GtkInputPurpose purpose); | ||||
| GtkInputPurpose st_entry_get_input_purpose  (StEntry        *entry); | ||||
| void            st_entry_set_input_hints    (StEntry        *entry, | ||||
|                                              GtkInputHints   hints); | ||||
| GtkInputHints   st_entry_get_input_hints    (StEntry        *entry); | ||||
|  | ||||
| void            st_entry_set_primary_icon   (StEntry        *entry, | ||||
|                                              ClutterActor   *icon); | ||||
| void            st_entry_set_secondary_icon (StEntry        *entry, | ||||
|                                              ClutterActor   *icon); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
|   | ||||
| @@ -249,11 +249,6 @@ st_icon_paint (ClutterActor *actor) | ||||
|           clutter_actor_get_allocation_box (priv->icon_texture, &allocation); | ||||
|           clutter_actor_box_get_size (&allocation, &width, &height); | ||||
|  | ||||
|           allocation.x1 = (width - priv->shadow_width) / 2; | ||||
|           allocation.y1 = (height - priv->shadow_height) / 2; | ||||
|           allocation.x2 = allocation.x1 + priv->shadow_width; | ||||
|           allocation.y2 = allocation.y1 + priv->shadow_height; | ||||
|  | ||||
|           _st_paint_shadow_with_opacity (priv->shadow_spec, | ||||
|                                          priv->shadow_material, | ||||
|                                          &allocation, | ||||
| @@ -410,8 +405,8 @@ st_icon_finish_update (StIcon *icon) | ||||
|       st_icon_update_shadow_material (icon); | ||||
|  | ||||
|       /* "pixbuf-change" is actually a misnomer for "texture-changed" */ | ||||
|       g_signal_connect (priv->icon_texture, "pixbuf-change", | ||||
|                         G_CALLBACK (on_pixbuf_changed), icon); | ||||
|       g_signal_connect_object (priv->icon_texture, "pixbuf-change", | ||||
|                                G_CALLBACK (on_pixbuf_changed), icon, 0); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -469,7 +464,7 @@ st_icon_update (StIcon *icon) | ||||
|       else | ||||
|         { | ||||
|           /* Will be shown when fully loaded */ | ||||
|           priv->opacity_handler_id = g_signal_connect (priv->pending_texture, "notify::opacity", G_CALLBACK (opacity_changed_cb), icon); | ||||
|           priv->opacity_handler_id = g_signal_connect_object (priv->pending_texture, "notify::opacity", G_CALLBACK (opacity_changed_cb), icon, 0); | ||||
|         } | ||||
|     } | ||||
|   else if (priv->icon_texture) | ||||
| @@ -544,7 +539,8 @@ st_icon_set_icon_name (StIcon      *icon, | ||||
|  | ||||
|   if (g_icon_equal (priv->gicon, gicon)) /* do nothing */ | ||||
|     { | ||||
|       g_object_unref (gicon); | ||||
|       if (gicon) | ||||
|         g_object_unref (gicon); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -50,6 +50,15 @@ | ||||
|  | ||||
| #include "st-im-text.h" | ||||
|  | ||||
| /* properties */ | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_INPUT_PURPOSE, | ||||
|   PROP_INPUT_HINTS, | ||||
| }; | ||||
|  | ||||
| #define ST_IM_TEXT_GET_PRIVATE(obj)    \ | ||||
|         (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_IM_TEXT, StIMTextPrivate)) | ||||
|  | ||||
| @@ -404,16 +413,67 @@ st_im_text_key_focus_out (ClutterActor *actor) | ||||
|     CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->key_focus_out (actor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_im_text_set_property (GObject      *gobject, | ||||
|                          guint         prop_id, | ||||
|                          const GValue *value, | ||||
|                          GParamSpec   *pspec) | ||||
| { | ||||
|   StIMText *imtext = ST_IM_TEXT (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_INPUT_PURPOSE: | ||||
|       st_im_text_set_input_purpose (imtext, g_value_get_enum (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_INPUT_HINTS: | ||||
|       st_im_text_set_input_hints (imtext, g_value_get_flags (value)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_im_text_get_property (GObject    *gobject, | ||||
|                          guint       prop_id, | ||||
|                          GValue     *value, | ||||
|                          GParamSpec *pspec) | ||||
| { | ||||
|   StIMText *imtext = ST_IM_TEXT (gobject); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_INPUT_PURPOSE: | ||||
|       g_value_set_enum (value, st_im_text_get_input_purpose (imtext)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_INPUT_HINTS: | ||||
|       g_value_set_flags (value, st_im_text_get_input_hints (imtext)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| st_im_text_class_init (StIMTextClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   ClutterTextClass *text_class = CLUTTER_TEXT_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (StIMTextPrivate)); | ||||
|  | ||||
|   object_class->dispose = st_im_text_dispose; | ||||
|   object_class->set_property = st_im_text_set_property; | ||||
|   object_class->get_property = st_im_text_get_property; | ||||
|  | ||||
|   actor_class->get_paint_volume = st_im_text_get_paint_volume; | ||||
|   actor_class->realize = st_im_text_realize; | ||||
| @@ -425,6 +485,26 @@ st_im_text_class_init (StIMTextClass *klass) | ||||
|   actor_class->key_focus_out = st_im_text_key_focus_out; | ||||
|  | ||||
|   text_class->cursor_event = st_im_text_cursor_event; | ||||
|  | ||||
|   pspec = g_param_spec_enum ("input-purpose", | ||||
|                              "Purpose", | ||||
|                              "Purpose of the text field", | ||||
|                              GTK_TYPE_INPUT_PURPOSE, | ||||
|                              GTK_INPUT_PURPOSE_FREE_FORM, | ||||
|                              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_INPUT_PURPOSE, | ||||
|                                    pspec); | ||||
|  | ||||
|   pspec = g_param_spec_flags ("input-hints", | ||||
|                               "hints", | ||||
|                               "Hints for the text field behaviour", | ||||
|                               GTK_TYPE_INPUT_HINTS, | ||||
|                               GTK_INPUT_HINT_NONE, | ||||
|                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); | ||||
|   g_object_class_install_property (object_class, | ||||
|                                    PROP_INPUT_HINTS, | ||||
|                                    pspec); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -460,3 +540,96 @@ st_im_text_new (const gchar *text) | ||||
|                        "text", text, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_im_text_set_input_purpose: | ||||
|  * @imtext: a #StIMText | ||||
|  * @purpose: the purpose | ||||
|  * | ||||
|  * Sets the #StIMText:input-purpose property which | ||||
|  * can be used by on-screen keyboards and other input | ||||
|  * methods to adjust their behaviour. | ||||
|  */ | ||||
| void | ||||
| st_im_text_set_input_purpose (StIMText       *imtext, | ||||
|                               GtkInputPurpose purpose) | ||||
| { | ||||
|   g_return_if_fail (ST_IS_IM_TEXT (imtext)); | ||||
|  | ||||
|   if (st_im_text_get_input_purpose (imtext) != purpose) | ||||
|     { | ||||
|       g_object_set (G_OBJECT (imtext->priv->im_context), | ||||
|                     "input-purpose", purpose, | ||||
|                     NULL); | ||||
|  | ||||
|       g_object_get (G_OBJECT (imtext->priv->im_context), | ||||
|                     "input-purpose", &purpose, | ||||
|                     NULL); | ||||
|  | ||||
|       g_object_notify (G_OBJECT (imtext), "input-purpose"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_im_text_get_input_purpose: | ||||
|  * @imtext: a #StIMText | ||||
|  * | ||||
|  * Gets the value of the #StIMText:input-purpose property. | ||||
|  */ | ||||
| GtkInputPurpose | ||||
| st_im_text_get_input_purpose (StIMText *imtext) | ||||
| { | ||||
|   GtkInputPurpose purpose; | ||||
|  | ||||
|   g_return_val_if_fail (ST_IS_IM_TEXT (imtext), GTK_INPUT_PURPOSE_FREE_FORM); | ||||
|  | ||||
|   g_object_get (G_OBJECT (imtext->priv->im_context), | ||||
|                 "input-purpose", &purpose, | ||||
|                 NULL); | ||||
|  | ||||
|   return purpose; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_im_text_set_input_hints: | ||||
|  * @imtext: a #StIMText | ||||
|  * @hints: the hints | ||||
|  * | ||||
|  * Sets the #StIMText:input-hints property, which | ||||
|  * allows input methods to fine-tune their behaviour. | ||||
|  */ | ||||
| void | ||||
| st_im_text_set_input_hints (StIMText     *imtext, | ||||
|                             GtkInputHints hints) | ||||
| { | ||||
|   g_return_if_fail (ST_IS_IM_TEXT (imtext)); | ||||
|  | ||||
|   if (st_im_text_get_input_hints (imtext) != hints) | ||||
|     { | ||||
|       g_object_set (G_OBJECT (imtext->priv->im_context), | ||||
|                     "input-hints", hints, | ||||
|                     NULL); | ||||
|  | ||||
|       g_object_notify (G_OBJECT (imtext), "input-hints"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * st_im_text_get_input_hints: | ||||
|  * @imtext: a #StIMText | ||||
|  * | ||||
|  * Gets the value of the #StIMText:input-hints property. | ||||
|  */ | ||||
| GtkInputHints | ||||
| st_im_text_get_input_hints (StIMText *imtext) | ||||
| { | ||||
|   GtkInputHints hints; | ||||
|  | ||||
|   g_return_val_if_fail (ST_IS_IM_TEXT (imtext), GTK_INPUT_HINT_NONE); | ||||
|  | ||||
|   g_object_get (G_OBJECT (imtext->priv->im_context), | ||||
|                 "input-hints", &hints, | ||||
|                 NULL); | ||||
|  | ||||
|   return hints; | ||||
| } | ||||
|   | ||||
| @@ -60,9 +60,13 @@ struct _StIMTextClass | ||||
|  | ||||
| GType st_im_text_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| ClutterActor *st_im_text_new             (const gchar *text); | ||||
| void          st_im_text_set_autoshow_im (StIMText    *self, | ||||
|                                           gboolean     autoshow); | ||||
| ClutterActor   *st_im_text_new               (const gchar    *text); | ||||
| void            st_im_text_set_input_purpose (StIMText       *imtext, | ||||
|                                               GtkInputPurpose purpose); | ||||
| GtkInputPurpose st_im_text_get_input_purpose (StIMText       *imtext); | ||||
| void            st_im_text_set_input_hints   (StIMText       *imtext, | ||||
|                                               GtkInputHints   hints); | ||||
| GtkInputHints   st_im_text_get_input_hints   (StIMText       *imtext); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
|   | ||||
| @@ -218,10 +218,6 @@ st_label_paint (ClutterActor *actor) | ||||
|       clutter_actor_get_allocation_box (priv->label, &allocation); | ||||
|       clutter_actor_box_get_size (&allocation, &width, &height); | ||||
|  | ||||
|       allocation.x1 = allocation.y1 = 0; | ||||
|       allocation.x2 = width; | ||||
|       allocation.y2 = height; | ||||
|  | ||||
|       if (priv->text_shadow_material == COGL_INVALID_HANDLE || | ||||
|           width != priv->shadow_width || | ||||
|           height != priv->shadow_height) | ||||
|   | ||||
| @@ -511,6 +511,7 @@ _st_create_shadow_material_from_actor (StShadow     *shadow_spec, | ||||
|       cogl_color_set_from_4ub (&clear_color, 0, 0, 0, 0); | ||||
|       cogl_push_framebuffer (offscreen); | ||||
|       cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR); | ||||
|       cogl_translate (-box.x1, -box.y1, 0); | ||||
|       cogl_ortho (0, width, height, 0, 0, 1.0); | ||||
|       clutter_actor_paint (actor); | ||||
|       cogl_pop_framebuffer (); | ||||
|   | ||||
| @@ -598,42 +598,36 @@ st_scroll_view_allocate (ClutterActor          *actor, | ||||
|    */ | ||||
|  | ||||
|   /* Vertical scrollbar */ | ||||
|   if (CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll)) | ||||
|     { | ||||
|       if (clutter_actor_get_text_direction (actor) == CLUTTER_TEXT_DIRECTION_RTL) | ||||
|         { | ||||
|           child_box.x1 = content_box.x1; | ||||
|           child_box.x2 = content_box.x1 + sb_width; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           child_box.x1 = content_box.x2 - sb_width; | ||||
|           child_box.x2 = content_box.x2; | ||||
|         } | ||||
|       child_box.y1 = content_box.y1; | ||||
|       child_box.y2 = content_box.y2 - (hscrollbar_visible ? sb_height : 0); | ||||
|     if (clutter_actor_get_text_direction (actor) == CLUTTER_TEXT_DIRECTION_RTL) | ||||
|       { | ||||
|         child_box.x1 = content_box.x1; | ||||
|         child_box.x2 = content_box.x1 + sb_width; | ||||
|       } | ||||
|     else | ||||
|       { | ||||
|         child_box.x1 = content_box.x2 - sb_width; | ||||
|         child_box.x2 = content_box.x2; | ||||
|       } | ||||
|     child_box.y1 = content_box.y1; | ||||
|     child_box.y2 = content_box.y2 - (hscrollbar_visible ? sb_height : 0); | ||||
|  | ||||
|       clutter_actor_allocate (priv->vscroll, &child_box, flags); | ||||
|     } | ||||
|     clutter_actor_allocate (priv->vscroll, &child_box, flags); | ||||
|  | ||||
|   /* Horizontal scrollbar */ | ||||
|   if (CLUTTER_ACTOR_IS_VISIBLE (priv->hscroll)) | ||||
|     { | ||||
|       if (clutter_actor_get_text_direction (actor) == CLUTTER_TEXT_DIRECTION_RTL) | ||||
|         { | ||||
|           child_box.x1 = content_box.x1 + (vscrollbar_visible ? sb_width : 0); | ||||
|           child_box.x2 = content_box.x2; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           child_box.x1 = content_box.x1; | ||||
|           child_box.x2 = content_box.x2 - (vscrollbar_visible ? sb_width : 0); | ||||
|         } | ||||
|       child_box.y1 = content_box.y2 - sb_height; | ||||
|       child_box.y2 = content_box.y2; | ||||
|     if (clutter_actor_get_text_direction (actor) == CLUTTER_TEXT_DIRECTION_RTL) | ||||
|       { | ||||
|         child_box.x1 = content_box.x1 + (vscrollbar_visible ? sb_width : 0); | ||||
|         child_box.x2 = content_box.x2; | ||||
|       } | ||||
|     else | ||||
|       { | ||||
|         child_box.x1 = content_box.x1; | ||||
|         child_box.x2 = content_box.x2 - (vscrollbar_visible ? sb_width : 0); | ||||
|       } | ||||
|     child_box.y1 = content_box.y2 - sb_height; | ||||
|     child_box.y2 = content_box.y2; | ||||
|  | ||||
|       clutter_actor_allocate (priv->hscroll, &child_box, flags); | ||||
|     } | ||||
|     clutter_actor_allocate (priv->hscroll, &child_box, flags); | ||||
|  | ||||
|   /* In case the scrollbar policy is NEVER or scrollbars should be | ||||
|    * overlayed, we don't trim the content box allocation by the | ||||
|   | ||||
| @@ -292,11 +292,6 @@ st_shadow_helper_paint (StShadowHelper  *helper, | ||||
|  | ||||
|   clutter_actor_box_get_size (actor_box, &width, &height); | ||||
|  | ||||
|   allocation.x1 = (width - helper->width) / 2; | ||||
|   allocation.y1 = (height - helper->height) / 2; | ||||
|   allocation.x2 = allocation.x1 + helper->width; | ||||
|   allocation.y2 = allocation.y1 + helper->height; | ||||
|  | ||||
|   _st_paint_shadow_with_opacity (helper->shadow, | ||||
|                                  helper->material, | ||||
|                                  &allocation, | ||||
|   | ||||
| @@ -608,8 +608,9 @@ st_widget_get_theme_node (StWidget *widget) | ||||
|  | ||||
|       if (stage == NULL) | ||||
|         { | ||||
|           g_error ("st_widget_get_theme_node called on the widget %s which is not in the stage.", | ||||
|                     st_describe_actor (CLUTTER_ACTOR (widget))); | ||||
|           g_critical ("st_widget_get_theme_node called on the widget %s which is not in the stage.", | ||||
|                       st_describe_actor (CLUTTER_ACTOR (widget))); | ||||
|           return g_object_new (ST_TYPE_THEME_NODE, NULL); | ||||
|         } | ||||
|  | ||||
|       if (parent_node == NULL) | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user