Compare commits

..

6 Commits

Author SHA1 Message Date
352ad8f558 Modal stack: fix handling of destroyed actors
Destroyed modal actors should be completely removed from the modal
stack automatically, including leaving modality if needed.
This allows for destroying modal dialogs without calling close().
2012-05-21 18:47:47 +02:00
d5dc886748 ScreenShield: improve locking/modal policy
Ensure that the lightbox is above everything (including the screenlock
itself) when fading in - this allows for fading while showing the
unlock dialog. Also, don't pushModal again when already locked, or
we won't get out of it.
2012-05-21 18:47:47 +02:00
17044adf96 Add UnlockDialog for unlocking the screen shield
When the screenshield is deactivated, instead of going back to the
session immediately, prompt the user for authentication.
This essentially reinstates what used to be provided by gnome-screensaver.
2012-05-21 18:47:44 +02:00
9dfd805be2 lightbox: make sure this.shown set to false when start showing 2012-05-21 18:47:44 +02:00
bbbb6b685f screenShield: add initial functionality
We are replacing the gnome-screensaver module with with a screen shield
that is part of gnome-shell.

This patch fades out the screen on idle and shows a shield with a background
image when there is activity again. The shield can be removed with a key or
button press.
2012-05-21 18:47:40 +02:00
71c0d5f82d Login dialog: update for GDM port to GDBus
libgdmgreeter changed interface slightly due to the port to GDBus.
Update for that.

https://bugzilla.gnome.org/show_bug.cgi?id=676401
2012-05-20 17:16:17 +02:00
61 changed files with 2835 additions and 2381 deletions

71
NEWS
View File

@ -1,74 +1,3 @@
3.5.2
=====
* main: Move 'toggle-recording' binding into the shell [Florian; #674377]
* popupMenu: make sure to break the grab when the slider is not visible
[Stefano; #672713]
* st-theme-node-drawing: Don't use GL types [Neil; #672711]
* Mirror Evolution calendar settings into our own schema [Owen; #674424]
* shell-network-agent: don't crash if a request isn't found [Dan; #674961]
* notificationDaemon: Match app based on WM_CLASS [Jasper; #673761]
* NetworkMenu: use network-offline while loading [Giovanni; #674426]
* lookingGlass: Remove the Errors tab [Jasper; #675104]
* searchDisplay: Reset keyboard focus after displaying async results
[Rui; #675078]
* gdm: don't fail if fprintd is unavailable [Ray; #675006]
* messageTray: Fix scrolling up [Jasper; #661615]
* main: Close the recorder instead of pausing it [Rui; #675128]
* Accessibility [Alejandro]
- Use the proper label_actor for date menu on top panel [#675307]
- Set the proper role/label_actor for SearchResult.content [#672242]
- do not expose a label text if 'hidden' style class is used [#675341]
* Magnifier: Add brightness and contrast functionality [Joseph; #639851]
* theme: use a smaller border-radius for top bar [Jakub; #672430]
* placeDisplay: use new bookmark file location [Matthias; #675443]
* port all synchronous search providers to the async API [Jasper, Rui; #675328]
* NetworkAgent: disallow multiple requests for the same connection/setting
[Giovanni; #674961]
* userMenu: Update to latest mockups [Florian; #675802]
* util: Don't double-fork when spawning from Alt-F2 [Colin; #675789]
* messageTray: Make Source usable without subclassing [Jasper; #661236]
* panel: Check for appMenu button's reactivity before opening [Florian; #676316]
* Fix formatting of bluetooth passkey [Florian; #651251]
* notificationDaemon: Filter out file-transfer notifications [Jasper; #676175]
* Don't use global.log() [Jasper; #675790]
* Fix broken extension loading in some distributions [Owen, Alexandre; #670477]
* shell-app: Raise windows in reverse order to preserve the stacking
[Rui; #676371]
* Generalize gdm-mode [Florian; #676156]
* Switch string formatting to the one inside gjs [Jasper; #675479]
* extensionUtils: Support subdirectories in getCurrentExtension
[Jasper; #677001]
* panel: Refuse to add (legacy) status icons not part of the session mode
[Florian; #677058]
* Add an initial-setup mode [Matthias; #676697]
* status/keyboard: Port to the new input sources settings [Rui; #641531]
* NetworkMenu: show notifications for failed VPN connections [Giovanni; #676330]
* userMenu: Indicate progress on status changes [Florian; #659067]
* recorder: Honor "disable-save-to-disk" lockdown key [Rūdolfs; #673630]
* searchDisplay: Use the rowLimit we pass to the IconGrid [Christian; #675527]
* endSessionDialog: Factor out _updateDescription from _updateContent
[Alejandro; #674210]
* Fix empathy's appMenu freezing the shell [Alban; #676447]
* Code cleanups [Florian, Giovanni, Jasper; #672807, #672413, #676837, #676850,
#672272]
* Misc bug fixes [Alban, Florian, Giovanni, Guillaume, Jasper, Piotr, Rico,
Ron, Rui, Stefano; #659968, #672192, #673177, #673198, #674323, #675301,
#675370, #676347, #676806, #677097]
Contributors:
Alban Browaeys, Giovanni Campagna, Matthias Clasen, Guillaume Desmottes,
Piotr Drąg, Stefano Facchini, Rui Matos, Rūdolfs Mazurs, Florian Müllner,
Alejandro Piñeiro, Neil Roberts, Alexandre Rostovtsev, Joseph Scheuhammer,
Jakub Steiner, Jasper St. Pierre, Ray Strode, Owen Taylor, Rico Tzschichholz,
Colin Walters, Dan Winship, Ron Yorston
Translations:
OKANO Takayoshi [ja], Daniel Mustieles [es], Changwoo Ryu [ko],
Yaron Shahrabani [he], Fran Diéguez [gl], Jonh Wendell [pt_BR],
Kjartan Maraas [nb], Luca Ferretti [it], Tom Tryfonidis [el],
Sandeep Sheshrao Shedmake [mr], Takanori MATSUURA [ja], Dirgita [id],
Mantas Kriaučiūnas [lt], Matej Urbančič [sl], Jiro Matsuzawa [ja]
3.4.1
=====
* Fix crash that occurred when an icon theme change caused unexpected

View File

@ -41,7 +41,7 @@
"It can be used only by extensions.gnome.org"
#define PLUGIN_MIME_STRING "application/x-gnome-shell-integration::Gnome Shell Integration Dummy Content-Type";
#define PLUGIN_API_VERSION 4
#define PLUGIN_API_VERSION 3
typedef struct {
GDBusProxy *proxy;
@ -163,7 +163,6 @@ NP_Initialize(NPNetscapeFuncs *pfuncs, NPPluginFuncs *plugin)
plugin->newp = NPP_New;
plugin->destroy = NPP_Destroy;
plugin->getvalue = NPP_GetValue;
plugin->setwindow = NPP_SetWindow;
return NPERR_NO_ERROR;
}
@ -268,7 +267,6 @@ typedef struct {
NPObject parent;
NPP instance;
GDBusProxy *proxy;
GSettings *settings;
NPObject *listener;
NPObject *restart_listener;
gint signal_id;
@ -325,9 +323,6 @@ on_shell_appeared (GDBusConnection *connection,
}
}
#define SHELL_SCHEMA "org.gnome.shell"
#define ENABLED_EXTENSIONS_KEY "enabled-extensions"
static NPObject *
plugin_object_allocate (NPP instance,
NPClass *klass)
@ -337,7 +332,6 @@ plugin_object_allocate (NPP instance,
obj->instance = instance;
obj->proxy = g_object_ref (data->proxy);
obj->settings = g_settings_new (SHELL_SCHEMA);
obj->signal_id = g_signal_connect (obj->proxy, "g-signal",
G_CALLBACK (on_shell_signal), obj);
@ -498,61 +492,7 @@ plugin_enable_extension (PluginObject *obj,
NPString uuid,
gboolean enabled)
{
gboolean ret;
gchar *uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
gsize length;
gchar **uuids;
const gchar **new_uuids;
if (!uuid_is_valid (uuid_str))
{
g_free (uuid_str);
return FALSE;
}
uuids = g_settings_get_strv (obj->settings, ENABLED_EXTENSIONS_KEY);
length = g_strv_length (uuids);
if (enabled)
{
new_uuids = g_new (const gchar *, length + 2); /* New key, NULL */
memcpy (new_uuids, uuids, length * sizeof (*new_uuids));
new_uuids[length] = uuid_str;
new_uuids[length + 1] = NULL;
}
else
{
gsize i = 0, j = 0;
new_uuids = g_new (const gchar *, length);
for (i = 0; i < length; i ++)
{
if (g_str_equal (uuids[i], uuid_str))
continue;
new_uuids[j] = uuids[i];
j++;
}
new_uuids[j] = NULL;
}
ret = g_settings_set_strv (obj->settings,
ENABLED_EXTENSIONS_KEY,
new_uuids);
g_strfreev (uuids);
g_free (new_uuids);
g_free (uuid_str);
return ret;
}
static gboolean
plugin_install_extension (PluginObject *obj,
NPString uuid)
{
gchar *uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
if (!uuid_is_valid (uuid_str))
{
g_free (uuid_str);
@ -560,7 +500,7 @@ plugin_install_extension (PluginObject *obj,
}
g_dbus_proxy_call (obj->proxy,
"InstallRemoteExtension",
(enabled ? "EnableExtension" : "DisableExtension"),
g_variant_new ("(s)", uuid_str),
G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */
@ -573,6 +513,40 @@ plugin_install_extension (PluginObject *obj,
return TRUE;
}
static gboolean
plugin_install_extension (PluginObject *obj,
NPString uuid,
NPString version_tag)
{
gchar *uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
gchar *version_tag_str;
if (!uuid_is_valid (uuid_str))
{
g_free (uuid_str);
return FALSE;
}
version_tag_str = g_strndup (version_tag.UTF8Characters,
version_tag.UTF8Length);
g_dbus_proxy_call (obj->proxy,
"InstallRemoteExtension",
g_variant_new ("(ss)",
uuid_str,
version_tag_str),
G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */
NULL, /* cancellable */
NULL, /* callback */
NULL /* user_data */);
g_free (uuid_str);
g_free (version_tag_str);
return TRUE;
}
static gboolean
plugin_uninstall_extension (PluginObject *obj,
NPString uuid,
@ -797,9 +771,11 @@ plugin_object_invoke (NPObject *npobj,
else if (name == install_extension_id)
{
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
if (!NPVARIANT_IS_STRING(args[1])) return FALSE;
return plugin_install_extension (obj,
NPVARIANT_TO_STRING(args[0]));
NPVARIANT_TO_STRING(args[0]),
NPVARIANT_TO_STRING(args[1]));
}
else if (name == uninstall_extension_id)
{
@ -970,12 +946,3 @@ NPP_GetValue(NPP instance,
return NPERR_NO_ERROR;
}
/* Opera tries to call NPP_SetWindow without checking the
* NULL pointer beforehand. */
NPError
NPP_SetWindow(NPP instance,
NPWindow *window)
{
return NPERR_NO_ERROR;
}

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.5.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_INIT([gnome-shell],[3.4.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c])
@ -63,7 +63,7 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.9.16
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.29.18
MUTTER_MIN_VERSION=3.5.2
MUTTER_MIN_VERSION=3.4.1
FOLKS_MIN_VERSION=0.5.2
GTK_MIN_VERSION=3.3.9
GIO_MIN_VERSION=2.31.6
@ -75,7 +75,6 @@ TELEPATHY_LOGGER_MIN_VERSION=0.2.4
POLKIT_MIN_VERSION=0.100
STARTUP_NOTIFICATION_MIN_VERSION=0.11
GCR_MIN_VERSION=3.3.90
GNOME_DESKTOP_REQUIRED_VERSION=3.5.1
# Collect more than 20 libraries for a prize!
PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
@ -96,8 +95,7 @@ PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
telepathy-logger-0.2 >= $TELEPATHY_LOGGER_MIN_VERSION
polkit-agent-1 >= $POLKIT_MIN_VERSION xfixes
libnm-glib libnm-util gnome-keyring-1
gcr-3 >= $GCR_MIN_VERSION
gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION)
gcr-3 >= $GCR_MIN_VERSION)
PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
@ -123,7 +121,7 @@ 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.2 x11)
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.5.1)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 0.1.7)
AC_MSG_CHECKING([for bluetooth support])
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
@ -239,6 +237,31 @@ AC_ARG_ENABLE(jhbuild-wrapper-script,
AS_HELP_STRING([--enable-jhbuild-wrapper-script],[Make "gnome-shell" script work for jhbuild]),,enable_jhbuild_wrapper_script=no)
AM_CONDITIONAL(USE_JHBUILD_WRAPPER_SCRIPT, test "x$enable_jhbuild_wrapper_script" = xyes)
AC_MSG_CHECKING([location of system Certificate Authority list])
AC_ARG_WITH(ca-certificates,
[AC_HELP_STRING([--with-ca-certificates=@<:@path@:>@],
[path to system Certificate Authority list])])
if test "$with_ca_certificates" = "no"; then
AC_MSG_RESULT([disabled])
else
if test -z "$with_ca_certificates"; then
for f in /etc/pki/tls/certs/ca-bundle.crt \
/etc/ssl/certs/ca-certificates.crt; do
if test -f "$f"; then
with_ca_certificates="$f"
fi
done
if test -z "$with_ca_certificates"; then
AC_MSG_ERROR([could not find. Use --with-ca-certificates=path to set, or --without-ca-certificates to disable])
fi
fi
AC_MSG_RESULT($with_ca_certificates)
AC_DEFINE_UNQUOTED(SHELL_SYSTEM_CA_FILE, ["$with_ca_certificates"], [The system TLS CA list])
fi
AC_SUBST(SHELL_SYSTEM_CA_FILE,["$with_ca_certificates"])
BROWSER_PLUGIN_DIR="${BROWSER_PLUGIN_DIR:-"\${libdir}/mozilla/plugins"}"
AC_ARG_VAR([BROWSER_PLUGIN_DIR],[Where to install the plugin to])

View File

@ -1715,7 +1715,7 @@ StScrollBar StButton#vhandle:hover
}
.lightbox {
background-color: rgba(0, 0, 0, 0.4);
background-color: black;
}
.flashspot {
@ -1948,12 +1948,10 @@ StScrollBar StButton#vhandle:hover
padding-bottom: 8px;
}
.hidden {
color: rgba(0,0,0,0);
}
/* intentionally left transparent to avoid dialog changing size */
.prompt-dialog-null-label {
font-size: 10pt;
color: rgba(0,0,0,0);
padding-bottom: 8px;
}

View File

@ -28,6 +28,7 @@ nobase_dist_js_DATA = \
misc/config.js \
misc/extensionUtils.js \
misc/fileUtils.js \
misc/format.js \
misc/gnomeSession.js \
misc/history.js \
misc/jsParse.js \
@ -66,7 +67,6 @@ nobase_dist_js_DATA = \
ui/messageTray.js \
ui/modalDialog.js \
ui/networkAgent.js \
ui/sessionMode.js \
ui/shellEntry.js \
ui/shellMountOperation.js \
ui/notificationDaemon.js \
@ -78,6 +78,7 @@ nobase_dist_js_DATA = \
ui/popupMenu.js \
ui/remoteSearch.js \
ui/runDialog.js \
ui/screenShield.js \
ui/scripting.js \
ui/search.js \
ui/searchDisplay.js \
@ -91,6 +92,7 @@ nobase_dist_js_DATA = \
ui/status/bluetooth.js \
ui/telepathyClient.js \
ui/tweener.js \
ui/unlockDialog.js \
ui/userMenu.js \
ui/viewSelector.js \
ui/wanda.js \

View File

@ -6,11 +6,11 @@ const GObject = imports.gi.GObject;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Pango = imports.gi.Pango;
const Format = imports.format;
const _ = Gettext.gettext;
const Config = imports.misc.config;
const Format = imports.misc.format;
const ExtensionUtils = imports.misc.extensionUtils;
@ -210,7 +210,7 @@ const Application = new Lang.Class({
try {
extension = ExtensionUtils.createExtensionObject(uuid, dir, type);
} catch(e) {
logError(e, 'Could not create extensions object');
global.logError('' + e);
return;
}
@ -257,7 +257,7 @@ function initEnvironment() {
},
logError: function(s) {
log('ERROR: ' + s);
global.log('ERROR: ' + s);
},
userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell'])

View File

@ -39,8 +39,8 @@ const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const Tweener = imports.ui.tweener;
const _PASSWORD_SERVICE_NAME = 'gdm-password';
const _FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
const PASSWORD_SERVICE_NAME = 'gdm-password';
const FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
const _FADE_ANIMATION_TIME = 0.16;
const _RESIZE_ANIMATION_TIME = 0.25;
const _SCROLL_ANIMATION_TIME = 2.0;
@ -747,15 +747,13 @@ const LoginDialog = new Lang.Class({
Lang.bind(this, this._onOpened));
this._userManager = AccountsService.UserManager.get_default()
this._greeterClient = new GdmGreeter.Client();
this._greeterClient = GdmGreeter.Server.new_for_greeter_sync(null);
this._greeterClient.open_connection();
this._greeterClient.call_start_conversation(_PASSWORD_SERVICE_NAME);
this._greeterClient.call_start_conversation_sync(PASSWORD_SERVICE_NAME, null);
this._greeterClient.connect('reset',
Lang.bind(this, this._onReset));
this._greeterClient.connect('default-session-changed',
this._greeterClient.connect('default-session-name-changed',
Lang.bind(this, this._onDefaultSessionChanged));
this._greeterClient.connect('info',
Lang.bind(this, this._onInfo));
@ -769,8 +767,6 @@ const LoginDialog = new Lang.Class({
Lang.bind(this, this._onSessionOpened));
this._greeterClient.connect('timed-login-requested',
Lang.bind(this, this._onTimedLoginRequested));
this._greeterClient.connect('authentication-failed',
Lang.bind(this, this._onAuthenticationFailed));
this._greeterClient.connect('conversation-stopped',
Lang.bind(this, this._onConversationStopped));
@ -899,7 +895,7 @@ const LoginDialog = new Lang.Class({
this._haveFingerprintReader = true;
if (this._haveFingerprintReader)
this._greeterClient.call_start_conversation(_FINGERPRINT_SERVICE_NAME);
this._greeterClient.call_start_conversation_sync(FINGERPRINT_SERVICE_NAME, null);
}));
},
@ -918,7 +914,7 @@ const LoginDialog = new Lang.Class({
},
_onReset: function(client, serviceName) {
this._greeterClient.call_start_conversation(_PASSWORD_SERVICE_NAME);
this._greeterClient.call_start_conversation_sync(PASSWORD_SERVICE_NAME, null);
this._startFingerprintConversationIfNeeded();
let tasks = [this._hidePrompt,
@ -954,7 +950,7 @@ const LoginDialog = new Lang.Class({
// We don't display fingerprint messages, because they
// have words like UPEK in them. Instead we use the messages
// as a cue to display our own message.
if (serviceName == _FINGERPRINT_SERVICE_NAME &&
if (serviceName == FINGERPRINT_SERVICE_NAME &&
this._haveFingerprintReader &&
(!this._promptFingerprintMessage.visible ||
this._promptFingerprintMessage.opacity != 255)) {
@ -963,7 +959,7 @@ const LoginDialog = new Lang.Class({
return;
}
if (serviceName != _PASSWORD_SERVICE_NAME)
if (serviceName != PASSWORD_SERVICE_NAME)
return;
Main.notifyError(info);
},
@ -971,13 +967,13 @@ const LoginDialog = new Lang.Class({
_onProblem: function(client, serviceName, problem) {
// we don't want to show auth failed messages to
// users who haven't enrolled their fingerprint.
if (serviceName != _PASSWORD_SERVICE_NAME)
if (serviceName != PASSWORD_SERVICE_NAME)
return;
Main.notifyError(problem);
},
_onCancel: function(client) {
this._greeterClient.call_cancel();
this._greeterClient.call_cancel_sync(null);
},
_fadeInPrompt: function() {
@ -1084,7 +1080,7 @@ const LoginDialog = new Lang.Class({
let _text = this._promptEntry.get_text();
this._promptEntry.reactive = false;
this._promptEntry.add_style_pseudo_class('insensitive');
this._greeterClient.call_answer_query(serviceName, _text);
this._greeterClient.call_answer_query_sync(serviceName, _text, null);
}];
let batch = new Batch.ConsecutiveBatch(this, tasks);
@ -1092,7 +1088,7 @@ const LoginDialog = new Lang.Class({
},
_onInfoQuery: function(client, serviceName, question) {
// We only expect questions to come from the main auth service
if (serviceName != _PASSWORD_SERVICE_NAME)
if (serviceName != PASSWORD_SERVICE_NAME)
return;
this._promptEntry.set_text('');
@ -1102,7 +1098,7 @@ const LoginDialog = new Lang.Class({
_onSecretInfoQuery: function(client, serviceName, secretQuestion) {
// We only expect secret requests to come from the main auth service
if (serviceName != _PASSWORD_SERVICE_NAME)
if (serviceName != PASSWORD_SERVICE_NAME)
return;
this._promptEntry.set_text('');
@ -1111,7 +1107,7 @@ const LoginDialog = new Lang.Class({
},
_onSessionOpened: function(client, serviceName) {
this._greeterClient.call_start_session_when_ready(serviceName, true);
this._greeterClient.call_start_session_when_ready_sync(serviceName, true, null);
},
_waitForItemForUser: function(userName) {
@ -1193,7 +1189,7 @@ const LoginDialog = new Lang.Class({
function() {
this._timedLoginBatch = null;
this._greeterClient.call_begin_auto_login(userName);
this._greeterClient.call_begin_auto_login_sync(userName, null);
}];
this._timedLoginBatch = new Batch.ConsecutiveBatch(this, tasks);
@ -1236,17 +1232,13 @@ const LoginDialog = new Lang.Class({
}));
},
_onAuthenticationFailed: function(client) {
this._greeterClient.call_cancel();
},
_onConversationStopped: function(client, serviceName) {
// if the password service fails, then cancel everything.
// But if, e.g., fingerprint fails, still give
// password authentication a chance to succeed
if (serviceName == _PASSWORD_SERVICE_NAME) {
this._greeterClient.call_cancel();
} else if (serviceName == _FINGERPRINT_SERVICE_NAME) {
if (serviceName == PASSWORD_SERVICE_NAME) {
this._greeterClient.call_cancel_sync(null);
} else if (serviceName == FINGERPRINT_SERVICE_NAME) {
_fadeOutActor(this._promptFingerprintMessage);
}
},
@ -1269,7 +1261,7 @@ const LoginDialog = new Lang.Class({
this._fadeOutLogo]),
function() {
this._greeterClient.call_begin_verification(_PASSWORD_SERVICE_NAME);
this._greeterClient.call_begin_verification_sync(PASSWORD_SERVICE_NAME, null);
}];
let batch = new Batch.ConsecutiveBatch(this, tasks);
@ -1328,11 +1320,11 @@ const LoginDialog = new Lang.Class({
function() {
let userName = activatedItem.user.get_user_name();
this._greeterClient.call_begin_verification_for_user(_PASSWORD_SERVICE_NAME,
userName);
this._greeterClient.call_begin_verification_for_user_sync(PASSWORD_SERVICE_NAME,
userName, null);
if (this._haveFingerprintReader)
this._greeterClient.call_begin_verification_for_user(_FINGERPRINT_SERVICE_NAME, userName);
this._greeterClient.call_begin_verification_for_user_sync(_FINGERPRINT_SERVICE_NAME, userName, null);
}];
this._user = activatedItem.user;

View File

@ -8,6 +8,8 @@ const PACKAGE_VERSION = '@PACKAGE_VERSION@';
const GJS_VERSION = '@GJS_VERSION@';
/* 1 if gnome-bluetooth is available, 0 otherwise */
const HAVE_BLUETOOTH = @HAVE_BLUETOOTH@;
/* The system TLS CA list */
const SHELL_SYSTEM_CA_FILE = '@SHELL_SYSTEM_CA_FILE@';
/* gettext package */
const GETTEXT_PACKAGE = '@GETTEXT_PACKAGE@';
/* locale dir */

View File

@ -40,18 +40,13 @@ function getCurrentExtension() {
throw new Error('Could not find current extension');
let path = match[1];
let file = Gio.File.new_for_path(path);
let uuid = GLib.path_get_basename(GLib.path_get_dirname(path));
// Walk up the directory tree, looking for an extesion with
// the same UUID as a directory name.
while (file != null) {
let extension = extensions[file.get_basename()];
if (extension !== undefined)
return extension;
file = file.get_parent();
}
let extension = extensions[uuid];
if (extension === undefined)
throw new Error('Could not find current extension');
throw new Error('Could not find current extension');
return extension;
}
/**
@ -125,7 +120,7 @@ function createExtensionObject(uuid, dir, type) {
// Encourage people to add this
if (!meta.url) {
log('Warning: Missing "url" property in %s/metadata.json'.format(uuid));
global.log('Warning: Missing "url" property in metadata.json');
}
if (uuid != meta.uuid) {
@ -162,7 +157,7 @@ function init() {
if (!userExtensionsDir.query_exists(null))
userExtensionsDir.make_directory_with_parents(null);
} catch (e) {
logError(e, 'Could not create extensions directory');
global.logError('' + e);
}
}
@ -172,7 +167,7 @@ function scanExtensionsInDirectory(callback, dir, type) {
try {
fileEnum = dir.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null);
} catch(e) {
logError(e, 'Could not enumerate extensions directory');
global.logError('' + e);
return;
}

71
js/misc/format.js Normal file
View File

@ -0,0 +1,71 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const ShellJS = imports.gi.ShellJS;
/*
* This function is intended to extend the String object and provide
* an String.format API for string formatting.
* It has to be set up using String.prototype.format = Format.format;
* Usage:
* "somestring %s %d".format('hello', 5);
* It supports %s, %d, %x and %f, for %f it also support precisions like
* "%.2f".format(1.526). All specifiers can be prefixed with a minimum
* field width, e.g. "%5s".format("foo"). Unless the width is prefixed
* with '0', the formatted string will be padded with spaces.
*/
function format() {
let str = this;
let i = 0;
let args = arguments;
return str.replace(/%(I+)?([0-9]+)?(?:\.([0-9]+))?(.)/g, function (str, flagsGroup, widthGroup, precisionGroup, genericGroup) {
if (precisionGroup != '' && genericGroup != 'f')
throw new Error("Precision can only be specified for 'f'");
let hasAlternativeIntFlag = (flagsGroup.indexOf('I') != -1);
if (hasAlternativeIntFlag && genericGroup != 'd')
throw new Error("Alternative output digits can only be specfied for 'd'");
let fillChar = (widthGroup[0] == '0') ? '0' : ' ';
let width = parseInt(widthGroup, 10) || 0;
function fillWidth(s, c, w) {
let fill = '';
for (let i = 0; i < w; i++)
fill += c;
return fill.substr(s.length) + s;
}
let s = '';
switch (genericGroup) {
case '%':
return '%';
break;
case 's':
s = args[i++].toString();
break;
case 'd':
let intV = parseInt(args[i++]);
if (hasAlternativeIntFlag)
s = ShellJS.format_int_alternative_output(intV);
else
s = intV.toString();
break;
case 'x':
s = parseInt(args[i++]).toString(16);
break;
case 'f':
if (precisionGroup == '')
s = parseFloat(args[i++]).toString();
else
s = parseFloat(args[i++]).toFixed(parseInt(precisionGroup));
break;
default:
throw new Error('Unsupported conversion character %' + genericGroup);
}
return fillWidth(s, fillChar, width);
});
}

View File

@ -63,7 +63,7 @@ const Contact = new Lang.Class({
this.individual.full_name ||
this.individual.nickname ||
email ||
C_("contact", "Unknown");
_("Unknown");
let aliasLabel = new St.Label({ text: aliasText,
style_class: 'contact-details-alias' });
details.add(aliasLabel, { x_fill: true,

View File

@ -45,7 +45,9 @@ const DateMenuButton = new Lang.Class({
Name: 'DateMenuButton',
Extends: PanelMenu.Button,
_init: function() {
_init: function(params) {
params = Params.parse(params, { showEvents: true });
let item;
let hbox;
let vbox;
@ -77,7 +79,7 @@ const DateMenuButton = new Lang.Class({
this._date.style_class = 'datemenu-date-label';
vbox.add(this._date);
if (Main.sessionMode.showCalendarEvents) {
if (params.showEvents) {
this._eventSource = new Calendar.DBusEventSource();
this._eventList = new Calendar.EventsList(this._eventSource);
} else {
@ -108,7 +110,7 @@ const DateMenuButton = new Lang.Class({
item.actor.reparent(vbox);
}
if (Main.sessionMode.showCalendarEvents) {
if (params.showEvents) {
// Add vertical separator
item = new St.DrawingArea({ style_class: 'calendar-vertical-separator',

View File

@ -342,7 +342,7 @@ const EndSessionDialog = new Lang.Class({
}
},
_updateDescription: function() {
_updateContent: function() {
if (this.state != ModalDialog.State.OPENING &&
this.state != ModalDialog.State.OPENED)
return;
@ -352,6 +352,17 @@ const EndSessionDialog = new Lang.Class({
let subject = dialogContent.subject;
let description;
if (this._user.is_loaded && !dialogContent.iconName) {
let iconFile = this._user.get_icon_file();
if (GLib.file_test(iconFile, GLib.FileTest.EXISTS))
this._setIconFromFile(iconFile, dialogContent.iconStyleClass);
else
this._setIconFromName('avatar-default', dialogContent.iconStyleClass);
} else if (dialogContent.iconName) {
this._setIconFromName(dialogContent.iconName,
dialogContent.iconStyleClass);
}
if (this._inhibitors.length > 0) {
this._stopTimer();
description = dialogContent.inhibitedDescription;
@ -384,27 +395,6 @@ const EndSessionDialog = new Lang.Class({
_setLabelText(this._descriptionLabel, description);
},
_updateContent: function() {
if (this.state != ModalDialog.State.OPENING &&
this.state != ModalDialog.State.OPENED)
return;
let dialogContent = DialogContent[this._type];
if (this._user.is_loaded && !dialogContent.iconName) {
let iconFile = this._user.get_icon_file();
if (GLib.file_test(iconFile, GLib.FileTest.EXISTS))
this._setIconFromFile(iconFile, dialogContent.iconStyleClass);
else
this._setIconFromName('avatar-default', dialogContent.iconStyleClass);
} else if (dialogContent.iconName) {
this._setIconFromName(dialogContent.iconName,
dialogContent.iconStyleClass);
}
this._updateDescription();
},
_updateButtons: function() {
let dialogContent = DialogContent[this._type];
let buttons = [{ action: Lang.bind(this, this.cancel),
@ -451,7 +441,7 @@ const EndSessionDialog = new Lang.Class({
{ _secondsLeft: 0,
time: this._secondsLeft,
transition: 'linear',
onUpdate: Lang.bind(this, this._updateDescription),
onUpdate: Lang.bind(this, this._updateContent),
onComplete: Lang.bind(this, function() {
let dialogContent = DialogContent[this._type];
let button = dialogContent.confirmButtons[dialogContent.confirmButtons.length - 1];

View File

@ -90,7 +90,7 @@ function init() {
}
// OK, now things are initialized enough that we can import shell JS
const Format = imports.format;
const Format = imports.misc.format;
const Tweener = imports.ui.tweener;
Tweener.init();

View File

@ -34,11 +34,24 @@ const REPOSITORY_URL_BASE = 'https://extensions.gnome.org';
const REPOSITORY_URL_DOWNLOAD = REPOSITORY_URL_BASE + '/download-extension/%s.shell-extension.zip';
const REPOSITORY_URL_INFO = REPOSITORY_URL_BASE + '/extension-info/';
const _httpSession = new Soup.SessionAsync({ ssl_use_system_ca_file: true });
const _httpSession = new Soup.SessionAsync();
// The unfortunate state of gjs, gobject-introspection and libsoup
// means that I have to do a hack to add a feature.
// See: https://bugzilla.gnome.org/show_bug.cgi?id=655189 for context.
// _httpSession.add_feature(new Soup.ProxyResolverDefault());
Soup.Session.prototype.add_feature.call(_httpSession, new Soup.ProxyResolverDefault());
if (Soup.Session.prototype.add_feature != null)
Soup.Session.prototype.add_feature.call(_httpSession, new Soup.ProxyResolverDefault());
function _getCertFile() {
let localCert = GLib.build_filenamev([global.userdatadir, 'extensions.gnome.org.crt']);
if (GLib.file_test(localCert, GLib.FileTest.EXISTS))
return localCert;
else
return Config.SHELL_SYSTEM_CA_FILE;
}
_httpSession.ssl_ca_file = _getCertFile();
// Arrays of uuids
var enabledExtensions;
@ -56,16 +69,18 @@ const disconnect = Lang.bind(_signals, _signals.disconnect);
const ENABLED_EXTENSIONS_KEY = 'enabled-extensions';
function installExtensionFromUUID(uuid) {
function installExtensionFromUUID(uuid, version_tag) {
let params = { uuid: uuid,
shell_version: Config.PACKAGE_VERSION };
version_tag: version_tag,
shell_version: Config.PACKAGE_VERSION,
api_version: API_VERSION.toString() };
let message = Soup.form_request_new_from_hash('GET', REPOSITORY_URL_INFO, params);
_httpSession.queue_message(message,
function(session, message) {
let info = JSON.parse(message.response_body.data);
let dialog = new InstallExtensionDialog(uuid, info);
let dialog = new InstallExtensionDialog(uuid, version_tag, info.name);
dialog.open(global.get_current_time());
});
}
@ -100,13 +115,21 @@ function gotExtensionZipFile(session, message, uuid) {
return;
}
let [file, stream] = Gio.File.new_tmp('XXXXXX.shell-extension.zip');
// FIXME: use a GFile mkstemp-type method once one exists
let fd, tmpzip;
try {
[fd, tmpzip] = GLib.file_open_tmp('XXXXXX.shell-extension.zip');
} catch (e) {
logExtensionError(uuid, 'tempfile: ' + e.toString());
return;
}
let stream = new Gio.UnixOutputStream({ fd: fd });
let dir = ExtensionUtils.userExtensionsDir.get_child(uuid);
let contents = message.response_body.flatten().as_bytes();
stream.output_stream.write_bytes(contents, null);
Shell.write_soup_message_to_stream(stream, message);
stream.close(null);
let [success, pid] = GLib.spawn_async(null,
['unzip', '-uod', dir.get_path(), '--', file.get_path()],
['unzip', '-uod', dir.get_path(), '--', tmpzip],
null,
GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
null);
@ -214,7 +237,7 @@ function logExtensionError(uuid, message, state) {
extension.errors = [];
extension.errors.push(message);
log('Extension "%s" had error: %s'.format(uuid, message));
global.logError('Extension "%s" had error: %s'.format(uuid, message));
state = state || ExtensionState.ERROR;
_signals.emit('extension-state-changed', { uuid: uuid,
error: message,
@ -226,7 +249,7 @@ function loadExtension(dir, type, enabled) {
let extension;
if (ExtensionUtils.extensions[uuid] != undefined) {
log('Extension "%s" is already loaded'.format(uuid));
global.logError('Extension "%s" is already loaded'.format(uuid));
return;
}
@ -255,6 +278,7 @@ function loadExtension(dir, type, enabled) {
}
_signals.emit('extension-state-changed', extension);
global.log('Loaded extension ' + uuid);
}
function initExtension(uuid) {
@ -366,11 +390,12 @@ const InstallExtensionDialog = new Lang.Class({
Name: 'InstallExtensionDialog',
Extends: ModalDialog.ModalDialog,
_init: function(uuid, info) {
_init: function(uuid, version_tag, name) {
this.parent({ styleClass: 'extension-dialog' });
this._uuid = uuid;
this._info = info;
this._version_tag = version_tag;
this._name = name;
this.setButtons([{ label: _("Cancel"),
action: Lang.bind(this, this._onCancelButtonPressed),
@ -380,17 +405,13 @@ const InstallExtensionDialog = new Lang.Class({
action: Lang.bind(this, this._onInstallButtonPressed)
}]);
let message = _("Download and install '%s' from extensions.gnome.org?").format(info.name);
let message = _("Download and install '%s' from extensions.gnome.org?").format(name);
let box = new St.BoxLayout();
this.contentLayout.add(box);
this._descriptionLabel = new St.Label({ text: message });
let gicon = new Gio.FileIcon({ file: Gio.File.new_for_uri(REPOSITORY_URL_BASE + info.icon) })
let icon = new St.Icon({ gicon: gicon });
box.add(icon);
let label = new St.Label({ text: message });
box.add(label);
this.contentLayout.add(this._descriptionLabel,
{ y_fill: true,
y_align: St.Align.START });
},
_onCancelButtonPressed: function(button, event) {
@ -414,7 +435,9 @@ const InstallExtensionDialog = new Lang.Class({
_signals.emit('extension-state-changed', state);
let params = { shell_version: Config.PACKAGE_VERSION };
let params = { version_tag: this._version_tag,
shell_version: Config.PACKAGE_VERSION,
api_version: API_VERSION.toString() };
let url = REPOSITORY_URL_DOWNLOAD.format(this._uuid);
let message = Soup.form_request_new_from_hash('GET', url, params);

View File

@ -282,10 +282,6 @@ const IconGrid = new Lang.Class({
return this._computeLayout(rowWidth)[0];
},
getRowLimit: function() {
return this._rowLimit;
},
_computeLayout: function (forWidth) {
let nColumns = 0;
let usedWidth = 0;

View File

@ -8,6 +8,8 @@ const St = imports.gi.St;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const DEFAULT_FADE_FACTOR = 0.4;
/**
* Lightbox:
* @container: parent Clutter.Container
@ -15,7 +17,8 @@ const Tweener = imports.ui.tweener;
* - inhibitEvents: whether to inhibit events for @container
* - width: shade actor width
* - height: shade actor height
* - fadeTime: seconds used to fade in/out
* - fadeInTime: seconds used to fade in
* - fadeOutTime: seconds used to fade out
*
* Lightbox creates a dark translucent "shade" actor to hide the
* contents of @container, and allows you to specify particular actors
@ -38,12 +41,16 @@ const Lightbox = new Lang.Class({
params = Params.parse(params, { inhibitEvents: false,
width: null,
height: null,
fadeTime: null
fadeInTime: null,
fadeOutTime: null,
fadeFactor: DEFAULT_FADE_FACTOR
});
this._container = container;
this._children = container.get_children();
this._fadeTime = params.fadeTime;
this._fadeInTime = params.fadeInTime;
this._fadeOutTime = params.fadeOutTime;
this._fadeFactor = params.fadeFactor;
this.actor = new St.Bin({ x: 0,
y: 0,
style_class: 'lightbox',
@ -52,6 +59,7 @@ const Lightbox = new Lang.Class({
container.add_actor(this.actor);
this.actor.raise_top();
this.actor.hide();
this.shown = false;
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
@ -93,24 +101,30 @@ const Lightbox = new Lang.Class({
},
show: function() {
if (this._fadeTime) {
if (this._fadeInTime) {
this.shown = false;
this.actor.opacity = 0;
Tweener.addTween(this.actor,
{ opacity: 255,
time: this._fadeTime,
transition: 'easeOutQuad'
{ opacity: 255 * this._fadeFactor,
time: this._fadeInTime,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
this.shown = true;
})
});
} else {
this.actor.opacity = 255;
this.actor.opacity = 255 * this._fadeFactor;
this.shown = true;
}
this.actor.show();
},
hide: function() {
if (this._fadeTime) {
this.shown = false;
if (this._fadeOutTime) {
Tweener.addTween(this.actor,
{ opacity: 0,
time: this._fadeTime,
time: this._fadeOutTime,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
this.actor.hide();

View File

@ -29,8 +29,8 @@ const LookingGlass = imports.ui.lookingGlass;
const NetworkAgent = imports.ui.networkAgent;
const NotificationDaemon = imports.ui.notificationDaemon;
const WindowAttentionHandler = imports.ui.windowAttentionHandler;
const ScreenShield = imports.ui.screenShield;
const Scripting = imports.ui.scripting;
const SessionMode = imports.ui.sessionMode;
const ShellDBus = imports.ui.shellDBus;
const TelepathyClient = imports.ui.telepathyClient;
const WindowManager = imports.ui.windowManager;
@ -52,12 +52,12 @@ let runDialog = null;
let lookingGlass = null;
let wm = null;
let messageTray = null;
let screenShield = null;
let notificationDaemon = null;
let windowAttentionHandler = null;
let telepathyClient = null;
let ctrlAltTabManager = null;
let recorder = null;
let sessionMode = null;
let shellDBusService = null;
let modalCount = 0;
let modalActorFocusStack = [];
@ -71,11 +71,12 @@ let networkAgent = null;
let _startDate;
let _defaultCssStylesheet = null;
let _cssStylesheet = null;
let _gdmCssStylesheet = null;
let _overridesSettings = null;
let background = null;
function createUserSession() {
function _createUserSession() {
// Load the calendar server. Note that we are careful about
// not loading any events until the user presses the clock
global.launch_calendar_server();
@ -84,11 +85,9 @@ function createUserSession() {
automountManager = new AutomountManager.AutomountManager();
autorunManager = new AutorunManager.AutorunManager();
networkAgent = new NetworkAgent.NetworkAgent();
_initRecorder();
}
function createGDMSession() {
function _createGDMSession() {
// We do this this here instead of at the top to prevent GDM
// related code from getting loaded in normal user sessions
const LoginDialog = imports.gdm.loginDialog;
@ -99,13 +98,8 @@ function createGDMSession() {
});
}
function createInitialSetupSession() {
networkAgent = new NetworkAgent.NetworkAgent();
}
function _initRecorder() {
let recorderSettings = new Gio.Settings({ schema: 'org.gnome.shell.recorder' });
let desktopLockdownSettings = new Gio.Settings({ schema: 'org.gnome.desktop.lockdown' });
let bindingSettings = new Gio.Settings({ schema: 'org.gnome.shell.keybindings' });
global.display.add_keybinding('toggle-recording',
@ -118,7 +112,7 @@ function _initRecorder() {
if (recorder.is_recording()) {
recorder.close();
Meta.enable_unredirect_for_screen(global.screen);
} else if (!desktopLockdownSettings.get_boolean('disable-save-to-disk')) {
} else {
// read the parameters from GSettings always in case they have changed
recorder.set_framerate(recorderSettings.get_int('framerate'));
/* Translators: this is a filename used for screencast recording */
@ -137,6 +131,26 @@ function _initRecorder() {
});
}
function _initUserSession() {
_initRecorder();
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, false, -1, 1);
ExtensionSystem.init();
ExtensionSystem.loadExtensions();
Meta.keybindings_set_custom_handler('panel-run-dialog', function() {
getRunDialog().open();
});
Meta.keybindings_set_custom_handler('panel-main-menu', function () {
overview.toggle();
});
global.display.connect('overlay-key', Lang.bind(overview, overview.toggle));
}
function start() {
// These are here so we don't break compatibility.
global.logError = window.log;
@ -147,7 +161,6 @@ function start() {
Gio.DesktopAppInfo.set_desktop_env('GNOME');
sessionMode = new SessionMode.SessionMode();
shellDBusService = new ShellDBus.GnomeShell();
// Ensure ShellWindowTracker and ShellAppUsage are initialized; this will
@ -170,6 +183,7 @@ function start() {
global.stage.no_clear_hint = true;
_defaultCssStylesheet = global.datadir + '/theme/gnome-shell.css';
_gdmCssStylesheet = global.datadir + '/theme/gdm.css';
loadTheme();
// Set up stage hierarchy to group all UI actors under one container.
@ -197,17 +211,22 @@ function start() {
layoutManager = new Layout.LayoutManager();
xdndHandler = new XdndHandler.XdndHandler();
ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
overview = new Overview.Overview();
// This overview object is just a stub for non-user sessions
overview = new Overview.Overview({ isDummy: global.session_type != Shell.SessionType.USER });
magnifier = new Magnifier.Magnifier();
statusIconDispatcher = new StatusIconDispatcher.StatusIconDispatcher();
panel = new Panel.Panel();
wm = new WindowManager.WindowManager();
messageTray = new MessageTray.MessageTray();
screenShield = new ScreenShield.ScreenShield();
keyboard = new Keyboard.Keyboard();
notificationDaemon = new NotificationDaemon.NotificationDaemon();
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
sessionMode.createSession();
if (global.session_type == Shell.SessionType.USER)
_createUserSession();
else if (global.session_type == Shell.SessionType.GDM)
_createGDMSession();
panel.startStatusArea();
@ -215,30 +234,8 @@ function start() {
keyboard.init();
overview.init();
if (sessionMode.hasWorkspaces)
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
false, -1, 1);
if (sessionMode.allowExtensions) {
ExtensionSystem.init();
ExtensionSystem.loadExtensions();
}
if (sessionMode.hasRunDialog) {
Meta.keybindings_set_custom_handler('panel-run-dialog', function() {
getRunDialog().open();
});
}
if (sessionMode.hasOverview) {
Meta.keybindings_set_custom_handler('panel-main-menu', function () {
overview.toggle();
});
global.display.connect('overlay-key',
Lang.bind(overview, overview.toggle));
}
if (global.session_type == Shell.SessionType.USER)
_initUserSession();
statusIconDispatcher.start(messageTray.actor);
// Provide the bus object for gnome-session to
@ -497,8 +494,8 @@ function loadTheme() {
let theme = new St.Theme ({ application_stylesheet: cssStylesheet });
if (sessionMode.extraStylesheet)
theme.load_stylesheet(sessionMode.extraStylesheet);
// FIXME: merge back into main stylesheet
theme.load_stylesheet(_gdmCssStylesheet);
if (previousTheme) {
let customStylesheets = previousTheme.get_custom_stylesheets();
@ -562,11 +559,6 @@ function _globalKeyPressHandler(actor, event) {
if (event.type() != Clutter.EventType.KEY_PRESS)
return false;
if (!sessionMode.allowKeybindingsWhenModal) {
if (modalCount > (overview.visible ? 1 : 0))
return false;
}
let symbol = event.get_key_symbol();
let keyCode = event.get_key_code();
let ignoredModifiers = global.display.get_ignored_modifier_mask();
@ -575,6 +567,11 @@ function _globalKeyPressHandler(actor, event) {
// This relies on the fact that Clutter.ModifierType is the same as Gdk.ModifierType
let action = global.display.get_keybinding_action(keyCode, modifierState);
// Other bindings are only available to the user session when the overview is up and
// no modal dialog is present.
if (global.session_type == Shell.SessionType.USER && (!overview.visible || modalCount > 1))
return false;
// This isn't a Meta.KeyBindingAction yet
if (symbol == Clutter.Super_L || symbol == Clutter.Super_R) {
overview.hide();
@ -587,39 +584,28 @@ function _globalKeyPressHandler(actor, event) {
return true;
}
// None of the other bindings are relevant outside of the user's session
if (global.session_type != Shell.SessionType.USER)
return false;
switch (action) {
// left/right would effectively act as synonyms for up/down if we enabled them;
// but that could be considered confusing; we also disable them in the main view.
//
// case Meta.KeyBindingAction.WORKSPACE_LEFT:
// if (!sessionMode.hasWorkspaces)
// return false;
//
// wm.actionMoveWorkspaceLeft();
// return true;
// case Meta.KeyBindingAction.WORKSPACE_RIGHT:
// if (!sessionMode.hasWorkspaces)
// return false;
//
// wm.actionMoveWorkspaceRight();
// return true;
case Meta.KeyBindingAction.WORKSPACE_UP:
if (!sessionMode.hasWorkspaces)
return false;
wm.actionMoveWorkspaceUp();
return true;
case Meta.KeyBindingAction.WORKSPACE_DOWN:
if (!sessionMode.hasWorkspaces)
return false;
wm.actionMoveWorkspaceDown();
return true;
case Meta.KeyBindingAction.PANEL_RUN_DIALOG:
case Meta.KeyBindingAction.COMMAND_2:
if (!sessionMode.hasRunDialog)
return false;
getRunDialog().open();
return true;
case Meta.KeyBindingAction.PANEL_MAIN_MENU:
@ -638,6 +624,10 @@ function _findModal(actor) {
return -1;
}
function isInModalStack(actor) {
return _findModal(actor) != -1;
}
/**
* pushModal:
* @actor: #ClutterActor which will be given keyboard focus
@ -678,7 +668,7 @@ function pushModal(actor, timestamp, options) {
let actorDestroyId = actor.connect('destroy', function() {
let index = _findModal(actor);
if (index >= 0)
modalActorFocusStack.splice(index, 1);
popModal(actor);
});
let curFocus = global.stage.get_key_focus();
let curFocusDestroyId;
@ -892,8 +882,7 @@ function initializeDeferredWork(actor, callback, props) {
function queueDeferredWork(workId) {
let data = _deferredWorkData[workId];
if (!data) {
let message = 'Invalid work id %d'.format(workId);
logError(new Error(message), message);
global.logError('invalid work id ', workId);
return;
}
if (_deferredWorkQueue.indexOf(workId) < 0)

View File

@ -221,19 +221,12 @@ const NotificationDaemon = new Lang.Class({
let [appName, replacesId, icon, summary, body, actions, hints, timeout] = params;
let id;
for (let hint in hints) {
// unpack the variants
hints[hint] = hints[hint].deep_unpack();
}
hints = Params.parse(hints, { urgency: Urgency.NORMAL }, true);
// Filter out chat, presence, calls and invitation notifications from
// Empathy, since we handle that information from telepathyClient.js
if (appName == 'Empathy' && (hints['category'] == 'im.received' ||
hints['category'] == 'x-empathy.im.room-invitation' ||
hints['category'] == 'x-empathy.call.incoming' ||
hints['category'] == 'x-empathy.transfer.incoming' ||
hints['category'] == 'x-empathy.call.incoming"' ||
hints['category'] == 'x-empathy.im.subscription-request' ||
hints['category'] == 'presence.online' ||
hints['category'] == 'presence.offline')) {
@ -256,6 +249,13 @@ const NotificationDaemon = new Lang.Class({
}
}
for (let hint in hints) {
// unpack the variants
hints[hint] = hints[hint].deep_unpack();
}
hints = Params.parse(hints, { urgency: Urgency.NORMAL }, true);
// Be compatible with the various hints for image data and image path
// 'image-data' and 'image-path' are the latest name of these hints, introduced in 1.2
@ -483,7 +483,7 @@ const NotificationDaemon = new Lang.Class({
},
_onTrayIconAdded: function(o, icon) {
let source = this._getSource(icon.title || icon.wm_class || C_("program", "Unknown"), icon.pid, null, null, icon);
let source = this._getSource(icon.title || icon.wm_class || _("Unknown"), icon.pid, null, null, icon);
},
_onTrayIconRemoved: function(o, icon) {

View File

@ -99,8 +99,10 @@ const ShellInfo = new Lang.Class({
const Overview = new Lang.Class({
Name: 'Overview',
_init : function() {
this.isDummy = !Main.sessionMode.hasOverview;
_init : function(params) {
params = Params.parse(params, { isDummy: false });
this.isDummy = params.isDummy;
// We only have an overview in user sessions, so
// create a dummy overview in other cases

View File

@ -14,6 +14,7 @@ const St = imports.gi.St;
const Signals = imports.signals;
const Atk = imports.gi.Atk;
const Config = imports.misc.config;
const CtrlAltTab = imports.ui.ctrlAltTab;
const DND = imports.ui.dnd;
const Layout = imports.ui.layout;
@ -31,6 +32,33 @@ const BUTTON_DND_ACTIVATION_TIMEOUT = 250;
const ANIMATED_ICON_UPDATE_TIMEOUT = 100;
const SPINNER_ANIMATION_TIME = 0.2;
const STANDARD_STATUS_AREA_ORDER = ['a11y', 'keyboard', 'volume', 'bluetooth', 'network', 'battery', 'userMenu'];
const STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION = {
'a11y': imports.ui.status.accessibility.ATIndicator,
'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator,
'keyboard': imports.ui.status.keyboard.XKBIndicator,
'userMenu': imports.ui.userMenu.UserMenuButton
};
if (Config.HAVE_BLUETOOTH)
STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION['bluetooth'] = imports.ui.status.bluetooth.Indicator;
try {
STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION['network'] = imports.ui.status.network.NMApplet;
} catch(e) {
log('NMApplet is not supported. It is possible that your NetworkManager version is too old');
}
const GDM_STATUS_AREA_ORDER = ['a11y', 'display', 'keyboard', 'volume', 'battery', 'powerMenu'];
const GDM_STATUS_AREA_SHELL_IMPLEMENTATION = {
'a11y': imports.ui.status.accessibility.ATIndicator,
'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator,
'keyboard': imports.ui.status.keyboard.XKBIndicator,
'powerMenu': imports.gdm.powerMenu.PowerMenuButton
};
// To make sure the panel corners blend nicely with the panel,
// we draw background and borders the same way, e.g. drawing
// them as filled shapes from the outside inwards instead of
@ -934,7 +962,7 @@ const Panel = new Lang.Class({
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
/* Button on the left side of the panel. */
if (Main.sessionMode.hasOverview) {
if (global.session_type == Shell.SessionType.USER) {
this._activitiesButton = new ActivitiesButton();
this._activities = this._activitiesButton.actor;
this._leftBox.add(this._activities);
@ -942,19 +970,28 @@ const Panel = new Lang.Class({
// The activities button has a pretend menu, so as to integrate
// more cleanly with the rest of the panel
this._menus.addMenu(this._activitiesButton.menu);
}
if (Main.sessionMode.hasAppMenu) {
this._appMenu = new AppMenuButton(this._menus);
this._leftBox.add(this._appMenu.actor);
}
/* center */
this._dateMenu = new DateMenu.DateMenuButton();
if (global.session_type == Shell.SessionType.USER)
this._dateMenu = new DateMenu.DateMenuButton({ showEvents: true });
else
this._dateMenu = new DateMenu.DateMenuButton({ showEvents: false });
this._centerBox.add(this._dateMenu.actor, { y_fill: true });
this._menus.addMenu(this._dateMenu.menu);
/* right */
if (global.session_type == Shell.SessionType.GDM) {
this._status_area_order = GDM_STATUS_AREA_ORDER;
this._status_area_shell_implementation = GDM_STATUS_AREA_SHELL_IMPLEMENTATION;
} else {
this._status_area_order = STANDARD_STATUS_AREA_ORDER;
this._status_area_shell_implementation = STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION;
}
Main.statusIconDispatcher.connect('status-icon-added', Lang.bind(this, this._onTrayIconAdded));
Main.statusIconDispatcher.connect('status-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
@ -1086,9 +1123,9 @@ const Panel = new Lang.Class({
},
startStatusArea: function() {
for (let i = 0; i < Main.sessionMode.statusArea.order.length; i++) {
let role = Main.sessionMode.statusArea.order[i];
let constructor = Main.sessionMode.statusArea.implementation[role];
for (let i = 0; i < this._status_area_order.length; i++) {
let role = this._status_area_order[i];
let constructor = this._status_area_shell_implementation[role];
if (!constructor) {
// This icon is not implemented (this is a bug)
continue;
@ -1138,21 +1175,18 @@ const Panel = new Lang.Class({
},
_onTrayIconAdded: function(o, icon, role) {
if (Main.sessionMode.statusArea.implementation[role]) {
if (this._status_area_shell_implementation[role]) {
// This icon is legacy, and replaced by a Shell version
// Hide it
return;
}
if (Main.sessionMode.statusArea.order.indexOf(role) == -1)
return;
icon.height = PANEL_ICON_SIZE;
let buttonBox = new PanelMenu.ButtonBox();
let box = buttonBox.actor;
box.add_actor(icon);
this._insertStatusItem(box, Main.sessionMode.statusArea.order.indexOf(role));
this._insertStatusItem(box, this._status_area_order.indexOf(role));
},
_onTrayIconRemoved: function(o, icon) {

View File

@ -167,7 +167,6 @@ const AuthenticationDialog = new Lang.Class({
*/
this._nullMessageLabel = new St.Label({ style_class: 'prompt-dialog-null-label',
text: 'abc'});
this._nullMessageLabel.add_style_class_name('hidden');
this._nullMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._nullMessageLabel.clutter_text.line_wrap = true;
messageBox.add(this._nullMessageLabel);

View File

@ -888,7 +888,8 @@ const PopupMenuBase = new Lang.Class({
},
addSettingsAction: function(title, desktopFile) {
if (!Main.sessionMode.allowSettings)
// Don't allow user settings to get edited unless we're in a user session
if (global.session_type != Shell.SessionType.USER)
return null;
let menuItem = this.addAction(title, function() {
@ -1920,7 +1921,7 @@ const RemoteMenu = new Lang.Class({
while (k0 < currentItems.length && currentItems[k0]._ignored)
k0++;
// find the right menu item matching the model item
for (j0 = 0; k0 < currentItems.length && j0 < position; j0++, k0++) {
for (j0 = 0; j0 < position; j0++, k0++) {
if (currentItems[k0]._ignored)
k0++;
}
@ -1930,7 +1931,7 @@ const RemoteMenu = new Lang.Class({
for (k = k0; k < currentItems.length; k++)
currentItems[k].destroy();
} else {
for (j = j0, k = k0; k < currentItems.length && j < j0 + removed; j++, k++) {
for (j = j0, k = k0; j < j0 + removed; j++, k++) {
currentItems[k].destroy();
if (currentItems[k]._ignored)
@ -1961,9 +1962,8 @@ const RemoteMenu = new Lang.Class({
k++;
}
} else if (changeSignal) {
let signalId = this.actionGroup.connect(changeSignal, Lang.bind(this, function(actionGroup, actionName) {
actionGroup.disconnect(signalId);
if (this._actions[actionName]) return;
let signalId = this.actionGroup.connect(changeSignal, Lang.bind(this, function() {
this.actionGroup.disconnect(signalId);
// force a full update
this._modelChanged(model, 0, -1, model.get_n_items(), target);

142
js/ui/screenShield.js Normal file
View File

@ -0,0 +1,142 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const St = imports.gi.St;
const GnomeSession = imports.misc.gnomeSession;
const Lightbox = imports.ui.lightbox;
const UnlockDialog = imports.ui.unlockDialog;
const Main = imports.ui.main;
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
const LOCK_ENABLED_KEY = 'lock-enabled';
/**
* To test screen shield, make sure to kill gnome-screensaver.
*
* If you are setting org.gnome.desktop.session.idle-delay directly in dconf,
* rather than through System Settings, you also need to set
* org.gnome.settings-daemon.plugins.power.sleep-display-ac and
* org.gnome.settings-daemon.plugins.power.sleep-display-battery to the same value.
* This will ensure that the screen blanks at the right time when it fades out.
* https://bugzilla.gnome.org/show_bug.cgi?id=668703 explains the dependance.
*/
const ScreenShield = new Lang.Class({
Name: 'ScreenShield',
_init: function() {
this._presence = new GnomeSession.Presence(Lang.bind(this, function(proxy, error) {
this._onStatusChanged(proxy.status);
}));
this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
this._onStatusChanged(status);
}));
this._settings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
this._isModal = false;
this._isLocked = false;
this._group = new St.Widget({ x: 0,
y: 0 });
Main.uiGroup.add_actor(this._group);
let constraint = new Clutter.BindConstraint({ source: global.stage,
coordinate: Clutter.BindCoordinate.POSITION | Clutter.BindCoordinate.SIZE });
this._group.add_constraint(constraint);
this._lightbox = new Lightbox.Lightbox(this._group,
{ inhibitEvents: true, fadeInTime: 10, fadeFactor: 1 });
this._background = Meta.BackgroundActor.new_for_screen(global.screen);
this._background.hide();
Main.uiGroup.add_actor(this._background);
},
_onStatusChanged: function(status) {
log ("in _onStatusChanged");
if (status == GnomeSession.PresenceStatus.IDLE) {
log("session gone idle");
if (this._dialog) {
log('canceling existing dialog');
this._dialog.cancel();
this._dialog = null;
}
this._group.reactive = true;
if (!this._isModal) {
Main.pushModal(this._group);
this._isModal = true;
}
this._group.raise_top();
this._lightbox.show();
} else {
log('status is now ' + status);
let lightboxWasShown = this._lightbox.shown;
log("this._lightbox.shown " + this._lightbox.shown);
this._lightbox.hide();
let shouldLock = lightboxWasShown && this._settings.get_boolean(LOCK_ENABLED_KEY);
if (shouldLock || this._isLocked) {
this._isLocked = true;
this._background.show();
this._background.raise_top();
this._showUnlockDialog();
} else if (this._isModal) {
this._popModal();
}
}
},
_popModal: function() {
this._group.reactive = false;
Main.popModal(this._group);
this._background.hide();
},
_showUnlockDialog: function() {
if (this._dialog) {
log ('_showUnlockDialog called again when the dialog was already there');
return;
}
try {
this._dialog = new UnlockDialog.UnlockDialog();
this._dialog.connect('failed', Lang.bind(this, this._onUnlockFailed));
this._dialog.connect('unlocked', Lang.bind(this, this._onUnlockSucceded));
if (!this._dialog.open(global.get_current_time()))
throw new Error('open failed!')
this._dialog._group.raise_top();
} catch(e) {
// FIXME: this is for debugging purposes
logError(e, 'error while creating unlock dialog');
this._popModal();
}
},
_onUnlockFailed: function() {
// FIXME: for now, on failure we just destroy the dialog and create a new
// one (this is what gnome-screensaver does)
// in the future, we may want to go back to the lock screen instead
this._dialog.destroy();
this._dialog = null;
this._showUnlockDialog();
},
_onUnlockSucceded: function() {
this._dialog.destroy();
this._dialog = null;
this._popModal();
},
});

View File

@ -354,7 +354,7 @@ const SearchSystem = new Lang.Class({
results.push([provider, []]);
provider.getSubsearchResultSet(previousResults, terms);
} catch (error) {
log('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
global.log ('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
}
}
} else {
@ -364,7 +364,7 @@ const SearchSystem = new Lang.Class({
results.push([provider, []]);
provider.getInitialResultSet(terms);
} catch (error) {
log('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
global.log ('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
}
}
}

View File

@ -5,7 +5,6 @@ const Lang = imports.lang;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
const St = imports.gi.St;
const Atk = imports.gi.Atk;
const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid;
@ -34,13 +33,12 @@ const SearchResult = new Lang.Class({
content = new St.Bin({ style_class: 'search-result-content',
reactive: true,
can_focus: true,
track_hover: true,
accessible_role: Atk.Role.PUSH_BUTTON });
track_hover: true });
let icon = new IconGrid.BaseIcon(this.metaInfo['name'],
{ createIcon: this.metaInfo['createIcon'] });
content.set_child(icon.actor);
this._dragActorSource = icon.icon;
content.label_actor = icon.label;
this.actor.label_actor = icon.label;
} else {
if (content._delegate && content._delegate.getDragActorSource)
this._dragActorSource = content._delegate.getDragActorSource();
@ -131,7 +129,7 @@ const GridSearchResults = new Lang.Class({
getResultsForDisplay: function() {
let alreadyVisible = this._pendingClear ? 0 : this._grid.visibleItemsCount();
let canDisplay = this._grid.childrenInRow(this._width) * this._grid.getRowLimit()
let canDisplay = this._grid.childrenInRow(this._width) * MAX_SEARCH_RESULTS_ROWS
- alreadyVisible;
let numResults = Math.min(this._notDisplayedResult.length, canDisplay);

View File

@ -1,124 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Config = imports.misc.config;
const Main = imports.ui.main;
const Params = imports.misc.params;
const STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION = {
'a11y': imports.ui.status.accessibility.ATIndicator,
'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator,
'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
'userMenu': imports.ui.userMenu.UserMenuButton
};
if (Config.HAVE_BLUETOOTH)
STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION['bluetooth'] =
imports.ui.status.bluetooth.Indicator;
try {
STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION['network'] =
imports.ui.status.network.NMApplet;
} catch(e) {
log('NMApplet is not supported. It is possible that your NetworkManager version is too old');
}
const DEFAULT_MODE = 'user';
const _modes = {
'gdm': { hasOverview: false,
hasAppMenu: false,
showCalendarEvents: false,
allowSettings: false,
allowExtensions: false,
allowKeybindingsWhenModal: true,
hasRunDialog: false,
hasWorkspaces: false,
createSession: Main.createGDMSession,
extraStylesheet: global.datadir + '/theme/gdm.css',
statusArea: {
order: [
'a11y', 'display', 'keyboard',
'volume', 'battery', 'powerMenu'
],
implementation: {
'a11y': imports.ui.status.accessibility.ATIndicator,
'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator,
'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
'powerMenu': imports.gdm.powerMenu.PowerMenuButton
}
}
},
'initial-setup': { hasOverview: false,
hasAppMenu: false,
showCalendarEvents: false,
allowSettings: false,
allowExtensions: false,
allowKeybindingsWhenModal: false,
hasRunDialog: false,
hasWorkspaces: false,
createSession: Main.createInitialSetupSession,
extraStylesheet: null,
statusArea: {
order: [
'a11y', 'keyboard', 'volume'
],
implementation: {
'a11y': imports.ui.status.accessibility.ATIndicator,
'keyboard': imports.ui.status.keyboard.XKBIndicator,
'volume': imports.ui.status.volume.Indicator
}
}
},
'user': { hasOverview: true,
hasAppMenu: true,
showCalendarEvents: true,
allowSettings: true,
allowExtensions: true,
allowKeybindingsWhenModal: false,
hasRunDialog: true,
hasWorkspaces: true,
createSession: Main.createUserSession,
extraStylesheet: null,
statusArea: {
order: [
'input-method', 'a11y', 'keyboard', 'volume', 'bluetooth',
'network', 'battery', 'userMenu'
],
implementation: STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION
}
}
};
function listModes() {
let modes = Object.getOwnPropertyNames(_modes);
for (let i = 0; i < modes.length; i++)
print(modes[i]);
}
const SessionMode = new Lang.Class({
Name: 'SessionMode',
_init: function() {
let params = _modes[global.session_mode];
params = Params.parse(params, _modes[DEFAULT_MODE]);
this._createSession = params.createSession;
delete params.createSession;
Lang.copyProperties(params, this);
},
createSession: function() {
if (this._createSession)
this._createSession();
}
});

View File

@ -56,8 +56,15 @@ const GnomeShellIface = <interface name="org.gnome.Shell">
<arg type="i" direction="in" name="width"/>
<arg type="i" direction="in" name="height"/>
</method>
<method name="EnableExtension">
<arg type="s" direction="in" name="uuid"/>
</method>
<method name="DisableExtension">
<arg type="s" direction="in" name="uuid"/>
</method>
<method name="InstallRemoteExtension">
<arg type="s" direction="in" name="uuid"/>
<arg type="s" direction="in" name="version"/>
</method>
<method name="UninstallExtension">
<arg type="s" direction="in" name="uuid"/>
@ -253,8 +260,22 @@ const GnomeShell = new Lang.Class({
return extension.errors;
},
InstallRemoteExtension: function(uuid) {
ExtensionSystem.installExtensionFromUUID(uuid);
EnableExtension: function(uuid) {
let enabledExtensions = global.settings.get_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY);
if (enabledExtensions.indexOf(uuid) == -1)
enabledExtensions.push(uuid);
global.settings.set_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY, enabledExtensions);
},
DisableExtension: function(uuid) {
let enabledExtensions = global.settings.get_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY);
while (enabledExtensions.indexOf(uuid) != -1)
enabledExtensions.splice(enabledExtensions.indexOf(uuid), 1);
global.settings.set_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY, enabledExtensions);
},
InstallRemoteExtension: function(uuid, version_tag) {
ExtensionSystem.installExtensionFromUUID(uuid, version_tag);
},
UninstallExtension: function(uuid) {

View File

@ -2,9 +2,9 @@
const Clutter = imports.gi.Clutter;
const GdkPixbuf = imports.gi.GdkPixbuf;
const Gkbd = imports.gi.Gkbd;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GnomeDesktop = imports.gi.GnomeDesktop;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
@ -14,28 +14,30 @@ const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu;
const Util = imports.misc.util;
const DESKTOP_INPUT_SOURCES_SCHEMA = 'org.gnome.desktop.input-sources';
const KEY_CURRENT_INPUT_SOURCE = 'current';
const KEY_INPUT_SOURCES = 'sources';
const INPUT_SOURCE_TYPE_XKB = 'xkb';
const LayoutMenuItem = new Lang.Class({
Name: 'LayoutMenuItem',
Extends: PopupMenu.PopupBaseMenuItem,
_init: function(displayName, shortName) {
_init: function(config, id, indicator, long_name) {
this.parent();
this.label = new St.Label({ text: displayName });
this.indicator = new St.Label({ text: shortName });
this._config = config;
this._id = id;
this.label = new St.Label({ text: long_name });
this.indicator = indicator;
this.addActor(this.label);
this.addActor(this.indicator);
},
activate: function(event) {
this.parent(event);
this._config.lock_group(this._id);
}
});
const InputSourceIndicator = new Lang.Class({
Name: 'InputSourceIndicator',
const XKBIndicator = new Lang.Class({
Name: 'XKBIndicator',
Extends: PanelMenu.Button,
_init: function() {
@ -48,144 +50,122 @@ const InputSourceIndicator = new Lang.Class({
this.actor.add_actor(this._container);
this.actor.add_style_class_name('panel-status-button');
this._labelActors = {};
this._layoutItems = {};
this._iconActor = new St.Icon({ icon_name: 'keyboard', icon_type: St.IconType.SYMBOLIC, style_class: 'system-status-icon' });
this._container.add_actor(this._iconActor);
this._labelActors = [ ];
this._layoutItems = [ ];
this._settings = new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_SCHEMA });
this._settings.connect('changed::' + KEY_CURRENT_INPUT_SOURCE, Lang.bind(this, this._currentInputSourceChanged));
this._settings.connect('changed::' + KEY_INPUT_SOURCES, Lang.bind(this, this._inputSourcesChanged));
this._showFlags = false;
this._config = Gkbd.Configuration.get();
this._config.connect('changed', Lang.bind(this, this._syncConfig));
this._config.connect('group-changed', Lang.bind(this, this._syncGroup));
this._config.start_listen();
this._currentSourceIndex = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
this._xkbInfo = new GnomeDesktop.XkbInfo();
this._syncConfig();
this._inputSourcesChanged();
// re-using "allowSettings" for the keyboard layout is a bit shady,
// but at least for now it is used as "allow popping up windows
// from shell menus"; we can always add a separate sessionMode
// option if need arises.
if (Main.sessionMode.allowSettings) {
if (global.session_type == Shell.SessionType.USER) {
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addAction(_("Show Keyboard Layout"), Lang.bind(this, this._showLayout));
this.menu.addAction(_("Show Keyboard Layout"), Lang.bind(this, function() {
Main.overview.hide();
Util.spawn(['gkbd-keyboard-display', '-g', String(this._config.get_current_group() + 1)]);
}));
}
this.menu.addSettingsAction(_("Region and Language Settings"), 'gnome-region-panel.desktop');
},
_currentInputSourceChanged: function() {
let nVisibleSources = Object.keys(this._layoutItems).length;
if (nVisibleSources < 2)
return;
_adjustGroupNames: function(names) {
// Disambiguate duplicate names with a subscript
// This is O(N^2) to avoid sorting names
// but N <= 4 so who cares?
let nSources = this._settings.get_value(KEY_INPUT_SOURCES).n_children();
let newCurrentSourceIndex = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
if (newCurrentSourceIndex >= nSources)
return;
if (!this._layoutItems[newCurrentSourceIndex]) {
// This source index is invalid as we weren't able to
// build a menu item for it, so we hide ourselves since we
// can't fix it here. *shrug*
this.menu.close();
this.actor.hide();
return;
} else {
this.actor.show();
for (let i = 0; i < names.length; i++) {
let name = names[i];
let cnt = 0;
for (let j = i + 1; j < names.length; j++) {
if (names[j] == name) {
cnt++;
// U+2081 SUBSCRIPT ONE
names[j] = name + String.fromCharCode(0x2081 + cnt);
}
}
if (cnt != 0)
names[i] = name + '\u2081';
}
if (this._layoutItems[this._currentSourceIndex]) {
this._layoutItems[this._currentSourceIndex].setShowDot(false);
this._container.set_skip_paint(this._labelActors[this._currentSourceIndex], true);
}
this._layoutItems[newCurrentSourceIndex].setShowDot(true);
this._container.set_skip_paint(this._labelActors[newCurrentSourceIndex], false);
this._currentSourceIndex = newCurrentSourceIndex;
return names;
},
_inputSourcesChanged: function() {
let sources = this._settings.get_value(KEY_INPUT_SOURCES);
let nSources = sources.n_children();
for (let i in this._layoutItems)
this._layoutItems[i].destroy();
for (let i in this._labelActors)
this._labelActors[i].destroy();
this._layoutItems = {};
this._labelActors = {};
let infos = [];
let infosByShortName = {};
for (let i = 0; i < nSources; i++) {
let [type, id] = sources.get_child_value(i).deep_unpack();
if (type != INPUT_SOURCE_TYPE_XKB)
continue;
let info = {};
[info.exists, info.displayName, info.shortName, , ] =
this._xkbInfo.get_layout_info(id);
if (!info.exists)
continue;
info.sourceIndex = i;
if (!(info.shortName in infosByShortName))
infosByShortName[info.shortName] = [];
infosByShortName[info.shortName].push(info);
infos.push(info);
_syncConfig: function() {
this._showFlags = this._config.if_flags_shown();
if (this._showFlags) {
this._container.set_skip_paint(this._iconActor, false);
} else {
this._container.set_skip_paint(this._iconActor, true);
}
if (infos.length > 1) {
let groups = this._config.get_group_names();
if (groups.length > 1) {
this.actor.show();
} else {
this.menu.close();
this.actor.hide();
}
for (let i = 0; i < infos.length; i++) {
let info = infos[i];
if (infosByShortName[info.shortName].length > 1) {
let sub = infosByShortName[info.shortName].indexOf(info) + 1;
info.shortName += String.fromCharCode(0x2080 + sub);
}
for (let i = 0; i < this._layoutItems.length; i++)
this._layoutItems[i].destroy();
let item = new LayoutMenuItem(info.displayName, info.shortName);
this._layoutItems[info.sourceIndex] = item;
for (let i = 0; i < this._labelActors.length; i++)
this._labelActors[i].destroy();
let short_names = this._adjustGroupNames(this._config.get_short_group_names());
this._selectedLayout = null;
this._layoutItems = [ ];
this._selectedLabel = null;
this._labelActors = [ ];
for (let i = 0; i < groups.length; i++) {
let icon_name = this._config.get_group_name(i);
let actor;
if (this._showFlags)
actor = new St.Icon({ icon_name: icon_name, icon_type: St.IconType.SYMBOLIC, style_class: 'popup-menu-icon' });
else
actor = new St.Label({ text: short_names[i] });
let item = new LayoutMenuItem(this._config, i, actor, groups[i]);
item._short_group_name = short_names[i];
item._icon_name = icon_name;
this._layoutItems.push(item);
this.menu.addMenuItem(item, i);
item.connect('activate', Lang.bind(this, function() {
this._settings.set_value(KEY_CURRENT_INPUT_SOURCE,
GLib.Variant.new_uint32(info.sourceIndex));
}));
let shortLabel = new St.Label({ text: info.shortName });
this._labelActors[info.sourceIndex] = shortLabel;
let shortLabel = new St.Label({ text: short_names[i] });
this._labelActors.push(shortLabel);
this._container.add_actor(shortLabel);
this._container.set_skip_paint(shortLabel, true);
}
this._currentInputSourceChanged();
this._syncGroup();
},
_showLayout: function() {
Main.overview.hide();
_syncGroup: function() {
let selected = this._config.get_current_group();
let sources = this._settings.get_value(KEY_INPUT_SOURCES);
let current = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
let id = sources.get_child_value(current).deep_unpack()[1];
let [, , , xkbLayout, xkbVariant] = this._xkbInfo.get_layout_info(id);
if (this._selectedLayout) {
this._selectedLayout.setShowDot(false);
this._selectedLayout = null;
}
if (!xkbLayout || xkbLayout.length == 0)
return;
if (this._selectedLabel) {
this._container.set_skip_paint(this._selectedLabel, true);
this._selectedLabel = null;
}
let description = xkbLayout;
if (xkbVariant.length > 0)
description = description + '\t' + xkbVariant;
let item = this._layoutItems[selected];
item.setShowDot(true);
Util.spawn(['gkbd-keyboard-display', '-l', description]);
this._iconActor.icon_name = item._icon_name;
this._selectedLabel = this._labelActors[selected];
this._container.set_skip_paint(this._selectedLabel, this._showFlags);
this._selectedLayout = item;
},
_containerGetPreferredWidth: function(container, for_height, alloc) {
@ -193,11 +173,15 @@ const InputSourceIndicator = new Lang.Class({
// for the height of all children, but we ignore the results
// for those we don't actually display.
let max_min_width = 0, max_natural_width = 0;
if (this._showFlags)
[max_min_width, max_natural_width] = this._iconActor.get_preferred_width(for_height);
for (let i in this._labelActors) {
for (let i = 0; i < this._labelActors.length; i++) {
let [min_width, natural_width] = this._labelActors[i].get_preferred_width(for_height);
max_min_width = Math.max(max_min_width, min_width);
max_natural_width = Math.max(max_natural_width, natural_width);
if (!this._showFlags) {
max_min_width = Math.max(max_min_width, min_width);
max_natural_width = Math.max(max_natural_width, natural_width);
}
}
alloc.min_size = max_min_width;
@ -206,11 +190,15 @@ const InputSourceIndicator = new Lang.Class({
_containerGetPreferredHeight: function(container, for_width, alloc) {
let max_min_height = 0, max_natural_height = 0;
for (let i in this._labelActors) {
if (this._showFlags)
[max_min_height, max_natural_height] = this._iconActor.get_preferred_height(for_width);
for (let i = 0; i < this._labelActors.length; i++) {
let [min_height, natural_height] = this._labelActors[i].get_preferred_height(for_width);
max_min_height = Math.max(max_min_height, min_height);
max_natural_height = Math.max(max_natural_height, natural_height);
if (!this._showFlags) {
max_min_height = Math.max(max_min_height, min_height);
max_natural_height = Math.max(max_natural_height, natural_height);
}
}
alloc.min_size = max_min_height;
@ -224,7 +212,8 @@ const InputSourceIndicator = new Lang.Class({
box.y2 -= box.y1;
box.y1 = 0;
for (let i in this._labelActors)
this._iconActor.allocate_align_fill(box, 0.5, 0, false, false, flags);
for (let i = 0; i < this._labelActors.length; i++)
this._labelActors[i].allocate_align_fill(box, 0.5, 0, false, false, flags);
}
});

View File

@ -304,10 +304,9 @@ const NMDevice = new Lang.Class({
// record the connection
let obj = {
connection: connections[i],
name: connections[i].get_id(),
uuid: connections[i].get_uuid(),
name: connections[i]._name,
uuid: connections[i]._uuid,
timestamp: connections[i]._timestamp,
item: null,
};
this._connections.push(obj);
}
@ -402,46 +401,48 @@ const NMDevice = new Lang.Class({
},
checkConnection: function(connection) {
let pos = this._findConnection(connection.get_uuid());
let pos = this._findConnection(connection._uuid);
let exists = pos != -1;
let valid = this.connectionValid(connection);
let similar = false;
if (exists) {
let existing = this._connections[pos];
// Check if connection changed name or id
similar = existing.name == connection.get_id() &&
existing.timestamp == connection._timestamp;
}
if (exists && valid && similar) {
// Nothing to do
return;
}
if (exists)
if (exists && !valid)
this.removeConnection(connection);
if (valid)
else if (!exists && valid)
this.addConnection(connection);
else if (exists && valid) {
// propagate changes and update the UI
if (this._connections[pos].timestamp != connection._timestamp) {
this._connections[pos].timestamp = connection._timestamp;
this._connections.sort(this._connectionSortFunction);
this._clearSection();
this._queueCreateSection();
}
}
},
addConnection: function(connection) {
// record the connection
let obj = {
connection: connection,
name: connection.get_id(),
uuid: connection.get_uuid(),
name: connection._name,
uuid: connection._uuid,
timestamp: connection._timestamp,
item: null,
};
Util.insertSorted(this._connections, obj, this._connectionSortFunction);
this._connections.push(obj);
this._connections.sort(this._connectionSortFunction);
this._clearSection();
this._queueCreateSection();
},
removeConnection: function(connection) {
let pos = this._findConnection(connection.get_uuid());
if (!connection._uuid) {
log('Cannot remove a connection without an UUID');
return;
}
let pos = this._findConnection(connection._uuid);
if (pos == -1) {
// this connection was never added, nothing to do here
return;
@ -711,10 +712,10 @@ const NMDeviceWired = new Lang.Class({
_createAutomaticConnection: function() {
let connection = new NetworkManager.Connection();
let uuid = NetworkManager.utils_uuid_generate();
connection._uuid = NetworkManager.utils_uuid_generate();
connection.add_setting(new NetworkManager.SettingWired());
connection.add_setting(new NetworkManager.SettingConnection({
uuid: uuid,
uuid: connection._uuid,
id: this._autoConnectionName,
type: NetworkManager.SETTING_WIRED_SETTING_NAME,
autoconnect: true
@ -858,10 +859,10 @@ const NMDeviceBluetooth = new Lang.Class({
_createAutomaticConnection: function() {
let connection = new NetworkManager.Connection;
let uuid = NetworkManager.utils_uuid_generate();
connection._uuid = NetworkManager.utils_uuid_generate();
connection.add_setting(new NetworkManager.SettingBluetooth);
connection.add_setting(new NetworkManager.SettingConnection({
uuid: uuid,
uuid: connection._uuid,
id: this._autoConnectionName,
type: NetworkManager.SETTING_BLUETOOTH_SETTING_NAME,
autoconnect: false
@ -896,12 +897,12 @@ const NMDeviceVPN = new Lang.Class({
Name: 'NMDeviceVPN',
Extends: NMDevice,
_init: function(client, device, connections) {
_init: function(client) {
// Disable autoconnections
this._autoConnectionName = null;
this.category = NMConnectionCategory.VPN;
this.parent(client, null, connections);
this.parent(client, null, [ ]);
},
connectionValid: function(connection) {
@ -913,24 +914,13 @@ const NMDeviceVPN = new Lang.Class({
},
get connected() {
if (!this._activeConnection)
return false;
return this._activeConnection.vpn_state == NetworkManager.VPNConnectionState.ACTIVATED;
return !!this._activeConnection;
},
setActiveConnection: function(activeConnection) {
if (this._stateChangeId)
this._activeConnection.disconnect(this._stateChangeId);
this._stateChangeId = 0;
this.parent(activeConnection);
if (this._activeConnection)
this._stateChangeId = this._activeConnection.connect('vpn-state-changed',
Lang.bind(this, this._connectionStateChanged));
this.emit('state-changed');
this.emit('active-connection-changed');
},
_shouldShowConnectionList: function() {
@ -943,39 +933,7 @@ const NMDeviceVPN = new Lang.Class({
},
getStatusLabel: function() {
if (!this._activeConnection) // Same as DISCONNECTED
return null;
switch(this._activeConnection.vpn_state) {
case NetworkManager.VPNConnectionState.DISCONNECTED:
case NetworkManager.VPNConnectionState.ACTIVATED:
return null;
case NetworkManager.VPNConnectionState.PREPARE:
case NetworkManager.VPNConnectionState.CONNECT:
case NetworkManager.VPNConnectionState.IP_CONFIG_GET:
return _("connecting...");
case NetworkManager.VPNConnectionState.NEED_AUTH:
/* Translators: this is for network connections that require some kind of key or password */
return _("authentication required");
case NetworkManager.VPNConnectionState.FAILED:
return _("connection failed");
default:
log('VPN connection state invalid, is %d'.format(this.device.state));
return 'invalid';
}
},
_connectionStateChanged: function(connection, newstate, reason) {
if (newstate == NetworkManager.VPNConnectionState.FAILED) {
// FIXME: if we ever want to show something based on reason,
// we need to convert from NetworkManager.VPNConnectionStateReason
// to NetworkManager.DeviceStateReason
this.emit('activation-failed', reason);
}
// Differently from real NMDevices, there is no need to queue
// an update of the menu section, contents wouldn't change anyway
this.emit('state-changed');
return null;
}
});
@ -1365,7 +1323,9 @@ const NMDeviceWireless = new Lang.Class({
},
removeConnection: function(connection) {
let pos = this._findConnection(connection.get_uuid());
if (!connection._uuid)
return;
let pos = this._findConnection(connection._uuid);
if (pos == -1) {
// removing connection that was never added
return;
@ -1379,7 +1339,7 @@ const NMDeviceWireless = new Lang.Class({
let apObj = this._networks[i];
let connections = apObj.connections;
for (let k = 0; k < connections.length; k++) {
if (connections[k].get_uuid() == connection.get_uuid()) {
if (connections[k]._uuid == connection._uuid) {
// remove the connection from the access point group
connections.splice(k);
forceupdate = forceupdate || connections.length == 0;
@ -1395,7 +1355,7 @@ const NMDeviceWireless = new Lang.Class({
forceupdate = true;
} else {
for (let j = 0; j < items.length; j++) {
if (items[j]._connection.get_uuid() == connection.get_uuid()) {
if (items[j]._connection._uuid == connection._uuid) {
items[j].destroy();
break;
}
@ -1422,8 +1382,8 @@ const NMDeviceWireless = new Lang.Class({
// record the connection
let obj = {
connection: connection,
name: connection.get_id(),
uuid: connection.get_uuid(),
name: connection._name,
uuid: connection._uuid,
};
this._connections.push(obj);
@ -1584,15 +1544,6 @@ const NMApplet = new Lang.Class({
this.menu.addMenuItem(this._statusSection);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._activeConnections = [ ];
this._connections = [ ];
this._mainConnection = null;
this._activeAccessPointUpdateId = 0;
this._activeAccessPoint = null;
this._mobileUpdateId = 0;
this._mobileUpdateDevice = null;
this._devices = { };
this._devices.wired = {
@ -1628,9 +1579,13 @@ const NMApplet = new Lang.Class({
this._devices.vpn = {
section: new PopupMenu.PopupMenuSection(),
device: this._makeWrapperDevice(NMDeviceVPN, null),
device: new NMDeviceVPN(this._client),
item: new NMWiredSectionTitleMenuItem(_("VPN Connections"))
};
this._devices.vpn.device.connect('active-connection-changed', Lang.bind(this, function() {
this._devices.vpn.item.updateForDevice(this._devices.vpn.device);
}));
this._devices.vpn.item.updateForDevice(this._devices.vpn.device);
this._devices.vpn.section.addMenuItem(this._devices.vpn.item);
this._devices.vpn.section.addMenuItem(this._devices.vpn.device.section);
this._devices.vpn.section.actor.hide();
@ -1638,6 +1593,15 @@ const NMApplet = new Lang.Class({
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addSettingsAction(_("Network Settings"), 'gnome-network-panel.desktop');
this._activeConnections = [ ];
this._connections = [ ];
this._mainConnection = null;
this._activeAccessPointUpdateId = 0;
this._activeAccessPoint = null;
this._mobileUpdateId = 0;
this._mobileUpdateDevice = null;
// Device types
this._dtypes = { };
this._dtypes[NetworkManager.DeviceType.ETHERNET] = NMDeviceWired;
@ -1704,18 +1668,6 @@ const NMApplet = new Lang.Class({
},
_syncSectionTitle: function(category) {
if (category == NMConnectionCategory.VPN) {
// Special case VPN: it's only one device (and a fake one
// actually), and we don't show it if empty
let device = this._devices.vpn.device;
let section = this._devices.vpn.section;
let item = this._devices.vpn.item;
section.actor.visible = !device.empty;
item.updateForDevice(device);
return;
}
let devices = this._devices[category].devices;
let item = this._devices[category].item;
let section = this._devices[category].section;
@ -1766,29 +1718,6 @@ const NMApplet = new Lang.Class({
this._source.notify(device._notification);
},
_makeWrapperDevice: function(wrapperClass, device) {
let wrapper = new wrapperClass(this._client, device, this._connections);
wrapper._activationFailedId = wrapper.connect('activation-failed', Lang.bind(this, function(device, reason) {
// XXX: nm-applet has no special text depending on reason
// but I'm not sure of this generic message
this._notifyForDevice(device, 'network-error',
_("Connection failed"),
_("Activation of network connection failed"),
MessageTray.Urgency.HIGH);
}));
wrapper._deviceStateChangedId = wrapper.connect('state-changed', Lang.bind(this, function(dev) {
this._syncSectionTitle(dev.category);
}));
wrapper._destroyId = wrapper.connect('destroy', function(wrapper) {
wrapper.disconnect(wrapper._activationFailedId);
wrapper.disconnect(wrapper._deviceStateChangedId);
wrapper.disconnect(wrapper._destroyId);
});
return wrapper;
},
_deviceAdded: function(client, device) {
if (device._delegate) {
// already seen, not adding again
@ -1796,8 +1725,24 @@ const NMApplet = new Lang.Class({
}
let wrapperClass = this._dtypes[device.get_device_type()];
if (wrapperClass) {
let wrapper = this._makeWrapperDevice(wrapperClass, device);
let wrapper = new wrapperClass(this._client, device, this._connections);
wrapper._activationFailedId = wrapper.connect('activation-failed', Lang.bind(this, function(device, reason) {
// XXX: nm-applet has no special text depending on reason
// but I'm not sure of this generic message
this._notifyForDevice(device, 'network-error',
_("Connection failed"),
_("Activation of network connection failed"),
MessageTray.Urgency.HIGH);
}));
wrapper._deviceStateChangedId = wrapper.connect('state-changed', Lang.bind(this, function(dev) {
this._syncSectionTitle(dev.category);
}));
wrapper._destroyId = wrapper.connect('destroy', function(wrapper) {
wrapper.disconnect(wrapper._activationFailedId);
wrapper.disconnect(wrapper._deviceStateChangedId);
wrapper.disconnect(wrapper._destroyId);
});
let section = this._devices[wrapper.category].section;
let devices = this._devices[wrapper.category].devices;
@ -1933,7 +1878,7 @@ const NMApplet = new Lang.Class({
let connections = this._settings.list_connections();
for (let i = 0; i < connections.length; i++) {
let connection = connections[i];
if (connection._updatedId) {
if (connection._uuid) {
// connection was already seen (for example because NetworkManager was restarted)
continue;
}
@ -1946,7 +1891,7 @@ const NMApplet = new Lang.Class({
},
_newConnection: function(settings, connection) {
if (connection._updatedId) {
if (connection._uuid) {
// connection was already seen
return;
}
@ -1969,31 +1914,35 @@ const NMApplet = new Lang.Class({
if (section == NMConnectionCategory.VPN) {
this._devices.vpn.device.removeConnection(connection);
this._syncSectionTitle(section);
if (this._devices.vpn.device.empty)
this._devices.vpn.section.actor.hide();
} else if (section != NMConnectionCategory.INVALID) {
let devices = this._devices[section].devices;
for (let i = 0; i < devices.length; i++)
devices[i].removeConnection(connection);
}
connection._uuid = null;
connection.disconnect(connection._removedId);
connection.disconnect(connection._updatedId);
connection._removedId = connection._updatedId = 0;
},
_updateConnection: function(connection) {
let connectionSettings = connection.get_setting_by_name(NetworkManager.SETTING_CONNECTION_SETTING_NAME);
connection._type = connectionSettings.type;
connection._section = this._ctypes[connection._type] || NMConnectionCategory.INVALID;
connection._name = connectionSettings.id;
connection._uuid = connectionSettings.uuid;
connection._timestamp = connectionSettings.timestamp;
let section = connection._section;
if (section == NMConnectionCategory.INVALID)
if (connection._section == NMConnectionCategory.INVALID)
return;
if (section == NMConnectionCategory.VPN) {
this._devices.vpn.device.checkConnection(connection);
this._syncSectionTitle(section);
this._devices.vpn.section.actor.show();
} else {
let devices = this._devices[section].devices;
for (let i = 0; i < devices.length; i++) {
@ -2016,10 +1965,12 @@ const NMApplet = new Lang.Class({
this._statusSection.actor.hide();
this._syncSectionTitle(NMConnectionCategory.WIRED);
this._syncSectionTitle(NMConnectionCategory.WIRELESS);
this._syncSectionTitle(NMConnectionCategory.WWAN);
this._syncSectionTitle(NMConnectionCategory.VPN);
this._syncSectionTitle('wired');
this._syncSectionTitle('wireless');
this._syncSectionTitle('wwan');
if (!this._devices.vpn.device.empty)
this._devices.vpn.section.actor.show();
},
_syncNMState: function() {

View File

@ -212,7 +212,7 @@ const DeviceItem = new Lang.Class({
case UPDeviceType.COMPUTER:
return _("Computer");
default:
return C_("device", "Unknown");
return _("Unknown");
}
}
});

View File

@ -420,13 +420,14 @@ const ChatSource = new Lang.Class({
Extends: MessageTray.Source,
_init: function(account, conn, channel, contact, client) {
this.isChat = true;
this._account = account;
this._contact = contact;
this._client = client;
this.parent(contact.get_alias());
this.isChat = true;
this._pendingMessages = [];
this._conn = conn;
@ -509,10 +510,10 @@ const ChatSource = new Lang.Class({
_getLogMessages: function() {
let logManager = Tpl.LogManager.dup_singleton();
let entity = Tpl.Entity.new_from_tp_contact(this._contact, Tpl.EntityType.CONTACT);
logManager.get_filtered_events_async(this._account, entity,
Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES,
null, Lang.bind(this, this._displayPendingMessages));
Shell.get_contact_events(logManager,
this._account, entity,
SCROLLBACK_HISTORY_LINES,
Lang.bind(this, this._displayPendingMessages));
},
_displayPendingMessages: function(logManager, result) {

363
js/ui/unlockDialog.js Normal file
View File

@ -0,0 +1,363 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const AccountsService = imports.gi.AccountsService;
const Clutter = imports.gi.Clutter;
const GdmGreeter = imports.gi.GdmGreeter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const ModalDialog = imports.ui.modalDialog;
const Fprint = imports.gdm.fingerprint;
const GdmLoginDialog = imports.gdm.loginDialog;
function _fadeInActor(actor) {
if (actor.opacity == 255 && actor.visible)
return;
actor.show();
let [minHeight, naturalHeight] = actor.get_preferred_height(-1);
actor.opacity = 0;
actor.set_height(0);
Tweener.addTween(actor,
{ opacity: 255,
height: naturalHeight,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: function() {
this.set_height(-1);
},
});
}
function _fadeOutActor(actor) {
if (!actor.visible || actor.opacity == 0) {
actor.opacity = 0;
actor.hide();
}
Tweener.addTween(actor,
{ opacity: 0,
height: 0,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: function() {
this.hide();
this.set_height(-1);
},
});
}
// A widget showing the user avatar and name
const UserWidget = new Lang.Class({
Name: 'UserWidget',
_init: function(user) {
this._user = user;
this.actor = new St.BoxLayout({ style_class: 'status-chooser',
vertical: false,
reactive: false
});
this._iconBin = new St.Bin({ style_class: 'status-chooser-user-icon' });
this.actor.add(this._iconBin,
{ x_fill: true,
y_fill: true });
this._label = new St.Label({ style_class: 'login-dialog-prompt-label',
// FIXME:
style: 'text-align: right' });
this.actor.add(this._label,
{ expand: true,
x_fill: true,
y_fill: true
});
this._userLoadedId = this._user.connect('notify::is-loaded',
Lang.bind(this,
this._updateUser));
this._userChangedId = this._user.connect('changed',
Lang.bind(this,
this._updateUser));
this.actor.connect('notify::mapped', Lang.bind(this, function() {
if (this.actor.mapped)
this._updateUser();
}));
},
destroy: function() {
// clean up signal handlers
if (this._userLoadedId != 0) {
this._user.disconnect(this._userLoadedId);
this._userLoadedId = 0;
}
if (this._userChangedId != 0) {
this._user.disconnect(this._userChangedId);
this._userChangedId = 0;
}
this.actor.destroy();
},
_updateUser: function() {
let iconFile = null;
if (this._user.is_loaded) {
this._label.text = this._user.get_real_name();
iconFile = this._user.get_icon_file();
if (!GLib.file_test(iconFile, GLib.FileTest.EXISTS))
iconFile = null;
} else {
this._label.text = "";
}
if (iconFile)
this._setIconFromFile(iconFile);
else
this._setIconFromName('avatar-default');
},
// XXX: a GFileIcon instead?
_setIconFromFile: function(iconFile) {
this._iconBin.set_style('background-image: url("' + iconFile + '");' +
'background-size: contain;');
this._iconBin.child = null;
},
_setIconFromName: function(iconName) {
this._iconBin.set_style(null);
if (iconName != null) {
let icon = new St.Icon({ icon_name: iconName,
icon_type: St.IconType.SYMBOLIC,
icon_size: DIALOG_ICON_SIZE });
this._iconBin.child = icon;
this._iconBin.show();
} else {
this._iconBin.child = null;
this._iconBin.hide();
}
}
});
const UnlockDialog = new Lang.Class({
Name: 'UnlockDialog',
Extends: ModalDialog.ModalDialog,
_init: function() {
this.parent({ shellReactive: true,
styleClass: 'login-dialog' });
this._userManager = AccountsService.UserManager.get_default();
this._userName = GLib.get_user_name();
this._user = this._userManager.get_user(this._userName);
this._greeterClient = GdmGreeter.Server.new_for_display_sync(null, null);
this._greeterClient.call_start_conversation_sync(GdmLoginDialog.PASSWORD_SERVICE_NAME, null);
this._greeterClient.connect('reset',
Lang.bind(this, this._onReset));
this._greeterClient.connect('ready',
Lang.bind(this, this._onReady));
this._greeterClient.connect('info',
Lang.bind(this, this._onInfo));
this._greeterClient.connect('problem',
Lang.bind(this, this._onProblem));
this._greeterClient.connect('info-query',
Lang.bind(this, this._onInfoQuery));
this._greeterClient.connect('secret-info-query',
Lang.bind(this, this._onSecretInfoQuery));
this._greeterClient.connect('session-opened',
Lang.bind(this, this._onSessionOpened));
this._greeterClient.connect('conversation-stopped',
Lang.bind(this, this._onConversationStopped));
this._fprintManager = new Fprint.FprintManager();
this._startFingerprintConversationIfNeeded();
this._userWidget = new UserWidget(this._user);
this.contentLayout.add_actor(this._userWidget.actor);
this._promptLayout = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
vertical: false
});
this._promptLabel = new St.Label({ style_class: 'login-dialog-prompt-label' });
this._promptLayout.add(this._promptLabel,
{ expand: false,
x_fill: true,
y_fill: true,
x_align: St.Align.START });
this._promptEntry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
can_focus: true });
this._promptLayout.add(this._promptEntry,
{ expand: true,
x_fill: true,
y_fill: false,
x_align: St.Align.START });
this.contentLayout.add_actor(this._promptLayout);
// Translators: this message is shown below the password entry field
// to indicate the user can swipe their finger instead
this._promptFingerprintMessage = new St.Label({ text: _("(or swipe finger)"),
style_class: 'login-dialog-prompt-fingerprint-message' });
this._promptFingerprintMessage.hide();
this.contentLayout.add_actor(this._promptFingerprintMessage);
this._okButton = { label: _("Unlock"),
action: Lang.bind(this, this._doUnlock),
key: Clutter.KEY_Return,
};
this.setButtons([this._okButton]);
this._updateOkButton(true);
},
_updateOkButton: function(sensitive) {
this._okButton.button.reactive = sensitive;
this._okButton.button.can_focus = sensitive;
if (sensitive)
this._okButton.button.remove_style_pseudo_class('disabled');
else
this._okButton.button.add_style_pseudo_class('disabled');
},
_onReset: function() {
// I'm not sure this is emitted for external greeters...
this._greeterClient.call_start_conversation_sync(GdmLoginDialog.PASSWORD_SERVICE_NAME, null);
this._startFingerprintConversationIfNeeded();
},
_startFingerprintConversationIfNeeded: function() {
this._haveFingerprintReader = false;
// FIXME: the greeter has a GSettings key for disabling fingerprint auth
this._fprintManager.GetDefaultDeviceRemote(Lang.bind(this,
function(device, error) {
if (!error && device)
this._haveFingerprintReader = true;
if (this._haveFingerprintReader)
this._greeterClient.call_start_conversation_sync(GdmLoginDialog.FINGERPRINT_SERVICE_NAME, null);
}));
},
_onReady: function(greeter, serviceName) {
greeter.call_begin_verification_for_user_sync(serviceName, this._userName, null);
},
_onInfo: function(greeter, serviceName, info) {
// We don't display fingerprint messages, because they
// have words like UPEK in them. Instead we use the messages
// as a cue to display our own message.
if (serviceName == GdmLoginDialog.FINGERPRINT_SERVICE_NAME &&
this._haveFingerprintReader &&
(!this._promptFingerprintMessage.visible ||
this._promptFingerprintMessage.opacity != 255)) {
_fadeInActor(this._promptFingerprintMessage);
return;
}
if (serviceName != GdmLoginDialog.PASSWORD_SERVICE_NAME)
return;
Main.notify(info);
},
_onProblem: function(client, serviceName, problem) {
// we don't want to show auth failed messages to
// users who haven't enrolled their fingerprint.
if (serviceName != GdmLoginDialog.PASSWORD_SERVICE_NAME)
return;
Main.notifyError(problem);
},
_onInfoQuery: function(client, serviceName, question) {
// We only expect questions to come from the main auth service
if (serviceName != GdmLoginDialog.PASSWORD_SERVICE_NAME)
return;
this._promptLabel.text = question;
this._promptEntry.text = '';
this._promptEntry.clutter_text.set_password_char('');
this._currentQuery = serviceName;
this._updateOkButton(true);
},
_onSecretInfoQuery: function(client, serviceName, secretQuestion) {
// We only expect secret requests to come from the main auth service
if (serviceName != GdmLoginDialog.PASSWORD_SERVICE_NAME)
return;
this._promptLabel.text = secretQuestion;
this._promptEntry.text = '';
this._promptEntry.clutter_text.set_password_char('\u25cf');
this._currentQuery = serviceName;
this._updateOkButton(true);
},
_doUnlock: function() {
if (!this._currentQuery)
return;
let query = this._currentQuery;
this._currentQuery = null;
this._updateOkButton(false);
this._greeterClient.call_answer_query_sync(query, this._promptEntry.text, null);
},
_onConversationStopped: function(client, serviceName) {
// if the password service fails, then cancel everything.
// But if, e.g., fingerprint fails, still give
// password authentication a chance to succeed
if (serviceName == GdmLoginDialog.PASSWORD_SERVICE_NAME) {
this._greeterClient.call_cancel_sync(null);
this.emit('failed');
} else if (serviceName == GdmLoginDialog.FINGERPRINT_SERVICE_NAME) {
_fadeOutActor(this._promptFingerprintMessage);
}
},
_onSessionOpened: function(client, serviceName) {
// For external greeters, SessionOpened means we succeded
// in the authentication process
// Close the greeter proxy
this._greeterClient.run_dispose();
this._greeterClient = null;
this.emit('unlocked');
},
destroy: function() {
if (this._greeterClient) {
this._greeterClient.run_dispose();
this._greeterClient = null;
}
this.parent();
},
cancel: function() {
this._greeterClient.call_cancel_sync(null);
this.destroy();
},
});

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const AccountsService = imports.gi.AccountsService;
const GdmGreeter = imports.gi.GdmGreeter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
@ -474,22 +473,13 @@ const UserMenuButton = new Lang.Class({
style_class: 'popup-menu-icon' });
this._idleIcon = new St.Icon({ icon_name: 'user-idle',
style_class: 'popup-menu-icon' });
this._pendingIcon = new St.Icon({ icon_name: 'user-status-pending',
style_class: 'popup-menu-icon' });
this._accountMgr.connect('most-available-presence-changed',
Lang.bind(this, this._updatePresenceIcon));
this._accountMgr.connect('account-enabled',
Lang.bind(this, this._onAccountEnabled));
this._accountMgr.connect('account-disabled',
Lang.bind(this, this._onAccountDisabled));
this._accountMgr.connect('account-removed',
Lang.bind(this, this._onAccountDisabled));
this._accountMgr.prepare_async(null, Lang.bind(this,
function(mgr) {
let [presence, s, msg] = mgr.get_most_available_presence();
this._updatePresenceIcon(mgr, presence, s, msg);
this._setupAccounts();
}));
this._name = new St.Label();
@ -559,20 +549,14 @@ const UserMenuButton = new Lang.Class({
_updateSwitchUser: function() {
let allowSwitch = !this._lockdownSettings.get_boolean(DISABLE_USER_SWITCH_KEY);
let multiUser = this._userManager.can_switch() && this._userManager.has_multiple_users;
let multiSession = GdmGreeter.get_session_ids().length > 1;
this._loginScreenItem.label.set_text(multiUser ? _("Switch User")
: _("Switch Session"));
this._loginScreenItem.actor.visible = allowSwitch && (multiUser || multiSession);
this._loginScreenItem.actor.visible = allowSwitch &&
this._userManager.can_switch() &&
this._userManager.has_multiple_users;
},
_updateLogout: function() {
let allowLogout = !this._lockdownSettings.get_boolean(DISABLE_LOG_OUT_KEY);
let multiUser = this._userManager.has_multiple_users;
let multiSession = GdmGreeter.get_session_ids().length > 1;
this._logoutItem.actor.visible = allowLogout && (multiUser || multiSession);
this._logoutItem.actor.visible = allowLogout && this._userManager.has_multiple_users;
},
_updateLockScreen: function() {
@ -629,52 +613,11 @@ const UserMenuButton = new Lang.Class({
this._iconBox.child = this._offlineIcon;
},
_setupAccounts: function() {
let accounts = this._accountMgr.get_valid_accounts();
for (let i = 0; i < accounts.length; i++) {
accounts[i]._changingId = accounts[i].connect('notify::connection-status',
Lang.bind(this, this._updateChangingPresence));
}
this._updateChangingPresence();
},
_onAccountEnabled: function(accountMgr, account) {
if (!account._changingId)
account._changingId = account.connect('notify::connection-status',
Lang.bind(this, this._updateChangingPresence));
this._updateChangingPresence();
},
_onAccountDisabled: function(accountMgr, account) {
account.disconnect(account._changingId);
account._changingId = 0;
this._updateChangingPresence();
},
_updateChangingPresence: function() {
let accounts = this._accountMgr.get_valid_accounts();
let changing = false;
for (let i = 0; i < accounts.length; i++) {
if (accounts[i].connection_status == Tp.ConnectionStatus.CONNECTING) {
changing = true;
break;
}
}
if (changing) {
this._iconBox.child = this._pendingIcon;
} else {
let [presence, s, msg] = this._accountMgr.get_most_available_presence();
this._updatePresenceIcon(this._accountMgr, presence, s, msg);
}
},
_createSubMenu: function() {
let item;
item = new IMStatusChooserItem();
if (Main.sessionMode.allowSettings)
item.connect('activate', Lang.bind(this, this._onMyAccountActivate));
item.connect('activate', Lang.bind(this, this._onMyAccountActivate));
this.menu.addMenuItem(item);
this._statusChooser = item;
@ -686,11 +629,9 @@ const UserMenuButton = new Lang.Class({
item = new PopupMenu.PopupSeparatorMenuItem();
this.menu.addMenuItem(item);
if (Main.sessionMode.allowSettings) {
item = new PopupMenu.PopupMenuItem(_("System Settings"));
item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
this.menu.addMenuItem(item);
}
item = new PopupMenu.PopupMenuItem(_("System Settings"));
item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
this.menu.addMenuItem(item);
item = new PopupMenu.PopupAlternatingMenuItem(_("Power Off"),
_("Suspend"));

View File

@ -301,7 +301,8 @@ const WindowClone = new Lang.Class({
if (!this._zoomLightbox)
this._zoomLightbox = new Lightbox.Lightbox(Main.uiGroup,
{ fadeTime: LIGHTBOX_FADE_TIME });
{ fadeInTime: LIGHTBOX_FADE_TIME,
fadeOutTime: LIGHTBOX_FADE_TIME });
this._zoomLightbox.show();
this._zoomLocalOrig = new ScaledPoint(this.actor.x, this.actor.y, this.actor.scale_x, this.actor.scale_y);

View File

@ -529,11 +529,9 @@ const WorkspacesDisplay = new Lang.Class({
this._updateAlwaysZoom();
}));
global.screen.connect('notify::n-workspaces',
Lang.bind(this, this._workspacesChanged));
this._switchWorkspaceNotifyId = 0;
this._nWorkspacesChangedId = 0;
this._itemDragBeginId = 0;
this._itemDragCancelledId = 0;
this._itemDragEndId = 0;
@ -572,6 +570,9 @@ const WorkspacesDisplay = new Lang.Class({
global.screen.connect('restacked',
Lang.bind(this, this._onRestacked));
if (this._nWorkspacesChangedId == 0)
this._nWorkspacesChangedId = global.screen.connect('notify::n-workspaces',
Lang.bind(this, this._workspacesChanged));
if (this._itemDragBeginId == 0)
this._itemDragBeginId = Main.overview.connect('item-drag-begin',
Lang.bind(this, this._dragBegin));
@ -924,16 +925,19 @@ const WorkspacesDisplay = new Lang.Class({
},
_workspacesChanged: function() {
let oldNumWorkspaces = this._workspaces[0].length;
let newNumWorkspaces = global.screen.n_workspaces;
let active = global.screen.get_active_workspace_index();
if (oldNumWorkspaces == newNumWorkspaces)
return;
this._updateAlwaysZoom();
this._updateZoom();
if (this._workspacesViews == null)
return;
let oldNumWorkspaces = this._workspaces[0].length;
let newNumWorkspaces = global.screen.n_workspaces;
let active = global.screen.get_active_workspace_index();
let lostWorkspaces = [];
if (newNumWorkspaces > oldNumWorkspaces) {
let monitors = Main.layoutManager.monitors;

397
po/es.po

File diff suppressed because it is too large Load Diff

345
po/gl.po
View File

@ -12,8 +12,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-03 15:02+0200\n"
"PO-Revision-Date: 2012-06-03 15:02+0200\n"
"POT-Creation-Date: 2012-05-11 11:31+0200\n"
"PO-Revision-Date: 2012-05-11 11:31+0200\n"
"Last-Translator: Fran Dieguez <frandieguez@gnome.org>\n"
"Language-Team: Galician <gnome-l10n-gl@gnome.org>\n"
"Language: gl\n"
@ -21,7 +21,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
"X-Generator: Gtranslator 2.91.4\n"
"X-Generator: Lokalize 1.2\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
@ -269,8 +269,8 @@ msgid "Not listed?"
msgstr "Non está na lista?"
#: ../js/gdm/loginDialog.js:1023 ../js/ui/endSessionDialog.js:401
#: ../js/ui/extensionSystem.js:375 ../js/ui/networkAgent.js:153
#: ../js/ui/polkitAuthenticationAgent.js:175 ../js/ui/status/bluetooth.js:431
#: ../js/ui/extensionSystem.js:400 ../js/ui/networkAgent.js:153
#: ../js/ui/polkitAuthenticationAgent.js:175 ../js/ui/status/bluetooth.js:459
msgid "Cancel"
msgstr "Cancelar"
@ -283,8 +283,8 @@ msgstr "Iniciar sesión"
msgid "Login Window"
msgstr "Xanela de inicio de sesión"
#: ../js/gdm/powerMenu.js:130 ../js/ui/userMenu.js:604
#: ../js/ui/userMenu.js:608 ../js/ui/userMenu.js:696
#: ../js/gdm/powerMenu.js:130 ../js/ui/userMenu.js:588
#: ../js/ui/userMenu.js:592 ../js/ui/userMenu.js:637
msgid "Suspend"
msgstr "Suspender"
@ -292,8 +292,8 @@ msgstr "Suspender"
msgid "Restart"
msgstr "Reiniciar"
#: ../js/gdm/powerMenu.js:140 ../js/ui/userMenu.js:606
#: ../js/ui/userMenu.js:608 ../js/ui/userMenu.js:695
#: ../js/gdm/powerMenu.js:140 ../js/ui/userMenu.js:590
#: ../js/ui/userMenu.js:592 ../js/ui/userMenu.js:636
msgid "Power Off"
msgstr "Apagar"
@ -351,12 +351,12 @@ msgstr "%s foi eliminado dos seus favoritos."
msgid "Removable Devices"
msgstr "Dispositivos extraíbeis"
#: ../js/ui/autorunManager.js:553
#: ../js/ui/autorunManager.js:560
#, c-format
msgid "Open with %s"
msgstr "Abrir con %s"
#: ../js/ui/autorunManager.js:579
#: ../js/ui/autorunManager.js:586
msgid "Eject"
msgstr "Expulsar"
@ -506,20 +506,20 @@ msgstr "Esta semana"
msgid "Next week"
msgstr "A vindeira semana"
#: ../js/ui/contactDisplay.js:66
msgctxt "contact"
#: ../js/ui/contactDisplay.js:66 ../js/ui/notificationDaemon.js:486
#: ../js/ui/status/power.js:215 ../src/shell-app.c:374
msgid "Unknown"
msgstr "Descoñecido"
#: ../js/ui/contactDisplay.js:89 ../js/ui/userMenu.js:130
#: ../js/ui/contactDisplay.js:89 ../js/ui/userMenu.js:129
msgid "Available"
msgstr "Dispoñíbel"
#: ../js/ui/contactDisplay.js:94 ../js/ui/userMenu.js:139
#: ../js/ui/contactDisplay.js:94 ../js/ui/userMenu.js:138
msgid "Away"
msgstr "Ausente"
#: ../js/ui/contactDisplay.js:98 ../js/ui/userMenu.js:133
#: ../js/ui/contactDisplay.js:98 ../js/ui/userMenu.js:132
msgid "Busy"
msgstr "Ocupado"
@ -531,62 +531,62 @@ msgstr "Desconectado"
msgid "CONTACTS"
msgstr "CONTACTOS"
#: ../js/ui/dash.js:239 ../js/ui/messageTray.js:1239
#: ../js/ui/dash.js:239 ../js/ui/messageTray.js:1209
msgid "Remove"
msgstr "Quitar"
#: ../js/ui/dateMenu.js:101
#: ../js/ui/dateMenu.js:103
msgid "Date and Time Settings"
msgstr "Preferencias de data e hora"
#: ../js/ui/dateMenu.js:127
#: ../js/ui/dateMenu.js:129
msgid "Open Calendar"
msgstr "Abrir o calendario"
#. Translators: This is the time format with date used
#. in 24-hour mode.
#: ../js/ui/dateMenu.js:185
#: ../js/ui/dateMenu.js:187
msgid "%a %b %e, %R:%S"
msgstr "%a %e de %b, %R:%S"
#: ../js/ui/dateMenu.js:186
#: ../js/ui/dateMenu.js:188
msgid "%a %b %e, %R"
msgstr "%a %e de %b, %R"
#. Translators: This is the time format without date used
#. in 24-hour mode.
#: ../js/ui/dateMenu.js:190
#: ../js/ui/dateMenu.js:192
msgid "%a %R:%S"
msgstr "%a %R:%S"
#: ../js/ui/dateMenu.js:191
#: ../js/ui/dateMenu.js:193
msgid "%a %R"
msgstr "%a %R"
#. Translators: This is a time format with date used
#. for AM/PM.
#: ../js/ui/dateMenu.js:198
#: ../js/ui/dateMenu.js:200
msgid "%a %b %e, %l:%M:%S %p"
msgstr "%a %e de %b, %l:%M:%S"
#: ../js/ui/dateMenu.js:199
#: ../js/ui/dateMenu.js:201
msgid "%a %b %e, %l:%M %p"
msgstr "%a %e de %b, %l:%M %p"
#. Translators: This is a time format without date used
#. for AM/PM.
#: ../js/ui/dateMenu.js:203
#: ../js/ui/dateMenu.js:205
msgid "%a %l:%M:%S %p"
msgstr "%a %l:%M:%S %p"
#: ../js/ui/dateMenu.js:204
#: ../js/ui/dateMenu.js:206
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#. 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:217
msgid "%A %B %e, %Y"
msgstr "%a, %e de %B, %Y"
@ -680,11 +680,11 @@ msgstr[1] "O seu computador reiniciarase automaticamente en %d segundos."
msgid "Restarting the system."
msgstr "Reiniciando o sistema."
#: ../js/ui/extensionSystem.js:379
#: ../js/ui/extensionSystem.js:404
msgid "Install"
msgstr "Instalar"
#: ../js/ui/extensionSystem.js:383
#: ../js/ui/extensionSystem.js:408
#, c-format
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "Desexa descargar e instalar «%s» desde extensions.gnome.org?"
@ -693,7 +693,7 @@ msgstr "Desexa descargar e instalar «%s» desde extensions.gnome.org?"
msgid "tray"
msgstr "área de notificación"
#: ../js/ui/keyboard.js:545 ../js/ui/status/keyboard.js:42
#: ../js/ui/keyboard.js:544 ../js/ui/status/keyboard.js:44
#: ../js/ui/status/power.js:203
msgid "Keyboard"
msgstr "Teclado"
@ -755,24 +755,24 @@ msgid "Web Page"
msgstr "Páxina web"
#. Translators: this is a filename used for screencast recording
#: ../js/ui/main.js:126
#: ../js/ui/main.js:118
#, no-c-format
msgid "Screencast from %d %t"
msgstr "Screencast desde %d %t"
#: ../js/ui/messageTray.js:1232
#: ../js/ui/messageTray.js:1202
msgid "Open"
msgstr "Abrir"
#: ../js/ui/messageTray.js:1249
#: ../js/ui/messageTray.js:1219
msgid "Unmute"
msgstr "Desactivar silencio"
#: ../js/ui/messageTray.js:1249
#: ../js/ui/messageTray.js:1219
msgid "Mute"
msgstr "Silenciar"
#: ../js/ui/messageTray.js:2522
#: ../js/ui/messageTray.js:2492
msgid "System Information"
msgstr "Información do sistema"
@ -857,44 +857,39 @@ msgstr "Contrasinal da rede de banda larga móbil"
msgid "A password is required to connect to '%s'."
msgstr "Requírese un contrasinal para conectarse a «%s»."
#: ../js/ui/notificationDaemon.js:486 ../src/shell-app.c:374
msgctxt "program"
msgid "Unknown"
msgstr "Descoñecido"
#: ../js/ui/overview.js:90
msgid "Undo"
msgstr "Desfacer"
#: ../js/ui/overview.js:130
#: ../js/ui/overview.js:132
msgid "Overview"
msgstr "Vista xeral"
#: ../js/ui/overview.js:200
#: ../js/ui/overview.js:202
msgid "Windows"
msgstr "Xanelas"
#: ../js/ui/overview.js:203
#: ../js/ui/overview.js:205
msgid "Applications"
msgstr "Aplicativos"
#. Translators: this is the name of the dock/favorites area on
#. the left of the overview
#: ../js/ui/overview.js:229
#: ../js/ui/overview.js:231
msgid "Dash"
msgstr "Taboleiro"
#: ../js/ui/panel.js:564
#: ../js/ui/panel.js:592
msgid "Quit"
msgstr "Saír"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:596
#: ../js/ui/panel.js:624
msgid "Activities"
msgstr "Actividades"
#: ../js/ui/panel.js:962
#: ../js/ui/panel.js:999
msgid "Top Bar"
msgstr "Barra superior"
@ -948,11 +943,11 @@ msgstr "toggle-switch-intl"
msgid "Please enter a command:"
msgstr "Escriba unha orde:"
#: ../js/ui/searchDisplay.js:323
#: ../js/ui/searchDisplay.js:321
msgid "Searching..."
msgstr "Buscando…"
#: ../js/ui/searchDisplay.js:376
#: ../js/ui/searchDisplay.js:374
msgid "No matching results."
msgstr "Non hai resultados que coincidan."
@ -972,7 +967,7 @@ msgstr "Mostrar texto"
msgid "Hide Text"
msgstr "Ocultar texto"
#: ../js/ui/shellMountOperation.js:272
#: ../js/ui/shellMountOperation.js:271
msgid "Wrong password, please try again"
msgstr "Contrasinal incorrecto, ténteo de novo"
@ -1024,9 +1019,9 @@ msgid "Large Text"
msgstr "Texto grande"
#: ../js/ui/status/bluetooth.js:31 ../js/ui/status/bluetooth.js:35
#: ../js/ui/status/bluetooth.js:255 ../js/ui/status/bluetooth.js:308
#: ../js/ui/status/bluetooth.js:339 ../js/ui/status/bluetooth.js:375
#: ../js/ui/status/bluetooth.js:404 ../js/ui/status/network.js:889
#: ../js/ui/status/bluetooth.js:255 ../js/ui/status/bluetooth.js:338
#: ../js/ui/status/bluetooth.js:368 ../js/ui/status/bluetooth.js:404
#: ../js/ui/status/bluetooth.js:433 ../js/ui/status/network.js:890
msgid "Bluetooth"
msgstr "Bluetooth"
@ -1055,12 +1050,11 @@ msgstr "hardware desactivado"
msgid "Connection"
msgstr "Conexión"
#: ../js/ui/status/bluetooth.js:211 ../js/ui/status/network.js:490
#: ../js/ui/status/bluetooth.js:211 ../js/ui/status/network.js:491
msgid "disconnecting..."
msgstr "desconectando…"
#: ../js/ui/status/bluetooth.js:224 ../js/ui/status/network.js:496
#: ../js/ui/status/network.js:956
#: ../js/ui/status/bluetooth.js:224 ../js/ui/status/network.js:497
msgid "connecting..."
msgstr "conectando…"
@ -1093,69 +1087,69 @@ msgstr "Preferencias do rato"
msgid "Sound Settings"
msgstr "Preferencias do son"
#: ../js/ui/status/bluetooth.js:340
#: ../js/ui/status/bluetooth.js:369
#, c-format
msgid "Authorization request from %s"
msgstr "Solicitude de autorización de %s"
#: ../js/ui/status/bluetooth.js:346
#: ../js/ui/status/bluetooth.js:375
#, c-format
msgid "Device %s wants access to the service '%s'"
msgstr "O dispositivo %s quere acceder ao servizo «%s»"
#: ../js/ui/status/bluetooth.js:348
#: ../js/ui/status/bluetooth.js:377
msgid "Always grant access"
msgstr "Conceder acceso sempre"
#: ../js/ui/status/bluetooth.js:349
#: ../js/ui/status/bluetooth.js:378
msgid "Grant this time only"
msgstr "Conceder só esta vez"
#: ../js/ui/status/bluetooth.js:350 ../js/ui/telepathyClient.js:1090
#: ../js/ui/status/bluetooth.js:379 ../js/ui/telepathyClient.js:1093
msgid "Reject"
msgstr "Rexeitar"
#: ../js/ui/status/bluetooth.js:376
#: ../js/ui/status/bluetooth.js:405
#, c-format
msgid "Pairing confirmation for %s"
msgstr "Confirmación de emparellado para «%s»"
#: ../js/ui/status/bluetooth.js:382 ../js/ui/status/bluetooth.js:412
#: ../js/ui/status/bluetooth.js:411 ../js/ui/status/bluetooth.js:441
#, c-format
msgid "Device %s wants to pair with this computer"
msgstr "O dispositivo «%s» quere emparellarse con este equipo"
#: ../js/ui/status/bluetooth.js:383
#: ../js/ui/status/bluetooth.js:412
#, c-format
msgid "Please confirm whether the PIN '%06d' matches the one on the device."
msgstr "Confirme que o PIN «%06d» coincide co mostrado no dispositivo."
msgid "Please confirm whether the PIN '%s' matches the one on the device."
msgstr "Confirme que o PIN mostrado en «%s» coincide co do dispositivo."
#: ../js/ui/status/bluetooth.js:385
#: ../js/ui/status/bluetooth.js:414
msgid "Matches"
msgstr "Coincide"
#: ../js/ui/status/bluetooth.js:386
#: ../js/ui/status/bluetooth.js:415
msgid "Does not match"
msgstr "Non coincide"
#: ../js/ui/status/bluetooth.js:405
#: ../js/ui/status/bluetooth.js:434
#, c-format
msgid "Pairing request for %s"
msgstr "Solicitude de emparellamento para «%s»"
#: ../js/ui/status/bluetooth.js:413
#: ../js/ui/status/bluetooth.js:442
msgid "Please enter the PIN mentioned on the device."
msgstr "Escriba o PIN mencionado no dispositivo."
#: ../js/ui/status/bluetooth.js:430
#: ../js/ui/status/bluetooth.js:458
msgid "OK"
msgstr "Aceptar"
#: ../js/ui/status/keyboard.js:69
#: ../js/ui/status/keyboard.js:68
msgid "Show Keyboard Layout"
msgstr "Mostrar a distribución do teclado"
#: ../js/ui/status/keyboard.js:71
#: ../js/ui/status/keyboard.js:73
msgid "Region and Language Settings"
msgstr "Configuración rexional e de idioma"
@ -1170,116 +1164,116 @@ msgstr "desactivada"
#. Translators: this is for network devices that are physically present but are not
#. under NetworkManager's control (and thus cannot be used in the menu)
#: ../js/ui/status/network.js:488
#: ../js/ui/status/network.js:489
msgid "unmanaged"
msgstr "non xestionada"
#. Translators: this is for network connections that require some kind of key or password
#: ../js/ui/status/network.js:499 ../js/ui/status/network.js:959
#: ../js/ui/status/network.js:500
msgid "authentication required"
msgstr "requírese autenticación"
#. Translators: this is for devices that require some kind of firmware or kernel
#. module, which is missing
#: ../js/ui/status/network.js:509
#: ../js/ui/status/network.js:510
msgid "firmware missing"
msgstr "falta o «firmware»"
#. Translators: this is for wired network devices that are physically disconnected
#: ../js/ui/status/network.js:516
#: ../js/ui/status/network.js:517
msgid "cable unplugged"
msgstr "cable desconectado"
#. Translators: this is for a network device that cannot be activated (for example it
#. is disabled by rfkill, or it has no coverage
#: ../js/ui/status/network.js:521
#: ../js/ui/status/network.js:522
msgid "unavailable"
msgstr "non dispoñíbel"
#: ../js/ui/status/network.js:523 ../js/ui/status/network.js:961
#: ../js/ui/status/network.js:524
msgid "connection failed"
msgstr "conexión fallida"
#: ../js/ui/status/network.js:584 ../js/ui/status/network.js:1537
#: ../js/ui/status/network.js:585 ../js/ui/status/network.js:1497
msgid "More..."
msgstr "Máis…"
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
#. and we cannot access its settings (including the name)
#: ../js/ui/status/network.js:620 ../js/ui/status/network.js:1472
#: ../js/ui/status/network.js:621 ../js/ui/status/network.js:1432
msgid "Connected (private)"
msgstr "Conectada (privada)"
#: ../js/ui/status/network.js:695
#: ../js/ui/status/network.js:696
msgid "Auto Ethernet"
msgstr "Ethernet automática"
#: ../js/ui/status/network.js:753
#: ../js/ui/status/network.js:754
msgid "Auto broadband"
msgstr "Banda larga automática"
#: ../js/ui/status/network.js:756
#: ../js/ui/status/network.js:757
msgid "Auto dial-up"
msgstr "Marcado automático"
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
#: ../js/ui/status/network.js:875 ../js/ui/status/network.js:1484
#: ../js/ui/status/network.js:876 ../js/ui/status/network.js:1444
#, c-format
msgid "Auto %s"
msgstr "%s automática"
#: ../js/ui/status/network.js:877
#: ../js/ui/status/network.js:878
msgid "Auto bluetooth"
msgstr "Bluetooth automática"
#: ../js/ui/status/network.js:1486
#: ../js/ui/status/network.js:1446
msgid "Auto wireless"
msgstr "Sen fíos automática"
#: ../js/ui/status/network.js:1573
#: ../js/ui/status/network.js:1533
msgid "Network"
msgstr "Rede"
#: ../js/ui/status/network.js:1580
#: ../js/ui/status/network.js:1540
msgid "Enable networking"
msgstr "Activar rede"
#: ../js/ui/status/network.js:1601
#: ../js/ui/status/network.js:1552
msgid "Wired"
msgstr "Con fíos"
#: ../js/ui/status/network.js:1612
#: ../js/ui/status/network.js:1563
msgid "Wireless"
msgstr "Sen fíos"
#: ../js/ui/status/network.js:1622
#: ../js/ui/status/network.js:1573
msgid "Mobile broadband"
msgstr "Banda larga móbil"
#: ../js/ui/status/network.js:1632
#: ../js/ui/status/network.js:1583
msgid "VPN Connections"
msgstr "Conexións VPN"
#: ../js/ui/status/network.js:1639
#: ../js/ui/status/network.js:1594
msgid "Network Settings"
msgstr "Preferencias da rede"
#: ../js/ui/status/network.js:1683
msgid "Network Manager"
msgstr "Xestor da rede"
#: ../js/ui/status/network.js:1776
#: ../js/ui/status/network.js:1731
msgid "Connection failed"
msgstr "Produciuse un fallo na conexión"
#: ../js/ui/status/network.js:1777
#: ../js/ui/status/network.js:1732
msgid "Activation of network connection failed"
msgstr "Produciuse un fallo na activación da conexión de rede"
#: ../js/ui/status/network.js:2037
#: ../js/ui/status/network.js:1985
msgid "Networking is disabled"
msgstr "A rede está desactivada"
#: ../js/ui/status/network.js:2109
msgid "Network Manager"
msgstr "Xestor da rede"
#: ../js/ui/status/power.js:59
msgid "Battery"
msgstr "Batería"
@ -1372,11 +1366,6 @@ msgstr "Tablet"
msgid "Computer"
msgstr "Equipo"
#: ../js/ui/status/power.js:215
msgctxt "device"
msgid "Unknown"
msgstr "Descoñecido"
#. Translators: This is the label for audio volume
#: ../js/ui/status/volume.js:25 ../js/ui/status/volume.js:39
msgid "Volume"
@ -1402,7 +1391,7 @@ msgstr "Chamar"
msgid "File Transfer"
msgstr "Transferencia de ficheiro"
#: ../js/ui/telepathyClient.js:368
#: ../js/ui/telepathyClient.js:369
msgid "Subscription request"
msgstr "Solicitude de autorización"
@ -1410,22 +1399,22 @@ msgstr "Solicitude de autorización"
msgid "Connection error"
msgstr "Erro de conexión"
#: ../js/ui/telepathyClient.js:662
#: ../js/ui/telepathyClient.js:663
#, c-format
msgid "%s is online."
msgstr "%s está conectado/a."
#: ../js/ui/telepathyClient.js:666
#: ../js/ui/telepathyClient.js:667
#, c-format
msgid "%s is offline."
msgstr "%s está desconectado/a."
#: ../js/ui/telepathyClient.js:670
#: ../js/ui/telepathyClient.js:671
#, c-format
msgid "%s is away."
msgstr "%s está ausente."
#: ../js/ui/telepathyClient.js:673
#: ../js/ui/telepathyClient.js:674
#, c-format
msgid "%s is busy."
msgstr "%s está ocupado/a."
@ -1433,35 +1422,35 @@ msgstr "%s está ocupado/a."
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds.
#: ../js/ui/telepathyClient.js:888
#: ../js/ui/telepathyClient.js:889
#, no-c-format
msgid "Sent at <b>%X</b> on <b>%A</b>"
msgstr "Enviado ás <b>%X</b> o <b>%A</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25",
#. shown when you get a chat message in the same year.
#: ../js/ui/telepathyClient.js:894
#: ../js/ui/telepathyClient.js:895
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
msgstr "Enviado ás <b>%X</b> o <b>%B %d</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year.
#: ../js/ui/telepathyClient.js:899
#: ../js/ui/telepathyClient.js:900
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
msgstr "Enviado ás <b>%X</b> o <b>%B %d</b>, %Y"
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: ../js/ui/telepathyClient.js:941
#: ../js/ui/telepathyClient.js:942
#, c-format
msgid "%s is now known as %s"
msgstr "Agora %s chámase %s"
#. translators: argument is a room name like
#. * room@jabber.org for example.
#: ../js/ui/telepathyClient.js:1041
#: ../js/ui/telepathyClient.js:1044
#, c-format
msgid "Invitation to %s"
msgstr "Convite a %s"
@ -1469,35 +1458,35 @@ msgstr "Convite a %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/telepathyClient.js:1049
#: ../js/ui/telepathyClient.js:1052
#, c-format
msgid "%s is inviting you to join %s"
msgstr "%s estalle convidando a unirse a %s"
#: ../js/ui/telepathyClient.js:1051 ../js/ui/telepathyClient.js:1130
#: ../js/ui/telepathyClient.js:1194
#: ../js/ui/telepathyClient.js:1054 ../js/ui/telepathyClient.js:1133
#: ../js/ui/telepathyClient.js:1231
msgid "Decline"
msgstr "Rexeitar"
#: ../js/ui/telepathyClient.js:1052 ../js/ui/telepathyClient.js:1131
#: ../js/ui/telepathyClient.js:1195
#: ../js/ui/telepathyClient.js:1055 ../js/ui/telepathyClient.js:1134
#: ../js/ui/telepathyClient.js:1232
msgid "Accept"
msgstr "Aceptar"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1082
#: ../js/ui/telepathyClient.js:1085
#, c-format
msgid "Video call from %s"
msgstr "Videochamada de %s"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1085
#: ../js/ui/telepathyClient.js:1088
#, c-format
msgid "Call from %s"
msgstr "Chamada de %s"
#. translators: this is a button label (verb), not a noun
#: ../js/ui/telepathyClient.js:1092
#: ../js/ui/telepathyClient.js:1095
msgid "Answer"
msgstr "Responder"
@ -1506,112 +1495,112 @@ msgstr "Responder"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#.
#: ../js/ui/telepathyClient.js:1124
#: ../js/ui/telepathyClient.js:1127
#, c-format
msgid "%s is sending you %s"
msgstr "%s esta enviándolle %s"
#. To translators: The parameter is the contact's alias
#: ../js/ui/telepathyClient.js:1159
#: ../js/ui/telepathyClient.js:1196
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "%s solicítalle permiso para ver cando está en liña"
#: ../js/ui/telepathyClient.js:1252
#: ../js/ui/telepathyClient.js:1289
msgid "Network error"
msgstr "Erro da rede"
#: ../js/ui/telepathyClient.js:1254
#: ../js/ui/telepathyClient.js:1291
msgid "Authentication failed"
msgstr "Fallou a autenticación"
#: ../js/ui/telepathyClient.js:1256
#: ../js/ui/telepathyClient.js:1293
msgid "Encryption error"
msgstr "Erro de cifrado"
#: ../js/ui/telepathyClient.js:1258
#: ../js/ui/telepathyClient.js:1295
msgid "Certificate not provided"
msgstr "Certificado non fornecido"
#: ../js/ui/telepathyClient.js:1260
#: ../js/ui/telepathyClient.js:1297
msgid "Certificate untrusted"
msgstr "Non se confía no certificado"
#: ../js/ui/telepathyClient.js:1262
#: ../js/ui/telepathyClient.js:1299
msgid "Certificate expired"
msgstr "Certificado caducado"
#: ../js/ui/telepathyClient.js:1264
#: ../js/ui/telepathyClient.js:1301
msgid "Certificate not activated"
msgstr "Certificado non activado"
#: ../js/ui/telepathyClient.js:1266
#: ../js/ui/telepathyClient.js:1303
msgid "Certificate hostname mismatch"
msgstr "O nome do servidor do certificado non coincide"
#: ../js/ui/telepathyClient.js:1268
#: ../js/ui/telepathyClient.js:1305
msgid "Certificate fingerprint mismatch"
msgstr "A pegada do certificado non coincide"
#: ../js/ui/telepathyClient.js:1270
#: ../js/ui/telepathyClient.js:1307
msgid "Certificate self-signed"
msgstr "Certificado autoasinado"
#: ../js/ui/telepathyClient.js:1272
#: ../js/ui/telepathyClient.js:1309
msgid "Status is set to offline"
msgstr "O estado está definido a «desconectado»"
#: ../js/ui/telepathyClient.js:1274
#: ../js/ui/telepathyClient.js:1311
msgid "Encryption is not available"
msgstr "O cifrado non está dispoñíbel"
#: ../js/ui/telepathyClient.js:1276
#: ../js/ui/telepathyClient.js:1313
msgid "Certificate is invalid"
msgstr "O certificado non é válido"
#: ../js/ui/telepathyClient.js:1278
#: ../js/ui/telepathyClient.js:1315
msgid "Connection has been refused"
msgstr "Rexeitouse a conexión"
#: ../js/ui/telepathyClient.js:1280
#: ../js/ui/telepathyClient.js:1317
msgid "Connection can't be established"
msgstr "Non é posíbel estabelecer a conexión"
#: ../js/ui/telepathyClient.js:1282
#: ../js/ui/telepathyClient.js:1319
msgid "Connection has been lost"
msgstr "Perdeuse a conexión"
#: ../js/ui/telepathyClient.js:1284
#: ../js/ui/telepathyClient.js:1321
msgid "This account is already connected to the server"
msgstr "Esta cuenta xa está conectada ao servidor"
#: ../js/ui/telepathyClient.js:1286
#: ../js/ui/telepathyClient.js:1323
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr ""
"Substituíuse a conexión por unha nova conexión empregando o mesmo recurso"
#: ../js/ui/telepathyClient.js:1288
#: ../js/ui/telepathyClient.js:1325
msgid "The account already exists on the server"
msgstr "Esta conta xa existe no servidor"
#: ../js/ui/telepathyClient.js:1290
#: ../js/ui/telepathyClient.js:1327
msgid "Server is currently too busy to handle the connection"
msgstr ""
"Nestes intres o servidor está moi ocupado tentando xestionar a conexión"
#: ../js/ui/telepathyClient.js:1292
#: ../js/ui/telepathyClient.js:1329
msgid "Certificate has been revoked"
msgstr "Revogouse o certificado"
#: ../js/ui/telepathyClient.js:1294
#: ../js/ui/telepathyClient.js:1331
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"O certificado usa un algoritmo de cifrado inseguro ou é criptográficamente "
"débil"
#: ../js/ui/telepathyClient.js:1296
#: ../js/ui/telepathyClient.js:1333
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@ -1620,70 +1609,66 @@ msgstr ""
"certificado do servidor excede os límites impostos pola biblioteca de "
"criptografía."
#: ../js/ui/telepathyClient.js:1298
#: ../js/ui/telepathyClient.js:1335
msgid "Internal error"
msgstr "Erro interno"
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#: ../js/ui/telepathyClient.js:1308
#: ../js/ui/telepathyClient.js:1345
#, c-format
msgid "Connection to %s failed"
msgstr "Fallou a conexión a %s"
#: ../js/ui/telepathyClient.js:1317
#: ../js/ui/telepathyClient.js:1354
msgid "Reconnect"
msgstr "Reconectar"
#: ../js/ui/telepathyClient.js:1318
#: ../js/ui/telepathyClient.js:1355
msgid "Edit account"
msgstr "Editar conta"
#: ../js/ui/telepathyClient.js:1364
#: ../js/ui/telepathyClient.js:1401
msgid "Unknown reason"
msgstr "Razón descoñecida"
#: ../js/ui/userMenu.js:136
#: ../js/ui/userMenu.js:135
msgid "Hidden"
msgstr "Oculto"
#: ../js/ui/userMenu.js:142
#: ../js/ui/userMenu.js:141
msgid "Idle"
msgstr "Inactivo"
#: ../js/ui/userMenu.js:145
#: ../js/ui/userMenu.js:144
msgid "Unavailable"
msgstr "Non dispoñíbel"
#: ../js/ui/userMenu.js:565 ../js/ui/userMenu.js:705
msgid "Switch User"
msgstr "Cambiar de usuario"
#: ../js/ui/userMenu.js:566
msgid "Switch Session"
msgstr "Cambiar de sesión"
#: ../js/ui/userMenu.js:681
#: ../js/ui/userMenu.js:624
msgid "Notifications"
msgstr "Notificacións"
#: ../js/ui/userMenu.js:690
#: ../js/ui/userMenu.js:632
msgid "System Settings"
msgstr "Preferencias do sistema"
#: ../js/ui/userMenu.js:710
#: ../js/ui/userMenu.js:646
msgid "Switch User"
msgstr "Cambiar de usuario"
#: ../js/ui/userMenu.js:651
msgid "Log Out"
msgstr "Saír da sesión"
#: ../js/ui/userMenu.js:718
#: ../js/ui/userMenu.js:659
msgid "Lock"
msgstr "Bloquear"
#: ../js/ui/userMenu.js:736
#: ../js/ui/userMenu.js:677
msgid "Your chat status will be set to busy"
msgstr "O seu estado do chat estabelecerase a «ocupado»"
#: ../js/ui/userMenu.js:737
#: ../js/ui/userMenu.js:678
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."
@ -1749,25 +1734,15 @@ msgstr[1] "%u entradas"
msgid "System Sounds"
msgstr "Sons do sistema"
#: ../src/main.c:313
#: ../src/main.c:255
msgid "Print version"
msgstr "Imprimir versión"
#: ../src/main.c:319
#: ../src/main.c:261
msgid "Mode used by GDM for login screen"
msgstr "Modo usado por GDM para a pantalla de inicio"
#: ../src/main.c:325
msgid "Use a specific mode, e.g. \"gdm\" for login screen"
msgstr ""
"Usar un modo específico, por exemplo, «gdm» para a pantalla de inicio de "
"sesión"
#: ../src/main.c:331
msgid "List possible modes"
msgstr "Listar os modos posíbeis"
#: ../src/shell-app.c:622
#: ../src/shell-app.c:619
#, c-format
msgid "Failed to launch '%s'"
msgstr "Produciuse un fallo ao iniciar «%s»"

462
po/he.po

File diff suppressed because it is too large Load Diff

562
po/ja.po

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@ msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-04-19 21:14+0000\n"
"PO-Revision-Date: 2012-05-19 22:57+0900\n"
"PO-Revision-Date: 2012-04-26 01:05+0900\n"
"Last-Translator: Changwoo Ryu <cwryu@debian.org>\n"
"Language-Team: GNOME Korea <gnome-kr@googlegroups.com>\n"
"MIME-Version: 1.0\n"
@ -51,7 +51,7 @@ msgstr "Alt-F2 대화 상자에서 내부 디버깅 및 감시 기능에 접근
#: ../data/org.gnome.shell.gschema.xml.in.h:3
msgid "Uuids of extensions to enable"
msgstr "사용할 확장의 UUID 목록"
msgstr "사용할 확장 기능의 UUID 목록"
#: ../data/org.gnome.shell.gschema.xml.in.h:4
msgid ""
@ -71,7 +71,11 @@ msgid ""
"used ones (e.g. in launchers). While this data will be kept private, you may "
"want to disable this for privacy reasons. Please note that doing so won't "
"remove already saved data."
msgstr "셸에서는 최근에 사용한 프로그램을(실행 메뉴 등에서) 표시하는 목적으로, 현재 사용 중인 프로그램을 감시합니다. 이 데이터는 비공개 데이터이지만 사생활 문제가 걱정된다면 이 기능을 끌 수도 있습니다. 단 이 기능을 사용하지 않더라도 이미 저장된 데이터를 제거하지는 않습니다."
msgstr ""
"셸에서는 최근에 사용한 프로그램을 (실행 메뉴 등에서) 표시하는 목적으로, 현재 "
"사용 중인 프로그램을 감시합니다. 이 데이터는 비공개 데이터이지만 사생활 문제"
"가 걱정된다면 이 기능을 끌 수도 있습니다. 단 이 기능을 사용하지 않더라도 이"
"미 저장된 데이터를 제거하지는 않습니다."
#: ../data/org.gnome.shell.gschema.xml.in.h:7
msgid "List of desktop file IDs for favorite applications"
@ -89,7 +93,7 @@ msgstr "사용하지 않는 OpenSearch 서비스"
#: ../data/org.gnome.shell.gschema.xml.in.h:10
msgid "History for command (Alt-F2) dialog"
msgstr "명령어 대화 상자에(Alt-F2) 기록 기능"
msgstr "명령어 대화 상자에 (Alt-F2) 기록 기능"
#: ../data/org.gnome.shell.gschema.xml.in.h:11
msgid "History for the looking glass dialog"
@ -162,7 +166,7 @@ msgid "The gstreamer pipeline used to encode the screencast"
msgstr "스크린 방송 인코딩에 사용할 gstreamer 파이프라인"
#: ../data/org.gnome.shell.gschema.xml.in.h:28
#, no-c-format
#, no-c-format, fuzzy
msgid ""
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
"used for gst-launch. The pipeline should have an unconnected sink pad where "
@ -174,31 +178,45 @@ msgid ""
"'vp8enc quality=8 speed=6 threads=%T ! queue ! webmmux' and records to WEBM "
"using the VP8 codec. %T is used as a placeholder for a guess at the optimal "
"thread count on the system."
msgstr "녹화 인코딩에 사용할 GStreamer 파이프라인을 지정합니다. gst-launch 프로그램에 사용하는 문법을 따릅니다. 녹화한 영상이 입력되는 싱크 패드는 이 파이프라인에 연결하지 않은 상태여야 합니다. 보통은 소스 패드도 연결하지 않고, 소스 패드의 출력을 출력 파일에 기록합니다. 하지만 파이프라인에서 이 출력을 처리할 수도 있습니다. shout2send 같은 프로그램을 이용해 아이스캐스트 서버로 출력을 보내거나 하는 용도로 사용할 수 있습니다. 설정을 취소하거나 빈 값으로 설정하면, 기본 파이프라인을 사용합니다. 기본 파이프라인은 'vp8enc quality=8 speed=6 threads=%T ! queue ! webmmux'이고 VP8 코덱을 사용해 WEBM 형식으로 녹화합니다. '%T' 기호는 시스템에서 최적으로 생각되는 스레드 수로 대체됩니다."
msgstr ""
"녹화 인코딩에 사용할 GStreamer 파이프라인을 지정합니다. gst-launch에 사용하"
"는 문법을 따릅니다. 파이프라인은 녹화한 영상이 있는 싱크 패드를 연결하지 않"
"은 상태여야 합니다. 보통 소스 패드와 연결하지 않았을 것입니다. 이 패드의 출력"
"은 출력 파일에 기록할 것입니다. 그러나 파이프라인은 이 출력을 다룰 수 있기도 "
"합니다 - 아마 shout2send와 같은 것을 통해 icecast 서버로 출력을 보내는데 사용"
"할지도 모릅니다. 만약 설정을 취소하거나 빈 값으로 설정한다면, 기본 파이프라인"
"을 사용할 것입니다. 이것은 현재 'vp8enc quality=8 speed=6 threads=%T ! "
"queue ! webmmux' 이며 VP8 코덱을 사용하여 WEBM으로 녹화합니다. %T는 시스템 상"
"의 최적의 스레드 수를 추측하기 위해 대체기호로 사용합니다."
#: ../data/org.gnome.shell.gschema.xml.in.h:29
msgid "File extension used for storing the screencast"
msgstr "스크린 방송을 저장할 때 사용할 파일 확장자"
#: ../data/org.gnome.shell.gschema.xml.in.h:30
#, fuzzy
msgid ""
"The filename for recorded screencasts will be a unique filename based on the "
"current date, and use this extension. It should be changed when recording to "
"a different container format."
msgstr "녹화한 스크린 방송 영상 파일은, 현재 날짜와 여기서 설정하는 확장자를 붙여 파일 이름을 만듭니다. 다른 컨테이너 형식으로 녹화하려면 이 값을 바꿔야 합니다."
msgstr ""
"스크린 방송 녹화 파일 이름은 현재 날짜와 이 확장자를 사용해서 결정됩니다. 녹"
"화할 때 다른 형식으로 바꿀 수도 있습니다."
#: ../js/extensionPrefs/main.js:125
#, c-format
#, c-format, fuzzy
msgid "There was an error loading the preferences dialog for %s:"
msgstr "%s에 대한 기본 설정 대화상자를 불러오는데 오류가 발생했습니다:"
#: ../js/extensionPrefs/main.js:165
#, fuzzy
msgid "<b>Extension</b>"
msgstr "<b>확장</b>"
#: ../js/extensionPrefs/main.js:189
#, fuzzy
msgid "Select an extension to configure using the combobox above."
msgstr "위의 콤보상자를 사용 설정할 확장을 선택하십시오."
msgstr "위의 콤보상자를 사용하여 설정할 확장을 선택하십시오."
#: ../js/gdm/loginDialog.js:627
msgid "Session..."
@ -656,13 +674,13 @@ msgstr "다시 입력하십시오:"
#: ../js/ui/lookingGlass.js:732
msgid "No extensions installed"
msgstr "확장을 설치하지 않았습니다"
msgstr "확장 기능을 설치하지 않았습니다"
#. Translators: argument is an extension UUID.
#: ../js/ui/lookingGlass.js:786
#, c-format
msgid "%s has not emitted any errors."
msgstr "%s에서 발생한 에러가 없습니다."
msgstr "%s이(가) 발생한 에러가 없습니다."
#: ../js/ui/lookingGlass.js:792
msgid "Hide Errors"
@ -1149,7 +1167,7 @@ msgstr "더 보기..."
#. and we cannot access its settings (including the name)
#: ../js/ui/status/network.js:621 ../js/ui/status/network.js:1440
msgid "Connected (private)"
msgstr "연결됨(개인)"
msgstr "연결됨 (개인)"
#: ../js/ui/status/network.js:696
msgid "Auto Ethernet"
@ -1555,7 +1573,7 @@ msgstr "내부 오류"
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#: ../js/ui/telepathyClient.js:1345
#, c-format
#, c-format, fuzzy
msgid "Connection to %s failed"
msgstr "%s에 연결이 실패했습니다"

159
po/lt.po
View File

@ -3,20 +3,19 @@
# This file is distributed under the same license as the gnome-shell package.
# Žygimantas Beručka <zygis@gnome.org>, 2010, 2011, 2012.
# Algimantas Margevičius <gymka@mail.ru>, 2011.
# Mantas Kriaučiūnas <mantas@akl.lt>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-05-19 13:58+0000\n"
"POT-Creation-Date: 2012-03-30 17:59+0000\n"
"PO-Revision-Date: 2012-04-05 15:14+0300\n"
"Last-Translator: Mantas Kriaučiūnas <mantas@akl.lt>\n"
"Last-Translator: Žygimantas Beručka <zygis@gnome.org>\n"
"Language-Team: Lithuanian\n"
"Language: lt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: lt\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%"
"100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Virtaal 0.7.0\n"
@ -24,7 +23,7 @@ msgstr ""
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "GNOME Shell aplinka"
msgstr "GNOME Shell"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
@ -80,11 +79,10 @@ msgid ""
"want to disable this for privacy reasons. Please note that doing so won't "
"remove already saved data."
msgstr ""
"Įprastai GNOME aplinka stebi aktyvias programas siekiant pateikti "
"dažniausiai naudojamas (pvz., leistukuose). Nors šie duomenys "
"konfidencialiai saugomi, jei norite, saugumo sumetimais galite šią funkciją "
"išjungti. Atminkite, kad išjungus šią funkciją anksčiau įrašyti duomenys "
"nebus pašalinti."
"Apvalkalas paprastai stebi aktyvias programas siekiant pateikti dažniausiai "
"naudojamas (pvz., leistukuose). Nors šie duomenys konfidencialiai saugomi, "
"jei norite, saugumo sumetimais galite šią funkciją išjungti. Atminkite, kad "
"tai padarius jau įrašyti duomenys jau nebus įrašyti."
#: ../data/org.gnome.shell.gschema.xml.in.h:7
msgid "List of desktop file IDs for favorite applications"
@ -224,7 +222,7 @@ msgstr ""
#: ../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 "<b>Extension</b>"
@ -234,40 +232,40 @@ msgstr "<b>Plėtinys</b>"
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:627
#: ../js/gdm/loginDialog.js:624
msgid "Session..."
msgstr "Seansas..."
#: ../js/gdm/loginDialog.js:789
#: ../js/gdm/loginDialog.js:786
msgctxt "title"
msgid "Sign In"
msgstr "Prisijungti"
#. Translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead
#: ../js/gdm/loginDialog.js:834
#: ../js/gdm/loginDialog.js:831
msgid "(or swipe finger)"
msgstr "(arba perbraukite pirštu)"
#. 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:855
#: ../js/gdm/loginDialog.js:852
msgid "Not listed?"
msgstr "Nėra sąraše?"
#: ../js/gdm/loginDialog.js:1023 ../js/ui/endSessionDialog.js:401
#: ../js/ui/extensionSystem.js:400 ../js/ui/networkAgent.js:153
#: ../js/gdm/loginDialog.js:1020 ../js/ui/endSessionDialog.js:401
#: ../js/ui/extensionSystem.js:399 ../js/ui/networkAgent.js:153
#: ../js/ui/polkitAuthenticationAgent.js:175 ../js/ui/status/bluetooth.js:462
msgid "Cancel"
msgstr "Atsisakyti"
msgstr "Atšaukti"
#: ../js/gdm/loginDialog.js:1028
#: ../js/gdm/loginDialog.js:1025
msgctxt "button"
msgid "Sign In"
msgstr "Prisijungti"
#: ../js/gdm/loginDialog.js:1380
#: ../js/gdm/loginDialog.js:1377
msgid "Login Window"
msgstr "Prisijungimo langas"
@ -675,11 +673,11 @@ msgstr[2] "Sistema bus paleista iš naujo po %d sekundžių."
msgid "Restarting the system."
msgstr "Sistema paleidžiama iš naujo."
#: ../js/ui/extensionSystem.js:404
#: ../js/ui/extensionSystem.js:403
msgid "Install"
msgstr "Įdiegti"
#: ../js/ui/extensionSystem.js:408
#: ../js/ui/extensionSystem.js:407
#, c-format
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "Atsiųsti ir įdiegti „%s“ iš extensions.gnome.org?"
@ -688,8 +686,7 @@ msgstr "Atsiųsti ir įdiegti „%s“ iš extensions.gnome.org?"
msgid "tray"
msgstr "dėklas"
#: ../js/ui/keyboard.js:544 ../js/ui/status/keyboard.js:44
#: ../js/ui/status/power.js:203
#: ../js/ui/keyboard.js:544 ../js/ui/status/power.js:203
msgid "Keyboard"
msgstr "Klaviatūra"
@ -725,7 +722,7 @@ msgstr "Įjungta"
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:808 ../src/gvc/gvc-mixer-control.c:1082
#: ../js/ui/lookingGlass.js:808 ../src/gvc/gvc-mixer-control.c:1093
msgid "Disabled"
msgstr "Išjungta"
@ -942,7 +939,7 @@ msgstr "Įveskite komandą:"
msgid "Searching..."
msgstr "Ieškoma..."
#: ../js/ui/searchDisplay.js:415
#: ../js/ui/searchDisplay.js:414
msgid "No matching results."
msgstr "Nerasta atitikmenų."
@ -1100,7 +1097,7 @@ msgstr "Visada leisti prieigą"
msgid "Grant this time only"
msgstr "Leisti tik šį kartą"
#: ../js/ui/status/bluetooth.js:382 ../js/ui/telepathyClient.js:1093
#: ../js/ui/status/bluetooth.js:382 ../js/ui/telepathyClient.js:1091
msgid "Reject"
msgstr "Atmesti"
@ -1177,7 +1174,7 @@ msgstr "Trūksta integruotos programinės įrangos (firmware)"
#. Translators: this is for wired network devices that are physically disconnected
#: ../js/ui/status/network.js:517
msgid "cable unplugged"
msgstr "atjungtas laidas"
msgstr "kabelis neįjungtas"
#. Translators: this is for a network device that cannot be activated (for example it
#. is disabled by rfkill, or it has no coverage
@ -1191,7 +1188,7 @@ msgstr "nepavyko prisijungti"
#: ../js/ui/status/network.js:585 ../js/ui/status/network.js:1505
msgid "More..."
msgstr "Rodyti daugiau tinklų..."
msgstr "Daugiau..."
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
#. and we cannot access its settings (including the name)
@ -1388,7 +1385,7 @@ msgstr "Skambutis"
#. We got the TpContact
#: ../js/ui/telepathyClient.js:287
msgid "File Transfer"
msgstr "Failo persiuntimas"
msgstr "Failo perdavimas"
#: ../js/ui/telepathyClient.js:369
msgid "Subscription request"
@ -1421,35 +1418,35 @@ msgstr "%s yra užsiėmęs (-usi)."
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds.
#: ../js/ui/telepathyClient.js:889
#: ../js/ui/telepathyClient.js:887
#, no-c-format
msgid "Sent at <b>%X</b> on <b>%A</b>"
msgstr "Išsiųsta <b>%X</b> <b>%A</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25",
#. shown when you get a chat message in the same year.
#: ../js/ui/telepathyClient.js:895
#: ../js/ui/telepathyClient.js:893
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
msgstr "Išsiųsta <b>%B %d</b>, <b>%A</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year.
#: ../js/ui/telepathyClient.js:900
#: ../js/ui/telepathyClient.js:898
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
msgstr "Išsiųsta %Y <b>%B %d</b>, <b>%A</b>"
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: ../js/ui/telepathyClient.js:942
#: ../js/ui/telepathyClient.js:940
#, 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/telepathyClient.js:1044
#: ../js/ui/telepathyClient.js:1042
#, c-format
msgid "Invitation to %s"
msgstr "Kvietimas į %s"
@ -1457,35 +1454,35 @@ 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/telepathyClient.js:1052
#: ../js/ui/telepathyClient.js:1050
#, c-format
msgid "%s is inviting you to join %s"
msgstr "%s jus kviečia prisijungti prie %s"
#: ../js/ui/telepathyClient.js:1054 ../js/ui/telepathyClient.js:1133
#: ../js/ui/telepathyClient.js:1231
#: ../js/ui/telepathyClient.js:1052 ../js/ui/telepathyClient.js:1131
#: ../js/ui/telepathyClient.js:1229
msgid "Decline"
msgstr "Atmesti"
#: ../js/ui/telepathyClient.js:1055 ../js/ui/telepathyClient.js:1134
#: ../js/ui/telepathyClient.js:1232
#: ../js/ui/telepathyClient.js:1053 ../js/ui/telepathyClient.js:1132
#: ../js/ui/telepathyClient.js:1230
msgid "Accept"
msgstr "Priimti"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1085
#: ../js/ui/telepathyClient.js:1083
#, c-format
msgid "Video call from %s"
msgstr "Vaizdo skambutis nuo %s"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1088
#: ../js/ui/telepathyClient.js:1086
#, c-format
msgid "Call from %s"
msgstr "Skambutis nuo %s"
#. translators: this is a button label (verb), not a noun
#: ../js/ui/telepathyClient.js:1095
#: ../js/ui/telepathyClient.js:1093
msgid "Answer"
msgstr "Atsiliepti"
@ -1494,110 +1491,110 @@ msgstr "Atsiliepti"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#.
#: ../js/ui/telepathyClient.js:1127
#: ../js/ui/telepathyClient.js:1125
#, 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/telepathyClient.js:1196
#: ../js/ui/telepathyClient.js:1194
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "%s pageidauja matyti, kai esate prisijungę prie interneto"
#: ../js/ui/telepathyClient.js:1289
#: ../js/ui/telepathyClient.js:1287
msgid "Network error"
msgstr "Tinklo klaida"
#: ../js/ui/telepathyClient.js:1291
#: ../js/ui/telepathyClient.js:1289
msgid "Authentication failed"
msgstr "Nepavyko patvirtinti tapatybės"
#: ../js/ui/telepathyClient.js:1293
#: ../js/ui/telepathyClient.js:1291
msgid "Encryption error"
msgstr "Šifravimo klaida"
#: ../js/ui/telepathyClient.js:1295
#: ../js/ui/telepathyClient.js:1293
msgid "Certificate not provided"
msgstr "Liudijimas nepateiktas"
#: ../js/ui/telepathyClient.js:1297
#: ../js/ui/telepathyClient.js:1295
msgid "Certificate untrusted"
msgstr "Liudijimas nepatikimas"
#: ../js/ui/telepathyClient.js:1299
#: ../js/ui/telepathyClient.js:1297
msgid "Certificate expired"
msgstr "Liudijimo galiojimas pasibaigęs"
#: ../js/ui/telepathyClient.js:1301
#: ../js/ui/telepathyClient.js:1299
msgid "Certificate not activated"
msgstr "Liudijimas neaktyvuotas"
#: ../js/ui/telepathyClient.js:1303
#: ../js/ui/telepathyClient.js:1301
msgid "Certificate hostname mismatch"
msgstr "Liudijimo serverio vardo nesutapimas"
#: ../js/ui/telepathyClient.js:1305
#: ../js/ui/telepathyClient.js:1303
msgid "Certificate fingerprint mismatch"
msgstr "Liudijimo piršto atspaudo nesutapimas"
#: ../js/ui/telepathyClient.js:1307
#: ../js/ui/telepathyClient.js:1305
msgid "Certificate self-signed"
msgstr "Liudijimas pačių pasirašytas"
#: ../js/ui/telepathyClient.js:1309
#: ../js/ui/telepathyClient.js:1307
msgid "Status is set to offline"
msgstr "Nustatyta atsijungimo būsena"
#: ../js/ui/telepathyClient.js:1311
#: ../js/ui/telepathyClient.js:1309
msgid "Encryption is not available"
msgstr "Šifravimas negalimas"
#: ../js/ui/telepathyClient.js:1313
#: ../js/ui/telepathyClient.js:1311
msgid "Certificate is invalid"
msgstr "Liudijimas netinkamas"
#: ../js/ui/telepathyClient.js:1315
#: ../js/ui/telepathyClient.js:1313
msgid "Connection has been refused"
msgstr "Ryšys atmestas"
#: ../js/ui/telepathyClient.js:1317
#: ../js/ui/telepathyClient.js:1315
msgid "Connection can't be established"
msgstr "Nepavyko užmegzti ryšio"
#: ../js/ui/telepathyClient.js:1319
#: ../js/ui/telepathyClient.js:1317
msgid "Connection has been lost"
msgstr "Ryšys nutrūko"
#: ../js/ui/telepathyClient.js:1321
#: ../js/ui/telepathyClient.js:1319
msgid "This account is already connected to the server"
msgstr "Ši paskyra jau prijungta prie serverio"
#: ../js/ui/telepathyClient.js:1323
#: ../js/ui/telepathyClient.js:1321
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/telepathyClient.js:1325
#: ../js/ui/telepathyClient.js:1323
msgid "The account already exists on the server"
msgstr "Tokia paskyra serveryje jau yra"
#: ../js/ui/telepathyClient.js:1327
#: ../js/ui/telepathyClient.js:1325
msgid "Server is currently too busy to handle the connection"
msgstr "Šiuo metu serveris per daug užimtas šiai užklausai apdoroti"
#: ../js/ui/telepathyClient.js:1329
#: ../js/ui/telepathyClient.js:1327
msgid "Certificate has been revoked"
msgstr "Liudijimas atšauktas"
#: ../js/ui/telepathyClient.js:1331
#: ../js/ui/telepathyClient.js:1329
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"Liudijimui naudojamas nesaugus šifravimo algoritmas arba jis kriptografiškai "
"silpnas"
#: ../js/ui/telepathyClient.js:1333
#: ../js/ui/telepathyClient.js:1331
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@ -1605,26 +1602,26 @@ msgstr ""
"Serverio liudijimo ilgis arba liudijimų eilės dydis viršija kriptografijos "
"bibliotekos apribojimus"
#: ../js/ui/telepathyClient.js:1335
#: ../js/ui/telepathyClient.js:1333
msgid "Internal error"
msgstr "Vidinė klaida"
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#: ../js/ui/telepathyClient.js:1345
#: ../js/ui/telepathyClient.js:1343
#, c-format
msgid "Connection to %s failed"
msgstr "Nepavyko prisijungti prie %s"
#: ../js/ui/telepathyClient.js:1354
#: ../js/ui/telepathyClient.js:1352
msgid "Reconnect"
msgstr "Prisijungti iš naujo"
#: ../js/ui/telepathyClient.js:1355
#: ../js/ui/telepathyClient.js:1353
msgid "Edit account"
msgstr "Taisyti paskyrą"
#: ../js/ui/telepathyClient.js:1401
#: ../js/ui/telepathyClient.js:1399
msgid "Unknown reason"
msgstr "Nežinoma priežastis"
@ -1650,7 +1647,7 @@ msgstr "Pranešimai"
#: ../js/ui/userMenu.js:639
msgid "Online Accounts"
msgstr "Interneto paskyros"
msgstr "Tinklo paskyros"
#: ../js/ui/userMenu.js:643
msgid "System Settings"
@ -1709,7 +1706,7 @@ msgstr "Orakulė sako %s"
#: ../js/ui/wanda.js:168
msgid "Your favorite Easter Egg"
msgstr "Jūsų mėgstamiausias Velykinis kiaušinis"
msgstr "Jūsų mėgstamiausias lykinis kiaušinis"
#: ../js/ui/windowAttentionHandler.js:19
#, c-format
@ -1718,7 +1715,7 @@ msgstr "„%s“ yra pasirengusi"
#. translators:
#. * The number of sound outputs on a particular device
#: ../src/gvc/gvc-mixer-control.c:1089
#: ../src/gvc/gvc-mixer-control.c:1100
#, c-format
msgid "%u Output"
msgid_plural "%u Outputs"
@ -1728,7 +1725,7 @@ msgstr[2] "%u išvestys"
#. translators:
#. * The number of sound inputs on a particular device
#: ../src/gvc/gvc-mixer-control.c:1099
#: ../src/gvc/gvc-mixer-control.c:1110
#, c-format
msgid "%u Input"
msgid_plural "%u Inputs"
@ -1736,15 +1733,15 @@ msgstr[0] "%u įvestis"
msgstr[1] "%u įvestys"
msgstr[2] "%u įvestys"
#: ../src/gvc/gvc-mixer-control.c:1397
#: ../src/gvc/gvc-mixer-control.c:1408
msgid "System Sounds"
msgstr "Sistemos garsai"
#: ../src/main.c:256
#: ../src/main.c:255
msgid "Print version"
msgstr "Išvesti versijos numerį"
#: ../src/main.c:262
#: ../src/main.c:261
msgid "Mode used by GDM for login screen"
msgstr "Veiksena, naudojama GDM prisijungimo ekrane"
@ -1777,7 +1774,7 @@ msgstr "Naudotojas užvėrė tapatybės patvirtinimo dialogą"
#. * nautilus
#: ../src/shell-util.c:97
msgid "Home"
msgstr "Namų aplankas"
msgstr "Namai"
#. Translators: this is the same string as the one found in
#. * nautilus

357
po/nb.po
View File

@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell 3.5.x\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-05-30 14:16+0200\n"
"PO-Revision-Date: 2012-05-30 14:19+0200\n"
"POT-Creation-Date: 2012-04-30 11:12+0200\n"
"PO-Revision-Date: 2012-04-30 11:13+0200\n"
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
"Language-Team: Norwegian bokmål <i18n-nb@lister.ping.uio.no>\n"
"Language: \n"
@ -246,8 +246,8 @@ msgid "Not listed?"
msgstr "Ikke listet?"
#: ../js/gdm/loginDialog.js:1023 ../js/ui/endSessionDialog.js:401
#: ../js/ui/extensionSystem.js:375 ../js/ui/networkAgent.js:153
#: ../js/ui/polkitAuthenticationAgent.js:175 ../js/ui/status/bluetooth.js:431
#: ../js/ui/extensionSystem.js:400 ../js/ui/networkAgent.js:153
#: ../js/ui/polkitAuthenticationAgent.js:175 ../js/ui/status/bluetooth.js:462
msgid "Cancel"
msgstr "Avbryt"
@ -260,31 +260,30 @@ msgstr "Logg inn"
msgid "Login Window"
msgstr "Innloggingsvindu"
#: ../js/gdm/powerMenu.js:130 ../js/ui/userMenu.js:595
#: ../js/ui/userMenu.js:599 ../js/ui/userMenu.js:647
#: ../js/gdm/powerMenu.js:155 ../js/ui/userMenu.js:597
#: ../js/ui/userMenu.js:599 ../js/ui/userMenu.js:668
msgid "Suspend"
msgstr "Hvilemodus"
#: ../js/gdm/powerMenu.js:135
#: ../js/gdm/powerMenu.js:160
msgid "Restart"
msgstr "Start på nytt"
#: ../js/gdm/powerMenu.js:140 ../js/ui/userMenu.js:597
#: ../js/ui/userMenu.js:599 ../js/ui/userMenu.js:646
#: ../js/gdm/powerMenu.js:165
msgid "Power Off"
msgstr "Slå av"
#: ../js/misc/util.js:93
#: ../js/misc/util.js:92
msgid "Command not found"
msgstr "Kommando ikke funnet"
#. Replace "Error invoking GLib.shell_parse_argv: " with
#. something nicer
#: ../js/misc/util.js:124
#: ../js/misc/util.js:119
msgid "Could not parse command:"
msgstr "Klarte ikke å lese kommando:"
#: ../js/misc/util.js:132
#: ../js/misc/util.js:127
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Kjøring av «%s» feilet:"
@ -298,19 +297,19 @@ msgstr "Alle"
msgid "APPLICATIONS"
msgstr "PROGRAMMER"
#: ../js/ui/appDisplay.js:374
#: ../js/ui/appDisplay.js:375
msgid "SETTINGS"
msgstr "INNSTILLINGER"
#: ../js/ui/appDisplay.js:679
#: ../js/ui/appDisplay.js:680
msgid "New Window"
msgstr "Nytt vindu"
#: ../js/ui/appDisplay.js:682
#: ../js/ui/appDisplay.js:683
msgid "Remove from Favorites"
msgstr "Fjern fra favoritter"
#: ../js/ui/appDisplay.js:683
#: ../js/ui/appDisplay.js:684
msgid "Add to Favorites"
msgstr "Legg til i favoritter"
@ -328,12 +327,12 @@ msgstr "%s ble fjernet fra dine favoritter."
msgid "Removable Devices"
msgstr "Avtagbare enheter"
#: ../js/ui/autorunManager.js:553
#: ../js/ui/autorunManager.js:560
#, c-format
msgid "Open with %s"
msgstr "Åpne med %s"
#: ../js/ui/autorunManager.js:579
#: ../js/ui/autorunManager.js:586
msgid "Eject"
msgstr "Løs ut"
@ -488,15 +487,15 @@ msgstr "Neste uke"
msgid "Unknown"
msgstr "Ukjent"
#: ../js/ui/contactDisplay.js:89 ../js/ui/userMenu.js:130
#: ../js/ui/contactDisplay.js:89 ../js/ui/userMenu.js:129
msgid "Available"
msgstr "Tilgjengelig"
#: ../js/ui/contactDisplay.js:94 ../js/ui/userMenu.js:139
#: ../js/ui/contactDisplay.js:94 ../js/ui/userMenu.js:138
msgid "Away"
msgstr "Borte"
#: ../js/ui/contactDisplay.js:98 ../js/ui/userMenu.js:133
#: ../js/ui/contactDisplay.js:98 ../js/ui/userMenu.js:132
msgid "Busy"
msgstr "Opptatt"
@ -508,62 +507,62 @@ msgstr "Frakoblet"
msgid "CONTACTS"
msgstr "KONTAKTER"
#: ../js/ui/dash.js:239 ../js/ui/messageTray.js:1239
#: ../js/ui/dash.js:239 ../js/ui/messageTray.js:1207
msgid "Remove"
msgstr "Fjern"
#: ../js/ui/dateMenu.js:101
#: ../js/ui/dateMenu.js:103
msgid "Date and Time Settings"
msgstr "Innstillinger for dato og klokkeslett"
#: ../js/ui/dateMenu.js:127
#: ../js/ui/dateMenu.js:129
msgid "Open Calendar"
msgstr "Åpne kalender"
#. Translators: This is the time format with date used
#. in 24-hour mode.
#: ../js/ui/dateMenu.js:185
#: ../js/ui/dateMenu.js:187
msgid "%a %b %e, %R:%S"
msgstr "%a %e %b, %R.%S"
#: ../js/ui/dateMenu.js:186
#: ../js/ui/dateMenu.js:188
msgid "%a %b %e, %R"
msgstr "%a %e %b, %R"
#. Translators: This is the time format without date used
#. in 24-hour mode.
#: ../js/ui/dateMenu.js:190
#: ../js/ui/dateMenu.js:192
msgid "%a %R:%S"
msgstr "%a %R.%S"
#: ../js/ui/dateMenu.js:191
#: ../js/ui/dateMenu.js:193
msgid "%a %R"
msgstr "%a %R"
#. Translators: This is a time format with date used
#. for AM/PM.
#: ../js/ui/dateMenu.js:198
#: ../js/ui/dateMenu.js:200
msgid "%a %b %e, %l:%M:%S %p"
msgstr "%a %e %b, %l.%M.%S %p"
#: ../js/ui/dateMenu.js:199
#: ../js/ui/dateMenu.js:201
msgid "%a %b %e, %l:%M %p"
msgstr "%a %e %b, %l.%M %p"
#. Translators: This is a time format without date used
#. for AM/PM.
#: ../js/ui/dateMenu.js:203
#: ../js/ui/dateMenu.js:205
msgid "%a %l:%M:%S %p"
msgstr "%a %l.%M.%S %p"
#: ../js/ui/dateMenu.js:204
#: ../js/ui/dateMenu.js:206
msgid "%a %l:%M %p"
msgstr "%a %l.%M %p"
#. 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:217
msgid "%A %B %e, %Y"
msgstr "%a %e %B, %Y"
@ -659,11 +658,11 @@ msgstr[1] "Systemet vil starte på nytt automatisk om %d sekunder."
msgid "Restarting the system."
msgstr "Starter systemet på nytt."
#: ../js/ui/extensionSystem.js:379
#: ../js/ui/extensionSystem.js:404
msgid "Install"
msgstr "Installer"
#: ../js/ui/extensionSystem.js:383
#: ../js/ui/extensionSystem.js:408
#, c-format
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "Last ned og installer «%s» fra extensions.gnome.org?"
@ -672,7 +671,7 @@ msgstr "Last ned og installer «%s» fra extensions.gnome.org?"
msgid "tray"
msgstr "varslingsområde"
#: ../js/ui/keyboard.js:545 ../js/ui/status/keyboard.js:44
#: ../js/ui/keyboard.js:544 ../js/ui/status/keyboard.js:44
#: ../js/ui/status/power.js:203
msgid "Keyboard"
msgstr "Tastatur"
@ -734,24 +733,24 @@ msgid "Web Page"
msgstr "Nettside"
#. Translators: this is a filename used for screencast recording
#: ../js/ui/main.js:121
#: ../js/ui/main.js:120
#, no-c-format
msgid "Screencast from %d %t"
msgstr "Skjermvideo fra %d %t"
#: ../js/ui/messageTray.js:1232
#: ../js/ui/messageTray.js:1200
msgid "Open"
msgstr "Åpne"
#: ../js/ui/messageTray.js:1249
#: ../js/ui/messageTray.js:1217
msgid "Unmute"
msgstr "Fjern demping"
#: ../js/ui/messageTray.js:1249
#: ../js/ui/messageTray.js:1217
msgid "Mute"
msgstr "Demp"
#: ../js/ui/messageTray.js:2522
#: ../js/ui/messageTray.js:2490
msgid "System Information"
msgstr "Systeminformasjon"
@ -840,35 +839,35 @@ msgstr "Et passord kreves for å koble til «%s»."
msgid "Undo"
msgstr "Angre"
#: ../js/ui/overview.js:130
#: ../js/ui/overview.js:132
msgid "Overview"
msgstr "Oversikt"
#: ../js/ui/overview.js:200
#: ../js/ui/overview.js:202
msgid "Windows"
msgstr "Vinduer"
#: ../js/ui/overview.js:203
#: ../js/ui/overview.js:205
msgid "Applications"
msgstr "Programmer"
#. Translators: this is the name of the dock/favorites area on
#. the left of the overview
#: ../js/ui/overview.js:229
#: ../js/ui/overview.js:231
msgid "Dash"
msgstr "Favoritter"
#: ../js/ui/panel.js:564
#: ../js/ui/panel.js:592
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:596
#: ../js/ui/panel.js:624
msgid "Activities"
msgstr "Aktiviteter"
#: ../js/ui/panel.js:962
#: ../js/ui/panel.js:999
msgid "Top Bar"
msgstr "Topp-panel"
@ -922,11 +921,11 @@ msgstr "toggle-switch-intl"
msgid "Please enter a command:"
msgstr "Oppgi en kommando:"
#: ../js/ui/searchDisplay.js:321
#: ../js/ui/searchDisplay.js:332
msgid "Searching..."
msgstr "Søker …"
#: ../js/ui/searchDisplay.js:374
#: ../js/ui/searchDisplay.js:422
msgid "No matching results."
msgstr "Ingen treff."
@ -946,7 +945,7 @@ msgstr "Vis tekst"
msgid "Hide Text"
msgstr "Skjul tekst"
#: ../js/ui/shellMountOperation.js:272
#: ../js/ui/shellMountOperation.js:271
msgid "Wrong password, please try again"
msgstr "Feil passord. Prøv igjen"
@ -998,9 +997,9 @@ msgid "Large Text"
msgstr "Stor tekst"
#: ../js/ui/status/bluetooth.js:31 ../js/ui/status/bluetooth.js:35
#: ../js/ui/status/bluetooth.js:255 ../js/ui/status/bluetooth.js:308
#: ../js/ui/status/bluetooth.js:339 ../js/ui/status/bluetooth.js:375
#: ../js/ui/status/bluetooth.js:404 ../js/ui/status/network.js:890
#: ../js/ui/status/bluetooth.js:258 ../js/ui/status/bluetooth.js:341
#: ../js/ui/status/bluetooth.js:371 ../js/ui/status/bluetooth.js:407
#: ../js/ui/status/bluetooth.js:436 ../js/ui/status/network.js:893
msgid "Bluetooth"
msgstr "Bluetooth"
@ -1025,110 +1024,110 @@ msgstr "Innstillinger for Bluetooth"
msgid "hardware disabled"
msgstr "maskinvare slått av"
#: ../js/ui/status/bluetooth.js:200
#: ../js/ui/status/bluetooth.js:203
msgid "Connection"
msgstr "Tilkobling"
#: ../js/ui/status/bluetooth.js:211 ../js/ui/status/network.js:491
#: ../js/ui/status/bluetooth.js:214 ../js/ui/status/network.js:491
msgid "disconnecting..."
msgstr "kobler fra …"
#: ../js/ui/status/bluetooth.js:224 ../js/ui/status/network.js:497
#: ../js/ui/status/bluetooth.js:227 ../js/ui/status/network.js:497
msgid "connecting..."
msgstr "kobler til …"
#: ../js/ui/status/bluetooth.js:242
#: ../js/ui/status/bluetooth.js:245
msgid "Send Files..."
msgstr "Send filer …"
#: ../js/ui/status/bluetooth.js:247
#: ../js/ui/status/bluetooth.js:250
msgid "Browse Files..."
msgstr "Bla gjennom filer …"
#: ../js/ui/status/bluetooth.js:256
#: ../js/ui/status/bluetooth.js:259
msgid "Error browsing device"
msgstr "Feil under lesing av enhet"
#: ../js/ui/status/bluetooth.js:257
#: ../js/ui/status/bluetooth.js:260
#, c-format
msgid "The requested device cannot be browsed, error is '%s'"
msgstr "Kan ikke bla gjennom forespurt enhet. Feilen er «%s»"
#: ../js/ui/status/bluetooth.js:265
#: ../js/ui/status/bluetooth.js:268
msgid "Keyboard Settings"
msgstr "Innstillinger for tastatur"
#: ../js/ui/status/bluetooth.js:268
#: ../js/ui/status/bluetooth.js:271
msgid "Mouse Settings"
msgstr "Innstillinger for mus"
#: ../js/ui/status/bluetooth.js:273 ../js/ui/status/volume.js:59
#: ../js/ui/status/bluetooth.js:276 ../js/ui/status/volume.js:59
msgid "Sound Settings"
msgstr "Innstillinger for lyd"
#: ../js/ui/status/bluetooth.js:340
#: ../js/ui/status/bluetooth.js:372
#, c-format
msgid "Authorization request from %s"
msgstr "Forespørsel om autorisering fra %s"
#: ../js/ui/status/bluetooth.js:346
#: ../js/ui/status/bluetooth.js:378
#, c-format
msgid "Device %s wants access to the service '%s'"
msgstr "Enhet %s vil ha tilgang til tjenesten «%s»"
#: ../js/ui/status/bluetooth.js:348
#: ../js/ui/status/bluetooth.js:380
msgid "Always grant access"
msgstr "Alltid gi tilgang"
#: ../js/ui/status/bluetooth.js:349
#: ../js/ui/status/bluetooth.js:381
msgid "Grant this time only"
msgstr "Gi tilgang kun denne ene gangen"
#: ../js/ui/status/bluetooth.js:350 ../js/ui/telepathyClient.js:1090
#: ../js/ui/status/bluetooth.js:382 ../js/ui/telepathyClient.js:1093
msgid "Reject"
msgstr "Avvis"
#: ../js/ui/status/bluetooth.js:376
#: ../js/ui/status/bluetooth.js:408
#, c-format
msgid "Pairing confirmation for %s"
msgstr "Bekreftelse for tilkobling for %s"
#: ../js/ui/status/bluetooth.js:382 ../js/ui/status/bluetooth.js:412
#: ../js/ui/status/bluetooth.js:414 ../js/ui/status/bluetooth.js:444
#, c-format
msgid "Device %s wants to pair with this computer"
msgstr "Enhet %s vil koble seg sammen med denne datamaskinen"
#: ../js/ui/status/bluetooth.js:383
#: ../js/ui/status/bluetooth.js:415
#, c-format
msgid "Please confirm whether the PIN '%06d' matches the one on the device."
msgstr "Vennligst bekreft om PIN «%06d» er lik den som brukes på enheten."
msgid "Please confirm whether the PIN '%s' matches the one on the device."
msgstr "Vennligst bekreft om PIN «%s» er lik den som brukes på enheten."
#: ../js/ui/status/bluetooth.js:385
#: ../js/ui/status/bluetooth.js:417
msgid "Matches"
msgstr "Stemmer overens"
#: ../js/ui/status/bluetooth.js:386
#: ../js/ui/status/bluetooth.js:418
msgid "Does not match"
msgstr "Stemmer ikke overens"
#: ../js/ui/status/bluetooth.js:405
#: ../js/ui/status/bluetooth.js:437
#, c-format
msgid "Pairing request for %s"
msgstr "Forespørsel om tilkobling for %s"
#: ../js/ui/status/bluetooth.js:413
#: ../js/ui/status/bluetooth.js:445
msgid "Please enter the PIN mentioned on the device."
msgstr "Vennligst oppgi PIN som oppgitt på enheten."
#: ../js/ui/status/bluetooth.js:430
#: ../js/ui/status/bluetooth.js:461
msgid "OK"
msgstr "OK"
#: ../js/ui/status/keyboard.js:72
#: ../js/ui/status/keyboard.js:68
msgid "Show Keyboard Layout"
msgstr "Vis tastaturutforming"
#: ../js/ui/status/keyboard.js:77
#: ../js/ui/status/keyboard.js:73
msgid "Region and Language Settings"
msgstr "Innstillinger for region og språk"
@ -1173,13 +1172,13 @@ msgstr "ikke tilgjengelig"
msgid "connection failed"
msgstr "tilkobling feilet"
#: ../js/ui/status/network.js:585 ../js/ui/status/network.js:1497
#: ../js/ui/status/network.js:585 ../js/ui/status/network.js:1505
msgid "More..."
msgstr "Mer …"
#. TRANSLATORS: this is the indication that a connection for another logged in user is active,
#. and we cannot access its settings (including the name)
#: ../js/ui/status/network.js:621 ../js/ui/status/network.js:1432
#: ../js/ui/status/network.js:621 ../js/ui/status/network.js:1440
msgid "Connected (private)"
msgstr "Tilkoblet (privat)"
@ -1187,72 +1186,72 @@ msgstr "Tilkoblet (privat)"
msgid "Auto Ethernet"
msgstr "Automatisk Ethernet"
#: ../js/ui/status/network.js:754
#: ../js/ui/status/network.js:757
msgid "Auto broadband"
msgstr "Automatisk bredbånd"
#: ../js/ui/status/network.js:757
#: ../js/ui/status/network.js:760
msgid "Auto dial-up"
msgstr "Automatisk oppringt"
#. TRANSLATORS: this the automatic wireless connection name (including the network name)
#: ../js/ui/status/network.js:876 ../js/ui/status/network.js:1444
#: ../js/ui/status/network.js:879 ../js/ui/status/network.js:1452
#, c-format
msgid "Auto %s"
msgstr "Automatisk %s"
#: ../js/ui/status/network.js:878
#: ../js/ui/status/network.js:881
msgid "Auto bluetooth"
msgstr "Automatisk Bluetooth"
#: ../js/ui/status/network.js:1446
#: ../js/ui/status/network.js:1454
msgid "Auto wireless"
msgstr "Automatisk trådløst"
#: ../js/ui/status/network.js:1533
#: ../js/ui/status/network.js:1541
msgid "Network"
msgstr "Nettverk"
#: ../js/ui/status/network.js:1540
#: ../js/ui/status/network.js:1548
msgid "Enable networking"
msgstr "Slå på nettverk"
#: ../js/ui/status/network.js:1552
#: ../js/ui/status/network.js:1560
msgid "Wired"
msgstr "Kablet"
#: ../js/ui/status/network.js:1563
#: ../js/ui/status/network.js:1571
msgid "Wireless"
msgstr "Trådløst"
#: ../js/ui/status/network.js:1573
#: ../js/ui/status/network.js:1581
msgid "Mobile broadband"
msgstr "Mobilt bredbånd"
#: ../js/ui/status/network.js:1583
#: ../js/ui/status/network.js:1591
msgid "VPN Connections"
msgstr "VPN-tilkoblinger"
#: ../js/ui/status/network.js:1594
#: ../js/ui/status/network.js:1602
msgid "Network Settings"
msgstr "Innstillinger for nettverk"
#: ../js/ui/status/network.js:1647
msgid "Network Manager"
msgstr "Nettverkshåndtering"
#: ../js/ui/status/network.js:1734
#: ../js/ui/status/network.js:1739
msgid "Connection failed"
msgstr "Tilkobling feilet"
#: ../js/ui/status/network.js:1735
#: ../js/ui/status/network.js:1740
msgid "Activation of network connection failed"
msgstr "Aktivering av nettverkstilkobling feilet"
#: ../js/ui/status/network.js:1988
#: ../js/ui/status/network.js:1993
msgid "Networking is disabled"
msgstr "Nettverk er slått av"
#: ../js/ui/status/network.js:2117
msgid "Network Manager"
msgstr "Nettverkshåndtering"
#: ../js/ui/status/power.js:59
msgid "Battery"
msgstr "Batteri"
@ -1370,7 +1369,7 @@ msgstr "Ring"
msgid "File Transfer"
msgstr "Filoverføring"
#: ../js/ui/telepathyClient.js:368
#: ../js/ui/telepathyClient.js:369
msgid "Subscription request"
msgstr "Forespørsel om abbonering"
@ -1378,22 +1377,22 @@ msgstr "Forespørsel om abbonering"
msgid "Connection error"
msgstr "Feil ved tilkobling"
#: ../js/ui/telepathyClient.js:662
#: ../js/ui/telepathyClient.js:663
#, c-format
msgid "%s is online."
msgstr "%s er tilkoblet."
#: ../js/ui/telepathyClient.js:666
#: ../js/ui/telepathyClient.js:667
#, c-format
msgid "%s is offline."
msgstr "%s er frakoblet."
#: ../js/ui/telepathyClient.js:670
#: ../js/ui/telepathyClient.js:671
#, c-format
msgid "%s is away."
msgstr "«%s» er borte."
#: ../js/ui/telepathyClient.js:673
#: ../js/ui/telepathyClient.js:674
#, c-format
msgid "%s is busy."
msgstr "%s er opptatt."
@ -1401,35 +1400,35 @@ msgstr "%s er opptatt."
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds.
#: ../js/ui/telepathyClient.js:888
#: ../js/ui/telepathyClient.js:889
#, no-c-format
msgid "Sent at <b>%X</b> on <b>%A</b>"
msgstr "Sendt <b>%X</b> på <b>%A</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25",
#. shown when you get a chat message in the same year.
#: ../js/ui/telepathyClient.js:894
#: ../js/ui/telepathyClient.js:895
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
msgstr "Sendt <b>%A</b>, <b>%B %d</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year.
#: ../js/ui/telepathyClient.js:899
#: ../js/ui/telepathyClient.js:900
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
msgstr "Sendt <b>%A</b>, <b>%B %d</b>, %Y"
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: ../js/ui/telepathyClient.js:941
#: ../js/ui/telepathyClient.js:942
#, c-format
msgid "%s is now known as %s"
msgstr "%s er nå kjent som %s"
#. translators: argument is a room name like
#. * room@jabber.org for example.
#: ../js/ui/telepathyClient.js:1041
#: ../js/ui/telepathyClient.js:1044
#, c-format
msgid "Invitation to %s"
msgstr "Invitasjon til %s"
@ -1437,35 +1436,35 @@ msgstr "Invitasjon til %s"
#. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example.
#: ../js/ui/telepathyClient.js:1049
#: ../js/ui/telepathyClient.js:1052
#, c-format
msgid "%s is inviting you to join %s"
msgstr "%s inviterer deg til å bli med i %s"
#: ../js/ui/telepathyClient.js:1051 ../js/ui/telepathyClient.js:1130
#: ../js/ui/telepathyClient.js:1194
#: ../js/ui/telepathyClient.js:1054 ../js/ui/telepathyClient.js:1133
#: ../js/ui/telepathyClient.js:1231
msgid "Decline"
msgstr "Avslå"
#: ../js/ui/telepathyClient.js:1052 ../js/ui/telepathyClient.js:1131
#: ../js/ui/telepathyClient.js:1195
#: ../js/ui/telepathyClient.js:1055 ../js/ui/telepathyClient.js:1134
#: ../js/ui/telepathyClient.js:1232
msgid "Accept"
msgstr "Godta"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1082
#: ../js/ui/telepathyClient.js:1085
#, c-format
msgid "Video call from %s"
msgstr "Videosamtale fra %s"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1085
#: ../js/ui/telepathyClient.js:1088
#, c-format
msgid "Call from %s"
msgstr "Samtale fra %s"
#. translators: this is a button label (verb), not a noun
#: ../js/ui/telepathyClient.js:1092
#: ../js/ui/telepathyClient.js:1095
msgid "Answer"
msgstr "Svar"
@ -1474,110 +1473,110 @@ msgstr "Svar"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#.
#: ../js/ui/telepathyClient.js:1124
#: ../js/ui/telepathyClient.js:1127
#, c-format
msgid "%s is sending you %s"
msgstr "%s sender deg %s"
#. To translators: The parameter is the contact's alias
#: ../js/ui/telepathyClient.js:1159
#: ../js/ui/telepathyClient.js:1196
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "%s vil ha rettigheter til å se når du er tilkoblet"
#: ../js/ui/telepathyClient.js:1252
#: ../js/ui/telepathyClient.js:1289
msgid "Network error"
msgstr "Nettverksfeil"
#: ../js/ui/telepathyClient.js:1254
#: ../js/ui/telepathyClient.js:1291
msgid "Authentication failed"
msgstr "Autentisering feilet"
#: ../js/ui/telepathyClient.js:1256
#: ../js/ui/telepathyClient.js:1293
msgid "Encryption error"
msgstr "Feil ved kryptering"
#: ../js/ui/telepathyClient.js:1258
#: ../js/ui/telepathyClient.js:1295
msgid "Certificate not provided"
msgstr "Sertifikat ikke oppgitt"
#: ../js/ui/telepathyClient.js:1260
#: ../js/ui/telepathyClient.js:1297
msgid "Certificate untrusted"
msgstr "Stoler ikke på sertifikatet"
#: ../js/ui/telepathyClient.js:1262
#: ../js/ui/telepathyClient.js:1299
msgid "Certificate expired"
msgstr "Sertifikatet er utløpt"
#: ../js/ui/telepathyClient.js:1264
#: ../js/ui/telepathyClient.js:1301
msgid "Certificate not activated"
msgstr "Sertifikatet er ikke aktivert"
#: ../js/ui/telepathyClient.js:1266
#: ../js/ui/telepathyClient.js:1303
msgid "Certificate hostname mismatch"
msgstr "Feil vertsnavn for sertifikat"
#: ../js/ui/telepathyClient.js:1268
#: ../js/ui/telepathyClient.js:1305
msgid "Certificate fingerprint mismatch"
msgstr "Feil fingeravtrykk for sertifikat"
#: ../js/ui/telepathyClient.js:1270
#: ../js/ui/telepathyClient.js:1307
msgid "Certificate self-signed"
msgstr "Sertifikatet er selvsignert"
#: ../js/ui/telepathyClient.js:1272
#: ../js/ui/telepathyClient.js:1309
msgid "Status is set to offline"
msgstr "Status er satt til frakoblet"
#: ../js/ui/telepathyClient.js:1274
#: ../js/ui/telepathyClient.js:1311
msgid "Encryption is not available"
msgstr "Kryptering er ikke tilgjengelig"
#: ../js/ui/telepathyClient.js:1276
#: ../js/ui/telepathyClient.js:1313
msgid "Certificate is invalid"
msgstr "Sertifikatet er ugyldig"
#: ../js/ui/telepathyClient.js:1278
#: ../js/ui/telepathyClient.js:1315
msgid "Connection has been refused"
msgstr "Tilkobling ble nektet"
#: ../js/ui/telepathyClient.js:1280
#: ../js/ui/telepathyClient.js:1317
msgid "Connection can't be established"
msgstr "Tilkobling kan ikke etableres"
#: ../js/ui/telepathyClient.js:1282
#: ../js/ui/telepathyClient.js:1319
msgid "Connection has been lost"
msgstr "Tilkobling tapt"
#: ../js/ui/telepathyClient.js:1284
#: ../js/ui/telepathyClient.js:1321
msgid "This account is already connected to the server"
msgstr "Denne kontoen er allerede koblet til tjeneren"
#: ../js/ui/telepathyClient.js:1286
#: ../js/ui/telepathyClient.js:1323
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr ""
"Tilkoblingen har blitt erstattet av en ny tilkobling som bruker samme ressurs"
#: ../js/ui/telepathyClient.js:1288
#: ../js/ui/telepathyClient.js:1325
msgid "The account already exists on the server"
msgstr "Kontoen eksisterer allerede på tjeneren"
#: ../js/ui/telepathyClient.js:1290
#: ../js/ui/telepathyClient.js:1327
msgid "Server is currently too busy to handle the connection"
msgstr "Tjener er for opptatt til å håndtere tilkoblingen"
#: ../js/ui/telepathyClient.js:1292
#: ../js/ui/telepathyClient.js:1329
msgid "Certificate has been revoked"
msgstr "Sertifikatet er tilbaketrukket"
#: ../js/ui/telepathyClient.js:1294
#: ../js/ui/telepathyClient.js:1331
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"Sertifikatet bruker en usikker sifferalgoritme eller er krytografisk svakt"
#: ../js/ui/telepathyClient.js:1296
#: ../js/ui/telepathyClient.js:1333
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@ -1585,70 +1584,74 @@ msgstr ""
"Lengden eller dybden på tjenersertifikatet oversteg grensen som er satt i "
"kryptografibiblioteket"
#: ../js/ui/telepathyClient.js:1298
#: ../js/ui/telepathyClient.js:1335
msgid "Internal error"
msgstr "Intern feil"
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#: ../js/ui/telepathyClient.js:1308
#: ../js/ui/telepathyClient.js:1345
#, c-format
msgid "Connection to %s failed"
msgstr "Tilkobling til %s feilet"
#: ../js/ui/telepathyClient.js:1317
#: ../js/ui/telepathyClient.js:1354
msgid "Reconnect"
msgstr "Koble til på nytt"
#: ../js/ui/telepathyClient.js:1318
#: ../js/ui/telepathyClient.js:1355
msgid "Edit account"
msgstr "Rediger konto"
#: ../js/ui/telepathyClient.js:1364
#: ../js/ui/telepathyClient.js:1401
msgid "Unknown reason"
msgstr "Ukjent årsak"
#: ../js/ui/userMenu.js:136
#: ../js/ui/userMenu.js:135
msgid "Hidden"
msgstr "Skjult"
#: ../js/ui/userMenu.js:142
#: ../js/ui/userMenu.js:141
msgid "Idle"
msgstr "Ledig"
#: ../js/ui/userMenu.js:145
#: ../js/ui/userMenu.js:144
msgid "Unavailable"
msgstr "Ikke tilgjengelig"
#: ../js/ui/userMenu.js:556 ../js/ui/userMenu.js:656
msgid "Switch User"
msgstr "Bytt bruker"
#: ../js/ui/userMenu.js:595 ../js/ui/userMenu.js:599 ../js/ui/userMenu.js:669
msgid "Power Off..."
msgstr "Slå av …"
#: ../js/ui/userMenu.js:557
msgid "Switch Session"
msgstr "Bytt økt"
#: ../js/ui/userMenu.js:632
#: ../js/ui/userMenu.js:631
msgid "Notifications"
msgstr "Varslinger"
#: ../js/ui/userMenu.js:641
#: ../js/ui/userMenu.js:639
msgid "Online Accounts"
msgstr "Kontoer på nettet"
#: ../js/ui/userMenu.js:643
msgid "System Settings"
msgstr "Systeminnstillinger"
#: ../js/ui/userMenu.js:661
msgid "Log Out"
msgstr "Logg ut"
#: ../js/ui/userMenu.js:650
msgid "Lock Screen"
msgstr "Lås skjerm"
#: ../js/ui/userMenu.js:669
msgid "Lock"
msgstr "Lås"
#: ../js/ui/userMenu.js:655
msgid "Switch User"
msgstr "Bytt bruker"
#: ../js/ui/userMenu.js:687
#: ../js/ui/userMenu.js:660
msgid "Log Out..."
msgstr "Logg ut …"
#: ../js/ui/userMenu.js:688
msgid "Your chat status will be set to busy"
msgstr "Din pratestatus vil bli satt til opptatt"
#: ../js/ui/userMenu.js:688
#: ../js/ui/userMenu.js:689
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."
@ -1714,23 +1717,15 @@ msgstr[1] "%u innganger"
msgid "System Sounds"
msgstr "Systemlyder"
#: ../src/main.c:313
#: ../src/main.c:255
msgid "Print version"
msgstr "Skriv ut versjon"
#: ../src/main.c:319
#: ../src/main.c:261
msgid "Mode used by GDM for login screen"
msgstr "Modus som brukes av GDM for innloggingsskjermen"
#: ../src/main.c:325
msgid "Use a specific mode, e.g. \"gdm\" for login screen"
msgstr "Bruk spesifikt modus, f.eks «gdm» for innloggingsskjerm"
#: ../src/main.c:331
msgid "List possible modes"
msgstr "Vis mulige modi"
#: ../src/shell-app.c:622
#: ../src/shell-app.c:619
#, c-format
msgid "Failed to launch '%s'"
msgstr "Klarte ikke å starte «%s»"

473
po/sl.po

File diff suppressed because it is too large Load Diff

View File

@ -93,8 +93,7 @@ gnome_shell_cflags = \
-DGNOME_SHELL_LIBEXECDIR=\"$(libexecdir)\" \
-DGNOME_SHELL_DATADIR=\"$(pkgdatadir)\" \
-DGNOME_SHELL_PKGLIBDIR=\"$(pkglibdir)\" \
-DJSDIR=\"$(pkgdatadir)/js\" \
-DMUTTER_TYPELIB_DIR=\"$(MUTTER_TYPELIB_DIR)\"
-DJSDIR=\"$(pkgdatadir)/js\"
privlibdir = $(pkglibdir)
privlib_LTLIBRARIES = libgnome-shell.la libgnome-shell-js.la
@ -194,7 +193,7 @@ libgnome_shell_la_gir_sources = \
gnome_shell_real_SOURCES = \
main.c
gnome_shell_real_CPPFLAGS = $(gnome_shell_cflags)
gnome_shell_real_LDADD = libgnome-shell.la libgnome-shell-js.la $(libgnome_shell_la_LIBADD)
gnome_shell_real_LDADD = libgnome-shell.la $(libgnome_shell_la_LIBADD)
gnome_shell_real_DEPENDENCIES = libgnome-shell.la
EXTRA_DIST += test-gapplication.js

View File

@ -24,12 +24,9 @@
#include "shell-a11y.h"
#include "shell-global.h"
#include "shell-global-private.h"
#include "shell-js.h"
#include "shell-perf-log.h"
#include "st.h"
#include <jsapi.h>
extern GType gnome_shell_plugin_get_type (void);
#define SHELL_DBUS_SERVICE "org.gnome.Shell"
@ -38,7 +35,6 @@ extern GType gnome_shell_plugin_get_type (void);
#define OVERRIDES_SCHEMA "org.gnome.shell.overrides"
static gboolean is_gdm_mode = FALSE;
static char *session_mode = NULL;
#define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1
#define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4
@ -177,18 +173,6 @@ shell_prefs_init (void)
OVERRIDES_SCHEMA);
}
static void
shell_introspection_init (void)
{
g_irepository_prepend_search_path (MUTTER_TYPELIB_DIR);
g_irepository_prepend_search_path (GNOME_SHELL_PKGLIBDIR);
#if HAVE_BLUETOOTH
g_irepository_prepend_search_path (BLUETOOTH_DIR);
#endif
}
static void
malloc_statistics_callback (ShellPerfLog *perf_log,
gpointer data)
@ -254,48 +238,6 @@ default_log_handler (const char *log_domain,
g_log_default_handler (log_domain, log_level, message, data);
}
static void
shut_up (const char *domain,
GLogLevelFlags level,
const char *message,
gpointer user_data)
{
}
static gboolean
list_modes (const char *option_name,
const char *value,
gpointer data,
GError **error)
{
ShellGlobal *global;
GjsContext *context;
const char *script;
int status;
/* Many of our imports require global to be set, so rather than
* tayloring our imports carefully here to avoid that dependency,
* we just set it.
* ShellGlobal has some GTK+ dependencies, so initialize GTK+; we
* don't really care if it fails though (e.g. when running from a tty),
* so we mute all warnings */
g_log_set_default_handler (shut_up, NULL);
gtk_init_check (NULL, NULL);
_shell_global_init (NULL);
global = shell_global_get ();
context = _shell_global_get_gjs_context (global);
shell_introspection_init ();
script = "imports.ui.environment.init();"
"imports.ui.sessionMode.listModes();";
if (!gjs_context_eval (context, script, -1, "<main>", &status, NULL))
g_message ("Retrieving list of available modes failed.");
exit (status);
}
static gboolean
print_version (const gchar *option_name,
const gchar *value,
@ -314,23 +256,11 @@ GOptionEntry gnome_shell_options[] = {
NULL
},
{
"gdm-mode", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE,
"gdm-mode", 0, 0, G_OPTION_ARG_NONE,
&is_gdm_mode,
N_("Mode used by GDM for login screen"),
NULL
},
{
"mode", 0, 0, G_OPTION_ARG_STRING,
&session_mode,
N_("Use a specific mode, e.g. \"gdm\" for login screen"),
"MODE"
},
{
"list-modes", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
list_modes,
N_("List possible modes"),
NULL
},
{ NULL }
};
@ -339,6 +269,7 @@ main (int argc, char **argv)
{
GOptionContext *ctx;
GError *error = NULL;
ShellSessionType session_type;
int ecode;
TpDebugSender *sender;
@ -377,7 +308,11 @@ main (int argc, char **argv)
shell_a11y_init ();
shell_perf_log_init ();
shell_prefs_init ();
shell_introspection_init ();
g_irepository_prepend_search_path (GNOME_SHELL_PKGLIBDIR);
#if HAVE_BLUETOOTH
g_irepository_prepend_search_path (BLUETOOTH_DIR);
#endif
/* Turn on telepathy-glib debugging but filter it out in
* default_log_handler. This handler also exposes all the logs over D-Bus
@ -388,10 +323,12 @@ main (int argc, char **argv)
g_log_set_default_handler (default_log_handler, sender);
/* Initialize the global object */
if (session_mode == NULL)
session_mode = is_gdm_mode ? "gdm" : "user";
if (is_gdm_mode)
session_type = SHELL_SESSION_GDM;
else
session_type = SHELL_SESSION_USER;
_shell_global_init ("session-mode", session_mode, NULL);
_shell_global_init ("session-type", session_type, NULL);
ecode = meta_run ();
@ -405,17 +342,3 @@ main (int argc, char **argv)
return ecode;
}
/* HACK:
Add a dummy function that calls into libgnome-shell-js.so to ensure it's
linked to /usr/bin/gnome-shell even when linking with --as-needed.
This function is never actually called.
https://bugzilla.gnome.org/show_bug.cgi?id=670477
*/
void _shell_link_to_shell_js (void);
void
_shell_link_to_shell_js (void)
{
shell_js_add_extension_importer (NULL, NULL, NULL, NULL);
}

View File

@ -371,7 +371,7 @@ shell_app_get_name (ShellApp *app)
name = meta_window_get_wm_class (window);
if (!name)
name = C_("program", "Unknown");
name = _("Unknown");
return name;
}
}
@ -493,7 +493,7 @@ shell_app_activate_window (ShellApp *app,
return;
else
{
GSList *windows_reversed, *iter;
GSList *iter;
ShellGlobal *global = shell_global_get ();
MetaScreen *screen = shell_global_get_screen (global);
MetaDisplay *display = meta_screen_get_display (screen);
@ -511,16 +511,13 @@ shell_app_activate_window (ShellApp *app,
/* Now raise all the other windows for the app that are on
* the same workspace, in reverse order to preserve the stacking.
*/
windows_reversed = g_slist_copy (windows);
windows_reversed = g_slist_reverse (windows_reversed);
for (iter = windows_reversed; iter; iter = iter->next)
for (iter = windows; iter; iter = iter->next)
{
MetaWindow *other_window = iter->data;
if (other_window != window)
meta_window_raise (other_window);
}
g_slist_free (windows_reversed);
/* If we have a transient that the user's interacted with more recently than
* the window, pick that.

View File

@ -16,4 +16,7 @@ GjsContext *_shell_global_get_gjs_context (ShellGlobal *global);
gboolean _shell_global_check_xdnd_event (ShellGlobal *global,
XEvent *xev);
void _shell_global_set_session_type (ShellGlobal *global,
ShellSessionType session_type);
#endif /* __SHELL_GLOBAL_PRIVATE_H__ */

View File

@ -59,7 +59,7 @@ struct _ShellGlobal {
MetaScreen *meta_screen;
GdkScreen *gdk_screen;
char *session_mode;
ShellSessionType session_type;
/* We use this window to get a notification from GTK+ when
* a widget in our process does a GTK+ grab. See
@ -97,7 +97,7 @@ struct _ShellGlobal {
enum {
PROP_0,
PROP_SESSION_MODE,
PROP_SESSION_TYPE,
PROP_OVERLAY_GROUP,
PROP_SCREEN,
PROP_GDK_SCREEN,
@ -143,9 +143,8 @@ shell_global_set_property(GObject *object,
case PROP_STAGE_INPUT_MODE:
shell_global_set_stage_input_mode (global, g_value_get_enum (value));
break;
case PROP_SESSION_MODE:
g_clear_pointer (&global->session_mode, g_free);
global->session_mode = g_ascii_strdown (g_value_get_string (value), -1);
case PROP_SESSION_TYPE:
global->session_type = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -163,8 +162,8 @@ shell_global_get_property(GObject *object,
switch (prop_id)
{
case PROP_SESSION_MODE:
g_value_set_string (value, shell_global_get_session_mode (global));
case PROP_SESSION_TYPE:
g_value_set_enum (value, shell_global_get_session_type (global));
break;
case PROP_OVERLAY_GROUP:
g_value_set_object (value, meta_get_overlay_group_for_screen (global->meta_screen));
@ -344,12 +343,13 @@ shell_global_class_init (ShellGlobalClass *klass)
G_TYPE_STRING);
g_object_class_install_property (gobject_class,
PROP_SESSION_MODE,
g_param_spec_string ("session-mode",
"Session Mode",
"The session mode to use",
"user",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
PROP_SESSION_TYPE,
g_param_spec_enum ("session-type",
"Session Type",
"The type of session",
SHELL_TYPE_SESSION_TYPE,
SHELL_SESSION_USER,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class,
PROP_OVERLAY_GROUP,
g_param_spec_object ("overlay-group",
@ -805,9 +805,90 @@ global_stage_after_paint (ClutterStage *stage,
"clutter.stagePaintDone");
}
static void
update_font_options (GtkSettings *settings,
ClutterStage *stage)
{
StThemeContext *context;
ClutterBackend *backend;
gint dpi;
gint hinting;
gchar *hint_style_str;
cairo_hint_style_t hint_style = CAIRO_HINT_STYLE_NONE;
gint antialias;
cairo_antialias_t antialias_mode = CAIRO_ANTIALIAS_NONE;
cairo_font_options_t *options;
g_object_get (settings,
"gtk-xft-dpi", &dpi,
"gtk-xft-antialias", &antialias,
"gtk-xft-hinting", &hinting,
"gtk-xft-hintstyle", &hint_style_str,
NULL);
context = st_theme_context_get_for_stage (stage);
if (dpi != -1)
/* GTK stores resolution as 1024 * dots/inch */
st_theme_context_set_resolution (context, dpi / 1024);
else
st_theme_context_set_default_resolution (context);
/* Clutter (as of 0.9) passes comprehensively wrong font options
* override whatever set_font_flags() did above.
*
* http://bugzilla.openedhand.com/show_bug.cgi?id=1456
*/
backend = clutter_get_default_backend ();
options = cairo_font_options_create ();
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
if (hinting >= 0 && !hinting)
{
hint_style = CAIRO_HINT_STYLE_NONE;
}
else if (hint_style_str)
{
if (strcmp (hint_style_str, "hintnone") == 0)
hint_style = CAIRO_HINT_STYLE_NONE;
else if (strcmp (hint_style_str, "hintslight") == 0)
hint_style = CAIRO_HINT_STYLE_SLIGHT;
else if (strcmp (hint_style_str, "hintmedium") == 0)
hint_style = CAIRO_HINT_STYLE_MEDIUM;
else if (strcmp (hint_style_str, "hintfull") == 0)
hint_style = CAIRO_HINT_STYLE_FULL;
}
g_free (hint_style_str);
cairo_font_options_set_hint_style (options, hint_style);
/* We don't want to turn on subpixel anti-aliasing; since Clutter
* doesn't currently have the code to support ARGB masks,
* generating them then squashing them back to A8 is pointless.
*/
antialias_mode = (antialias < 0 || antialias) ? CAIRO_ANTIALIAS_GRAY
: CAIRO_ANTIALIAS_NONE;
cairo_font_options_set_antialias (options, antialias_mode);
clutter_backend_set_font_options (backend, options);
cairo_font_options_destroy (options);
}
static void
settings_notify_cb (GtkSettings *settings,
GParamSpec *pspec,
gpointer data)
{
update_font_options (settings, CLUTTER_STAGE (data));
}
static void
shell_fonts_init (ClutterStage *stage)
{
GtkSettings *settings;
CoglPangoFontMap *fontmap;
/* Disable text mipmapping; it causes problems on pre-GEM Intel
@ -817,6 +898,19 @@ shell_fonts_init (ClutterStage *stage)
*/
fontmap = COGL_PANGO_FONT_MAP (clutter_get_font_map ());
cogl_pango_font_map_set_use_mipmapping (fontmap, FALSE);
settings = gtk_settings_get_default ();
g_object_connect (settings,
"signal::notify::gtk-xft-dpi",
G_CALLBACK (settings_notify_cb), stage,
"signal::notify::gtk-xft-antialias",
G_CALLBACK (settings_notify_cb), stage,
"signal::notify::gtk-xft-hinting",
G_CALLBACK (settings_notify_cb), stage,
"signal::notify::gtk-xft-hintstyle",
G_CALLBACK (settings_notify_cb), stage,
NULL);
update_font_options (settings, stage);
}
/* This is an IBus workaround. The flow of events with IBus is that every time
@ -1776,10 +1870,31 @@ shell_global_launch_calendar_server (ShellGlobal *global)
g_free (calendar_server_exe);
}
const char *
shell_global_get_session_mode (ShellGlobal *global)
/**
* shell_global_get_session_type:
* @global: The #ShellGlobal.
*
* Gets the type of session gnome-shell provides.
*
* The type determines what UI elements are displayed,
* what keybindings work, and generally how the shell
* behaves.
*
* A session type of #SHELL_SESSION_USER means gnome-shell
* will enable the activities overview, status menu, run dialog,
* etc. This is the default.
*
* A session type of #SHELL_SESSION_GDM means gnome-shell
* will enable a login dialog and run in a more confined
* way. This type is suitable for the display manager.
*
* Returns: the type of session gnome-shell is providing.
*/
ShellSessionType
shell_global_get_session_type (ShellGlobal *global)
{
g_return_val_if_fail (SHELL_IS_GLOBAL (global), "user");
g_return_val_if_fail (SHELL_IS_GLOBAL (global),
SHELL_SESSION_USER);
return global->session_mode;
return global->session_type;
}

View File

@ -141,7 +141,12 @@ void shell_global_reexec_self (ShellGlobal *global);
void shell_global_launch_calendar_server (ShellGlobal *global);
const char * shell_global_get_session_mode (ShellGlobal *global);
typedef enum {
SHELL_SESSION_USER,
SHELL_SESSION_GDM
} ShellSessionType;
ShellSessionType shell_global_get_session_type (ShellGlobal *global);
G_END_DECLS

View File

@ -79,3 +79,15 @@ shell_js_add_extension_importer (const char *target_object_script,
JS_EndRequest (context);
return ret;
}
/**
* shell_js_format_int_alternative_output:
* @intval:
*
* Returns: (transfer full):
*/
gchar *
shell_js_format_int_alternative_output (gint intval)
{
return g_strdup_printf ("%Id", intval);
}

View File

@ -11,6 +11,8 @@ gboolean shell_js_add_extension_importer (const char *target_object_script,
const char *directory,
GError **error);
gchar *shell_js_format_int_alternative_output (gint intval);
G_BEGIN_DECLS
#endif /* __SHELL_JS_H__ */

View File

@ -330,6 +330,34 @@ shell_tp_client_grab_contact_list_changed (ShellTpClient *self,
/* Telepathy utility functions */
/**
* shell_get_contact_events:
* @log_manager: A #TplLogManager
* @account: A #TpAccount
* @entity: A #TplEntity
* @num_events: The number of events to retrieve
* @callback: (scope async): User callback to run when the contact is ready
*
* Wrap tpl_log_manager_get_filtered_events_async because gjs cannot support
* multiple callbacks in the same function call.
*/
void
shell_get_contact_events (TplLogManager *log_manager,
TpAccount *account,
TplEntity *entity,
guint num_events,
GAsyncReadyCallback callback)
{
tpl_log_manager_get_filtered_events_async (log_manager,
account,
entity,
TPL_EVENT_MASK_TEXT,
num_events,
NULL, NULL,
callback, NULL);
}
/* gjs doesn't allow us to craft a GError so we need a C wrapper */
void
shell_decline_dispatch_op (TpAddDispatchOperationContext *context,

View File

@ -7,6 +7,7 @@
#include <glib-object.h>
#include <telepathy-glib/telepathy-glib.h>
#include <telepathy-logger/telepathy-logger.h>
G_BEGIN_DECLS
@ -102,6 +103,12 @@ void shell_tp_client_grab_contact_list_changed (ShellTpClient *self,
/* Telepathy utility functions */
void shell_get_contact_events (TplLogManager *log_manager,
TpAccount *account,
TplEntity *entity,
guint num_events,
GAsyncReadyCallback callback);
void shell_decline_dispatch_op (TpAddDispatchOperationContext *context,
const gchar *message);

View File

@ -592,6 +592,29 @@ shell_util_get_week_start ()
return week_start;
}
/**
* shell_write_soup_message_to_stream:
* @stream: a #GOutputStream
* @message: a #SoupMessage
* @error: location to store GError
*
* Write a string to a GOutputStream as binary data. This is a
* workaround for the lack of proper binary strings in GJS.
*/
void
shell_write_soup_message_to_stream (GOutputStream *stream,
SoupMessage *message,
GError **error)
{
SoupMessageBody *body;
body = message->response_body;
g_output_stream_write_all (stream,
body->data, body->length,
NULL, NULL, error);
}
/**
* shell_write_string_to_stream:
* @stream: a #GOutputStream

View File

@ -25,6 +25,10 @@ char *shell_util_normalize_and_casefold (const char *str);
char *shell_util_format_date (const char *format,
gint64 time_ms);
void shell_write_soup_message_to_stream (GOutputStream *stream,
SoupMessage *message,
GError **error);
gboolean shell_write_string_to_stream (GOutputStream *stream,
const char *str,
GError **error);

View File

@ -490,7 +490,7 @@ st_label_accessible_get_name (AtkObject *obj)
actor = CLUTTER_ACTOR (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (obj)));
if (actor == NULL || st_widget_has_style_class_name (ST_WIDGET (actor), "hidden"))
if (actor == NULL) /* State is defunct */
name = NULL;
else
name = st_label_get_text (ST_LABEL (actor));

View File

@ -28,6 +28,7 @@
struct _StThemeContext {
GObject parent;
double resolution;
PangoFontDescription *font;
StThemeNode *root_node;
StTheme *theme;
@ -37,6 +38,7 @@ struct _StThemeContextClass {
GObjectClass parent_class;
};
#define DEFAULT_RESOLUTION 96.
#define DEFAULT_FONT "sans-serif 10"
enum
@ -91,6 +93,7 @@ st_theme_context_class_init (StThemeContextClass *klass)
static void
st_theme_context_init (StThemeContext *context)
{
context->resolution = DEFAULT_RESOLUTION;
context->font = pango_font_description_from_string (DEFAULT_FONT);
g_signal_connect (st_texture_cache_get_default (),
@ -229,6 +232,66 @@ st_theme_context_get_theme (StThemeContext *context)
return context->theme;
}
/**
* st_theme_context_set_resolution:
* @context: a #StThemeContext
* @resolution: resolution of the context (number of pixels in an "inch")
*
* Sets the resolution of the theme context. This is the scale factor
* used to convert between points and the length units pt, in, and cm.
* This does not necessarily need to correspond to the actual number
* resolution of the device. A value of 72. means that points and
* pixels are identical. The default value is 96.
*/
void
st_theme_context_set_resolution (StThemeContext *context,
double resolution)
{
g_return_if_fail (ST_IS_THEME_CONTEXT (context));
if (resolution == context->resolution)
return;
context->resolution = resolution;
st_theme_context_changed (context);
}
/**
* st_theme_context_set_default_resolution:
* @context: a #StThemeContext
*
* Sets the resolution of the theme context to the default value of 96.
* See st_theme_context_set_resolution().
*/
void
st_theme_context_set_default_resolution (StThemeContext *context)
{
g_return_if_fail (ST_IS_THEME_CONTEXT (context));
if (context->resolution == DEFAULT_RESOLUTION)
return;
context->resolution = DEFAULT_RESOLUTION;
st_theme_context_changed (context);
}
/**
* st_theme_context_get_resolution:
* @context: a #StThemeContext
*
* Gets the current resolution of the theme context.
* See st_theme_context_set_resolution().
*
* Return value: the resolution (in dots-per-"inch")
*/
double
st_theme_context_get_resolution (StThemeContext *context)
{
g_return_val_if_fail (ST_IS_THEME_CONTEXT (context), DEFAULT_RESOLUTION);
return context->resolution;
}
/**
* st_theme_context_set_font:
* @context: a #StThemeContext

View File

@ -56,6 +56,10 @@ void st_theme_context_set_theme (StThemeContext
StTheme *theme);
StTheme * st_theme_context_get_theme (StThemeContext *context);
void st_theme_context_set_resolution (StThemeContext *context,
gdouble resolution);
void st_theme_context_set_default_resolution (StThemeContext *context);
double st_theme_context_get_resolution (StThemeContext *context);
void st_theme_context_set_font (StThemeContext *context,
const PangoFontDescription *font);
const PangoFontDescription *st_theme_context_get_font (StThemeContext *context);

View File

@ -820,7 +820,7 @@ get_length_from_term (StThemeNode *node,
break;
case POINTS:
{
double resolution = clutter_backend_get_resolution (clutter_get_default_backend ());
double resolution = st_theme_context_get_resolution (node->context);
*length = num->val * multiplier * (resolution / 72.);
}
break;
@ -842,7 +842,7 @@ get_length_from_term (StThemeNode *node,
}
else
{
double resolution = clutter_backend_get_resolution (clutter_get_default_backend ());
double resolution = st_theme_context_get_resolution (node->context);
*length = num->val * multiplier * (resolution / 72.) * font_size;
}
}
@ -2139,7 +2139,7 @@ font_size_from_term (StThemeNode *node,
{
if (term->type == TERM_IDENT)
{
double resolution = clutter_backend_get_resolution (clutter_get_default_backend ());
double resolution = st_theme_context_get_resolution (node->context);
/* We work in integers to avoid double comparisons when converting back
* from a size in pixels to a logical size.
*/
@ -2346,7 +2346,7 @@ st_theme_node_get_font (StThemeNode *node)
parent_size = pango_font_description_get_size (node->font_desc);
if (!pango_font_description_get_size_is_absolute (node->font_desc))
{
double resolution = clutter_backend_get_resolution (clutter_get_default_backend ());
double resolution = st_theme_context_get_resolution (node->context);
parent_size *= (resolution / 72.);
}

View File

@ -435,6 +435,7 @@ main (int argc, char **argv)
stage = clutter_stage_new ();
context = st_theme_context_get_for_stage (CLUTTER_STAGE (stage));
st_theme_context_set_theme (context, theme);
st_theme_context_set_resolution (context, 96.);
st_theme_context_set_font (context,
pango_font_description_from_string ("sans-serif 12"));